Next version of internationalized input for X11. On my machine (famous last words :-) with a US English keyboard and locale I can compose ` and e and get a text
authorBob Pendleton <bob@pendleton.com>
Fri, 07 Mar 2008 20:54:11 +0000
changeset 2325 c7bcf84ba1b9
parent 2324 3202e4826c57
child 2326 133562468ff2
Next version of internationalized input for X11. On my machine (famous last words :-) with a US English keyboard and locale I can compose ` and e and get a text input event with the character รจ. You still get the keypress keyrelease events for the individual keys that go into composing the character.
src/video/x11/SDL_x11dyn.c
src/video/x11/SDL_x11dyn.h
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11sym.h
src/video/x11/SDL_x11window.c
--- a/src/video/x11/SDL_x11dyn.c	Fri Mar 07 17:20:37 2008 +0000
+++ b/src/video/x11/SDL_x11dyn.c	Fri Mar 07 20:54:11 2008 +0000
@@ -98,6 +98,7 @@
 /* Annoying varargs entry point... */
 #ifdef X_HAVE_UTF8_STRING
 XIC(*pXCreateIC) (XIM,...) = NULL;
+char *(*pXGetICValues) (XIC, ...) = NULL;
 #endif
 
 /* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
@@ -128,6 +129,7 @@
 
 #ifdef X_HAVE_UTF8_STRING
             pXCreateIC = NULL;
+            pXGetICValues = NULL;
 #endif
 
             for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
@@ -165,6 +167,8 @@
 
 #ifdef X_HAVE_UTF8_STRING
         X11_GetSym("XCreateIC", &SDL_X11_HAVE_UTF8, (void **) &pXCreateIC);
+        X11_GetSym("XGetICValues", &SDL_X11_HAVE_UTF8,
+                   (void **) &pXGetICValues);
 #endif
 
         if (SDL_X11_HAVE_BASEXLIB) {
@@ -179,6 +183,7 @@
 #else
 #ifdef X_HAVE_UTF8_STRING
     pXCreateIC = XCreateIC;
+    pXGetICValues = XGetICValues;
 #endif
 #endif
 
--- a/src/video/x11/SDL_x11dyn.h	Fri Mar 07 17:20:37 2008 +0000
+++ b/src/video/x11/SDL_x11dyn.h	Fri Mar 07 20:54:11 2008 +0000
@@ -68,9 +68,10 @@
     int SDL_X11_LoadSymbols(void);
     void SDL_X11_UnloadSymbols(void);
 
-/* That's really annoying...make this a function pointer no matter what. */
+/* That's really annoying...make these function pointers no matter what. */
 #ifdef X_HAVE_UTF8_STRING
     extern XIC(*pXCreateIC) (XIM, ...);
+    extern char *(*pXGetICValues) (XIC, ...);
 #endif
 
 /* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
--- a/src/video/x11/SDL_x11events.c	Fri Mar 07 17:20:37 2008 +0000
+++ b/src/video/x11/SDL_x11events.c	Fri Mar 07 20:54:11 2008 +0000
@@ -1,3 +1,4 @@
+#define DEBUG_XEVENTS
 /*
     SDL - Simple DirectMedia Layer
     Copyright (C) 1997-2006 Sam Lantinga
@@ -40,6 +41,15 @@
     SDL_zero(xevent);           /* valgrind fix. --ryan. */
     XNextEvent(videodata->display, &xevent);
 
+    /* filter events catchs XIM events and sends them to the correct
+       handler */
+    if (XFilterEvent(&xevent, None) == True) {
+#ifdef DEBUG_XEVENTS
+        printf("Filtered event of type = 0x%X\n", xevent.type);
+#endif
+        return;
+    }
+
     /* Send a SDL_SYSWMEVENT if the application wants them */
     if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
         SDL_SysWMmsg wmmsg;
@@ -182,14 +192,14 @@
             KeyCode keycode = xevent.xkey.keycode;
             KeySym keysym = NoSymbol;
             char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
