libX11/SOURCES/0005-Accept-anon-windows-in-XFilterEvent-to-update-XIM-st.patch

169 lines
5.4 KiB
Diff

From b3157722535db692d54b8fe7d26d07f94d49daf3 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 26 Apr 2024 01:29:26 +0900
Subject: [PATCH libX11 5/7] Accept anon windows in XFilterEvent to update XIM
state
When input focuses are switched quickly with shortcut keys in a Java
window, the focus is sometimes lost and the Window=0 is assigned in
XFilterEvent() but the XKeyEvent was forwarded by a XIM serer(IBus)
with XIM_FORWARD_EVENT -> XNextEvent() -> XFilterEvent() and the event
needs to be forwarded to the XIM XKeyEvent press and release filters
to update the XIM state with Window=0 likes _XimPendingFilter() and
_XimUnfabricateSerial().
Closes: #205, #206
Fixes: 024d229f ("ximcp: Unmark to fabricate key events with XKeyEvent serial")
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 5a1e62d77b65ba148b1c6d1d22a81dc2b07e7d9e)
---
modules/im/ximcp/imDefFlt.c | 34 ++++++++++++++++++++++++++++++----
src/FilterEv.c | 25 +++++++++++++++++++++++++
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/modules/im/ximcp/imDefFlt.c b/modules/im/ximcp/imDefFlt.c
index ad8a272b..76d63e88 100644
--- a/modules/im/ximcp/imDefFlt.c
+++ b/modules/im/ximcp/imDefFlt.c
@@ -138,7 +138,8 @@ _XimPendingFilter(
static Bool
_XimProtoKeypressFilter(
Xic ic,
- XKeyEvent *ev)
+ XKeyEvent *ev,
+ Window w)
{
Xim im = (Xim)ic->core.im;
@@ -147,6 +148,9 @@ _XimProtoKeypressFilter(
_XimUnfabricateSerial(im, ev);
return NOTFILTERD;
}
+ /* w=0 is used for _XimIsFabricatedSerial() only */
+ if (!w)
+ return NOTFILTERD;
if (IS_NEGLECT_EVENT(ic, KeyPressMask))
return FILTERD;
@@ -193,13 +197,14 @@ _XimFilterKeypress(
XEvent *ev,
XPointer client_data)
{
- return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev );
+ return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev, w);
}
static Bool
_XimProtoKeyreleaseFilter(
Xic ic,
- XKeyEvent *ev)
+ XKeyEvent *ev,
+ Window w)
{
Xim im = (Xim)ic->core.im;
@@ -208,6 +213,9 @@ _XimProtoKeyreleaseFilter(
_XimUnfabricateSerial(im, ev);
return NOTFILTERD;
}
+ /* w=0 is used for _XimIsFabricatedSerial() only */
+ if (!w)
+ return NOTFILTERD;
if (IS_NEGLECT_EVENT(ic, KeyReleaseMask))
return FILTERD;
@@ -254,7 +262,7 @@ _XimFilterKeyrelease(
XEvent *ev,
XPointer client_data)
{
- return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev);
+ return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev, w);
}
static void
@@ -263,6 +271,11 @@ _XimRegisterKeyPressFilter(
{
if (ic->core.focus_window) {
if (!(ic->private.proto.registed_filter_event & KEYPRESS_MASK)) {
+ _XRegisterFilterByType (ic->core.im->core.display,
+ 0,
+ KeyPress, KeyPress,
+ _XimFilterKeypress,
+ (XPointer)ic);
_XRegisterFilterByType (ic->core.im->core.display,
ic->core.focus_window,
KeyPress, KeyPress,
@@ -280,6 +293,11 @@ _XimRegisterKeyReleaseFilter(
{
if (ic->core.focus_window) {
if (!(ic->private.proto.registed_filter_event & KEYRELEASE_MASK)) {
+ _XRegisterFilterByType (ic->core.im->core.display,
+ 0,
+ KeyRelease, KeyRelease,
+ _XimFilterKeyrelease,
+ (XPointer)ic);
_XRegisterFilterByType (ic->core.im->core.display,
ic->core.focus_window,
KeyRelease, KeyRelease,
@@ -301,6 +319,10 @@ _XimUnregisterKeyPressFilter(
ic->core.focus_window,
_XimFilterKeypress,
(XPointer)ic);
+ _XUnregisterFilter (ic->core.im->core.display,
+ 0,
+ _XimFilterKeypress,
+ (XPointer)ic);
ic->private.proto.registed_filter_event &= ~KEYPRESS_MASK;
}
}
@@ -317,6 +339,10 @@ _XimUnregisterKeyReleaseFilter(
ic->core.focus_window,
_XimFilterKeyrelease,
(XPointer)ic);
+ _XUnregisterFilter (ic->core.im->core.display,
+ 0,
+ _XimFilterKeyrelease,
+ (XPointer)ic);
ic->private.proto.registed_filter_event &= ~KEYRELEASE_MASK;
}
}
diff --git a/src/FilterEv.c b/src/FilterEv.c
index 0a48e548..07845bcc 100644
--- a/src/FilterEv.c
+++ b/src/FilterEv.c
@@ -100,6 +100,31 @@ XFilterEvent(
}
}
}
+ for (p = ev->xany.display->im_filters; p != NULL; p = p->next) {
+ /* Java sometimes calls XFilterEvent() with window=0 and ev come from
+ * XNextEvent() when users type some keys quickly and switch multiple
+ * input focuses in a Java window with the keys.
+ * But XKeyEvent filters need to receive the event with window=0 for
+ * _XimPendingFilter() and _XimUnfabricateSerial() to clear the
+ * fowarded XKeyEvent with XIM_FORWARD_EVENT.
+ *
+ * The case of p->window == 0 is checkekd after all cases of p->window
+ * != 0 are checked because all input contexts share
+ * Display->im_filters but each input context has
+ * Xic->private.proto.registed_filter_event for the filters
+ * and same p->filter could be registerd to Display->im_filters twice
+ * with different p->window.
+ */
+ if (p->window == 0 && window == 0) {
+ if ((mask & p->event_mask) ||
+ (ev->type >= p->start_type && ev->type <= p->end_type)) {
+ UnlockDisplay(ev->xany.display);
+ ret = (*(p->filter))(ev->xany.display, p->window, ev,
+ p->client_data);
+ return(ret);
+ }
+ }
+ }
UnlockDisplay(ev->xany.display);
#endif
return(False);
--
2.47.1