[PATCH 0/1] MR1580: winex11.drv: Hide invisible owner windows that have visible owned windows in pager.
Manual tests on XP, Win7 and Win10 show that such windows are not shown in pager. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1580
From: Zhiyi Zhang <zzhang(a)codeweavers.com> Manual tests on XP, Win7 and Win10 show that such windows are not shown in pager. --- dlls/win32u/sysparams.c | 35 +++++++++++++++++++++++++++++++++++ dlls/winex11.drv/window.c | 23 +++++++++++++++++++++++ include/ntuser.h | 6 ++++++ 3 files changed, 64 insertions(+) diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d02ff16a2c0..05e477797fd 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1914,6 +1914,38 @@ static BOOL is_window_rect_full_screen( const RECT *rect ) return ret; } +static BOOL has_visible_owned_window( HWND owner ) +{ + BOOL ret = FALSE; + UINT i, dpi; + DWORD style; + HWND *list; + RECT rect; + + if (!(list = list_window_children( 0, get_desktop_window(), NULL, 0 ))) + return FALSE; + + dpi = get_thread_dpi(); + for (i = 0; list[i]; i++) + { + if (NtUserGetWindowRelative( list[i], GW_OWNER ) != owner) + continue; + + style = get_window_long( list[i], GWL_STYLE ); + if (!(style & WS_VISIBLE)) + continue; + + get_window_rect( list[i], &rect, dpi ); + if (!IsRectEmpty( &rect )) + { + ret = TRUE; + break; + } + } + free( list ); + return ret; +} + RECT get_display_rect( const WCHAR *display ) { struct monitor *monitor; @@ -5496,6 +5528,9 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code ) case NtUserCallOneParam_GetSysColor: return get_sys_color( arg ); + case NtUserCallOneParam_HasVisibleOwnedWindow: + return has_visible_owned_window( UlongToHandle(arg) ); + case NtUserCallOneParam_IsWindowRectFullScreen: return is_window_rect_full_screen( (const RECT *)arg ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 603314ff3bb..39dcfd3b95a 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1011,12 +1011,22 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) } } +static BOOL is_invisible_owner_window( const struct x11drv_win_data *data, UINT style ) +{ + if ((style & WS_VISIBLE) && !IsRectEmpty( &data->whole_rect )) + return FALSE; + + return NtUserHasVisibleOwnedWindow( data->hwnd ); +} + /*********************************************************************** * update_net_wm_states */ void update_net_wm_states( struct x11drv_win_data *data ) { UINT i, style, ex_style, new_state = 0; + struct x11drv_win_data *owner_data; + HWND owner; if (!data->managed) return; if (data->whole_window == root_window) return; @@ -1046,6 +1056,19 @@ void update_net_wm_states( struct x11drv_win_data *data ) new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR); } + /* If this window has no WS_EX_APPWINDOW and is invisible and has a visible owned window, then + * such a window should not be shown in pager and KDE switcher */ + if (!(ex_style & WS_EX_APPWINDOW) && is_invisible_owner_window( data, style )) + new_state |= (1 << NET_WM_STATE_SKIP_PAGER) | (1 << KDE_NET_WM_STATE_SKIP_SWITCHER); + + /* Update owner as well because a window may be newly owned */ + owner = NtUserGetWindowRelative( data->hwnd, GW_OWNER ); + if (owner && owner != data->hwnd && (owner_data = get_win_data( owner ))) + { + update_net_wm_states( owner_data ); + release_win_data( owner_data ); + } + if (!data->mapped) /* set the _NET_WM_STATE atom directly */ { Atom atoms[NB_NET_WM_STATES+1]; diff --git a/include/ntuser.h b/include/ntuser.h index 5331b3d7400..6e523871702 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -958,6 +958,7 @@ enum NtUserCallOneParam_GetSysColorPen, NtUserCallOneParam_GetSystemMetrics, NtUserCallOneParam_GetVirtualScreenRect, + NtUserCallOneParam_HasVisibleOwnedWindow, NtUserCallOneParam_IsWindowRectFullScreen, NtUserCallOneParam_MessageBeep, NtUserCallOneParam_RealizePalette, @@ -1057,6 +1058,11 @@ static inline RECT NtUserGetVirtualScreenRect(void) return virtual; } +static inline BOOL NtUserHasVisibleOwnedWindow( HWND owner ) +{ + return NtUserCallOneParam( HandleToUlong(owner), NtUserCallOneParam_HasVisibleOwnedWindow ); +} + static inline BOOL NtUserIsWindowRectFullScreen( const RECT *rect ) { return NtUserCallOneParam( (UINT_PTR)rect, NtUserCallOneParam_IsWindowRectFullScreen ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/1580
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126893 Your paranoid android. === debian11 (build log) === ../wine/dlls/winex11.drv/window.c:1061:61: error: ���KDE_NET_WM_STATE_SKIP_SWITCHER��� undeclared (first use in this function); did you mean ���NET_WM_STATE_SKIP_PAGER���? Task: The win32 Wine build failed === debian11b (build log) === ../wine/dlls/winex11.drv/window.c:1061:61: error: ���KDE_NET_WM_STATE_SKIP_SWITCHER��� undeclared (first use in this function); did you mean ���NET_WM_STATE_SKIP_PAGER���? Task: The wow64 Wine build failed
This causes the China Mobile Cloud app to jump a bit on KWin when clicking its caption. I will look at the jumping issue later. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1580#note_25703
participants (3)
-
Marvin -
Zhiyi Zhang -
Zhiyi Zhang (@zhiyi)