From 49fd00c84f1ed0c7b8451a07769e7c9ab6fa3310 Mon Sep 17 00:00:00 2001 From: Bob Pendleton Date: Fri, 7 Mar 2008 20:54:11 +0000 Subject: [PATCH] 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 | 5 +++++ src/video/x11/SDL_x11dyn.h | 3 ++- src/video/x11/SDL_x11events.c | 23 ++++++++++++++++++++--- src/video/x11/SDL_x11sym.h | 1 + src/video/x11/SDL_x11window.c | 30 +++++++++++++++++++++--------- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/video/x11/SDL_x11dyn.c b/src/video/x11/SDL_x11dyn.c index 0bc668813..0fa037506 100644 --- a/src/video/x11/SDL_x11dyn.c +++ b/src/video/x11/SDL_x11dyn.c @@ -98,6 +98,7 @@ X11_GetSym(const char *fnname, int *rc, void **fn) /* 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 @@ SDL_X11_UnloadSymbols(void) #ifdef X_HAVE_UTF8_STRING pXCreateIC = NULL; + pXGetICValues = NULL; #endif for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { @@ -165,6 +167,8 @@ SDL_X11_LoadSymbols(void) #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 @@ SDL_X11_LoadSymbols(void) #else #ifdef X_HAVE_UTF8_STRING pXCreateIC = XCreateIC; + pXGetICValues = XGetICValues; #endif #endif diff --git a/src/video/x11/SDL_x11dyn.h b/src/video/x11/SDL_x11dyn.h index 31d312f35..fc99073d0 100644 --- a/src/video/x11/SDL_x11dyn.h +++ b/src/video/x11/SDL_x11dyn.h @@ -68,9 +68,10 @@ extern "C" 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. */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index eddeee5d7..882482ce1 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1,3 +1,4 @@ +#define DEBUG_XEVENTS /* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga @@ -40,6 +41,15 @@ X11_DispatchEvent(_THIS) 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 @@ X11_DispatchEvent(_THIS) 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 @@ X11_DispatchEvent(_THIS) 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); diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 45aaec885..be881ab18 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -156,6 +156,7 @@ SDL_X11_SYM(int,Xutf8TextListToTextProperty,(Display* a,char** b,int c,XICCEncod 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) diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 50f4b9645..9de82581c 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -455,13 +455,6 @@ X11_CreateWindow(_THIS, SDL_Window * window) 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 @@ X11_CreateWindow(_THIS, SDL_Window * window) } #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 @@ X11_DestroyWindow(_THIS, SDL_Window * window) #endif if (data->created) { XDestroyWindow(display, data->window); - X11_PumpEvents(_this); } SDL_free(data); }