mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-07 05:04:05 +00:00
win32u: Move default IME window management from imm32.
This commit is contained in:
parent
f4f589c421
commit
047d74c4b1
219
dlls/imm32/imm.c
219
dlls/imm32/imm.c
|
@ -100,14 +100,6 @@ typedef struct _tagTRANSMSG {
|
|||
LPARAM lParam;
|
||||
} TRANSMSG, *LPTRANSMSG;
|
||||
|
||||
typedef struct _tagIMMThreadData {
|
||||
struct list entry;
|
||||
DWORD threadID;
|
||||
HWND hwndDefault;
|
||||
BOOL disableIME;
|
||||
DWORD windowRefs;
|
||||
} IMMThreadData;
|
||||
|
||||
struct coinit_spy
|
||||
{
|
||||
IInitializeSpy IInitializeSpy_iface;
|
||||
|
@ -123,20 +115,9 @@ struct coinit_spy
|
|||
};
|
||||
|
||||
static struct list ImmHklList = LIST_INIT(ImmHklList);
|
||||
static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
|
||||
|
||||
static const WCHAR szImeRegFmt[] = L"System\\CurrentControlSet\\Control\\Keyboard Layouts\\%08lx";
|
||||
|
||||
static CRITICAL_SECTION threaddata_cs;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
{
|
||||
0, 0, &threaddata_cs,
|
||||
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
|
||||
};
|
||||
static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||
static BOOL disable_ime;
|
||||
|
||||
static inline BOOL is_himc_ime_unicode(const InputContextData *data)
|
||||
{
|
||||
return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
|
||||
|
@ -412,38 +393,6 @@ static void imm_coinit_thread(void)
|
|||
spy->apt_flags |= IMM_APT_CREATED;
|
||||
}
|
||||
|
||||
static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
|
||||
{
|
||||
IMMThreadData *data;
|
||||
DWORD process;
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
|
||||
if (process != GetCurrentProcessId()) return NULL;
|
||||
}
|
||||
else if (thread)
|
||||
{
|
||||
HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, thread);
|
||||
if (!h) return NULL;
|
||||
process = GetProcessIdOfThread(h);
|
||||
CloseHandle(h);
|
||||
if (process != GetCurrentProcessId()) return NULL;
|
||||
}
|
||||
else
|
||||
thread = GetCurrentThreadId();
|
||||
|
||||
EnterCriticalSection(&threaddata_cs);
|
||||
LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
|
||||
if (data->threadID == thread) return data;
|
||||
|
||||
data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
|
||||
data->threadID = thread;
|
||||
list_add_head(&ImmThreadDataList,&data->entry);
|
||||
TRACE("Thread Data Created (%lx)\n",thread);
|
||||
return data;
|
||||
}
|
||||
|
||||
static BOOL IMM_IsDefaultContext(HIMC imc)
|
||||
{
|
||||
InputContextData *data = get_imc_data(imc);
|
||||
|
@ -490,21 +439,6 @@ static BOOL free_input_context_data(HIMC hIMC)
|
|||
static void IMM_FreeThreadData(void)
|
||||
{
|
||||
struct coinit_spy *spy;
|
||||
IMMThreadData *data;
|
||||
|
||||
EnterCriticalSection(&threaddata_cs);
|
||||
LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
|
||||
{
|
||||
if (data->threadID == GetCurrentThreadId())
|
||||
{
|
||||
list_remove(&data->entry);
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
HeapFree(GetProcessHeap(),0,data);
|
||||
TRACE("Thread Data Destroyed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
free_input_context_data(NtUserGetThreadInfo()->default_imc);
|
||||
if ((spy = get_thread_coinit_spy()))
|
||||
|
@ -981,62 +915,6 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static HWND imm_detach_default_window(IMMThreadData *thread_data)
|
||||
{
|
||||
HWND to_destroy;
|
||||
|
||||
to_destroy = thread_data->hwndDefault;
|
||||
thread_data->hwndDefault = NULL;
|
||||
thread_data->windowRefs = 0;
|
||||
return to_destroy;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmDisableIME (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmDisableIME(DWORD idThread)
|
||||
{
|
||||
IMMThreadData *thread_data;
|
||||
HWND to_destroy;
|
||||
|
||||
if (idThread == (DWORD)-1)
|
||||
{
|
||||
disable_ime = TRUE;
|
||||
|
||||
while (1)
|
||||
{
|
||||
to_destroy = 0;
|
||||
EnterCriticalSection(&threaddata_cs);
|
||||
LIST_FOR_EACH_ENTRY(thread_data, &ImmThreadDataList, IMMThreadData, entry)
|
||||
{
|
||||
if (thread_data->hwndDefault)
|
||||
{
|
||||
to_destroy = imm_detach_default_window(thread_data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
if (!to_destroy)
|
||||
break;
|
||||
DestroyWindow(to_destroy);
|
||||
}
|
||||
}
|
||||
else if (!idThread || idThread == GetCurrentThreadId())
|
||||
{
|
||||
thread_data = IMM_GetThreadData(NULL, idThread);
|
||||
if (!thread_data) return FALSE;
|
||||
thread_data->disableIME = TRUE;
|
||||
to_destroy = imm_detach_default_window(thread_data);
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
if (to_destroy)
|
||||
DestroyWindow(to_destroy);
|
||||
}
|
||||
else return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmEnumRegisterWordA (IMM32.@)
|
||||
*/
|
||||
|
@ -1816,107 +1694,12 @@ BOOL WINAPI ImmGetConversionStatus(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL needs_ime_window(HWND hwnd)
|
||||
{
|
||||
WCHAR classW[8];
|
||||
|
||||
if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !lstrcmpW(classW, L"IME"))
|
||||
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 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=%lu, hwndDefault=%p\n",
|
||||
thread_data->windowRefs, thread_data->hwndDefault);
|
||||
|
||||
/* Create default IME window */
|
||||
if (thread_data->windowRefs == 1)
|
||||
{
|
||||
/* Do not create the window inside of a critical section */
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
new = CreateWindowExW( 0, L"IME", L"Default IME",
|
||||
WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
|
||||
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 */
|
||||
if (thread_data->hwndDefault == NULL)
|
||||
{
|
||||
thread_data->hwndDefault = new;
|
||||
new = NULL;
|
||||
TRACE("Default is %p\n", thread_data->hwndDefault);
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
/* 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=%lu, hwndDefault=%p\n",
|
||||
thread_data->windowRefs, thread_data->hwndDefault);
|
||||
|
||||
/* Destroy default IME window */
|
||||
if (thread_data->windowRefs == 0)
|
||||
to_destroy = imm_detach_default_window(thread_data);
|
||||
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;
|
||||
return NtUserGetDefaultImeWindow(hWnd);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
@ stdcall ImmDestroyContext(long)
|
||||
@ stdcall ImmDestroyIMCC(long)
|
||||
@ stdcall ImmDestroySoftKeyboard(long)
|
||||
@ stdcall ImmDisableIME(long)
|
||||
@ stdcall ImmDisableIme(long) ImmDisableIME
|
||||
@ stdcall ImmDisableIME(long) NtUserDisableThreadIme
|
||||
@ stdcall ImmDisableIme(long) NtUserDisableThreadIme
|
||||
@ stdcall ImmDisableLegacyIME()
|
||||
@ stdcall ImmDisableTextFrameService(long)
|
||||
@ stdcall ImmEnumInputContext(long ptr long)
|
||||
|
@ -115,5 +115,3 @@
|
|||
################################################################
|
||||
# Wine internal extensions
|
||||
@ stdcall __wine_ime_wnd_proc(long long long long long)
|
||||
@ stdcall __wine_register_window(long)
|
||||
@ stdcall __wine_unregister_window(long)
|
||||
|
|
|
@ -2426,11 +2426,9 @@ static void test_ImmDisableIME(void)
|
|||
|
||||
ok(IsWindow(def), "not a window\n");
|
||||
def2 = ImmGetDefaultIMEWnd(hwnd);
|
||||
todo_wine
|
||||
ok(def2 == def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def2);
|
||||
ok(IsWindow(def), "not a window\n");
|
||||
msg_spy_pump_msg_queue();
|
||||
todo_wine
|
||||
ok(!IsWindow(def), "window is still valid\n");
|
||||
def = ImmGetDefaultIMEWnd(hwnd);
|
||||
ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def);
|
||||
|
|
|
@ -39,8 +39,6 @@ BOOL WINAPI ImmSetActiveContext(HWND, HIMC, BOOL);
|
|||
|
||||
#define IMM_INIT_MAGIC 0x19650412
|
||||
static LRESULT (WINAPI *imm_ime_wnd_proc)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi);
|
||||
BOOL (WINAPI *imm_register_window)(HWND) = NULL;
|
||||
void (WINAPI *imm_unregister_window)(HWND) = NULL;
|
||||
|
||||
/* USER signal proc flags and codes */
|
||||
/* See UserSignalProc for comments */
|
||||
|
@ -328,8 +326,6 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
|||
|
||||
/* this part is not compatible with native imm32.dll */
|
||||
imm_ime_wnd_proc = (void*)GetProcAddress(imm32, "__wine_ime_wnd_proc");
|
||||
imm_register_window = (void*)GetProcAddress(imm32, "__wine_register_window");
|
||||
imm_unregister_window = (void*)GetProcAddress(imm32, "__wine_unregister_window");
|
||||
if (!imm_ime_wnd_proc)
|
||||
FIXME("native imm32.dll not supported\n");
|
||||
return TRUE;
|
||||
|
|
|
@ -119,22 +119,6 @@ static void dpiaware_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void CDECL notify_ime( HWND hwnd, UINT param )
|
||||
{
|
||||
HWND ime_default = ImmGetDefaultIMEWnd( hwnd );
|
||||
if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) );
|
||||
}
|
||||
|
||||
static BOOL WINAPI register_imm( HWND hwnd )
|
||||
{
|
||||
return imm_register_window( hwnd );
|
||||
}
|
||||
|
||||
static void WINAPI unregister_imm( HWND hwnd )
|
||||
{
|
||||
imm_unregister_window( hwnd );
|
||||
}
|
||||
|
||||
static NTSTATUS try_finally( NTSTATUS (CDECL *func)( void *), void *arg,
|
||||
void (CALLBACK *finally_func)( BOOL ))
|
||||
{
|
||||
|
@ -152,11 +136,8 @@ static const struct user_callbacks user_funcs =
|
|||
ImmProcessKey,
|
||||
ImmTranslateMessage,
|
||||
NtWaitForMultipleObjects,
|
||||
notify_ime,
|
||||
post_dde_message,
|
||||
unpack_dde_message,
|
||||
register_imm,
|
||||
unregister_imm,
|
||||
try_finally,
|
||||
};
|
||||
|
||||
|
|
|
@ -47,9 +47,6 @@ struct wm_char_mapping_data
|
|||
MSG get_msg;
|
||||
};
|
||||
|
||||
extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline struct user_thread_info *get_user_thread_info(void)
|
||||
{
|
||||
return (struct user_thread_info *)NtCurrentTeb()->Win32ClientInfo;
|
||||
|
|
|
@ -1007,6 +1007,18 @@ WORD get_class_word( HWND hwnd, INT offset )
|
|||
return retvalue;
|
||||
}
|
||||
|
||||
BOOL needs_ime_window( HWND hwnd )
|
||||
{
|
||||
static const WCHAR imeW[] = {'I','M','E',0};
|
||||
CLASS *class;
|
||||
BOOL ret;
|
||||
|
||||
if (!(class = get_class_ptr( hwnd, FALSE ))) return FALSE;
|
||||
ret = !(class->style & CS_IME) && wcscmp( imeW, class->name );
|
||||
release_class_ptr( class );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void register_builtins(void)
|
||||
{
|
||||
void *ret_ptr;
|
||||
|
|
|
@ -1157,6 +1157,7 @@ static struct unix_funcs unix_funcs =
|
|||
NtUserDestroyCursor,
|
||||
NtUserDestroyMenu,
|
||||
NtUserDestroyWindow,
|
||||
NtUserDisableThreadIme,
|
||||
NtUserDispatchMessage,
|
||||
NtUserDragDetect,
|
||||
NtUserDrawCaptionTemp,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/*
|
||||
* Input Context implementation
|
||||
*
|
||||
* Copyright 1998 Patrik Stridvall
|
||||
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
||||
* Copyright 2022 Jacek Caban for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -22,6 +24,7 @@
|
|||
#pragma makedep unix
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include "win32u_private.h"
|
||||
#include "ntuser_private.h"
|
||||
#include "wine/debug.h"
|
||||
|
@ -36,6 +39,18 @@ struct imc
|
|||
UINT_PTR client_ptr;
|
||||
};
|
||||
|
||||
struct imm_thread_data
|
||||
{
|
||||
struct list entry;
|
||||
DWORD thread_id;
|
||||
HWND default_hwnd;
|
||||
BOOL disable_ime;
|
||||
UINT window_cnt;
|
||||
};
|
||||
|
||||
static struct list thread_data_list = LIST_INIT( thread_data_list );
|
||||
static pthread_mutex_t imm_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static BOOL disable_ime;
|
||||
|
||||
static struct imc *get_imc_ptr( HIMC handle )
|
||||
{
|
||||
|
@ -215,3 +230,164 @@ HIMC get_window_input_context( HWND hwnd )
|
|||
release_win_ptr( win );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HWND detach_default_window( struct imm_thread_data *thread_data )
|
||||
{
|
||||
HWND hwnd = thread_data->default_hwnd;
|
||||
thread_data->default_hwnd = NULL;
|
||||
thread_data->window_cnt = 0;
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
static struct imm_thread_data *get_imm_thread_data(void)
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
if (!thread_info->imm_thread_data)
|
||||
{
|
||||
struct imm_thread_data *data;
|
||||
if (!(data = calloc( 1, sizeof( *data )))) return NULL;
|
||||
data->thread_id = GetCurrentThreadId();
|
||||
|
||||
pthread_mutex_lock( &imm_mutex );
|
||||
list_add_tail( &thread_data_list, &data->entry );
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
|
||||
thread_info->imm_thread_data = data;
|
||||
}
|
||||
return thread_info->imm_thread_data;
|
||||
}
|
||||
|
||||
BOOL register_imm_window( HWND hwnd )
|
||||
{
|
||||
struct imm_thread_data *thread_data;
|
||||
|
||||
TRACE( "(%p)\n", hwnd );
|
||||
|
||||
if (disable_ime || !needs_ime_window( hwnd ))
|
||||
return FALSE;
|
||||
|
||||
thread_data = get_imm_thread_data();
|
||||
if (!thread_data || thread_data->disable_ime)
|
||||
return FALSE;
|
||||
|
||||
TRACE( "window_cnt=%u, default_hwnd=%p\n", thread_data->window_cnt + 1, thread_data->default_hwnd );
|
||||
|
||||
/* Create default IME window */
|
||||
if (!thread_data->window_cnt++)
|
||||
{
|
||||
UNICODE_STRING class_name, name;
|
||||
static const WCHAR imeW[] = {'I','M','E',0};
|
||||
static const WCHAR default_imeW[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
|
||||
|
||||
RtlInitUnicodeString( &class_name, imeW );
|
||||
RtlInitUnicodeString( &name, default_imeW );
|
||||
thread_data->default_hwnd = NtUserCreateWindowEx( 0, &class_name, &class_name, &name,
|
||||
WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
|
||||
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, FALSE );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void unregister_imm_window( HWND hwnd )
|
||||
{
|
||||
struct imm_thread_data *thread_data = get_user_thread_info()->imm_thread_data;
|
||||
|
||||
if (!thread_data) return;
|
||||
if (thread_data->default_hwnd == hwnd)
|
||||
{
|
||||
detach_default_window( thread_data );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN)) return;
|
||||
|
||||
/* destroy default IME window */
|
||||
TRACE( "unregister IME window for %p\n", hwnd );
|
||||
if (!--thread_data->window_cnt)
|
||||
{
|
||||
HWND destroy_hwnd = detach_default_window( thread_data );
|
||||
if (destroy_hwnd) NtUserDestroyWindow( destroy_hwnd );
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* NtUserDisableThreadIme (win32u.@)
|
||||
*/
|
||||
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id )
|
||||
{
|
||||
struct imm_thread_data *thread_data;
|
||||
|
||||
if (thread_id == -1)
|
||||
{
|
||||
disable_ime = TRUE;
|
||||
|
||||
pthread_mutex_lock( &imm_mutex );
|
||||
LIST_FOR_EACH_ENTRY( thread_data, &thread_data_list, struct imm_thread_data, entry )
|
||||
{
|
||||
if (thread_data->thread_id == GetCurrentThreadId()) continue;
|
||||
if (!thread_data->default_hwnd) continue;
|
||||
NtUserMessageCall( thread_data->default_hwnd, WM_WINE_DESTROYWINDOW, 0, 0,
|
||||
0, NtUserSendNotifyMessage, FALSE );
|
||||
}
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
}
|
||||
else if (!thread_id || thread_id == GetCurrentThreadId())
|
||||
{
|
||||
if (!(thread_data = get_imm_thread_data())) return FALSE;
|
||||
thread_data->disable_ime = TRUE;
|
||||
}
|
||||
else return FALSE;
|
||||
|
||||
if ((thread_data = get_user_thread_info()->imm_thread_data))
|
||||
{
|
||||
HWND destroy_hwnd = detach_default_window( thread_data );
|
||||
NtUserDestroyWindow( destroy_hwnd );
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HWND get_default_ime_window( HWND hwnd )
|
||||
{
|
||||
struct imm_thread_data *thread_data;
|
||||
HWND ret = 0;
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
DWORD thread_id;
|
||||
|
||||
if (!(thread_id = get_window_thread( hwnd, NULL ))) return 0;
|
||||
|
||||
pthread_mutex_lock( &imm_mutex );
|
||||
LIST_FOR_EACH_ENTRY( thread_data, &thread_data_list, struct imm_thread_data, entry )
|
||||
{
|
||||
if (thread_data->thread_id != thread_id) continue;
|
||||
ret = thread_data->default_hwnd;
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
}
|
||||
else if ((thread_data = get_user_thread_info()->imm_thread_data))
|
||||
{
|
||||
ret = thread_data->default_hwnd;
|
||||
}
|
||||
|
||||
TRACE( "default for %p is %p\n", hwnd, ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cleanup_imm_thread(void)
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
|
||||
if (thread_info->imm_thread_data)
|
||||
{
|
||||
pthread_mutex_lock( &imm_mutex );
|
||||
list_remove( &thread_info->imm_thread_data->entry );
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
free( thread_info->imm_thread_data );
|
||||
thread_info->imm_thread_data = NULL;
|
||||
}
|
||||
|
||||
NtUserDestroyInputContext( thread_info->client_info.default_imc );
|
||||
}
|
||||
|
|
|
@ -1551,7 +1551,7 @@ HWND get_focus(void)
|
|||
*/
|
||||
static HWND set_focus_window( HWND hwnd )
|
||||
{
|
||||
HWND previous = 0;
|
||||
HWND previous = 0, ime_hwnd;
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_REQ( set_focus_window )
|
||||
|
@ -1568,7 +1568,10 @@ static HWND set_focus_window( HWND hwnd )
|
|||
{
|
||||
send_message( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 );
|
||||
|
||||
if (user_callbacks) user_callbacks->notify_ime( previous, IME_INTERNAL_DEACTIVATE );
|
||||
ime_hwnd = get_default_ime_window( previous );
|
||||
if (ime_hwnd)
|
||||
send_message( ime_hwnd, WM_IME_INTERNAL, IME_INTERNAL_DEACTIVATE,
|
||||
HandleToUlong(previous) );
|
||||
|
||||
if (hwnd != get_focus()) return previous; /* changed by the message */
|
||||
}
|
||||
|
@ -1576,7 +1579,10 @@ static HWND set_focus_window( HWND hwnd )
|
|||
{
|
||||
user_driver->pSetFocus(hwnd);
|
||||
|
||||
if (user_callbacks) user_callbacks->notify_ime( hwnd, IME_INTERNAL_ACTIVATE );
|
||||
ime_hwnd = get_default_ime_window( hwnd );
|
||||
if (ime_hwnd)
|
||||
send_message( ime_hwnd, WM_IME_INTERNAL, IME_INTERNAL_ACTIVATE,
|
||||
HandleToUlong(hwnd) );
|
||||
|
||||
if (previous)
|
||||
NtUserNotifyWinEvent( EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, 0 );
|
||||
|
|
|
@ -35,13 +35,10 @@ struct user_callbacks
|
|||
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
|
||||
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
|
||||
NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
|
||||
void (CDECL *notify_ime)( HWND hwnd, UINT param );
|
||||
BOOL (CDECL *post_dde_message)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid,
|
||||
DWORD type );
|
||||
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
|
||||
void **buffer, size_t size );
|
||||
BOOL (WINAPI *register_imm)( HWND hwnd );
|
||||
void (WINAPI *unregister_imm)( HWND hwnd );
|
||||
NTSTATUS (CDECL *try_finally)( NTSTATUS (CDECL *func)( void *), void *arg,
|
||||
void (CALLBACK *finally_func)( BOOL ));
|
||||
};
|
||||
|
@ -154,6 +151,7 @@ struct user_thread_info
|
|||
struct received_message_info *receive_info; /* Message being currently received */
|
||||
struct wm_char_mapping_data *wmchar_data; /* Data for WM_CHAR mappings */
|
||||
struct user_key_state_info *key_state; /* Cache of global key state */
|
||||
struct imm_thread_data *imm_thread_data; /* IMM thread data */
|
||||
HKL kbd_layout; /* Current keyboard layout */
|
||||
DWORD kbd_layout_id; /* Current keyboard layout ID */
|
||||
struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */
|
||||
|
@ -273,6 +271,7 @@ WNDPROC get_winproc( WNDPROC proc, BOOL ansi ) DECLSPEC_HIDDEN;
|
|||
void get_winproc_params( struct win_proc_params *params ) DECLSPEC_HIDDEN;
|
||||
struct dce *get_class_dce( struct tagCLASS *class ) DECLSPEC_HIDDEN;
|
||||
struct dce *set_class_dce( struct tagCLASS *class, struct dce *dce ) DECLSPEC_HIDDEN;
|
||||
BOOL needs_ime_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern void register_builtin_classes(void) DECLSPEC_HIDDEN;
|
||||
|
||||
/* cursoricon.c */
|
||||
|
|
|
@ -4818,7 +4818,7 @@ static void thread_detach(void)
|
|||
free( thread_info->rawinput );
|
||||
|
||||
destroy_thread_windows();
|
||||
NtUserDestroyInputContext( thread_info->client_info.default_imc );
|
||||
cleanup_imm_thread();
|
||||
NtClose( thread_info->server_queue );
|
||||
|
||||
exiting_thread_id = 0;
|
||||
|
|
|
@ -837,7 +837,7 @@
|
|||
@ stdcall NtUserDestroyWindow(long)
|
||||
@ stub NtUserDisableImmersiveOwner
|
||||
@ stub NtUserDisableProcessWindowFiltering
|
||||
@ stub NtUserDisableThreadIme
|
||||
@ stdcall NtUserDisableThreadIme(long)
|
||||
@ stub NtUserDiscardPointerFrameMessages
|
||||
@ stdcall NtUserDispatchMessage(ptr)
|
||||
@ stub NtUserDisplayConfigGetDeviceInfo
|
||||
|
|
|
@ -214,6 +214,7 @@ struct unix_funcs
|
|||
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
|
||||
BOOL (WINAPI *pNtUserDestroyMenu)( HMENU handle );
|
||||
BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd );
|
||||
BOOL (WINAPI *pNtUserDisableThreadIme)( DWORD thread_id );
|
||||
LRESULT (WINAPI *pNtUserDispatchMessage)( const MSG *msg );
|
||||
BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y );
|
||||
BOOL (WINAPI *pNtUserDrawCaptionTemp)( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
|
||||
|
@ -393,8 +394,12 @@ extern LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL
|
|||
extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* imm.c */
|
||||
extern void cleanup_imm_thread(void) DECLSPEC_HIDDEN;
|
||||
extern HWND get_default_ime_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HIMC get_default_input_context(void) DECLSPEC_HIDDEN;
|
||||
extern HIMC get_window_input_context( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern BOOL register_imm_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern void unregister_imm_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* input.c */
|
||||
extern BOOL destroy_caret(void) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -4680,12 +4680,7 @@ LRESULT destroy_window( 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);
|
||||
if (user_callbacks) user_callbacks->unregister_imm( hwnd );
|
||||
}
|
||||
unregister_imm_window( hwnd );
|
||||
|
||||
/* free child windows */
|
||||
if ((children = list_window_children( 0, hwnd, NULL, 0 )))
|
||||
|
@ -5262,7 +5257,7 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name,
|
|||
/* create default IME window */
|
||||
|
||||
if (!is_desktop_window( hwnd ) && parent != get_hwnd_message_parent() &&
|
||||
user_callbacks && user_callbacks->register_imm( hwnd ))
|
||||
register_imm_window( hwnd ))
|
||||
{
|
||||
TRACE( "register IME window for %p\n", hwnd );
|
||||
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
|
||||
|
@ -5377,6 +5372,9 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
|
|||
case NtUserCallHwnd_DrawMenuBar:
|
||||
return draw_menu_bar( hwnd );
|
||||
|
||||
case NtUserCallHwnd_GetDefaultImeWindow:
|
||||
return HandleToUlong( get_default_ime_window( hwnd ));
|
||||
|
||||
case NtUserCallHwnd_GetDpiForWindow:
|
||||
return get_dpi_for_window( hwnd );
|
||||
|
||||
|
|
|
@ -849,6 +849,12 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd )
|
|||
return unix_funcs->pNtUserDestroyWindow( hwnd );
|
||||
}
|
||||
|
||||
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id )
|
||||
{
|
||||
if (!unix_funcs) return FALSE;
|
||||
return unix_funcs->pNtUserDisableThreadIme( thread_id );
|
||||
}
|
||||
|
||||
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
|
||||
{
|
||||
if (!unix_funcs) return 0;
|
||||
|
|
|
@ -599,6 +599,7 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
|
|||
BOOL WINAPI NtUserDestroyInputContext( HIMC handle );
|
||||
BOOL WINAPI NtUserDestroyMenu( HMENU menu );
|
||||
BOOL WINAPI NtUserDestroyWindow( HWND hwnd );
|
||||
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id );
|
||||
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg );
|
||||
BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y );
|
||||
BOOL WINAPI NtUserDrawCaptionTemp( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
|
||||
|
@ -1055,6 +1056,7 @@ enum
|
|||
{
|
||||
NtUserCallHwnd_ArrangeIconicWindows,
|
||||
NtUserCallHwnd_DrawMenuBar,
|
||||
NtUserCallHwnd_GetDefaultImeWindow,
|
||||
NtUserCallHwnd_GetDpiForWindow,
|
||||
NtUserCallHwnd_GetParent,
|
||||
NtUserCallHwnd_GetWindowContextHelpId,
|
||||
|
@ -1083,6 +1085,11 @@ static inline DWORD NtUserGetWindowContextHelpId( HWND hwnd )
|
|||
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetWindowContextHelpId );
|
||||
}
|
||||
|
||||
static inline HWND NtUserGetDefaultImeWindow( HWND hwnd )
|
||||
{
|
||||
return UlongToHandle( NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDefaultImeWindow ));
|
||||
}
|
||||
|
||||
static inline UINT NtUserGetDpiForWindow( HWND hwnd )
|
||||
{
|
||||
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDpiForWindow );
|
||||
|
|
Loading…
Reference in a new issue