winex11.drv: Connect to XIM server dynamically.

Kusanagi Kouichi slash at ma.neweb.ne.jp
Sat Mar 29 01:23:34 CDT 2008


If I want to use XIM, I must start XIM server before wine.
Furthermore, if XIM server stops, wine can't use XIM again
even if XIM server restarts.
---
 dlls/winex11.drv/window.c      |   18 ++-
 dlls/winex11.drv/x11drv.h      |    5 +-
 dlls/winex11.drv/x11drv_main.c |    5 +-
 dlls/winex11.drv/xim.c         |  267 ++++++++++++++++++++++++---------------
 4 files changed, 182 insertions(+), 113 deletions(-)

diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index ffeed8e..1598e75 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,19 @@ Window X11DRV_get_client_window( HWND hwnd )
 XIC X11DRV_get_ic( HWND hwnd )
 {
     struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
+    struct x11drv_thread_data *tdata;
+
+    if (!data)
+        return NULL;
+
+    if (data->xic)
+        return data->xic;
+
+    tdata = x11drv_thread_data();
+    if (!tdata->xim)
+        return NULL;
 
-    if (!data) return 0;
-    return data->xic;
+    return X11DRV_CreateIC(tdata->xim, data->whole_window, &data->xic);
 }
 
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 52670e8..427e36c 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -274,8 +274,9 @@ 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 char input_style[];
+extern XIC X11DRV_CreateIC(XIM xim, Window win, XIC *xic);
+extern BOOL X11DRV_SetupXIM(Display *display, XIM *xim);
 extern void X11DRV_XIMLookupChars( const char *str, DWORD count );
 
 extern void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event );
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index d445e64..f080f85 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->display, &data->xim ))
         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..edca47c 100644
--- a/dlls/winex11.drv/xim.c
+++ b/dlls/winex11.drv/xim.c
@@ -52,8 +52,7 @@ typedef struct tagInputContextData
 } InputContextData;
 
 static HIMC root_context;
-static XIMStyle ximStyle = 0;
-static XIMStyle ximStyleRoot = 0;
+static XIMStyle ximStyle;
 
 /* moved here from imm32 for dll separation */
 static DWORD dwCompStringLength = 0;
@@ -290,7 +289,7 @@ static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_d
     dwPreeditPos = 0;
 }
 
-static void XIMPreEditDrawCallback(XIM ic, XPointer client_data,
+static void XIMPreEditDrawCallback(XIC ic, XPointer client_data,
                                    XIMPreeditDrawCallbackStruct *P_DR)
 {
     TRACE("PreEditDrawCallback %p\n",ic);
@@ -394,111 +393,135 @@ void X11DRV_ForceXIMReset(HWND hwnd)
     }
 }
 
