win32u: Move WM_NCLBUTTONDOWN implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
This commit is contained in:
Jacek Caban 2022-06-15 02:58:19 +02:00 committed by Alexandre Julliard
parent 80ef8832aa
commit 8ddf64b69a
6 changed files with 175 additions and 348 deletions

View file

@ -121,7 +121,6 @@ extern HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) DECLSPEC_HIDDEN;
/* nonclient area */
extern LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN;
extern LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
extern LRESULT NC_HandleNCMouseMove( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
extern LRESULT NC_HandleNCMouseLeave( HWND hwnd ) DECLSPEC_HIDDEN;
extern LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;

View file

@ -175,9 +175,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
iF10Key = iMenuSysKey = 0;
break;
case WM_NCLBUTTONDOWN:
return NC_HandleNCLButtonDown( hwnd, wParam, lParam );
case WM_LBUTTONDBLCLK:
return NC_HandleNCLButtonDblClk( hwnd, HTCLIENT, lParam );

View file

@ -32,17 +32,6 @@
#include "wine/server.h"
/*******************************************************************
* FOCUS_MouseActivate
*
* Activate a window as a result of a mouse click
*/
BOOL FOCUS_MouseActivate( HWND hwnd )
{
return NtUserSetForegroundWindow( hwnd, TRUE );
}
/*******************************************************************
* SetForegroundWindow (USER32.@)
*/

View file

@ -624,111 +624,6 @@ BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
}
/******************************************************************************
*
* NC_DrawCloseButton
*
* Draws the close button.
*
* If bGrayed is true, then draw a disabled Close button
*
*****************************************************************************/
static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
{
RECT rect;
DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
/* A tool window has a smaller Close button */
if (ex_style & WS_EX_TOOLWINDOW)
{
INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
rect.bottom = rect.top + iBmpHeight;
rect.right = rect.left + iBmpWidth;
}
else
{
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
rect.top += 2;
rect.right -= 2;
}
DrawFrameControl( hdc, &rect, DFC_CAPTION,
(DFCS_CAPTIONCLOSE |
(down ? DFCS_PUSHED : 0) |
(bGrayed ? DFCS_INACTIVE : 0)) );
}
/******************************************************************************
* NC_DrawMaxButton
*
* Draws the maximize button for windows.
* If bGrayed is true, then draw a disabled Maximize button
*/
static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
{
RECT rect;
UINT flags;
DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
/* never draw maximize box when window has WS_EX_TOOLWINDOW style */
if (ex_style & WS_EX_TOOLWINDOW) return;
flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
if (style & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CXSIZE);
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
rect.top += 2;
rect.right -= 2;
if (down) flags |= DFCS_PUSHED;
if (bGrayed) flags |= DFCS_INACTIVE;
DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
}
/******************************************************************************
* NC_DrawMinButton
*
* Draws the minimize button for windows.
* If bGrayed is true, then draw a disabled Minimize button
*/
static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
{
RECT rect;
UINT flags;
DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
/* never draw minimize box when window has WS_EX_TOOLWINDOW style */
if (ex_style & WS_EX_TOOLWINDOW) return;
flags = (style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN;
NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
if (style & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CXSIZE);
if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
rect.top += 2;
rect.right -= 2;
if (down) flags |= DFCS_PUSHED;
if (bGrayed) flags |= DFCS_INACTIVE;
DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
}
/***********************************************************************
* NC_HandleSetCursor
*
@ -798,147 +693,6 @@ void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
}
}
/***********************************************************************
* NC_TrackMinMaxBox
*
* Track a mouse button press on the minimize or maximize box.
*
* The big difference between 3.1 and 95 is the disabled button state.
* In win95 the system button can be disabled, so it can ignore the mouse
* event.
*
*/
static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
{
MSG msg;
HDC hdc = GetWindowDC( hwnd );
BOOL pressed = TRUE;
UINT state;
DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE);
void (*paintButton)(HWND, HDC, BOOL, BOOL);
if (wParam == HTMINBUTTON)
{
/* If the style is not present, do nothing */
if (!(wndStyle & WS_MINIMIZEBOX))
return;
/* Check if the sysmenu item for minimize is there */
state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
paintButton = NC_DrawMinButton;
}
else
{
/* If the style is not present, do nothing */
if (!(wndStyle & WS_MAXIMIZEBOX))
return;
/* Check if the sysmenu item for maximize is there */
state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
paintButton = NC_DrawMaxButton;
}
NtUserSetCapture( hwnd );
(*paintButton)( hwnd, hdc, TRUE, FALSE);
while(1)
{
BOOL oldstate = pressed;
if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue;
if(msg.message == WM_LBUTTONUP)
break;
if(msg.message != WM_MOUSEMOVE)
continue;
pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
if (pressed != oldstate)
(*paintButton)( hwnd, hdc, pressed, FALSE);
}
if(pressed)
(*paintButton)(hwnd, hdc, FALSE, FALSE);
ReleaseCapture();
NtUserReleaseDC( hwnd, hdc );
/* If the minimize or maximize items of the sysmenu are not there */
/* or if the style is not present, do nothing */
if ((!pressed) || (state == 0xFFFFFFFF))
return;
if (wParam == HTMINBUTTON)
SendMessageW( hwnd, WM_SYSCOMMAND,
IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
else
SendMessageW( hwnd, WM_SYSCOMMAND,
IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
}
/***********************************************************************
* NC_TrackCloseButton
*
* Track a mouse button press on the Win95 close button.
*/
static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
MSG msg;
HDC hdc;
BOOL pressed = TRUE;
HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE);
UINT state;
if(hSysMenu == 0)
return;
state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
/* If the close item of the sysmenu is disabled or not present do nothing */
if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
return;
hdc = GetWindowDC( hwnd );
NtUserSetCapture( hwnd );
NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
while(1)
{
BOOL oldstate = pressed;
if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue;
if(msg.message == WM_LBUTTONUP)
break;
if(msg.message != WM_MOUSEMOVE)
continue;
pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
if (pressed != oldstate)
NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
}
if(pressed)
NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
ReleaseCapture();
NtUserReleaseDC( hwnd, hdc );
if (!pressed) return;
SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
}
/***********************************************************************
* NC_TrackScrollBar
@ -963,91 +717,6 @@ static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
}
/***********************************************************************
* NC_HandleNCLButtonDown
*
* Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
*/
LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
switch(wParam) /* Hit test */
{
case HTCAPTION:
{
HWND top = hwnd, parent;
while(1)
{
if ((GetWindowLongW( top, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) != WS_CHILD)
break;
parent = NtUserGetAncestor( top, GA_PARENT );
if (!parent || parent == GetDesktopWindow()) break;
top = parent;
}
if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
break;
}
case HTSYSMENU:
if (style & WS_SYSMENU)
{
HDC hDC = GetWindowDC( hwnd );
NC_DrawSysButton( hwnd, hDC, TRUE );
NtUserReleaseDC( hwnd, hDC );
SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
}
break;
case HTMENU:
SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
break;
case HTHSCROLL:
SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
break;
case HTVSCROLL:
SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
break;
case HTMINBUTTON:
case HTMAXBUTTON:
NC_TrackMinMaxBox( hwnd, wParam );
break;
case HTCLOSE:
NC_TrackCloseButton (hwnd, wParam, lParam);
break;
case HTLEFT:
case HTRIGHT:
case HTTOP:
case HTTOPLEFT:
case HTTOPRIGHT:
case HTBOTTOM:
case HTBOTTOMLEFT:
case HTBOTTOMRIGHT:
/* Old comment:
* "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
* This was previously done by setting wParam=SC_SIZE + wParam - 2
*/
/* But that is not what WinNT does. Instead it sends this. This
* is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
* SC_MOUSEMENU into wParam.
*/
SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
break;
case HTBORDER:
break;
}
return 0;
}
/***********************************************************************
* NC_HandleNCRButtonDown
*

View file

@ -86,7 +86,6 @@ extern void free_cached_data( UINT format, HANDLE handle ) DECLSPEC_HIDDEN;
extern HANDLE render_synthesized_format( UINT format, UINT from ) DECLSPEC_HIDDEN;
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
extern HDC get_display_dc(void) DECLSPEC_HIDDEN;
extern void release_display_dc( HDC hdc ) DECLSPEC_HIDDEN;

View file

@ -1790,6 +1790,177 @@ static LRESULT handle_nc_hit_test( HWND hwnd, POINT pt )
return HTNOWHERE;
}
static void track_min_max_box( HWND hwnd, WORD wparam )
{
HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
DWORD style = get_window_long( hwnd, GWL_STYLE );
HMENU sys_menu = NtUserGetSystemMenu(hwnd, FALSE);
void (*paint_button)( HWND, HDC, BOOL, BOOL );
BOOL pressed = TRUE;
UINT state;
MSG msg;
if (wparam == HTMINBUTTON)
{
/* If the style is not present, do nothing */
if (!(style & WS_MINIMIZEBOX)) return;
/* Check if the sysmenu item for minimize is there */
state = get_menu_state( sys_menu, SC_MINIMIZE, MF_BYCOMMAND );
paint_button = draw_min_button;
}
else
{
/* If the style is not present, do nothing */
if (!(style & WS_MAXIMIZEBOX)) return;
/* Check if the sysmenu item for maximize is there */
state = get_menu_state( sys_menu, SC_MAXIMIZE, MF_BYCOMMAND );
paint_button = draw_max_button;
}
NtUserSetCapture( hwnd );
paint_button( hwnd, hdc, TRUE, FALSE);
for (;;)
{
BOOL oldstate = pressed;
if (!NtUserGetMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue;
if(msg.message == WM_LBUTTONUP) break;
if(msg.message != WM_MOUSEMOVE) continue;
pressed = handle_nc_hit_test( hwnd, msg.pt ) == wparam;
if (pressed != oldstate) paint_button( hwnd, hdc, pressed, FALSE);
}
if (pressed) paint_button( hwnd, hdc, FALSE, FALSE );
release_capture();
NtUserReleaseDC( hwnd, hdc );
/* If the minimize or maximize items of the sysmenu are not there
* or if the style is not present, do nothing */
if (!pressed || state == 0xffffffff) return;
if (wparam == HTMINBUTTON)
send_message( hwnd, WM_SYSCOMMAND,
is_iconic( hwnd ) ? SC_RESTORE : SC_MINIMIZE, MAKELONG( msg.pt.x, msg.pt.y ));
else
send_message( hwnd, WM_SYSCOMMAND,
is_zoomed( hwnd ) ? SC_RESTORE : SC_MAXIMIZE, MAKELONG( msg.pt.x, msg.pt.y ));
}
static void track_close_button( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
HMENU sys_menu;
BOOL pressed = TRUE;
UINT state;
MSG msg;
HDC hdc;
if (!(sys_menu = NtUserGetSystemMenu( hwnd, FALSE ))) return;
state = get_menu_state( sys_menu, SC_CLOSE, MF_BYCOMMAND );
/* If the close item of the sysmenu is disabled or not present do nothing */
if((state & MF_DISABLED) || (state & MF_GRAYED) || state == 0xFFFFFFFF) return;
hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
NtUserSetCapture( hwnd );
draw_close_button( hwnd, hdc, TRUE, FALSE );
for (;;)
{
BOOL oldstate = pressed;
if (!NtUserGetMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue;
if (msg.message == WM_LBUTTONUP) break;
if (msg.message != WM_MOUSEMOVE) continue;
pressed = handle_nc_hit_test( hwnd, msg.pt ) == wparam;
if (pressed != oldstate) draw_close_button( hwnd, hdc, pressed, FALSE );
}
if (pressed) draw_close_button( hwnd, hdc, FALSE, FALSE );
release_capture();
NtUserReleaseDC( hwnd, hdc );
if (pressed) send_message( hwnd, WM_SYSCOMMAND, SC_CLOSE, lparam );
}
static LRESULT handle_nc_lbutton_down( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
LONG style = get_window_long( hwnd, GWL_STYLE );
switch (wparam) /* Hit test */
{
case HTCAPTION:
{
HWND top = hwnd, parent;
for (;;)
{
if ((get_window_long( top, GWL_STYLE ) & (WS_POPUP | WS_CHILD)) != WS_CHILD)
break;
parent = NtUserGetAncestor( top, GA_PARENT );
if (!parent || parent == get_desktop_window()) break;
top = parent;
}
if (set_foreground_window( top, TRUE ) || (get_active_window() == top))
send_message( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lparam );
break;
}
case HTSYSMENU:
if (style & WS_SYSMENU)
{
HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
draw_nc_sys_button( hwnd, hdc, TRUE );
NtUserReleaseDC( hwnd, hdc );
send_message( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lparam );
}
break;
case HTMENU:
send_message( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lparam );
break;
case HTHSCROLL:
send_message( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lparam );
break;
case HTVSCROLL:
send_message( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lparam );
break;
case HTMINBUTTON:
case HTMAXBUTTON:
track_min_max_box( hwnd, wparam );
break;
case HTCLOSE:
track_close_button( hwnd, wparam, lparam );
break;
case HTLEFT:
case HTRIGHT:
case HTTOP:
case HTTOPLEFT:
case HTTOPRIGHT:
case HTBOTTOM:
case HTBOTTOMLEFT:
case HTBOTTOMRIGHT:
send_message( hwnd, WM_SYSCOMMAND, SC_SIZE + wparam - (HTLEFT - WMSZ_LEFT), lparam );
break;
case HTBORDER:
break;
}
return 0;
}
LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi )
{
LRESULT result = 0;
@ -1835,6 +2006,9 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
case WM_NCACTIVATE:
return handle_nc_activate( hwnd, wparam, lparam );
case WM_NCLBUTTONDOWN:
return handle_nc_lbutton_down( hwnd, wparam, lparam );
case WM_WINDOWPOSCHANGING:
return handle_window_pos_changing( hwnd, (WINDOWPOS *)lparam );
@ -1886,7 +2060,7 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
if (result) break;
}
/* Caption clicks are handled by NC_HandleNCLButtonDown() */
/* Caption clicks are handled by handle_nc_lbutton_down() */
result = HIWORD(lparam) == WM_LBUTTONDOWN && LOWORD(lparam) == HTCAPTION ?
MA_NOACTIVATE : MA_ACTIVATE;
break;