From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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 );