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.4-feature


Attached file "fltk-1_v3.3.x-keyboard-osx.patch"...


Link: http://www.fltk.org/str.php?L2599
Version: 1.4-feature
diff -up fltk-1.3.x-r8617/configure.in.kbd-osx fltk-1.3.x-r8617/configure.in
--- fltk-1.3.x-r8617/configure.in.kbd-osx       2011-05-06 14:03:21.157506553 
+0200
+++ fltk-1.3.x-r8617/configure.in       2011-05-06 14:03:22.369688397 +0200
@@ -874,6 +874,8 @@ case $uname_GUI in
     Darwin*)
         # MacOS X uses Cocoa for graphics.
         LIBS="$LIBS -framework Cocoa"
+        # And some Carbon for keyboard handling
+        LIBS="$LIBS -framework Carbon"
 
        if test x$have_pthread = xyes; then
            AC_DEFINE(HAVE_PTHREAD)
diff -up fltk-1.3.x-r8617/src/Fl_cocoa.mm.kbd-osx 
fltk-1.3.x-r8617/src/Fl_cocoa.mm
--- fltk-1.3.x-r8617/src/Fl_cocoa.mm.kbd-osx    2011-04-19 14:37:20.000000000 
+0200
+++ fltk-1.3.x-r8617/src/Fl_cocoa.mm    2011-05-10 12:21:24.720638507 +0200
@@ -61,6 +61,7 @@ extern "C" {
 #include <stdarg.h>
 
 #import <Cocoa/Cocoa.h>
+#import <Carbon/Carbon.h>
 
 #ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
 #if defined(__LP64__) && __LP64__
@@ -124,6 +125,8 @@ static Fl_Window* send_motion;
 extern Fl_Window* fl_xmousewin;
 #endif
 
+bool use_simple_keyboard = false;
+
 enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
 
 
@@ -140,6 +143,39 @@ void fl_set_status(int x, int y, int w, 
 {
 }
 
+// Undocumented voodoo. Taken from Mozilla.
+#define ENABLE_ROMAN_KYBDS_ONLY -23
+
+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;
+
+  // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
+  // Safari people seem to think implies turning off advanced IME stuff
+  // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
+  // in Safari/Webcore). Should be good enough for us then...
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+  CFArrayRef inputSources = TISCreateASCIICapableInputSourceList();
+  TSMSetDocumentProperty(TSMGetActiveDocument(),
+                         kTSMDocumentEnabledInputSourcesPropertyTag,
+                         sizeof(CFArrayRef), &inputSources);
+  CFRelease(inputSources);
+#else
+  KeyScript(use_simple_keyboard ? ENABLE_ROMAN_KYBDS_ONLY : smKeyEnableKybds);
+#endif  
+}
+
 /*
  * Mac keyboard lookup table
  * See also the inverse converter vktab in Fl_get_key_mac.cxx
@@ -848,34 +884,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 +913,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 +932,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 +951,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 +1653,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 +1672,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 +1699,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 +1741,56 @@ static void  q_set_window_title(NSWindow
 - (void)scrollWheel:(NSEvent *)theEvent {
   cocoaMouseWheelHandler(theEvent);
 }
-- (void)keyDown:(NSEvent *)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);
+
+  // The simple keyboard model will ignore insertText, so we need to grab
+  // the symbol directly from the event. Note that we still use setMarkedText.
+  if (use_simple_keyboard)
+    [FLView prepareEtext:[theEvent charactersIgnoringModifiers]];
+
+  // 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.
   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 {
+  //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 +1898,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 +1927,98 @@ 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 generally do not want these side channel
+  // inputs, but we have no other way of getting dead keys so we make
+  // an exception in that case.
+  if (use_simple_keyboard) {
+    if (in_key_event && (Fl::e_length == 0)) {
+      [FLView prepareEtext:received];
+
+      Fl::e_text = (char*)cocoaDead2FLTK(Fl::e_text);
+      Fl::e_length = strlen(Fl::e_text);
+    }
+    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

Reply via email to