From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/win32u/driver.c | 4 ++-- dlls/win32u/gdiobj.c | 1 - dlls/win32u/win32u.spec | 1 - dlls/win32u/win32u_private.h | 1 - dlls/win32u/wrappers.c | 9 --------- include/wine/gdi_driver.h | 12 ++++++------ 6 files changed, 8 insertions(+), 20 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 1f538d100ed..4a853b516f4 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1223,9 +1223,9 @@ static const struct user_driver_funcs lazy_load_driver = const struct user_driver_funcs *user_driver = &lazy_load_driver;
/****************************************************************************** - * __wine_set_user_driver (win32u.@) + * __wine_set_user_driver (win32u.so) */ -void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version ) +void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version ) { struct user_driver_funcs *driver, *prev;
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index edb21456d8d..c29e7773e6c 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1249,7 +1249,6 @@ static struct unix_funcs unix_funcs = __wine_get_vulkan_driver, __wine_get_wgl_driver, __wine_send_input, - __wine_set_user_driver, };
NTSTATUS gdi_init(void) diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 17be6894508..8584fc4e5c3 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1322,7 +1322,6 @@
# Graphics drivers @ cdecl __wine_send_input(long ptr ptr) -@ cdecl __wine_set_user_driver(ptr long)
# OpenGL @ cdecl __wine_get_wgl_driver(long long) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index fd6dba82da2..c5303010ef3 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -328,7 +328,6 @@ struct unix_funcs const struct vulkan_funcs * (CDECL *get_vulkan_driver)( UINT version ); struct opengl_funcs * (CDECL *get_wgl_driver)( HDC hdc, UINT version ); BOOL (CDECL *wine_send_input)( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput ); - void (CDECL *set_user_driver)( const struct user_driver_funcs *funcs, UINT version ); };
/* clipboard.c */ diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 13b4b7164ab..b336059fe96 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1408,15 +1408,6 @@ BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *raw return unix_funcs->wine_send_input( hwnd, input, rawinput ); }
-/*********************************************************************** - * __wine_set_user_driver (win32u.@) - */ -void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version ) -{ - if (!unix_funcs) return; - return unix_funcs->set_user_driver( funcs, version ); -} - extern void wrappers_init( unixlib_handle_t handle ) { const void *args; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 52fd6fe49d3..998aa3ed3e9 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -168,7 +168,7 @@ struct gdi_dc_funcs };
/* increment this when you change the DC function table */ -#define WINE_GDI_DRIVER_VERSION 79 +#define WINE_GDI_DRIVER_VERSION 80
#define GDI_PRIORITY_NULL_DRV 0 /* null driver */ #define GDI_PRIORITY_FONT_DRV 100 /* any font driver */ @@ -196,9 +196,9 @@ static inline void push_dc_driver( PHYSDEV *dev, PHYSDEV physdev, const struct g
/* support for window surfaces */
-struct window_surface; +#ifdef WINE_UNIX_LIB
-#ifndef __WINE_USE_MSVCRT +struct window_surface;
struct window_surface_funcs { @@ -333,10 +333,10 @@ struct user_driver_funcs void (*pThreadDetach)(void); };
-#endif /* __WINE_USE_MSVCRT */ +extern void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version ); + +#endif /* WINE_UNIX_LIB */
-struct user_driver_funcs; -extern void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version ); extern struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version ); extern const struct vulkan_funcs * CDECL __wine_get_vulkan_driver( UINT version );
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/edit.c | 4 +- dlls/user32/listbox.c | 8 +- dlls/user32/mdi.c | 8 +- dlls/user32/painting.c | 240 +---------------------------------- dlls/user32/user32.spec | 2 +- dlls/win32u/dce.c | 204 +++++++++++++++++++++++++++++ dlls/win32u/gdiobj.c | 1 + dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 4 + dlls/win32u/window.c | 2 +- dlls/win32u/wrappers.c | 9 ++ include/ntuser.h | 6 + 12 files changed, 239 insertions(+), 251 deletions(-)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index b7eaf2b9ddf..70f105b9a0a 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -1708,8 +1708,8 @@ static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy)
GetClientRect(es->hwndSelf, &rc1); IntersectRect(&rc, &rc1, &es->format_rect); - ScrollWindowEx(es->hwndSelf, -dx, dy, - NULL, &rc, NULL, NULL, SW_INVALIDATE); + NtUserScrollWindowEx(es->hwndSelf, -dx, dy, + NULL, &rc, NULL, NULL, SW_INVALIDATE); /* force scroll info update */ EDIT_UpdateScrollInfo(es); } diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 0eed2fdfe65..b8f127c0963 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -439,8 +439,8 @@ static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll ) else dy = (descr->top_item - index) * descr->item_height;
- ScrollWindowEx( descr->self, dx, dy, NULL, NULL, 0, NULL, - SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); + NtUserScrollWindowEx( descr->self, dx, dy, NULL, NULL, 0, NULL, + SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); } else InvalidateRect( descr->self, NULL, TRUE ); @@ -1340,8 +1340,8 @@ static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos ) /* Invalidate the focused item so it will be repainted correctly */ if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1) InvalidateRect( descr->self, &rect, TRUE ); - ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL, - SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); + NtUserScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL, + SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); } else InvalidateRect( descr->self, NULL, TRUE ); diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c index e5a52012413..26772aed763 100644 --- a/dlls/user32/mdi.c +++ b/dlls/user32/mdi.c @@ -1822,11 +1822,11 @@ void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam, SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
if( uMsg == WM_VSCROLL ) - ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL, - SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); + NtUserScrollWindowEx( hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL, + SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); else - ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL, - SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); + NtUserScrollWindowEx( hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL, + SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); done: SetThreadDpiAwarenessContext( context ); } diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index e7be362773a..419c952d998 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -19,72 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include <assert.h> -#include <stdarg.h> -#include <string.h> - -#include "ntstatus.h" -#define WIN32_NO_STATUS #include "user_private.h" -#include "win.h" -#include "controls.h" -#include "wine/server.h" -#include "wine/list.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(win); - - -/************************************************************************* - * fix_caret - * - * Helper for ScrollWindowEx: - * If the return value is 0, no special caret handling is necessary. - * Otherwise the return value is the handle of the window that owns the - * caret. Its caret needs to be hidden during the scroll operation and - * moved to new_caret_pos if move_caret is TRUE. - */ -static HWND fix_caret(HWND hWnd, const RECT *scroll_rect, INT dx, INT dy, - UINT flags, LPBOOL move_caret, LPPOINT new_caret_pos) -{ - GUITHREADINFO info; - RECT rect, mapped_rcCaret; - - info.cbSize = sizeof(info); - if (!NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info )) return 0; - if (!info.hwndCaret) return 0; - - mapped_rcCaret = info.rcCaret; - if (info.hwndCaret == hWnd) - { - /* The caret needs to be moved along with scrolling even if it's - * outside the visible area. Otherwise, when the caret is scrolled - * out from the view, the position won't get updated anymore and - * the caret will never scroll back again. */ - *move_caret = TRUE; - new_caret_pos->x = info.rcCaret.left + dx; - new_caret_pos->y = info.rcCaret.top + dy; - } - else - { - *move_caret = FALSE; - if (!(flags & SW_SCROLLCHILDREN) || !IsChild(hWnd, info.hwndCaret)) - return 0; - MapWindowPoints(info.hwndCaret, hWnd, (LPPOINT)&mapped_rcCaret, 2); - } - - /* If the caret is not in the src/dest rects, all is fine done. */ - if (!IntersectRect(&rect, scroll_rect, &mapped_rcCaret)) - { - rect = *scroll_rect; - OffsetRect(&rect, dx, dy); - if (!IntersectRect(&rect, &rect, &mapped_rcCaret)) - return 0; - } - - /* Indicate that the caret needs to be updated during the scrolling. */ - return info.hwndCaret; -}
/*********************************************************************** @@ -197,177 +132,6 @@ BOOL WINAPI ValidateRect( HWND hwnd, const RECT *rect ) }
-static INT scroll_window( HWND hwnd, INT dx, INT dy, const RECT *rect, const RECT *clipRect, - HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags, BOOL is_ex ) -{ - INT retVal = NULLREGION; - BOOL bOwnRgn = TRUE; - BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE)); - int rdw_flags; - HRGN hrgnTemp; - HRGN hrgnWinupd = 0; - HDC hDC; - RECT rc, cliprc; - HWND hwndCaret = NULL; - BOOL moveCaret = FALSE; - POINT newCaretPos; - - TRACE( "%p, %d,%d hrgnUpdate=%p rcUpdate = %p %s %04x\n", - hwnd, dx, dy, hrgnUpdate, rcUpdate, wine_dbgstr_rect(rect), flags ); - TRACE( "clipRect = %s\n", wine_dbgstr_rect(clipRect)); - if( flags & ~( SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE)) - FIXME("some flags (%04x) are unhandled\n", flags); - - rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? - RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ; - - if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR; - hwnd = WIN_GetFullHandle( hwnd ); - - GetClientRect(hwnd, &rc); - - if (clipRect) IntersectRect(&cliprc,&rc,clipRect); - else cliprc = rc; - - if (rect) IntersectRect(&rc, &rc, rect); - - if( hrgnUpdate ) bOwnRgn = FALSE; - else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ); - - newCaretPos.x = newCaretPos.y = 0; - - if( !IsRectEmpty(&cliprc) && (dx || dy)) { - DWORD dcxflags = 0; - DWORD style = GetWindowLongW( hwnd, GWL_STYLE ); - - hwndCaret = fix_caret(hwnd, &rc, dx, dy, flags, &moveCaret, &newCaretPos); - if (hwndCaret) - NtUserHideCaret( hwndCaret ); - - if (is_ex) dcxflags |= DCX_CACHE; - if( style & WS_CLIPSIBLINGS) dcxflags |= DCX_CLIPSIBLINGS; - if( GetClassLongW( hwnd, GCL_STYLE ) & CS_PARENTDC) - dcxflags |= DCX_PARENTCLIP; - if( !(flags & SW_SCROLLCHILDREN) && (style & WS_CLIPCHILDREN)) - dcxflags |= DCX_CLIPCHILDREN; - hDC = NtUserGetDCEx( hwnd, 0, dcxflags); - if (hDC) - { - NtUserScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate ); - - NtUserReleaseDC( hwnd, hDC ); - - if (!bUpdate) - NtUserRedrawWindow( hwnd, NULL, hrgnUpdate, rdw_flags); - } - - /* If the windows has an update region, this must be - * scrolled as well. Keep a copy in hrgnWinupd - * to be added to hrngUpdate at the end. */ - hrgnTemp = CreateRectRgn( 0, 0, 0, 0 ); - retVal = NtUserGetUpdateRgn( hwnd, hrgnTemp, FALSE ); - if (retVal != NULLREGION) - { - HRGN hrgnClip = CreateRectRgnIndirect(&cliprc); - if( !bOwnRgn) { - hrgnWinupd = CreateRectRgn( 0, 0, 0, 0); - CombineRgn( hrgnWinupd, hrgnTemp, 0, RGN_COPY); - } - OffsetRgn( hrgnTemp, dx, dy ); - CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND ); - if( !bOwnRgn) - CombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR ); - NtUserRedrawWindow( hwnd, NULL, hrgnTemp, rdw_flags); - - /* Catch the case where the scrolling amount exceeds the size of the - * original window. This generated a second update area that is the - * location where the original scrolled content would end up. - * This second region is not returned by the ScrollDC and sets - * ScrollWindowEx apart from just a ScrollDC. - * - * This has been verified with testing on windows. - */ - if (abs(dx) > abs(rc.right - rc.left) || - abs(dy) > abs(rc.bottom - rc.top)) - { - SetRectRgn( hrgnTemp, rc.left + dx, rc.top + dy, rc.right+dx, rc.bottom + dy); - CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND ); - CombineRgn( hrgnUpdate, hrgnUpdate, hrgnTemp, RGN_OR ); - - if (rcUpdate) - { - RECT rcTemp; - GetRgnBox( hrgnTemp, &rcTemp ); - UnionRect( rcUpdate, rcUpdate, &rcTemp ); - } - - if( !bOwnRgn) - CombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR ); - } - DeleteObject( hrgnClip ); - } - DeleteObject( hrgnTemp ); - } else { - /* nothing was scrolled */ - if( !bOwnRgn) - SetRectRgn( hrgnUpdate, 0, 0, 0, 0 ); - SetRectEmpty( rcUpdate); - } - - if( flags & SW_SCROLLCHILDREN ) - { - HWND *list = WIN_ListChildren( hwnd ); - if (list) - { - int i; - RECT r, dummy; - for (i = 0; list[i]; i++) - { - WIN_GetRectangles( list[i], COORDS_PARENT, &r, NULL ); - if (!rect || IntersectRect(&dummy, &r, rect)) - NtUserSetWindowPos( list[i], 0, r.left + dx, r.top + dy, 0, 0, - SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | - SWP_NOREDRAW | SWP_DEFERERASE ); - } - HeapFree( GetProcessHeap(), 0, list ); - } - } - - if( flags & (SW_INVALIDATE | SW_ERASE) ) - NtUserRedrawWindow( hwnd, NULL, hrgnUpdate, rdw_flags | - ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) ); - - if( hrgnWinupd) { - CombineRgn( hrgnUpdate, hrgnUpdate, hrgnWinupd, RGN_OR); - DeleteObject( hrgnWinupd); - } - - if( moveCaret ) - SetCaretPos( newCaretPos.x, newCaretPos.y ); - if( hwndCaret ) - NtUserShowCaret( hwndCaret ); - - if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate ); - - return retVal; -} - - -/************************************************************************* - * ScrollWindowEx (USER32.@) - * - * Note: contrary to what the doc says, pixels that are scrolled from the - * outside of clipRect to the inside are NOT painted. - * - */ -INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy, - const RECT *rect, const RECT *clipRect, - HRGN hrgnUpdate, LPRECT rcUpdate, - UINT flags ) -{ - return scroll_window( hwnd, dx, dy, rect, clipRect, hrgnUpdate, rcUpdate, flags, TRUE ); -} - /************************************************************************* * ScrollWindow (USER32.@) * @@ -375,8 +139,8 @@ INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy, BOOL WINAPI ScrollWindow( HWND hwnd, INT dx, INT dy, const RECT *rect, const RECT *clipRect ) { - return scroll_window( hwnd, dx, dy, rect, clipRect, 0, NULL, - SW_INVALIDATE | SW_ERASE | (rect ? 0 : SW_SCROLLCHILDREN), FALSE ) != ERROR; + UINT flags = SW_INVALIDATE | SW_ERASE | (rect ? 0 : SW_SCROLLCHILDREN) | SW_NODCCACHE; + return NtUserScrollWindowEx( hwnd, dx, dy, rect, clipRect, 0, NULL, flags ); }
/************************************************************************ diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index ee533305a6e..8a7387040dc 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -630,7 +630,7 @@ @ stdcall ScrollChildren(long long long long) @ stdcall ScrollDC(long long long ptr ptr long ptr) NtUserScrollDC @ stdcall ScrollWindow(long long long ptr ptr) -@ stdcall ScrollWindowEx(long long long ptr ptr long ptr long) +@ stdcall ScrollWindowEx(long long long ptr ptr long ptr long) NtUserScrollWindowEx @ stdcall SendDlgItemMessageA(long long long long long) @ stdcall SendDlgItemMessageW(long long long long long) @ stdcall SendIMEMessageExA(long long) diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index acbb213d7b7..872112e4a24 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -1591,3 +1591,207 @@ BOOL WINAPI NtUserLockWindowUpdate( HWND hwnd ) } return !InterlockedCompareExchangePointer( (void **)&locked_hwnd, hwnd, 0 ); } + +/************************************************************************* + * fix_caret + * + * Helper for NtUserScrollWindowEx: + * If the return value is 0, no special caret handling is necessary. + * Otherwise the return value is the handle of the window that owns the + * caret. Its caret needs to be hidden during the scroll operation and + * moved to new_caret_pos if move_caret is TRUE. + */ +static HWND fix_caret( HWND hwnd, const RECT *scroll_rect, INT dx, INT dy, + UINT flags, BOOL *move_caret, POINT *new_caret_pos ) +{ + RECT rect, mapped_caret; + GUITHREADINFO info; + + info.cbSize = sizeof(info); + if (!NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info )) return 0; + if (!info.hwndCaret) return 0; + + mapped_caret = info.rcCaret; + if (info.hwndCaret == hwnd) + { + /* The caret needs to be moved along with scrolling even if it's + * outside the visible area. Otherwise, when the caret is scrolled + * out from the view, the position won't get updated anymore and + * the caret will never scroll back again. */ + *move_caret = TRUE; + new_caret_pos->x = info.rcCaret.left + dx; + new_caret_pos->y = info.rcCaret.top + dy; + } + else + { + *move_caret = FALSE; + if (!(flags & SW_SCROLLCHILDREN) || !is_child( hwnd, info.hwndCaret )) + return 0; + map_window_points( info.hwndCaret, hwnd, (POINT *)&mapped_caret, 2, get_thread_dpi() ); + } + + /* If the caret is not in the src/dest rects, all is fine done. */ + if (!intersect_rect( &rect, scroll_rect, &mapped_caret )) + { + rect = *scroll_rect; + OffsetRect( &rect, dx, dy ); + if (!intersect_rect( &rect, &rect, &mapped_caret )) + return 0; + } + + /* Indicate that the caret needs to be updated during the scrolling. */ + return info.hwndCaret; +} + +/************************************************************************* + * NtUserScrollWindowEx (win32u.@) + * + * Note: contrary to what the doc says, pixels that are scrolled from the + * outside of clipRect to the inside are NOT painted. + */ +INT WINAPI NtUserScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect, + const RECT *clip_rect, HRGN update_rgn, + RECT *update_rect, UINT flags ) +{ + BOOL update = update_rect || update_rgn || flags & (SW_INVALIDATE | SW_ERASE); + BOOL own_rgn = TRUE, move_caret = FALSE; + HRGN temp_rgn, winupd_rgn = 0; + INT retval = NULLREGION; + HWND caret_hwnd = NULL; + POINT new_caret_pos; + RECT rc, cliprc; + int rdw_flags; + HDC hdc; + + TRACE( "%p, %d,%d update_rgn=%p update_rect = %p %s %04x\n", + hwnd, dx, dy, update_rgn, update_rect, wine_dbgstr_rect(rect), flags ); + TRACE( "clip_rect = %s\n", wine_dbgstr_rect(clip_rect) ); + if (flags & ~(SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE)) + FIXME( "some flags (%04x) are unhandled\n", flags ); + + rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? + RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE; + + if (!is_window_drawable( hwnd, TRUE )) return ERROR; + hwnd = get_full_window_handle( hwnd ); + + get_client_rect( hwnd, &rc ); + if (clip_rect) intersect_rect( &cliprc, &rc, clip_rect ); + else cliprc = rc; + + if (rect) intersect_rect( &rc, &rc, rect ); + if (update_rgn) own_rgn = FALSE; + else if (update) update_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + + new_caret_pos.x = new_caret_pos.y = 0; + + if (!IsRectEmpty( &cliprc ) && (dx || dy)) + { + DWORD style = get_window_long( hwnd, GWL_STYLE ); + DWORD dcxflags = 0; + + caret_hwnd = fix_caret( hwnd, &rc, dx, dy, flags, &move_caret, &new_caret_pos ); + if (caret_hwnd) NtUserHideCaret( caret_hwnd ); + + if (!(flags & SW_NODCCACHE)) dcxflags |= DCX_CACHE; + if (style & WS_CLIPSIBLINGS) dcxflags |= DCX_CLIPSIBLINGS; + if (get_class_long( hwnd, GCL_STYLE, FALSE ) & CS_PARENTDC) dcxflags |= DCX_PARENTCLIP; + if (!(flags & SW_SCROLLCHILDREN) && (style & WS_CLIPCHILDREN)) + dcxflags |= DCX_CLIPCHILDREN; + hdc = NtUserGetDCEx( hwnd, 0, dcxflags); + if (hdc) + { + NtUserScrollDC( hdc, dx, dy, &rc, &cliprc, update_rgn, update_rect ); + NtUserReleaseDC( hwnd, hdc ); + if (!update) NtUserRedrawWindow( hwnd, NULL, update_rgn, rdw_flags ); + } + + /* If the windows has an update region, this must be scrolled as well. + * Keep a copy in winupd_rgn to be added to hrngUpdate at the end. */ + temp_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + retval = NtUserGetUpdateRgn( hwnd, temp_rgn, FALSE ); + if (retval != NULLREGION) + { + HRGN clip_rgn = NtGdiCreateRectRgn( cliprc.left, cliprc.top, + cliprc.right, cliprc.bottom ); + if (!own_rgn) + { + winupd_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0); + NtGdiCombineRgn( winupd_rgn, temp_rgn, 0, RGN_COPY); + } + NtGdiOffsetRgn( temp_rgn, dx, dy ); + NtGdiCombineRgn( temp_rgn, temp_rgn, clip_rgn, RGN_AND ); + if (!own_rgn) NtGdiCombineRgn( winupd_rgn, winupd_rgn, temp_rgn, RGN_OR ); + NtUserRedrawWindow( hwnd, NULL, temp_rgn, rdw_flags ); + + /* + * Catch the case where the scrolling amount exceeds the size of the + * original window. This generated a second update area that is the + * location where the original scrolled content would end up. + * This second region is not returned by the ScrollDC and sets + * ScrollWindowEx apart from just a ScrollDC. + * + * This has been verified with testing on windows. + */ + if (abs( dx ) > abs( rc.right - rc.left ) || abs( dy ) > abs( rc.bottom - rc.top )) + { + NtGdiSetRectRgn( temp_rgn, rc.left + dx, rc.top + dy, rc.right+dx, rc.bottom + dy ); + NtGdiCombineRgn( temp_rgn, temp_rgn, clip_rgn, RGN_AND ); + NtGdiCombineRgn( update_rgn, update_rgn, temp_rgn, RGN_OR ); + + if (update_rect) + { + RECT temp_rect; + NtGdiGetRgnBox( temp_rgn, &temp_rect ); + union_rect( update_rect, update_rect, &temp_rect ); + } + + if (!own_rgn) NtGdiCombineRgn( winupd_rgn, winupd_rgn, temp_rgn, RGN_OR ); + } + NtGdiDeleteObjectApp( clip_rgn ); + } + NtGdiDeleteObjectApp( temp_rgn ); + } + else + { + /* nothing was scrolled */ + if (!own_rgn) NtGdiSetRectRgn( update_rgn, 0, 0, 0, 0 ); + SetRectEmpty( update_rect ); + } + + if (flags & SW_SCROLLCHILDREN) + { + HWND *list = list_window_children( 0, hwnd, NULL, 0 ); + if (list) + { + RECT r, dummy; + int i; + + for (i = 0; list[i]; i++) + { + get_window_rects( list[i], COORDS_PARENT, &r, NULL, get_thread_dpi() ); + if (!rect || intersect_rect( &dummy, &r, rect )) + NtUserSetWindowPos( list[i], 0, r.left + dx, r.top + dy, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | + SWP_NOREDRAW | SWP_DEFERERASE ); + } + free( list ); + } + } + + if (flags & (SW_INVALIDATE | SW_ERASE)) + NtUserRedrawWindow( hwnd, NULL, update_rgn, rdw_flags | + ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) ); + + if (winupd_rgn) + { + NtGdiCombineRgn( update_rgn, update_rgn, winupd_rgn, RGN_OR ); + NtGdiDeleteObjectApp( winupd_rgn ); + } + + if (move_caret) set_caret_pos( new_caret_pos.x, new_caret_pos.y ); + if (caret_hwnd) NtUserShowCaret( caret_hwnd ); + if (own_rgn && update_rgn) NtGdiDeleteObjectApp( update_rgn ); + + return retval; +} diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index c29e7773e6c..222b74b45d6 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1200,6 +1200,7 @@ static struct unix_funcs unix_funcs = NtUserRegisterHotKey, NtUserReleaseDC, NtUserScrollDC, + NtUserScrollWindowEx, NtUserSelectPalette, NtUserSendInput, NtUserSetActiveWindow, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 8584fc4e5c3..86d359b8386 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1156,7 +1156,7 @@ @ stub NtUserRestoreWindowDpiChanges @ stub NtUserSBGetParms @ stdcall NtUserScrollDC(long long long ptr ptr long ptr) -@ stub NtUserScrollWindowEx +@ stdcall NtUserScrollWindowEx(long long long ptr ptr long ptr long) @ stdcall NtUserSelectPalette(long long long) @ stub NtUserSendEventMessage @ stdcall NtUserSendInput(long ptr long) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index c5303010ef3..2394a8850a5 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -268,6 +268,9 @@ struct unix_funcs INT (WINAPI *pNtUserReleaseDC)( HWND hwnd, HDC hdc ); BOOL (WINAPI *pNtUserScrollDC)( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip, HRGN ret_update_rgn, RECT *update_rect ); + INT (WINAPI *pNtUserScrollWindowEx)( HWND hwnd, INT dx, INT dy, const RECT *rect, + const RECT *clip_rect, HRGN update_rgn, + RECT *update_rect, UINT flags ); HPALETTE (WINAPI *pNtUserSelectPalette)( HDC hdc, HPALETTE hpal, WORD bkg ); UINT (WINAPI *pNtUserSendInput)( UINT count, INPUT *inputs, int size ); HWND (WINAPI *pNtUserSetActiveWindow)( HWND hwnd ); @@ -449,6 +452,7 @@ extern HWND is_current_process_window( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND is_current_thread_window( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN; 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 DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 319f47712e6..34bf87bc9ba 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -762,7 +762,7 @@ static BOOL is_window_visible( HWND hwnd ) * minimized, and it is itself not minimized unless we are * trying to draw its default class icon. */ -static BOOL is_window_drawable( HWND hwnd, BOOL icon ) +BOOL is_window_drawable( HWND hwnd, BOOL icon ) { HWND *list; BOOL retval = TRUE; diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index b336059fe96..679cce95b9a 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1112,6 +1112,15 @@ BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const R return unix_funcs->pNtUserScrollDC( hdc, dx, dy, scroll, clip, ret_update_rgn, update_rect ); }
+INT WINAPI NtUserScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect, + const RECT *clip_rect, HRGN update_rgn, + RECT *update_rect, UINT flags ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserScrollWindowEx( hwnd, dx, dy, rect, clip_rect, + update_rgn, update_rect, flags ); +} + HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE hpal, WORD bkg ) { if (!unix_funcs) return 0; diff --git a/include/ntuser.h b/include/ntuser.h index e0c65a9f532..b6b69879dd7 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -227,6 +227,9 @@ struct send_message_callback_params #define NTUSER_OBJ_ACCEL 0x08 #define NTUSER_OBJ_HOOK 0x0f
+/* NtUserScrollWindowEx flag */ +#define SW_NODCCACHE 0x8000 + /* NtUserInitializeClientPfnArrays parameter, not compatible with Windows */ struct user_client_procs { @@ -615,6 +618,9 @@ BOOL WINAPI NtUserRemoveMenu( HMENU menu, UINT id, UINT flags ); HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str ); BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip, HRGN ret_update_rgn, RECT *update_rect ); +INT WINAPI NtUserScrollWindowEx( HWND hwnd, INT dx, INT dy, const RECT *rect, + const RECT *clip_rect, HRGN update_rgn, + RECT *update_rect, UINT flags ) DECLSPEC_HIDDEN; HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE palette, WORD force_background ); UINT WINAPI NtUserSendInput( UINT count, INPUT *inputs, int size ); HWND WINAPI NtUserSetActiveWindow( HWND hwnd );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116511
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
user32: menu.c:2324: Test failed: test 25
=== debian11 (64 bit WoW report) ===
user32: msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x030f instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0086 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0006
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/win.c | 11 +---------- dlls/win32u/window.c | 18 ++++++++++++++++++ include/ntuser.h | 6 ++++++ 3 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c index bac75063f7d..4adffc37d6b 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1475,16 +1475,7 @@ DWORD WINAPI GetWindowContextHelpId( HWND hwnd ) */ BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id ) { - WND *wnd = WIN_GetPtr( hwnd ); - if (!wnd || wnd == WND_DESKTOP) return FALSE; - if (wnd == WND_OTHER_PROCESS) - { - if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd ); - return FALSE; - } - wnd->helpContext = id; - WIN_ReleasePtr( wnd ); - return TRUE; + return NtUserSetWindowContextHelpId( hwnd, id ); }
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 34bf87bc9ba..d09a719185a 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -4539,6 +4539,21 @@ static DWORD get_window_context_help_id( HWND hwnd ) return retval; }
+/* see SetWindowContextHelpId */ +static BOOL set_window_context_help_id( HWND hwnd, DWORD id ) +{ + WND *win = get_win_ptr( hwnd ); + if (!win || win == WND_DESKTOP) return FALSE; + if (win == WND_OTHER_PROCESS) + { + if (is_window( hwnd )) FIXME( "not supported on other process window %p\n", hwnd ); + return FALSE; + } + win->helpContext = id; + release_win_ptr( win ); + return TRUE; +} + /*********************************************************************** * send_destroy_message */ @@ -5432,6 +5447,9 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_SetForegroundWindow: return set_foreground_window( hwnd, param );
+ case NtUserCallHwndParam_SetWindowContextHelpId: + return set_window_context_help_id( hwnd, param ); + case NtUserCallHwndParam_SetWindowPixelFormat: return set_window_pixel_format( hwnd, param );
diff --git a/include/ntuser.h b/include/ntuser.h index b6b69879dd7..482bdbcbddd 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1021,6 +1021,7 @@ enum NtUserCallHwndParam_MonitorFromWindow, NtUserCallHwndParam_ScreenToClient, NtUserCallHwndParam_SetForegroundWindow, + NtUserCallHwndParam_SetWindowContextHelpId, NtUserCallHwndParam_SetWindowPixelFormat, NtUserCallHwndParam_ShowOwnedPopups, /* temporary exports */ @@ -1171,6 +1172,11 @@ static inline BOOL NtUserSetForegroundWindow( HWND hwnd, BOOL mouse ) return NtUserCallHwndParam( hwnd, mouse, NtUserCallHwndParam_SetForegroundWindow ); }
+static inline BOOL NtUserSetWindowContextHelpId( HWND hwnd, DWORD id ) +{ + return NtUserCallHwndParam( hwnd, id, NtUserCallHwndParam_SetWindowContextHelpId ); +} + static inline BOOL NtUserSetWindowPixelFormat( HWND hwnd, int format ) { return NtUserCallHwndParam( hwnd, format, NtUserCallHwndParam_SetWindowPixelFormat );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116512
Your paranoid android.
=== debian11 (64 bit WoW report) ===
user32: msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x030f instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0086 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0006
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/win.c | 42 ++------------------------------- dlls/win32u/gdiobj.c | 1 + dlls/win32u/input.c | 45 ++++++++++++++++++++++++++++++++++++ dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 1 + dlls/win32u/wrappers.c | 6 +++++ include/ntuser.h | 1 + 7 files changed, 57 insertions(+), 41 deletions(-)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 4adffc37d6b..7b0fc884402 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1482,47 +1482,9 @@ BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id ) /******************************************************************* * DragDetect (USER32.@) */ -BOOL WINAPI DragDetect( HWND hWnd, POINT pt ) +BOOL WINAPI DragDetect( HWND hwnd, POINT pt ) { - MSG msg; - RECT rect; - WORD wDragWidth, wDragHeight; - - TRACE( "%p,%s\n", hWnd, wine_dbgstr_point( &pt ) ); - - if (!(NtUserGetKeyState( VK_LBUTTON ) & 0x8000)) - return FALSE; - - wDragWidth = GetSystemMetrics(SM_CXDRAG); - wDragHeight= GetSystemMetrics(SM_CYDRAG); - SetRect(&rect, pt.x - wDragWidth, pt.y - wDragHeight, pt.x + wDragWidth, pt.y + wDragHeight); - - NtUserSetCapture( hWnd ); - - while(1) - { - while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE )) - { - if( msg.message == WM_LBUTTONUP ) - { - ReleaseCapture(); - return FALSE; - } - if( msg.message == WM_MOUSEMOVE ) - { - POINT tmp; - tmp.x = (short)LOWORD(msg.lParam); - tmp.y = (short)HIWORD(msg.lParam); - if( !PtInRect( &rect, tmp )) - { - ReleaseCapture(); - return TRUE; - } - } - } - WaitMessage(); - } - return FALSE; + return NtUserDragDetect( hwnd, pt.x, pt.y ); }
/****************************************************************************** diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 222b74b45d6..7d9adcdec6a 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1158,6 +1158,7 @@ static struct unix_funcs unix_funcs = NtUserDestroyMenu, NtUserDestroyWindow, NtUserDispatchMessage, + NtUserDragDetect, NtUserDrawIconEx, NtUserEmptyClipboard, NtUserEnableMenuItem, diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 2b196fb5b1d..6f0e4f45501 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1394,6 +1394,51 @@ BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info ) return TRUE; }
+/******************************************************************* + * NtUserDragDetect (win32u.@) + */ +BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y ) +{ + WORD width, height; + RECT rect; + MSG msg; + + TRACE( "%p (%d,%d)\n", hwnd, x, y ); + + if (!(NtUserGetKeyState( VK_LBUTTON ) & 0x8000)) return FALSE; + + width = get_system_metrics( SM_CXDRAG ); + height = get_system_metrics( SM_CYDRAG ); + SetRect( &rect, x - width, y - height, x + width, y + height ); + + NtUserSetCapture( hwnd ); + + for (;;) + { + while (NtUserPeekMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE )) + { + if (msg.message == WM_LBUTTONUP) + { + release_capture(); + return FALSE; + } + if (msg.message == WM_MOUSEMOVE) + { + POINT tmp; + tmp.x = (short)LOWORD( msg.lParam ); + tmp.y = (short)HIWORD( msg.lParam ); + if (!PtInRect( &rect, tmp )) + { + release_capture(); + return TRUE; + } + } + } + NtUserMsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, 0 ); + } + return FALSE; +} + /********************************************************************** * set_capture_window */ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 86d359b8386..28c839f5901 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -845,7 +845,7 @@ @ stub NtUserDoSoundConnect @ stub NtUserDoSoundDisconnect @ stub NtUserDownlevelTouchpad -@ stub NtUserDragDetect +@ stdcall NtUserDragDetect(long long long) @ stub NtUserDragObject @ stub NtUserDrawAnimatedRects @ stub NtUserDrawCaption diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 2394a8850a5..e72ab8ff1d7 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -214,6 +214,7 @@ struct unix_funcs BOOL (WINAPI *pNtUserDestroyMenu)( HMENU handle ); BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd ); LRESULT (WINAPI *pNtUserDispatchMessage)( const MSG *msg ); + BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y ); BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width, INT height, UINT istep, HBRUSH hbr, UINT flags ); BOOL (WINAPI *pNtUserEmptyClipboard)(void); diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 679cce95b9a..e4219ed5648 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -855,6 +855,12 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ) return unix_funcs->pNtUserDispatchMessage( msg ); }
+BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserDragDetect( hwnd, x, y ); +} + BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, INT height, UINT istep, HBRUSH hbr, UINT flags ) { diff --git a/include/ntuser.h b/include/ntuser.h index 482bdbcbddd..7451d649702 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -513,6 +513,7 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg ); BOOL WINAPI NtUserDestroyMenu( HMENU menu ); BOOL WINAPI NtUserDestroyWindow( HWND hwnd ); LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ); +BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y ); BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, INT height, UINT istep, HBRUSH hbr, UINT flags ); BOOL WINAPI NtUserEmptyClipboard(void);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116513
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32: menu.c:2324: Test failed: test 25
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/user32.spec | 2 +- dlls/user32/user_main.c | 8 ++++++ dlls/user32/win.c | 47 ----------------------------------- dlls/win32u/cursoricon.c | 21 ++++++++++++++++ dlls/win32u/gdiobj.c | 1 + dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 1 + dlls/win32u/window.c | 48 ++++++++++++++++++++++++++++++++++++ dlls/win32u/wrappers.c | 7 ++++++ include/ntuser.h | 15 ++++++++++- 10 files changed, 102 insertions(+), 50 deletions(-)
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 8a7387040dc..b41d661ee2a 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -445,7 +445,7 @@ @ stdcall InsertMenuItemA(long long long ptr) @ stdcall InsertMenuItemW(long long long ptr) @ stdcall InsertMenuW(long long long long ptr) -@ stdcall InternalGetWindowIcon(ptr long) +@ stdcall InternalGetWindowIcon(ptr long) NtUserInternalGetWindowIcon @ stdcall InternalGetWindowText(long ptr long) NtUserInternalGetWindowText @ stdcall IntersectRect(ptr ptr ptr) @ stdcall InvalidateRect(long ptr long) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index d0c1cc616a7..755fc3d578e 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -164,6 +164,13 @@ static NTSTATUS WINAPI User32CopyImage( const struct copy_image_params *params, return HandleToUlong( ret ); }
+static NTSTATUS WINAPI User32LoadImage( const struct load_image_params *params, ULONG size ) +{ + HANDLE ret = LoadImageW( params->hinst, params->name, params->type, + params->dx, params->dy, params->flags ); + return HandleToUlong( ret ); +} + static NTSTATUS WINAPI User32FreeCachedClipboardData( const struct free_cached_data_params *params, ULONG size ) { @@ -193,6 +200,7 @@ static const void *kernel_callback_table[NtUserCallCount] = User32CopyImage, User32FreeCachedClipboardData, User32LoadDriver, + User32LoadImage, User32RegisterBuiltinClasses, User32RenderSsynthesizedFormat, }; diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 7b0fc884402..99753791f09 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1794,50 +1794,3 @@ BOOL WINAPI SetWindowCompositionAttribute(HWND hwnd, void *data) SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } - -/*********************************************************************** - * InternalGetWindowIcon (USER32.@) - */ -HICON WINAPI InternalGetWindowIcon( HWND hwnd, UINT type ) -{ - WND *win = WIN_GetPtr( hwnd ); - HICON ret; - - TRACE( "hwnd %p, type %#x\n", hwnd, type ); - - if (!win) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return 0; - } - if (win == WND_OTHER_PROCESS || win == WND_DESKTOP) - { - if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd ); - return 0; - } - - switch (type) - { - case ICON_BIG: - ret = win->hIcon; - if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICON ); - break; - - case ICON_SMALL: - case ICON_SMALL2: - ret = win->hIconSmall ? win->hIconSmall : win->hIconSmall2; - if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICONSM ); - if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICON ); - break; - - default: - SetLastError( ERROR_INVALID_PARAMETER ); - WIN_ReleasePtr( win ); - return 0; - } - - if (!ret) ret = LoadIconW( 0, (const WCHAR *)IDI_APPLICATION ); - - WIN_ReleasePtr( win ); - return CopyIcon( ret ); -} diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c index e51feb87115..eaafd07e190 100644 --- a/dlls/win32u/cursoricon.c +++ b/dlls/win32u/cursoricon.c @@ -801,3 +801,24 @@ HANDLE WINAPI CopyImage( HANDLE hwnd, UINT type, INT dx, INT dy, UINT flags ) ret = KeUserModeCallback( NtUserCopyImage, ¶ms, sizeof(params), &ret_ptr, &ret_len ); return UlongToHandle( ret ); } + +/****************************************************************************** + * LoadImage (win32u.so) + */ +HANDLE WINAPI LoadImageW( HINSTANCE hinst, const WCHAR *name, UINT type, + INT dx, INT dy, UINT flags ) +{ + void *ret_ptr; + ULONG ret_len; + NTSTATUS ret; + struct load_image_params params = + { .hinst = hinst, .name = name, .type = type, .dx = dx, .dy = dy, .flags = flags }; + + if (HIWORD(name)) + { + ERR( "name %s not supported in Unix modules\n", debugstr_w( name )); + return 0; + } + ret = KeUserModeCallback( NtUserLoadImage, ¶ms, sizeof(params), &ret_ptr, &ret_len ); + return UlongToHandle( ret ); +} diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 7d9adcdec6a..72924bb658a 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1187,6 +1187,7 @@ static struct unix_funcs unix_funcs = NtUserGetUpdatedClipboardFormats, NtUserGetWindowPlacement, NtUserHideCaret, + NtUserInternalGetWindowIcon, NtUserIsClipboardFormatAvailable, NtUserMapVirtualKeyEx, NtUserMessageCall, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 28c839f5901..de500da143b 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1044,7 +1044,7 @@ @ stub NtUserInjectPointerInput @ stub NtUserInjectTouchInput @ stub NtUserInteractiveControlQueryUsage -@ stub NtUserInternalGetWindowIcon +@ stdcall NtUserInternalGetWindowIcon(ptr long) @ stdcall -syscall NtUserInternalGetWindowText(long ptr long) @ stub NtUserInternalToUnicode @ stub NtUserInvalidateRect diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index e72ab8ff1d7..09c800bd777 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -249,6 +249,7 @@ struct unix_funcs BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size ); BOOL (WINAPI *pNtUserGetWindowPlacement)( HWND hwnd, WINDOWPLACEMENT *placement ); BOOL (WINAPI *pNtUserHideCaret)( HWND hwnd ); + HICON (WINAPI *pNtUserInternalGetWindowIcon)( HWND hwnd, UINT type ); BOOL (WINAPI *pNtUserIsClipboardFormatAvailable)( UINT format ); UINT (WINAPI *pNtUserMapVirtualKeyEx)( UINT code, UINT type, HKL layout ); LRESULT (WINAPI *pNtUserMessageCall)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index d09a719185a..08e901cc855 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -4554,6 +4554,54 @@ static BOOL set_window_context_help_id( HWND hwnd, DWORD id ) return TRUE; }
+/*********************************************************************** + * NtUserInternalGetWindowIcon (win32u.@) + */ +HICON WINAPI NtUserInternalGetWindowIcon( HWND hwnd, UINT type ) +{ + WND *win = get_win_ptr( hwnd ); + HICON ret; + + TRACE( "hwnd %p, type %#x\n", hwnd, type ); + + if (!win) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (win == WND_OTHER_PROCESS || win == WND_DESKTOP) + { + if (is_window( hwnd )) FIXME( "not supported on other process window %p\n", hwnd ); + return 0; + } + + switch (type) + { + case ICON_BIG: + ret = win->hIcon; + if (!ret) ret = (HICON)get_class_long_ptr( hwnd, GCLP_HICON, FALSE ); + break; + + case ICON_SMALL: + case ICON_SMALL2: + ret = win->hIconSmall ? win->hIconSmall : win->hIconSmall2; + if (!ret) ret = (HICON)get_class_long_ptr( hwnd, GCLP_HICONSM, FALSE ); + if (!ret) ret = (HICON)get_class_long_ptr( hwnd, GCLP_HICON, FALSE ); + break; + + default: + SetLastError( ERROR_INVALID_PARAMETER ); + release_win_ptr( win ); + return 0; + } + release_win_ptr( win ); + + if (!ret) ret = LoadImageW( 0, (const WCHAR *)IDI_APPLICATION, IMAGE_ICON, + 0, 0, LR_SHARED | LR_DEFAULTSIZE ); + + return CopyImage( ret, IMAGE_ICON, 0, 0, 0 ); +} + /*********************************************************************** * send_destroy_message */ diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index e4219ed5648..99e0b9f3d88 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1029,12 +1029,19 @@ BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *ou return unix_funcs->pNtUserGetUpdatedClipboardFormats( formats, size, out_size ); }
+ BOOL WINAPI NtUserGetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *placement ) { if (!unix_funcs) return FALSE; return unix_funcs->pNtUserGetWindowPlacement( hwnd, placement ); }
+HICON WINAPI NtUserInternalGetWindowIcon( HWND hwnd, UINT type ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserInternalGetWindowIcon( hwnd, type ); +} + BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format ) { if (!unix_funcs) return FALSE; diff --git a/include/ntuser.h b/include/ntuser.h index 7451d649702..9d9ac0247d1 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -35,6 +35,7 @@ enum NtUserCopyImage, NtUserFreeCachedClipboardData, NtUserLoadDriver, + NtUserLoadImage, NtUserRegisterBuiltinClasses, NtUserRenderSynthesizedFormat, /* win16 hooks */ @@ -147,7 +148,7 @@ struct win_hook_params WCHAR module[MAX_PATH]; };
-/* NtUserCopyMessage params */ +/* NtUserCopyImage params */ struct copy_image_params { HANDLE hwnd; @@ -164,6 +165,17 @@ struct free_cached_data_params HANDLE handle; };
+/* NtUserLoadImage params */ +struct load_image_params +{ + HINSTANCE hinst; + const WCHAR *name; + UINT type; + INT dx; + INT dy; + UINT flags; +}; + /* NtUserRenderSynthesizedFormat params */ struct render_synthesized_format_params { @@ -589,6 +601,7 @@ BOOL WINAPI NtUserHideCaret( HWND hwnd ); NTSTATUS WINAPI NtUserInitializeClientPfnArrays( const struct user_client_procs *client_procsA, const struct user_client_procs *client_procsW, const void *client_workers, HINSTANCE user_module ); +HICON WINAPI NtUserInternalGetWindowIcon( HWND hwnd, UINT type ); INT WINAPI NtUserInternalGetWindowText( HWND hwnd, WCHAR *text, INT count ); BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format ); BOOL WINAPI NtUserKillTimer( HWND hwnd, UINT_PTR id );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116514
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
user32: msg.c:6881: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got msg 0x0005 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x030f instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 6: the msg 0x0111 was expected, but got msg 0x001c instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0086 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0006
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winex11.drv/dllmain.c | 7 ------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/window.c | 5 +++-- 3 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index e2cbd51351d..b7c5692b32d 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -27,12 +27,6 @@ static unixlib_handle_t x11drv_handle; NTSTATUS (CDECL *x11drv_unix_call)( enum x11drv_funcs code, void *params );
-static NTSTATUS x11drv_load_icon( UINT id ) -{ - return HandleToUlong( LoadIconW( NULL, UlongToPtr( id ))); -} - - typedef NTSTATUS (*callback_func)( UINT arg ); static const callback_func callback_funcs[] = { @@ -43,7 +37,6 @@ static const callback_func callback_funcs[] = x11drv_ime_set_cursor_pos, x11drv_ime_set_open_status, x11drv_ime_update_association, - x11drv_load_icon, };
C_ASSERT( ARRAYSIZE(callback_funcs) == client_funcs_count ); diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 451c308f0cd..d490600226f 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -105,7 +105,6 @@ enum client_callback client_ime_set_cursor_pos, client_ime_set_open_status, client_ime_update_association, - client_load_icon, client_funcs_count };
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 5d9a93688c3..3ebbee0856e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -631,8 +631,9 @@ static void fetch_icon_data( HWND hwnd, HICON icon_big, HICON icon_small ) icon_big = get_icon_info( (HICON)NtUserGetClassLongPtrW( hwnd, GCLP_HICON ), &ii ); if (!icon_big) { - UINT winlogo = x11drv_client_call( client_load_icon, IDI_WINLOGO ); - icon_big = get_icon_info( UlongToHandle( winlogo ), &ii ); + icon_big = LoadImageW( 0, (const WCHAR *)IDI_WINLOGO, IMAGE_ICON, 0, 0, + LR_SHARED | LR_DEFAULTSIZE ); + icon_big = get_icon_info( icon_big, &ii ); } } if (!icon_small)
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 );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116516
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
user32: msg.c:6881: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got msg 0x0005 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x030f instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 6: the msg 0x0111 was expected, but got msg 0x001c instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0086 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0006
=== debian11 (32 bit WoW report) ===
user32: menu.c:2324: Test failed: test 25
This merge request was approved by Huw Davies.