File libX11-commit-first-info-in-XimCommitInfo.patch of Package libX11

From 041b5291f0956c5cda5054be2981c0d02b009a4c Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Wed, 31 Jan 2024 20:27:57 +0900
Subject: [PATCH] imDefLkup: Commit first info in XimCommitInfo

Xic.private.proto.commit_info can receive multiple XimCommitInfo
when typing keys very quickly like an bar code scanner (or evemu-play)
and the first info in XimCommitInfo should be committed to keep
the typing key order.

--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -640,22 +640,48 @@
 }
 
 static void
-_XimUnregCommitInfo(
-    Xic			ic)
+_XimUnregRealCommitInfo(
+    Xic                        ic,
+    Bool               reverse)
 {
     XimCommitInfo	info;
+    XimCommitInfo       prev_info = NULL;
 
-    if (!(info = ic->private.proto.commit_info))
+    info = ic->private.proto.commit_info;
+    while (reverse && info) {
+       if (!info->next)
+           break;
+       prev_info = info;
+       info = info->next;
+    }
+    if (!info)
 	return;
 
 
     Xfree(info->string);
     Xfree(info->keysym);
-    ic->private.proto.commit_info = info->next;
+    if (prev_info)
+       prev_info->next = info->next;
+    else
+       ic->private.proto.commit_info = info->next;
     Xfree(info);
     return;
 }
 
+static void
+_XimUnregCommitInfo(
+    Xic                        ic)
+{
+    _XimUnregRealCommitInfo(ic, False);
+}
+
+static void
+_XimUnregFirstCommitInfo(
+    Xic                        ic)
+{
+    _XimUnregRealCommitInfo(ic, True);
+}
+
 void
 _XimFreeCommitInfo(
     Xic			ic)
@@ -665,6 +691,19 @@
     return;
 }
 
+static XimCommitInfo
+_XimFirstCommitInfo(
+    Xic                        ic)
+{
+    XimCommitInfo info = ic->private.proto.commit_info;
+    while (info) {
+       if (!info->next)
+           break;
+       info = info->next;
+    }
+    return info;
+}
+
 static Bool
 _XimProcKeySym(
     Xic			  ic,
@@ -1059,7 +1098,7 @@
 	state = &tmp_state;
 
     if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */
-	if (!(info = ic->private.proto.commit_info)) {
+        if (!(info = _XimFirstCommitInfo(ic))) {
 	    *state = XLookupNone;
 	    return 0;
 	}
@@ -1075,7 +1114,7 @@
 	    else
 		*state = XLookupKeySym;
 	}
-	_XimUnregCommitInfo(ic);
+        _XimUnregFirstCommitInfo(ic);
 
     } else  if (ev->type == KeyPress) {
 	ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL);
@@ -1122,7 +1161,7 @@
 	state = &tmp_state;
 
     if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
-	if (!(info = ic->private.proto.commit_info)) {
+        if (!(info = _XimFirstCommitInfo(ic))) {
            *state = XLookupNone;
 	    return 0;
 	}
@@ -1138,7 +1177,7 @@
 	    else
 		*state = XLookupKeySym;
 	}
-	_XimUnregCommitInfo(ic);
+        _XimUnregFirstCommitInfo(ic);
 
     } else if (ev->type == KeyPress) {
 	ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL);
@@ -1185,7 +1224,7 @@
 	state = &tmp_state;
 
     if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
-	if (!(info = ic->private.proto.commit_info)) {
+        if (!(info = _XimFirstCommitInfo(ic))) {
            *state = XLookupNone;
 	    return 0;
 	}
@@ -1201,7 +1240,7 @@
 	    else
 		*state = XLookupKeySym;
 	}
-	_XimUnregCommitInfo(ic);
+        _XimUnregFirstCommitInfo(ic);
 
     } else if (ev->type == KeyPress) {
 	ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL);
openSUSE Build Service is sponsored by