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 {
