To solve the problem that scim unexpectedly stops working

1 message Options
Embed this post
Permalink
Choe Hwanjin

To solve the problem that scim unexpectedly stops working

Reply Threaded More More options
Print post
Permalink
In brief, sometimes scim is blocked to receive new key events.
The detailed descriptions are here:
https://bugs.freedesktop.org/show_bug.cgi?id=7869

The problem happens when scim is working in XIM mode.
I think it is a bug of XIM client or XIM protocol itself.

Anyway, I found a way to work around the bug.
It is to reset all the sync flag and remove the queue, when the focus
is changing.

I made a patch, which is attached.
Please review it.

[scim-xim-block.patch]

Index: modules/FrontEnd/IMdkit/i18nPtHdr.c
===================================================================
--- modules/FrontEnd/IMdkit/i18nPtHdr.c (revision 56)
+++ modules/FrontEnd/IMdkit/i18nPtHdr.c (working copy)
@@ -53,6 +53,38 @@
 
 extern Xi18nClient *_Xi18nFindClient (Xi18n, CARD16);
 
+static void DiscardQueue (XIMS ims, CARD16 connect_id)
+{
+    Xi18n i18n_core = ims->protocol;
+    Xi18nClient *client = (Xi18nClient *) _Xi18nFindClient (i18n_core,
+                                                            connect_id);
+
+    if (client != NULL) {
+ client->sync = False;
+ while (client->pending != NULL) {
+    XIMPending* pending = client->pending;
+
+    client->pending = pending->next;
+
+    XFree(pending->p);
+    XFree(pending);
+ }
+    }
+}
+
+static void DiscardAllQueue(XIMS ims)
+{
+    Xi18n i18n_core = ims->protocol;
+    Xi18nClient* client = i18n_core->address.clients;
+
+    while (client != NULL) {
+ if (client->sync) {
+    DiscardQueue(ims, client->connect_id);
+ }
+ client = client->next;
+    }
+}
+
 static void GetProtocolVersion (CARD16 client_major,
                                 CARD16 client_minor,
                                 CARD16 *server_major,
@@ -866,6 +898,21 @@
     CARD16 connect_id = call_data->any.connect_id;
     CARD16 input_method_ID;
 
+    /* some buggy xim clients do not send XIM_SYNC_REPLY for synchronous
+     * events. In such case, xim server is waiting for XIM_SYNC_REPLY
+     * forever. So the xim server is blocked to waiting sync reply.
+     * It prevents further input.
+     * Usually it happens when a client calls XSetICFocus() with another ic
+     * before passing an event to XFilterEvent(), where the event is needed
+     * by the old focused ic to sync its state.
+     * To avoid such problem, remove the whole clients queue and set them
+     * as asynchronous.
+     *
+     * See:
+     * http://bugs.freedesktop.org/show_bug.cgi?id=7869
+     */
+    DiscardAllQueue(ims);
+
     setfocus = (IMChangeFocusStruct *) &call_data->changefocus;
 
     fm = FrameMgrInit (set_ic_focus_fr,
@@ -897,7 +944,18 @@
     IMChangeFocusStruct *unsetfocus;
     CARD16 connect_id = call_data->any.connect_id;
     CARD16 input_method_ID;
+    Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
 
+    /* some buggy clients unset focus ic before the ic answer the sync reply,
+     * so the xim server may be blocked to waiting sync reply. To avoid
+     * this problem, remove the client queue and set it asynchronous
+     *
+     * See: SetICFocusMessageProc
+     */
+    if (client != NULL && client->sync) {
+ DiscardQueue(ims, client->connect_id);
+    }
+
     unsetfocus = (IMChangeFocusStruct *) &call_data->changefocus;
 
     fm = FrameMgrInit (unset_ic_focus_fr,


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Scim-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/scim-devel