From 8ddf64b69a821d1df029f188755b0928ea81cd9a Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 15 Jun 2022 02:58:19 +0200 Subject: [PATCH] win32u: Move WM_NCLBUTTONDOWN implementation from user32. Signed-off-by: Jacek Caban --- dlls/user32/controls.h | 1 - dlls/user32/defwnd.c | 3 - dlls/user32/focus.c | 11 -- dlls/user32/nonclient.c | 331 ------------------------------------- dlls/user32/user_private.h | 1 - dlls/win32u/defwnd.c | 176 +++++++++++++++++++- 6 files changed, 175 insertions(+), 348 deletions(-) diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index c09ab1233d0..eec6a4babe2 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -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; diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 8f32594fd34..0c783666b7e 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -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 ); diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index c494adce5a6..7e1536ab802 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -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.@) */ diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 96518ed4648..128f633fa33 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -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 * diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index aa3e1565bfa..3997e2410f8 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -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; diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 6ec27fc6725..780570b5ad4 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -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;