We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2526

Summary: ibus on Ubuntu 14.04 causes duplicate keydown events
Product: SDL Reporter: johnv
Component: eventsAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: alex, metalcaedes
Version: 2.0.3Keywords: target-2.0.4
Hardware: x86_64   
OS: Linux   
Attachments: repro for XFilterEvent bug

Description johnv 2014-05-08 23:06:52 UTC
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;
     }
Comment 1 Daniel Gibson 2015-02-09 01:39:19 UTC
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?
Comment 2 Daniel Gibson 2015-02-09 15:28:34 UTC
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?
Comment 3 Alex Baines 2015-09-28 22:58:34 UTC
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.
Comment 4 Sam Lantinga 2016-10-01 21:11:16 UTC
Fixed by Alex's patch in bug 3136
https://hg.libsdl.org/SDL/rev/2f18ea79bc03