GNOME Bugzilla – Bug 93575
Compose key functionality not working
Last modified: 2011-02-04 16:11:52 UTC
I am unable to use the Compose key functionality on Solaris. I am using "C" Locale. For example typing Compose + a + e on gedit generates a beep. It should generate one letter - "latin small ligature ae" (Unicode 0x00e6) Input Method used is "Default".
The problem is in gtk/gtkimcontextsimple.c(no_sequence_matches) if context_simple->tentative_match is FALSE, then we check whether the n_compose value is > 1. However in gtk_im_context_simple_filter_keypress() the n_compose value is incremented alteast twice. Thereby the check for n_compose > 1 is always true. Attaching a patch which is a probably a fix for the problem.
Created attachment 11163 [details] [review] Proposed Patch
On applying the previous patch, i get a beep whenever i press Enter, Backspace etc.. :-). Attaching a modified patch.
Created attachment 11173 [details] [review] Modified patch
If the Locale is "C", the compose key functionality does not work when i change the Input Method to "X Input Method". For example typing Compose + a + e on gedit generates two characters "ae". Debugging this further here are my observations. In modules/input/gtkimcontextxim.c (gtk_im_context_xim_filter_keypress) 1. XFilterEvent() does not return TRUE for the "Compose" keypress and the "a" keypress or "e" keypress. 2. XmbLookupString always returns XLookupBoth. The compose functionality works when i set LANG="en_US.UTF-8" and run gedit. Here are my observations in this case. 1. XFilterEvent () returns TRUE for "Compose", "a", and "e". 2. After this eventually gtk_im_context_xim_filter_keypress is called. And now XFilterEvent returns FALSE. XmbLookupString returns XLookupBoth. Could this a bug in gtk+? Or is this a bug with the XIM extension on Solaris with "C" Locale ?
I don't think either of the first two pathces are correct - no_sequence_matches() can definitely be called with n_compose == 1. Plus, <compose> <a> <e> works fine for me with GtkIMContextSimple. <compose> <a> <e> really can't work for XIM and LANG=C, since LANG=C tends to imply a character encoding of ASCII, and ASCII doesn't include <a><e>.
Sun's XmbLookupString() implementation for "C" locale is internally calling XLookupString with XComposeStatus structure. This is not functional with GTK+ apps, since the gdk x11 backend also calls XLookupString with XComposeStatus structure. Not giving XComposeStatus structure in gdkevent-x11.c seems to make XmbLookupString return ligature ae, at least. (Xlib's recommendation about XComposeStatus argument is that "a portable program must pass NULL for this argument".) BTW, the iconv module picked up in "C" locale does not handle 8bit characters. Some hack to use "ISO-8859-1" instead of "ASCII" may be needed, but I'm afraid this is not quite right in other platforms, so am lean to making it Sun's local patch. Owen, do you mind removing XComposeStatus and pass NULL when XLookupString is called in gdk x11 backend? I'd want to commit this only to the HEAD if it's okay for you.
I do have the same problem on a Sun/Solaris 2.8. It seems that on Sun, XLookupString always calls _XLookupString => _XTranslateKeySym => HandleComposeSequence, so it handles internally the compose sequence. This happens even when we pass NULL for the ComposeStatus. The problem is that both XLookupString and GtkIMContextSimple tries to handle the compose key, so when GtkIMContextSimple sees the GdkEvent, the keysym field contains the "composed letter" and the compose sequence doesn't match any predefined sequence. Therefore, GtkIMContextSimple simply discards the whole sequence and beeps. Owen, when you said that a compose sequence works for you with GtkIMContextSimple, do you mean that you did it on Linux ? If so, I think that XFree implementation of XLookupString doesn't handle the compose key itself and GtkIMContextSimple can do its work on the unprocessed sequence. Can X experts tell us what is the correct, official behaviour for XLookupString?
The behavior of XLookupString is very badly defined, especially when it comes to the XComposeStatus structure. One possibility is that we should just use XLookupKeysym and always store "" in GdkEventKey->string (programs are supposed to be using GtkIMContext now anyways)
Created attachment 11607 [details] [review] Patch removing the use of XLookupString
I've attached a fix that removes the use of XLookupString: * gdk/x11/gdkevents-x11.c (translate_key_event): Use gdk_keymap_translate_keyboard_state() rather than XLookupString() to get the keysymbol, since XLookupString can confuse the input method handling. (#93575) That part of the patch is fairly straightforward. However, it is likely to reveal a different bug with the handling of Caps_Lock without XKB that has been around for a long time, so I went ahead and fixed that as well: * gdk/x11/gdkkeys-x11.c: Rewrite the handling of key translation for the non-XKB case to properly handle Shift_Lock, Caps_Lock, Num_Lock according to the Xlib spec. (bug 67066) I'd appreciate as much testing as you can give this for this set of patches, espcially for the handling of Caps_Lock and Num_Lock without XKB.
I'll test the patch on the system without XKB. [BTW, what would happen if we build gtk+ on the system with XKB, and install it on the other system without XKB? No harm?]
GTK+ checks whether the server hsa the XKEYBOARD extension or not at run time so there is no problem swiching between servers with and without XKB. You can't compile GTK+ with Xkb support and then move the GTK+ binaries to a system that doesn't have Xkb support in the libraries ... but that should be fairly obvious :-)
Control chacters on gnome-terminal is lost with the patch in gdkevent-x11.c. By copy&paste, I could give control characters to the terminal, so it seems that key input itself is affected.
vte or libzvt? On my systems, <Control>a produces a keysym of a, not 0x1 == Control-A even when Xlib is doing the translating, so I'd think that gnome-terminal could handle it? Is this different for you? What does xev show?
Yeah - I'm using libzvt of libzvt-i18n:-) xev says, <Control>a produces state=0x4 and keysym=a keypress and keyrelease events. I'll look into from libzvt code. It might have a bad assumption w.r.t. control codes.
libzvt assumes event->length=1 and event->string=0x01 when Ctrl<a> is pressed. Instead, it should generate 0x01 string from event->keyval=0x61 and event->state=0x04. vte does this?
Ah yes, one of the main changes in this bug is that it eliminates event->string as anything useful. (The basic idea of this bug, after all, is that we can't call XLookupString in gdk_event_translate()) event->string was basically a leftover from GTK+-1.2. I suppose we should do some primitive filling in of event->string based on gdk_keyval_to_unicode() and special-cased handling of Control; we'd also have to use g_utf8_to_locale() since event->string is locale-dependent :-(. But in any case, ZVT should definitely be handling control characters itself, as should VTE, which seems to have the same bug. (I didn't do a make install with my patch, so I didn't test that out.) Note that VTE at least is buggy even if we fill in event->string because it thinks event->string is UTF-8. not encoding-of-the-locale.
Comitted with further changes to fill in event->string with a close approximation of what was there before (including the bizarre Xlib bugs for applying CONTROL to ascii characters. Did you know that <Ctrl>4 <Ctrl>\ <Ctrl>| all give the same character?) Also fixed docs to say that event->string is deprecated.
The fix made for this bug seems to have broken Caps Lock and Num Lock on Solaris -- see bug 115819 for more info. I poked around a bit using the debugger, but it was not obvious to me how to make this work, without reverting to using XLookupString().
*** Bug 73424 has been marked as a duplicate of this bug. ***