| Summary: | ibus on Ubuntu 14.04 causes duplicate keydown events | ||
|---|---|---|---|
| Product: | SDL | Reporter: | johnv |
| Component: | events | Assignee: | Ryan C. Gordon <icculus> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | alex, metalcaedes |
| Version: | 2.0.3 | Keywords: | target-2.0.4 |
| Hardware: | x86_64 | ||
| OS: | Linux | ||
| Attachments: | repro for XFilterEvent bug | ||
Without the troubling code, dead keys don't generate any keydown events, which also sucks.. see https://bugzilla.libsdl.org/show_bug.cgi?id=2071 Is there be a way to make both cases work? I don't know much about ibus, but maybe it should only be used for textinput events and not for key presses? Does that make sense, and if it does, is it technically possible? This is only an issue because you are calling XSetLocaleModifiers. SDL doesn't call it internally afaict so $XMODIFIERS is never read, and XIM won't connect to ibus-daemon even if it was started with --xim.
If you *have* to call XSetLocaleModifiers for some reason, you can work around this issue by checking if XMODIFIERS contains "@im=ibus" and calling XSetLocaleModifiers("@im=none"). e.g:
> const char* xmodifiers = SDL_getenv("XMODIFIERS");
> if (SDL_strcmp(xmodifiers, "@im=ibus") == 0) {
> XSetLocaleModifiers("@im=none");
> } else {
> XSetLocaleModifiers("");
> }
Maybe something like that could be added into SDL internally, since using iBus via XIM could also conflict with the DBus+iBus code that was added.
Fixed by Alex's patch in bug 3136 https://hg.libsdl.org/SDL/rev/2f18ea79bc03 |
Created attachment 1642 [details] repro for XFilterEvent bug In a clean install of Ubuntu 14.04, ibus is enabled by default. (in the environment, XMODIFIERS=@im=ibus). This means that in some cases, XFilterEvent will return TRUE for a keydown event. And then the same keydown event is redelivered immediately, but XFilterEvent returns FALSE. There is code in X11_DispatchEvent() which calls SDL_SendKeyboardKey even though XFilterEvent returned true. This causes a duplicate SDL keydown event. See the attached code for a repro case on Ubuntu 14.04 with Unity. I don't know the rationale behind why SDL would deliver keydowns for these filtered keys. Here is a patch which just ignores the filtered events, but it is possible something cleverer needs to be done. --- a/src/video/x11/SDL_x11events.c Tue May 06 20:31:10 2014 -0400 +++ b/src/video/x11/SDL_x11events.c Thu May 08 16:02:44 2014 -0700 @@ -279,23 +279,12 @@ Display *display = videodata->display; SDL_WindowData *data; XEvent xevent; - int orig_event_type; - KeyCode orig_keycode; XClientMessageEvent m; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ X11_XNextEvent(display, &xevent); - /* Save the original keycode for dead keys, which are filtered out by - the XFilterEvent() call below. - */ - orig_event_type = xevent.type; - if (orig_event_type == KeyPress || orig_event_type == KeyRelease) { - orig_keycode = xevent.xkey.keycode; - } else { - orig_keycode = 0; - } /* filter events catchs XIM events and sends them to the correct handler */ if (X11_XFilterEvent(&xevent, None) == True) { @@ -303,15 +292,6 @@ printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif - if (orig_keycode) { - /* Make sure dead key press/release events are sent */ - SDL_Scancode scancode = videodata->key_layout[orig_keycode]; - if (orig_event_type == KeyPress) { - SDL_SendKeyboardKey(SDL_PRESSED, scancode); - } else { - SDL_SendKeyboardKey(SDL_RELEASED, scancode); - } - } return; }