summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2010-01-01 23:03:42 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2010-01-01 23:03:42 (GMT)
commitaa4c765febd5c742dbc658574c6a06d4e94fdc59 (patch)
treefe2654888e979765a3b62105e2c73fdee4cf4442
parent5834454dfdb57f33bae61fb49206c33584e05ee6 (diff)
downloadtk-aa4c765febd5c742dbc658574c6a06d4e94fdc59.zip
tk-aa4c765febd5c742dbc658574c6a06d4e94fdc59.tar.gz
tk-aa4c765febd5c742dbc658574c6a06d4e94fdc59.tar.bz2
[Bug 1924761]: Consolidate calls to XFilterEvent to make input methods work.
-rw-r--r--ChangeLog25
-rw-r--r--generic/tkEvent.c78
-rw-r--r--generic/tkInt.h7
-rw-r--r--unix/tkUnixEvent.c32
4 files changed, 67 insertions, 75 deletions
diff --git a/ChangeLog b/ChangeLog
index ead5b95..dd9c9de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,28 @@
+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 Donal K. Fellows <dkf@users.sf.net>
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index 2a13871..d298f46 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.35.2.2 2009/01/11 19:29:42 georgeps Exp $
+ * RCS: @(#) $Id: tkEvent.c,v 1.35.2.3 2010/01/01 23:03:42 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 */
@@ -379,62 +378,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
@@ -1346,9 +1289,24 @@ 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
diff --git a/generic/tkInt.h b/generic/tkInt.h
index c929f05..9cec9ab 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.82.2.4 2009/06/27 19:53:16 nijtmans Exp $
+ * RCS: $Id: tkInt.h,v 1.82.2.5 2010/01/01 23:03:42 dkf Exp $
*/
#ifndef _TKINT
@@ -313,8 +313,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 bb66552..52e5673 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.27 2008/03/26 19:04:10 jenglish Exp $
+ * RCS: @(#) $Id: tkUnixEvent.c,v 1.27.2.1 2010/01/01 23:03:42 dkf Exp $
*/
#include "tkUnixInt.h"
@@ -279,21 +279,39 @@ TransferXEventsToTcl(
Display *display)
{
XEvent 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) {
XNextEvent(display, &event);
- if (event.type != KeyPress && event.type != KeyRelease) {
- if (XFilterEvent(&event, 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, TCL_QUEUE_TAIL);
}
}