Moved mouse capture handling into the server.
This commit is contained in:
parent
0b850f9f74
commit
a9e8f59c95
|
@ -39,13 +39,12 @@
|
|||
#include "wingdi.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "win.h"
|
||||
#include "controls.h"
|
||||
#include "nonclient.h"
|
||||
#include "user.h"
|
||||
#include "message.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(menu);
|
||||
|
@ -2365,6 +2364,30 @@ static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MENU_SetCapture
|
||||
*/
|
||||
static void MENU_SetCapture( HWND hwnd )
|
||||
{
|
||||
HWND previous = 0;
|
||||
|
||||
SERVER_START_REQ( set_capture_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
req->flags = CAPTURE_MENU;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
previous = reply->previous;
|
||||
hwnd = reply->full_handle;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (previous && previous != hwnd)
|
||||
SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MENU_DoNextMenu
|
||||
*
|
||||
|
@ -2450,9 +2473,8 @@ static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
|
|||
|
||||
if( hNewWnd != pmt->hOwnerWnd )
|
||||
{
|
||||
ReleaseCapture();
|
||||
pmt->hOwnerWnd = hNewWnd;
|
||||
EVENT_Capture( pmt->hOwnerWnd, HTMENU );
|
||||
MENU_SetCapture( pmt->hOwnerWnd );
|
||||
}
|
||||
|
||||
pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */
|
||||
|
@ -2681,7 +2703,7 @@ static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
|
|||
fEndMenu = !fRemove;
|
||||
}
|
||||
|
||||
EVENT_Capture( mt.hOwnerWnd, HTMENU );
|
||||
MENU_SetCapture( mt.hOwnerWnd );
|
||||
|
||||
while (!fEndMenu)
|
||||
{
|
||||
|
@ -2735,14 +2757,12 @@ static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
|
|||
if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
|
||||
{
|
||||
/*
|
||||
* use the mouse coordinates in lParam instead of those in the MSG
|
||||
* struct to properly handle synthetic messages. lParam coords are
|
||||
* relative to client area, so they must be converted; since they can
|
||||
* be negative, we must use SLOWORD/SHIWORD instead of LOWORD/HIWORD.
|
||||
* Use the mouse coordinates in lParam instead of those in the MSG
|
||||
* struct to properly handle synthetic messages. They are already
|
||||
* in screen coordinates.
|
||||
*/
|
||||
mt.pt.x = SLOWORD(msg.lParam);
|
||||
mt.pt.y = SHIWORD(msg.lParam);
|
||||
ClientToScreen(msg.hwnd,&mt.pt);
|
||||
|
||||
/* Find a menu for this mouse event */
|
||||
hmenu = MENU_PtMenu( mt.hTopMenu, mt.pt );
|
||||
|
@ -2911,7 +2931,7 @@ static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
|
|||
else mt.trackFlags &= ~TF_SKIPREMOVE;
|
||||
}
|
||||
|
||||
ReleaseCapture();
|
||||
MENU_SetCapture(0); /* release the capture */
|
||||
|
||||
/* If dropdown is still painted and the close box is clicked on
|
||||
then the menu will be destroyed as part of the DispatchMessage above.
|
||||
|
@ -3967,7 +3987,7 @@ BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
|
|||
if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_CHILD) return FALSE;
|
||||
|
||||
hWnd = WIN_GetFullHandle( hWnd );
|
||||
if (GetCapture() == hWnd) ReleaseCapture();
|
||||
if (GetCapture() == hWnd) MENU_SetCapture(0); /* release the capture */
|
||||
|
||||
if (hMenu != 0)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "nonclient.h"
|
||||
#include "message.h"
|
||||
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
||||
|
@ -1828,6 +1829,29 @@ static LONG start_size_move( HWND hwnd, WPARAM wParam, POINT *capturePoint, LONG
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_movesize_capture
|
||||
*/
|
||||
static void set_movesize_capture( HWND hwnd )
|
||||
{
|
||||
HWND previous = 0;
|
||||
|
||||
SERVER_START_REQ( set_capture_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
req->flags = CAPTURE_MOVESIZE;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
previous = reply->previous;
|
||||
hwnd = reply->full_handle;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (previous && previous != hwnd)
|
||||
SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SysCommandSizeMove (X11DRV.@)
|
||||
*
|
||||
|
@ -1874,11 +1898,11 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
|
|||
if ( hittest && hittest != HTSYSMENU ) hittest += 2;
|
||||
else
|
||||
{
|
||||
SetCapture(hwnd);
|
||||
set_movesize_capture( hwnd );
|
||||
hittest = start_size_move( hwnd, wParam, &capturePoint, style );
|
||||
if (!hittest)
|
||||
{
|
||||
ReleaseCapture();
|
||||
set_movesize_capture(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1938,7 +1962,7 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
|
|||
RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
|
||||
|
||||
SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
|
||||
SetCapture( hwnd );
|
||||
set_movesize_capture( hwnd );
|
||||
|
||||
/* grab the server only when moving top-level windows without desktop */
|
||||
grab = (!DragFullWindows && !parent && (root_window == DefaultRootWindow(gdi_display)));
|
||||
|
@ -2048,7 +2072,7 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
|
|||
}
|
||||
}
|
||||
|
||||
ReleaseCapture();
|
||||
set_movesize_capture(0);
|
||||
if( iconic )
|
||||
{
|
||||
if( moved ) /* restore cursors, show icon title later on */
|
||||
|
|
|
@ -39,8 +39,4 @@ extern void TIMER_RemoveWindowTimers( HWND hwnd );
|
|||
extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue );
|
||||
extern BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc );
|
||||
|
||||
/* input.c */
|
||||
|
||||
extern HWND EVENT_Capture( HWND, INT16 );
|
||||
|
||||
#endif /* __WINE_MESSAGE_H */
|
||||
|
|
|
@ -2802,6 +2802,22 @@ struct set_active_window_reply
|
|||
};
|
||||
|
||||
|
||||
struct set_capture_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
unsigned int flags;
|
||||
};
|
||||
struct set_capture_window_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t previous;
|
||||
user_handle_t full_handle;
|
||||
};
|
||||
#define CAPTURE_MENU 0x01
|
||||
#define CAPTURE_MOVESIZE 0x02
|
||||
|
||||
|
||||
enum request
|
||||
{
|
||||
REQ_new_process,
|
||||
|
@ -2965,6 +2981,7 @@ enum request
|
|||
REQ_set_foreground_window,
|
||||
REQ_set_focus_window,
|
||||
REQ_set_active_window,
|
||||
REQ_set_capture_window,
|
||||
REQ_NB_REQUESTS
|
||||
};
|
||||
|
||||
|
@ -3133,6 +3150,7 @@ union generic_request
|
|||
struct set_foreground_window_request set_foreground_window_request;
|
||||
struct set_focus_window_request set_focus_window_request;
|
||||
struct set_active_window_request set_active_window_request;
|
||||
struct set_capture_window_request set_capture_window_request;
|
||||
};
|
||||
union generic_reply
|
||||
{
|
||||
|
@ -3299,8 +3317,9 @@ union generic_reply
|
|||
struct set_foreground_window_reply set_foreground_window_reply;
|
||||
struct set_focus_window_reply set_focus_window_reply;
|
||||
struct set_active_window_reply set_active_window_reply;
|
||||
struct set_capture_window_reply set_capture_window_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 86
|
||||
#define SERVER_PROTOCOL_VERSION 87
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1955,3 +1955,14 @@ enum message_type
|
|||
@REPLY
|
||||
user_handle_t previous; /* handle to the previous active window */
|
||||
@END
|
||||
|
||||
/* Set the current thread capture window */
|
||||
@REQ(set_capture_window)
|
||||
user_handle_t handle; /* handle to the capture window */
|
||||
unsigned int flags; /* capture flags (see below) */
|
||||
@REPLY
|
||||
user_handle_t previous; /* handle to the previous capture window */
|
||||
user_handle_t full_handle; /* full 32-bit handle of new capture window */
|
||||
@END
|
||||
#define CAPTURE_MENU 0x01 /* capture is for a menu */
|
||||
#define CAPTURE_MOVESIZE 0x02 /* capture is for moving/resizing */
|
||||
|
|
|
@ -1369,3 +1369,22 @@ DECL_HANDLER(set_active_window)
|
|||
else set_error( STATUS_INVALID_HANDLE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* set the current thread capture window */
|
||||
DECL_HANDLER(set_capture_window)
|
||||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
reply->previous = reply->full_handle = 0;
|
||||
if (queue && check_queue_input_window( queue, req->handle ))
|
||||
{
|
||||
struct thread_input *input = queue->input;
|
||||
|
||||
reply->previous = input->capture;
|
||||
input->capture = get_user_full_handle( req->handle );
|
||||
input->menu_owner = (req->flags & CAPTURE_MENU) ? input->capture : 0;
|
||||
input->move_size = (req->flags & CAPTURE_MOVESIZE) ? input->capture : 0;
|
||||
reply->full_handle = input->capture;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,6 +264,7 @@ DECL_HANDLER(get_thread_input);
|
|||
DECL_HANDLER(set_foreground_window);
|
||||
DECL_HANDLER(set_focus_window);
|
||||
DECL_HANDLER(set_active_window);
|
||||
DECL_HANDLER(set_capture_window);
|
||||
|
||||
#ifdef WANT_REQUEST_HANDLERS
|
||||
|
||||
|
@ -431,6 +432,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_set_foreground_window,
|
||||
(req_handler)req_set_focus_window,
|
||||
(req_handler)req_set_active_window,
|
||||
(req_handler)req_set_capture_window,
|
||||
};
|
||||
#endif /* WANT_REQUEST_HANDLERS */
|
||||
|
||||
|
|
|
@ -2233,6 +2233,18 @@ static void dump_set_active_window_reply( const struct set_active_window_reply *
|
|||
fprintf( stderr, " previous=%08x", req->previous );
|
||||
}
|
||||
|
||||
static void dump_set_capture_window_request( const struct set_capture_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x,", req->handle );
|
||||
fprintf( stderr, " flags=%08x", req->flags );
|
||||
}
|
||||
|
||||
static void dump_set_capture_window_reply( const struct set_capture_window_reply *req )
|
||||
{
|
||||
fprintf( stderr, " previous=%08x,", req->previous );
|
||||
fprintf( stderr, " full_handle=%08x", req->full_handle );
|
||||
}
|
||||
|
||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||
(dump_func)dump_new_process_request,
|
||||
(dump_func)dump_get_new_process_info_request,
|
||||
|
@ -2395,6 +2407,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_set_foreground_window_request,
|
||||
(dump_func)dump_set_focus_window_request,
|
||||
(dump_func)dump_set_active_window_request,
|
||||
(dump_func)dump_set_capture_window_request,
|
||||
};
|
||||
|
||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||
|
@ -2559,6 +2572,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_set_foreground_window_reply,
|
||||
(dump_func)dump_set_focus_window_reply,
|
||||
(dump_func)dump_set_active_window_reply,
|
||||
(dump_func)dump_set_capture_window_reply,
|
||||
};
|
||||
|
||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||
|
@ -2723,6 +2737,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"set_foreground_window",
|
||||
"set_focus_window",
|
||||
"set_active_window",
|
||||
"set_capture_window",
|
||||
};
|
||||
|
||||
/* ### make_requests end ### */
|
||||
|
|
104
windows/input.c
104
windows/input.c
|
@ -512,84 +512,28 @@ BOOL WINAPI SetCursorPos( INT x, INT y )
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* EVENT_Capture
|
||||
*
|
||||
* We need this to be able to generate double click messages
|
||||
* when menu code captures mouse in the window without CS_DBLCLK style.
|
||||
*/
|
||||
HWND EVENT_Capture(HWND hwnd, INT16 ht)
|
||||
{
|
||||
HWND capturePrev = 0, captureWnd = 0;
|
||||
MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
|
||||
WND* wndPtr = 0;
|
||||
INT16 captureHT = 0;
|
||||
|
||||
capturePrev = GetCapture();
|
||||
|
||||
if (!hwnd)
|
||||
{
|
||||
captureWnd = 0;
|
||||
captureHT = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
wndPtr = WIN_FindWndPtr( hwnd );
|
||||
if (wndPtr)
|
||||
{
|
||||
TRACE_(win)("(0x%04x)\n", hwnd );
|
||||
captureWnd = wndPtr->hwndSelf;
|
||||
captureHT = ht;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the messageQ for the current thread */
|
||||
if (!(pCurMsgQ = QUEUE_Current()))
|
||||
{
|
||||
WARN_(win)("\tCurrent message queue not found. Exiting!\n" );
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Update the perQ capture window and send messages */
|
||||
if( capturePrev != captureWnd )
|
||||
{
|
||||
if (wndPtr)
|
||||
{
|
||||
/* Retrieve the message queue associated with this window */
|
||||
pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
|
||||
if ( !pMsgQ )
|
||||
{
|
||||
WARN_(win)("\tMessage queue not found. Exiting!\n" );
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Make sure that message queue for the window we are setting capture to
|
||||
* shares the same perQ data as the current threads message queue.
|
||||
*/
|
||||
if ( pCurMsgQ->pQData != pMsgQ->pQData )
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
PERQDATA_SetCaptureWnd( captureWnd, captureHT );
|
||||
if (capturePrev) SendMessageA( capturePrev, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
/* Unlock the queues before returning */
|
||||
if ( pMsgQ )
|
||||
QUEUE_Unlock( pMsgQ );
|
||||
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return capturePrev;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* SetCapture (USER32.@)
|
||||
*/
|
||||
HWND WINAPI SetCapture( HWND hwnd )
|
||||
{
|
||||
return EVENT_Capture( hwnd, HTCLIENT );
|
||||
HWND previous = 0;
|
||||
|
||||
SERVER_START_REQ( set_capture_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
req->flags = 0;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
previous = reply->previous;
|
||||
hwnd = reply->full_handle;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (previous && previous != hwnd)
|
||||
SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
|
||||
return previous;
|
||||
}
|
||||
|
||||
|
||||
|
@ -598,7 +542,7 @@ HWND WINAPI SetCapture( HWND hwnd )
|
|||
*/
|
||||
BOOL WINAPI ReleaseCapture(void)
|
||||
{
|
||||
return (EVENT_Capture( 0, 0 ) != 0);
|
||||
return (SetCapture(0) != 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -607,10 +551,18 @@ BOOL WINAPI ReleaseCapture(void)
|
|||
*/
|
||||
HWND WINAPI GetCapture(void)
|
||||
{
|
||||
INT hittest;
|
||||
return PERQDATA_GetCaptureWnd( &hittest );
|
||||
HWND ret = 0;
|
||||
|
||||
SERVER_START_REQ( get_thread_input )
|
||||
{
|
||||
req->tid = GetCurrentThreadId();
|
||||
if (!wine_server_call_err( req )) ret = reply->capture;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* GetAsyncKeyState (USER32.@)
|
||||
*
|
||||
|
|
|
@ -384,12 +384,14 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info )
|
|||
static MSG clk_msg;
|
||||
|
||||
POINT pt;
|
||||
INT ht, hittest;
|
||||
INT hittest;
|
||||
GUITHREADINFO info;
|
||||
|
||||
/* find the window to dispatch this mouse message to */
|
||||
|
||||
hittest = HTCLIENT;
|
||||
if (!(msg->hwnd = PERQDATA_GetCaptureWnd( &ht )))
|
||||
GetGUIThreadInfo( GetCurrentThreadId(), &info );
|
||||
if (!(msg->hwnd = info.hwndCapture))
|
||||
{
|
||||
/* If no capture HWND, find window which contains the mouse position.
|
||||
* Also find the position of the cursor hot spot (hittest) */
|
||||
|
@ -398,7 +400,6 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info )
|
|||
if (!IsWindow(hWndScope)) hWndScope = 0;
|
||||
if (!(msg->hwnd = WINPOS_WindowFromPoint( hWndScope, msg->pt, &hittest )))
|
||||
msg->hwnd = GetDesktopWindow();
|
||||
ht = hittest;
|
||||
}
|
||||
|
||||
if (HOOK_IsHooked( WH_JOURNALRECORD ))
|
||||
|
@ -423,7 +424,9 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info )
|
|||
* note that ...MOUSEMOVEs can slip in between
|
||||
* ...BUTTONDOWN and ...BUTTONDBLCLK messages */
|
||||
|
||||
if (GetClassLongA( msg->hwnd, GCL_STYLE ) & CS_DBLCLKS || ht != HTCLIENT )
|
||||
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) &&
|
||||
|
@ -447,7 +450,12 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info )
|
|||
msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
|
||||
msg->wParam = hittest;
|
||||
}
|
||||
else ScreenToClient( msg->hwnd, &pt );
|
||||
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 );
|
||||
return TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue