[PATCH 7/7] win32u: Move SC_SIZE and SC_MOVE handling from user32.
Jacek Caban
wine at gitlab.winehq.org
Wed Jun 8 19:14:36 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/user32/nonclient.c | 5 -
dlls/user32/win.h | 1 -
dlls/user32/winpos.c | 406 --------------------------------
dlls/win32u/dc.c | 10 +
dlls/win32u/defwnd.c | 437 +++++++++++++++++++++++++++++++++++
dlls/win32u/win32u_private.h | 2 +
dlls/win32u/window.c | 8 +-
include/ntgdi.h | 2 +
include/ntuser.h | 8 -
9 files changed, 453 insertions(+), 426 deletions(-)
diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c
index e677f1aeb66..2ad40b8b116 100644
--- a/dlls/user32/nonclient.c
+++ b/dlls/user32/nonclient.c
@@ -1545,11 +1545,6 @@ LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
switch (wParam & 0xfff0)
{
- case SC_SIZE:
- case SC_MOVE:
- WINPOS_SysCommandSizeMove( hwnd, wParam );
- break;
-
case SC_CLOSE:
return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 9d42aef6645..1dfc8eb0ad1 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -57,7 +57,6 @@ static inline void WIN_ReleasePtr( WND *ptr )
extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode ) DECLSPEC_HIDDEN;
extern void WINPOS_ActivateOtherWindow( HWND hwnd ) DECLSPEC_HIDDEN;
-extern void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) DECLSPEC_HIDDEN;
extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN;
extern UINT get_win_monitor_dpi( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index d38a3df18da..f7f4e8bb427 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -19,31 +19,12 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <string.h>
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
#include "user_private.h"
-#include "winerror.h"
-#include "controls.h"
#include "win.h"
-#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(win);
-#define HAS_THICKFRAME(style) \
- (((style) & WS_THICKFRAME) && \
- !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
-
-#define ON_LEFT_BORDER(hit) \
- (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
-#define ON_RIGHT_BORDER(hit) \
- (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
-#define ON_TOP_BORDER(hit) \
- (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
-#define ON_BOTTOM_BORDER(hit) \
- (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
-
/***********************************************************************
* SwitchToThisWindow (USER32.@)
@@ -358,390 +339,3 @@ UINT WINAPI ArrangeIconicWindows( HWND parent )
{
return NtUserArrangeIconicWindows( parent );
}
-
-
-/***********************************************************************
- * draw_moving_frame
- *
- * Draw the frame used when moving or resizing window.
- */
-static void draw_moving_frame( HWND parent, HDC hdc, RECT *screen_rect, BOOL thickframe )
-{
- RECT rect = *screen_rect;
-
- if (parent) MapWindowPoints( 0, parent, (POINT *)&rect, 2 );
- if (thickframe)
- {
- const int width = GetSystemMetrics(SM_CXFRAME);
- const int height = GetSystemMetrics(SM_CYFRAME);
-
- HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
- PatBlt( hdc, rect.left, rect.top,
- rect.right - rect.left - width, height, PATINVERT );
- PatBlt( hdc, rect.left, rect.top + height, width,
- rect.bottom - rect.top - height, PATINVERT );
- PatBlt( hdc, rect.left + width, rect.bottom - 1,
- rect.right - rect.left - width, -height, PATINVERT );
- PatBlt( hdc, rect.right - 1, rect.top, -width,
- rect.bottom - rect.top - height, PATINVERT );
- SelectObject( hdc, hbrush );
- }
- else DrawFocusRect( hdc, &rect );
-}
-
-
-/***********************************************************************
- * start_size_move
- *
- * Initialization of a move or resize, when initiated from a menu choice.
- * Return hit test code for caption or sizing border.
- */
-static LONG start_size_move( HWND hwnd, WPARAM wParam, POINT *capturePoint, LONG style )
-{
- LONG hittest = 0;
- POINT pt;
- MSG msg;
- RECT rectWindow;
-
- GetWindowRect( hwnd, &rectWindow );
-
- if ((wParam & 0xfff0) == SC_MOVE)
- {
- /* Move pointer at the center of the caption */
- RECT rect = rectWindow;
- /* Note: to be exactly centered we should take the different types
- * of border into account, but it shouldn't make more than a few pixels
- * of difference so let's not bother with that */
- rect.top += GetSystemMetrics(SM_CYBORDER);
- if (style & WS_SYSMENU)
- rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
- if (style & WS_MINIMIZEBOX)
- rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
- if (style & WS_MAXIMIZEBOX)
- rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
- pt.x = (rect.right + rect.left) / 2;
- pt.y = rect.top + GetSystemMetrics(SM_CYSIZE)/2;
- hittest = HTCAPTION;
- *capturePoint = pt;
- }
- else /* SC_SIZE */
- {
- NtUserSetCursor( LoadCursorW( 0, (LPWSTR)IDC_SIZEALL ) );
- pt.x = pt.y = 0;
- while(!hittest)
- {
- if (!GetMessageW( &msg, 0, 0, 0 )) return 0;
- if (NtUserCallMsgFilter( &msg, MSGF_SIZE )) continue;
-
- switch(msg.message)
- {
- case WM_MOUSEMOVE:
- pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
- pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
- hittest = SendMessageW( hwnd, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
- if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
- break;
-
- case WM_LBUTTONUP:
- return 0;
-
- case WM_KEYDOWN:
- switch(msg.wParam)
- {
- case VK_UP:
- hittest = HTTOP;
- pt.x =(rectWindow.left+rectWindow.right)/2;
- pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
- break;
- case VK_DOWN:
- hittest = HTBOTTOM;
- pt.x =(rectWindow.left+rectWindow.right)/2;
- pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
- break;
- case VK_LEFT:
- hittest = HTLEFT;
- pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
- pt.y =(rectWindow.top+rectWindow.bottom)/2;
- break;
- case VK_RIGHT:
- hittest = HTRIGHT;
- pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
- pt.y =(rectWindow.top+rectWindow.bottom)/2;
- break;
- case VK_RETURN:
- case VK_ESCAPE:
- return 0;
- }
- break;
- default:
- TranslateMessage( &msg );
- DispatchMessageW( &msg );
- break;
- }
- }
- *capturePoint = pt;
- }
- NtUserSetCursorPos( pt.x, pt.y );
- SendMessageW( hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
- return hittest;
-}
-
-
-/***********************************************************************
- * WINPOS_SysCommandSizeMove
- *
- * Perform SC_MOVE and SC_SIZE commands.
- */
-void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
-{
- MSG msg;
- RECT sizingRect, mouseRect, origRect;
- HDC hdc;
- HWND parent;
- LONG hittest = (LONG)(wParam & 0x0f);
- WPARAM syscommand = wParam & 0xfff0;
- MINMAXINFO minmax;
- POINT capturePoint, pt;
- LONG style = GetWindowLongW( hwnd, GWL_STYLE );
- BOOL thickframe = HAS_THICKFRAME( style );
- BOOL moved = FALSE;
- DWORD dwPoint = GetMessagePos ();
- BOOL DragFullWindows = TRUE;
- HMONITOR mon = 0;
-
- if (IsZoomed(hwnd) || !IsWindowVisible(hwnd)) return;
-
- pt.x = (short)LOWORD(dwPoint);
- pt.y = (short)HIWORD(dwPoint);
- capturePoint = pt;
- NtUserClipCursor( NULL );
-
- TRACE("hwnd %p command %04Ix, hittest %ld, pos %ld,%ld\n",
- hwnd, syscommand, hittest, pt.x, pt.y);
-
- if (syscommand == SC_MOVE)
- {
- if (!hittest) hittest = start_size_move( hwnd, wParam, &capturePoint, style );
- if (!hittest) return;
- }
- else /* SC_SIZE */
- {
- if ( hittest && (syscommand != SC_MOUSEMENU) )
- hittest += (HTLEFT - WMSZ_LEFT);
- else
- {
- set_capture_window( hwnd, GUI_INMOVESIZE, NULL );
- hittest = start_size_move( hwnd, wParam, &capturePoint, style );
- if (!hittest)
- {
- set_capture_window( 0, GUI_INMOVESIZE, NULL );
- return;
- }
- }
- }
-
- /* Get min/max info */
-
- minmax = NtUserGetMinMaxInfo( hwnd );
- WIN_GetRectangles( hwnd, COORDS_PARENT, &sizingRect, NULL );
- origRect = sizingRect;
- if (style & WS_CHILD)
- {
- parent = GetParent(hwnd);
- GetClientRect( parent, &mouseRect );
- MapWindowPoints( parent, 0, (LPPOINT)&mouseRect, 2 );
- MapWindowPoints( parent, 0, (LPPOINT)&sizingRect, 2 );
- }
- else
- {
- parent = 0;
- mouseRect = get_virtual_screen_rect();
- mon = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
- }
-
- if (ON_LEFT_BORDER(hittest))
- {
- mouseRect.left = max( mouseRect.left, sizingRect.right-minmax.ptMaxTrackSize.x+capturePoint.x-sizingRect.left );
- mouseRect.right = min( mouseRect.right, sizingRect.right-minmax.ptMinTrackSize.x+capturePoint.x-sizingRect.left );
- }
- else if (ON_RIGHT_BORDER(hittest))
- {
- mouseRect.left = max( mouseRect.left, sizingRect.left+minmax.ptMinTrackSize.x+capturePoint.x-sizingRect.right );
- mouseRect.right = min( mouseRect.right, sizingRect.left+minmax.ptMaxTrackSize.x+capturePoint.x-sizingRect.right );
- }
- if (ON_TOP_BORDER(hittest))
- {
- mouseRect.top = max( mouseRect.top, sizingRect.bottom-minmax.ptMaxTrackSize.y+capturePoint.y-sizingRect.top );
- mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minmax.ptMinTrackSize.y+capturePoint.y-sizingRect.top);
- }
- else if (ON_BOTTOM_BORDER(hittest))
- {
- mouseRect.top = max( mouseRect.top, sizingRect.top+minmax.ptMinTrackSize.y+capturePoint.y-sizingRect.bottom );
- mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+minmax.ptMaxTrackSize.y+capturePoint.y-sizingRect.bottom );
- }
-
- /* Retrieve a default cache DC (without using the window style) */
- hdc = NtUserGetDCEx( parent, 0, DCX_CACHE );
-
- /* we only allow disabling the full window drag for child windows */
- if (parent) SystemParametersInfoW( SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0 );
-
- /* repaint the window before moving it around */
- NtUserRedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
-
- SendMessageW( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
- set_capture_window( hwnd, GUI_INMOVESIZE, NULL );
-
- while(1)
- {
- int dx = 0, dy = 0;
-
- if (!GetMessageW( &msg, 0, 0, 0 )) break;
- if (NtUserCallMsgFilter( &msg, MSGF_SIZE )) continue;
-
- /* Exit on button-up, Return, or Esc */
- if ((msg.message == WM_LBUTTONUP) ||
- ((msg.message == WM_KEYDOWN) &&
- ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
-
- if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
- {
- TranslateMessage( &msg );
- DispatchMessageW( &msg );
- continue; /* We are not interested in other messages */
- }
-
- pt = msg.pt;
-
- if (msg.message == WM_KEYDOWN) switch(msg.wParam)
- {
- case VK_UP: pt.y -= 8; break;
- case VK_DOWN: pt.y += 8; break;
- case VK_LEFT: pt.x -= 8; break;
- case VK_RIGHT: pt.x += 8; break;
- }
-
- pt.x = max( pt.x, mouseRect.left );
- pt.x = min( pt.x, mouseRect.right - 1 );
- pt.y = max( pt.y, mouseRect.top );
- pt.y = min( pt.y, mouseRect.bottom - 1 );
-
- if (!parent)
- {
- HMONITOR newmon;
- MONITORINFO info;
-
- if ((newmon = MonitorFromPoint( pt, MONITOR_DEFAULTTONULL )))
- mon = newmon;
-
- info.cbSize = sizeof(info);
- if (mon && GetMonitorInfoW( mon, &info ))
- {
- pt.x = max( pt.x, info.rcWork.left );
- pt.x = min( pt.x, info.rcWork.right - 1 );
- pt.y = max( pt.y, info.rcWork.top );
- pt.y = min( pt.y, info.rcWork.bottom - 1 );
- }
- }
-
- dx = pt.x - capturePoint.x;
- dy = pt.y - capturePoint.y;
-
- if (dx || dy)
- {
- if( !moved )
- {
- moved = TRUE;
- if (!DragFullWindows)
- draw_moving_frame( parent, hdc, &sizingRect, thickframe );
- }
-
- if (msg.message == WM_KEYDOWN) NtUserSetCursorPos( pt.x, pt.y );
- else
- {
- if (!DragFullWindows) draw_moving_frame( parent, hdc, &sizingRect, thickframe );
- if (hittest == HTCAPTION || hittest == HTBORDER) OffsetRect( &sizingRect, dx, dy );
- if (ON_LEFT_BORDER(hittest)) sizingRect.left += dx;
- else if (ON_RIGHT_BORDER(hittest)) sizingRect.right += dx;
- if (ON_TOP_BORDER(hittest)) sizingRect.top += dy;
- else if (ON_BOTTOM_BORDER(hittest)) sizingRect.bottom += dy;
- capturePoint = pt;
-
- /* determine the hit location */
- if (syscommand == SC_SIZE && hittest != HTBORDER)
- {
- WPARAM wpSizingHit = 0;
-
- if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
- wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
- SendMessageW( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&sizingRect );
- }
- else
- SendMessageW( hwnd, WM_MOVING, 0, (LPARAM)&sizingRect );
-
- if (!DragFullWindows)
- draw_moving_frame( parent, hdc, &sizingRect, thickframe );
- else
- {
- RECT rect = sizingRect;
- MapWindowPoints( 0, parent, (POINT *)&rect, 2 );
- NtUserSetWindowPos( hwnd, 0, rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top,
- (hittest == HTCAPTION) ? SWP_NOSIZE : 0 );
- }
- }
- }
- }
-
- if (moved && !DragFullWindows)
- {
- draw_moving_frame( parent, hdc, &sizingRect, thickframe );
- }
-
- set_capture_window( 0, GUI_INMOVESIZE, NULL );
- NtUserReleaseDC( parent, hdc );
- if (parent) MapWindowPoints( 0, parent, (POINT *)&sizingRect, 2 );
-
- if (HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, (WPARAM)hwnd, (LPARAM)&sizingRect, TRUE ))
- moved = FALSE;
-
- SendMessageW( hwnd, WM_EXITSIZEMOVE, 0, 0 );
- SendMessageW( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
-
- /* window moved or resized */
- if (moved)
- {
- /* if the moving/resizing isn't canceled call SetWindowPos
- * with the new position or the new size of the window
- */
- if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
- {
- /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
- if (!DragFullWindows)
- NtUserSetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
- sizingRect.right - sizingRect.left,
- sizingRect.bottom - sizingRect.top,
- ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
- }
- else
- { /* restore previous size/position */
- if(DragFullWindows)
- NtUserSetWindowPos( hwnd, 0, origRect.left, origRect.top,
- origRect.right - origRect.left,
- origRect.bottom - origRect.top,
- ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
- }
- }
-
- if (IsIconic(hwnd))
- {
- /* Single click brings up the system menu when iconized */
-
- if( !moved )
- {
- if(style & WS_SYSMENU )
- SendMessageW( hwnd, WM_SYSCOMMAND,
- SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
- }
- }
-}
diff --git a/dlls/win32u/dc.c b/dlls/win32u/dc.c
index 95dd2651929..f50c13d18bb 100644
--- a/dlls/win32u/dc.c
+++ b/dlls/win32u/dc.c
@@ -932,6 +932,11 @@ BOOL WINAPI NtGdiGetAndSetDCDword( HDC hdc, UINT method, DWORD value, DWORD *pre
set_bk_color( dc, value );
break;
+ case NtGdiSetBkMode:
+ prev = dc->attr->background_mode;
+ dc->attr->background_mode = value;
+ break;
+
case NtGdiSetTextColor:
prev = dc->attr->text_color;
set_text_color( dc, value );
@@ -956,6 +961,11 @@ BOOL WINAPI NtGdiGetAndSetDCDword( HDC hdc, UINT method, DWORD value, DWORD *pre
ret = set_graphics_mode( dc, value );
break;
+ case NtGdiSetROP2:
+ prev = dc->attr->rop_mode;
+ dc->attr->rop_mode = value;
+ break;
+
default:
WARN( "unknown method %u\n", method );
ret = FALSE;
diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c
index 9b4edc90eaa..3dc0ff1187b 100644
--- a/dlls/win32u/defwnd.c
+++ b/dlls/win32u/defwnd.c
@@ -42,6 +42,30 @@ void fill_rect( HDC dc, const RECT *rect, HBRUSH hbrush )
if (prev_brush) NtGdiSelectBrush( dc, prev_brush );
}
+/* see DrawFocusRect */
+static BOOL draw_focus_rect( HDC hdc, const RECT *rc )
+{
+ DWORD prev_draw_mode, prev_bk_mode;
+ HPEN prev_pen, pen;
+ HBRUSH prev_brush;
+
+ prev_brush = NtGdiSelectBrush(hdc, GetStockObject(NULL_BRUSH));
+ pen = NtGdiExtCreatePen( PS_COSMETIC|PS_ALTERNATE, 1, BS_SOLID,
+ 0, 0, 0, 0, NULL, 0, FALSE, NULL );
+ prev_pen = NtGdiSelectPen(hdc, pen);
+ NtGdiGetAndSetDCDword( hdc, NtGdiSetROP2, R2_NOT, &prev_draw_mode );
+ NtGdiGetAndSetDCDword( hdc, NtGdiSetBkMode, TRANSPARENT, &prev_bk_mode );
+
+ NtGdiRectangle( hdc, rc->left, rc->top, rc->right, rc->bottom );
+
+ NtGdiGetAndSetDCDword( hdc, NtGdiSetBkMode, prev_bk_mode, NULL );
+ NtGdiGetAndSetDCDword( hdc, NtGdiSetROP2, prev_draw_mode, NULL );
+ NtGdiSelectPen( hdc, prev_pen );
+ NtGdiDeleteObjectApp( pen );
+ NtGdiSelectBrush( hdc, prev_brush );
+ return TRUE;
+}
+
/***********************************************************************
* AdjustWindowRectEx (win32u.so)
*/
@@ -216,6 +240,414 @@ static LONG handle_window_pos_changing( HWND hwnd, WINDOWPOS *winpos )
return 0;
}
+/***********************************************************************
+ * draw_moving_frame
+ *
+ * Draw the frame used when moving or resizing window.
+ */
+static void draw_moving_frame( HWND parent, HDC hdc, RECT *screen_rect, BOOL thickframe )
+{
+ RECT rect = *screen_rect;
+
+ if (parent) map_window_points( 0, parent, (POINT *)&rect, 2, get_thread_dpi() );
+ if (thickframe)
+ {
+ const int width = get_system_metrics( SM_CXFRAME );
+ const int height = get_system_metrics( SM_CYFRAME );
+
+ HBRUSH hbrush = NtGdiSelectBrush( hdc, GetStockObject( GRAY_BRUSH ));
+ NtGdiPatBlt( hdc, rect.left, rect.top,
+ rect.right - rect.left - width, height, PATINVERT );
+ NtGdiPatBlt( hdc, rect.left, rect.top + height, width,
+ rect.bottom - rect.top - height, PATINVERT );
+ NtGdiPatBlt( hdc, rect.left + width, rect.bottom - 1,
+ rect.right - rect.left - width, -height, PATINVERT );
+ NtGdiPatBlt( hdc, rect.right - 1, rect.top, -width,
+ rect.bottom - rect.top - height, PATINVERT );
+ NtGdiSelectBrush( hdc, hbrush );
+ }
+ else draw_focus_rect( hdc, &rect );
+}
+
+/***********************************************************************
+ * start_size_move
+ *
+ * Initialization of a move or resize, when initiated from a menu choice.
+ * Return hit test code for caption or sizing border.
+ */
+static LONG start_size_move( HWND hwnd, WPARAM wparam, POINT *capture_point, LONG style )
+{
+ RECT window_rect;
+ LONG hittest = 0;
+ POINT pt;
+ MSG msg;
+
+ get_window_rect( hwnd, &window_rect, get_thread_dpi() );
+
+ if ((wparam & 0xfff0) == SC_MOVE)
+ {
+ /* Move pointer at the center of the caption */
+ RECT rect = window_rect;
+ /* Note: to be exactly centered we should take the different types
+ * of border into account, but it shouldn't make more than a few pixels
+ * of difference so let's not bother with that */
+ rect.top += get_system_metrics( SM_CYBORDER );
+ if (style & WS_SYSMENU) rect.left += get_system_metrics( SM_CXSIZE ) + 1;
+ if (style & WS_MINIMIZEBOX) rect.right -= get_system_metrics( SM_CXSIZE ) + 1;
+ if (style & WS_MAXIMIZEBOX) rect.right -= get_system_metrics( SM_CXSIZE ) + 1;
+ pt.x = (rect.right + rect.left) / 2;
+ pt.y = rect.top + get_system_metrics( SM_CYSIZE ) / 2;
+ hittest = HTCAPTION;
+ *capture_point = pt;
+ }
+ else /* SC_SIZE */
+ {
+ HCURSOR cursor;
+ cursor = LoadImageW( 0, (WCHAR *)IDC_SIZEALL, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE );
+ NtUserSetCursor( cursor );
+ pt.x = pt.y = 0;
+ while (!hittest)
+ {
+ if (!NtUserGetMessage( &msg, 0, 0, 0 )) return 0;
+ if (NtUserCallMsgFilter( &msg, MSGF_SIZE )) continue;
+
+ switch (msg.message)
+ {
+ case WM_MOUSEMOVE:
+ pt.x = min( max( msg.pt.x, window_rect.left ), window_rect.right - 1 );
+ pt.y = min( max( msg.pt.y, window_rect.top ), window_rect.bottom - 1 );
+ hittest = send_message( hwnd, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ));
+ if (hittest < HTLEFT || hittest > HTBOTTOMRIGHT) hittest = 0;
+ break;
+
+ case WM_LBUTTONUP:
+ return 0;
+
+ case WM_KEYDOWN:
+ switch (msg.wParam)
+ {
+ case VK_UP:
+ hittest = HTTOP;
+ pt.x = (window_rect.left + window_rect.right) / 2;
+ pt.y = window_rect.top + get_system_metrics( SM_CYFRAME ) / 2;
+ break;
+ case VK_DOWN:
+ hittest = HTBOTTOM;
+ pt.x = (window_rect.left + window_rect.right) / 2;
+ pt.y = window_rect.bottom - get_system_metrics( SM_CYFRAME ) / 2;
+ break;
+ case VK_LEFT:
+ hittest = HTLEFT;
+ pt.x = window_rect.left + get_system_metrics( SM_CXFRAME ) / 2;
+ pt.y = (window_rect.top + window_rect.bottom) / 2;
+ break;
+ case VK_RIGHT:
+ hittest = HTRIGHT;
+ pt.x = window_rect.right - get_system_metrics( SM_CXFRAME ) / 2;
+ pt.y = (window_rect.top + window_rect.bottom) / 2;
+ break;
+ case VK_RETURN:
+ case VK_ESCAPE:
+ return 0;
+ }
+ break;
+ default:
+ NtUserTranslateMessage( &msg, 0 );
+ NtUserDispatchMessage( &msg );
+ break;
+ }
+ }
+ *capture_point = pt;
+ }
+ NtUserSetCursorPos( pt.x, pt.y );
+ send_message( hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
+ return hittest;
+}
+
+static BOOL on_left_border( int hit )
+{
+ return hit == HTLEFT || hit == HTTOPLEFT || hit == HTBOTTOMLEFT;
+}
+
+static BOOL on_right_border( int hit )
+{
+ return hit == HTRIGHT || hit == HTTOPRIGHT || hit == HTBOTTOMRIGHT;
+}
+
+static BOOL on_top_border( int hit )
+{
+ return hit == HTTOP || hit == HTTOPLEFT || hit == HTTOPRIGHT;
+}
+
+static BOOL on_bottom_border( int hit )
+{
+ return hit == HTBOTTOM || hit == HTBOTTOMLEFT || hit == HTBOTTOMRIGHT;
+}
+
+/***********************************************************************
+ * sys_command_size_move
+ *
+ * Perform SC_MOVE and SC_SIZE commands.
+ */
+static void sys_command_size_move( HWND hwnd, WPARAM wparam )
+{
+ DWORD msg_pos = NtUserGetThreadInfo()->message_pos;
+ BOOL thickframe, drag_full_windows = TRUE, moved = FALSE;
+ RECT sizing_rect, mouse_rect, orig_rect;
+ LONG hittest = wparam & 0x0f;
+ WPARAM syscommand = wparam & 0xfff0;
+ LONG style = get_window_long( hwnd, GWL_STYLE );
+ POINT capture_point, pt;
+ MINMAXINFO minmax;
+ HMONITOR mon = 0;
+ HWND parent;
+ UINT dpi;
+ HDC hdc;
+ MSG msg;
+
+ if (is_zoomed( hwnd ) || !is_window_visible( hwnd )) return;
+
+ thickframe = (style & WS_THICKFRAME) && !((style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME);
+
+ pt.x = (short)LOWORD(msg_pos);
+ pt.y = (short)HIWORD(msg_pos);
+ capture_point = pt;
+ NtUserClipCursor( NULL );
+
+ TRACE( "hwnd %p command %04lx, hittest %d, pos %d,%d\n",
+ hwnd, syscommand, hittest, pt.x, pt.y );
+
+ if (syscommand == SC_MOVE)
+ {
+ if (!hittest) hittest = start_size_move( hwnd, wparam, &capture_point, style );
+ if (!hittest) return;
+ }
+ else /* SC_SIZE */
+ {
+ if (hittest && syscommand != SC_MOUSEMENU)
+ hittest += (HTLEFT - WMSZ_LEFT);
+ else
+ {
+ set_capture_window( hwnd, GUI_INMOVESIZE, NULL );
+ hittest = start_size_move( hwnd, wparam, &capture_point, style );
+ if (!hittest)
+ {
+ set_capture_window( 0, GUI_INMOVESIZE, NULL );
+ return;
+ }
+ }
+ }
+
+ minmax = get_min_max_info( hwnd );
+ dpi = get_thread_dpi();
+ get_window_rects( hwnd, COORDS_PARENT, &sizing_rect, NULL, dpi );
+ orig_rect = sizing_rect;
+ if (style & WS_CHILD)
+ {
+ parent = get_parent( hwnd );
+ get_client_rect( parent, &mouse_rect );
+ map_window_points( parent, 0, (POINT *)&mouse_rect, 2, dpi );
+ map_window_points( parent, 0, (POINT *)&sizing_rect, 2, dpi );
+ }
+ else
+ {
+ parent = 0;
+ mouse_rect = get_virtual_screen_rect( get_thread_dpi() );
+ mon = monitor_from_point( pt, MONITOR_DEFAULTTONEAREST, dpi );
+ }
+
+ if (on_left_border( hittest ))
+ {
+ mouse_rect.left = max( mouse_rect.left,
+ sizing_rect.right - minmax.ptMaxTrackSize.x + capture_point.x - sizing_rect.left );
+ mouse_rect.right = min( mouse_rect.right,
+ sizing_rect.right - minmax.ptMinTrackSize.x + capture_point.x - sizing_rect.left );
+ }
+ else if (on_right_border( hittest ))
+ {
+ mouse_rect.left = max( mouse_rect.left,
+ sizing_rect.left + minmax.ptMinTrackSize.x + capture_point.x - sizing_rect.right );
+ mouse_rect.right = min( mouse_rect.right,
+ sizing_rect.left + minmax.ptMaxTrackSize.x + capture_point.x - sizing_rect.right );
+ }
+
+ if (on_top_border( hittest ))
+ {
+ mouse_rect.top = max( mouse_rect.top,
+ sizing_rect.bottom - minmax.ptMaxTrackSize.y + capture_point.y - sizing_rect.top );
+ mouse_rect.bottom = min( mouse_rect.bottom,
+ sizing_rect.bottom - minmax.ptMinTrackSize.y + capture_point.y - sizing_rect.top );
+ }
+ else if (on_bottom_border( hittest ))
+ {
+ mouse_rect.top = max( mouse_rect.top,
+ sizing_rect.top + minmax.ptMinTrackSize.y + capture_point.y - sizing_rect.bottom );
+ mouse_rect.bottom = min( mouse_rect.bottom,
+ sizing_rect.top + minmax.ptMaxTrackSize.y + capture_point.y - sizing_rect.bottom );
+ }
+
+ /* Retrieve a default cache DC (without using the window style) */
+ hdc = NtUserGetDCEx( parent, 0, DCX_CACHE );
+
+ /* we only allow disabling the full window drag for child windows */
+ if (parent) NtUserSystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &drag_full_windows, 0 );
+
+ /* repaint the window before moving it around */
+ NtUserRedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
+
+ send_message( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
+ set_capture_window( hwnd, GUI_INMOVESIZE, NULL );
+
+ for (;;)
+ {
+ int dx = 0, dy = 0;
+
+ if (!NtUserGetMessage( &msg, 0, 0, 0 )) break;
+ if (NtUserCallMsgFilter( &msg, MSGF_SIZE )) continue;
+
+ /* Exit on button-up, Return, or Esc */
+ if (msg.message == WM_LBUTTONUP ||
+ (msg.message == WM_KEYDOWN && (msg.wParam == VK_RETURN || msg.wParam == VK_ESCAPE)))
+ break;
+
+ if (msg.message != WM_KEYDOWN && msg.message != WM_MOUSEMOVE)
+ {
+ NtUserTranslateMessage( &msg, 0 );
+ NtUserDispatchMessage( &msg );
+ continue; /* We are not interested in other messages */
+ }
+
+ pt = msg.pt;
+
+ if (msg.message == WM_KEYDOWN)
+ {
+ switch (msg.wParam)
+ {
+ case VK_UP: pt.y -= 8; break;
+ case VK_DOWN: pt.y += 8; break;
+ case VK_LEFT: pt.x -= 8; break;
+ case VK_RIGHT: pt.x += 8; break;
+ }
+ }
+
+ pt.x = max( pt.x, mouse_rect.left );
+ pt.x = min( pt.x, mouse_rect.right - 1 );
+ pt.y = max( pt.y, mouse_rect.top );
+ pt.y = min( pt.y, mouse_rect.bottom - 1 );
+
+ if (!parent)
+ {
+ HMONITOR newmon;
+ MONITORINFO info;
+
+ if ((newmon = monitor_from_point( pt, MONITOR_DEFAULTTONULL, get_thread_dpi() )))
+ mon = newmon;
+
+ info.cbSize = sizeof(info);
+ if (mon && get_monitor_info( mon, &info ))
+ {
+ pt.x = max( pt.x, info.rcWork.left );
+ pt.x = min( pt.x, info.rcWork.right - 1 );
+ pt.y = max( pt.y, info.rcWork.top );
+ pt.y = min( pt.y, info.rcWork.bottom - 1 );
+ }
+ }
+
+ dx = pt.x - capture_point.x;
+ dy = pt.y - capture_point.y;
+
+ if (dx || dy)
+ {
+ if (!moved)
+ {
+ moved = TRUE;
+ if (!drag_full_windows)
+ draw_moving_frame( parent, hdc, &sizing_rect, thickframe );
+ }
+
+ if (msg.message == WM_KEYDOWN) NtUserSetCursorPos( pt.x, pt.y );
+ else
+ {
+ if (!drag_full_windows) draw_moving_frame( parent, hdc, &sizing_rect, thickframe );
+ if (hittest == HTCAPTION || hittest == HTBORDER) OffsetRect( &sizing_rect, dx, dy );
+ if (on_left_border( hittest )) sizing_rect.left += dx;
+ else if (on_right_border( hittest )) sizing_rect.right += dx;
+ if (on_top_border( hittest )) sizing_rect.top += dy;
+ else if (on_bottom_border( hittest )) sizing_rect.bottom += dy;
+ capture_point = pt;
+
+ /* determine the hit location */
+ if (syscommand == SC_SIZE && hittest != HTBORDER)
+ {
+ WPARAM sizing_hit = 0;
+
+ if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
+ sizing_hit = WMSZ_LEFT + (hittest - HTLEFT);
+ send_message( hwnd, WM_SIZING, sizing_hit, (LPARAM)&sizing_rect );
+ }
+ else
+ send_message( hwnd, WM_MOVING, 0, (LPARAM)&sizing_rect );
+
+ if (!drag_full_windows)
+ draw_moving_frame( parent, hdc, &sizing_rect, thickframe );
+ else
+ {
+ RECT rect = sizing_rect;
+ map_window_points( 0, parent, (POINT *)&rect, 2, get_thread_dpi() );
+ NtUserSetWindowPos( hwnd, 0, rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ hittest == HTCAPTION ? SWP_NOSIZE : 0 );
+ }
+ }
+ }
+ }
+
+ if (moved && !drag_full_windows)
+ draw_moving_frame( parent, hdc, &sizing_rect, thickframe );
+
+ set_capture_window( 0, GUI_INMOVESIZE, NULL );
+ NtUserReleaseDC( parent, hdc );
+ if (parent) map_window_points( 0, parent, (POINT *)&sizing_rect, 2, get_thread_dpi() );
+
+ if (call_hooks( WH_CBT, HCBT_MOVESIZE, (WPARAM)hwnd, (LPARAM)&sizing_rect, TRUE ))
+ moved = FALSE;
+
+ send_message( hwnd, WM_EXITSIZEMOVE, 0, 0 );
+ send_message( hwnd, WM_SETVISIBLE, !is_iconic(hwnd), 0 );
+
+ /* window moved or resized */
+ if (moved)
+ {
+ /* if the moving/resizing isn't canceled call SetWindowPos
+ * with the new position or the new size of the window
+ */
+ if (!(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) )
+ {
+ /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
+ if (!drag_full_windows)
+ NtUserSetWindowPos( hwnd, 0, sizing_rect.left, sizing_rect.top,
+ sizing_rect.right - sizing_rect.left,
+ sizing_rect.bottom - sizing_rect.top,
+ hittest == HTCAPTION ? SWP_NOSIZE : 0 );
+ }
+ else
+ {
+ /* restore previous size/position */
+ if (drag_full_windows)
+ NtUserSetWindowPos( hwnd, 0, orig_rect.left, orig_rect.top,
+ orig_rect.right - orig_rect.left,
+ orig_rect.bottom - orig_rect.top,
+ hittest == HTCAPTION ? SWP_NOSIZE : 0 );
+ }
+ }
+
+ if (is_iconic(hwnd) && !moved && (style & WS_SYSMENU))
+ {
+ /* Single click brings up the system menu when iconized */
+ send_message( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x, pt.y) );
+ }
+}
+
static LRESULT handle_sys_command( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
if (!is_window_enabled( hwnd )) return 0;
@@ -228,6 +660,11 @@ static LRESULT handle_sys_command( HWND hwnd, WPARAM wparam, LPARAM lparam )
switch (wparam & 0xfff0)
{
+ case SC_SIZE:
+ case SC_MOVE:
+ sys_command_size_move( hwnd, wparam );
+ break;
+
case SC_MINIMIZE:
show_owned_popups( hwnd, FALSE );
NtUserShowWindow( hwnd, SW_MINIMIZE );
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 09c800bd777..957d930d9da 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -457,6 +457,8 @@ extern BOOL is_iconic( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL is_window_drawable( HWND hwnd, BOOL icon ) DECLSPEC_HIDDEN;
extern BOOL is_window_enabled( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL is_window_unicode( HWND hwnd ) DECLSPEC_HIDDEN;
+extern BOOL is_window_visible( HWND hwnd ) DECLSPEC_HIDDEN;
+extern BOOL is_zoomed( HWND hwnd ) DECLSPEC_HIDDEN;
extern DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN;
extern BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi ) DECLSPEC_HIDDEN;
enum coords_relative;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index 08e901cc855..f98dabe27f3 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -737,7 +737,7 @@ BOOL is_child( HWND parent, HWND child )
}
/* see IsWindowVisible */
-static BOOL is_window_visible( HWND hwnd )
+BOOL is_window_visible( HWND hwnd )
{
HWND *list;
BOOL retval = TRUE;
@@ -965,7 +965,7 @@ BOOL is_iconic( HWND hwnd )
return (get_window_long( hwnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
}
-static BOOL is_zoomed( HWND hwnd )
+BOOL is_zoomed( HWND hwnd )
{
return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
}
@@ -5439,10 +5439,6 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code )
case NtUserCallHwndParam_GetClientRect:
return get_client_rect( hwnd, (RECT *)param );
- case NtUserCallHwndParam_GetMinMaxInfo:
- *(MINMAXINFO *)param = get_min_max_info( hwnd );
- return 0;
-
case NtUserCallHwndParam_GetWindowInfo:
return get_window_info( hwnd, (WINDOWINFO *)param );
diff --git a/include/ntgdi.h b/include/ntgdi.h
index 5a9d5a798fe..14b1dde45d5 100644
--- a/include/ntgdi.h
+++ b/include/ntgdi.h
@@ -109,10 +109,12 @@ enum
NtGdiSetMapMode = 8,
/* not compatible with Windows */
NtGdiSetBkColor = 100,
+ NtGdiSetBkMode,
NtGdiSetTextColor,
NtGdiSetDCBrushColor,
NtGdiSetDCPenColor,
NtGdiSetGraphicsMode,
+ NtGdiSetROP2,
};
/* NtGdiGetDCDword parameter, not compatible with Windows */
diff --git a/include/ntuser.h b/include/ntuser.h
index 9d9ac0247d1..8320a83800f 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -1018,7 +1018,6 @@ enum
NtUserCallHwndParam_GetClassLongPtrW,
NtUserCallHwndParam_GetClassWord,
NtUserCallHwndParam_GetClientRect,
- NtUserCallHwndParam_GetMinMaxInfo,
NtUserCallHwndParam_GetWindowInfo,
NtUserCallHwndParam_GetWindowLongA,
NtUserCallHwndParam_GetWindowLongW,
@@ -1085,13 +1084,6 @@ static inline BOOL NtUserGetClientRect( HWND hwnd, RECT *rect )
return NtUserCallHwndParam( hwnd, (UINT_PTR)rect, NtUserCallHwndParam_GetClientRect );
}
-static inline MINMAXINFO NtUserGetMinMaxInfo( HWND hwnd )
-{
- MINMAXINFO info;
- NtUserCallHwndParam( hwnd, (UINT_PTR)&info, NtUserCallHwndParam_GetMinMaxInfo );
- return info;
-}
-
static inline BOOL NtUserGetWindowInfo( HWND hwnd, WINDOWINFO *info )
{
return NtUserCallHwndParam( hwnd, (UINT_PTR)info, NtUserCallHwndParam_GetWindowInfo );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/211
More information about the wine-devel
mailing list