-/***********************************************************************
-*           X11DRV Ime creation
-*/
-XIM X11DRV_SetupXIM(Display *display, const char *input_style)
-{
-    XIMStyle ximStyleRequest, ximStyleCallback, ximStyleNone;
-    XIMStyles *ximStyles = NULL;
-    INT i;
-    XIM xim;
+static void X11DRV_OpenIM(Display *display, XPointer p, XPointer data);
 
-    ximStyleRequest = STYLE_CALLBACK;
+static void X11DRV_DestroyIM(XIM xim, XPointer p, XPointer data)
+{
+    TRACE("xim = %p, p = %p\n", xim, p);
+    *(XIM *)p = NULL;
+    ximStyle = 0;
+    wine_tsx11_lock();
+    XRegisterIMInstantiateCallback(XDisplayOfIM(xim), NULL, NULL, NULL,
+                                   X11DRV_OpenIM, p);
+    wine_tsx11_unlock();
+}
 
-    if (!strcasecmp(input_style, "offthespot"))
-        ximStyleRequest = STYLE_OFFTHESPOT;
-    else if (!strcasecmp(input_style, "overthespot"))
-        ximStyleRequest = STYLE_OVERTHESPOT;
-    else if (!strcasecmp(input_style, "root"))
-        ximStyleRequest = STYLE_ROOT;
+static BOOL X11DRV_SelectStyle(XIM xim)
+{
+    static XIMStyle ximStyleRequest;
+    XIMStyle ximStyleCallback, ximStyleRoot, ximStyleNone;
+    XIMStyles *ximStyles;
+    INT i;
 
-    wine_tsx11_lock();
+    if (ximStyle)
+        return TRUE;
 
-    if(!XSupportsLocale())
+    if (!ximStyleRequest)
     {
-        WARN("X does not support locale.\n");
-        goto err;
+        if (!strcasecmp(input_style, "offthespot"))
+            ximStyleRequest = STYLE_OFFTHESPOT;
+        else if (!strcasecmp(input_style, "overthespot"))
+            ximStyleRequest = STYLE_OVERTHESPOT;
+        else if (!strcasecmp(input_style, "root"))
+            ximStyleRequest = STYLE_ROOT;
+        else
+            ximStyleRequest = STYLE_CALLBACK;
     }
-    if(XSetLocaleModifiers("") == NULL)
+
+    if (XGetIMValues(xim, XNQueryInputStyle, &ximStyles, NULL))
     {
-        WARN("Could not set locale modifiers.\n");
-        goto err;
+        WARN("Could not find supported input style.\n");
+        return FALSE;
     }
 
-    xim = XOpenIM(display, NULL, NULL, NULL);
-    if (xim == NULL)
+    TRACE("ximStyles->count_styles = %d\n", ximStyles->count_styles);
+
+    ximStyleRoot = 0;
+    ximStyleNone = 0;
+    ximStyleCallback = 0;
+
+    for (i = 0; i < ximStyles->count_styles; ++i)
     {
-        WARN("Could not open input method.\n");
-        goto err;
+        XIMStyle style = ximStyles->supported_styles[i];
+        TRACE("ximStyles[%d] = %s%s%s%s%s\n", i,
+                    (style & XIMPreeditArea)? "XIMPreeditArea ": "",
+                    (style & XIMPreeditCallbacks)? "XIMPreeditCallbacks ": "",
+                    (style & XIMPreeditPosition)? "XIMPreeditPosition ": "",
+                    (style & XIMPreeditNothing)? "XIMPreeditNothing ": "",
+                    (style & XIMPreeditNone)? "XIMPreeditNone ": "");
+        if (!ximStyle && (style == ximStyleRequest))
+        {
+            ximStyle = ximStyleRequest;
+            TRACE("Setting Style: ximStyle = ximStyleRequest\n");
+        }
+
+        if (!ximStyleRoot && (style == STYLE_ROOT))
+        {
+            ximStyleRoot = STYLE_ROOT;
+            TRACE("Setting Style: ximStyleRoot = STYLE_ROOT\n");
+        }
+        else if (!ximStyleCallback && (style == STYLE_CALLBACK))
+        {
+            ximStyleCallback = STYLE_CALLBACK;
+            TRACE("Setting Style: ximStyleCallback = STYLE_CALLBACK\n");
+        }
+        else if (!ximStyleNone && (style == STYLE_NONE))
+        {
+            TRACE("Setting Style: ximStyleNone = STYLE_NONE\n");
+            ximStyleNone = STYLE_NONE;
+        }
     }
+    XFree(ximStyles);
 
-    TRACE("X display of IM = %p\n", XDisplayOfIM(xim));
-    TRACE("Using %s locale of Input Method\n", XLocaleOfIM(xim));
+    if (ximStyle == 0)
+        ximStyle = ximStyleRoot;
+
+    if (ximStyle == 0)
+        ximStyle = ximStyleNone;
 
-    XGetIMValues(xim, XNQueryInputStyle, &ximStyles, NULL);
-    if (ximStyles == 0)
+    if (ximStyleCallback == 0)
     {
-        WARN("Could not find supported input style.\n");
+        TRACE("No callback style avalable\n");
+        ximStyleCallback = ximStyle;
     }
-    else
-    {
-        TRACE("ximStyles->count_styles = %d\n", ximStyles->count_styles);
 
-        ximStyleRoot = 0;
-        ximStyleNone = 0;
-        ximStyleCallback = 0;
-
-        for (i = 0; i < ximStyles->count_styles; ++i)
-        {
-            int style = ximStyles->supported_styles[i];
-            TRACE("ximStyles[%d] = %s%s%s%s%s\n", i,
-                        (style&XIMPreeditArea)?"XIMPreeditArea ":"",
-                        (style&XIMPreeditCallbacks)?"XIMPreeditCallbacks ":"",
-                        (style&XIMPreeditPosition)?"XIMPreeditPosition ":"",
-                        (style&XIMPreeditNothing)?"XIMPreeditNothing ":"",
-                        (style&XIMPreeditNone)?"XIMPreeditNone ":"");
-            if (!ximStyle && (ximStyles->supported_styles[i] ==
-                                ximStyleRequest))
-            {
-                ximStyle = ximStyleRequest;
-                TRACE("Setting Style: ximStyle = ximStyleRequest\n");
-            }
-            else if (!ximStyleRoot &&(ximStyles->supported_styles[i] ==
-                     STYLE_ROOT))
-            {
-                ximStyleRoot = STYLE_ROOT;
-                TRACE("Setting Style: ximStyleRoot = STYLE_ROOT\n");
-            }
-            else if (!ximStyleCallback &&(ximStyles->supported_styles[i] ==
-                     STYLE_CALLBACK))
-            {
-                ximStyleCallback = STYLE_CALLBACK;
-                TRACE("Setting Style: ximStyleCallback = STYLE_CALLBACK\n");
-            }
-            else if (!ximStyleNone && (ximStyles->supported_styles[i] ==
-                     STYLE_NONE))
-            {
-                TRACE("Setting Style: ximStyleNone = STYLE_NONE\n");
-                ximStyleNone = STYLE_NONE;
-            }
-        }
-        XFree(ximStyles);
+    return TRUE;
+}
 
-        if (ximStyle == 0)
-            ximStyle = ximStyleRoot;
+static void X11DRV_OpenIM(Display *display, XPointer p, XPointer data)
+{
+    XIM xim;
+    XIMCallback destroy;
 
-        if (ximStyle == 0)
-            ximStyle = ximStyleNone;
+    wine_tsx11_lock();
+    xim = XOpenIM(display, NULL, NULL, NULL);
+    if (xim == NULL)
+    {
+        WARN("Could not open input method.\n");
+        wine_tsx11_unlock();
+        return;
+    }
 
-        if (ximStyleCallback == 0)
-        {
-            TRACE("No callback style avalable\n");
-            ximStyleCallback = ximStyle;
-        }
+    if (!X11DRV_SelectStyle(xim))
+    {
+        XCloseIM(xim);
+        wine_tsx11_unlock();
+        return;
+    }
 
+    destroy.client_data = p;
+    destroy.callback = X11DRV_DestroyIM;
+    if (XSetIMValues(xim, XNDestroyCallback, &destroy, NULL))
+    {
+        WARN("Could not set destroy callback.\n");
     }
 
+    *(XIM *)p = xim;
+    TRACE("xim = %p\n", xim);
+    TRACE("X display of IM = %p\n", XDisplayOfIM(xim));
+    TRACE("Using %s locale of Input Method\n", XLocaleOfIM(xim));
+
+    XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL, X11DRV_OpenIM, p);
     wine_tsx11_unlock();
 
     if(!hImmDll)
@@ -513,26 +536,59 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
         }
     }
 
