DO NOT REPLY TO THIS MESSAGE. INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.
[STR New]
Link: http://www.fltk.org/str.php?L2599
Version: 1.3-feature
Attached file "fltk-1.3.x-keyboard-osx.patch"...
Link: http://www.fltk.org/str.php?L2599
Version: 1.3-feature
diff -up fltk-1.3.x-r8617/src/Fl_cocoa.mm.orig fltk-1.3.x-r8617/src/Fl_cocoa.mm
--- fltk-1.3.x-r8617/src/Fl_cocoa.mm.orig 2011-05-05 13:08:57.156415261
+0200
+++ fltk-1.3.x-r8617/src/Fl_cocoa.mm 2011-05-05 14:09:38.311810412 +0200
@@ -124,6 +124,8 @@ static Fl_Window* send_motion;
extern Fl_Window* fl_xmousewin;
#endif
+bool use_simple_keyboard = false;
+
enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
@@ -140,6 +142,22 @@ void fl_set_status(int x, int y, int w,
{
}
+void fl_update_focus(void)
+{
+ Fl_Widget *focus;
+
+ focus = Fl::grab();
+ if (!focus)
+ focus = Fl::focus();
+ if (!focus)
+ return;
+
+ if (focus->simple_keyboard())
+ use_simple_keyboard = true;
+ else
+ use_simple_keyboard = false;
+}
+
/*
* Mac keyboard lookup table
* See also the inverse converter vktab in Fl_get_key_mac.cxx
@@ -848,34 +866,26 @@ static void cocoaMouseHandler(NSEvent *t
return;
}
-
-static void calc_e_text(CFStringRef s, char *buffer, size_t len, unsigned sym)
+static const char* cocoaDead2FLTK(const char *in)
{
- int i, no_text_key = false;
- static unsigned notext[] = { // keys that don't emit text
- FL_BackSpace, FL_Print, FL_Scroll_Lock, FL_Pause,
- FL_Insert, FL_Home, FL_Page_Up, FL_Delete, FL_End, FL_Page_Down,
- FL_Left, FL_Up, FL_Right, FL_Down,
- 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) {
- no_text_key = true;
- break;
- }
- }
-
- if (no_text_key) {
- buffer[0] = 0;
- } else {
- CFStringGetCString(s, buffer, len, kCFStringEncodingUTF8);
- }
+ if (strcmp(in, "\140") == 0) // GRAVE ACCENT
+ return "\314\200"; // COMBINING GRAVE ACCENT
+ if (strcmp(in, "\302\264") == 0) // ACUTE ACCENT
+ return "\314\201"; // COMBINING ACUTE ACCENT
+ if (strcmp(in, "\136") == 0) // CIRCUMFLEX ACCENT
+ return "\314\202"; // COMBINING CIRCUMFLEX ACCENT
+ if (strcmp(in, "\176") == 0) // TILDE
+ return "\314\203"; // COMBINING TILDE
+ if (strcmp(in, "\302\250") == 0) // DIAERESIS
+ return "\314\210"; // COMBINING DIAERESIS
+ // FIXME: OS X dead key behaviour isn't documented and I don't have
+ // any more keyboards to test with...
+
+ // hope that OS X gave us something proper to begin with
+ return in;
}
-static int cocoaKeyboardHandler(NSEvent *theEvent);
+static void cocoaKeyboardHandler(NSEvent *theEvent);
@interface FLTextView : NSTextView
// this subclass is needed under OS X <= 10.4 but not under >= 10.5 where the
base class is enough
@@ -885,11 +895,13 @@ static int cocoaKeyboardHandler(NSEvent
@implementation FLTextView
- (void)insertText:(id)aString
{
- cocoaKeyboardHandler([NSApp currentEvent]);
+ //NSLog(@"FLTextView:insertText:");
+ [[[NSApp keyWindow] contentView] insertText:aString];
}
- (void)doCommandBySelector:(SEL)aSelector
{
- cocoaKeyboardHandler([NSApp currentEvent]);
+ //NSLog(@"FLTextView:doCommandBySelector:");
+ [[[NSApp keyWindow] contentView] doCommandBySelector:aSelector];
}
@end
@@ -902,15 +914,10 @@ Events during a character composition se
replace the temporary character by this one
- keyup -> [theEvent characters] contains the standard character
*/
-static int cocoaKeyboardHandler(NSEvent *theEvent)
+static void cocoaKeyboardHandler(NSEvent *theEvent)
{
- static char buffer[32];
- 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
@@ -926,40 +933,31 @@ static int cocoaKeyboardHandler(NSEvent
// In this mode, there seem to be no key-down codes
// printf("%08x %08x %08x\n", keyCode, mods, key);
maskedKeyCode = keyCode & 0x7f;
- switch([theEvent type]) {
- case NSKeyDown:
- sendEvent = FL_KEYBOARD;
- // fall through
- case NSKeyUp:
- if ( !sendEvent ) {
- sendEvent = FL_KEYUP;
- Fl::e_state &= 0xbfffffff; // clear the deadkey flag
- }
- mods_to_e_state( mods ); // process modifier keys
- sym = macKeyLookUp[maskedKeyCode];
- if (sym < 0xff00) { // a "simple" key
- // find the result of this key without modifier
- NSString *sim = [theEvent charactersIgnoringModifiers];
- UniChar one;
- CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one);
- // charactersIgnoringModifiers doesn't ignore shift, remove it when
it's on
- 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;
- default: // prevent 'not handled in switch' warnings
- break;
+
+ if ([theEvent type] == NSKeyUp) {
+ Fl::e_state &= 0xbfffffff; // clear the deadkey flag
}
- if (sendEvent) {
- retval = Fl::handle(sendEvent,window);
+
+ mods_to_e_state( mods ); // process modifier keys
+ sym = macKeyLookUp[maskedKeyCode];
+ if (sym < 0xff00) { // a "simple" key
+ // find the result of this key without modifier
+ NSString *sim = [theEvent charactersIgnoringModifiers];
+ UniChar one;
+ CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one);
+ // charactersIgnoringModifiers doesn't ignore shift, remove it when it's on
+ if(one >= 'A' && one <= 'Z') one += 32;
+ if (one > 0 && one <= 0x7f && (sym<'0' || sym>'9') ) sym = one;
}
- fl_unlock_function();
- return retval;
+ Fl::e_keysym = Fl::e_original_keysym = sym;
+
+ //NSLog(@"cocoaKeyboardHandler: keycode=%08x keysym=%08x mods=%08x symbol=%@
(%@)",
+ // keyCode, sym, mods, [theEvent characters], [theEvent
charactersIgnoringModifiers]);
+
+ // If there is text associated with this key, it will be filled
+ // in later.
+ Fl::e_length = 0;
+ Fl::e_text = "";
}
@@ -1637,7 +1635,10 @@ static void q_set_window_title(NSWindow
@interface FLView : NSView <NSTextInput> {
+ int next_compose_length;
+ bool in_key_event;
}
++ (void)prepareEtext:(NSString*)aString;
- (void)drawRect:(NSRect)rect;
- (BOOL)acceptsFirstResponder;
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
@@ -1653,6 +1654,7 @@ static void q_set_window_title(NSWindow
- (void)rightMouseDragged:(NSEvent *)theEvent;
- (void)otherMouseDragged:(NSEvent *)theEvent;
- (void)scrollWheel:(NSEvent *)theEvent;
+- (BOOL)handleKeyDown:(NSEvent *)theEvent;
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
- (void)flagsChanged:(NSEvent *)theEvent;
@@ -1679,8 +1681,8 @@ static void q_set_window_title(NSWindow
}
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent
{
- int retval = cocoaKeyboardHandler(theEvent);
- return (retval ? YES : NO);
+ //NSLog(@"performKeyEquivalent:");
+ return [self handleKeyDown:theEvent];
}
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent
{
@@ -1721,14 +1723,61 @@ static void q_set_window_title(NSWindow
- (void)scrollWheel:(NSEvent *)theEvent {
cocoaMouseWheelHandler(theEvent);
}
+- (BOOL)handleKeyDown:(NSEvent *)theEvent {
+ fl_lock_function();
+
+ Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window];
+
+ next_compose_length = -1;
+ in_key_event = true;
+
+ // First let's process the raw key press
+ cocoaKeyboardHandler(theEvent);
+
+ // Then we can let the OS have a stab at it and let it process it through
+ // relevant input methods and see if it thinks it should result in some text.
+ //
+ // Note: We avoid this step if the widget receiving key events has requested
+ // a simple keyboard model. This seems to be enough to make OS X avoid
+ // triggering input methods.
+ //
+ if (use_simple_keyboard) {
+ // We still want a symbol, which we can grab directly from the event
+ [FLView prepareEtext:[theEvent charactersIgnoringModifiers]];
+ } else {
+ NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
+ [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+ }
+
+ in_key_event = false;
+
+ Fl::first_window(window);
+ int handled = Fl::handle(FL_KEYDOWN,window);
+
+ // We have to update this after Fl::handle as it says what to do on the
+ // _next_ input
+ if (next_compose_length != -1)
+ Fl::compose_state = next_compose_length;
+
+ fl_unlock_function();
+
+ return (handled ? YES : NO);
+}
- (void)keyDown:(NSEvent *)theEvent {
- NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
- [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+ //NSLog(@"keyDown: ");
+ [self handleKeyDown:theEvent];
}
- (void)keyUp:(NSEvent *)theEvent {
+ //NSLog(@"keyUp: ");
+ fl_lock_function();
+ Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window];
cocoaKeyboardHandler(theEvent);
+ Fl::first_window(window);
+ Fl::handle(FL_KEYUP,window);
+ fl_unlock_function();
}
- (void)flagsChanged:(NSEvent *)theEvent {
+ //NSLog(@"flagsChanged: ");
fl_lock_function();
static UInt32 prevMods = 0;
NSUInteger mods = [theEvent modifierFlags];
@@ -1836,6 +1885,27 @@ static void q_set_window_title(NSWindow
return NSDragOperationGeneric;
}
++ (void)prepareEtext:(NSString*)aString {
+ // fills Fl::e_text with UTF-8 encoded aString using an adequate memory
allocation
+ static char *received_utf8 = NULL;
+ static int lreceived = 0;
+ char *p = (char*)[aString UTF8String];
+ int l = strlen(p);
+ if (l > 0) {
+ if (lreceived == 0) {
+ received_utf8 = (char*)malloc(l + 1);
+ lreceived = l;
+ }
+ else if (l > lreceived) {
+ received_utf8 = (char*)realloc(received_utf8, l + 1);
+ lreceived = l;
+ }
+ strcpy(received_utf8, p);
+ Fl::e_text = received_utf8;
+ }
+ Fl::e_length = l;
+}
+
// These functions implement text input.
// Only two-stroke character composition works at this point.
// Needs much elaboration to fully support CJK text input,
@@ -1844,49 +1914,89 @@ static void q_set_window_title(NSWindow
}
- (void)insertText:(id)aString {
- NSEvent *event = [NSApp currentEvent];
- NSEventType type = [event type];
- NSString *str = @"";
NSString *received;
if ([aString isKindOfClass:[NSAttributedString class]]) {
received = [(NSAttributedString*)aString string];
} else {
received = (NSString*)aString;
}
- if (type == NSKeyDown ) {
- str = [event characters];
- }
- if ([received isEqualToString:@"\b"] || [str isEqualToString:received]) {
- if (type == NSKeyDown ) cocoaKeyboardHandler(event);
- } else {
- fl_lock_function();
- Fl_Window *window = [(FLWindow*)[NSApp keyWindow] getFl_Window];
- Fl::e_text = (char*)[received UTF8String];
- Fl::e_length = strlen(Fl::e_text);
- if (type == NSKeyDown ) {
- Fl::e_keysym = macKeyLookUp[ [event keyCode] & 0x7f] ;
- Fl::handle(FL_KEYBOARD, window);
- }
- else {
- Fl::handle(FL_PASTE, window);
- // for some reason, the window does not redraw until the next mouse move
or button push
- // sending a 'redraw()' or 'awake()' does not solve the issue!
- Fl::flush();
- }
- fl_unlock_function();
+ //NSLog(@"insertText: received=%@",received);
+
+ fl_lock_function();
+
+ // Simple keyboard widgets do not want these side channel inputs.
+ if (use_simple_keyboard)
+ goto end;
+
+ [FLView prepareEtext:received];
+
+ // We can get called outside of key events (e.g. from the character
+ // palette). We need to fake our own key event at that point.
+ if (!in_key_event) {
+ Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
+ Fl::e_keysym = Fl::e_original_keysym = 0;
+ Fl::handle(FL_KEYDOWN, target);
}
+
+end:
+ fl_unlock_function();
}
- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection {
- // NSLog(@"setMarkedText: %@ %d %d Fl::compose_state=%d",
- // aString,newSelection.location,newSelection.length,newSelection.location);
- [self insertText:aString];
- Fl::compose_state = newSelection.location;
+ NSString *received, *current, *aggregate;
+
+ if (newSelection.location == 0) {
+ [self unmarkText];
+ return;
+ }
+
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
+ received = [(NSAttributedString*)aString string];
+ } else {
+ received = (NSString*)aString;
+ }
+
+ //NSLog(@"setMarkedText: %@ %d %d",
+ // received,newSelection.location,newSelection.length);
+
+ fl_lock_function();
+
+ // Simple keyboard widgets do not want these side channel inputs.
+ if (use_simple_keyboard)
+ goto end;
+
+ // This code creates the OS X behaviour of seeing dead keys as things
+ // are being composed. Comment out to get Windows/Unix behaviour.
+ //
+ // Note: The concatenation thing is because of how OS X deals with
+ // invalid sequences. At that point it will spit out one call
+ // to insertText with the now aborted sequence, and one new
+ // call to setMarkedText with the new sequence. Since we want
+ // both to be visible, we need to concatenate.
+ next_compose_length = newSelection.location;
+
+ current = [NSString stringWithUTF8String:Fl::e_text];
+ aggregate = [current stringByAppendingString:received];
+
+ [FLView prepareEtext:aggregate];
+
+ // We can get called outside of key events (e.g. from the character
+ // palette). We need to fake our own key event at that point.
+ if (!in_key_event) {
+ Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
+ Fl::e_keysym = Fl::e_original_keysym = 0;
+ Fl::handle(FL_KEYDOWN, target);
+ }
+
+end:
+ fl_unlock_function();
}
- (void)unmarkText {
+ fl_lock_function();
Fl::compose_state = 0;
//NSLog(@"unmarkText");
+ fl_unlock_function();
}
- (NSRange)selectedRange {
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev