win32u: Move process_hardware_message implementation from user32.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4072ba5d8a
commit
5bcb9d1263
|
@ -47,8 +47,6 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(msg);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(key);
|
||||
|
||||
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
|
||||
#define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
|
||||
|
||||
/* Message class descriptor */
|
||||
const struct builtin_class_descr MESSAGE_builtin_class =
|
||||
|
@ -75,26 +73,6 @@ static inline void *unpack_ptr( ULONGLONG ptr64 )
|
|||
return (void *)(ULONG_PTR)ptr64;
|
||||
}
|
||||
|
||||
/* check whether message is in the range of keyboard messages */
|
||||
static inline BOOL is_keyboard_message( UINT message )
|
||||
{
|
||||
return (message >= WM_KEYFIRST && message <= WM_KEYLAST);
|
||||
}
|
||||
|
||||
/* check whether message is in the range of mouse messages */
|
||||
static inline BOOL is_mouse_message( UINT message )
|
||||
{
|
||||
return ((message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST) ||
|
||||
(message >= WM_MOUSEFIRST && message <= WM_MOUSELAST));
|
||||
}
|
||||
|
||||
/* check whether message matches the specified hwnd filter */
|
||||
static inline BOOL check_hwnd_filter( const MSG *msg, HWND hwnd_filter )
|
||||
{
|
||||
if (!hwnd_filter || hwnd_filter == GetDesktopWindow()) return TRUE;
|
||||
return (msg->hwnd == hwnd_filter || IsChild( hwnd_filter, msg->hwnd ));
|
||||
}
|
||||
|
||||
/* check for pending WM_CHAR message with DBCS trailing byte */
|
||||
static inline BOOL get_pending_wmchar( MSG *msg, UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
|
@ -596,51 +574,7 @@ BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* send_parent_notify
|
||||
*
|
||||
* Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
|
||||
* the window has the WS_EX_NOPARENTNOTIFY style.
|
||||
*/
|
||||
static void send_parent_notify( HWND hwnd, WORD event, WORD idChild, POINT pt )
|
||||
{
|
||||
/* pt has to be in the client coordinates of the parent window */
|
||||
MapWindowPoints( 0, hwnd, &pt, 1 );
|
||||
for (;;)
|
||||
{
|
||||
HWND parent;
|
||||
|
||||
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) break;
|
||||
if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) break;
|
||||
if (!(parent = GetParent(hwnd))) break;
|
||||
if (parent == GetDesktopWindow()) break;
|
||||
MapWindowPoints( hwnd, parent, &pt, 1 );
|
||||
hwnd = parent;
|
||||
SendMessageW( hwnd, WM_PARENTNOTIFY,
|
||||
MAKEWPARAM( event, idChild ), MAKELPARAM( pt.x, pt.y ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* accept_hardware_message
|
||||
*
|
||||
* Tell the server we have passed the message to the app
|
||||
* (even though we may end up dropping it later on)
|
||||
*/
|
||||
static void accept_hardware_message( UINT hw_id )
|
||||
{
|
||||
SERVER_START_REQ( accept_hardware_message )
|
||||
{
|
||||
req->hw_id = hw_id;
|
||||
if (wine_server_call( req ))
|
||||
FIXME("Failed to reply to MSG_HARDWARE message. Message may not be removed from queue.\n");
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
|
||||
static BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data )
|
||||
BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data )
|
||||
{
|
||||
struct rawinput_thread_data *thread_data = rawinput_thread_data();
|
||||
|
||||
|
@ -658,333 +592,6 @@ static BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardwar
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* process_keyboard_message
|
||||
*
|
||||
* returns TRUE if the contents of 'msg' should be passed to the application
|
||||
*/
|
||||
static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter,
|
||||
UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
EVENTMSG event;
|
||||
|
||||
if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ||
|
||||
msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
|
||||
switch (msg->wParam)
|
||||
{
|
||||
case VK_LSHIFT: case VK_RSHIFT:
|
||||
msg->wParam = VK_SHIFT;
|
||||
break;
|
||||
case VK_LCONTROL: case VK_RCONTROL:
|
||||
msg->wParam = VK_CONTROL;
|
||||
break;
|
||||
case VK_LMENU: case VK_RMENU:
|
||||
msg->wParam = VK_MENU;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: is this really the right place for this hook? */
|
||||
event.message = msg->message;
|
||||
event.hwnd = msg->hwnd;
|
||||
event.time = msg->time;
|
||||
event.paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
|
||||
event.paramH = msg->lParam & 0x7FFF;
|
||||
if (HIWORD(msg->lParam) & 0x0100) event.paramH |= 0x8000; /* special_key - bit */
|
||||
HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event, TRUE );
|
||||
|
||||
/* check message filters */
|
||||
if (msg->message < first || msg->message > last) return FALSE;
|
||||
if (!check_hwnd_filter( msg, hwnd_filter )) return FALSE;
|
||||
|
||||
if (remove)
|
||||
{
|
||||
if((msg->message == WM_KEYDOWN) &&
|
||||
(msg->hwnd != GetDesktopWindow()))
|
||||
{
|
||||
/* Handle F1 key by sending out WM_HELP message */
|
||||
if (msg->wParam == VK_F1)
|
||||
{
|
||||
PostMessageW( msg->hwnd, WM_KEYF1, 0, 0 );
|
||||
}
|
||||
else if(msg->wParam >= VK_BROWSER_BACK &&
|
||||
msg->wParam <= VK_LAUNCH_APP2)
|
||||
{
|
||||
/* FIXME: Process keystate */
|
||||
SendMessageW(msg->hwnd, WM_APPCOMMAND, (WPARAM)msg->hwnd, MAKELPARAM(0, (FAPPCOMMAND_KEY | (msg->wParam - VK_BROWSER_BACK + 1))));
|
||||
}
|
||||
}
|
||||
else if (msg->message == WM_KEYUP)
|
||||
{
|
||||
/* Handle VK_APPS key by posting a WM_CONTEXTMENU message */
|
||||
if (msg->wParam == VK_APPS && !MENU_IsMenuActive())
|
||||
PostMessageW(msg->hwnd, WM_CONTEXTMENU, (WPARAM)msg->hwnd, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
|
||||
LOWORD(msg->wParam), msg->lParam, TRUE ))
|
||||
{
|
||||
/* skip this message */
|
||||
HOOK_CallHooks( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam, TRUE );
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
if (remove) accept_hardware_message( hw_id );
|
||||
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
|
||||
|
||||
if ( remove && msg->message == WM_KEYDOWN )
|
||||
if (ImmProcessKey(msg->hwnd, NtUserGetKeyboardLayout(0), msg->wParam, msg->lParam, 0) )
|
||||
msg->wParam = VK_PROCESSKEY;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* process_mouse_message
|
||||
*
|
||||
* returns TRUE if the contents of 'msg' should be passed to the application
|
||||
*/
|
||||
static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, HWND hwnd_filter,
|
||||
UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
static MSG clk_msg;
|
||||
|
||||
POINT pt;
|
||||
UINT message;
|
||||
INT hittest;
|
||||
EVENTMSG event;
|
||||
GUITHREADINFO info;
|
||||
MOUSEHOOKSTRUCTEX hook;
|
||||
BOOL eatMsg;
|
||||
WPARAM wparam;
|
||||
|
||||
/* find the window to dispatch this mouse message to */
|
||||
|
||||
info.cbSize = sizeof(info);
|
||||
NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info );
|
||||
if (info.hwndCapture)
|
||||
{
|
||||
hittest = HTCLIENT;
|
||||
msg->hwnd = info.hwndCapture;
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND orig = msg->hwnd;
|
||||
|
||||
msg->hwnd = WINPOS_WindowFromPoint( msg->hwnd, msg->pt, &hittest );
|
||||
if (!msg->hwnd) /* As a heuristic, try the next window if it's the owner of orig */
|
||||
{
|
||||
HWND next = GetWindow( orig, GW_HWNDNEXT );
|
||||
|
||||
if (next && GetWindow( orig, GW_OWNER ) == next && WIN_IsCurrentThread( next ))
|
||||
msg->hwnd = WINPOS_WindowFromPoint( next, msg->pt, &hittest );
|
||||
}
|
||||
}
|
||||
|
||||
if (!msg->hwnd || !WIN_IsCurrentThread( msg->hwnd ))
|
||||
{
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
|
||||
SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( msg->hwnd ));
|
||||
|
||||
/* FIXME: is this really the right place for this hook? */
|
||||
event.message = msg->message;
|
||||
event.time = msg->time;
|
||||
event.hwnd = msg->hwnd;
|
||||
event.paramL = msg->pt.x;
|
||||
event.paramH = msg->pt.y;
|
||||
HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event, TRUE );
|
||||
|
||||
if (!check_hwnd_filter( msg, hwnd_filter )) return FALSE;
|
||||
|
||||
pt = msg->pt;
|
||||
message = msg->message;
|
||||
wparam = msg->wParam;
|
||||
/* Note: windows has no concept of a non-client wheel message */
|
||||
if (message != WM_MOUSEWHEEL)
|
||||
{
|
||||
if (hittest != HTCLIENT)
|
||||
{
|
||||
message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
|
||||
wparam = hittest;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* coordinates don't get translated while tracking a menu */
|
||||
/* FIXME: should differentiate popups and top-level menus */
|
||||
if (!(info.flags & GUI_INMENUMODE))
|
||||
ScreenToClient( msg->hwnd, &pt );
|
||||
}
|
||||
}
|
||||
msg->lParam = MAKELONG( pt.x, pt.y );
|
||||
|
||||
/* translate double clicks */
|
||||
|
||||
if ((msg->message == WM_LBUTTONDOWN) ||
|
||||
(msg->message == WM_RBUTTONDOWN) ||
|
||||
(msg->message == WM_MBUTTONDOWN) ||
|
||||
(msg->message == WM_XBUTTONDOWN))
|
||||
{
|
||||
BOOL update = remove;
|
||||
|
||||
/* translate double clicks -
|
||||
* note that ...MOUSEMOVEs can slip in between
|
||||
* ...BUTTONDOWN and ...BUTTONDBLCLK messages */
|
||||
|
||||
if ((info.flags & (GUI_INMENUMODE|GUI_INMOVESIZE)) ||
|
||||
hittest != HTCLIENT ||
|
||||
(GetClassLongA( msg->hwnd, GCL_STYLE ) & CS_DBLCLKS))
|
||||
{
|
||||
if ((msg->message == clk_msg.message) &&
|
||||
(msg->hwnd == clk_msg.hwnd) &&
|
||||
(msg->wParam == clk_msg.wParam) &&
|
||||
(msg->time - clk_msg.time < NtUserGetDoubleClickTime()) &&
|
||||
(abs(msg->pt.x - clk_msg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK)/2) &&
|
||||
(abs(msg->pt.y - clk_msg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK)/2))
|
||||
{
|
||||
message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
|
||||
if (update)
|
||||
{
|
||||
clk_msg.message = 0; /* clear the double click conditions */
|
||||
update = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (message < first || message > last) return FALSE;
|
||||
/* update static double click conditions */
|
||||
if (update) clk_msg = *msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message < first || message > last) return FALSE;
|
||||
}
|
||||
msg->wParam = wparam;
|
||||
|
||||
/* message is accepted now (but may still get dropped) */
|
||||
|
||||
hook.s.pt = msg->pt;
|
||||
hook.s.hwnd = msg->hwnd;
|
||||
hook.s.wHitTestCode = hittest;
|
||||
hook.s.dwExtraInfo = extra_info;
|
||||
hook.mouseData = msg->wParam;
|
||||
if (HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
|
||||
message, (LPARAM)&hook, TRUE ))
|
||||
{
|
||||
hook.s.pt = msg->pt;
|
||||
hook.s.hwnd = msg->hwnd;
|
||||
hook.s.wHitTestCode = hittest;
|
||||
hook.s.dwExtraInfo = extra_info;
|
||||
hook.mouseData = msg->wParam;
|
||||
HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook, TRUE );
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((hittest == HTERROR) || (hittest == HTNOWHERE))
|
||||
{
|
||||
SendMessageW( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
|
||||
MAKELONG( hittest, msg->message ));
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (remove) accept_hardware_message( hw_id );
|
||||
|
||||
if (!remove || info.hwndCapture)
|
||||
{
|
||||
msg->message = message;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
eatMsg = FALSE;
|
||||
|
||||
if ((msg->message == WM_LBUTTONDOWN) ||
|
||||
(msg->message == WM_RBUTTONDOWN) ||
|
||||
(msg->message == WM_MBUTTONDOWN) ||
|
||||
(msg->message == WM_XBUTTONDOWN))
|
||||
{
|
||||
/* Send the WM_PARENTNOTIFY,
|
||||
* note that even for double/nonclient clicks
|
||||
* notification message is still WM_L/M/RBUTTONDOWN.
|
||||
*/
|
||||
send_parent_notify( msg->hwnd, msg->message, 0, msg->pt );
|
||||
|
||||
/* Activate the window if needed */
|
||||
|
||||
if (msg->hwnd != info.hwndActive)
|
||||
{
|
||||
HWND hwndTop = NtUserGetAncestor( msg->hwnd, GA_ROOT );
|
||||
|
||||
if ((GetWindowLongW( hwndTop, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) != WS_CHILD)
|
||||
{
|
||||
LONG ret = SendMessageW( msg->hwnd, WM_MOUSEACTIVATE, (WPARAM)hwndTop,
|
||||
MAKELONG( hittest, msg->message ) );
|
||||
switch(ret)
|
||||
{
|
||||
case MA_NOACTIVATEANDEAT:
|
||||
eatMsg = TRUE;
|
||||
/* fall through */
|
||||
case MA_NOACTIVATE:
|
||||
break;
|
||||
case MA_ACTIVATEANDEAT:
|
||||
eatMsg = TRUE;
|
||||
/* fall through */
|
||||
case MA_ACTIVATE:
|
||||
case 0:
|
||||
if (!FOCUS_MouseActivate( hwndTop )) eatMsg = TRUE;
|
||||
break;
|
||||
default:
|
||||
WARN( "unknown WM_MOUSEACTIVATE code %d\n", ret );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* send the WM_SETCURSOR message */
|
||||
|
||||
/* Windows sends the normal mouse message as the message parameter
|
||||
in the WM_SETCURSOR message even if it's non-client mouse message */
|
||||
SendMessageW( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, MAKELONG( hittest, msg->message ));
|
||||
|
||||
msg->message = message;
|
||||
return !eatMsg;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* process_hardware_message
|
||||
*
|
||||
* Process a hardware message; return TRUE if message should be passed on to the app
|
||||
*/
|
||||
BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data,
|
||||
HWND hwnd_filter, UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
DPI_AWARENESS_CONTEXT context;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
get_user_thread_info()->msg_source.deviceType = msg_data->source.device;
|
||||
get_user_thread_info()->msg_source.originId = msg_data->source.origin;
|
||||
|
||||
/* hardware messages are always in physical coords */
|
||||
context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
|
||||
|
||||
if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE)
|
||||
ret = process_rawinput_message( msg, hw_id, msg_data );
|
||||
else if (is_keyboard_message( msg->message ))
|
||||
ret = process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove );
|
||||
else if (is_mouse_message( msg->message ))
|
||||
ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove );
|
||||
else
|
||||
ERR( "unknown message type %x\n", msg->message );
|
||||
SetThreadDpiAwarenessContext( context );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SendMessageTimeoutW (USER32.@)
|
||||
|
|
|
@ -164,6 +164,7 @@ static const struct user_callbacks user_funcs =
|
|||
DestroyCaret,
|
||||
EndMenu,
|
||||
HideCaret,
|
||||
ImmProcessKey,
|
||||
SetSystemMenu,
|
||||
ShowCaret,
|
||||
free_menu_items,
|
||||
|
@ -171,7 +172,7 @@ static const struct user_callbacks user_funcs =
|
|||
MENU_IsMenuActive,
|
||||
notify_ime,
|
||||
post_dde_message,
|
||||
process_hardware_message,
|
||||
process_rawinput_message,
|
||||
rawinput_device_get_usages,
|
||||
register_builtin_classes,
|
||||
MENU_SetMenu,
|
||||
|
|
|
@ -85,8 +85,8 @@ extern void rawinput_update_device_list(void);
|
|||
|
||||
extern BOOL post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid,
|
||||
DWORD type ) DECLSPEC_HIDDEN;
|
||||
extern BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data,
|
||||
HWND hwnd_filter, UINT first, UINT last, BOOL remove ) DECLSPEC_HIDDEN;
|
||||
extern BOOL process_rawinput_message( MSG *msg, UINT hw_id,
|
||||
const struct hardware_msg_data *msg_data ) DECLSPEC_HIDDEN;
|
||||
extern BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
|
||||
void **buffer, size_t size ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -296,6 +296,26 @@ static inline BOOL listbox_has_strings( HWND hwnd )
|
|||
return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
|
||||
}
|
||||
|
||||
/* check whether message is in the range of keyboard messages */
|
||||
static inline BOOL is_keyboard_message( UINT message )
|
||||
{
|
||||
return (message >= WM_KEYFIRST && message <= WM_KEYLAST);
|
||||
}
|
||||
|
||||
/* check whether message is in the range of mouse messages */
|
||||
static inline BOOL is_mouse_message( UINT message )
|
||||
{
|
||||
return ((message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST) ||
|
||||
(message >= WM_MOUSEFIRST && message <= WM_MOUSELAST));
|
||||
}
|
||||
|
||||
/* check whether message matches the specified hwnd filter */
|
||||
static inline BOOL check_hwnd_filter( const MSG *msg, HWND hwnd_filter )
|
||||
{
|
||||
if (!hwnd_filter || hwnd_filter == get_desktop_window()) return TRUE;
|
||||
return (msg->hwnd == hwnd_filter || is_child( hwnd_filter, msg->hwnd ));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* unpack_message
|
||||
*
|
||||
|
@ -1224,6 +1244,374 @@ static inline void call_sendmsg_callback( SENDASYNCPROC callback, HWND hwnd, UIN
|
|||
callback, hwnd, debugstr_msg_name( msg, hwnd ), data, result );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* accept_hardware_message
|
||||
*
|
||||
* Tell the server we have passed the message to the app
|
||||
* (even though we may end up dropping it later on)
|
||||
*/
|
||||
static void accept_hardware_message( UINT hw_id )
|
||||
{
|
||||
SERVER_START_REQ( accept_hardware_message )
|
||||
{
|
||||
req->hw_id = hw_id;
|
||||
if (wine_server_call( req ))
|
||||
FIXME("Failed to reply to MSG_HARDWARE message. Message may not be removed from queue.\n");
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* send_parent_notify
|
||||
*
|
||||
* Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
|
||||
* the window has the WS_EX_NOPARENTNOTIFY style.
|
||||
*/
|
||||
static void send_parent_notify( HWND hwnd, WORD event, WORD idChild, POINT pt )
|
||||
{
|
||||
/* pt has to be in the client coordinates of the parent window */
|
||||
map_window_points( 0, hwnd, &pt, 1, get_thread_dpi() );
|
||||
for (;;)
|
||||
{
|
||||
HWND parent;
|
||||
|
||||
if (!(get_window_long( hwnd, GWL_STYLE ) & WS_CHILD)) break;
|
||||
if (get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) break;
|
||||
if (!(parent = get_parent( hwnd ))) break;
|
||||
if (parent == get_desktop_window()) break;
|
||||
map_window_points( hwnd, parent, &pt, 1, get_thread_dpi() );
|
||||
hwnd = parent;
|
||||
send_message( hwnd, WM_PARENTNOTIFY,
|
||||
MAKEWPARAM( event, idChild ), MAKELPARAM( pt.x, pt.y ) );
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* process_keyboard_message
|
||||
*
|
||||
* returns TRUE if the contents of 'msg' should be passed to the application
|
||||
*/
|
||||
static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter,
|
||||
UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
EVENTMSG event;
|
||||
|
||||
if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ||
|
||||
msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
|
||||
switch (msg->wParam)
|
||||
{
|
||||
case VK_LSHIFT: case VK_RSHIFT:
|
||||
msg->wParam = VK_SHIFT;
|
||||
break;
|
||||
case VK_LCONTROL: case VK_RCONTROL:
|
||||
msg->wParam = VK_CONTROL;
|
||||
break;
|
||||
case VK_LMENU: case VK_RMENU:
|
||||
msg->wParam = VK_MENU;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: is this really the right place for this hook? */
|
||||
event.message = msg->message;
|
||||
event.hwnd = msg->hwnd;
|
||||
event.time = msg->time;
|
||||
event.paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
|
||||
event.paramH = msg->lParam & 0x7FFF;
|
||||
if (HIWORD(msg->lParam) & 0x0100) event.paramH |= 0x8000; /* special_key - bit */
|
||||
call_hooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event, TRUE );
|
||||
|
||||
/* check message filters */
|
||||
if (msg->message < first || msg->message > last) return FALSE;
|
||||
if (!check_hwnd_filter( msg, hwnd_filter )) return FALSE;
|
||||
|
||||
if (remove)
|
||||
{
|
||||
if((msg->message == WM_KEYDOWN) &&
|
||||
(msg->hwnd != get_desktop_window()))
|
||||
{
|
||||
/* Handle F1 key by sending out WM_HELP message */
|
||||
if (msg->wParam == VK_F1)
|
||||
{
|
||||
NtUserPostMessage( msg->hwnd, WM_KEYF1, 0, 0 );
|
||||
}
|
||||
else if(msg->wParam >= VK_BROWSER_BACK &&
|
||||
msg->wParam <= VK_LAUNCH_APP2)
|
||||
{
|
||||
/* FIXME: Process keystate */
|
||||
send_message( msg->hwnd, WM_APPCOMMAND, (WPARAM)msg->hwnd,
|
||||
MAKELPARAM(0, (FAPPCOMMAND_KEY | (msg->wParam - VK_BROWSER_BACK + 1))) );
|
||||
}
|
||||
}
|
||||
else if (msg->message == WM_KEYUP)
|
||||
{
|
||||
/* Handle VK_APPS key by posting a WM_CONTEXTMENU message */
|
||||
if (msg->wParam == VK_APPS && user_callbacks && !user_callbacks->is_menu_active())
|
||||
NtUserPostMessage( msg->hwnd, WM_CONTEXTMENU, (WPARAM)msg->hwnd, -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if (call_hooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
|
||||
LOWORD(msg->wParam), msg->lParam, TRUE ))
|
||||
{
|
||||
/* skip this message */
|
||||
call_hooks( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam, TRUE );
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
if (remove) accept_hardware_message( hw_id );
|
||||
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
|
||||
|
||||
if (remove && msg->message == WM_KEYDOWN && user_callbacks)
|
||||
if (user_callbacks->pImmProcessKey( msg->hwnd, NtUserGetKeyboardLayout(0),
|
||||
msg->wParam, msg->lParam, 0 ))
|
||||
msg->wParam = VK_PROCESSKEY;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* process_mouse_message
|
||||
*
|
||||
* returns TRUE if the contents of 'msg' should be passed to the application
|
||||
*/
|
||||
static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, HWND hwnd_filter,
|
||||
UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
static MSG clk_msg;
|
||||
|
||||
POINT pt;
|
||||
UINT message;
|
||||
INT hittest;
|
||||
EVENTMSG event;
|
||||
GUITHREADINFO info;
|
||||
MOUSEHOOKSTRUCTEX hook;
|
||||
BOOL eat_msg;
|
||||
WPARAM wparam;
|
||||
|
||||
/* find the window to dispatch this mouse message to */
|
||||
|
||||
info.cbSize = sizeof(info);
|
||||
NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info );
|
||||
if (info.hwndCapture)
|
||||
{
|
||||
hittest = HTCLIENT;
|
||||
msg->hwnd = info.hwndCapture;
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND orig = msg->hwnd;
|
||||
|
||||
msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest );
|
||||
if (!msg->hwnd) /* As a heuristic, try the next window if it's the owner of orig */
|
||||
{
|
||||
HWND next = get_window_relative( orig, GW_HWNDNEXT );
|
||||
|
||||
if (next && get_window_relative( orig, GW_OWNER ) == next &&
|
||||
is_current_thread_window( next ))
|
||||
msg->hwnd = window_from_point( next, msg->pt, &hittest );
|
||||
}
|
||||
}
|
||||
|
||||
if (!msg->hwnd || !is_current_thread_window( msg->hwnd ))
|
||||
{
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
|
||||
set_thread_dpi_awareness_context( get_window_dpi_awareness_context( msg->hwnd ));
|
||||
|
||||
/* FIXME: is this really the right place for this hook? */
|
||||
event.message = msg->message;
|
||||
event.time = msg->time;
|
||||
event.hwnd = msg->hwnd;
|
||||
event.paramL = msg->pt.x;
|
||||
event.paramH = msg->pt.y;
|
||||
call_hooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event, TRUE );
|
||||
|
||||
if (!check_hwnd_filter( msg, hwnd_filter )) return FALSE;
|
||||
|
||||
pt = msg->pt;
|
||||
message = msg->message;
|
||||
wparam = msg->wParam;
|
||||
/* Note: windows has no concept of a non-client wheel message */
|
||||
if (message != WM_MOUSEWHEEL)
|
||||
{
|
||||
if (hittest != HTCLIENT)
|
||||
{
|
||||
message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
|
||||
wparam = hittest;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* coordinates don't get translated while tracking a menu */
|
||||
/* FIXME: should differentiate popups and top-level menus */
|
||||
if (!(info.flags & GUI_INMENUMODE))
|
||||
screen_to_client( msg->hwnd, &pt );
|
||||
}
|
||||
}
|
||||
msg->lParam = MAKELONG( pt.x, pt.y );
|
||||
|
||||
/* translate double clicks */
|
||||
|
||||
if (msg->message == WM_LBUTTONDOWN ||
|
||||
msg->message == WM_RBUTTONDOWN ||
|
||||
msg->message == WM_MBUTTONDOWN ||
|
||||
msg->message == WM_XBUTTONDOWN)
|
||||
{
|
||||
BOOL update = remove;
|
||||
|
||||
/* translate double clicks -
|
||||
* note that ...MOUSEMOVEs can slip in between
|
||||
* ...BUTTONDOWN and ...BUTTONDBLCLK messages */
|
||||
|
||||
if ((info.flags & (GUI_INMENUMODE|GUI_INMOVESIZE)) ||
|
||||
hittest != HTCLIENT ||
|
||||
(get_class_long( msg->hwnd, GCL_STYLE, FALSE ) & CS_DBLCLKS))
|
||||
{
|
||||
if ((msg->message == clk_msg.message) &&
|
||||
(msg->hwnd == clk_msg.hwnd) &&
|
||||
(msg->wParam == clk_msg.wParam) &&
|
||||
(msg->time - clk_msg.time < NtUserGetDoubleClickTime()) &&
|
||||
(abs(msg->pt.x - clk_msg.pt.x) < get_system_metrics( SM_CXDOUBLECLK ) / 2) &&
|
||||
(abs(msg->pt.y - clk_msg.pt.y) < get_system_metrics( SM_CYDOUBLECLK ) / 2))
|
||||
{
|
||||
message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
|
||||
if (update)
|
||||
{
|
||||
clk_msg.message = 0; /* clear the double click conditions */
|
||||
update = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (message < first || message > last) return FALSE;
|
||||
/* update static double click conditions */
|
||||
if (update) clk_msg = *msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message < first || message > last) return FALSE;
|
||||
}
|
||||
msg->wParam = wparam;
|
||||
|
||||
/* message is accepted now (but may still get dropped) */
|
||||
|
||||
hook.pt = msg->pt;
|
||||
hook.hwnd = msg->hwnd;
|
||||
hook.wHitTestCode = hittest;
|
||||
hook.dwExtraInfo = extra_info;
|
||||
hook.mouseData = msg->wParam;
|
||||
if (call_hooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE, message, (LPARAM)&hook, TRUE ))
|
||||
{
|
||||
hook.pt = msg->pt;
|
||||
hook.hwnd = msg->hwnd;
|
||||
hook.wHitTestCode = hittest;
|
||||
hook.dwExtraInfo = extra_info;
|
||||
hook.mouseData = msg->wParam;
|
||||
call_hooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook, TRUE );
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((hittest == HTERROR) || (hittest == HTNOWHERE))
|
||||
{
|
||||
send_message( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, MAKELONG( hittest, msg->message ));
|
||||
accept_hardware_message( hw_id );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (remove) accept_hardware_message( hw_id );
|
||||
|
||||
if (!remove || info.hwndCapture)
|
||||
{
|
||||
msg->message = message;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
eat_msg = FALSE;
|
||||
|
||||
if (msg->message == WM_LBUTTONDOWN ||
|
||||
msg->message == WM_RBUTTONDOWN ||
|
||||
msg->message == WM_MBUTTONDOWN ||
|
||||
msg->message == WM_XBUTTONDOWN)
|
||||
{
|
||||
/* Send the WM_PARENTNOTIFY,
|
||||
* note that even for double/nonclient clicks
|
||||
* notification message is still WM_L/M/RBUTTONDOWN.
|
||||
*/
|
||||
send_parent_notify( msg->hwnd, msg->message, 0, msg->pt );
|
||||
|
||||
/* Activate the window if needed */
|
||||
|
||||
if (msg->hwnd != info.hwndActive)
|
||||
{
|
||||
HWND hwndTop = NtUserGetAncestor( msg->hwnd, GA_ROOT );
|
||||
|
||||
if ((get_window_long( hwndTop, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) != WS_CHILD)
|
||||
{
|
||||
LONG ret = send_message( msg->hwnd, WM_MOUSEACTIVATE, (WPARAM)hwndTop,
|
||||
MAKELONG( hittest, msg->message ) );
|
||||
switch(ret)
|
||||
{
|
||||
case MA_NOACTIVATEANDEAT:
|
||||
eat_msg = TRUE;
|
||||
/* fall through */
|
||||
case MA_NOACTIVATE:
|
||||
break;
|
||||
case MA_ACTIVATEANDEAT:
|
||||
eat_msg = TRUE;
|
||||
/* fall through */
|
||||
case MA_ACTIVATE:
|
||||
case 0:
|
||||
if (!set_foreground_window( hwndTop, TRUE )) eat_msg = TRUE;
|
||||
break;
|
||||
default:
|
||||
WARN( "unknown WM_MOUSEACTIVATE code %d\n", ret );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* send the WM_SETCURSOR message */
|
||||
|
||||
/* Windows sends the normal mouse message as the message parameter
|
||||
in the WM_SETCURSOR message even if it's non-client mouse message */
|
||||
send_message( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, MAKELONG( hittest, msg->message ));
|
||||
|
||||
msg->message = message;
|
||||
return !eat_msg;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* process_hardware_message
|
||||
*
|
||||
* Process a hardware message; return TRUE if message should be passed on to the app
|
||||
*/
|
||||
static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data,
|
||||
HWND hwnd_filter, UINT first, UINT last, BOOL remove )
|
||||
{
|
||||
DPI_AWARENESS_CONTEXT context;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
get_user_thread_info()->msg_source.deviceType = msg_data->source.device;
|
||||
get_user_thread_info()->msg_source.originId = msg_data->source.origin;
|
||||
|
||||
/* hardware messages are always in physical coords */
|
||||
context = set_thread_dpi_awareness_context( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
|
||||
|
||||
if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE)
|
||||
ret = user_callbacks && user_callbacks->process_rawinput_message( msg, hw_id, msg_data );
|
||||
else if (is_keyboard_message( msg->message ))
|
||||
ret = process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove );
|
||||
else if (is_mouse_message( msg->message ))
|
||||
ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove );
|
||||
else
|
||||
ERR( "unknown message type %x\n", msg->message );
|
||||
set_thread_dpi_awareness_context( context );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* peek_message
|
||||
*
|
||||
|
@ -1402,8 +1790,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
|
|||
if (size >= sizeof(msg_data->hardware))
|
||||
{
|
||||
hw_id = msg_data->hardware.hw_id;
|
||||
if (!user_callbacks) continue;
|
||||
if (!user_callbacks->process_hardware_message( &info.msg, hw_id, &msg_data->hardware,
|
||||
if (!process_hardware_message( &info.msg, hw_id, &msg_data->hardware,
|
||||
hwnd, first, last, flags & PM_REMOVE ))
|
||||
{
|
||||
TRACE("dropping msg %x\n", info.msg.message );
|
||||
|
|
|
@ -37,6 +37,7 @@ struct user_callbacks
|
|||
BOOL (WINAPI *pDestroyCaret)(void);
|
||||
BOOL (WINAPI *pEndMenu)(void);
|
||||
BOOL (WINAPI *pHideCaret)( HWND hwnd );
|
||||
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
|
||||
BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu );
|
||||
BOOL (WINAPI *pShowCaret)( HWND hwnd );
|
||||
void (CDECL *free_menu_items)( void *ptr );
|
||||
|
@ -45,8 +46,7 @@ struct user_callbacks
|
|||
void (CDECL *notify_ime)( HWND hwnd, UINT param );
|
||||
BOOL (CDECL *post_dde_message)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid,
|
||||
DWORD type );
|
||||
BOOL (CDECL *process_hardware_message)( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data,
|
||||
HWND hwnd_filter, UINT first, UINT last, BOOL remove );
|
||||
BOOL (CDECL *process_rawinput_message)( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data );
|
||||
BOOL (CDECL *rawinput_device_get_usages)(HANDLE handle, USHORT *usage_page, USHORT *usage);
|
||||
void (CDECL *register_builtin_classes)(void);
|
||||
BOOL (CDECL *set_menu)( HWND hwnd, HMENU menu );
|
||||
|
|
|
@ -395,9 +395,11 @@ extern BOOL get_client_rect( HWND hwnd, RECT *rect ) DECLSPEC_HIDDEN;
|
|||
extern HWND get_desktop_window(void) DECLSPEC_HIDDEN;
|
||||
extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND get_full_window_handle( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND get_parent( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
|
||||
extern DPI_AWARENESS_CONTEXT get_window_dpi_awareness_context( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern BOOL get_window_placement( HWND hwnd, WINDOWPLACEMENT *placement ) DECLSPEC_HIDDEN;
|
||||
extern HWND get_window_relative( HWND hwnd, UINT rel ) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_window_thread( HWND hwnd, DWORD *process ) DECLSPEC_HIDDEN;
|
||||
extern HWND is_current_process_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND is_current_thread_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
|
@ -414,11 +416,13 @@ extern HWND *list_window_children( HDESK desktop, HWND hwnd, UNICODE_STRING *cla
|
|||
extern int map_window_points( HWND hwnd_from, HWND hwnd_to, POINT *points, UINT count,
|
||||
UINT dpi ) DECLSPEC_HIDDEN;
|
||||
extern void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN;
|
||||
extern BOOL screen_to_client( HWND hwnd, POINT *pt ) DECLSPEC_HIDDEN;
|
||||
extern LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval,
|
||||
BOOL ansi ) DECLSPEC_HIDDEN;
|
||||
extern BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ) DECLSPEC_HIDDEN;
|
||||
extern ULONG set_window_style( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN;
|
||||
extern void update_window_state( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND window_from_point( HWND hwnd, POINT pt, INT *hittest ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* to release pointers retrieved by win_get_ptr */
|
||||
static inline void release_win_ptr( struct tagWND *ptr )
|
||||
|
|
|
@ -344,7 +344,7 @@ DWORD get_window_thread( HWND hwnd, DWORD *process )
|
|||
}
|
||||
|
||||
/* see GetParent */
|
||||
static HWND get_parent( HWND hwnd )
|
||||
HWND get_parent( HWND hwnd )
|
||||
{
|
||||
HWND retval = 0;
|
||||
WND *win;
|
||||
|
@ -479,7 +479,7 @@ HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent )
|
|||
}
|
||||
|
||||
/* see GetWindow */
|
||||
static HWND get_window_relative( HWND hwnd, UINT rel )
|
||||
HWND get_window_relative( HWND hwnd, UINT rel )
|
||||
{
|
||||
HWND retval = 0;
|
||||
|
||||
|
@ -2189,7 +2189,7 @@ static HWND *list_children_from_point( HWND hwnd, POINT pt )
|
|||
*
|
||||
* Find the window and hittest for a given point.
|
||||
*/
|
||||
static HWND window_from_point( HWND hwnd, POINT pt, INT *hittest )
|
||||
HWND window_from_point( HWND hwnd, POINT pt, INT *hittest )
|
||||
{
|
||||
int i, res;
|
||||
HWND ret, *list;
|
||||
|
@ -2588,7 +2588,7 @@ other_process: /* one of the parents may belong to another process, do it the h
|
|||
}
|
||||
|
||||
/* see ScreenToClient */
|
||||
static BOOL screen_to_client( HWND hwnd, POINT *pt )
|
||||
BOOL screen_to_client( HWND hwnd, POINT *pt )
|
||||
{
|
||||
POINT offset;
|
||||
BOOL mirrored;
|
||||
|
|
Loading…
Reference in New Issue