-    return xim;
+    return;
 
+}
+
+/***********************************************************************
+*           X11DRV Ime creation
+*/
+BOOL X11DRV_SetupXIM(Display *display, XIM *xim)
+{
+    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(display, NULL, NULL, NULL,
+                                         X11DRV_OpenIM, (XPointer)xim);
 err:
     wine_tsx11_unlock();
-    return NULL;
+    return ret;
 }
 
+static BOOL X11DRV_DestroyIC(XIC xic, XPointer p, XPointer data)
+{
+    TRACE("xic = %p, p = %p\n", xic, p);
+    *(XIC *)p = NULL;
+    return TRUE;
+}
 
-XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
+XIC X11DRV_CreateIC(XIM xim, Window win, XIC *p)
 {
     XPoint spot = {0};
     XVaNestedList preedit = NULL;
     XVaNestedList status = NULL;
     XIC xic;
-    XIMCallback P_StartCB;
-    XIMCallback P_DoneCB;
-    XIMCallback P_DrawCB;
-    XIMCallback P_CaretCB;
+    XICCallback destroy = {(XPointer)p, X11DRV_DestroyIC};
+    XICCallback P_StartCB;
+    XICCallback P_DoneCB;
+    XICCallback P_DrawCB;
+    XICCallback P_CaretCB;
     LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
 
+    TRACE("xim = %p\n", xim);
     wine_tsx11_lock();
 
     /* use complex and slow XIC initialization method only for CJK */
@@ -544,20 +600,22 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
                         XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
                         XNClientWindow, win,
                         XNFocusWindow, win,
+                        XNDestroyCallback, &destroy,
                         NULL);
         wine_tsx11_unlock();
