From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/menu.c | 14 +----- dlls/win32u/menu.c | 101 +++++++++++++++++++++++++++++++++++++--- dlls/win32u/syscall.c | 1 + dlls/win32u/win32u.spec | 2 +- dlls/wow64win/syscall.h | 1 + dlls/wow64win/user.c | 10 ++++ include/ntuser.h | 1 + 7 files changed, 110 insertions(+), 20 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 73aee6b849d..a06ef21c634 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -4321,19 +4321,9 @@ DWORD WINAPI GetMenuContextHelpId( HMENU menu ) /********************************************************************** * MenuItemFromPoint (USER32.@) */ -INT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen) +INT WINAPI MenuItemFromPoint( HWND hwnd, HMENU menu, POINT pt ) { - POPUPMENU *menu = grab_menu_ptr(hMenu); - UINT pos; - - /*FIXME: Do we have to handle hWnd here? */ - if (!menu) return -1; - - if (MENU_FindItemByCoords( menu, ptScreen, &pos ) != ht_item) - pos = -1; - - release_menu_ptr(menu); - return pos; + return NtUserMenuItemFromPoint( hwnd, menu, pt.x, pt.y ); }
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c index 8367af32395..d84af186da9 100644 --- a/dlls/win32u/menu.c +++ b/dlls/win32u/menu.c @@ -40,6 +40,15 @@ struct accelerator ACCEL table[1]; };
+enum hittest +{ + ht_nowhere, /* outside the menu */ + ht_border, /* anywhere that's not an item or a scroll arrow */ + ht_item, /* a menu item */ + ht_scroll_up, /* scroll up arrow */ + ht_scroll_down /* scroll down arrow */ +}; + /* maximum allowed depth of any branch in the menu tree. * This value is slightly larger than in windows (25) to * stay on the safe side. */ @@ -424,6 +433,76 @@ static UINT find_submenu( HMENU *handle_ptr, HMENU target ) return NO_SELECTED_ITEM; }
+/* Adjust menu item rectangle according to scrolling state */ +static void adjust_menu_item_rect( const POPUPMENU *menu, RECT *rect ) +{ + INT scroll_offset = menu->bScrolling ? menu->nScrollPos : 0; + OffsetRect( rect, menu->items_rect.left, menu->items_rect.top - scroll_offset ); +} + +/*********************************************************************** + * find_item_by_coords + * + * Find the item at the specified coordinates (screen coords). Does + * not work for child windows and therefore should not be called for + * an arbitrary system menu. + * + * Returns a hittest code. *pos will contain the position of the + * item or NO_SELECTED_ITEM. If the hittest code is ht_scroll_up + * or ht_scroll_down then *pos will contain the position of the + * item that's just outside the items_rect - ie, the one that would + * be scrolled completely into view. + */ +static enum hittest find_item_by_coords( const POPUPMENU *menu, POINT pt, UINT *pos ) +{ + enum hittest ht = ht_border; + MENUITEM *item; + RECT rect; + UINT i; + + *pos = NO_SELECTED_ITEM; + + if (!get_window_rect( menu->hWnd, &rect, get_thread_dpi() ) || !PtInRect( &rect, pt )) + return ht_nowhere; + + if (get_window_long( menu->hWnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) pt.x = rect.right - 1 - pt.x; + else pt.x -= rect.left; + pt.y -= rect.top; + + if (!PtInRect( &menu->items_rect, pt )) + { + if (!menu->bScrolling || pt.x < menu->items_rect.left || pt.x >= menu->items_rect.right) + return ht_border; + + /* On a scroll arrow. Update pt so that it points to the item just outside items_rect */ + if (pt.y < menu->items_rect.top) + { + ht = ht_scroll_up; + pt.y = menu->items_rect.top - 1; + } + else + { + ht = ht_scroll_down; + pt.y = menu->items_rect.bottom; + } + } + + item = menu->items; + for (i = 0; i < menu->nItems; i++, item++) + { + rect = item->rect; + adjust_menu_item_rect( menu, &rect ); + if (PtInRect( &rect, pt )) + { + *pos = i; + if (ht != ht_scroll_up && ht != ht_scroll_down) ht = ht_item; + break; + } + } + + return ht; +} + /* see GetMenu */ HMENU get_menu( HWND hwnd ) { @@ -1040,6 +1119,21 @@ static HMENU get_sub_menu( HMENU handle, INT pos ) return submenu; }
+/********************************************************************** + * NtUserMenuItemFromPoint (win32u.@) + */ +INT WINAPI NtUserMenuItemFromPoint( HWND hwnd, HMENU handle, int x, int y ) +{ + POINT pt = { .x = x, .y = y }; + POPUPMENU *menu; + UINT pos; + + if (!(menu = grab_menu_ptr(handle))) return -1; + if (find_item_by_coords( menu, pt, &pos ) != ht_item) pos = -1; + release_menu_ptr(menu); + return pos; +} + /********************************************************************** * NtUserGetSystemMenu (win32u.@) */ @@ -1823,13 +1917,6 @@ got_bitmap: NtGdiDeleteObjectApp( mem_hdc ); }
-/* Adjust menu item rectangle according to scrolling state */ -static void adjust_menu_item_rect( const POPUPMENU *menu, RECT *rect ) -{ - INT scroll_offset = menu->bScrolling ? menu->nScrollPos : 0; - OffsetRect( rect, menu->items_rect.left, menu->items_rect.top - scroll_offset ); -} - /* Draw a single menu item */ static void draw_menu_item( HWND hwnd, POPUPMENU *menu, HWND owner, HDC hdc, MENUITEM *item, BOOL menu_bar, UINT odaction ) diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index ac13580308d..a926049f0ed 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -151,6 +151,7 @@ static void * const syscalls[] = NtUserInternalGetWindowText, NtUserKillTimer, NtUserLockWindowUpdate, + NtUserMenuItemFromPoint, NtUserNotifyWinEvent, NtUserOpenDesktop, NtUserOpenInputDesktop, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 4dfebaa9d2d..f296f162fff 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1078,7 +1078,7 @@ @ stub NtUserMapPointsByVisualIdentifier @ stdcall NtUserMapVirtualKeyEx(long long long) @ stub NtUserMarkWindowForRawMouse -@ stub NtUserMenuItemFromPoint +@ stdcall -syscall NtUserMenuItemFromPoint(long long long long) @ stdcall NtUserMessageCall(long long long long long long long) @ stub NtUserMinInitialize @ stub NtUserMinMaximize diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index e30d367cda7..7c9627a6121 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -138,6 +138,7 @@ SYSCALL_ENTRY( NtUserInternalGetWindowText ) \ SYSCALL_ENTRY( NtUserKillTimer ) \ SYSCALL_ENTRY( NtUserLockWindowUpdate ) \ + SYSCALL_ENTRY( NtUserMenuItemFromPoint ) \ SYSCALL_ENTRY( NtUserNotifyWinEvent ) \ SYSCALL_ENTRY( NtUserOpenDesktop ) \ SYSCALL_ENTRY( NtUserOpenInputDesktop ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index c2d134626f1..51c0a5d0ed8 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -736,6 +736,16 @@ NTSTATUS WINAPI wow64_NtUserGetMenuItemRect( UINT *args ) return NtUserGetMenuItemRect( hwnd, handle, item, rect ); }
+NTSTATUS WINAPI wow64_NtUserMenuItemFromPoint( UINT *args ) +{ + HWND hwnd = get_handle( &args ); + HMENU handle = get_handle( &args ); + int x = get_ulong( &args ); + int y = get_ulong( &args ); + + return NtUserMenuItemFromPoint( hwnd, handle, x, y ); +} + NTSTATUS WINAPI wow64_NtUserSetMenuContextHelpId( UINT *args ) { HMENU menu = get_handle( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index 5f744c24906..0415ba076a5 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -620,6 +620,7 @@ BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format ); BOOL WINAPI NtUserKillTimer( HWND hwnd, UINT_PTR id ); BOOL WINAPI NtUserLockWindowUpdate( HWND hwnd ); UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ); +INT WINAPI NtUserMenuItemFromPoint( HWND hwnd, HMENU handle, int x, int y ); LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *result_info, DWORD type, BOOL ansi ); BOOL WINAPI NtUserMoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy, BOOL repaint );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them if they are indeed new. Note that rare failures and failures with always changing text (e.g. because of memory addresses) can cause false positives. If this is what happened, then fixing those would really help.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117025
Your paranoid android.
=== debian11 (32 bit Chinese:China 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/defwnd.c | 23 ----------------------- dlls/win32u/defwnd.c | 27 +++++++++++++++++++++++++++ dlls/win32u/menu.c | 6 ++++++ dlls/win32u/message.c | 2 +- dlls/win32u/win32u_private.h | 2 ++ dlls/win32u/window.c | 4 ++-- 6 files changed, 38 insertions(+), 26 deletions(-)
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index df5aa9353f4..6f2c3013aaa 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -435,29 +435,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa SendMessageW( parent, msg, wParam, lParam ); break; } - case WM_KEYF1: - { - HELPINFO hi; - - hi.cbSize = sizeof(HELPINFO); - GetCursorPos( &hi.MousePos ); - if (MENU_IsMenuActive()) - { - hi.iContextType = HELPINFO_MENUITEM; - hi.hItemHandle = MENU_IsMenuActive(); - hi.iCtrlId = MenuItemFromPoint( hwnd, hi.hItemHandle, hi.MousePos ); - hi.dwContextId = GetMenuContextHelpId( hi.hItemHandle ); - } - else - { - hi.iContextType = HELPINFO_WINDOW; - hi.hItemHandle = hwnd; - hi.iCtrlId = GetWindowLongPtrA( hwnd, GWLP_ID ); - hi.dwContextId = GetWindowContextHelpId( hwnd ); - } - SendMessageW( hwnd, WM_HELP, 0, (LPARAM)&hi ); - break; - }
case WM_INPUTLANGCHANGEREQUEST: NtUserActivateKeyboardLayout( (HKL)lParam, 0 ); diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index f9a23bcee3f..3705cbf8022 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -1766,6 +1766,33 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, case WM_SYSCOMMAND: result = handle_sys_command( hwnd, wparam, lparam ); break; + + case WM_KEYF1: + { + HELPINFO hi; + + hi.cbSize = sizeof(HELPINFO); + get_cursor_pos( &hi.MousePos ); + if (is_menu_active()) + { + MENUINFO info = { .cbSize = sizeof(info), .fMask = MIM_HELPID }; + hi.iContextType = HELPINFO_MENUITEM; + hi.hItemHandle = is_menu_active(); + hi.iCtrlId = NtUserMenuItemFromPoint( hwnd, hi.hItemHandle, + hi.MousePos.x, hi.MousePos.y ); + get_menu_info( hi.hItemHandle, &info ); + hi.dwContextId = info.dwContextHelpID; + } + else + { + hi.iContextType = HELPINFO_WINDOW; + hi.hItemHandle = hwnd; + hi.iCtrlId = get_window_long_ptr( hwnd, GWLP_ID, FALSE ); + hi.dwContextId = get_window_context_help_id( hwnd ); + } + send_message( hwnd, WM_HELP, 0, (LPARAM)&hi ); + break; + } }
return result; diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c index d84af186da9..8ccece38e74 100644 --- a/dlls/win32u/menu.c +++ b/dlls/win32u/menu.c @@ -2492,3 +2492,9 @@ LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM l } return 0; } + +HWND is_menu_active(void) +{ + if (!user_callbacks) return 0; + return user_callbacks->is_menu_active(); +} diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index cea1a33812a..f5315ec5dd4 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -1346,7 +1346,7 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, else if (msg->message == WM_KEYUP) { /* Handle VK_APPS key by posting a WM_CONTEXTMENU message */ - if (msg->wParam == VK_APPS && user_callbacks && !user_callbacks->is_menu_active()) + if (msg->wParam == VK_APPS && !is_menu_active()) NtUserPostMessage( msg->hwnd, WM_CONTEXTMENU, (WPARAM)msg->hwnd, -1 ); } } diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index d3f060669a4..80fe2e027e0 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -402,6 +402,7 @@ extern BOOL get_menu_info( HMENU handle, MENUINFO *info ) DECLSPEC_HIDDEN; extern INT get_menu_item_count( HMENU handle ) DECLSPEC_HIDDEN; extern UINT get_menu_state( HMENU handle, UINT item_id, UINT flags ) DECLSPEC_HIDDEN; extern BOOL is_menu( HMENU handle ) DECLSPEC_HIDDEN; +extern HWND is_menu_active(void) DECLSPEC_HIDDEN; extern LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; extern BOOL set_window_menu( HWND hwnd, HMENU handle ) DECLSPEC_HIDDEN; @@ -463,6 +464,7 @@ extern HWND get_parent( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN; extern DPI_AWARENESS_CONTEXT get_window_dpi_awareness_context( HWND hwnd ) DECLSPEC_HIDDEN; extern MINMAXINFO get_min_max_info( HWND hwnd ) DECLSPEC_HIDDEN; +extern DWORD get_window_context_help_id( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND get_window_relative( HWND hwnd, UINT rel ) DECLSPEC_HIDDEN; extern DWORD get_window_thread( HWND hwnd, DWORD *process ) DECLSPEC_HIDDEN; extern HWND is_current_process_window( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 94f285de2bb..5575b9a0381 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -4524,7 +4524,7 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info ) }
/* see GetWindowContextHelpId */ -static DWORD get_window_context_help_id( HWND hwnd ) +DWORD get_window_context_help_id( HWND hwnd ) { DWORD retval; WND *win = get_win_ptr( hwnd ); @@ -4759,7 +4759,7 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd )
if (call_hooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
- if (user_callbacks && user_callbacks->is_menu_active() == hwnd) + if (user_callbacks && is_menu_active() == hwnd) user_callbacks->pEndMenu();
is_child = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/button.c | 12 ++++++------ dlls/user32/combo.c | 16 ++++++++-------- dlls/user32/edit.c | 6 +++--- dlls/user32/listbox.c | 28 ++++++++++++++-------------- dlls/user32/menu.c | 4 ++-- dlls/user32/painting.c | 35 ----------------------------------- dlls/user32/scroll.c | 2 +- dlls/user32/user32.spec | 4 ++-- dlls/win32u/dce.c | 30 ++++++++++++++++++++++++++++++ dlls/win32u/gdiobj.c | 2 ++ dlls/win32u/win32u.spec | 4 ++-- dlls/win32u/win32u_private.h | 2 ++ dlls/win32u/wrappers.c | 12 ++++++++++++ include/ntuser.h | 2 ++ 14 files changed, 86 insertions(+), 73 deletions(-)
diff --git a/dlls/user32/button.c b/dlls/user32/button.c index f4b570126f7..d1dc6a3c6ff 100644 --- a/dlls/user32/button.c +++ b/dlls/user32/button.c @@ -382,7 +382,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, if (unicode) DefWindowProcW( hWnd, WM_SETTEXT, wParam, lParam ); else DefWindowProcA( hWnd, WM_SETTEXT, wParam, lParam ); if (btn_type == BS_GROUPBOX) /* Yes, only for BS_GROUPBOX */ - InvalidateRect( hWnd, NULL, TRUE ); + NtUserInvalidateRect( hWnd, NULL, TRUE ); else paint_button( hWnd, btn_type, ODA_DRAWENTIRE ); return 1; /* success. FIXME: check text length */ @@ -390,7 +390,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
case WM_SETFONT: set_button_font( hWnd, (HFONT)wParam ); - if (lParam) InvalidateRect(hWnd, NULL, TRUE); + if (lParam) NtUserInvalidateRect(hWnd, NULL, TRUE); break;
case WM_GETFONT: @@ -415,11 +415,11 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, if (style & BS_NOTIFY) BUTTON_NOTIFY_PARENT(hWnd, BN_KILLFOCUS);
- InvalidateRect( hWnd, NULL, FALSE ); + NtUserInvalidateRect( hWnd, NULL, FALSE ); break;
case WM_SYSCOLORCHANGE: - InvalidateRect( hWnd, NULL, FALSE ); + NtUserInvalidateRect( hWnd, NULL, FALSE ); break;
case BM_SETSTYLE: @@ -429,7 +429,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
/* Only redraw if lParam flag is set.*/ if (lParam) - InvalidateRect( hWnd, NULL, TRUE ); + NtUserInvalidateRect( hWnd, NULL, TRUE );
break;
@@ -452,7 +452,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, return 0; } oldHbitmap = (HBITMAP)SetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET, lParam ); - InvalidateRect( hWnd, NULL, FALSE ); + NtUserInvalidateRect( hWnd, NULL, FALSE ); return (LRESULT)oldHbitmap;
case BM_GETIMAGE: diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c index 73ec5691e88..fe7b33235c0 100644 --- a/dlls/user32/combo.c +++ b/dlls/user32/combo.c @@ -1084,9 +1084,9 @@ BOOL COMBO_FlipListbox( LPHEADCOMBO lphc, BOOL ok, BOOL bRedrawButton ) * CBRepaintButton */ static void CBRepaintButton( LPHEADCOMBO lphc ) - { - InvalidateRect(lphc->self, &lphc->buttonRect, TRUE); - UpdateWindow(lphc->self); +{ + NtUserInvalidateRect(lphc->self, &lphc->buttonRect, TRUE); + UpdateWindow(lphc->self); }
/*********************************************************************** @@ -1104,7 +1104,7 @@ static void COMBO_SetFocus( LPHEADCOMBO lphc ) /* lphc->wState |= CBF_FOCUSED; */
if( !(lphc->wState & CBF_EDIT) ) - InvalidateRect(lphc->self, &lphc->textRect, TRUE); + NtUserInvalidateRect(lphc->self, &lphc->textRect, TRUE);
CB_NOTIFY( lphc, CBN_SETFOCUS ); lphc->wState |= CBF_FOCUSED; @@ -1130,7 +1130,7 @@ static void COMBO_KillFocus( LPHEADCOMBO lphc )
/* redraw text */ if( !(lphc->wState & CBF_EDIT) ) - InvalidateRect(lphc->self, &lphc->textRect, TRUE); + NtUserInvalidateRect(lphc->self, &lphc->textRect, TRUE);
CB_NOTIFY( lphc, CBN_KILLFOCUS ); } @@ -1561,7 +1561,7 @@ static LRESULT COMBO_SelectString( LPHEADCOMBO lphc, INT start, LPARAM pText, BO CBUpdateEdit( lphc, index ); else { - InvalidateRect(lphc->self, &lphc->textRect, TRUE); + NtUserInvalidateRect(lphc->self, &lphc->textRect, TRUE); } } return (LRESULT)index; @@ -1854,7 +1854,7 @@ LRESULT ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM lPar EnableWindow( lphc->hWndLBox, (BOOL)wParam );
/* Force the control to repaint when the enabled state changes. */ - InvalidateRect(lphc->self, NULL, TRUE); + NtUserInvalidateRect(lphc->self, NULL, TRUE); return TRUE; case WM_SETREDRAW: if( wParam ) @@ -2003,7 +2003,7 @@ LRESULT ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM lPar if( (lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc) ) SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)L""); else - InvalidateRect(lphc->self, NULL, TRUE); + NtUserInvalidateRect(lphc->self, NULL, TRUE); return TRUE; case CB_INITSTORAGE: return SendMessageW(lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam); diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index 70f105b9a0a..439e33c0b14 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -1421,7 +1421,7 @@ static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase) es->flags &= ~EF_UPDATE; EDIT_NOTIFY_PARENT(es, EN_UPDATE); } - InvalidateRgn(es->hwndSelf, hrgn, bErase); + NtUserInvalidateRgn(es->hwndSelf, hrgn, bErase); }
@@ -1436,7 +1436,7 @@ static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase) es->flags &= ~EF_UPDATE; EDIT_NOTIFY_PARENT(es, EN_UPDATE); } - InvalidateRect(es->hwndSelf, rc, bErase); + NtUserInvalidateRect(es->hwndSelf, rc, bErase); }
/********************************************************************* @@ -4873,7 +4873,7 @@ LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, B }
if (old_style ^ es->style) - InvalidateRect(es->hwndSelf, NULL, TRUE); + NtUserInvalidateRect(es->hwndSelf, NULL, TRUE);
result = 1; break; diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index b8f127c0963..1e7231b4c05 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -443,7 +443,7 @@ static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll ) SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); } else - InvalidateRect( descr->self, NULL, TRUE ); + NtUserInvalidateRect( descr->self, NULL, TRUE ); descr->top_item = index; LISTBOX_UpdateScroll( descr ); return LB_OKAY; @@ -465,7 +465,7 @@ static void LISTBOX_UpdatePage( LB_DESCR *descr ) if (page_size == descr->page_size) return; descr->page_size = page_size; if (descr->style & LBS_MULTICOLUMN) - InvalidateRect( descr->self, NULL, TRUE ); + NtUserInvalidateRect( descr->self, NULL, TRUE ); LISTBOX_SetTopItem( descr, descr->top_item, FALSE ); }
@@ -510,7 +510,7 @@ static void LISTBOX_UpdateSize( LB_DESCR *descr ) /* Invalidate the focused item so it will be repainted correctly */ if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1) { - InvalidateRect( descr->self, &rect, FALSE ); + NtUserInvalidateRect( descr->self, &rect, FALSE ); } }
@@ -741,7 +741,7 @@ static void LISTBOX_SetRedraw( LB_DESCR *descr, BOOL on ) descr->style &= ~LBS_NOREDRAW; if (descr->style & LBS_DISPLAYCHANGED) { /* page was changed while setredraw false, refresh automatically */ - InvalidateRect(descr->self, NULL, TRUE); + NtUserInvalidateRect(descr->self, NULL, TRUE); if ((descr->top_item + descr->page_size) > descr->nb_items) { /* reset top of page if less than number of items/page */ descr->top_item = descr->nb_items - descr->page_size; @@ -1246,14 +1246,14 @@ static void LISTBOX_InvalidateItems( LB_DESCR *descr, INT index ) return; } rect.bottom = descr->height; - InvalidateRect( descr->self, &rect, TRUE ); + NtUserInvalidateRect( descr->self, &rect, TRUE ); if (descr->style & LBS_MULTICOLUMN) { /* Repaint the other columns */ rect.left = rect.right; rect.right = descr->width; rect.top = 0; - InvalidateRect( descr->self, &rect, TRUE ); + NtUserInvalidateRect( descr->self, &rect, TRUE ); } } } @@ -1263,7 +1263,7 @@ static void LISTBOX_InvalidateItemRect( LB_DESCR *descr, INT index ) RECT rect;
if (LISTBOX_GetItemRect( descr, index, &rect ) == 1) - InvalidateRect( descr->self, &rect, TRUE ); + NtUserInvalidateRect( descr->self, &rect, TRUE ); }
/*********************************************************************** @@ -1314,7 +1314,7 @@ static LRESULT LISTBOX_SetItemHeight( LB_DESCR *descr, INT index, INT height, BO LISTBOX_UpdatePage( descr ); LISTBOX_UpdateScroll( descr ); if (repaint) - InvalidateRect( descr->self, 0, TRUE ); + NtUserInvalidateRect( descr->self, 0, TRUE ); } return LB_OKAY; } @@ -1339,12 +1339,12 @@ static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos ) RECT rect; /* Invalidate the focused item so it will be repainted correctly */ if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1) - InvalidateRect( descr->self, &rect, TRUE ); + NtUserInvalidateRect( descr->self, &rect, TRUE ); NtUserScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL, SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN ); } else - InvalidateRect( descr->self, NULL, TRUE ); + NtUserInvalidateRect( descr->self, NULL, TRUE ); }
@@ -1863,7 +1863,7 @@ static LRESULT LISTBOX_SetCount( LB_DESCR *descr, UINT count ) } else SendMessageW(descr->self, LB_RESETCONTENT, 0, 0);
- InvalidateRect( descr->self, NULL, TRUE ); + NtUserInvalidateRect( descr->self, NULL, TRUE ); return LB_OKAY; }
@@ -2696,7 +2696,7 @@ LRESULT ListBoxWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam case LB_RESETCONTENT: LISTBOX_ResetContent( descr ); LISTBOX_UpdateScroll( descr ); - InvalidateRect( descr->self, NULL, TRUE ); + NtUserInvalidateRect( descr->self, NULL, TRUE ); return 0;
case LB_ADDSTRING: @@ -3076,7 +3076,7 @@ LRESULT ListBoxWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam return LISTBOX_Destroy( descr );
case WM_ENABLE: - InvalidateRect( descr->self, NULL, TRUE ); + NtUserInvalidateRect( descr->self, NULL, TRUE ); return 0;
case WM_SETREDRAW: @@ -3102,7 +3102,7 @@ LRESULT ListBoxWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam return (LRESULT)descr->font; case WM_SETFONT: LISTBOX_SetFont( descr, (HFONT)wParam ); - if (lParam) InvalidateRect( descr->self, 0, TRUE ); + if (lParam) NtUserInvalidateRect( descr->self, 0, TRUE ); return 0; case WM_SETFOCUS: descr->in_focus = TRUE; diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index a06ef21c634..d0637a61809 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -1728,14 +1728,14 @@ MENU_EnsureMenuItemVisible(LPPOPUPMENU lppop, UINT wIndex, HDC hdc) { arrow_rect.top = 0; arrow_rect.bottom = lppop->items_rect.top; - InvalidateRect(lppop->hWnd, &arrow_rect, FALSE); + NtUserInvalidateRect(lppop->hWnd, &arrow_rect, FALSE); } if (nOldPos + scroll_height == lppop->nTotalHeight || lppop->nScrollPos + scroll_height == lppop->nTotalHeight) { arrow_rect.top = lppop->items_rect.bottom; arrow_rect.bottom = lppop->Height; - InvalidateRect(lppop->hWnd, &arrow_rect, FALSE); + NtUserInvalidateRect(lppop->hWnd, &arrow_rect, FALSE); } } } diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 419c952d998..89451e4e46b 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -62,41 +62,6 @@ BOOL WINAPI UpdateWindow( HWND hwnd ) }
-/*********************************************************************** - * InvalidateRgn (USER32.@) - */ -BOOL WINAPI InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase ) -{ - if (!hwnd) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - - return NtUserRedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) ); -} - - -/*********************************************************************** - * InvalidateRect (USER32.@) - * - * MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws - * all windows and sends WM_ERASEBKGND and WM_NCPAINT. - */ -BOOL WINAPI InvalidateRect( HWND hwnd, const RECT *rect, BOOL erase ) -{ - UINT flags = RDW_INVALIDATE | (erase ? RDW_ERASE : 0); - - if (!hwnd) - { - flags = RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW; - rect = NULL; - } - - return NtUserRedrawWindow( hwnd, rect, 0, flags ); -} - - /*********************************************************************** * ValidateRgn (USER32.@) */ diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c index 8bf1f4312ab..b6f15b4a295 100644 --- a/dlls/user32/scroll.c +++ b/dlls/user32/scroll.c @@ -1507,7 +1507,7 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA rect.bottom=rect.top+thumbSize; } NtUserHideCaret( hwnd ); - InvalidateRect(hwnd,&rect,0); + NtUserInvalidateRect( hwnd, &rect, 0 ); DestroyCaret(); } break; diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 1399f488720..d34bff5715e 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -448,8 +448,8 @@ @ stdcall InternalGetWindowIcon(ptr long) NtUserInternalGetWindowIcon @ stdcall InternalGetWindowText(long ptr long) NtUserInternalGetWindowText @ stdcall IntersectRect(ptr ptr ptr) -@ stdcall InvalidateRect(long ptr long) -@ stdcall InvalidateRgn(long long long) +@ stdcall InvalidateRect(long ptr long) NtUserInvalidateRect +@ stdcall InvalidateRgn(long long long) NtUserInvalidateRgn @ stdcall InvertRect(long ptr) @ stdcall -import IsCharAlphaA(long) @ stdcall -import IsCharAlphaNumericA(long) diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 872112e4a24..67590e80fa3 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -1575,6 +1575,36 @@ INT WINAPI NtUserExcludeUpdateRgn( HDC hdc, HWND hwnd ) return ret; }
+/*********************************************************************** + * NtUserInvalidateRgn (win32u.@) + */ +BOOL WINAPI NtUserInvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase ) +{ + if (!hwnd) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } + + return NtUserRedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) ); +} + +/*********************************************************************** + * NtUserInvalidateRect (win32u.@) + */ +BOOL WINAPI NtUserInvalidateRect( HWND hwnd, const RECT *rect, BOOL erase ) +{ + UINT flags = RDW_INVALIDATE | (erase ? RDW_ERASE : 0); + + if (!hwnd) + { + flags = RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW; + rect = NULL; + } + + return NtUserRedrawWindow( hwnd, rect, 0, flags ); +} + /*********************************************************************** * NtUserLockWindowUpdate (win32u.@) */ diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 9c6415236c2..3c2ec6bb2e9 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1189,6 +1189,8 @@ static struct unix_funcs unix_funcs = NtUserGetWindowPlacement, NtUserHideCaret, NtUserInternalGetWindowIcon, + NtUserInvalidateRect, + NtUserInvalidateRgn, NtUserIsClipboardFormatAvailable, NtUserMapVirtualKeyEx, NtUserMessageCall, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index f296f162fff..54f5f990676 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1047,8 +1047,8 @@ @ stdcall NtUserInternalGetWindowIcon(ptr long) @ stdcall -syscall NtUserInternalGetWindowText(long ptr long) @ stub NtUserInternalToUnicode -@ stub NtUserInvalidateRect -@ stub NtUserInvalidateRgn +@ stdcall NtUserInvalidateRect(long ptr long) +@ stdcall NtUserInvalidateRgn(long long long) @ stub NtUserIsChildWindowDpiMessageEnabled @ stdcall NtUserIsClipboardFormatAvailable(long) @ stub NtUserIsMouseInPointerEnabled diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 80fe2e027e0..d1bc382f031 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -251,6 +251,8 @@ struct unix_funcs BOOL (WINAPI *pNtUserGetWindowPlacement)( HWND hwnd, WINDOWPLACEMENT *placement ); BOOL (WINAPI *pNtUserHideCaret)( HWND hwnd ); HICON (WINAPI *pNtUserInternalGetWindowIcon)( HWND hwnd, UINT type ); + BOOL (WINAPI *pNtUserInvalidateRect)( HWND hwnd, const RECT *rect, BOOL erase ); + BOOL (WINAPI *pNtUserInvalidateRgn)( HWND hwnd, HRGN hrgn, BOOL erase ); 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/wrappers.c b/dlls/win32u/wrappers.c index 6620597b7b1..945ea5d7fd5 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1048,6 +1048,18 @@ HICON WINAPI NtUserInternalGetWindowIcon( HWND hwnd, UINT type ) return unix_funcs->pNtUserInternalGetWindowIcon( hwnd, type ); }
+BOOL WINAPI NtUserInvalidateRect( HWND hwnd, const RECT *rect, BOOL erase ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserInvalidateRect( hwnd, rect, erase ); +} + +BOOL WINAPI NtUserInvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserInvalidateRgn( hwnd, hrgn, erase ); +} + BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format ) { if (!unix_funcs) return FALSE; diff --git a/include/ntuser.h b/include/ntuser.h index 0415ba076a5..cf8a909493b 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -617,6 +617,8 @@ NTSTATUS WINAPI NtUserInitializeClientPfnArrays( const struct user_client_procs HICON WINAPI NtUserInternalGetWindowIcon( HWND hwnd, UINT type ); INT WINAPI NtUserInternalGetWindowText( HWND hwnd, WCHAR *text, INT count ); BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format ); +BOOL WINAPI NtUserInvalidateRect( HWND hwnd, const RECT *rect, BOOL erase ); +BOOL WINAPI NtUserInvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase ); BOOL WINAPI NtUserKillTimer( HWND hwnd, UINT_PTR id ); BOOL WINAPI NtUserLockWindowUpdate( HWND hwnd ); UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them if they are indeed new. Note that rare failures and failures with always changing text (e.g. because of memory addresses) can cause false positives. If this is what happened, then fixing those would really help.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117027
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32: win.c:10946: Test failed: GetForegroundWindow() = 00000000
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/class.c | 4 ++++ dlls/user32/win.c | 20 ++++---------------- dlls/win32u/sysparams.c | 8 ++++++++ dlls/win32u/win32u_private.h | 1 + dlls/win32u/window.c | 1 + include/ntuser.h | 12 ++++++++++++ 6 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index 620477f1b14..76e2688bb82 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -309,6 +309,8 @@ static void load_uxtheme(void) */ BOOL WINAPI User32RegisterBuiltinClasses( const struct win_hook_params *params, ULONG size ) { + DWORD layout; + register_builtin( &BUTTON_builtin_class ); register_builtin( &COMBO_builtin_class ); register_builtin( &COMBOLBOX_builtin_class ); @@ -322,6 +324,8 @@ BOOL WINAPI User32RegisterBuiltinClasses( const struct win_hook_params *params, register_builtin( &STATIC_builtin_class ); register_builtin( &IME_builtin_class );
+ GetProcessDefaultLayout( &layout ); /* make sure that process layout is initialized */ + /* Load uxtheme.dll so that standard scrollbars and dialogs are hooked for theming support */ load_uxtheme(); return TRUE; diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 99753791f09..9d19376fe44 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -36,8 +36,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
-static DWORD process_layout = ~0u; -
/*********************************************************************** * get_user_handle_ptr @@ -626,15 +624,6 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, } }
- /* FIXME: move to win32u */ - if (!cs->hwndParent && className != (const WCHAR *)DESKTOP_CLASS_ATOM && - (IS_INTRESOURCE(className) || wcsicmp( className, L"Message" ))) - { - DWORD layout; - GetProcessDefaultLayout( &layout ); - if (layout & LAYOUT_RTL) cs->dwExStyle |= WS_EX_LAYOUTRTL; - } - menu = cs->hMenu; if (!menu && info.lpszMenuName && (cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = LoadMenuW( cs->hInstance, info.lpszMenuName ); @@ -1610,7 +1599,8 @@ BOOL WINAPI GetProcessDefaultLayout( DWORD *layout ) SetLastError( ERROR_NOACCESS ); return FALSE; } - if (process_layout == ~0u) + *layout = NtUserGetProcessDefaultLayout(); + if (*layout == ~0u) { WCHAR *str, buffer[MAX_PATH]; DWORD i, version_layout = 0; @@ -1640,9 +1630,8 @@ BOOL WINAPI GetProcessDefaultLayout( DWORD *layout )
done: HeapFree( GetProcessHeap(), 0, data ); - process_layout = version_layout; + NtUserSetProcessDefaultLayout( *layout = version_layout ); } - *layout = process_layout; return TRUE; }
@@ -1654,8 +1643,7 @@ BOOL WINAPI GetProcessDefaultLayout( DWORD *layout ) */ BOOL WINAPI SetProcessDefaultLayout( DWORD layout ) { - process_layout = layout; - return TRUE; + return NtUserSetProcessDefaultLayout( layout ); }
#ifdef _WIN64 diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 1c1d9ddc621..d4ab352ccbd 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -360,6 +360,7 @@ union sysparam_all_entry
static UINT system_dpi; static RECT work_area; +DWORD process_layout = ~0u;
static HDC display_dc; static pthread_mutex_t display_dc_lock = PTHREAD_MUTEX_INITIALIZER; @@ -4714,6 +4715,9 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code ) case NtUserCallNoParam_GetInputState: return get_input_state();
+ case NtUserCallNoParam_GetProcessDefaultLayout: + return process_layout; + case NtUserCallNoParam_ReleaseCapture: return release_capture();
@@ -4805,6 +4809,10 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code ) case NtUserCallOneParam_SetCaretBlinkTime: return set_caret_blink_time( arg );
+ case NtUserCallOneParam_SetProcessDefaultLayout: + process_layout = arg; + return TRUE; + /* temporary exports */ case NtUserCallHooks: { diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index d1bc382f031..23343c413dc 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -424,6 +424,7 @@ extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM
/* sysparams.c */ extern BOOL enable_thunk_lock DECLSPEC_HIDDEN; +extern DWORD process_layout DECLSPEC_HIDDEN; extern HBRUSH get_55aa_brush(void) DECLSPEC_HIDDEN; extern DWORD get_dialog_base_units(void) DECLSPEC_HIDDEN; extern LONG get_char_dimensions( HDC hdc, TEXTMETRICW *metric, LONG *height ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 5575b9a0381..431686bdcaa 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5126,6 +5126,7 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, (class_name->Length != sizeof(messageW) || wcsnicmp( class_name->Buffer, messageW, ARRAYSIZE(messageW) ))) { + if (process_layout & LAYOUT_RTL) cs.dwExStyle |= WS_EX_LAYOUTRTL; parent = get_desktop_window(); } } diff --git a/include/ntuser.h b/include/ntuser.h index cf8a909493b..1f3cc2f2e7e 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -725,6 +725,7 @@ enum NtUserCallNoParam_GetDesktopWindow, NtUserCallNoParam_GetDialogBaseUnits, NtUserCallNoParam_GetInputState, + NtUserCallNoParam_GetProcessDefaultLayout, NtUserCallNoParam_ReleaseCapture, /* temporary exports */ NtUserExitingThread, @@ -751,6 +752,11 @@ static inline BOOL NtUserGetInputState(void) return NtUserCallNoParam( NtUserCallNoParam_GetInputState ); }
+static inline DWORD NtUserGetProcessDefaultLayout(void) +{ + return NtUserCallNoParam( NtUserCallNoParam_GetProcessDefaultLayout ); +} + static inline BOOL NtUserReleaseCapture(void) { return NtUserCallNoParam( NtUserCallNoParam_ReleaseCapture ); @@ -780,6 +786,7 @@ enum NtUserCallOneParam_MessageBeep, NtUserCallOneParam_RealizePalette, NtUserCallOneParam_SetCaretBlinkTime, + NtUserCallOneParam_SetProcessDefaultLayout, /* temporary exports */ NtUserCallHooks, NtUserGetDeskPattern, @@ -898,6 +905,11 @@ static inline UINT NtUserRealizePalette( HDC hdc ) return NtUserCallOneParam( HandleToUlong(hdc), NtUserCallOneParam_RealizePalette ); }
+static inline UINT NtUserSetProcessDefaultLayout( DWORD layout ) +{ + return NtUserCallOneParam( layout, NtUserCallOneParam_SetProcessDefaultLayout ); +} + /* NtUserCallTwoParam codes, not compatible with Windows */ enum {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them if they are indeed new. Note that rare failures and failures with always changing text (e.g. because of memory addresses) can cause false positives. If this is what happened, then fixing those would really help.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117028
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
user32: msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0135 was expected, but got msg 0x030f instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 7: the msg 0x8000 was expected, but got msg 0x0086 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: 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/defwnd.c | 8 -- dlls/win32u/defwnd.c | 177 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 8 deletions(-)
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 6f2c3013aaa..8f32594fd34 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -165,14 +165,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa case WM_NCMOUSELEAVE: return NC_HandleNCMouseLeave( hwnd );
- case WM_NCHITTEST: - { - POINT pt; - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - return NC_HandleNCHitTest( hwnd, pt ); - } - case WM_WINDOWPOSCHANGED: DEFWND_HandleWindowPosChanged( hwnd, (const WINDOWPOS *)lParam ); break; diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 3705cbf8022..6ec27fc6725 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -1621,6 +1621,175 @@ static void handle_nc_calc_size( HWND hwnd, WPARAM wparam, RECT *win_rect ) } }
+static LRESULT handle_nc_hit_test( HWND hwnd, POINT pt ) +{ + RECT rect, client_rect; + DWORD style, ex_style; + + TRACE( "hwnd %p pt %d,%d\n", hwnd, pt.x, pt.y ); + + get_window_rects( hwnd, COORDS_SCREEN, &rect, &client_rect, get_thread_dpi() ); + if (!PtInRect( &rect, pt )) return HTNOWHERE; + + style = get_window_long( hwnd, GWL_STYLE ); + ex_style = get_window_long( hwnd, GWL_EXSTYLE ); + + if (PtInRect( &client_rect, pt )) return HTCLIENT; + + /* Check borders */ + if (has_thick_frame( style, ex_style )) + { + InflateRect( &rect, -get_system_metrics( SM_CXFRAME ), -get_system_metrics( SM_CYFRAME )); + if (!PtInRect( &rect, pt )) + { + /* Check top sizing border */ + if (pt.y < rect.top) + { + if (pt.x < rect.left + get_system_metrics( SM_CXSIZE )) return HTTOPLEFT; + if (pt.x >= rect.right - get_system_metrics( SM_CXSIZE )) return HTTOPRIGHT; + return HTTOP; + } + /* Check bottom sizing border */ + if (pt.y >= rect.bottom) + { + if (pt.x < rect.left + get_system_metrics( SM_CXSIZE )) return HTBOTTOMLEFT; + if (pt.x >= rect.right - get_system_metrics( SM_CXSIZE )) return HTBOTTOMRIGHT; + return HTBOTTOM; + } + /* Check left sizing border */ + if (pt.x < rect.left) + { + if (pt.y < rect.top + get_system_metrics( SM_CYSIZE )) return HTTOPLEFT; + if (pt.y >= rect.bottom - get_system_metrics( SM_CYSIZE )) return HTBOTTOMLEFT; + return HTLEFT; + } + /* Check right sizing border */ + if (pt.x >= rect.right) + { + if (pt.y < rect.top + get_system_metrics( SM_CYSIZE )) return HTTOPRIGHT; + if (pt.y >= rect.bottom-get_system_metrics( SM_CYSIZE )) return HTBOTTOMRIGHT; + return HTRIGHT; + } + } + } + else /* No thick frame */ + { + if (has_dialog_frame( style, ex_style )) + InflateRect( &rect, -get_system_metrics( SM_CXDLGFRAME ), + -get_system_metrics( SM_CYDLGFRAME )); + else if (has_thin_frame( style )) + InflateRect(&rect, -get_system_metrics( SM_CXBORDER ), + -get_system_metrics( SM_CYBORDER )); + if (!PtInRect( &rect, pt )) return HTBORDER; + } + + /* Check caption */ + if ((style & WS_CAPTION) == WS_CAPTION) + { + if (ex_style & WS_EX_TOOLWINDOW) + rect.top += get_system_metrics( SM_CYSMCAPTION ) - 1; + else + rect.top += get_system_metrics( SM_CYCAPTION ) - 1; + if (!PtInRect( &rect, pt )) + { + BOOL min_or_max_box = (style & WS_SYSMENU) && (style & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)); + if (ex_style & WS_EX_LAYOUTRTL) + { + /* Check system menu */ + if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW) && + get_nc_icon_for_window( hwnd )) + { + rect.right -= get_system_metrics( SM_CYCAPTION ) - 1; + if (pt.x > rect.right) return HTSYSMENU; + } + + /* Check close button */ + if (style & WS_SYSMENU) + { + rect.left += get_system_metrics( SM_CYCAPTION ); + if (pt.x < rect.left) return HTCLOSE; + } + + if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW)) + { + /* Check maximize box */ + rect.left += get_system_metrics( SM_CXSIZE ); + if (pt.x < rect.left) return HTMAXBUTTON; + + /* Check minimize box */ + rect.left += get_system_metrics( SM_CXSIZE ); + if (pt.x < rect.left) return HTMINBUTTON; + } + } + else + { + /* Check system menu */ + if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW) && + get_nc_icon_for_window( hwnd )) + { + rect.left += get_system_metrics( SM_CYCAPTION ) - 1; + if (pt.x < rect.left) return HTSYSMENU; + } + + /* Check close button */ + if (style & WS_SYSMENU) + { + rect.right -= get_system_metrics( SM_CYCAPTION ); + if (pt.x > rect.right) return HTCLOSE; + } + + if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW)) + { + /* Check maximize box */ + rect.right -= get_system_metrics( SM_CXSIZE ); + if (pt.x > rect.right) return HTMAXBUTTON; + + /* Check minimize box */ + rect.right -= get_system_metrics( SM_CXSIZE ); + if (pt.x > rect.right) return HTMINBUTTON; + } + } + return HTCAPTION; + } + } + + /* Check menu bar */ + if (has_menu( hwnd, style ) && (pt.y < client_rect.top) && + (pt.x >= client_rect.left) && (pt.x < client_rect.right)) + return HTMENU; + + /* Check vertical scroll bar */ + if (ex_style & WS_EX_LAYOUTRTL) ex_style ^= WS_EX_LEFTSCROLLBAR; + if (style & WS_VSCROLL) + { + if (ex_style & WS_EX_LEFTSCROLLBAR) + client_rect.left -= get_system_metrics( SM_CXVSCROLL ); + else + client_rect.right += get_system_metrics( SM_CXVSCROLL ); + if (PtInRect( &client_rect, pt )) return HTVSCROLL; + } + + /* Check horizontal scroll bar */ + if (style & WS_HSCROLL) + { + client_rect.bottom += get_system_metrics( SM_CYHSCROLL ); + if (PtInRect( &client_rect, pt )) + { + /* Check size box */ + if ((style & WS_VSCROLL) && + ((ex_style & WS_EX_LEFTSCROLLBAR) + ? (pt.x <= client_rect.left + get_system_metrics( SM_CXVSCROLL )) + : (pt.x >= client_rect.right - get_system_metrics( SM_CXVSCROLL )))) + return HTSIZE; + return HTHSCROLL; + } + } + + /* Has to return HTNOWHERE if nothing was found + Could happen when a window has a customized non client area */ + return HTNOWHERE; +} + LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) { LRESULT result = 0; @@ -1652,6 +1821,14 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, handle_nc_calc_size( hwnd, wparam, (RECT *)lparam ); break;
+ case WM_NCHITTEST: + { + POINT pt; + pt.x = (short)LOWORD( lparam ); + pt.y = (short)HIWORD( lparam ); + return handle_nc_hit_test( hwnd, pt ); + } + case WM_NCPAINT: return handle_nc_paint( hwnd, (HRGN)wparam );
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/controls.h | 1 - dlls/user32/defwnd.c | 3 - dlls/user32/focus.c | 11 -- dlls/user32/nonclient.c | 331 ------------------------------------- dlls/user32/user_private.h | 1 - dlls/win32u/defwnd.c | 176 +++++++++++++++++++- 6 files changed, 175 insertions(+), 348 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index c09ab1233d0..eec6a4babe2 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -121,7 +121,6 @@ extern HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) DECLSPEC_HIDDEN;
/* nonclient area */ extern LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN; -extern LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCMouseMove( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCMouseLeave( HWND hwnd ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 8f32594fd34..0c783666b7e 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -175,9 +175,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa iF10Key = iMenuSysKey = 0; break;
- case WM_NCLBUTTONDOWN: - return NC_HandleNCLButtonDown( hwnd, wParam, lParam ); - case WM_LBUTTONDBLCLK: return NC_HandleNCLButtonDblClk( hwnd, HTCLIENT, lParam );
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index c494adce5a6..7e1536ab802 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -32,17 +32,6 @@ #include "wine/server.h"
-/******************************************************************* - * FOCUS_MouseActivate - * - * Activate a window as a result of a mouse click - */ -BOOL FOCUS_MouseActivate( HWND hwnd ) -{ - return NtUserSetForegroundWindow( hwnd, TRUE ); -} - - /******************************************************************* * SetForegroundWindow (USER32.@) */ diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 96518ed4648..128f633fa33 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -624,111 +624,6 @@ BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down) }
-/****************************************************************************** - * - * NC_DrawCloseButton - * - * Draws the close button. - * - * If bGrayed is true, then draw a disabled Close button - * - *****************************************************************************/ - -static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed) -{ - RECT rect; - DWORD style = GetWindowLongW( hwnd, GWL_STYLE ); - DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); - - NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); - - /* A tool window has a smaller Close button */ - if (ex_style & WS_EX_TOOLWINDOW) - { - INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */ - INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */ - INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION); - - rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2; - rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2; - rect.bottom = rect.top + iBmpHeight; - rect.right = rect.left + iBmpWidth; - } - else - { - rect.left = rect.right - GetSystemMetrics(SM_CXSIZE); - rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2; - rect.top += 2; - rect.right -= 2; - } - DrawFrameControl( hdc, &rect, DFC_CAPTION, - (DFCS_CAPTIONCLOSE | - (down ? DFCS_PUSHED : 0) | - (bGrayed ? DFCS_INACTIVE : 0)) ); -} - -/****************************************************************************** - * NC_DrawMaxButton - * - * Draws the maximize button for windows. - * If bGrayed is true, then draw a disabled Maximize button - */ -static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed) -{ - RECT rect; - UINT flags; - DWORD style = GetWindowLongW( hwnd, GWL_STYLE ); - DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); - - /* never draw maximize box when window has WS_EX_TOOLWINDOW style */ - if (ex_style & WS_EX_TOOLWINDOW) return; - - flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX; - - NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); - if (style & WS_SYSMENU) - rect.right -= GetSystemMetrics(SM_CXSIZE); - rect.left = rect.right - GetSystemMetrics(SM_CXSIZE); - rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2; - rect.top += 2; - rect.right -= 2; - if (down) flags |= DFCS_PUSHED; - if (bGrayed) flags |= DFCS_INACTIVE; - DrawFrameControl( hdc, &rect, DFC_CAPTION, flags ); -} - -/****************************************************************************** - * NC_DrawMinButton - * - * Draws the minimize button for windows. - * If bGrayed is true, then draw a disabled Minimize button - */ -static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed) -{ - RECT rect; - UINT flags; - DWORD style = GetWindowLongW( hwnd, GWL_STYLE ); - DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); - - /* never draw minimize box when window has WS_EX_TOOLWINDOW style */ - if (ex_style & WS_EX_TOOLWINDOW) return; - - flags = (style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN; - - NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); - if (style & WS_SYSMENU) - rect.right -= GetSystemMetrics(SM_CXSIZE); - if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX)) - rect.right -= GetSystemMetrics(SM_CXSIZE) - 2; - rect.left = rect.right - GetSystemMetrics(SM_CXSIZE); - rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2; - rect.top += 2; - rect.right -= 2; - if (down) flags |= DFCS_PUSHED; - if (bGrayed) flags |= DFCS_INACTIVE; - DrawFrameControl( hdc, &rect, DFC_CAPTION, flags ); -} - /*********************************************************************** * NC_HandleSetCursor * @@ -798,147 +693,6 @@ void NC_GetSysPopupPos( HWND hwnd, RECT* rect ) } }
-/*********************************************************************** - * NC_TrackMinMaxBox - * - * Track a mouse button press on the minimize or maximize box. - * - * The big difference between 3.1 and 95 is the disabled button state. - * In win95 the system button can be disabled, so it can ignore the mouse - * event. - * - */ -static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam ) -{ - MSG msg; - HDC hdc = GetWindowDC( hwnd ); - BOOL pressed = TRUE; - UINT state; - DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE); - HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE); - - void (*paintButton)(HWND, HDC, BOOL, BOOL); - - if (wParam == HTMINBUTTON) - { - /* If the style is not present, do nothing */ - if (!(wndStyle & WS_MINIMIZEBOX)) - return; - - /* Check if the sysmenu item for minimize is there */ - state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND); - - paintButton = NC_DrawMinButton; - } - else - { - /* If the style is not present, do nothing */ - if (!(wndStyle & WS_MAXIMIZEBOX)) - return; - - /* Check if the sysmenu item for maximize is there */ - state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND); - - paintButton = NC_DrawMaxButton; - } - - NtUserSetCapture( hwnd ); - - (*paintButton)( hwnd, hdc, TRUE, FALSE); - - while(1) - { - BOOL oldstate = pressed; - - if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; - if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; - - if(msg.message == WM_LBUTTONUP) - break; - - if(msg.message != WM_MOUSEMOVE) - continue; - - pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam); - if (pressed != oldstate) - (*paintButton)( hwnd, hdc, pressed, FALSE); - } - - if(pressed) - (*paintButton)(hwnd, hdc, FALSE, FALSE); - - ReleaseCapture(); - NtUserReleaseDC( hwnd, hdc ); - - /* If the minimize or maximize items of the sysmenu are not there */ - /* or if the style is not present, do nothing */ - if ((!pressed) || (state == 0xFFFFFFFF)) - return; - - if (wParam == HTMINBUTTON) - SendMessageW( hwnd, WM_SYSCOMMAND, - IsIconic(hwnd) ? SC_RESTORE : SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) ); - else - SendMessageW( hwnd, WM_SYSCOMMAND, - IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) ); -} - -/*********************************************************************** - * NC_TrackCloseButton - * - * Track a mouse button press on the Win95 close button. - */ -static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - MSG msg; - HDC hdc; - BOOL pressed = TRUE; - HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE); - UINT state; - - if(hSysMenu == 0) - return; - - state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); - - /* If the close item of the sysmenu is disabled or not present do nothing */ - if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF)) - return; - - hdc = GetWindowDC( hwnd ); - - NtUserSetCapture( hwnd ); - - NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE); - - while(1) - { - BOOL oldstate = pressed; - - if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; - if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; - - if(msg.message == WM_LBUTTONUP) - break; - - if(msg.message != WM_MOUSEMOVE) - continue; - - pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam); - if (pressed != oldstate) - NC_DrawCloseButton (hwnd, hdc, pressed, FALSE); - } - - if(pressed) - NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE); - - ReleaseCapture(); - NtUserReleaseDC( hwnd, hdc ); - if (!pressed) return; - - SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam ); -} -
/*********************************************************************** * NC_TrackScrollBar @@ -963,91 +717,6 @@ static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt ) }
-/*********************************************************************** - * NC_HandleNCLButtonDown - * - * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc(). - */ -LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) -{ - LONG style = GetWindowLongW( hwnd, GWL_STYLE ); - - switch(wParam) /* Hit test */ - { - case HTCAPTION: - { - HWND top = hwnd, parent; - while(1) - { - if ((GetWindowLongW( top, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) != WS_CHILD) - break; - parent = NtUserGetAncestor( top, GA_PARENT ); - if (!parent || parent == GetDesktopWindow()) break; - top = parent; - } - - if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top)) - SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam ); - break; - } - - case HTSYSMENU: - if (style & WS_SYSMENU) - { - HDC hDC = GetWindowDC( hwnd ); - NC_DrawSysButton( hwnd, hDC, TRUE ); - NtUserReleaseDC( hwnd, hDC ); - SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam ); - } - break; - - case HTMENU: - SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam ); - break; - - case HTHSCROLL: - SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam ); - break; - - case HTVSCROLL: - SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam ); - break; - - case HTMINBUTTON: - case HTMAXBUTTON: - NC_TrackMinMaxBox( hwnd, wParam ); - break; - - case HTCLOSE: - NC_TrackCloseButton (hwnd, wParam, lParam); - break; - - case HTLEFT: - case HTRIGHT: - case HTTOP: - case HTTOPLEFT: - case HTTOPRIGHT: - case HTBOTTOM: - case HTBOTTOMLEFT: - case HTBOTTOMRIGHT: - /* Old comment: - * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU" - * This was previously done by setting wParam=SC_SIZE + wParam - 2 - */ - /* But that is not what WinNT does. Instead it sends this. This - * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds - * SC_MOUSEMENU into wParam. - */ - SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam); - break; - - case HTBORDER: - break; - } - return 0; -} - - /*********************************************************************** * NC_HandleNCRButtonDown * diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index aa3e1565bfa..3997e2410f8 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -86,7 +86,6 @@ extern void free_cached_data( UINT format, HANDLE handle ) DECLSPEC_HIDDEN; extern HANDLE render_synthesized_format( UINT format, UINT from ) DECLSPEC_HIDDEN;
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN; -extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN; extern HDC get_display_dc(void) DECLSPEC_HIDDEN; extern void release_display_dc( HDC hdc ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 6ec27fc6725..780570b5ad4 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -1790,6 +1790,177 @@ static LRESULT handle_nc_hit_test( HWND hwnd, POINT pt ) return HTNOWHERE; }
+static void track_min_max_box( HWND hwnd, WORD wparam ) +{ + HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ); + DWORD style = get_window_long( hwnd, GWL_STYLE ); + HMENU sys_menu = NtUserGetSystemMenu(hwnd, FALSE); + void (*paint_button)( HWND, HDC, BOOL, BOOL ); + BOOL pressed = TRUE; + UINT state; + MSG msg; + + if (wparam == HTMINBUTTON) + { + /* If the style is not present, do nothing */ + if (!(style & WS_MINIMIZEBOX)) return; + + /* Check if the sysmenu item for minimize is there */ + state = get_menu_state( sys_menu, SC_MINIMIZE, MF_BYCOMMAND ); + paint_button = draw_min_button; + } + else + { + /* If the style is not present, do nothing */ + if (!(style & WS_MAXIMIZEBOX)) return; + + /* Check if the sysmenu item for maximize is there */ + state = get_menu_state( sys_menu, SC_MAXIMIZE, MF_BYCOMMAND ); + paint_button = draw_max_button; + } + + NtUserSetCapture( hwnd ); + paint_button( hwnd, hdc, TRUE, FALSE); + + for (;;) + { + BOOL oldstate = pressed; + + if (!NtUserGetMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; + if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; + if(msg.message == WM_LBUTTONUP) break; + if(msg.message != WM_MOUSEMOVE) continue; + + pressed = handle_nc_hit_test( hwnd, msg.pt ) == wparam; + if (pressed != oldstate) paint_button( hwnd, hdc, pressed, FALSE); + } + + if (pressed) paint_button( hwnd, hdc, FALSE, FALSE ); + + release_capture(); + NtUserReleaseDC( hwnd, hdc ); + + /* If the minimize or maximize items of the sysmenu are not there + * or if the style is not present, do nothing */ + if (!pressed || state == 0xffffffff) return; + + if (wparam == HTMINBUTTON) + send_message( hwnd, WM_SYSCOMMAND, + is_iconic( hwnd ) ? SC_RESTORE : SC_MINIMIZE, MAKELONG( msg.pt.x, msg.pt.y )); + else + send_message( hwnd, WM_SYSCOMMAND, + is_zoomed( hwnd ) ? SC_RESTORE : SC_MAXIMIZE, MAKELONG( msg.pt.x, msg.pt.y )); +} + +static void track_close_button( HWND hwnd, WPARAM wparam, LPARAM lparam ) +{ + HMENU sys_menu; + BOOL pressed = TRUE; + UINT state; + MSG msg; + HDC hdc; + + if (!(sys_menu = NtUserGetSystemMenu( hwnd, FALSE ))) return; + + state = get_menu_state( sys_menu, SC_CLOSE, MF_BYCOMMAND ); + + /* If the close item of the sysmenu is disabled or not present do nothing */ + if((state & MF_DISABLED) || (state & MF_GRAYED) || state == 0xFFFFFFFF) return; + hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ); + NtUserSetCapture( hwnd ); + draw_close_button( hwnd, hdc, TRUE, FALSE ); + + for (;;) + { + BOOL oldstate = pressed; + + if (!NtUserGetMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; + if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; + if (msg.message == WM_LBUTTONUP) break; + if (msg.message != WM_MOUSEMOVE) continue; + + pressed = handle_nc_hit_test( hwnd, msg.pt ) == wparam; + if (pressed != oldstate) draw_close_button( hwnd, hdc, pressed, FALSE ); + } + + if (pressed) draw_close_button( hwnd, hdc, FALSE, FALSE ); + + release_capture(); + NtUserReleaseDC( hwnd, hdc ); + if (pressed) send_message( hwnd, WM_SYSCOMMAND, SC_CLOSE, lparam ); +} + +static LRESULT handle_nc_lbutton_down( HWND hwnd, WPARAM wparam, LPARAM lparam ) +{ + LONG style = get_window_long( hwnd, GWL_STYLE ); + + switch (wparam) /* Hit test */ + { + case HTCAPTION: + { + HWND top = hwnd, parent; + for (;;) + { + if ((get_window_long( top, GWL_STYLE ) & (WS_POPUP | WS_CHILD)) != WS_CHILD) + break; + parent = NtUserGetAncestor( top, GA_PARENT ); + if (!parent || parent == get_desktop_window()) break; + top = parent; + } + + if (set_foreground_window( top, TRUE ) || (get_active_window() == top)) + send_message( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lparam ); + break; + } + + case HTSYSMENU: + if (style & WS_SYSMENU) + { + HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ); + draw_nc_sys_button( hwnd, hdc, TRUE ); + NtUserReleaseDC( hwnd, hdc ); + send_message( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lparam ); + } + break; + + case HTMENU: + send_message( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lparam ); + break; + + case HTHSCROLL: + send_message( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lparam ); + break; + + case HTVSCROLL: + send_message( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lparam ); + break; + + case HTMINBUTTON: + case HTMAXBUTTON: + track_min_max_box( hwnd, wparam ); + break; + + case HTCLOSE: + track_close_button( hwnd, wparam, lparam ); + break; + + case HTLEFT: + case HTRIGHT: + case HTTOP: + case HTTOPLEFT: + case HTTOPRIGHT: + case HTBOTTOM: + case HTBOTTOMLEFT: + case HTBOTTOMRIGHT: + send_message( hwnd, WM_SYSCOMMAND, SC_SIZE + wparam - (HTLEFT - WMSZ_LEFT), lparam ); + break; + + case HTBORDER: + break; + } + return 0; +} + LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) { LRESULT result = 0; @@ -1835,6 +2006,9 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, case WM_NCACTIVATE: return handle_nc_activate( hwnd, wparam, lparam );
+ case WM_NCLBUTTONDOWN: + return handle_nc_lbutton_down( hwnd, wparam, lparam ); + case WM_WINDOWPOSCHANGING: return handle_window_pos_changing( hwnd, (WINDOWPOS *)lparam );
@@ -1886,7 +2060,7 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, if (result) break; }
- /* Caption clicks are handled by NC_HandleNCLButtonDown() */ + /* Caption clicks are handled by handle_nc_lbutton_down() */ result = HIWORD(lparam) == WM_LBUTTONDOWN && LOWORD(lparam) == HTCAPTION ? MA_NOACTIVATE : MA_ACTIVATE; break;
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/controls.h | 1 - dlls/user32/defwnd.c | 3 --- dlls/user32/nonclient.c | 34 ---------------------------------- dlls/win32u/defwnd.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index eec6a4babe2..d4e8ccd7b08 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -123,7 +123,6 @@ extern HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCMouseMove( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCMouseLeave( HWND hwnd ) DECLSPEC_HIDDEN; -extern LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam) DECLSPEC_HIDDEN; extern LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 0c783666b7e..a0d6ca44ecb 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -181,9 +181,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa case WM_NCLBUTTONDBLCLK: return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
- case WM_NCRBUTTONDOWN: - return NC_HandleNCRButtonDown( hwnd, wParam, lParam ); - case WM_RBUTTONUP: { POINT pt; diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 128f633fa33..174f6e46977 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -717,40 +717,6 @@ static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt ) }
-/*********************************************************************** - * NC_HandleNCRButtonDown - * - * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc(). - */ -LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) -{ - MSG msg; - INT hittest = wParam; - - switch (hittest) - { - case HTCAPTION: - case HTSYSMENU: - NtUserSetCapture( hwnd ); - for (;;) - { - if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; - if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; - if (msg.message == WM_RBUTTONUP) - { - hittest = NC_HandleNCHitTest( hwnd, msg.pt ); - break; - } - } - ReleaseCapture(); - if (hittest == HTCAPTION || hittest == HTSYSMENU) - SendMessageW( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELPARAM(msg.pt.x, msg.pt.y)); - break; - } - return 0; -} - - /*********************************************************************** * NC_HandleNCLButtonDblClk * diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 780570b5ad4..7126d492c78 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -1961,6 +1961,34 @@ static LRESULT handle_nc_lbutton_down( HWND hwnd, WPARAM wparam, LPARAM lparam ) return 0; }
+static LRESULT handle_nc_rbutton_down( HWND hwnd, WPARAM wparam, LPARAM lparam ) +{ + int hittest = wparam; + MSG msg; + + switch (hittest) + { + case HTCAPTION: + case HTSYSMENU: + NtUserSetCapture( hwnd ); + for (;;) + { + if (!NtUserGetMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break; + if (NtUserCallMsgFilter( &msg, MSGF_MAX )) continue; + if (msg.message == WM_RBUTTONUP) + { + hittest = handle_nc_hit_test( hwnd, msg.pt ); + break; + } + } + release_capture(); + if (hittest == HTCAPTION || hittest == HTSYSMENU) + send_message( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELPARAM( msg.pt.x, msg.pt.y )); + break; + } + return 0; +} + LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) { LRESULT result = 0; @@ -2009,6 +2037,9 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, case WM_NCLBUTTONDOWN: return handle_nc_lbutton_down( hwnd, wparam, lparam );
+ case WM_NCRBUTTONDOWN: + return handle_nc_rbutton_down( hwnd, wparam, lparam ); + case WM_WINDOWPOSCHANGING: return handle_window_pos_changing( hwnd, (WINDOWPOS *)lparam );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them if they are indeed new. Note that rare failures and failures with always changing text (e.g. because of memory addresses) can cause false positives. If this is what happened, then fixing those would really help.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117031
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
user32: win.c:11787: Test failed: 011D00CE: expected NOT topmost win.c:11606: Test succeeded inside todo block: 5: hwnd 00C00042 is still topmost
=== debian11 (64 bit WoW report) ===
user32: input.c:728: Test failed: 0 (a4/0): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 0 (a4/0): a4 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 0 (a4/0): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 1 (46/0): 46 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 1 (46/0): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 2 (46/2): 46 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 2 (46/2): the msg sequence is not complete: expected 0105 - actual 0000 input.c:728: Test failed: 3 (a4/2): 12 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 3 (a4/2): a4 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 3 (a4/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 4 (a2/0): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 4 (a2/0): a2 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 4 (a2/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 5 (4f/0): 4f from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 5 (4f/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 6 (4f/2): 4f from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 6 (4f/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 7 (a2/2): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 7 (a2/2): a2 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 7 (a2/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 8 (a4/0): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 8 (a4/0): a4 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 8 (a4/0): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 9 (a2/0): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 9 (a2/0): a2 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 9 (a2/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 10 (58/0): 58 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 10 (58/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 11 (58/2): 58 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 11 (58/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 12 (a2/2): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 12 (a2/2): a2 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 12 (a2/2): the msg sequence is not complete: expected 0105 - actual 0000 input.c:728: Test failed: 13 (a4/2): 12 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 13 (a4/2): a4 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 13 (a4/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 14 (a0/0): 10 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 14 (a0/0): a0 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 14 (a0/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 15 (41/0): 41 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 15 (41/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 16 (41/2): 41 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 16 (41/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 17 (a0/2): 10 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 17 (a0/2): a0 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 17 (a0/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 18 (a1/0): 10 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 18 (a1/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 19 (a1/2): 10 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 19 (a1/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 20 (a0/1): 10 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 20 (a0/1): a1 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 20 (a0/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 21 (a0/3): 10 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 21 (a0/3): a1 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 21 (a0/3): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 22 (a1/1): 10 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 22 (a1/1): a1 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 22 (a1/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 23 (a1/3): 10 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 23 (a1/3): a1 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 23 (a1/3): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 24 (10/0): 10 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 24 (10/0): a0 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 24 (10/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 25 (10/2): 10 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 25 (10/2): a0 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 25 (10/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 26 (10/1): 10 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 26 (10/1): a1 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 26 (10/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 27 (10/3): 10 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 27 (10/3): a1 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 27 (10/3): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 28 (a3/0): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 28 (a3/0): a2 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 28 (a3/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 29 (a3/2): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 29 (a3/2): a2 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 29 (a3/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 30 (a2/1): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 30 (a2/1): a3 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 30 (a2/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 31 (a2/3): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 31 (a2/3): a3 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 31 (a2/3): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 32 (a3/1): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 32 (a3/1): a3 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 32 (a3/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 33 (a3/3): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 33 (a3/3): a3 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 33 (a3/3): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 34 (11/0): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 34 (11/0): a2 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 34 (11/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 35 (11/2): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 35 (11/2): a2 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 35 (11/2): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 36 (11/1): 11 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 36 (11/1): a3 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 36 (11/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 37 (11/3): 11 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 37 (11/3): a3 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 37 (11/3): the msg sequence is not complete: expected 0101 - actual 0000 input.c:728: Test failed: 38 (a5/0): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 38 (a5/0): a4 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 38 (a5/0): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 40 (a4/1): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 40 (a4/1): a5 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 40 (a4/1): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 42 (a5/1): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 42 (a5/1): a5 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 42 (a5/1): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 44 (12/0): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 44 (12/0): a4 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 44 (12/0): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 46 (12/1): 12 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 46 (12/1): a5 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 46 (12/1): the msg sequence is not complete: expected 0104 - actual 0000 input.c:728: Test failed: 48 (a0/0): 10 from 00 -> 00 instead of 00 -> 80 input.c:728: Test failed: 48 (a0/0): a0 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 48 (a0/0): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 49 (a1/1): a1 from 00 -> 00 instead of 00 -> 80 input.c:854: Test failed: 49 (a1/1): the msg sequence is not complete: expected 0100 - actual 0000 input.c:728: Test failed: 50 (a1/3): a1 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 51 (a0/2): 10 from 00 -> 00 instead of 80 -> 00 input.c:728: Test failed: 51 (a0/2): a0 from 00 -> 00 instead of 80 -> 00 input.c:854: Test failed: 51 (a0/2): the msg sequence is not complete: expected 0101 - actual 0000
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/focus.c | 2 +- dlls/win32u/window.c | 6 +++--- dlls/winemac.drv/window.c | 8 ++++---- dlls/winex11.drv/event.c | 6 +++--- include/ntuser.h | 12 ++++++------ 5 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index 7e1536ab802..bf80777ca97 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -37,7 +37,7 @@ */ BOOL WINAPI SetForegroundWindow( HWND hwnd ) { - return NtUserSetForegroundWindow( hwnd, FALSE ); + return NtUserSetForegroundWindow( hwnd ); }
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 431686bdcaa..42274905d5b 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5403,6 +5403,9 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ) case NtUserCallHwnd_IsWindowVisible: return is_window_visible( hwnd );
+ case NtUserCallHwnd_SetForegroundWindow: + return set_foreground_window( hwnd, FALSE ); + default: FIXME( "invalid code %u\n", code ); return 0; @@ -5489,9 +5492,6 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_ScreenToClient: return screen_to_client( hwnd, (POINT *)param );
- case NtUserCallHwndParam_SetForegroundWindow: - return set_foreground_window( hwnd, param ); - case NtUserCallHwndParam_SetWindowContextHelpId: return set_window_context_help_id( hwnd, param );
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 9d778f427b0..22c250c1d18 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -2350,7 +2350,7 @@ void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event) if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) { TRACE("setting foreground window to %p\n", hwnd); - NtUserSetForegroundWindow(hwnd, FALSE); + NtUserSetForegroundWindow(hwnd); return; } } @@ -2375,7 +2375,7 @@ void macdrv_window_lost_focus(HWND hwnd, const macdrv_event *event) { send_message(hwnd, WM_CANCELMODE, 0, 0); if (hwnd == NtUserGetForegroundWindow()) - NtUserSetForegroundWindow(NtUserGetDesktopWindow(), FALSE); + NtUserSetForegroundWindow(NtUserGetDesktopWindow()); } }
@@ -2404,7 +2404,7 @@ void macdrv_app_deactivated(void) if (get_active_window() == NtUserGetForegroundWindow()) { TRACE("setting fg to desktop\n"); - NtUserSetForegroundWindow(NtUserGetDesktopWindow(), FALSE); + NtUserSetForegroundWindow(NtUserGetDesktopWindow()); } }
@@ -2573,7 +2573,7 @@ void macdrv_window_drag_begin(HWND hwnd, const macdrv_event *event) if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) { TRACE("setting foreground window to %p\n", hwnd); - NtUserSetForegroundWindow(hwnd, FALSE); + NtUserSetForegroundWindow(hwnd); } }
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index f81d2338faf..cbfb228ea09 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -596,7 +596,7 @@ static void set_focus( Display *display, HWND hwnd, Time time ) GUITHREADINFO threadinfo;
TRACE( "setting foreground window to %p\n", hwnd ); - NtUserSetForegroundWindow( hwnd, FALSE ); + NtUserSetForegroundWindow( hwnd );
threadinfo.cbSize = sizeof(threadinfo); NtUserGetGUIThreadInfo( 0, &threadinfo ); @@ -812,7 +812,7 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) if (!hwnd) hwnd = x11drv_thread_data()->last_focus; if (hwnd && can_activate_window(hwnd)) set_focus( event->display, hwnd, CurrentTime ); } - else NtUserSetForegroundWindow( hwnd, FALSE ); + else NtUserSetForegroundWindow( hwnd ); return TRUE; }
@@ -858,7 +858,7 @@ static void focus_out( Display *display , HWND hwnd ) if (hwnd == NtUserGetForegroundWindow()) { TRACE( "lost focus, setting fg to desktop\n" ); - NtUserSetForegroundWindow( NtUserGetDesktopWindow(), FALSE ); + NtUserSetForegroundWindow( NtUserGetDesktopWindow() ); } } } diff --git a/include/ntuser.h b/include/ntuser.h index 1f3cc2f2e7e..0904aadff0f 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -983,6 +983,7 @@ enum NtUserCallHwnd_IsWindowEnabled, NtUserCallHwnd_IsWindowUnicode, NtUserCallHwnd_IsWindowVisible, + NtUserCallHwnd_SetForegroundWindow, };
static inline UINT NtUserArrangeIconicWindows( HWND parent ) @@ -1041,6 +1042,11 @@ static inline BOOL NtUserIsWindowVisible( HWND hwnd ) return NtUserCallHwnd( hwnd, NtUserCallHwnd_IsWindowVisible ); }
+static inline BOOL NtUserSetForegroundWindow( HWND hwnd ) +{ + return NtUserCallHwnd( hwnd, NtUserCallHwnd_SetForegroundWindow ); +} + /* NtUserCallHwndParam codes, not compatible with Windows */ enum { @@ -1067,7 +1073,6 @@ enum NtUserCallHwndParam_MirrorRgn, NtUserCallHwndParam_MonitorFromWindow, NtUserCallHwndParam_ScreenToClient, - NtUserCallHwndParam_SetForegroundWindow, NtUserCallHwndParam_SetWindowContextHelpId, NtUserCallHwndParam_SetWindowPixelFormat, NtUserCallHwndParam_ShowOwnedPopups, @@ -1207,11 +1212,6 @@ static inline BOOL NtUserScreenToClient( HWND hwnd, POINT *pt ) return NtUserCallHwndParam( hwnd, (UINT_PTR)pt, NtUserCallHwndParam_ScreenToClient ); }
-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 );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them if they are indeed new. Note that rare failures and failures with always changing text (e.g. because of memory addresses) can cause false positives. If this is what happened, then fixing those would really help.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117032
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
user32: menu.c:2324: Test failed: test 25
This merge request was approved by Huw Davies.