From 6130ca3ef131a8459a378ee9e3fa67484d6fe178 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 15 Dec 2016 16:07:06 +0000 Subject: Proposed fix for [7d967c68a09e07e355358af40f36dd5dd84c7022|7d967c68]: Tk applications segmentation fault when ibus-daemon IME is restarted --- generic/tkEvent.c | 13 ++++++++++++- generic/tkInt.h | 6 ++++++ generic/tkWindow.c | 11 +++++++++-- unix/tkUnixEvent.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) 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 5855b7c..85c5590 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 */ -- cgit v0.12