mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-21 18:04:15 +00:00
user32: Create and destroy the default IME window implicitly.
Signed-off-by: Akihiro Sagawa <sagawa.aki@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
876d5de0b4
commit
911d269be8
101
dlls/imm32/imm.c
101
dlls/imm32/imm.c
|
@ -96,6 +96,7 @@ typedef struct _tagIMMThreadData {
|
|||
HIMC defaultContext;
|
||||
HWND hwndDefault;
|
||||
BOOL disableIME;
|
||||
DWORD windowRefs;
|
||||
} IMMThreadData;
|
||||
|
||||
static struct list ImmHklList = LIST_INIT(ImmHklList);
|
||||
|
@ -1618,27 +1619,51 @@ BOOL WINAPI ImmGetConversionStatus(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetDefaultIMEWnd (IMM32.@)
|
||||
*/
|
||||
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
||||
static BOOL needs_ime_window(HWND hwnd)
|
||||
{
|
||||
HWND ret, new = NULL;
|
||||
IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
|
||||
WCHAR classW[8];
|
||||
|
||||
if (GetClassNameW(hwnd, classW, sizeof(classW)/sizeof(classW[0])) &&
|
||||
!strcmpW(classW, szwIME))
|
||||
return FALSE;
|
||||
if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_register_window (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI __wine_register_window(HWND hwnd)
|
||||
{
|
||||
HWND new = NULL;
|
||||
IMMThreadData *thread_data;
|
||||
TRACE("(%p)\n", hwnd);
|
||||
|
||||
if (!needs_ime_window(hwnd))
|
||||
return FALSE;
|
||||
|
||||
thread_data = IMM_GetThreadData(hwnd, 0);
|
||||
if (!thread_data)
|
||||
return NULL;
|
||||
if (thread_data->hwndDefault == NULL && thread_data->threadID == GetCurrentThreadId())
|
||||
return FALSE;
|
||||
|
||||
if (thread_data->disableIME || disable_ime)
|
||||
{
|
||||
TRACE("IME for this thread is disabled\n");
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
return FALSE;
|
||||
}
|
||||
thread_data->windowRefs++;
|
||||
TRACE("windowRefs=%u, hwndDefault=%p\n",
|
||||
thread_data->windowRefs, thread_data->hwndDefault);
|
||||
|
||||
/* Create default IME window */
|
||||
if (thread_data->windowRefs == 1)
|
||||
{
|
||||
if (thread_data->disableIME || disable_ime)
|
||||
{
|
||||
TRACE("IME for this thread is disabled\n");
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
return NULL;
|
||||
}
|
||||
/* Do not create the window inside of a critical section */
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
new = CreateWindowExW( WS_EX_TOOLWINDOW,
|
||||
szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
|
||||
szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
|
||||
/* thread_data is in the current thread so we can assume it's still valid */
|
||||
EnterCriticalSection(&threaddata_cs);
|
||||
/* See if anyone beat us */
|
||||
|
@ -1646,16 +1671,56 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
|||
{
|
||||
thread_data->hwndDefault = new;
|
||||
new = NULL;
|
||||
TRACE("Default is %p\n", thread_data->hwndDefault);
|
||||
}
|
||||
}
|
||||
ret = thread_data->hwndDefault;
|
||||
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
TRACE("Default is %p\n",ret);
|
||||
|
||||
/* Clean up an unused new window outside of the critical section */
|
||||
if (new != NULL)
|
||||
{
|
||||
DestroyWindow(new);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_unregister_window (IMM32.@)
|
||||
*/
|
||||
void WINAPI __wine_unregister_window(HWND hwnd)
|
||||
{
|
||||
HWND to_destroy = 0;
|
||||
IMMThreadData *thread_data;
|
||||
TRACE("(%p)\n", hwnd);
|
||||
|
||||
thread_data = IMM_GetThreadData(hwnd, 0);
|
||||
if (!thread_data) return;
|
||||
|
||||
thread_data->windowRefs--;
|
||||
TRACE("windowRefs=%u, hwndDefault=%p\n",
|
||||
thread_data->windowRefs, thread_data->hwndDefault);
|
||||
|
||||
/* Destroy default IME window */
|
||||
if (thread_data->windowRefs == 0 && thread_data->hwndDefault)
|
||||
{
|
||||
to_destroy = thread_data->hwndDefault;
|
||||
thread_data->hwndDefault = NULL;
|
||||
}
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
if (to_destroy) DestroyWindow( to_destroy );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetDefaultIMEWnd (IMM32.@)
|
||||
*/
|
||||
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
||||
{
|
||||
HWND ret;
|
||||
IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
|
||||
if (!thread_data)
|
||||
return NULL;
|
||||
ret = thread_data->hwndDefault;
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
TRACE("Default is %p\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -114,3 +114,5 @@
|
|||
################################################################
|
||||
# Wine internal extensions
|
||||
@ stdcall __wine_get_ui_window(ptr)
|
||||
@ stdcall __wine_register_window(long)
|
||||
@ stdcall __wine_unregister_window(long)
|
||||
|
|
|
@ -207,7 +207,6 @@ static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
case FIRST_WINDOW:
|
||||
case SECOND_WINDOW:
|
||||
case CREATE_CANCEL:
|
||||
todo_wine_if(test_phase == FIRST_WINDOW || test_phase == CREATE_CANCEL)
|
||||
ok(default_ime_wnd != NULL, "expected IME window existence\n");
|
||||
break;
|
||||
case IME_DISABLED:
|
||||
|
@ -223,7 +222,6 @@ static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
case FIRST_WINDOW:
|
||||
case SECOND_WINDOW:
|
||||
case CREATE_CANCEL:
|
||||
todo_wine_if(test_phase == FIRST_WINDOW || test_phase == CREATE_CANCEL)
|
||||
ok(default_ime_wnd != NULL, "expected IME window existence\n");
|
||||
break;
|
||||
case IME_DISABLED:
|
||||
|
@ -952,9 +950,9 @@ static DWORD WINAPI test_default_ime_window_cb(void *arg)
|
|||
240, 24, hwnd, NULL, GetModuleHandleW(NULL), NULL);
|
||||
}
|
||||
ime_wnd = get_ime_window();
|
||||
todo_wine ok(ime_wnd != NULL, "Expected IME window existence\n");
|
||||
ok(ime_wnd != NULL, "Expected IME window existence\n");
|
||||
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
|
||||
todo_wine ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
|
||||
ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
|
||||
|
||||
test_phase = SECOND_WINDOW;
|
||||
hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
||||
|
@ -962,7 +960,7 @@ static DWORD WINAPI test_default_ime_window_cb(void *arg)
|
|||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
||||
DestroyWindow(hwnd2);
|
||||
todo_wine ok(IsWindow(ime_wnd) ||
|
||||
ok(IsWindow(ime_wnd) ||
|
||||
broken(!testcase->visible /* Vista */) ||
|
||||
broken(!testcase->top_level_window /* Vista */) ,
|
||||
"Expected IME window existence\n");
|
||||
|
@ -1000,9 +998,9 @@ static DWORD WINAPI test_default_ime_window_cancel_cb(void *arg)
|
|||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
||||
ime_wnd = get_ime_window();
|
||||
todo_wine ok(ime_wnd != NULL, "Expected IME window existence\n");
|
||||
ok(ime_wnd != NULL, "Expected IME window existence\n");
|
||||
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd2);
|
||||
todo_wine ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
|
||||
ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
|
||||
|
||||
DestroyWindow(hwnd2);
|
||||
ok(!IsWindow(ime_wnd), "Expected no IME windows\n");
|
||||
|
|
|
@ -41,6 +41,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
|
|||
|
||||
#define IMM_INIT_MAGIC 0x19650412
|
||||
static HWND (WINAPI *imm_get_ui_window)(HKL);
|
||||
BOOL (WINAPI *imm_register_window)(HWND) = NULL;
|
||||
void (WINAPI *imm_unregister_window)(HWND) = NULL;
|
||||
|
||||
/* MSIME messages */
|
||||
static UINT WM_MSIME_SERVICE;
|
||||
|
@ -684,6 +686,8 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
|||
|
||||
/* this part is not compatible with native imm32.dll */
|
||||
imm_get_ui_window = (void*)GetProcAddress(imm32, "__wine_get_ui_window");
|
||||
imm_register_window = (void*)GetProcAddress(imm32, "__wine_register_window");
|
||||
imm_unregister_window = (void*)GetProcAddress(imm32, "__wine_unregister_window");
|
||||
if (!imm_get_ui_window)
|
||||
FIXME("native imm32.dll not supported\n");
|
||||
return TRUE;
|
||||
|
|
|
@ -196,6 +196,8 @@ struct user_thread_info
|
|||
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) );
|
||||
|
||||
extern INT global_key_state_counter DECLSPEC_HIDDEN;
|
||||
extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
|
||||
|
||||
struct user_key_state_info
|
||||
{
|
||||
|
|
|
@ -958,6 +958,13 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
|
|||
|
||||
TRACE("%p\n", hwnd );
|
||||
|
||||
/* destroy default IME window */
|
||||
if (win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN)
|
||||
{
|
||||
TRACE("unregister IME window for %p\n", hwnd);
|
||||
imm_unregister_window( hwnd );
|
||||
}
|
||||
|
||||
/* free child windows */
|
||||
if ((list = WIN_ListChildren( hwnd )))
|
||||
{
|
||||
|
@ -1604,6 +1611,14 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
/* create default IME window */
|
||||
|
||||
if (imm_register_window && !is_desktop_window( hwnd ) && imm_register_window( hwnd ))
|
||||
{
|
||||
TRACE("register IME window for %p\n", hwnd);
|
||||
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
|
||||
}
|
||||
|
||||
/* send WM_NCCALCSIZE */
|
||||
|
||||
if (WIN_GetRectangles( hwnd, COORDS_PARENT, &rect, NULL ))
|
||||
|
|
|
@ -77,6 +77,7 @@ typedef struct tagWND
|
|||
#define WIN_ISUNICODE 0x0010 /* Window is Unicode */
|
||||
#define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0020 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */
|
||||
#define WIN_CHILDREN_MOVED 0x0040 /* children may have moved, ignore stored positions */
|
||||
#define WIN_HAS_IME_WIN 0x0080 /* the window has been registered with imm32 */
|
||||
|
||||
/* Window functions */
|
||||
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Reference in a new issue