diff options
-rw-r--r-- | generic/tk.h | 3 | ||||
-rw-r--r-- | generic/tkEvent.c | 13 | ||||
-rw-r--r-- | generic/tkInt.h | 6 | ||||
-rw-r--r-- | generic/tkWindow.c | 11 | ||||
-rw-r--r-- | unix/tkUnixEvent.c | 46 |
5 files changed, 76 insertions, 3 deletions
diff --git a/generic/tk.h b/generic/tk.h index a0fbba9..1d070d3 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -817,6 +817,9 @@ typedef struct Tk_FakeWin { int minReqWidth; int minReqHeight; char *dummy20; /* geometryMaster */ +#ifdef TK_USE_INPUT_METHODS + int dummy21; +#endif /* TK_USE_INPUT_METHODS */ } Tk_FakeWin; /* diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 95aeda1..d058e7c 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -356,6 +356,7 @@ CreateXIC( /* XCreateIC failed. */ return; } + winPtr->ximGeneration = dispPtr->ximGeneration; /* * Adjust the window's event mask if the IM requires it. @@ -1288,6 +1289,14 @@ Tk_HandleEvent( */ #ifdef TK_USE_INPUT_METHODS + /* + * If the XIC has been invalidated, it must be recreated. + */ + if (winPtr->dispPtr->ximGeneration != winPtr->ximGeneration) { + winPtr->flags &= ~TK_CHECKED_IC; + winPtr->inputContext = NULL; + } + if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)) { if (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) { winPtr->flags |= TK_CHECKED_IC; @@ -1295,7 +1304,9 @@ Tk_HandleEvent( CreateXIC(winPtr); } } - if (eventPtr->type == FocusIn && winPtr->inputContext != NULL) { + if ((eventPtr->type == FocusIn) && + (winPtr->dispPtr->inputMethod != NULL) && + (winPtr->inputContext != NULL)) { XSetICFocus(winPtr->inputContext); } } diff --git a/generic/tkInt.h b/generic/tkInt.h index 1615a81..f00d833 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -508,6 +508,9 @@ typedef struct TkDisplay { int iconDataSize; /* Size of default iconphoto image data. */ unsigned char *iconDataPtr; /* Default iconphoto image data, if set. */ +#ifdef TK_USE_INPUT_METHODS + int ximGeneration; /* Used to invalidate XIC */ +#endif /* TK_USE_INPUT_METHODS */ } TkDisplay; /* @@ -809,6 +812,9 @@ typedef struct TkWindow { int minReqWidth; /* Minimum requested width. */ int minReqHeight; /* Minimum requested height. */ char *geometryMaster; +#ifdef TK_USE_INPUT_METHODS + int ximGeneration; /* Used to invalidate XIC */ +#endif /* TK_USE_INPUT_METHODS */ } TkWindow; /* diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 3b3b025..9a31365 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -355,6 +355,9 @@ CreateTopLevelWindow( * Set the flags specified in the call. */ +#ifdef TK_USE_INPUT_METHODS + winPtr->ximGeneration = 0; +#endif /*TK_USE_INPUT_METHODS*/ winPtr->flags |= flags; /* @@ -472,6 +475,9 @@ GetScreen( dispPtr->cursorFont = None; dispPtr->warpWindow = NULL; dispPtr->multipleAtom = None; +#ifdef TK_USE_INPUT_METHODS + dispPtr->ximGeneration = 0; +#endif /*TK_USE_INPUT_METHODS*/ /* * By default we do want to collapse motion events in @@ -1442,10 +1448,11 @@ Tk_DestroyWindow( UnlinkWindow(winPtr); TkEventDeadWindow(winPtr); #ifdef TK_USE_INPUT_METHODS - if (winPtr->inputContext != NULL) { + if (winPtr->inputContext != NULL && + winPtr->ximGeneration == winPtr->dispPtr->ximGeneration) { XDestroyIC(winPtr->inputContext); - winPtr->inputContext = NULL; } + winPtr->inputContext = NULL; #endif /* TK_USE_INPUT_METHODS */ if (winPtr->tagPtr != NULL) { TkFreeBindingTags(winPtr); diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c index f3beb16..111d430 100644 --- a/unix/tkUnixEvent.c +++ b/unix/tkUnixEvent.c @@ -38,6 +38,8 @@ static void DisplayFileProc(ClientData clientData, int flags); static void DisplaySetupProc(ClientData clientData, int flags); static void TransferXEventsToTcl(Display *display); #ifdef TK_USE_INPUT_METHODS +static void InstantiateIMCallback(Display *, XPointer client_data, XPointer call_data); +static void DestroyIMCallback(XIM im, XPointer client_data, XPointer call_data); static void OpenIM(TkDisplay *dispPtr); #endif @@ -179,6 +181,8 @@ TkpOpenDisplay( dispPtr->flags |= use_xkb; #ifdef TK_USE_INPUT_METHODS OpenIM(dispPtr); + XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, + InstantiateIMCallback, (XPointer) dispPtr); #endif Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE, DisplayFileProc, dispPtr); @@ -664,6 +668,35 @@ TkpSync( } #ifdef TK_USE_INPUT_METHODS +static void +InstantiateIMCallback( + Display *display, + XPointer client_data, + XPointer call_data) +{ + TkDisplay *dispPtr; + + dispPtr = (TkDisplay *) client_data; + OpenIM(dispPtr); + XUnregisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, + InstantiateIMCallback, (XPointer) dispPtr); +} + +static void +DestroyIMCallback( + XIM im, + XPointer client_data, + XPointer call_data) +{ + TkDisplay *dispPtr; + + dispPtr = (TkDisplay *) client_data; + dispPtr->inputMethod = NULL; + ++dispPtr->ximGeneration; + XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, + InstantiateIMCallback, (XPointer) dispPtr); +} + /* *-------------------------------------------------------------- * @@ -693,11 +726,23 @@ OpenIM( return; } + ++dispPtr->ximGeneration; dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL); if (dispPtr->inputMethod == NULL) { return; } + /* Require X11R6 */ + { + XIMCallback destroy_cb; + + destroy_cb.callback = DestroyIMCallback; + destroy_cb.client_data = (XPointer) dispPtr; + if (XSetIMValues(dispPtr->inputMethod, XNDestroyCallback, + &destroy_cb, NULL)) + goto error; + } + if ((XGetIMValues(dispPtr->inputMethod, XNQueryInputStyle, &stylePtr, NULL) != NULL) || (stylePtr == NULL)) { goto error; @@ -744,6 +789,7 @@ error: if (dispPtr->inputMethod) { XCloseIM(dispPtr->inputMethod); dispPtr->inputMethod = NULL; + ++dispPtr->ximGeneration; } } #endif /* TK_USE_INPUT_METHODS */ |