From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/dllmain.c | 38 ++++++++++++++++++++++++++++-- dlls/winex11.drv/event.c | 15 ++++-------- dlls/winex11.drv/unixlib.h | 42 ++++++++++++++++++++++------------ dlls/winex11.drv/window.c | 2 +- dlls/winex11.drv/x11drv.h | 16 +++++++++---- dlls/winex11.drv/x11drv_main.c | 15 ++++++++++++ dlls/winex11.drv/xdnd.c | 41 ++++++++++----------------------- include/ntuser.h | 3 +++ 8 files changed, 110 insertions(+), 62 deletions(-)
diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 6a9f4a57273..751b6ec08a4 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -116,23 +116,57 @@ static DWORD WINAPI clipboard_thread( void *arg ) }
-void X11DRV_InitClipboard(void) +static NTSTATUS x11drv_clipboard_init( UINT arg ) { DWORD id; HANDLE thread = CreateThread( NULL, 0, clipboard_thread, NULL, 0, &id );
if (thread) CloseHandle( thread ); else ERR( "failed to create clipboard thread\n" ); + return 0; }
+typedef NTSTATUS (*callback_func)( UINT arg ); +static const callback_func callback_funcs[] = +{ + x11drv_clipboard_init, + x11drv_dnd_drop_event, + x11drv_dnd_leave_event, +}; + +C_ASSERT( ARRAYSIZE(callback_funcs) == client_funcs_count ); + +static NTSTATUS WINAPI x11drv_callback( void *arg, ULONG size ) +{ + struct client_callback_params *params = arg; + return callback_funcs[params->id]( params->arg ); +} + +typedef NTSTATUS (WINAPI *kernel_callback)( void *params, ULONG size ); +static const kernel_callback kernel_callbacks[] = +{ + x11drv_callback, + x11drv_dnd_enter_event, + x11drv_dnd_position_event, + x11drv_dnd_post_drop, +}; + +C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last ); + BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) { + void **callback_table; + if (reason != DLL_PROCESS_ATTACH) return TRUE;
DisableThreadLibraryCalls( instance ); x11drv_module = instance; - return !X11DRV_CALL( init, NULL ); + if (X11DRV_CALL( init, NULL )) return FALSE; + + callback_table = NtCurrentTeb()->Peb->KernelCallbackTable; + memcpy( callback_table + NtUserDriverCallbackFirst, kernel_callbacks, sizeof(kernel_callbacks) ); + return TRUE; }
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 105caab5deb..cefc86d0902 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1479,7 +1479,7 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt ) static void post_drop( HWND hwnd, DROPFILES *drop, ULONG size ) { drop->fWide = HandleToUlong( hwnd ); /* abuse fWide to pass window handle */ - x11drv_post_drop( drop, size ); + x11drv_client_func( client_func_dnd_post_drop, drop, size ); }
/********************************************************************** @@ -1744,7 +1744,7 @@ static void handle_xdnd_enter_event( HWND hWnd, XClientMessageEvent *event ) xdndtypes, count, &size ); if (data) { - handle_dnd_enter_event( data, size ); + x11drv_client_func( client_func_dnd_enter_event, data, size ); free( data ); }
@@ -1795,12 +1795,11 @@ static void handle_xdnd_position_event( HWND hwnd, XClientMessageEvent *event ) XClientMessageEvent e; DWORD effect;
- params.type = DND_POSITION_EVENT; params.hwnd = hwnd; params.point = root_to_virtual_screen( event->data.l[2] >> 16, event->data.l[2] & 0xFFFF ); params.effect = effect = xdnd_action_to_drop_effect( event->data.l[4] );
- effect = handle_dnd_event( ¶ms ); + effect = x11drv_client_func( client_func_dnd_position_event, ¶ms, sizeof(params) );
TRACE( "actionRequested(%ld) chosen(0x%x) at x(%d),y(%d)\n", event->data.l[4], effect, params.point.x, params.point.y ); @@ -1825,13 +1824,10 @@ static void handle_xdnd_position_event( HWND hwnd, XClientMessageEvent *event )
static void handle_xdnd_drop_event( HWND hwnd, XClientMessageEvent *event ) { - struct dnd_drop_event_params params; XClientMessageEvent e; DWORD effect;
- params.type = DND_DROP_EVENT; - params.hwnd = hwnd; - effect = handle_dnd_event( ¶ms ); + effect = x11drv_client_call( client_dnd_drop_event, HandleToUlong( hwnd ));
/* Tell the target we are finished. */ memset( &e, 0, sizeof(e) ); @@ -1849,8 +1845,7 @@ static void handle_xdnd_drop_event( HWND hwnd, XClientMessageEvent *event )
static void handle_xdnd_leave_event( HWND hwnd, XClientMessageEvent *event ) { - UINT type = DND_LEAVE_EVENT; - handle_dnd_event( &type ); + x11drv_client_call( client_dnd_leave_event, 0 ); }
diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 2a957af0f56..ec5f75a1697 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -68,33 +68,45 @@ struct xim_preedit_state_params BOOL open; };
-/* DnD support */ +/* driver client callbacks exposed with KernelCallbackTable interface */ +enum x11drv_client_funcs +{ + client_func_callback = NtUserDriverCallbackFirst, + client_func_dnd_enter_event, + client_func_dnd_position_event, + client_func_dnd_post_drop, + client_func_last +};
-struct format_entry +C_ASSERT( client_func_last <= NtUserDriverCallbackLast + 1 ); + +/* simplified interface for client callbacks requiring only a single UINT parameter */ +enum client_callback { - UINT format; - UINT size; - char data[1]; + client_clipboard_init, + client_dnd_drop_event, + client_dnd_leave_event, + client_funcs_count };
-enum dnd_event_type +/* x11drv_callback params */ +struct client_callback_params { - DND_DROP_EVENT, - DND_LEAVE_EVENT, - DND_POSITION_EVENT, + UINT id; + UINT arg; };
-/* DND_DROP_EVENT params */ -struct dnd_drop_event_params +/* x11drv_dnd_enter_event and x11drv_dnd_post_drop params */ +struct format_entry { - UINT type; - HWND hwnd; + UINT format; + UINT size; + char data[1]; };
-/* DND_POSITION_EVENT params */ +/* x11drv_dnd_position_event params */ struct dnd_position_event_params { - UINT type; HWND hwnd; POINT point; DWORD effect; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index de52023c467..7ccec4ee4ec 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1904,7 +1904,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd ) CWOverrideRedirect | CWEventMask, &attr ); XFlush( data->display ); NtUserSetProp( hwnd, clip_window_prop, (HANDLE)data->clip_window ); - X11DRV_InitClipboard(); + x11drv_client_call( client_clipboard_init, 0 ); X11DRV_DisplayDevices_RegisterEventHandlers(); } return TRUE; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index c6e5044c110..02eb67c9cc2 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -296,9 +296,6 @@ extern BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp, extern void IME_SetResultString(LPWSTR lpResult, DWORD dwResultlen) DECLSPEC_HIDDEN;
-extern void handle_dnd_enter_event( struct format_entry *formats, ULONG size ) DECLSPEC_HIDDEN; -extern UINT handle_dnd_event( void *params ) DECLSPEC_HIDDEN; - extern struct format_entry *import_xdnd_selection( Display *display, Window win, Atom selection, Atom *targets, UINT count, size_t *size ) DECLSPEC_HIDDEN; @@ -677,7 +674,6 @@ extern XContext winContext DECLSPEC_HIDDEN; /* X context to associate an X cursor to a Win32 cursor handle */ extern XContext cursor_context DECLSPEC_HIDDEN;
-extern void X11DRV_InitClipboard(void) DECLSPEC_HIDDEN; extern void X11DRV_SetFocus( HWND hwnd ) DECLSPEC_HIDDEN; extern void set_window_cursor( Window window, HCURSOR handle ) DECLSPEC_HIDDEN; extern void sync_window_cursor( Window window ) DECLSPEC_HIDDEN; @@ -850,7 +846,17 @@ extern NTSTATUS x11drv_tablet_info( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_xim_preedit_state( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_xim_reset( void *arg ) DECLSPEC_HIDDEN;
-extern NTSTATUS WINAPI x11drv_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; + +extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; + + +extern NTSTATUS x11drv_client_func( enum x11drv_client_funcs func, const void *params, + ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_client_call( enum client_callback func, UINT arg ) DECLSPEC_HIDDEN;
/* GDI helpers */
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 5347bc7c1a5..749fe2f761b 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -957,6 +957,21 @@ NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDP }
+NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size ) +{ + /* FIXME: use KeUserModeCallback instead */ + NTSTATUS (WINAPI *func)( const void *, ULONG ) = ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[id]; + return func( params, size ); +} + + +NTSTATUS x11drv_client_call( enum client_callback func, UINT arg ) +{ + struct client_callback_params params = { .id = func, .arg = arg }; + return x11drv_client_func( client_func_callback, ¶ms, sizeof(params) ); +} + + const unixlib_entry_t __wine_unix_call_funcs[] = { x11drv_clipboard_message, diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c index 45205c836be..975fe7a114b 100644 --- a/dlls/winex11.drv/xdnd.c +++ b/dlls/winex11.drv/xdnd.c @@ -176,12 +176,13 @@ static HWND window_accepting_files(HWND hwnd) }
/************************************************************************** - * X11DRV_XDND_PositionEvent + * x11drv_dnd_position_event * * Handle an XdndPosition event. */ -static BOOL handle_position_event( struct dnd_position_event_params *params ) +NTSTATUS WINAPI x11drv_dnd_position_event( void *arg, ULONG size ) { + struct dnd_position_event_params *params = arg; int accept = 0; /* Assume we're not accepting */ IDropTarget *dropTarget = NULL; DWORD effect = params->effect; @@ -264,7 +265,7 @@ static BOOL handle_position_event( struct dnd_position_event_params *params ) return accept ? effect : 0; }
-static DWORD handle_drop_event( struct dnd_drop_event_params *params ) +NTSTATUS x11drv_dnd_drop_event( UINT arg ) { IDropTarget *dropTarget; DWORD effect = XDNDDropEffect; @@ -318,7 +319,7 @@ static DWORD handle_drop_event( struct dnd_drop_event_params *params ) /* Only send WM_DROPFILES if Drop didn't succeed or DROPEFFECT_NONE was set. * Doing both causes winamp to duplicate the dropped files (#29081) */
- HWND hwnd_drop = window_accepting_files(window_from_point_dnd( params->hwnd, XDNDxy )); + HWND hwnd_drop = window_accepting_files(window_from_point_dnd( UlongToHandle(arg), XDNDxy ));
if (hwnd_drop && X11DRV_XDND_HasHDROP()) { @@ -338,11 +339,11 @@ static DWORD handle_drop_event( struct dnd_drop_event_params *params ) }
/************************************************************************** - * X11DRV_XDND_LeaveEvent + * x11drv_dnd_leave_event * * Handle an XdndLeave event. */ -static NTSTATUS handle_leave_event(void) +NTSTATUS x11drv_dnd_leave_event( UINT arg ) { IDropTarget *dropTarget;
@@ -367,10 +368,11 @@ static NTSTATUS handle_leave_event(void)
/************************************************************************** - * handle_dnd_enter_event + * x11drv_dnd_enter_event */ -void handle_dnd_enter_event( struct format_entry *formats, ULONG size ) +NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) { + struct format_entry *formats = params; XDNDAccepted = FALSE; X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
@@ -379,6 +381,7 @@ void handle_dnd_enter_event( struct format_entry *formats, ULONG size ) memcpy( xdnd_formats, formats, size ); xdnd_formats_end = (struct format_entry *)((char *)xdnd_formats + size); } + return 0; }
@@ -729,27 +732,7 @@ static IDataObjectVtbl xdndDataObjectVtbl =
static IDataObject XDNDDataObject = { &xdndDataObjectVtbl };
-UINT handle_dnd_event( void *params ) -{ - - switch (*(UINT *)params) - { - case DND_DROP_EVENT: - return handle_drop_event( params ); - - case DND_LEAVE_EVENT: - return handle_leave_event(); - - case DND_POSITION_EVENT: - return handle_position_event( params ); - - default: - ERR( "invalid event\n" ); - return 0; - } -} - -NTSTATUS WINAPI x11drv_post_drop( void *data, ULONG size ) +NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) { HDROP handle;
diff --git a/include/ntuser.h b/include/ntuser.h index d11cffb8950..fdc43cac8ed 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -42,6 +42,9 @@ enum /* Vulkan support */ NtUserCallVulkanDebugReportCallback, NtUserCallVulkanDebugUtilsCallback, + /* Driver-specific callbacks */ + NtUserDriverCallbackFirst, + NtUserDriverCallbackLast = NtUserDriverCallbackFirst + 10, NtUserCallCount };
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/dllmain.c | 7 +++++ dlls/winex11.drv/ime.c | 58 ++++++++++++++++++++++---------------- dlls/winex11.drv/unixlib.h | 7 +++++ dlls/winex11.drv/x11drv.h | 19 +++++-------- dlls/winex11.drv/xim.c | 27 ++++++++---------- 5 files changed, 66 insertions(+), 52 deletions(-)
diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 751b6ec08a4..bbfcefe05e3 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -133,6 +133,11 @@ static const callback_func callback_funcs[] = x11drv_clipboard_init, x11drv_dnd_drop_event, x11drv_dnd_leave_event, + x11drv_ime_get_cursor_pos, + x11drv_ime_set_composition_status, + x11drv_ime_set_cursor_pos, + x11drv_ime_set_open_status, + x11drv_ime_update_association, };
C_ASSERT( ARRAYSIZE(callback_funcs) == client_funcs_count ); @@ -150,6 +155,8 @@ static const kernel_callback kernel_callbacks[] = x11drv_dnd_enter_event, x11drv_dnd_position_event, x11drv_dnd_post_drop, + x11drv_ime_set_composition_string, + x11drv_ime_set_result, };
C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last ); diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 1656601577d..b2b61a17604 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -916,15 +916,16 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
/* Interfaces to XIM and other parts of winex11drv */
-void IME_SetOpenStatus(BOOL fOpen) +NTSTATUS x11drv_ime_set_open_status( UINT open ) { HIMC imc;
imc = RealIMC(FROM_X11); - ImmSetOpenStatus(imc, fOpen); + ImmSetOpenStatus(imc, open); + return 0; }
-void IME_SetCompositionStatus(BOOL fOpen) +NTSTATUS x11drv_ime_set_composition_status( UINT open ) { HIMC imc; LPINPUTCONTEXT lpIMC; @@ -933,28 +934,29 @@ void IME_SetCompositionStatus(BOOL fOpen) imc = RealIMC(FROM_X11); lpIMC = ImmLockIMC(imc); if (lpIMC == NULL) - return; + return 0;
myPrivate = ImmLockIMCC(lpIMC->hPrivate);
- if (fOpen && !myPrivate->bInComposition) + if (open && !myPrivate->bInComposition) { GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0); } - else if (!fOpen && myPrivate->bInComposition) + else if (!open && myPrivate->bInComposition) { ShowWindow(myPrivate->hwndDefault, SW_HIDE); ImmDestroyIMCC(lpIMC->hCompStr); lpIMC->hCompStr = ImeCreateBlankCompStr(); GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0); } - myPrivate->bInComposition = fOpen; + myPrivate->bInComposition = open;
ImmUnlockIMCC(lpIMC->hPrivate); ImmUnlockIMC(imc); + return 0; }
-INT IME_GetCursorPos(void) +NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) { LPINPUTCONTEXT lpIMC; INT rc = 0; @@ -974,68 +976,73 @@ INT IME_GetCursorPos(void) return rc; }
-void IME_SetCursorPos(DWORD pos) +NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) { LPINPUTCONTEXT lpIMC; LPCOMPOSITIONSTRING compstr;
if (!hSelectedFrom) - return; + return 0;
lpIMC = LockRealIMC(FROM_X11); if (!lpIMC) - return; + return 0;
compstr = ImmLockIMCC(lpIMC->hCompStr); if (!compstr) { UnlockRealIMC(FROM_X11); - return; + return 0; }
compstr->dwCursorPos = pos; ImmUnlockIMCC(lpIMC->hCompStr); UnlockRealIMC(FROM_X11); GenerateIMEMessage(FROM_X11, WM_IME_COMPOSITION, pos, GCS_CURSORPOS); - return; + return 0; }
-void IME_UpdateAssociation(HWND focus) +NTSTATUS x11drv_ime_update_association( UINT arg ) { - ImmGetContext(focus); + HWND focus = UlongToHandle( arg );
- if (!focus || !hSelectedFrom) - return; + ImmGetContext(focus);
- ImmAssociateContext(focus,RealIMC(FROM_X11)); + if (focus && hSelectedFrom) + ImmAssociateContext(focus,RealIMC(FROM_X11)); + return 0; }
-BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, - LPCVOID lpRead, DWORD dwReadLen) +NTSTATUS WINAPI x11drv_ime_set_composition_string( void *param, ULONG size ) { - return ImeSetCompositionString(FROM_X11, dwIndex, lpComp, dwCompLen, - lpRead, dwReadLen); + return ImeSetCompositionString(FROM_X11, SCS_SETSTR, param, size, NULL, 0); }
-void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen) +NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG len ) { + WCHAR *lpResult = params; HIMC imc; LPINPUTCONTEXT lpIMC; HIMCC newCompStr; LPIMEPRIVATE myPrivate; BOOL inComp; + HWND focus; + + len /= sizeof(WCHAR); + if ((focus = GetFocus())) + x11drv_ime_update_association( HandleToUlong( focus ));
imc = RealIMC(FROM_X11); lpIMC = ImmLockIMC(imc); if (lpIMC == NULL) - return; + return 0;
newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0); ImmDestroyIMCC(lpIMC->hCompStr); lpIMC->hCompStr = newCompStr;
- newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, dwResultLen); + newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, len); ImmDestroyIMCC(lpIMC->hCompStr); lpIMC->hCompStr = newCompStr;
@@ -1057,6 +1064,7 @@ void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen) ImmSetOpenStatus(imc, FALSE);
ImmUnlockIMC(imc); + return 0; }
/***** diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index ec5f75a1697..fe3b430dc87 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -75,6 +75,8 @@ enum x11drv_client_funcs client_func_dnd_enter_event, client_func_dnd_position_event, client_func_dnd_post_drop, + client_func_ime_set_composition_string, + client_func_ime_set_result, client_func_last };
@@ -86,6 +88,11 @@ enum client_callback client_clipboard_init, client_dnd_drop_event, client_dnd_leave_event, + client_ime_get_cursor_pos, + client_ime_set_composition_status, + client_ime_set_cursor_pos, + client_ime_set_open_status, + client_ime_update_association, client_funcs_count };
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 02eb67c9cc2..3986733782a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -284,18 +284,6 @@ extern const struct gdi_dc_funcs *X11DRV_XRender_Init(void) DECLSPEC_HIDDEN; extern struct opengl_funcs *get_glx_driver(UINT) DECLSPEC_HIDDEN; extern const struct vulkan_funcs *get_vulkan_driver(UINT) DECLSPEC_HIDDEN;
-/* IME support */ -extern void IME_SetOpenStatus(BOOL fOpen) DECLSPEC_HIDDEN; -extern void IME_SetCompositionStatus(BOOL fOpen) DECLSPEC_HIDDEN; -extern INT IME_GetCursorPos(void) DECLSPEC_HIDDEN; -extern void IME_SetCursorPos(DWORD pos) DECLSPEC_HIDDEN; -extern void IME_UpdateAssociation(HWND focus) DECLSPEC_HIDDEN; -extern BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp, - DWORD dwCompLen, LPCVOID lpRead, - DWORD dwReadLen) DECLSPEC_HIDDEN; -extern void IME_SetResultString(LPWSTR lpResult, DWORD dwResultlen) DECLSPEC_HIDDEN; - - extern struct format_entry *import_xdnd_selection( Display *display, Window win, Atom selection, Atom *targets, UINT count, size_t *size ) DECLSPEC_HIDDEN; @@ -849,9 +837,16 @@ extern NTSTATUS x11drv_xim_reset( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI x11drv_ime_set_composition_string( void *params, ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_ime_set_open_status( UINT open ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_client_func( enum x11drv_client_funcs func, const void *params, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 4b63a24cccf..595fb31fe0b 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -89,25 +89,21 @@ static void X11DRV_ImmSetInternalString(DWORD dwOffset, if (lpComp) memcpy(ptr_new, lpComp, byte_length); dwCompStringLength += byte_expansion;
- IME_SetCompositionString(SCS_SETSTR, CompositionString, - dwCompStringLength, NULL, 0); + x11drv_client_func( client_func_ime_set_composition_string, + CompositionString, dwCompStringLength ); }
void X11DRV_XIMLookupChars( const char *str, DWORD count ) { WCHAR *output; DWORD len; - HWND focus;
TRACE("%p %u\n", str, count);
if (!(output = malloc( count * sizeof(WCHAR) ))) return; len = ntdll_umbstowcs( str, count, output, count );
- if ((focus = GetFocus())) - IME_UpdateAssociation(focus); - - IME_SetResultString( output, len ); + x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); free( output ); }
@@ -120,21 +116,22 @@ static BOOL XIMPreEditStateNotifyCallback(XIC xic, XPointer p, XPointer data) switch (state) { case XIMPreeditEnable: - IME_SetOpenStatus(TRUE); + x11drv_client_call( client_ime_set_open_status, TRUE ); break; case XIMPreeditDisable: - IME_SetOpenStatus(FALSE); + x11drv_client_call( client_ime_set_open_status, FALSE ); break; default: break; } + return TRUE; }
static int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data) { TRACE("PreEditStartCallback %p\n",ic); - IME_SetCompositionStatus(TRUE); + x11drv_client_call( client_ime_set_composition_status, TRUE ); ximInComposeMode = TRUE; return -1; } @@ -148,7 +145,7 @@ static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_d dwCompStringSize = 0; dwCompStringLength = 0; CompositionString = NULL; - IME_SetCompositionStatus(FALSE); + x11drv_client_call( client_ime_set_composition_status, FALSE ); }
static void XIMPreEditDrawCallback(XIM ic, XPointer client_data, @@ -188,7 +185,7 @@ static void XIMPreEditDrawCallback(XIM ic, XPointer client_data, } else X11DRV_ImmSetInternalString (sel, len, NULL, 0); - IME_SetCursorPos(P_DR->caret); + x11drv_client_call( client_ime_set_cursor_pos, P_DR->caret ); } TRACE("Finished\n"); } @@ -200,7 +197,7 @@ static void XIMPreEditCaretCallback(XIC ic, XPointer client_data,
if (P_C) { - int pos = IME_GetCursorPos(); + int pos = x11drv_client_call( client_ime_get_cursor_pos, 0 ); TRACE("pos: %d\n", pos); switch(P_C->direction) { @@ -229,7 +226,7 @@ static void XIMPreEditCaretCallback(XIC ic, XPointer client_data, FIXME("Not implemented\n"); break; } - IME_SetCursorPos(pos); + x11drv_client_call( client_ime_set_cursor_pos, pos ); P_C->position = pos; } TRACE("Finished\n"); @@ -423,7 +420,7 @@ static BOOL open_xim( Display *display ) else thread_data->font_set = NULL;
- IME_UpdateAssociation(NULL); + x11drv_client_call( client_ime_update_association, 0 ); return TRUE; }
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/systray.c | 33 ++++++------------------ dlls/winex11.drv/unixlib.h | 3 +++ dlls/winex11.drv/window.c | 46 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 3 +++ dlls/winex11.drv/x11drv_main.c | 3 +++ 5 files changed, 62 insertions(+), 26 deletions(-)
diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c index 45ad0617246..bb2e5d563dd 100644 --- a/dlls/winex11.drv/systray.c +++ b/dlls/winex11.drv/systray.c @@ -587,10 +587,13 @@ static BOOL init_systray(void) { static BOOL init_done; WNDCLASSEXW class; - Display *display;
- if (is_virtual_desktop()) return FALSE; if (init_done) return TRUE; + if (!X11DRV_CALL( systray_init, NULL )) + { + init_done = TRUE; + return FALSE; + }
icon_cx = GetSystemMetrics( SM_CXSMICON ) + 2 * ICON_BORDER; icon_cy = GetSystemMetrics( SM_CYSMICON ) + 2 * ICON_BORDER; @@ -620,17 +623,6 @@ static BOOL init_systray(void) return FALSE; }
- display = thread_init_display(); - if (DefaultScreen( display ) == 0) - systray_atom = x11drv_atom(_NET_SYSTEM_TRAY_S0); - else - { - char systray_buffer[29]; /* strlen(_NET_SYSTEM_TRAY_S4294967295)+1 */ - sprintf( systray_buffer, "_NET_SYSTEM_TRAY_S%u", DefaultScreen( display ) ); - systray_atom = XInternAtom( display, systray_buffer, False ); - } - XSelectInput( display, root_window, StructureNotifyMask ); - init_done = TRUE; return TRUE; } @@ -700,18 +692,11 @@ void change_systray_owner( Display *display, Window systray_window ) /* hide a tray icon */ static BOOL hide_icon( struct tray_icon *icon ) { - struct x11drv_win_data *data; - TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner );
if (!icon->window) return TRUE; /* already hidden */
- /* make sure we don't try to unmap it, it confuses some systray docks */ - if ((data = get_win_data( icon->window ))) - { - if (data->embedded) data->mapped = FALSE; - release_win_data( data ); - } + X11DRV_CALL( systray_hide, &icon->window ); DestroyWindow(icon->window); DestroyWindow(icon->tooltip); icon->window = 0; @@ -759,11 +744,7 @@ static BOOL modify_icon( struct tray_icon *icon, NOTIFYICONDATAW *nid ) { if (icon->display != -1) InvalidateRect( icon->window, NULL, TRUE ); else if (icon->layered) repaint_tray_icon( icon ); - else - { - Window win = X11DRV_get_whole_window( icon->window ); - if (win) XClearArea( gdi_display, win, 0, 0, 0, 0, True ); - } + else X11DRV_CALL( systray_clear, &icon->window ); } }
diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index fe3b430dc87..ce89f7d4d39 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -24,6 +24,9 @@ enum x11drv_funcs unix_clipboard_message, unix_create_desktop, unix_init, + unix_systray_clear, + unix_systray_hide, + unix_systray_init, unix_tablet_attach_queue, unix_tablet_get_packet, unix_tablet_info, diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 7ccec4ee4ec..4ae1d3f11a3 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2092,6 +2092,52 @@ HWND create_foreign_window( Display *display, Window xwin ) }
+NTSTATUS x11drv_systray_init( void *arg ) +{ + Display *display; + + if (is_virtual_desktop()) return FALSE; + + display = thread_init_display(); + if (DefaultScreen( display ) == 0) + systray_atom = x11drv_atom(_NET_SYSTEM_TRAY_S0); + else + { + char systray_buffer[29]; /* strlen(_NET_SYSTEM_TRAY_S4294967295)+1 */ + sprintf( systray_buffer, "_NET_SYSTEM_TRAY_S%u", DefaultScreen( display ) ); + systray_atom = XInternAtom( display, systray_buffer, False ); + } + XSelectInput( display, root_window, StructureNotifyMask ); + + return TRUE; +} + + +NTSTATUS x11drv_systray_clear( void *arg ) +{ + HWND hwnd = *(HWND*)arg; + Window win = X11DRV_get_whole_window( hwnd ); + if (win) XClearArea( gdi_display, win, 0, 0, 0, 0, True ); + return 0; +} + + +NTSTATUS x11drv_systray_hide( void *arg ) +{ + HWND hwnd = *(HWND*)arg; + struct x11drv_win_data *data; + + /* make sure we don't try to unmap it, it confuses some systray docks */ + if ((data = get_win_data( hwnd ))) + { + if (data->embedded) data->mapped = FALSE; + release_win_data( data ); + } + + return 0; +} + + /*********************************************************************** * X11DRV_get_whole_window * diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 3986733782a..ec72d8a550e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -827,6 +827,9 @@ static inline BOOL is_window_rect_mapped( const RECT *rect )
extern NTSTATUS x11drv_clipboard_message( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_create_desktop( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_systray_clear( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_systray_hide( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_systray_init( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_attach_queue( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_get_packet( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_load_info( void *arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 749fe2f761b..2d65f2a03d6 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -977,6 +977,9 @@ const unixlib_entry_t __wine_unix_call_funcs[] = x11drv_clipboard_message, x11drv_create_desktop, x11drv_init, + x11drv_systray_clear, + x11drv_systray_hide, + x11drv_systray_init, x11drv_tablet_attach_queue, x11drv_tablet_get_packet, x11drv_tablet_info,
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/dllmain.c | 1 + dlls/winex11.drv/event.c | 10 ++- dlls/winex11.drv/systray.c | 117 ++++++--------------------------- dlls/winex11.drv/unixlib.h | 16 +++++ dlls/winex11.drv/window.c | 114 ++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 + dlls/winex11.drv/x11drv_main.c | 2 + 7 files changed, 165 insertions(+), 97 deletions(-)
diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index bbfcefe05e3..7ea07647dc9 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -157,6 +157,7 @@ static const kernel_callback kernel_callbacks[] = x11drv_dnd_post_drop, x11drv_ime_set_composition_string, x11drv_ime_set_result, + x11drv_systray_change_owner, };
C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last ); diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index cefc86d0902..12b0884a250 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -621,8 +621,16 @@ static void set_focus( Display *display, HWND hwnd, Time time ) static void handle_manager_message( HWND hwnd, XClientMessageEvent *event ) { if (hwnd != NtUserGetDesktopWindow()) return; + if (systray_atom && event->data.l[1] == systray_atom) - change_systray_owner( event->display, event->data.l[2] ); + { + struct systray_change_owner_params params; + + TRACE( "new owner %lx\n", event->data.l[2] ); + + params.event_handle = (UINT_PTR)event; + x11drv_client_func( client_func_systray_change_owner, ¶ms, sizeof(params) ); + } }
diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c index bb2e5d563dd..ae1c5738f8e 100644 --- a/dlls/winex11.drv/systray.c +++ b/dlls/winex11.drv/systray.c @@ -75,12 +75,6 @@ static BOOL show_icon( struct tray_icon *icon ); static BOOL hide_icon( struct tray_icon *icon ); static BOOL delete_icon( struct tray_icon *icon );
-#define SYSTEM_TRAY_REQUEST_DOCK 0 -#define SYSTEM_TRAY_BEGIN_MESSAGE 1 -#define SYSTEM_TRAY_CANCEL_MESSAGE 2 - -Atom systray_atom = 0; - #define MIN_DISPLAYED 8 #define ICON_BORDER 2
@@ -550,39 +544,6 @@ static LRESULT WINAPI tray_icon_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR return DefWindowProcW( hwnd, msg, wparam, lparam ); }
-/* find the X11 window owner the system tray selection */ -static Window get_systray_selection_owner( Display *display ) -{ - return XGetSelectionOwner( display, systray_atom ); -} - -static void get_systray_visual_info( Display *display, Window systray_window, XVisualInfo *info ) -{ - XVisualInfo *list, template; - VisualID *visual_id; - Atom type; - int format, num; - unsigned long count, remaining; - - *info = default_visual; - if (XGetWindowProperty( display, systray_window, x11drv_atom(_NET_SYSTEM_TRAY_VISUAL), 0, - 65536/sizeof(CARD32), False, XA_VISUALID, &type, &format, &count, - &remaining, (unsigned char **)&visual_id )) - return; - - if (type == XA_VISUALID && format == 32) - { - template.visualid = visual_id[0]; - if ((list = XGetVisualInfo( display, VisualIDMask, &template, &num ))) - { - *info = list[0]; - TRACE( "systray window %lx got visual %lx\n", systray_window, info->visualid ); - XFree( list ); - } - } - XFree( visual_id ); -} - static BOOL init_systray(void) { static BOOL init_done; @@ -627,66 +588,27 @@ static BOOL init_systray(void) return TRUE; }
-/* dock the given icon with the NETWM system tray */ -static void dock_systray_icon( Display *display, struct tray_icon *icon, Window systray_window ) -{ - Window window; - XEvent ev; - XSetWindowAttributes attr; - XVisualInfo visual; - struct x11drv_win_data *data; - - get_systray_visual_info( display, systray_window, &visual ); - - icon->layered = (visual.depth == 32); - CreateWindowExW( icon->layered ? WS_EX_LAYERED : 0, - icon_classname, NULL, WS_CLIPSIBLINGS | WS_POPUP, - CW_USEDEFAULT, CW_USEDEFAULT, icon_cx, icon_cy, - NULL, NULL, NULL, icon ); - - if (!(data = get_win_data( icon->window ))) return; - if (icon->layered) set_window_visual( data, &visual, TRUE ); - make_window_embedded( data ); - window = data->whole_window; - release_win_data( data ); - - ShowWindow( icon->window, SW_SHOWNA ); - - TRACE( "icon window %p/%lx\n", icon->window, window ); - - /* send the docking request message */ - ev.xclient.type = ClientMessage; - ev.xclient.window = systray_window; - ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE ); - ev.xclient.format = 32; - ev.xclient.data.l[0] = CurrentTime; - ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK; - ev.xclient.data.l[2] = window; - ev.xclient.data.l[3] = 0; - ev.xclient.data.l[4] = 0; - XSendEvent( display, systray_window, False, NoEventMask, &ev ); - - if (!icon->layered) - { - attr.background_pixmap = ParentRelative; - attr.bit_gravity = ForgetGravity; - XChangeWindowAttributes( display, window, CWBackPixmap | CWBitGravity, &attr ); - } - else repaint_tray_icon( icon ); -} - /* dock systray windows again with the new owner */ -void change_systray_owner( Display *display, Window systray_window ) +NTSTATUS WINAPI x11drv_systray_change_owner( void *arg, ULONG size ) { + struct systray_change_owner_params *params = arg; + struct systray_dock_params dock_params; struct tray_icon *icon;
- TRACE( "new owner %lx\n", systray_window ); LIST_FOR_EACH_ENTRY( icon, &icon_list, struct tray_icon, entry ) { if (icon->display == -1) continue; hide_icon( icon ); - dock_systray_icon( display, icon, systray_window ); + + dock_params.event_handle = params->event_handle; + dock_params.icon = icon; + dock_params.cx = icon_cx; + dock_params.cy = icon_cy; + dock_params.layered = &icon->layered; + X11DRV_CALL( systray_dock, &dock_params ); } + + return 0; }
/* hide a tray icon */ @@ -710,16 +632,19 @@ static BOOL hide_icon( struct tray_icon *icon ) /* make the icon visible */ static BOOL show_icon( struct tray_icon *icon ) { - Window systray_window; - Display *display = thread_init_display(); + struct systray_dock_params params; + + if (icon->window) return TRUE; /* already shown */
TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner );
- if (icon->window) return TRUE; /* already shown */ + params.event_handle = 0; + params.icon = icon; + params.cx = icon_cx; + params.cy = icon_cy; + params.layered = &icon->layered;
- if ((systray_window = get_systray_selection_owner( display ))) - dock_systray_icon( display, icon, systray_window ); - else + if (X11DRV_CALL( systray_dock, ¶ms )) add_to_standalone_tray( icon );
update_balloon( icon ); diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index ce89f7d4d39..dc3c74979ca 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -25,6 +25,7 @@ enum x11drv_funcs unix_create_desktop, unix_init, unix_systray_clear, + unix_systray_dock, unix_systray_hide, unix_systray_init, unix_tablet_attach_queue, @@ -56,6 +57,15 @@ struct create_desktop_params UINT height; };
+struct systray_dock_params +{ + UINT64 event_handle; + void *icon; + int cx; + int cy; + BOOL *layered; +}; + /* x11drv_tablet_info params */ struct tablet_info_params { @@ -80,6 +90,7 @@ enum x11drv_client_funcs client_func_dnd_post_drop, client_func_ime_set_composition_string, client_func_ime_set_result, + client_func_systray_change_owner, client_func_last };
@@ -121,3 +132,8 @@ struct dnd_position_event_params POINT point; DWORD effect; }; + +struct systray_change_owner_params +{ + UINT64 event_handle; +}; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 4ae1d3f11a3..f006150fb7c 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -53,6 +53,7 @@ #include "mwm.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv); +WINE_DECLARE_DEBUG_CHANNEL(systray);
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 #define _NET_WM_MOVERESIZE_SIZE_TOP 1 @@ -70,6 +71,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv); #define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_TOGGLE 2
+#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + static const unsigned int net_wm_state_atoms[NB_NET_WM_STATES] = { XATOM__NET_WM_STATE_FULLSCREEN, @@ -2138,6 +2143,115 @@ NTSTATUS x11drv_systray_hide( void *arg ) }
+/* find the X11 window owner the system tray selection */ +static Window get_systray_selection_owner( Display *display ) +{ + return XGetSelectionOwner( display, systray_atom ); +} + + +static void get_systray_visual_info( Display *display, Window systray_window, XVisualInfo *info ) +{ + XVisualInfo *list, template; + VisualID *visual_id; + Atom type; + int format, num; + unsigned long count, remaining; + + *info = default_visual; + if (XGetWindowProperty( display, systray_window, x11drv_atom(_NET_SYSTEM_TRAY_VISUAL), 0, + 65536/sizeof(CARD32), False, XA_VISUALID, &type, &format, &count, + &remaining, (unsigned char **)&visual_id )) + return; + + if (type == XA_VISUALID && format == 32) + { + template.visualid = visual_id[0]; + if ((list = XGetVisualInfo( display, VisualIDMask, &template, &num ))) + { + *info = list[0]; + TRACE_(systray)( "systray window %lx got visual %lx\n", systray_window, info->visualid ); + XFree( list ); + } + } + XFree( visual_id ); +} + + +NTSTATUS x11drv_systray_dock( void *arg ) +{ + struct systray_dock_params *params = arg; + Window systray_window, window; + Display *display; + XEvent ev; + XSetWindowAttributes attr; + XVisualInfo visual; + struct x11drv_win_data *data; + BOOL layered; + HWND hwnd; + + static const WCHAR icon_classname[] = + {'_','_','w','i','n','e','x','1','1','_','t','r','a','y','_','i','c','o','n',0}; + + if (params->event_handle) + { + XClientMessageEvent *event = (XClientMessageEvent *)(UINT_PTR)params->event_handle; + display = event->display; + systray_window = event->data.l[2]; + } + else + { + display = thread_init_display(); + if (!(systray_window = get_systray_selection_owner( display ))) return STATUS_UNSUCCESSFUL; + } + + get_systray_visual_info( display, systray_window, &visual ); + + *params->layered = layered = (visual.depth == 32); + + hwnd = CreateWindowExW( layered ? WS_EX_LAYERED : 0, + icon_classname, NULL, WS_CLIPSIBLINGS | WS_POPUP, + CW_USEDEFAULT, CW_USEDEFAULT, params->cx, params->cy, + NULL, NULL, NULL, params->icon ); + + if (!(data = get_win_data( hwnd ))) return STATUS_UNSUCCESSFUL; + if (layered) set_window_visual( data, &visual, TRUE ); + make_window_embedded( data ); + window = data->whole_window; + release_win_data( data ); + + NtUserShowWindow( hwnd, SW_SHOWNA ); + + TRACE_(systray)( "icon window %p/%lx\n", hwnd, window ); + + /* send the docking request message */ + ev.xclient.type = ClientMessage; + ev.xclient.window = systray_window; + ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE ); + ev.xclient.format = 32; + ev.xclient.data.l[0] = CurrentTime; + ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK; + ev.xclient.data.l[2] = window; + ev.xclient.data.l[3] = 0; + ev.xclient.data.l[4] = 0; + XSendEvent( display, systray_window, False, NoEventMask, &ev ); + + if (!layered) + { + attr.background_pixmap = ParentRelative; + attr.bit_gravity = ForgetGravity; + XChangeWindowAttributes( display, window, CWBackPixmap | CWBitGravity, &attr ); + } + else + { + /* force repainig */ + send_message( hwnd, WM_SIZE, SIZE_RESTORED, MAKELONG( params->cx, params->cy )); + } + + return STATUS_SUCCESS; +} + + /*********************************************************************** * X11DRV_get_whole_window * diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index ec72d8a550e..d3db49b86b6 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -828,6 +828,7 @@ static inline BOOL is_window_rect_mapped( const RECT *rect ) extern NTSTATUS x11drv_clipboard_message( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_create_desktop( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_systray_clear( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS x11drv_systray_dock( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_systray_hide( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_systray_init( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_attach_queue( void *arg ) DECLSPEC_HIDDEN; @@ -842,6 +843,7 @@ extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DEC extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_ime_set_composition_string( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG size ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 2d65f2a03d6..cbcfc659a67 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -60,6 +60,7 @@ XVisualInfo default_visual = { 0 }; XVisualInfo argb_visual = { 0 }; Colormap default_colormap = None; XPixmapFormatValues **pixmap_formats; +Atom systray_atom = 0; unsigned int screen_bpp; Window root_window; BOOL usexvidmode = TRUE; @@ -978,6 +979,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = x11drv_create_desktop, x11drv_init, x11drv_systray_clear, + x11drv_systray_dock, x11drv_systray_hide, x11drv_systray_init, x11drv_tablet_attach_queue,
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/systray.c | 25 ++++++++++++++++++++++++- dlls/winex11.drv/window.c | 23 ----------------------- dlls/winex11.drv/x11drv.h | 3 ++- 3 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c index ae1c5738f8e..1c6616e0d9c 100644 --- a/dlls/winex11.drv/systray.c +++ b/dlls/winex11.drv/systray.c @@ -142,7 +142,7 @@ static void create_tooltip(struct tray_icon *icon) } }
-void update_systray_balloon_position(void) +static void update_systray_balloon_position(void) { RECT rect; POINT pos; @@ -783,3 +783,26 @@ int CDECL wine_notify_icon( DWORD msg, NOTIFYICONDATAW *data ) } return ret; } + + +/* window procedure for foreign windows */ +LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + switch(msg) + { + case WM_WINDOWPOSCHANGED: + update_systray_balloon_position(); + break; + case WM_PARENTNOTIFY: + if (LOWORD(wparam) == WM_DESTROY) + { + TRACE( "%p: got parent notify destroy for win %lx\n", hwnd, lparam ); + PostMessageW( hwnd, WM_CLOSE, 0, 0 ); /* so that we come back here once the child is gone */ + } + return 0; + case WM_CLOSE: + if (GetWindow( hwnd, GW_CHILD )) return 0; /* refuse to die if we still have children */ + break; + } + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index f006150fb7c..7726ba78db0 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1987,29 +1987,6 @@ static struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd, const RECT *wi }
-/* window procedure for foreign windows */ -static LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) -{ - switch(msg) - { - case WM_WINDOWPOSCHANGED: - update_systray_balloon_position(); - break; - case WM_PARENTNOTIFY: - if (LOWORD(wparam) == WM_DESTROY) - { - TRACE( "%p: got parent notify destroy for win %lx\n", hwnd, lparam ); - NtUserPostMessage( hwnd, WM_CLOSE, 0, 0 ); /* so that we come back here once the child is gone */ - } - return 0; - case WM_CLOSE: - if (NtUserGetWindowRelative( hwnd, GW_CHILD )) return 0; /* refuse to die if we still have children */ - break; - } - return DefWindowProcW( hwnd, msg, wparam, lparam ); -} - - /*********************************************************************** * create_foreign_window * diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d3db49b86b6..42d9e39b082 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -642,7 +642,6 @@ extern Window create_dummy_client_window(void) DECLSPEC_HIDDEN; extern Window create_client_window( HWND hwnd, const XVisualInfo *visual ) DECLSPEC_HIDDEN; extern void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BOOL use_alpha ) DECLSPEC_HIDDEN; extern void change_systray_owner( Display *display, Window systray_window ) DECLSPEC_HIDDEN; -extern void update_systray_balloon_position(void) DECLSPEC_HIDDEN; extern HWND create_foreign_window( Display *display, Window window ) DECLSPEC_HIDDEN; extern BOOL update_clipboard( HWND hwnd ) DECLSPEC_HIDDEN; extern void init_win_context(void) DECLSPEC_HIDDEN; @@ -853,6 +852,8 @@ extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_open_status( UINT open ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
+extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, + LPARAM lparam ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_client_func( enum x11drv_client_funcs func, const void *params, ULONG size ) DECLSPEC_HIDDEN;
From: Jacek Caban jacek@codeweavers.com
A/W conversion is not used in those cases anyway, so just use a single implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/dialog.c | 2 +- dlls/user32/hook.c | 20 ---------------- dlls/user32/menu.c | 2 +- dlls/user32/nonclient.c | 6 ++--- dlls/user32/scroll.c | 2 +- dlls/user32/user32.spec | 6 ++--- dlls/user32/winpos.c | 4 ++-- dlls/win32u/hook.c | 11 +++++++++ dlls/win32u/syscall.c | 1 + dlls/win32u/tests/win32u.c | 45 +++++++++++++++++++++++++++++++++++ dlls/win32u/win32u.spec | 2 +- dlls/wow64win/syscall.h | 1 + dlls/wow64win/user.c | 48 ++++++++++++++++++++++++++++++++++++++ include/ntuser.h | 1 + 14 files changed, 119 insertions(+), 32 deletions(-)
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index ea9fae4200a..95967269daf 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -1164,7 +1164,7 @@ BOOL WINAPI IsDialogMessageW( HWND hwndDlg, LPMSG msg ) if (!IsWindow( hwndDlg )) return FALSE;
- if (CallMsgFilterW( msg, MSGF_DIALOGBOX )) return TRUE; + if (NtUserCallMsgFilter( msg, MSGF_DIALOGBOX )) return TRUE;
hwndDlg = WIN_GetFullHandle( hwndDlg ); if (is_desktop_window(hwndDlg)) return FALSE; diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 76033f0dee1..c0ebe05684f 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -383,26 +383,6 @@ BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc ) }
-/*********************************************************************** - * CallMsgFilterA (USER32.@) - */ -BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code ) -{ - if (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg, FALSE )) return TRUE; - return HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)msg, FALSE ); -} - - -/*********************************************************************** - * CallMsgFilterW (USER32.@) - */ -BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code ) -{ - if (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg, TRUE )) return TRUE; - return HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)msg, TRUE ); -} - - /*********************************************************************** * SetWinEventHook [USER32.@] * diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 64e5d35ba39..afe3c50154e 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -2974,7 +2974,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, { if (PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE )) { - if (!CallMsgFilterW( &msg, MSGF_MENU )) break; + if (!NtUserCallMsgFilter( &msg, MSGF_MENU )) break; /* remove the message from the queue */ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE ); } diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 003ecb7e5e5..85d1a14a195 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -1249,7 +1249,7 @@ static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam ) BOOL oldstate = pressed;
if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; - if (CallMsgFilterW( &msg, MSGF_MAX )) continue; + if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue;
if(msg.message == WM_LBUTTONUP) break; @@ -1314,7 +1314,7 @@ static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam) BOOL oldstate = pressed;
if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; - if (CallMsgFilterW( &msg, MSGF_MAX )) continue; + if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue;
if(msg.message == WM_LBUTTONUP) break; @@ -1464,7 +1464,7 @@ LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) for (;;) { if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; - if (CallMsgFilterW( &msg, MSGF_MAX )) continue; + if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; if (msg.message == WM_RBUTTONUP) { hittest = NC_HandleNCHitTest( hwnd, msg.pt ); diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c index efe115246f2..1909d4082ce 100644 --- a/dlls/user32/scroll.c +++ b/dlls/user32/scroll.c @@ -1110,7 +1110,7 @@ void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt ) do { if (!GetMessageW( &msg, 0, 0, 0 )) break; - if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue; + if (NtUserCallMsgFilter( &msg, MSGF_SCROLLBAR )) continue; if (msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE || msg.message == WM_MOUSELEAVE || diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 1ae27b2482f..555023de110 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -25,9 +25,9 @@ # @ stub BuildReasonArray @ stdcall CalcChildScroll(long long) @ stdcall CalcMenuBar(long long long long ptr) CalcMenuBar -@ stdcall CallMsgFilter(ptr long) CallMsgFilterA -@ stdcall CallMsgFilterA(ptr long) -@ stdcall CallMsgFilterW(ptr long) +@ stdcall CallMsgFilter(ptr long) NtUserCallMsgFilter +@ stdcall CallMsgFilterA(ptr long) NtUserCallMsgFilter +@ stdcall CallMsgFilterW(ptr long) NtUserCallMsgFilter @ stdcall CallNextHookEx(long long long long) NtUserCallNextHookEx @ stdcall CallWindowProcA(ptr long long long long) @ stdcall CallWindowProcW(ptr long long long long) diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 63c08e5d795..cdcd03484cd 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -786,7 +786,7 @@ static LONG start_size_move( HWND hwnd, WPARAM wParam, POINT *capturePoint, LONG while(!hittest) { if (!GetMessageW( &msg, 0, 0, 0 )) return 0; - if (CallMsgFilterW( &msg, MSGF_SIZE )) continue; + if (NtUserCallMsgFilter( &msg, MSGF_SIZE )) continue;
switch(msg.message) { @@ -952,7 +952,7 @@ void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) int dx = 0, dy = 0;
if (!GetMessageW( &msg, 0, 0, 0 )) break; - if (CallMsgFilterW( &msg, MSGF_SIZE )) continue; + if (NtUserCallMsgFilter( &msg, MSGF_SIZE )) continue;
/* Exit on button-up, Return, or Esc */ if ((msg.message == WM_LBUTTONUP) || diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index eb08e3d0d0c..a271693622a 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -172,6 +172,17 @@ BOOL unhook_windows_hook( INT id, HOOKPROC proc ) return !status; }
+/*********************************************************************** + * NtUserCallMsgFilter (win32u.@) + */ +BOOL WINAPI NtUserCallMsgFilter( MSG *msg, INT code ) +{ + /* FIXME: We should use NtCallbackReturn instead of passing (potentially kernel) pointer + * like that, but we need to consequently use syscall thunks first for that to work. */ + if (call_hooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg, TRUE )) return TRUE; + return call_hooks( WH_MSGFILTER, code, 0, (LPARAM)msg, TRUE ); +} + static UINT get_ll_hook_timeout(void) { /* FIXME: should retrieve LowLevelHooksTimeout in HKEY_CURRENT_USER\Control Panel\Desktop */ diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 488056ef439..f306ea12d4a 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -106,6 +106,7 @@ static void * const syscalls[] = NtUserAddClipboardFormatListener, NtUserAttachThreadInput, NtUserBuildHwndList, + NtUserCallMsgFilter, NtUserCheckMenuItem, NtUserChildWindowFromPointEx, NtUserCloseDesktop, diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 03c143cc143..4df81e1677e 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -579,6 +579,50 @@ static void test_menu(void) ok( ret, "NtUserDestroyMenu failed: %lu\n", GetLastError() ); }
+static MSG *msg_ptr; + +static LRESULT WINAPI hook_proc( INT code, WPARAM wparam, LPARAM lparam ) +{ + msg_ptr = (MSG *)lparam; + ok( code == 100, "code = %d\n", code ); + ok( msg_ptr->time = 1, "time = %lx\n", msg_ptr->time ); + ok( msg_ptr->wParam == 10, "wParam = %Ix\n", msg_ptr->wParam ); + ok( msg_ptr->lParam == 20, "lParam = %Ix\n", msg_ptr->lParam ); + msg_ptr->time = 3; + msg_ptr->wParam = 1; + msg_ptr->lParam = 2; + return CallNextHookEx( NULL, code, wparam, lparam ); +} + +static void test_message_filter(void) +{ + HHOOK hook; + MSG msg; + BOOL ret; + + hook = SetWindowsHookExW( WH_MSGFILTER, hook_proc, NULL, GetCurrentThreadId() ); + ok( hook != NULL, "SetWindowsHookExW failed\n"); + + memset( &msg, 0, sizeof(msg) ); + msg.time = 1; + msg.wParam = 10; + msg.lParam = 20; + ret = NtUserCallMsgFilter( &msg, 100 ); + ok( !ret, "CallMsgFilterW returned: %x\n", ret ); + todo_wine + ok( msg_ptr != &msg, "our ptr was passed directly to hook\n" ); + + if (sizeof(void *) == 8) /* on some Windows versions, msg is not modified on wow64 */ + { + ok( msg.time == 3, "time = %lx\n", msg.time ); + ok( msg.wParam == 1, "wParam = %Ix\n", msg.wParam ); + ok( msg.lParam == 2, "lParam = %Ix\n", msg.lParam ); + } + + ret = NtUserUnhookWindowsHookEx( hook ); + ok( ret, "NtUserUnhookWindowsHook failed: %lu\n", GetLastError() ); +} + START_TEST(win32u) { /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ @@ -592,6 +636,7 @@ START_TEST(win32u) test_message_call(); test_window_text(); test_menu(); + test_message_filter();
test_NtUserCloseWindowStation(); } diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index d6a51c1d3b9..a915f89e578 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -776,7 +776,7 @@ @ stub NtUserCallHwndParamLock @ stub NtUserCallHwndParamLockSafe @ stub NtUserCallHwndSafe -@ stub NtUserCallMsgFilter +@ stdcall -syscall NtUserCallMsgFilter(ptr long) @ stdcall NtUserCallNextHookEx(long long long long) @ stdcall NtUserCallNoParam(long) @ stdcall NtUserCallOneParam(long long) diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 27ba163408b..2eb3ac55ff1 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -93,6 +93,7 @@ SYSCALL_ENTRY( NtUserAddClipboardFormatListener ) \ SYSCALL_ENTRY( NtUserAttachThreadInput ) \ SYSCALL_ENTRY( NtUserBuildHwndList ) \ + SYSCALL_ENTRY( NtUserCallMsgFilter ) \ SYSCALL_ENTRY( NtUserCheckMenuItem ) \ SYSCALL_ENTRY( NtUserChildWindowFromPointEx ) \ SYSCALL_ENTRY( NtUserCloseDesktop ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index d90c4ec2f99..e828dae5247 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -46,6 +46,42 @@ typedef struct UINT32 hbmpItem; } MENUITEMINFOW32;
+typedef struct +{ + UINT32 hwnd; + UINT message; + UINT32 wParam; + UINT32 lParam; + DWORD time; + POINT pt; +} MSG32; + +static MSG *msg_32to64( MSG *msg, MSG32 *msg32 ) +{ + if (!msg32) return NULL; + + msg->hwnd = UlongToHandle( msg32->hwnd ); + msg->message = msg32->message; + msg->wParam = msg32->wParam; + msg->lParam = msg32->lParam; + msg->time = msg32->time; + msg->pt = msg32->pt; + return msg; +} + +static MSG32 *msg_64to32( MSG *msg, MSG32 *msg32 ) +{ + if (!msg32) return NULL; + + msg32->hwnd = HandleToUlong( msg->hwnd ); + msg32->message = msg->message; + msg32->wParam = msg->wParam; + msg32->lParam = msg->lParam; + msg32->time = msg->time; + msg32->pt = msg->pt; + return msg32; +} + NTSTATUS WINAPI wow64_NtUserInitializeClientPfnArrays( UINT *args ) { FIXME( "\n" ); @@ -555,6 +591,18 @@ NTSTATUS WINAPI wow64_NtUserUnhookWindowsHookEx( UINT *args ) return NtUserUnhookWindowsHookEx( handle ); }
+NTSTATUS WINAPI wow64_NtUserCallMsgFilter( UINT *args ) +{ + MSG32 *msg32 = get_ptr( &args ); + INT code = get_ulong( &args ); + MSG msg; + BOOL ret; + + ret = NtUserCallMsgFilter( msg_32to64( &msg, msg32 ), code ); + msg_64to32( &msg, msg32 ); + return ret; +} + NTSTATUS WINAPI wow64_NtUserGetForegroundWindow( UINT *args ) { return HandleToUlong( NtUserGetForegroundWindow() ); diff --git a/include/ntuser.h b/include/ntuser.h index fdc43cac8ed..bc44ac76d4e 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -462,6 +462,7 @@ NTSTATUS WINAPI NtUserBuildHwndList( HDESK desktop, ULONG unk2, ULONG unk3, ULON ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ); ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ); LRESULT WINAPI NtUserCallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ); +BOOL WINAPI NtUserCallMsgFilter( MSG *msg, INT code ); ULONG_PTR WINAPI NtUserCallNoParam( ULONG code ); ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code ); ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code );
On 5/5/22 15:40, Jacek Caban wrote:
+static LRESULT WINAPI hook_proc( INT code, WPARAM wparam, LPARAM lparam ) +{
- msg_ptr = (MSG *)lparam;
- ok( code == 100, "code = %d\n", code );
- ok( msg_ptr->time = 1, "time = %lx\n", msg_ptr->time );
- ok( msg_ptr->wParam == 10, "wParam = %Ix\n", msg_ptr->wParam );
- ok( msg_ptr->lParam == 20, "lParam = %Ix\n", msg_ptr->lParam );
- msg_ptr->time = 3;
- msg_ptr->wParam = 1;
- msg_ptr->lParam = 2;
- return CallNextHookEx( NULL, code, wparam, lparam );
+}
I pushed a v2 with a warning fix.
Jacek
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/mouse.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 7133f2e2694..46951103bc1 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -1228,6 +1228,27 @@ done: return cursor; }
+static BOOL get_icon_info( HICON handle, ICONINFOEXW *ret ) +{ + UNICODE_STRING module, res_name; + ICONINFO info; + + module.Buffer = ret->szModName; + module.MaximumLength = sizeof(ret->szModName) - sizeof(WCHAR); + res_name.Buffer = ret->szResName; + res_name.MaximumLength = sizeof(ret->szResName) - sizeof(WCHAR); + if (!NtUserGetIconInfo( handle, &info, &module, &res_name, NULL, 0 )) return FALSE; + ret->fIcon = info.fIcon; + ret->xHotspot = info.xHotspot; + ret->yHotspot = info.yHotspot; + ret->hbmColor = info.hbmColor; + ret->hbmMask = info.hbmMask; + ret->wResID = res_name.Length ? 0 : LOWORD( res_name.Buffer ); + ret->szModName[module.Length] = 0; + ret->szResName[res_name.Length] = 0; + return TRUE; +} + /*********************************************************************** * create_xlib_load_mono_cursor * @@ -1243,8 +1264,7 @@ static Cursor create_xlib_load_mono_cursor( HDC hdc, HANDLE handle, int width, i if (!(mono = CopyImage( handle, IMAGE_CURSOR, width, height, LR_MONOCHROME | LR_COPYFROMRESOURCE ))) return None;
- info.cbSize = sizeof(info); - if (GetIconInfoExW( mono, &info )) + if (get_icon_info( mono, &info )) { if (!info.hbmColor) { @@ -1413,8 +1433,7 @@ static Cursor create_cursor( HANDLE handle )
if (!handle) return get_empty_cursor();
- info.cbSize = sizeof(info); - if (!GetIconInfoExW( handle, &info )) return 0; + if (!get_icon_info( handle, &info )) return 0;
if (use_system_cursors && (cursor = create_xcursor_system_cursor( &info ))) {
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/clipboard.c | 4 ++-- dlls/winex11.drv/desktop.c | 5 +++-- dlls/winex11.drv/event.c | 5 +++-- dlls/winex11.drv/mouse.c | 8 ++++---- dlls/winex11.drv/window.c | 12 ++++++++---- dlls/winex11.drv/wintab.c | 10 +++++----- 6 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index 9486f37954e..276eee9b4dd 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -2292,8 +2292,8 @@ void X11DRV_UpdateClipboard(void) if (GetCurrentThreadId() == clipboard_thread_id) return; now = NtGetTickCount(); if ((int)(now - last_update) <= SELECTION_UPDATE_DELAY) return; - if (SendMessageTimeoutW( GetClipboardOwner(), WM_X11DRV_UPDATE_CLIPBOARD, 0, 0, - SMTO_ABORTIFHUNG, 5000, &ret ) && ret) + if (send_message_timeout( NtUserGetClipboardOwner(), WM_X11DRV_UPDATE_CLIPBOARD, 0, 0, + SMTO_ABORTIFHUNG, 5000, &ret ) && ret) last_update = now; }
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 61fe5578e8b..c335bc5ba2b 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -192,9 +192,10 @@ static LONG X11DRV_desktop_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
static void query_desktop_work_area( RECT *rc_work ) { - static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; + static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d'}; + UNICODE_STRING str = { sizeof(trayW), sizeof(trayW), (WCHAR *)trayW }; RECT rect; - HWND hwnd = FindWindowW( trayW, NULL ); + HWND hwnd = NtUserFindWindowEx( 0, 0, &str, NULL, 0 );
if (!hwnd || !NtUserIsWindowVisible( hwnd )) return; if (!NtUserGetWindowRect( hwnd, &rect )) return; diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 12b0884a250..d5e7127ceed 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -665,10 +665,11 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event ) HMENU hSysMenu;
if (NtUserGetClassLongW( hwnd, GCL_STYLE ) & CS_NOCLOSE) return; - hSysMenu = GetSystemMenu(hwnd, FALSE); + hSysMenu = NtUserGetSystemMenu( hwnd, FALSE ); if (hSysMenu) { - UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); + UINT state = NtUserThunkedMenuItemInfo( hSysMenu, SC_CLOSE, MF_BYCOMMAND, + NtUserGetMenuState, NULL, NULL ); if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED))) return; } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 46951103bc1..02c5bf88f0e 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -406,7 +406,7 @@ static BOOL grab_clipping_window( const RECT *clip ) if (data->xi2_state != xi_enabled) { WARN( "XInput2 not supported, refusing to clip to %s\n", wine_dbgstr_rect(clip) ); - DestroyWindow( msg_hwnd ); + NtUserDestroyWindow( msg_hwnd ); NtUserClipCursor( NULL ); return TRUE; } @@ -432,7 +432,7 @@ static BOOL grab_clipping_window( const RECT *clip ) if (!clipping_cursor) { disable_xinput2(); - DestroyWindow( msg_hwnd ); + NtUserDestroyWindow( msg_hwnd ); return FALSE; } clip_rect = *clip; @@ -1697,9 +1697,9 @@ void move_resize_window( HWND hwnd, int dir )
while (NtUserPeekMessage( &msg, 0, 0, 0, PM_REMOVE )) { - if (!CallMsgFilterW( &msg, MSGF_SIZE )) + if (!NtUserCallMsgFilter( &msg, MSGF_SIZE )) { - TranslateMessage( &msg ); + NtUserTranslateMessage( &msg, 0 ); NtUserDispatchMessage( &msg ); } } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 7726ba78db0..cfb61c3217a 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2007,13 +2007,16 @@ HWND create_foreign_window( Display *display, Window xwin )
if (!class_registered) { + UNICODE_STRING class_name, version = { 0 }; WNDCLASSEXW class;
memset( &class, 0, sizeof(class) ); class.cbSize = sizeof(class); class.lpfnWndProc = foreign_window_proc; class.lpszClassName = classW; - if (!RegisterClassExW( &class ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) + RtlInitUnicodeString( &class_name, classW ); + if (!NtUserRegisterClassExWOW( &class, &class_name, &version, NULL, 0, 0, NULL ) && + GetLastError() != ERROR_CLASS_ALREADY_EXISTS) { ERR( "Could not register foreign window class\n" ); return FALSE; @@ -2052,7 +2055,7 @@ HWND create_foreign_window( Display *display, Window xwin )
if (!(data = alloc_win_data( display, hwnd ))) { - DestroyWindow( hwnd ); + NtUserDestroyWindow( hwnd ); return 0; } SetRect( &data->window_rect, pos.x, pos.y, pos.x + attr.width, pos.y + attr.height ); @@ -2681,12 +2684,13 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, /* check if the window icon should be hidden (i.e. moved off-screen) */ static BOOL hide_icon( struct x11drv_win_data *data ) { - static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; + static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d'}; + UNICODE_STRING str = { sizeof(trayW), sizeof(trayW), (WCHAR *)trayW };
if (data->managed) return TRUE; /* hide icons in desktop mode when the taskbar is active */ if (!is_virtual_desktop()) return FALSE; - return NtUserIsWindowVisible( FindWindowW( trayW, NULL )); + return NtUserIsWindowVisible( NtUserFindWindowEx( 0, 0, &str, NULL, 0 )); }
/*********************************************************************** diff --git a/dlls/winex11.drv/wintab.c b/dlls/winex11.drv/wintab.c index 44d9c7698aa..a6b80daedbe 100644 --- a/dlls/winex11.drv/wintab.c +++ b/dlls/winex11.drv/wintab.c @@ -536,8 +536,8 @@ NTSTATUS x11drv_tablet_load_info( void *hwnd ) gSysContext.lcSensZ = 65536; gSysContext.lcSysSensX= 65536; gSysContext.lcSysSensY= 65536; - gSysContext.lcSysExtX = GetSystemMetrics(SM_CXVIRTUALSCREEN); - gSysContext.lcSysExtY = GetSystemMetrics(SM_CYVIRTUALSCREEN); + gSysContext.lcSysExtX = NtUserGetSystemMetrics( SM_CXVIRTUALSCREEN ); + gSysContext.lcSysExtY = NtUserGetSystemMetrics( SM_CYVIRTUALSCREEN );
/* initialize cursors */ disable_system_cursors(); @@ -905,7 +905,7 @@ static BOOL motion_event( HWND hwnd, XEvent *event ) gMsgPacket.pkNormalPressure = motion->axis_data[2]; gMsgPacket.pkButtons = get_button_state(curnum); gMsgPacket.pkChanged = get_changed_state(&gMsgPacket); - SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd); + send_message( hwndTabletDefault, WT_PACKET, gMsgPacket.pkSerialNumber, (LPARAM)hwnd ); last_packet = gMsgPacket; return TRUE; } @@ -944,7 +944,7 @@ static BOOL button_event( HWND hwnd, XEvent *event ) } gMsgPacket.pkButtons = get_button_state(curnum); gMsgPacket.pkChanged = get_changed_state(&gMsgPacket); - SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd); + send_message( hwndTabletDefault, WT_PACKET, gMsgPacket.pkSerialNumber, (LPARAM)hwnd ); last_packet = gMsgPacket; return TRUE; } @@ -996,7 +996,7 @@ static BOOL proximity_event( HWND hwnd, XEvent *event ) */ proximity_info = MAKELPARAM((event->type == proximity_in_type), (event->type == proximity_in_type) || (event->type == proximity_out_type)); - SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info); + send_message( hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info ); return TRUE; }
From: Jacek Caban jacek@codeweavers.com
Its implementation doesn't seem to be exposed from win32u and it generally fits well in user space. It will be also useful for drivers.
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/user_main.c | 8 +++++++- dlls/win32u/class.c | 30 +++++++++++++++--------------- dlls/win32u/cursoricon.c | 15 +++++++++++++++ dlls/win32u/defwnd.c | 16 ++++++++-------- dlls/win32u/ntuser_private.h | 1 - include/ntuser.h | 11 +++++++++++ 6 files changed, 56 insertions(+), 25 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index b282056d8c8..9cd9bd60146 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -159,7 +159,6 @@ static void CDECL free_win_ptr( WND *win )
static const struct user_callbacks user_funcs = { - CopyImage, EndMenu, ImmProcessKey, ImmTranslateMessage, @@ -176,6 +175,12 @@ static const struct user_callbacks user_funcs = unregister_imm, };
+static NTSTATUS WINAPI User32CopyImage( const struct copy_image_params *params, ULONG size ) +{ + HANDLE ret = CopyImage( params->hwnd, params->type, params->dx, params->dy, params->flags ); + return HandleToUlong( ret ); +} + static NTSTATUS WINAPI User32FreeCachedClipboardData( const struct free_cached_data_params *params, ULONG size ) { @@ -202,6 +207,7 @@ static const void *kernel_callback_table[NtUserCallCount] = User32CallWinEventHook, User32CallWindowProc, User32CallWindowsHook, + User32CopyImage, User32FreeCachedClipboardData, User32LoadDriver, User32RegisterBuiltinClasses, diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index fd74f63291a..1a6c92edc3a 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -444,11 +444,11 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam class->hbrBackground = wc->hbrBackground; class->winproc = alloc_winproc( wc->lpfnWndProc, ansi ); if (client_menu_name) class->menu_name = *client_menu_name; - if (wc->hIcon && !wc->hIconSm && user_callbacks) - class->hIconSmIntern = user_callbacks->pCopyImage( wc->hIcon, IMAGE_ICON, - get_system_metrics( SM_CXSMICON ), - get_system_metrics( SM_CYSMICON ), - LR_COPYFROMRESOURCE ); + if (wc->hIcon && !wc->hIconSm) + class->hIconSmIntern = CopyImage( wc->hIcon, IMAGE_ICON, + get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), + LR_COPYFROMRESOURCE ); release_class_ptr( class ); return atom; } @@ -699,20 +699,20 @@ static ULONG_PTR set_class_long( HWND hwnd, INT offset, LONG_PTR newval, UINT si NtUserDestroyCursor( class->hIconSmIntern, 0 ); class->hIconSmIntern = NULL; } - if (newval && !class->hIconSm && user_callbacks) - class->hIconSmIntern = user_callbacks->pCopyImage( (HICON)newval, IMAGE_ICON, - get_system_metrics( SM_CXSMICON ), - get_system_metrics( SM_CYSMICON ), - LR_COPYFROMRESOURCE ); + if (newval && !class->hIconSm) + class->hIconSmIntern = CopyImage( (HICON)newval, IMAGE_ICON, + get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), + LR_COPYFROMRESOURCE ); class->hIcon = (HICON)newval; break; case GCLP_HICONSM: retval = (ULONG_PTR)class->hIconSm; - if (retval && !newval && class->hIcon && user_callbacks) - class->hIconSmIntern = user_callbacks->pCopyImage( class->hIcon, IMAGE_ICON, - get_system_metrics( SM_CXSMICON ), - get_system_metrics( SM_CYSMICON ), - LR_COPYFROMRESOURCE ); + if (retval && !newval && class->hIcon) + class->hIconSmIntern = CopyImage( class->hIcon, IMAGE_ICON, + get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), + LR_COPYFROMRESOURCE ); else if (newval && class->hIconSmIntern) { NtUserDestroyCursor( class->hIconSmIntern, 0 ); diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c index 0249eb3da50..032110b26d0 100644 --- a/dlls/win32u/cursoricon.c +++ b/dlls/win32u/cursoricon.c @@ -786,3 +786,18 @@ ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param ) } return ret; } + +/****************************************************************************** + * CopyImage (win32u.so) + */ +HANDLE WINAPI CopyImage( HANDLE hwnd, UINT type, INT dx, INT dy, UINT flags ) +{ + void *ret_ptr; + ULONG ret_len; + NTSTATUS ret; + struct copy_image_params params = + { .hwnd = hwnd, .type = type, .dx = dx, .dy = dy, .flags = flags }; + + ret = KeUserModeCallback( NtUserCopyImage, ¶ms, sizeof(params), &ret_ptr, &ret_len ); + return UlongToHandle( ret ); +} diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 7455a91980c..1fa80928c65 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -123,11 +123,11 @@ static HICON set_window_icon( HWND hwnd, WPARAM type, HICON icon ) { case ICON_SMALL: ret = win->hIconSmall; - if (ret && !icon && win->hIcon && user_callbacks) + if (ret && !icon && win->hIcon) { - win->hIconSmall2 = user_callbacks->pCopyImage( win->hIcon, IMAGE_ICON, - get_system_metrics( SM_CXSMICON ), - get_system_metrics( SM_CYSMICON ), 0 ); + win->hIconSmall2 = CopyImage( win->hIcon, IMAGE_ICON, + get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), 0 ); } else if (icon && win->hIconSmall2) { @@ -144,11 +144,11 @@ static HICON set_window_icon( HWND hwnd, WPARAM type, HICON icon ) NtUserDestroyCursor( win->hIconSmall2, 0 ); win->hIconSmall2 = NULL; } - if (icon && !win->hIconSmall && user_callbacks) + if (icon && !win->hIconSmall) { - win->hIconSmall2 = user_callbacks->pCopyImage( icon, IMAGE_ICON, - get_system_metrics( SM_CXSMICON ), - get_system_metrics( SM_CYSMICON ), 0 ); + win->hIconSmall2 = CopyImage( icon, IMAGE_ICON, + get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), 0 ); } win->hIcon = icon; break; diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 6e25e0ec0db..931c87a6e1c 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -32,7 +32,6 @@ struct hardware_msg_data;
struct user_callbacks { - HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT ); BOOL (WINAPI *pEndMenu)(void); BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD); BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM); diff --git a/include/ntuser.h b/include/ntuser.h index bc44ac76d4e..a39fffaedf9 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -32,6 +32,7 @@ enum NtUserCallWinEventHook, NtUserCallWinProc, NtUserCallWindowsHook, + NtUserCopyImage, NtUserFreeCachedClipboardData, NtUserLoadDriver, NtUserRegisterBuiltinClasses, @@ -146,6 +147,16 @@ struct win_hook_params WCHAR module[MAX_PATH]; };
+/* NtUserCopyMessage params */ +struct copy_image_params +{ + HANDLE hwnd; + UINT type; + INT dx; + INT dy; + UINT flags; +}; + /* NtUserFreeCachedClipboardData params */ struct free_cached_data_params {