Simpler and cleaner handling of cocoa keyboard events.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7802 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2010-11-06 15:06:25 +00:00
parent 17259bcbfc
commit ae9da5cff9

View File

@ -885,16 +885,16 @@ static void calc_e_text(CFStringRef s, char *buffer, size_t len, unsigned sym)
FL_Menu, FL_Num_Lock, FL_Help
};
int count = sizeof(notext)/sizeof(int);
if (sym > FL_F && sym <= FL_F_Last) no_text_key = true;
else for (i=0; i < count; i++) {
if(notext[i] == sym) {
if (notext[i] == sym) {
no_text_key = true;
break;
}
}
if ( no_text_key) {
if (no_text_key) {
buffer[0] = 0;
} else {
CFStringGetCString(s, buffer, len, kCFStringEncodingUTF8);
@ -915,10 +915,16 @@ OSStatus carbonTextHandler( EventHandlerCallRef nextHandler, EventRef event, voi
Fl_Window *window = [(FLWindow*)keywindow getFl_Window];
fl_lock_function();
UniChar ucs[20];
ByteCount actual_size;
int i;
GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText,
NULL, 20, NULL, ucs );
char utf8buf[5];
int len = fl_utf8encode(ucs[0], utf8buf);
NULL, 20, &actual_size, ucs );
char utf8buf[50], *p;
p = utf8buf;
for(i=0; i < actual_size/2; i++) {
p += fl_utf8encode(ucs[i], p);
}
int len = p - utf8buf;
utf8buf[len]=0;
Fl::e_length = len;
@ -935,40 +941,77 @@ OSStatus carbonTextHandler( EventHandlerCallRef nextHandler, EventRef event, voi
return noErr;
}
OSStatus cocoaKeyboardHandler(NSEvent *theEvent);
@interface FLTextView : NSTextView
{
BOOL compose_key; // YES iff entering a character composition
BOOL needKBhandler_val;
}
- (BOOL)needKBhandler;
- (void)needKBhandler:(BOOL)value;
- (BOOL)compose;
- (void)compose:(BOOL)value;
- (void)insertText:(id)aString;
- (void)doCommandBySelector:(SEL)aSelector;
@end
@implementation FLTextView
- (BOOL)needKBhandler
{
return needKBhandler_val;
}
- (void)needKBhandler:(BOOL)value
{
needKBhandler_val = value;
}
- (BOOL)compose
{
return compose_key;
}
- (void)compose:(BOOL)value
{
compose_key = value;
}
- (void)insertText:(id)aString
{
cocoaKeyboardHandler([NSApp currentEvent]);
}
- (void)doCommandBySelector:(SEL)aSelector
{
cocoaKeyboardHandler([NSApp currentEvent]);
}
@end
/*
* handle cocoa keyboard events
Events during a character composition sequence:
- keydown with deadkey -> [[theEvent characters] length] is 0
- keyup -> [theEvent characters] contains the deadkey: display it temporarily
- keydown with next key -> [theEvent characters] contains the composed character:
replace the temporary character by this one
- keyup -> [theEvent characters] contains the standard character
*/
OSStatus cocoaKeyboardHandler(NSEvent *theEvent)
{
static char buffer[32];
int sendEvent = 0;
int sendEvent = 0, retval = 0;
Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window];
Fl::first_window(window);
NSUInteger mods;
fl_lock_function();
// get the modifiers
mods = [theEvent modifierFlags];
// get the key code
UInt32 keyCode = 0, maskedKeyCode = 0;
unsigned short sym = 0;
keyCode = [theEvent keyCode];
NSString *s = [theEvent characters];
static BOOL compose = NO;
// send keydown events to an object of type NSText that handles character composition sequences
NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
if([theEvent type] == NSKeyDown) [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
NSString *s = [theEvent characters];
FLTextView *edit = (FLTextView*)[[theEvent window] fieldEditor:YES forObject:nil];
[edit needKBhandler:NO];
if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) {
s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit
}
if ([s length] == 0) { // this is a dead key that must be combined with the next key to be pressed
compose=YES;
fl_unlock_function();
return noErr;
}
// extended keyboards can also send sequences on key-up to generate Kanji etc. codes.
// Some observed prefixes are 0x81 to 0x83, followed by an 8 bit keycode.
// In this mode, there seem to be no key-down codes
@ -977,10 +1020,9 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent)
switch([theEvent type]) {
case NSKeyDown:
sendEvent = FL_KEYBOARD;
if(compose) Fl::compose_state = 1;
// fall through
case NSKeyUp: {
if(compose) sendEvent = FL_KEYBOARD;
case NSKeyUp:
if([edit compose]) sendEvent = FL_KEYBOARD; // when composing, the temporary character appears at KeyUp
if ( !sendEvent ) {
sendEvent = FL_KEYUP;
Fl::e_state &= 0xbfffffff; // clear the deadkey flag
@ -992,35 +1034,26 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent)
NSString *sim = [theEvent charactersIgnoringModifiers];
UniChar one;
CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one);
sym = one;
// charactersIgnoringModifiers doesn't ignore shift, remove it when it's on
if(sym >= 'A' && sym <= 'Z') sym += 32;
if(one >= 'A' && one <= 'Z') one += 32;
if (one > 0 && one <= 0x7f && (sym<'0' || sym>'9') ) sym = one;
}
Fl::e_keysym = Fl::e_original_keysym = sym;
// Handle FL_KP_Enter on regular keyboards and on Powerbooks
if ( maskedKeyCode==0x4c || maskedKeyCode==0x34) s = @"\r";
calc_e_text((CFStringRef)s, buffer, sizeof(buffer), sym);
Fl::e_length = strlen(buffer);
Fl::e_text = buffer;
}
if (sendEvent) {
retval = Fl::handle(sendEvent,window);
if([edit compose]) {
Fl::compose_state = 1;
[edit compose:NO];
}
break;
default:
fl_unlock_function();
return eventNotHandledErr;
}
while (window->parent()) window = window->window();
if (sendEvent && Fl::handle(sendEvent,window)) {
if ([theEvent type] == NSKeyDown) {
[edit setString:@""];
if (compose) compose = NO;
}
fl_unlock_function();
return noErr; // return noErr if FLTK handled the event
} else {
fl_unlock_function();
return eventNotHandledErr;
}
fl_unlock_function();
return retval ? (int)noErr : (int)eventNotHandledErr; // return noErr if FLTK handled the event
}
@ -1097,6 +1130,7 @@ extern "C" {
UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
}
@interface FLDelegate : NSObject
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
<NSWindowDelegate, NSApplicationDelegate>
@ -1113,7 +1147,7 @@ extern "C" {
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
- (void)applicationDidBecomeActive:(NSNotification *)notify;
- (void)applicationWillResignActive:(NSNotification *)notify;
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client;
@end
@implementation FLDelegate
- (void)windowDidMove:(NSNotification *)notif
@ -1203,7 +1237,7 @@ extern "C" {
}
/**
* Cocoa organizes the Z depth of windows on a global priority. FLTK however
* expectes the window manager to organize Z level by application. The trickery
* expects the window manager to organize Z level by application. The trickery
* below will change Z order during activation and deactivation.
*/
- (void)applicationDidBecomeActive:(NSNotification *)notify
@ -1278,6 +1312,16 @@ extern "C" {
}
}
}
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client
{
NSRect rect={{0,0},{20,20}};
static FLTextView *view = nil;
if (!view) {
view = [[FLTextView alloc] initWithFrame:rect];
[view compose:NO];
}
return view;
}
@end
@interface FLApplication : NSApplication
@ -1446,18 +1490,6 @@ void Fl::get_mouse(int &x, int &y)
}
/*
* convert Mac keystrokes to FLTK
*/
/*
* unsigned short mac2fltk(ulong macKey)
* {
* unsigned short cc = macKeyLookUp[(macKey>>8)&0x7f];
* if (cc) return cc;
* return macKey&0xff;
* }
*/
/*
* Initialize the given port for redraw and call the window's flush() to actually draw the content
*/
@ -1476,24 +1508,6 @@ static void handleUpdateEvent( Fl_Window *window )
Fl_X *i = Fl_X::i( window );
i->wait_for_expose = 0;
// FIXME: Matt: this is in the Carbon version. Does it need to be here?
/*
* // I don't think so (MG). This function gets called only when a full
* // redraw is needed (creation, resize, deminiaturization)
* // and later in it we set damages to DAMAGE_ALL, so there is no
* // point in limiting redraw to i->region
* if ( i->xid && window->damage() ) {
* NSView *view = [(NSWindow*)i->xid contentView];
* if ( view && i->region ) {
* int ix;
* Fl_Region rgn = i->region;
* for (ix=0; ix<rgn->count; ix++) {
* NSRect rect = NSRectFromCGRect(rgn->rects[ix]);
* [view setNeedsDisplayInRect:rect];
* }
* }
* }
*/
if ( i->region ) {
XDestroyRegion(i->region);
i->region = 0;
@ -1513,6 +1527,7 @@ static void handleUpdateEvent( Fl_Window *window )
window->clear_damage();
}
int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
int W, H, xoff, yoff, dx, dy;
int ret = bx = by = bt = 0;
@ -1709,7 +1724,13 @@ static void q_set_window_title(NSWindow *nsw, const char * name ) {
cocoaMouseWheelHandler(theEvent);
}
- (void)keyDown:(NSEvent *)theEvent {
cocoaKeyboardHandler(theEvent);
FLTextView *edit = (FLTextView*)[[theEvent window] fieldEditor:YES forObject:nil];
if ([[theEvent characters] length] == 0) [edit compose:YES];
if (Fl::compose_state) [edit needKBhandler:YES];
else [edit needKBhandler:NO];
[edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
// in some cases (e.g., some Greek letters with tonos) interpretKeyEvents does not call insertText
if ([edit needKBhandler]) cocoaKeyboardHandler(theEvent);
}
- (void)keyUp:(NSEvent *)theEvent {
cocoaKeyboardHandler(theEvent);
@ -2825,7 +2846,7 @@ static void createAppleMenu(void)
if (MACsystemVersion < 0x1060) {
// [NSApp setAppleMenu:appleMenu];
// to avoid compiler warning raised by use of undocumented setAppleMenu :
[NSApp performSelector:@selector(setAppleMenu:) withObject:appleMenu];
[NSApp performSelector:@selector(setAppleMenu:) withObject:appleMenu];
}
[NSApp setServicesMenu:services];
[NSApp setMainMenu:mainmenu];