diff -up fltk-1.3.x-r8617/FL/Fl_Widget.H.orig fltk-1.3.x-r8617/FL/Fl_Widget.H
--- fltk-1.3.x-r8617/FL/Fl_Widget.H.orig	2011-05-04 12:44:24.517343484 +0200
+++ fltk-1.3.x-r8617/FL/Fl_Widget.H	2011-05-04 15:03:03.821527220 +0200
@@ -179,6 +179,7 @@ protected:
         NO_OVERLAY      = 1<<15,  ///< window not using a hardware overlay plane (Fl_Menu_Window)
         GROUP_RELATIVE  = 1<<16,  ///< position this widget relative to the parent group, not to the window
         COPIED_TOOLTIP  = 1<<17,  ///< the widget tooltip is internally copied, its destruction is handled by the widget
+        SIMPLE_KEYBOARD = 1<<18,  ///< the widget wants simple, consistent keypresses and not advanced input (like character composition and CJK input)
         // (space for more flags)
         USERFLAG3       = 1<<29,  ///< reserved for 3rd party extensions
         USERFLAG2       = 1<<30,  ///< reserved for 3rd party extensions
@@ -781,6 +782,35 @@ public:
    */
   void clear_changed() {flags_ &= ~CHANGED;}
 
+  /** 
+      Returns if the widget sees a simplified keyboard model or not.
+
+      Normally widgets get a full-featured keyboard model that is geared
+      towards text input. This includes support for compose sequences and
+      advanced input methods, commonly used for asian writing system. This
+      system however has downsides in that extra graphic can be presented
+      to the user and that a physical key press doesn't correspond directly
+      to a FLTK event.
+
+      Widgets that need a direct correspondence between actual key events
+      and those seen by the widget can swith to the simplified keyboard
+      model.
+
+     \retval 0 if the widget uses the normal keyboard model
+     \see set_changed(), clear_changed()
+   */
+  unsigned int simple_keyboard() const {return flags_&SIMPLE_KEYBOARD;}
+
+  /** Marks a widget to use the simple keyboard model.
+      \see changed(), clear_changed()
+   */
+  void set_simple_keyboard() {flags_ |= SIMPLE_KEYBOARD;}
+
+  /** Marks a widget to use the normal keyboard model.
+      \see changed(), set_changed()
+   */
+  void set_normal_keyboard() {flags_ &= ~SIMPLE_KEYBOARD;}
+
   /** Gives the widget the keyboard focus.
       Tries to make this widget be the Fl::focus() widget, by first sending 
       it an FL_FOCUS event, and if it returns non-zero, setting 
diff -up fltk-1.3.x-r8617/src/Fl.cxx.orig fltk-1.3.x-r8617/src/Fl.cxx
--- fltk-1.3.x-r8617/src/Fl.cxx.orig	2011-05-04 15:42:35.494214271 +0200
+++ fltk-1.3.x-r8617/src/Fl.cxx	2011-05-04 15:42:39.622833481 +0200
@@ -63,6 +63,8 @@ void fl_cleanup_dc_list(void);
 extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle);
 #endif // WIN32
 
+extern void fl_update_focus(void);
+
 //
 // Globals...
 //
@@ -864,6 +866,8 @@ void Fl::focus(Fl_Widget *o) {
       fl_oldfocus = p;
     }
     e_number = old_event;
+    // let the platform code do what it needs
+    fl_update_focus();
   }
 }
 
diff -up fltk-1.3.x-r8617/src/Fl_grab.cxx.orig fltk-1.3.x-r8617/src/Fl_grab.cxx
--- fltk-1.3.x-r8617/src/Fl_grab.cxx.orig	2011-05-04 14:25:14.817153418 +0200
+++ fltk-1.3.x-r8617/src/Fl_grab.cxx	2011-05-04 14:41:40.896082696 +0200
@@ -38,7 +38,8 @@
 // override_redirect, it does similar things on WIN32.
 
 extern void fl_fix_focus(); // in Fl.cxx
+void fl_update_focus(void);
 
 #ifdef WIN32
 // We have to keep track of whether we have captured the mouse, since
 // MSWindows shows little respect for this... Grep for fl_capture to
@@ -79,6 +80,7 @@ void Fl::grab(Fl_Window* win) {
 #endif
     }
     grab_ = win;
+    fl_update_focus();
   } else {
     if (grab_) {
 #ifdef WIN32
@@ -94,6 +96,7 @@ void Fl::grab(Fl_Window* win) {
       XFlush(fl_display);
 #endif
       grab_ = 0;
+      fl_update_focus();
       fl_fix_focus();
     }
   }
diff -up fltk-1.3.x-r8617/src/Fl_x.cxx.orig fltk-1.3.x-r8617/src/Fl_x.cxx
--- fltk-1.3.x-r8617/src/Fl_x.cxx.orig	2011-05-04 12:31:46.275583047 +0200
+++ fltk-1.3.x-r8617/src/Fl_x.cxx	2011-05-04 14:42:26.351901055 +0200
@@ -299,6 +299,7 @@ XVisualInfo *fl_visual;
 Colormap fl_colormap;
 XIM fl_xim_im = 0;
 XIC fl_xim_ic = 0;
+Window fl_xim_win = 0;
 char fl_is_over_the_spot = 0;
 static XRectangle status_area;
 
@@ -580,6 +581,79 @@ void fl_init_xim() {
   if(xim_styles) XFree(xim_styles);
 }
 
+void fl_xim_deactivate(void);
+
+void fl_xim_activate(Window xid)
+{
+  if (!fl_xim_im)
+    return;
+
+  // If the focused window has changed, then use the brute force method
+  // of completely recreating the input context.
+  if (fl_xim_win != xid) {
+    fl_xim_deactivate();
+
+    fl_new_ic();
+    fl_xim_win = xid;
+
+    XSetICValues(fl_xim_ic,
+                 XNFocusWindow, fl_xim_win,
+                 XNClientWindow, fl_xim_win,
+                 NULL);
+  }
+
+  fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
+}
+
+void fl_xim_deactivate(void)
+{
+  if (!fl_xim_ic)
+    return;
+
+  XDestroyIC(fl_xim_ic);
+  fl_xim_ic = NULL;
+
+  fl_xim_win = 0;
+}
+
+void fl_update_focus(void)
+{
+  Fl_Widget *focus;
+
+  focus = Fl::grab();
+  if (!focus)
+    focus = Fl::focus();
+  if (!focus)
+    return;
+
+  if (focus->simple_keyboard()) {
+    fl_xim_deactivate();
+  } else {
+    Fl_Window *win;
+
+    // Grabs are special in that events are sent to the first
+    // available window
+    if (focus == Fl::grab())
+      win = Fl::first_window();
+    else {
+      win = focus->as_window();
+      if (!win)
+        win = focus->window();
+    }
+
+    if (!win) {
+      Fl::warning("Cannot find window for widget receiving focus");
+      return;
+    }
+
+    // No X11 window created yet
+    if (!Fl_X::i(win) || !fl_xid(win))
+      return;
+
+    fl_xim_activate(fl_xid(win));
+  }
+}
+
 void fl_open_display() {
   if (fl_display) return;
 
@@ -863,10 +937,9 @@ int fl_handle(const XEvent& thisevent)
   XEvent xevent = thisevent;
   fl_xevent = &thisevent;
   Window xid = xevent.xany.window;
-  static Window xim_win = 0;
 
   if (fl_xim_ic && xevent.type == DestroyNotify &&
-        xid != xim_win && !fl_find(xid))
+        xid != fl_xim_win && !fl_find(xid))
   {
     XIM xim_im;
     xim_im = XOpenIM(fl_display, NULL, NULL, NULL);
@@ -881,48 +954,15 @@ int fl_handle(const XEvent& thisevent)
     return 0;
   }
 
-  if (fl_xim_ic && (xevent.type == FocusIn))
-  {
-#define POOR_XIM
-#ifdef POOR_XIM
-        if (xim_win != xid)
-        {
-                xim_win  = xid;
-                XDestroyIC(fl_xim_ic);
-                fl_xim_ic = NULL;
-                fl_new_ic();
-                XSetICValues(fl_xim_ic,
-                                XNFocusWindow, xevent.xclient.window,
-                                XNClientWindow, xid,
-                                NULL);
-        }
-        fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-#else
-    if (Fl::first_window() && Fl::first_window()->modal()) {
-      Window x  = fl_xid(Fl::first_window());
-      if (x != xim_win) {
-        xim_win  = x;
-        XSetICValues(fl_xim_ic,
-                        XNFocusWindow, xim_win,
-                        XNClientWindow, xim_win,
-                        NULL);
-        fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-      }
-    } else if (xim_win != xid && xid) {
-      xim_win = xid;
-      XSetICValues(fl_xim_ic,
-                        XNFocusWindow, xevent.xclient.window,
-                        XNClientWindow, xid,
-                        //XNFocusWindow, xim_win,
-                        //XNClientWindow, xim_win,
-                        NULL);
-      fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-    }
-#endif
-  }
+  // Activate XIM for this window early, so that XFilterEvent() can start
+  // doing its magic.
+  if (xevent.type == FocusIn)
+    fl_xim_activate(xid);
 
-  if ( XFilterEvent((XEvent *)&xevent, 0) )
-      return(1);
+  if (fl_xim_ic) {
+    if (XFilterEvent((XEvent *)&xevent, 0))
+      return 1;
+  }
 
   switch (xevent.type) {
 
@@ -1247,15 +1287,15 @@ int fl_handle(const XEvent& thisevent)
         //static XComposeStatus compose;
         len = XLookupString((XKeyEvent*)&(xevent.xkey),
                              buffer, buffer_len, &keysym, 0/*&compose*/);
-        if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets
-          // force it to type a character (not sure if this ever is needed):
-          // if (!len) {buffer[0] = char(keysym); len = 1;}
-          len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
-          if (len < 1) len = 1;
-          // ignore all effects of shift on the keysyms, which makes it a lot
-          // easier to program shortcuts and is Windoze-compatable:
-          keysym = XKeycodeToKeysym(fl_display, keycode, 0);
-        }
+        // XLookupString() is only defined to return Latin-1 (although it
+        // often gives you more). To be safe, use our own lookups based on
+        // keysym.
+        len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
+        if (len < 1)
+          len = 1;
+        // ignore all effects of shift on the keysyms, which makes it a lot
+        // easier to program shortcuts and is Windoze-compatable:
+        keysym = XKeycodeToKeysym(fl_display, keycode, 0);
       }
       // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not
       //      set until set_event_xy() is called later...
