mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-24 05:46:23 +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;
|
LPARAM lParam;
|
||||||
} TRANSMSG, *LPTRANSMSG;
|
} TRANSMSG, *LPTRANSMSG;
|
||||||
|
|
||||||
typedef struct _tagIMMThreadData {
|
|
||||||
struct list entry;
|
|
||||||
DWORD threadID;
|
|
||||||
HWND hwndDefault;
|
|
||||||
BOOL disableIME;
|
|
||||||
DWORD windowRefs;
|
|
||||||
} IMMThreadData;
|
|
||||||
|
|
||||||
struct coinit_spy
|
struct coinit_spy
|
||||||
{
|
{
|
||||||
IInitializeSpy IInitializeSpy_iface;
|
IInitializeSpy IInitializeSpy_iface;
|
||||||
|
@ -123,20 +115,9 @@ struct coinit_spy
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct list ImmHklList = LIST_INIT(ImmHklList);
|
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 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)
|
static inline BOOL is_himc_ime_unicode(const InputContextData *data)
|
||||||
{
|
{
|
||||||
return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
|
return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
|
||||||
|
@ -412,38 +393,6 @@ static void imm_coinit_thread(void)
|
||||||
spy->apt_flags |= IMM_APT_CREATED;
|
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)
|
static BOOL IMM_IsDefaultContext(HIMC imc)
|
||||||
{
|
{
|
||||||
InputContextData *data = get_imc_data(imc);
|
InputContextData *data = get_imc_data(imc);
|
||||||
|
@ -490,21 +439,6 @@ static BOOL free_input_context_data(HIMC hIMC)
|
||||||
static void IMM_FreeThreadData(void)
|
static void IMM_FreeThreadData(void)
|
||||||
{
|
{
|
||||||
struct coinit_spy *spy;
|
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);
|
free_input_context_data(NtUserGetThreadInfo()->default_imc);
|
||||||
if ((spy = get_thread_coinit_spy()))
|
if ((spy = get_thread_coinit_spy()))
|
||||||
|
@ -981,62 +915,6 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
||||||
return FALSE;
|
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.@)
|
* ImmEnumRegisterWordA (IMM32.@)
|
||||||
*/
|
*/
|
||||||
|
@ -1816,107 +1694,12 @@ BOOL WINAPI ImmGetConversionStatus(
|
||||||
return TRUE;
|
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.@)
|
* ImmGetDefaultIMEWnd (IMM32.@)
|
||||||
*/
|
*/
|
||||||
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
||||||
{
|
{
|
||||||
HWND ret;
|
return NtUserGetDefaultImeWindow(hWnd);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
@ stdcall ImmDestroyContext(long)
|
@ stdcall ImmDestroyContext(long)
|
||||||
@ stdcall ImmDestroyIMCC(long)
|
@ stdcall ImmDestroyIMCC(long)
|
||||||
@ stdcall ImmDestroySoftKeyboard(long)
|
@ stdcall ImmDestroySoftKeyboard(long)
|
||||||
@ stdcall ImmDisableIME(long)
|
@ stdcall ImmDisableIME(long) NtUserDisableThreadIme
|
||||||
@ stdcall ImmDisableIme(long) ImmDisableIME
|
@ stdcall ImmDisableIme(long) NtUserDisableThreadIme
|
||||||
@ stdcall ImmDisableLegacyIME()
|
@ stdcall ImmDisableLegacyIME()
|
||||||
@ stdcall ImmDisableTextFrameService(long)
|
@ stdcall ImmDisableTextFrameService(long)
|
||||||
@ stdcall ImmEnumInputContext(long ptr long)
|
@ stdcall ImmEnumInputContext(long ptr long)
|
||||||
|
@ -115,5 +115,3 @@
|
||||||
################################################################
|
################################################################
|
||||||
# Wine internal extensions
|
# Wine internal extensions
|
||||||
@ stdcall __wine_ime_wnd_proc(long long long long long)
|
@ 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");
|
ok(IsWindow(def), "not a window\n");
|
||||||
def2 = ImmGetDefaultIMEWnd(hwnd);
|
def2 = ImmGetDefaultIMEWnd(hwnd);
|
||||||
todo_wine
|
|
||||||
ok(def2 == def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def2);
|
ok(def2 == def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def2);
|
||||||
ok(IsWindow(def), "not a window\n");
|
ok(IsWindow(def), "not a window\n");
|
||||||
msg_spy_pump_msg_queue();
|
msg_spy_pump_msg_queue();
|
||||||
todo_wine
|
|
||||||
ok(!IsWindow(def), "window is still valid\n");
|
ok(!IsWindow(def), "window is still valid\n");
|
||||||
def = ImmGetDefaultIMEWnd(hwnd);
|
def = ImmGetDefaultIMEWnd(hwnd);
|
||||||
ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def);
|
ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def);
|
||||||
|
|
|
@ -39,8 +39,6 @@ BOOL WINAPI ImmSetActiveContext(HWND, HIMC, BOOL);
|
||||||
|
|
||||||
#define IMM_INIT_MAGIC 0x19650412
|
#define IMM_INIT_MAGIC 0x19650412
|
||||||
static LRESULT (WINAPI *imm_ime_wnd_proc)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi);
|
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 */
|
/* USER signal proc flags and codes */
|
||||||
/* See UserSignalProc for comments */
|
/* See UserSignalProc for comments */
|
||||||
|
@ -328,8 +326,6 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
||||||
|
|
||||||
/* this part is not compatible with native imm32.dll */
|
/* this part is not compatible with native imm32.dll */
|
||||||
imm_ime_wnd_proc = (void*)GetProcAddress(imm32, "__wine_ime_wnd_proc");
|
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)
|
if (!imm_ime_wnd_proc)
|
||||||
FIXME("native imm32.dll not supported\n");
|
FIXME("native imm32.dll not supported\n");
|
||||||
return TRUE;
|
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,
|
static NTSTATUS try_finally( NTSTATUS (CDECL *func)( void *), void *arg,
|
||||||
void (CALLBACK *finally_func)( BOOL ))
|
void (CALLBACK *finally_func)( BOOL ))
|
||||||
{
|
{
|
||||||
|
@ -152,11 +136,8 @@ static const struct user_callbacks user_funcs =
|
||||||
ImmProcessKey,
|
ImmProcessKey,
|
||||||
ImmTranslateMessage,
|
ImmTranslateMessage,
|
||||||
NtWaitForMultipleObjects,
|
NtWaitForMultipleObjects,
|
||||||
notify_ime,
|
|
||||||
post_dde_message,
|
post_dde_message,
|
||||||
unpack_dde_message,
|
unpack_dde_message,
|
||||||
register_imm,
|
|
||||||
unregister_imm,
|
|
||||||
try_finally,
|
try_finally,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,6 @@ struct wm_char_mapping_data
|
||||||
MSG get_msg;
|
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)
|
static inline struct user_thread_info *get_user_thread_info(void)
|
||||||
{
|
{
|
||||||
return (struct user_thread_info *)NtCurrentTeb()->Win32ClientInfo;
|
return (struct user_thread_info *)NtCurrentTeb()->Win32ClientInfo;
|
||||||
|
|
|
@ -1007,6 +1007,18 @@ WORD get_class_word( HWND hwnd, INT offset )
|
||||||
return retvalue;
|
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)
|
static void register_builtins(void)
|
||||||
{
|
{
|
||||||
void *ret_ptr;
|
void *ret_ptr;
|
||||||
|
|
|
@ -1157,6 +1157,7 @@ static struct unix_funcs unix_funcs =
|
||||||
NtUserDestroyCursor,
|
NtUserDestroyCursor,
|
||||||
NtUserDestroyMenu,
|
NtUserDestroyMenu,
|
||||||
NtUserDestroyWindow,
|
NtUserDestroyWindow,
|
||||||
|
NtUserDisableThreadIme,
|
||||||
NtUserDispatchMessage,
|
NtUserDispatchMessage,
|
||||||
NtUserDragDetect,
|
NtUserDragDetect,
|
||||||
NtUserDrawCaptionTemp,
|
NtUserDrawCaptionTemp,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Input Context implementation
|
* Input Context implementation
|
||||||
*
|
*
|
||||||
|
* Copyright 1998 Patrik Stridvall
|
||||||
|
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
||||||
* Copyright 2022 Jacek Caban for CodeWeavers
|
* Copyright 2022 Jacek Caban for CodeWeavers
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -22,6 +24,7 @@
|
||||||
#pragma makedep unix
|
#pragma makedep unix
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
#include "win32u_private.h"
|
#include "win32u_private.h"
|
||||||
#include "ntuser_private.h"
|
#include "ntuser_private.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
@ -36,6 +39,18 @@ struct imc
|
||||||
UINT_PTR client_ptr;
|
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 )
|
static struct imc *get_imc_ptr( HIMC handle )
|
||||||
{
|
{
|
||||||
|
@ -215,3 +230,164 @@ HIMC get_window_input_context( HWND hwnd )
|
||||||
release_win_ptr( win );
|
release_win_ptr( win );
|
||||||
return ret;
|
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 )
|
static HWND set_focus_window( HWND hwnd )
|
||||||
{
|
{
|
||||||
HWND previous = 0;
|
HWND previous = 0, ime_hwnd;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
SERVER_START_REQ( set_focus_window )
|
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 );
|
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 */
|
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);
|
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)
|
if (previous)
|
||||||
NtUserNotifyWinEvent( EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, 0 );
|
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 *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
|
||||||
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
|
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
|
||||||
NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
|
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,
|
BOOL (CDECL *post_dde_message)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid,
|
||||||
DWORD type );
|
DWORD type );
|
||||||
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
|
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
|
||||||
void **buffer, size_t size );
|
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,
|
NTSTATUS (CDECL *try_finally)( NTSTATUS (CDECL *func)( void *), void *arg,
|
||||||
void (CALLBACK *finally_func)( BOOL ));
|
void (CALLBACK *finally_func)( BOOL ));
|
||||||
};
|
};
|
||||||
|
@ -154,6 +151,7 @@ struct user_thread_info
|
||||||
struct received_message_info *receive_info; /* Message being currently received */
|
struct received_message_info *receive_info; /* Message being currently received */
|
||||||
struct wm_char_mapping_data *wmchar_data; /* Data for WM_CHAR mappings */
|
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 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 */
|
HKL kbd_layout; /* Current keyboard layout */
|
||||||
DWORD kbd_layout_id; /* Current keyboard layout ID */
|
DWORD kbd_layout_id; /* Current keyboard layout ID */
|
||||||
struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */
|
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;
|
void get_winproc_params( struct win_proc_params *params ) DECLSPEC_HIDDEN;
|
||||||
struct dce *get_class_dce( struct tagCLASS *class ) 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;
|
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;
|
extern void register_builtin_classes(void) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* cursoricon.c */
|
/* cursoricon.c */
|
||||||
|
|
|
@ -4818,7 +4818,7 @@ static void thread_detach(void)
|
||||||
free( thread_info->rawinput );
|
free( thread_info->rawinput );
|
||||||
|
|
||||||
destroy_thread_windows();
|
destroy_thread_windows();
|
||||||
NtUserDestroyInputContext( thread_info->client_info.default_imc );
|
cleanup_imm_thread();
|
||||||
NtClose( thread_info->server_queue );
|
NtClose( thread_info->server_queue );
|
||||||
|
|
||||||
exiting_thread_id = 0;
|
exiting_thread_id = 0;
|
||||||
|
|
|
@ -837,7 +837,7 @@
|
||||||
@ stdcall NtUserDestroyWindow(long)
|
@ stdcall NtUserDestroyWindow(long)
|
||||||
@ stub NtUserDisableImmersiveOwner
|
@ stub NtUserDisableImmersiveOwner
|
||||||
@ stub NtUserDisableProcessWindowFiltering
|
@ stub NtUserDisableProcessWindowFiltering
|
||||||
@ stub NtUserDisableThreadIme
|
@ stdcall NtUserDisableThreadIme(long)
|
||||||
@ stub NtUserDiscardPointerFrameMessages
|
@ stub NtUserDiscardPointerFrameMessages
|
||||||
@ stdcall NtUserDispatchMessage(ptr)
|
@ stdcall NtUserDispatchMessage(ptr)
|
||||||
@ stub NtUserDisplayConfigGetDeviceInfo
|
@ stub NtUserDisplayConfigGetDeviceInfo
|
||||||
|
|
|
@ -214,6 +214,7 @@ struct unix_funcs
|
||||||
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
|
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
|
||||||
BOOL (WINAPI *pNtUserDestroyMenu)( HMENU handle );
|
BOOL (WINAPI *pNtUserDestroyMenu)( HMENU handle );
|
||||||
BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd );
|
BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd );
|
||||||
|
BOOL (WINAPI *pNtUserDisableThreadIme)( DWORD thread_id );
|
||||||
LRESULT (WINAPI *pNtUserDispatchMessage)( const MSG *msg );
|
LRESULT (WINAPI *pNtUserDispatchMessage)( const MSG *msg );
|
||||||
BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y );
|
BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y );
|
||||||
BOOL (WINAPI *pNtUserDrawCaptionTemp)( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
|
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;
|
extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* imm.c */
|
/* 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_default_input_context(void) DECLSPEC_HIDDEN;
|
||||||
extern HIMC get_window_input_context( HWND hwnd ) 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 */
|
/* input.c */
|
||||||
extern BOOL destroy_caret(void) DECLSPEC_HIDDEN;
|
extern BOOL destroy_caret(void) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -4680,12 +4680,7 @@ LRESULT destroy_window( HWND hwnd )
|
||||||
|
|
||||||
TRACE( "%p\n", hwnd );
|
TRACE( "%p\n", hwnd );
|
||||||
|
|
||||||
/* destroy default IME window */
|
unregister_imm_window( hwnd );
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free child windows */
|
/* free child windows */
|
||||||
if ((children = list_window_children( 0, hwnd, NULL, 0 )))
|
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 */
|
/* create default IME window */
|
||||||
|
|
||||||
if (!is_desktop_window( hwnd ) && parent != get_hwnd_message_parent() &&
|
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 );
|
TRACE( "register IME window for %p\n", hwnd );
|
||||||
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
|
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
|
||||||
|
@ -5377,6 +5372,9 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
|
||||||
case NtUserCallHwnd_DrawMenuBar:
|
case NtUserCallHwnd_DrawMenuBar:
|
||||||
return draw_menu_bar( hwnd );
|
return draw_menu_bar( hwnd );
|
||||||
|
|
||||||
|
case NtUserCallHwnd_GetDefaultImeWindow:
|
||||||
|
return HandleToUlong( get_default_ime_window( hwnd ));
|
||||||
|
|
||||||
case NtUserCallHwnd_GetDpiForWindow:
|
case NtUserCallHwnd_GetDpiForWindow:
|
||||||
return get_dpi_for_window( hwnd );
|
return get_dpi_for_window( hwnd );
|
||||||
|
|
||||||
|
|
|
@ -849,6 +849,12 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd )
|
||||||
return unix_funcs->pNtUserDestroyWindow( 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 )
|
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
|
||||||
{
|
{
|
||||||
if (!unix_funcs) return 0;
|
if (!unix_funcs) return 0;
|
||||||
|
|
|
@ -599,6 +599,7 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
|
||||||
BOOL WINAPI NtUserDestroyInputContext( HIMC handle );
|
BOOL WINAPI NtUserDestroyInputContext( HIMC handle );
|
||||||
BOOL WINAPI NtUserDestroyMenu( HMENU menu );
|
BOOL WINAPI NtUserDestroyMenu( HMENU menu );
|
||||||
BOOL WINAPI NtUserDestroyWindow( HWND hwnd );
|
BOOL WINAPI NtUserDestroyWindow( HWND hwnd );
|
||||||
|
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id );
|
||||||
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg );
|
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg );
|
||||||
BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y );
|
BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y );
|
||||||
BOOL WINAPI NtUserDrawCaptionTemp( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
|
BOOL WINAPI NtUserDrawCaptionTemp( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
|
||||||
|
@ -1055,6 +1056,7 @@ enum
|
||||||
{
|
{
|
||||||
NtUserCallHwnd_ArrangeIconicWindows,
|
NtUserCallHwnd_ArrangeIconicWindows,
|
||||||
NtUserCallHwnd_DrawMenuBar,
|
NtUserCallHwnd_DrawMenuBar,
|
||||||
|
NtUserCallHwnd_GetDefaultImeWindow,
|
||||||
NtUserCallHwnd_GetDpiForWindow,
|
NtUserCallHwnd_GetDpiForWindow,
|
||||||
NtUserCallHwnd_GetParent,
|
NtUserCallHwnd_GetParent,
|
||||||
NtUserCallHwnd_GetWindowContextHelpId,
|
NtUserCallHwnd_GetWindowContextHelpId,
|
||||||
|
@ -1083,6 +1085,11 @@ static inline DWORD NtUserGetWindowContextHelpId( HWND hwnd )
|
||||||
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetWindowContextHelpId );
|
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetWindowContextHelpId );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline HWND NtUserGetDefaultImeWindow( HWND hwnd )
|
||||||
|
{
|
||||||
|
return UlongToHandle( NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDefaultImeWindow ));
|
||||||
|
}
|
||||||
|
|
||||||
static inline UINT NtUserGetDpiForWindow( HWND hwnd )
|
static inline UINT NtUserGetDpiForWindow( HWND hwnd )
|
||||||
{
|
{
|
||||||
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDpiForWindow );
|
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDpiForWindow );
|
||||||
|
|
Loading…
Reference in a new issue