winex11.drv: Connect to XIM server dynamically. [take 3]

Kusanagi Kouichi slash at ma.neweb.ne.jp
Fri Apr 4 06:44:36 CDT 2008


Don't store a pointer to an internal field of a structure.
XRegisterIMInstantiateCallback goes back to xim.c. It should be called
after XSetLocaleModifiers.
---
 dlls/winex11.drv/window.c      |   15 +++++--
 dlls/winex11.drv/x11drv.h      |   11 +++--
 dlls/winex11.drv/x11drv_main.c |    5 +-
 dlls/winex11.drv/xim.c         |   86 +++++++++++++++++++++++++++++++++-------
 4 files changed, 90 insertions(+), 27 deletions(-)

diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index ffeed8e..6323622 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1126,7 +1126,6 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
 {
     int cx, cy, mask;
     XSetWindowAttributes attr;
-    XIM xim;
     WCHAR text[1024];
     HRGN hrgn;
 
@@ -1166,9 +1165,6 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
         return 0;
     }
 
-    xim = x11drv_thread_data()->xim;
-    if (xim) data->xic = X11DRV_CreateIC( xim, display, data->whole_window );
-
     set_initial_wm_hints( display, data );
     X11DRV_set_wm_hints( display, data );
 
@@ -1487,9 +1483,18 @@ Window X11DRV_get_client_window( HWND hwnd )
 XIC X11DRV_get_ic( HWND hwnd )
 {
     struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
+    XIM xim;
 
     if (!data) return 0;
-    return data->xic;
+
+    if (data->xic)
+        return data->xic;
+
+    xim = x11drv_thread_data()->xim;
+    if (!xim)
+        return NULL;
+
+    return X11DRV_CreateIC(xim, data);
 }
 
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index ab5ff76..2ff0c0f 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -273,11 +273,6 @@ extern void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev);
 extern Drawable get_glxdrawable(X11DRV_PDEVICE *physDev);
 extern BOOL destroy_glxpixmap(Display *display, XID glxpixmap);
 
-/* XIM support */
-extern XIC X11DRV_CreateIC(XIM xim, Display *display, Window win);
-extern XIM X11DRV_SetupXIM(Display *display, const char *input_style);
-extern void X11DRV_XIMLookupChars( const char *str, DWORD count );
-
 extern void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event );
 extern void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event );
 extern void X11DRV_XDND_DropEvent( HWND hWnd, XClientMessageEvent *event );
@@ -690,6 +685,12 @@ extern BOOL X11DRV_is_window_rect_mapped( const RECT *rect );
 extern XIC X11DRV_get_ic( HWND hwnd );
 extern BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig );
 
+/* XIM support */
+extern char input_style[];
+extern XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data);
+extern BOOL X11DRV_SetupXIM(struct x11drv_thread_data *data);
+extern void X11DRV_XIMLookupChars( const char *str, DWORD count );
+
 extern int pixelformat_from_fbconfig_id( XID fbconfig_id );
 extern XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id );
 extern void mark_drawable_dirty( Drawable old, Drawable new );
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index d445e64..83c7a84 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -100,7 +100,7 @@ static int err_callback_result;              /* error callback result */
 static unsigned long err_serial;             /* serial number of first request */
 static int (*old_error_handler)( Display *, XErrorEvent * );
 static int use_xim = 1;
-static char input_style[20];
+char input_style[20];
 
 #define IS_OPTION_TRUE(ch) \
     ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
@@ -651,7 +651,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
     wine_tsx11_unlock();
 
-    if (use_xim && !(data->xim = X11DRV_SetupXIM( data->display, input_style )))
+    data->xim = NULL;
+    if (use_xim && !X11DRV_SetupXIM(data))
         WARN("Input Method is not available\n");
 
     set_queue_display_fd( data->display );
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c
index ad28bc5..921f7e8 100644
--- a/dlls/winex11.drv/xim.c
+++ b/dlls/winex11.drv/xim.c
@@ -394,15 +394,29 @@ void X11DRV_ForceXIMReset(HWND hwnd)
     }
 }
 
+static void X11DRV_OpenIM(Display *display, XPointer p, XPointer data);
+
+static void X11DRV_DestroyIM(XIM xim, XPointer p, XPointer data)
+{
+    TRACE("xim = %p, p = %p\n", xim, p);
+    ((struct x11drv_thread_data *)p)->xim = NULL;
+    ximStyle = 0;
+    wine_tsx11_lock();
+    XRegisterIMInstantiateCallback(XDisplayOfIM(xim), NULL, NULL, NULL,
+                                   X11DRV_OpenIM, p);
+    wine_tsx11_unlock();
+}
+
 /***********************************************************************
 *           X11DRV Ime creation
 */
