summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2010-01-01 22:50:26 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2010-01-01 22:50:26 (GMT)
commit1a86dacbaaea58d12f5c210efdd06d8974adc362 (patch)
tree2acdd461994a57bdc0d886e6e24d27cc14d317af
parent3147e53de56d78b75db674135ff4782d49467c73 (diff)
downloadtk-1a86dacbaaea58d12f5c210efdd06d8974adc362.zip
tk-1a86dacbaaea58d12f5c210efdd06d8974adc362.tar.gz
tk-1a86dacbaaea58d12f5c210efdd06d8974adc362.tar.bz2
[Bug 1924761]: Consolidate calls to XFilterEvent to make input methods work.
-rw-r--r--ChangeLog30
-rw-r--r--generic/tkEvent.c90
-rw-r--r--generic/tkInt.h7
-rw-r--r--unix/tkUnixEvent.c32
4 files changed, 75 insertions, 84 deletions
diff --git a/ChangeLog b/ChangeLog
index 50a4bdd..0bcdd4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,19 +1,33 @@
+2010-01-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixEvent.c (TransferXEventsToTcl): [Bug 1924761]: Move the
+ * generic/tkEvent.c (Tk_HandleEvent): passing of key events to
+ XFilterEvent to the low level point where all other events are
+ handled, where it should have been all along. This makes more input
+ methods work, stops [event generate] from interfering with input
+ methods, and allows the simplification of tkEvent.c by removing half
+ of InvokeInputMethods and allowing the rest - which was not full input
+ method handling - to be rolled back into Tk_HandleEvent. Introduces a
+ small potential bug when a focus change and input method handling are
+ too close together in the Tk event queue, but that should be less
+ deadly to usability than the previous problems where input methods
+ could fail completely or reorder key presses...
+
2009-12-30 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tkMenu.c: Torn off menu items are only activated over
- * tests/menu.tcl: a limited region of the window. Fixed to make
- the whole width of a menu item activate the entry. [Patch 2879789]
+ * generic/tkMenu.c: [Patch 2879789]: Torn off menu items are only
+ * tests/menu.tcl: activated over a limited region of the window.
+ Fixed to make the whole width of a menu item activate the entry.
2009-12-27 Pat Thoyts <patthoyts@users.sourceforge.net>
- * win/tkWinMenu.c: Highlight for cascade items in torn-off menus
- is incorrect on Windows. Applied patch from [Bug 2879927].
+ * win/tkWinMenu.c: [Bug 2879927]: Highlight for cascade items in
+ torn-off menus is incorrect on Windows.
2009-12-25 Joe English <jenglish@users.sourceforge.net>
- * library/ttk/utils.tcl, library/notebook.tcl:
- Reworked ActivateTab focus selection logic ([Bug 2917688],
- also fixes [Bug 2546779]).
+ * library/ttk/utils.tcl, library/notebook.tcl: [Bugs 2917688,2546779]:
+ Reworked ActivateTab focus selection logic.
2009-12-25 Donal K. Fellows <dkf@users.sf.net>
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index bcadee5..36f1c3a 100644
--- a/generic/tkEvent.c
+++ b/generic/tkEvent.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkEvent.c,v 1.39 2009/01/11 19:05:17 georgeps Exp $
+ * RCS: @(#) $Id: tkEvent.c,v 1.40 2010/01/01 22:50:27 dkf Exp $
*/
#include "tkInt.h"
@@ -212,7 +212,6 @@ static int TkXErrorHandler(ClientData clientData,
static void UpdateButtonEventState(XEvent *eventPtr);
static int WindowEventProc(Tcl_Event *evPtr, int flags);
#ifdef TK_USE_INPUT_METHODS
-static int InvokeInputMethods(TkWindow *winPtr, XEvent *eventPtr);
static void CreateXIC(TkWindow *winPtr);
#endif /* TK_USE_INPUT_METHODS */
@@ -322,7 +321,7 @@ InvokeMouseHandlers(
*----------------------------------------------------------------------
*/
-#if defined(TK_USE_INPUT_METHODS)
+#ifdef TK_USE_INPUT_METHODS
static void
CreateXIC(
TkWindow *winPtr)
@@ -373,62 +372,6 @@ CreateXIC(
/*
*----------------------------------------------------------------------
*
- * InvokeInputMethods --
- *
- * Pass the event to the input method(s), if there are any, and discard
- * the event if the input method(s) insist. Create the input context for
- * the window if it hasn't already been done (XFilterEvent needs this
- * context).
- *
- * When the event is a FocusIn event, set the input context focus to the
- * receiving window.
- *
- * Results:
- * 1 when we are done with the event.
- * 0 when the event can be processed further.
- *
- * Side effects:
- * Input contexts/methods may be created.
- *
- *----------------------------------------------------------------------
- */
-
-#ifdef TK_USE_INPUT_METHODS
-static int
-InvokeInputMethods(
- TkWindow *winPtr,
- XEvent *eventPtr)
-{
- TkDisplay *dispPtr = winPtr->dispPtr;
-
- if ((dispPtr->flags & TK_DISPLAY_USE_IM)) {
- if (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) {
- winPtr->flags |= TK_CHECKED_IC;
- if (dispPtr->inputMethod != NULL) {
- CreateXIC(winPtr);
- }
- }
- switch (eventPtr->type) {
- case FocusIn:
- if (winPtr->inputContext != NULL) {
- XSetICFocus(winPtr->inputContext);
- }
- break;
- case KeyPress:
- case KeyRelease:
- if (XFilterEvent(eventPtr, None)) {
- return 1;
- }
- break;
- }
- }
- return 0;
-}
-#endif /*TK_USE_INPUT_METHODS*/
-
-/*
- *----------------------------------------------------------------------
- *
* GetTkWindowFromXEvent --
*
* Attempt to find which TkWindow is associated with an event. If it
@@ -1276,7 +1219,7 @@ Tk_HandleEvent(
unsigned long mask;
InProgress ip;
Tcl_Interp *interp = NULL;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr =
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
UpdateButtonEventState(eventPtr);
@@ -1330,7 +1273,7 @@ Tk_HandleEvent(
* code.
*/
- Tcl_Preserve((ClientData) interp);
+ Tcl_Preserve(interp);
result = ((InvokeFocusHandlers(&winPtr, mask, eventPtr))
|| (InvokeMouseHandlers(winPtr, mask, eventPtr)));
@@ -1340,11 +1283,26 @@ Tk_HandleEvent(
}
}
+ /*
+ * Create the input context for the window if it hasn't already been done
+ * (XFilterEvent needs this context). When the event is a FocusIn event,
+ * set the input context focus to the receiving window. This code is only
+ * ever active for X11.
+ */
+
#ifdef TK_USE_INPUT_METHODS
- if (InvokeInputMethods(winPtr, eventPtr)) {
- goto releaseInterpreter;
+ if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)) {
+ if (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) {
+ winPtr->flags |= TK_CHECKED_IC;
+ if (winPtr->dispPtr->inputMethod != NULL) {
+ CreateXIC(winPtr);
+ }
+ }
+ if (eventPtr->type == FocusIn && winPtr->inputContext != NULL) {
+ XSetICFocus(winPtr->inputContext);
+ }
}
-#endif
+#endif /*TK_USE_INPUT_METHODS*/
/*
* For events where it hasn't already been done, update the current time
@@ -1375,7 +1333,7 @@ Tk_HandleEvent(
Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS")) {
TkWmProtocolEventProc(winPtr, eventPtr);
} else {
- InvokeClientMessageHandlers(tsdPtr, (Tk_Window)winPtr,
+ InvokeClientMessageHandlers(tsdPtr, (Tk_Window) winPtr,
eventPtr);
}
}
@@ -1417,7 +1375,7 @@ Tk_HandleEvent(
releaseInterpreter:
if (interp != NULL) {
- Tcl_Release((ClientData) interp);
+ Tcl_Release(interp);
}
/*
diff --git a/generic/tkInt.h b/generic/tkInt.h
index ee9441e..a9062ec 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: $Id: tkInt.h,v 1.115 2009/12/15 18:12:07 dgp Exp $
+ * RCS: $Id: tkInt.h,v 1.116 2010/01/01 22:50:27 dkf Exp $
*/
#ifndef _TKINT
@@ -314,8 +314,9 @@ typedef struct TkDisplay {
* multiple applications on the display have
* the focus, this will refer to the innermost
* window in the innermost application. This
- * information isn't used under Unix or
- * Windows, but it's needed on the Mac. */
+ * information isn't used on Windows, but it's
+ * needed on the Mac, and also on X11 when XIM
+ * processing is being done. */
/*
* Information used by tkGC.c only:
diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c
index d572d42..39e3e5e 100644
--- a/unix/tkUnixEvent.c
+++ b/unix/tkUnixEvent.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixEvent.c,v 1.32 2009/12/16 21:12:25 nijtmans Exp $
+ * RCS: @(#) $Id: tkUnixEvent.c,v 1.33 2010/01/01 22:50:27 dkf Exp $
*/
#include "tkUnixInt.h"
@@ -282,12 +282,17 @@ TransferXEventsToTcl(
xGenericEvent xge;
#endif
} event;
+ Window w;
/*
* Transfer events from the X event queue to the Tk event queue after XIM
- * event filtering. KeyPress and KeyRelease events are filtered in
- * Tk_HandleEvent instead of here, so that Tk's focus management code can
- * redirect them.
+ * event filtering. KeyPress and KeyRelease events need special treatment
+ * so that they get directed according to Tk's focus rules during XIM
+ * handling. Theoretically they can go to the wrong place still (if
+ * there's a focus change in the queue) but if we push the handling off
+ * until Tk_HandleEvent then many input methods actually cease to work
+ * correctly. Most of the time, Tk processes its event queue fast enough
+ * for this to not be an issue anyway. [Bug 1924761]
*/
while (QLength(display) > 0) {
@@ -298,11 +303,24 @@ TransferXEventsToTcl(
event.xge.extension, event.xge.evtype);
}
#endif
- if (event.x.type != KeyPress && event.x.type != KeyRelease) {
- if (XFilterEvent(&event.x, None)) {
- continue;
+ w = None;
+ if (event.x.type == KeyPress || event.x.type == KeyRelease) {
+ TkDisplay *dispPtr;
+
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
+ if (dispPtr == NULL) {
+ break;
+ } else if (dispPtr->display == event.x.xany.display) {
+ if (dispPtr->focusPtr != NULL) {
+ w = dispPtr->focusPtr->window;
+ }
+ break;
+ }
}
}
+ if (XFilterEvent(&event.x, w)) {
+ continue;
+ }
Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);
}
}