+        *p = xic;
         return xic;
     }
 
     /* create callbacks */
     P_StartCB.client_data = NULL;
-    P_StartCB.callback = (XIMProc)XIMPreEditStartCallback;
+    P_StartCB.callback = (XICProc)XIMPreEditStartCallback;
     P_DoneCB.client_data = NULL;
-    P_DoneCB.callback = (XIMProc)XIMPreEditDoneCallback;
+    P_DoneCB.callback = (XICProc)XIMPreEditDoneCallback;
     P_DrawCB.client_data = NULL;
-    P_DrawCB.callback = (XIMProc)XIMPreEditDrawCallback;
+    P_DrawCB.callback = (XICProc)XIMPreEditDrawCallback;
     P_CaretCB.client_data = NULL;
-    P_CaretCB.callback = (XIMProc)XIMPreEditCaretCallback;
+    P_CaretCB.callback = (XICProc)XIMPreEditCaretCallback;
 
     if ((ximStyle & (XIMPreeditNothing | XIMPreeditNone)) == 0)
     {
@@ -568,7 +626,6 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
                         XNPreeditDrawCallback, &P_DrawCB,
                         XNPreeditCaretCallback, &P_CaretCB,
                         NULL);
-        TRACE("preedit = %p\n", preedit);
     }
     else
     {
@@ -579,15 +636,14 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
                         XNPreeditCaretCallback, &P_CaretCB,
                         NULL);
 
-        TRACE("preedit = %p\n", preedit);
     }
+    TRACE("preedit = %p\n", preedit);
 
     if ((ximStyle & (XIMStatusNothing | XIMStatusNone)) == 0)
     {
-        status = XVaCreateNestedList(0,
-            NULL);
+        status = XVaCreateNestedList(0, NULL);
         TRACE("status = %p\n", status);
-     }
+    }
 
     if (preedit != NULL && status != NULL)
     {
@@ -597,8 +653,9 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNStatusAttributes, status,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
-     }
+    }
     else if (preedit != NULL)
     {
         xic = XCreateIC(xim,
@@ -606,6 +663,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 +673,7 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNStatusAttributes, status,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
     }
     else
@@ -623,10 +682,12 @@ XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
               XNInputStyle, ximStyle,
               XNClientWindow, win,
               XNFocusWindow, win,
+              XNDestroyCallback, &destroy,
               NULL);
     }
 
     TRACE("xic = %p\n", xic);
+    *p = xic;
 
     if (preedit != NULL)
         XFree(preedit);
-- 
1.5.4.5




More information about the wine-patches mailing list