-            Uint32 ucs4 = 0;
+            Status status = 0;
 
 #ifdef DEBUG_XEVENTS
             printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
 #endif
             SDL_SendKeyboardKey(videodata->keyboard, SDL_PRESSED,
                                 videodata->key_layout[keycode]);
-#if 1
+#if 0
             if (videodata->key_layout[keycode] == SDLK_UNKNOWN) {
                 int min_keycode, max_keycode;
                 XDisplayKeycodes(videodata->display, &min_keycode,
@@ -201,9 +211,16 @@
                         XKeysymToString(keysym));
             }
 #endif
-            /* Xutf8LookupString(), works for Latin-1 */
+            /* */
             SDL_zero(text);
+#ifdef X_HAVE_UTF8_STRING
+            if (data->ic) {
+                Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
+                                  &keysym, status);
+            }
+#else
             XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
+#endif
             if (*text) {
                 printf("Sending text event %s\n", text);
                 SDL_SendKeyboardText(videodata->keyboard, text);
--- a/src/video/x11/SDL_x11sym.h	Fri Mar 07 17:20:37 2008 +0000
+++ b/src/video/x11/SDL_x11sym.h	Fri Mar 07 20:54:11 2008 +0000
@@ -156,6 +156,7 @@
 SDL_X11_SYM(int,Xutf8LookupString,(XIC a,XKeyPressedEvent* b,char* c,int d,KeySym* e,Status* f),(a,b,c,d,e,f),return)
 /*SDL_X11_SYM(XIC,XCreateIC,(XIM, ...),return)  !!! ARGH! */
 SDL_X11_SYM(void,XDestroyIC,(XIC a),(a),)
+/*SDL_X11_SYM(char*,XGetICValues,(XIC, ...),return)  !!! ARGH! */
 SDL_X11_SYM(void,XSetICFocus,(XIC a),(a),)
 SDL_X11_SYM(void,XUnsetICFocus,(XIC a),(a),)
 SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d),(a,b,c,d),return)
--- a/src/video/x11/SDL_x11window.c	Fri Mar 07 17:20:37 2008 +0000
+++ b/src/video/x11/SDL_x11window.c	Fri Mar 07 20:54:11 2008 +0000
@@ -455,13 +455,6 @@
         XFree(wmhints);
     }
 
-    XSelectInput(data->display, w,
-                 (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
-                  ExposureMask | ButtonPressMask | ButtonReleaseMask |
-                  PointerMotionMask | KeyPressMask | KeyReleaseMask |
-                  PropertyChangeMask | StructureNotifyMask |
-                  KeymapStateMask));
-
     /* Set the class hints so we can get an icon (AfterStep) */
     classhints = XAllocClassHint();
     if (classhints != NULL) {
@@ -481,9 +474,29 @@
         }
 #endif
         XDestroyWindow(data->display, w);
-        X11_PumpEvents(_this);
         return -1;
     }
+#ifdef X_HAVE_UTF8_STRING
+    {
+        Uint32 fevent = 0;
+        pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
+                      XNFilterEvents, &fevent, NULL);
+        XSelectInput(data->display, w,
+                     (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
+                      ExposureMask | ButtonPressMask | ButtonReleaseMask |
+                      PointerMotionMask | KeyPressMask | KeyReleaseMask |
+                      PropertyChangeMask | StructureNotifyMask |
+                      KeymapStateMask | fevent));
+    }
+#else
+    XSelectInput(data->display, w,
+                 (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
+                  ExposureMask | ButtonPressMask | ButtonReleaseMask |
+                  PointerMotionMask | KeyPressMask | KeyReleaseMask |
+                  PropertyChangeMask | StructureNotifyMask |
+                  KeymapStateMask));
+#endif
+
     return 0;
 }
 
@@ -680,7 +693,6 @@
 #endif
         if (data->created) {
             XDestroyWindow(display, data->window);
-            X11_PumpEvents(_this);
         }
         SDL_free(data);
     }