Use X11 XIM callbacks to enable full IME support.
Correct some timing issues with XIM input. Start to provide the framework for the MSIME messages.
This commit is contained in:
parent
3defd321b2
commit
9672b791ee
|
@ -3,7 +3,7 @@ TOPOBJDIR = ../..
|
|||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
MODULE = imm32.dll
|
||||
IMPORTS = user32 kernel32
|
||||
IMPORTS = user32 gdi32 kernel32
|
||||
ALTNAMES = imm.dll
|
||||
|
||||
SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
|
||||
|
|
909
dlls/imm32/imm.c
909
dlls/imm32/imm.c
File diff suppressed because it is too large
Load Diff
|
@ -21,22 +21,23 @@
|
|||
@ stdcall ImmGetCompositionFontW(long ptr)
|
||||
@ stdcall ImmGetCompositionStringA (long long ptr long)
|
||||
@ stdcall ImmGetCompositionStringW (long long ptr long)
|
||||
@ stdcall ImmGetCompositionString (long long ptr long) ImmGetCompositionStringA
|
||||
@ stdcall ImmGetCompositionWindow(long ptr)
|
||||
@ stdcall ImmGetContext(long)
|
||||
@ stdcall ImmGetConversionListA(long long str ptr long long)
|
||||
@ stdcall ImmGetConversionListW(long long wstr ptr long long)
|
||||
@ stdcall ImmGetConversionStatus(long ptr ptr)
|
||||
@ stdcall ImmGetDefaultIMEWnd(long)
|
||||
@ stdcall ImmGetDescriptionA(long str long)
|
||||
@ stdcall ImmGetDescriptionW(long wstr long)
|
||||
@ stdcall ImmGetGuideLineA(long long str long)
|
||||
@ stdcall ImmGetGuideLineW(long long wstr long)
|
||||
@ stdcall ImmGetDescriptionA(long ptr long)
|
||||
@ stdcall ImmGetDescriptionW(long ptr long)
|
||||
@ stdcall ImmGetGuideLineA(long long ptr long)
|
||||
@ stdcall ImmGetGuideLineW(long long ptr long)
|
||||
@ stub ImmGetHotKey
|
||||
@ stub ImmGetIMCCLockCount
|
||||
@ stub ImmGetIMCCSize
|
||||
@ stub ImmGetIMCLockCount
|
||||
@ stdcall ImmGetIMEFileNameA(long str long)
|
||||
@ stdcall ImmGetIMEFileNameW(long wstr long)
|
||||
@ stdcall ImmGetIMEFileNameA(long ptr long)
|
||||
@ stdcall ImmGetIMEFileNameW(long ptr long)
|
||||
@ stdcall ImmGetOpenStatus(long)
|
||||
@ stdcall ImmGetProperty(long long)
|
||||
@ stdcall ImmGetRegisterWordStyleA(long long ptr)
|
||||
|
|
|
@ -39,6 +39,7 @@ C_SRCS = \
|
|||
x11drv_main.c \
|
||||
xdnd.c \
|
||||
xfont.c \
|
||||
xim.c \
|
||||
xrandr.c \
|
||||
xrender.c \
|
||||
xvidmode.c
|
||||
|
|
|
@ -54,6 +54,8 @@ WINE_DECLARE_DEBUG_CHANNEL(clipboard);
|
|||
/* X context to associate a hwnd to an X window */
|
||||
extern XContext winContext;
|
||||
|
||||
extern BOOL ximInComposeMode;
|
||||
|
||||
#define DndNotDnd -1 /* OffiX drag&drop */
|
||||
#define DndUnknown 0
|
||||
#define DndRawData 1
|
||||
|
@ -532,6 +534,8 @@ static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
|
|||
TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
|
||||
|
||||
if (event->detail == NotifyPointer) return;
|
||||
if (ximInComposeMode) return;
|
||||
|
||||
x11drv_thread_data()->last_focus = hwnd;
|
||||
if ((xic = X11DRV_get_ic( hwnd )))
|
||||
{
|
||||
|
|
|
@ -807,8 +807,8 @@ static const struct {
|
|||
{0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
|
||||
{0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
|
||||
{0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0xe0010411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0xe0010411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
{0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
|
||||
|
@ -1113,7 +1113,16 @@ void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event )
|
|||
return;
|
||||
}
|
||||
|
||||
TRACE_(key)("state = %X\n", event->state);
|
||||
TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
|
||||
|
||||
if (status == XBufferOverflow)
|
||||
ERR("Buffer Overflow need %i!\n",ascii_chars);
|
||||
|
||||
if (status == XLookupChars)
|
||||
{
|
||||
X11DRV_XIMLookupChars( Str, ascii_chars );
|
||||
return;
|
||||
}
|
||||
|
||||
/* If XKB extensions are used, the state mask for AltGr will use the group
|
||||
index instead of the modifier mask. The group index is set in bits
|
||||
|
@ -1560,7 +1569,7 @@ HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
|
|||
*/
|
||||
langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
|
||||
if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
|
||||
layout |= 0xe001 << 16; /* FIXME */
|
||||
layout = 0xe001 << 16; /* FIXME */
|
||||
|
||||
return (HKL)layout;
|
||||
}
|
||||
|
|
|
@ -789,16 +789,6 @@ static Window create_whole_window( Display *display, WND *win )
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (is_top_level)
|
||||
{
|
||||
XIM xim = x11drv_thread_data()->xim;
|
||||
if (xim) data->xic = XCreateIC( xim,
|
||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||
XNClientWindow, data->whole_window,
|
||||
XNFocusWindow, data->whole_window,
|
||||
0 );
|
||||
}
|
||||
|
||||
/* non-maximized child must be at bottom of Z order */
|
||||
if ((win->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
|
||||
{
|
||||
|
@ -809,7 +799,12 @@ static Window create_whole_window( Display *display, WND *win )
|
|||
|
||||
wine_tsx11_unlock();
|
||||
|
||||
if (is_top_level) X11DRV_set_wm_hints( display, win );
|
||||
if (is_top_level)
|
||||
{
|
||||
XIM xim = x11drv_thread_data()->xim;
|
||||
if (xim) data->xic = X11DRV_CreateIC( xim, display, data->whole_window );
|
||||
X11DRV_set_wm_hints( display, win );
|
||||
}
|
||||
|
||||
return data->whole_window;
|
||||
}
|
||||
|
|
|
@ -234,6 +234,11 @@ extern void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev);
|
|||
extern void X11DRV_OpenGL_Init(Display *display);
|
||||
extern XVisualInfo *X11DRV_setup_opengl_visual(Display *display);
|
||||
|
||||
/* 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 int X11DRV_XDND_Event(HWND hWnd, XClientMessageEvent *event);
|
||||
|
||||
/* exported dib functions for now */
|
||||
|
|
|
@ -119,3 +119,6 @@
|
|||
# X11 locks
|
||||
@ cdecl -norelay wine_tsx11_lock()
|
||||
@ cdecl -norelay wine_tsx11_unlock()
|
||||
|
||||
# XIM
|
||||
@ cdecl ForceXIMReset(long) X11DRV_ForceXIMReset
|
||||
|
|
|
@ -104,6 +104,8 @@ static void *err_callback_arg; /* error callback argument */
|
|||
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];
|
||||
|
||||
#define IS_OPTION_TRUE(ch) \
|
||||
((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
||||
|
@ -308,6 +310,11 @@ static void setup_options(void)
|
|||
if (!get_config_key( hkey, appkey, "DesktopDoubleBuffered", buffer, sizeof(buffer) ))
|
||||
desktop_dbl_buf = IS_OPTION_TRUE( buffer[0] );
|
||||
|
||||
if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
|
||||
use_xim = IS_OPTION_TRUE( buffer[0] );
|
||||
|
||||
get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
|
||||
|
||||
if (appkey) RegCloseKey( appkey );
|
||||
RegCloseKey( hkey );
|
||||
}
|
||||
|
@ -460,15 +467,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
|
|||
MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
|
||||
ExitProcess(1);
|
||||
}
|
||||
fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
|
||||
|
||||
if ((data->xim = XOpenIM( data->display, NULL, NULL, NULL )))
|
||||
{
|
||||
TRACE("X display of IM = %p\n", XDisplayOfIM(data->xim));
|
||||
TRACE("Using %s locale of Input Method\n", XLocaleOfIM(data->xim));
|
||||
}
|
||||
else
|
||||
WARN("Can't open input method\n");
|
||||
fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
if (use_xkb)
|
||||
|
@ -480,6 +480,10 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
|
|||
|
||||
if (synchronous) XSynchronize( data->display, True );
|
||||
wine_tsx11_unlock();
|
||||
|
||||
if (use_xim && !(data->xim = X11DRV_SetupXIM( data->display, input_style )))
|
||||
WARN("Input Method is not available\n");
|
||||
|
||||
if (wine_server_fd_to_handle( ConnectionNumber(data->display), GENERIC_READ | SYNCHRONIZE,
|
||||
FALSE, &data->display_fd ))
|
||||
{
|
||||
|
|
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* Functions for further XIM control
|
||||
*
|
||||
* Copyright 2003 CodeWeavers, Aric Stewart
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "wingdi.h"
|
||||
#include "winnls.h"
|
||||
#include "x11drv.h"
|
||||
#include "imm.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
||||
|
||||
/* this must match with imm32/imm.c */
|
||||
#define FROM_IME 0xcafe1337
|
||||
|
||||
BOOL ximInComposeMode=FALSE;
|
||||
|
||||
static HIMC root_context;
|
||||
static XIMStyle ximStyle = 0;
|
||||
static XIMStyle ximStyleRoot = 0;
|
||||
|
||||
/* moved here from imm32 for dll seperation */
|
||||
static DWORD dwCompStringLength = 0;
|
||||
static LPBYTE CompositionString = NULL;
|
||||
static DWORD dwCompStringSize = 0;
|
||||
static LPBYTE ResultString = NULL;
|
||||
static DWORD dwResultStringSize = 0;
|
||||
|
||||
static HMODULE hImmDll = NULL;
|
||||
static HIMC (WINAPI *pImmAssociateContext)(HWND,HIMC);
|
||||
static HIMC (WINAPI *pImmCreateContext)(void);
|
||||
static VOID (WINAPI *pImmSetOpenStatus)(HIMC,BOOL);
|
||||
static BOOL (WINAPI *pImmSetCompositionString)(HIMC, DWORD, LPWSTR,
|
||||
DWORD, LPWSTR, DWORD);
|
||||
static VOID (WINAPI *pImmNotifyIME)(HIMC, DWORD, DWORD, DWORD);
|
||||
|
||||
/* WINE specific messages from the xim in x11drv level */
|
||||
|
||||
#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea)
|
||||
#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing)
|
||||
#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing)
|
||||
/* this uses all the callbacks to utilize full IME support */
|
||||
#define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing)
|
||||
/* inorder to enable deadkey support */
|
||||
#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing)
|
||||
|
||||
/*
|
||||
* here are the functions that sort of marshall calls into IMM32.DLL
|
||||
*/
|
||||
static void LoadImmDll()
|
||||
{
|
||||
hImmDll = LoadLibraryA("imm32.dll");
|
||||
|
||||
pImmAssociateContext = (void *)GetProcAddress(hImmDll, "ImmAssociateContext");
|
||||
if (!pImmAssociateContext)
|
||||
WARN("IMM: pImmAssociateContext not found in DLL\n");
|
||||
|
||||
pImmCreateContext = (void *)GetProcAddress(hImmDll, "ImmCreateContext");
|
||||
if (!pImmCreateContext)
|
||||
WARN("IMM: pImmCreateContext not found in DLL\n");
|
||||
|
||||
pImmSetOpenStatus = (void *)GetProcAddress( hImmDll, "ImmSetOpenStatus");
|
||||
if (!pImmSetOpenStatus)
|
||||
WARN("IMM: pImmSetOpenStatus not found in DLL\n");
|
||||
|
||||
pImmSetCompositionString =(void *)GetProcAddress(hImmDll, "ImmSetCompositionStringW");
|
||||
|
||||
if (!pImmSetCompositionString)
|
||||
WARN("IMM: pImmSetCompositionStringW not found in DLL\n");
|
||||
|
||||
pImmNotifyIME = (void *)GetProcAddress( hImmDll, "ImmNotifyIME");
|
||||
|
||||
if (!pImmNotifyIME)
|
||||
WARN("IMM: pImmNotifyIME not found in DLL\n");
|
||||
}
|
||||
|
||||
static BOOL X11DRV_ImmSetInternalString(DWORD dwIndex, DWORD dwOffset,
|
||||
DWORD selLength, LPWSTR lpComp, DWORD dwCompLen)
|
||||
{
|
||||
/* Composition strings are edited in chunks */
|
||||
int byte_length = dwCompLen * sizeof(WCHAR);
|
||||
int byte_offset = dwOffset * sizeof(WCHAR);
|
||||
int byte_selection = selLength * sizeof(WCHAR);
|
||||
BOOL rc = FALSE;
|
||||
|
||||
TRACE("( %li, %li, %ld, %p, %ld):\n", dwOffset, selLength, dwIndex, lpComp,
|
||||
dwCompLen );
|
||||
|
||||
if (dwIndex == GCS_COMPSTR)
|
||||
{
|
||||
int i,j;
|
||||
LPBYTE ptr_new;
|
||||
LPBYTE ptr_old;
|
||||
|
||||
if ((dwCompLen == 0) && (selLength == 0))
|
||||
{
|
||||
/* DO Nothing */
|
||||
}
|
||||
/* deletion occurred */
|
||||
else if ((dwCompLen== 0) && (selLength != 0))
|
||||
{
|
||||
if (dwCompStringLength)
|
||||
{
|
||||
for (i = 0; i < byte_selection; i++)
|
||||
{
|
||||
if (byte_offset+byte_selection+i <
|
||||
dwCompStringLength)
|
||||
{
|
||||
CompositionString[byte_offset + i] =
|
||||
CompositionString[byte_offset + byte_selection + i];
|
||||
}
|
||||
else
|
||||
CompositionString[byte_offset + i] = 0;
|
||||
}
|
||||
/* clean up the end */
|
||||
dwCompStringLength -= byte_selection;
|
||||
|
||||
i = dwCompStringLength;
|
||||
while (i < dwCompStringSize)
|
||||
{
|
||||
CompositionString[i++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int byte_expansion = byte_length - byte_selection;
|
||||
|
||||
if (byte_expansion + dwCompStringLength >= dwCompStringSize)
|
||||
{
|
||||
if (CompositionString)
|
||||
CompositionString =
|
||||
HeapReAlloc(GetProcessHeap(), 0,
|
||||
CompositionString,
|
||||
dwCompStringSize +
|
||||
byte_expansion);
|
||||
else
|
||||
CompositionString =
|
||||
HeapAlloc(GetProcessHeap(), 0, dwCompStringSize +
|
||||
byte_expansion);
|
||||
|
||||
memset(&(CompositionString[dwCompStringSize]), byte_expansion,
|
||||
0);
|
||||
|
||||
dwCompStringSize += byte_expansion;
|
||||
}
|
||||
|
||||
ptr_new = ((LPBYTE)lpComp);
|
||||
ptr_old = CompositionString + byte_offset + byte_selection;
|
||||
|
||||
dwCompStringLength += byte_expansion;
|
||||
|
||||
for (j=0,i = byte_offset; i < dwCompStringSize; i++)
|
||||
{
|
||||
if (j < byte_length)
|
||||
{
|
||||
CompositionString[i] = ptr_new[j++];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptr_old < CompositionString + dwCompStringSize)
|
||||
{
|
||||
CompositionString[i] = *ptr_old;
|
||||
ptr_old++;
|
||||
}
|
||||
else
|
||||
CompositionString[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pImmSetCompositionString)
|
||||
rc = pImmSetCompositionString((HIMC)FROM_IME, SCS_SETSTR,
|
||||
(LPWSTR)CompositionString, dwCompStringLength,
|
||||
NULL, 0);
|
||||
}
|
||||
else if ((dwIndex == GCS_RESULTSTR) && (lpComp) && (dwCompLen))
|
||||
{
|
||||
if (dwResultStringSize)
|
||||
HeapFree(GetProcessHeap(),0,ResultString);
|
||||
dwResultStringSize= byte_length;
|
||||
ResultString= HeapAlloc(GetProcessHeap(),0,byte_length);
|
||||
memcpy(ResultString,lpComp,byte_length);
|
||||
|
||||
if (pImmSetCompositionString)
|
||||
rc = pImmSetCompositionString((HIMC)FROM_IME, SCS_SETSTR,
|
||||
(LPWSTR)ResultString, dwResultStringSize,
|
||||
NULL, 0);
|
||||
|
||||
if (pImmNotifyIME)
|
||||
pImmNotifyIME((HIMC)FROM_IME, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void X11DRV_XIMLookupChars( const char *str, DWORD count )
|
||||
{
|
||||
DWORD dwOutput;
|
||||
WCHAR wcOutput[64];
|
||||
HWND focus;
|
||||
|
||||
dwOutput = MultiByteToWideChar(CP_UNIXCP, 0, str, count, wcOutput, sizeof(wcOutput));
|
||||
|
||||
if (pImmAssociateContext && (focus = GetFocus()))
|
||||
pImmAssociateContext(focus,root_context);
|
||||
|
||||
X11DRV_ImmSetInternalString(GCS_RESULTSTR,0,0,wcOutput,dwOutput);
|
||||
}
|
||||
|
||||
static void X11DRV_ImmSetOpenStatus(BOOL fOpen)
|
||||
{
|
||||
if (fOpen == FALSE)
|
||||
{
|
||||
if (dwCompStringSize)
|
||||
HeapFree(GetProcessHeap(),0,CompositionString);
|
||||
|
||||
dwCompStringSize = 0;
|
||||
dwCompStringLength = 0;
|
||||
CompositionString = NULL;
|
||||
|
||||
if (dwResultStringSize)
|
||||
HeapFree(GetProcessHeap(),0,ResultString);
|
||||
|
||||
dwResultStringSize = 0;
|
||||
ResultString = NULL;
|
||||
}
|
||||
|
||||
if (pImmSetOpenStatus)
|
||||
pImmSetOpenStatus((HIMC)FROM_IME,fOpen);
|
||||
}
|
||||
|
||||
static int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
|
||||
{
|
||||
TRACE("PreEditStartCallback %p\n",ic);
|
||||
X11DRV_ImmSetOpenStatus(TRUE);
|
||||
ximInComposeMode = TRUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
|
||||
{
|
||||
TRACE("PreeditDoneCallback %p\n",ic);
|
||||
ximInComposeMode = FALSE;
|
||||
X11DRV_ImmSetOpenStatus(FALSE);
|
||||
}
|
||||
|
||||
static void XIMPreEditDrawCallback(XIM ic, XPointer client_data,
|
||||
XIMPreeditDrawCallbackStruct *P_DR)
|
||||
{
|
||||
DWORD dwOutput;
|
||||
WCHAR wcOutput[64];
|
||||
|
||||
TRACE("PreEditDrawCallback %p\n",ic);
|
||||
|
||||
if (P_DR)
|
||||
{
|
||||
int sel = P_DR->chg_first;
|
||||
int len = P_DR->chg_length;
|
||||
if (P_DR->text)
|
||||
{
|
||||
if (! P_DR->text->encoding_is_wchar)
|
||||
{
|
||||
TRACE("multibyte\n");
|
||||
dwOutput = MultiByteToWideChar(CP_UNIXCP, 0,
|
||||
P_DR->text->string.multi_byte, -1,
|
||||
wcOutput, 64);
|
||||
|
||||
/* ignore null */
|
||||
dwOutput --;
|
||||
X11DRV_ImmSetInternalString (GCS_COMPSTR, sel, len, wcOutput, dwOutput);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("wchar PROBIBILY WRONG\n");
|
||||
X11DRV_ImmSetInternalString (GCS_COMPSTR, sel, len,
|
||||
(LPWSTR)P_DR->text->string.wide_char,
|
||||
P_DR->text->length);
|
||||
}
|
||||
}
|
||||
else
|
||||
X11DRV_ImmSetInternalString (GCS_COMPSTR, sel, len, NULL, 0);
|
||||
}
|
||||
TRACE("Finished\n");
|
||||
}
|
||||
|
||||
static void XIMPreEditCaretCallback(XIC ic, XPointer client_data,
|
||||
XIMPreeditCaretCallbackStruct *P_C)
|
||||
{
|
||||
FIXME("PreeditCaretCalback %p\n",ic);
|
||||
}
|
||||
|
||||
void WINAPI X11DRV_ForceXIMReset(HWND hwnd)
|
||||
{
|
||||
XIC ic = X11DRV_get_ic(hwnd);
|
||||
if (ic)
|
||||
{
|
||||
char* leftover;
|
||||
TRACE("Forcing Reset %p\n",ic);
|
||||
wine_tsx11_lock();
|
||||
leftover = XmbResetIC(ic);
|
||||
XFree(leftover);
|
||||
wine_tsx11_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* X11DRV Ime creation
|
||||
*/
|
||||
XIM X11DRV_SetupXIM(Display *display, const char *input_style)
|
||||
{
|
||||
XIMStyle ximStyleRequest, ximStyleCallback, ximStyleNone;
|
||||
XIMStyles *ximStyles = NULL;
|
||||
INT i;
|
||||
XIM xim;
|
||||
|
||||
ximStyleRequest = STYLE_CALLBACK;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
WARN("Could not open input method.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
TRACE("X display of IM = %p\n", XDisplayOfIM(xim));
|
||||
TRACE("Using %s locale of Input Method\n", XLocaleOfIM(xim));
|
||||
|
||||
XGetIMValues(xim, XNQueryInputStyle, &ximStyles, NULL);
|
||||
if (ximStyles == 0)
|
||||
{
|
||||
WARN("Could not find supported input style.\n");
|
||||
}
|
||||
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);
|
||||
|
||||
if (ximStyle == 0)
|
||||
ximStyle = ximStyleRoot;
|
||||
|
||||
if (ximStyle == 0)
|
||||
ximStyle = ximStyleNone;
|
||||
|
||||
if (ximStyleCallback == 0)
|
||||
{
|
||||
TRACE("No callback style avalable\n");
|
||||
ximStyleCallback = ximStyle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wine_tsx11_unlock();
|
||||
|
||||
LoadImmDll();
|
||||
|
||||
if (pImmCreateContext)
|
||||
{
|
||||
root_context = pImmCreateContext();
|
||||
if (pImmAssociateContext)
|
||||
pImmAssociateContext(0,root_context);
|
||||
}
|
||||
|
||||
return xim;
|
||||
|
||||
err:
|
||||
wine_tsx11_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
|
||||
{
|
||||
XFontSet fontSet;
|
||||
char **list;
|
||||
int count;
|
||||
XPoint spot = {0};
|
||||
XVaNestedList preedit = NULL;
|
||||
XVaNestedList status = NULL;
|
||||
XIC xic;
|
||||
XIMCallback P_StartCB;
|
||||
XIMCallback P_DoneCB;
|
||||
XIMCallback P_DrawCB;
|
||||
XIMCallback P_CaretCB;
|
||||
LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
|
||||
|
||||
wine_tsx11_lock();
|
||||
|
||||
/* use complex and slow XIC initialization method only for CJK */
|
||||
if (langid != LANG_CHINESE &&
|
||||
langid != LANG_JAPANESE &&
|
||||
langid != LANG_KOREAN)
|
||||
{
|
||||
xic = XCreateIC(xim,
|
||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||
XNClientWindow, win,
|
||||
XNFocusWindow, win,
|
||||
0);
|
||||
wine_tsx11_unlock();
|
||||
return xic;
|
||||
}
|
||||
|
||||
fontSet = XCreateFontSet(display,
|
||||
"*", /*FIXME*/
|
||||
&list, &count, NULL);
|
||||
|
||||
TRACE("ximFontSet = 0x%x\n", (unsigned int) fontSet);
|
||||
TRACE("list = 0x%x, count = %d\n", (unsigned int) list, count);
|
||||
|
||||
if (list != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
TRACE("list[%d] = %s\n", i, list[i]);
|
||||
}
|
||||
XFreeStringList(list);
|
||||
}
|
||||
|
||||
/* create callbacks */
|
||||
P_StartCB.client_data = NULL;
|
||||
P_StartCB.callback = (XIMProc)XIMPreEditStartCallback;
|
||||
P_DoneCB.client_data = NULL;
|
||||
P_DoneCB.callback = (XIMProc)XIMPreEditDoneCallback;
|
||||
P_DrawCB.client_data = NULL;
|
||||
P_DrawCB.callback = (XIMProc)XIMPreEditDrawCallback;
|
||||
P_CaretCB.client_data = NULL;
|
||||
P_CaretCB.callback = (XIMProc)XIMPreEditCaretCallback;
|
||||
|
||||
if ((ximStyle & (XIMPreeditNothing | XIMPreeditNone)) == 0)
|
||||
{
|
||||
preedit = XVaCreateNestedList(0,
|
||||
XNFontSet, fontSet,
|
||||
XNSpotLocation, &spot,
|
||||
XNPreeditStartCallback, &P_StartCB,
|
||||
XNPreeditDoneCallback, &P_DoneCB,
|
||||
XNPreeditDrawCallback, &P_DrawCB,
|
||||
XNPreeditCaretCallback, &P_CaretCB,
|
||||
NULL);
|
||||
TRACE("preedit = 0x%x\n", (unsigned int) preedit);
|
||||
}
|
||||
else
|
||||
{
|
||||
preedit = XVaCreateNestedList(0,
|
||||
XNPreeditStartCallback, &P_StartCB,
|
||||
XNPreeditDoneCallback, &P_DoneCB,
|
||||
XNPreeditDrawCallback, &P_DrawCB,
|
||||
XNPreeditCaretCallback, &P_CaretCB,
|
||||
NULL);
|
||||
|
||||
TRACE("preedit = 0x%x\n", (unsigned int) preedit);
|
||||
}
|
||||
|
||||
if ((ximStyle & (XIMStatusNothing | XIMStatusNone)) == 0)
|
||||
{
|
||||
status = XVaCreateNestedList(0,
|
||||
XNFontSet, fontSet,
|
||||
NULL);
|
||||
TRACE("status = 0x%x\n", (unsigned int) status);
|
||||
}
|
||||
|
||||
if (preedit != NULL && status != NULL)
|
||||
{
|
||||
xic = XCreateIC(xim,
|
||||
XNInputStyle, ximStyle,
|
||||
XNPreeditAttributes, preedit,
|
||||
XNStatusAttributes, status,
|
||||
XNClientWindow, win,
|
||||
XNFocusWindow, win,
|
||||
NULL);
|
||||
}
|
||||
else if (preedit != NULL)
|
||||
{
|
||||
xic = XCreateIC(xim,
|
||||
XNInputStyle, ximStyle,
|
||||
XNPreeditAttributes, preedit,
|
||||
XNClientWindow, win,
|
||||
XNFocusWindow, win,
|
||||
NULL);
|
||||
}
|
||||
else if (status != NULL)
|
||||
{
|
||||
xic = XCreateIC(xim,
|
||||
XNInputStyle, ximStyle,
|
||||
XNStatusAttributes, status,
|
||||
XNClientWindow, win,
|
||||
XNFocusWindow, win,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
xic = XCreateIC(xim,
|
||||
XNInputStyle, ximStyle,
|
||||
XNClientWindow, win,
|
||||
XNFocusWindow, win,
|
||||
NULL);
|
||||
}
|
||||
|
||||
TRACE("xic = 0x%x\n", (unsigned int) xic);
|
||||
|
||||
if (preedit != NULL)
|
||||
XFree(preedit);
|
||||
if (status != NULL)
|
||||
XFree(status);
|
||||
|
||||
wine_tsx11_unlock();
|
||||
|
||||
return xic;
|
||||
}
|
Loading…
Reference in New Issue