-XIM X11DRV_SetupXIM(Display *display, const char *input_style)
+static void X11DRV_OpenIM(Display *display, XPointer p, XPointer data)
 {
     XIMStyle ximStyleRequest, ximStyleCallback, ximStyleNone;
     XIMStyles *ximStyles = NULL;
     INT i;
     XIM xim;
+    XIMCallback destroy;
 
     ximStyleRequest = STYLE_CALLBACK;
 
@@ -415,17 +429,6 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
 
     wine_tsx11_lock();
 
-    if(!XSupportsLocale())
-    {
-        WARN("X does not support locale.\n");
-        goto err;
-    }
-    if(XSetLocaleModifiers("") == NULL)
-    {
-        WARN("Could not set locale modifiers.\n");
-        goto err;
-    }
-
     xim = XOpenIM(display, NULL, NULL, NULL);
     if (xim == NULL)
     {
@@ -433,6 +436,14 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
         goto err;
     }
 
+    destroy.client_data = p;
+    destroy.callback = X11DRV_DestroyIM;
+    if (XSetIMValues(xim, XNDestroyCallback, &destroy, NULL))
+    {
+        WARN("Could not set destroy callback.\n");
+    }
+
+    TRACE("xim = %p\n", xim);
     TRACE("X display of IM = %p\n", XDisplayOfIM(xim));
     TRACE("Using %s locale of Input Method\n", XLocaleOfIM(xim));
 
@@ -440,6 +451,8 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
     if (ximStyles == 0)
     {
         WARN("Could not find supported input style.\n");
+        XCloseIM(xim);
+        goto err;
     }
     else
     {
@@ -499,6 +512,8 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
 
     }
 
+    ((struct x11drv_thread_data *)p)->xim = xim;
+    XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL, X11DRV_OpenIM, p);
     wine_tsx11_unlock();
 
     if(!hImmDll)
@@ -513,26 +528,60 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
         }
     }
 
-    return xim;
+    return;
 
 err:
     wine_tsx11_unlock();
-    return NULL;
+    return;
 }
 
+BOOL X11DRV_SetupXIM(struct x11drv_thread_data *data)
+{
+    BOOL ret = FALSE;
+
+    wine_tsx11_lock();
+
+    if(!XSupportsLocale())
+    {
+        WARN("X does not support locale.\n");
+        goto err;
+    }
+
+    if(XSetLocaleModifiers("") == NULL)
+    {
+        WARN("Could not set locale modifiers.\n");
+        goto err;
+    }
+
+    ret = XRegisterIMInstantiateCallback(data->display, NULL, NULL, NULL,
+                                         X11DRV_OpenIM, (XPointer)data);
+err:
+    wine_tsx11_unlock();
+    return ret;
+}
+
+static BOOL X11DRV_DestroyIC(XIC xic, XPointer p, XPointer data)
+{
+    TRACE("xic = %p, p = %p\n", xic, p);
+    ((struct x11drv_win_data *)p)->xic = NULL;
+    return TRUE;
+}
 
-XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
+XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
 {
     XPoint spot = {0};
     XVaNestedList preedit = NULL;
     XVaNestedList status = NULL;
     XIC xic;
+    XICCallback destroy = {(XPointer)data, X11DRV_DestroyIC};
     XIMCallback P_StartCB;
     XIMCallback P_DoneCB;
     XIMCallback P_DrawCB;
     XIMCallback P_CaretCB;
     LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
+    Window win = data->whole_window;
 
+    TRACE("xim = %p\n", xim);
     wine_tsx11_lock();
 
     /* use complex and slow XIC initialization method only for CJK */
@@ -544,8 +593,10 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
                         XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
                         XNClientWindow, win,
                         XNFocusWindow, win,
+                        XNDestroyCallback, &destroy,
                         NULL);
         wine_tsx11_unlock();
+        data->xic = xic;
         return xic;
     }
 
@@ -597,6 +648,7 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNStatusAttributes, status,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
      }
     else if (preedit != NULL)
@@ -606,6 +658,7 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNPreeditAttributes, preedit,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
     }
     else if (status != NULL)
@@ -615,6 +668,7 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNStatusAttributes, status,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
     }
     else
@@ -623,10 +677,12 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNInputStyle, ximStyle,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
     }
 
     TRACE("xic = %p\n", xic);
+    data->xic = xic;
 
     if (preedit != NULL)
         XFree(preedit);
-- 
1.5.4.5




More information about the wine-patches mailing list