diff --git a/include/win.h b/include/win.h index 5e8e31f1a57..fcf7eeacd75 100644 --- a/include/win.h +++ b/include/win.h @@ -157,6 +157,7 @@ typedef struct #define WIN_ISDIALOG 0x0200 /* Window is a dialog */ #define WIN_ISWIN32 0x0400 /* Understands Win32 messages */ #define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0800 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */ +#define WIN_NEEDS_INTERNALSOP 0x1000 /* Window was hidden by WIN_InternalShowOwnedPopups */ /* BuildWinArray() flags */ #define BWA_SKIPDISABLED 0x0001 @@ -196,6 +197,7 @@ extern WND* WIN_GetTopParentPtr( WND* pWnd ); extern BOOL WIN_IsWindowDrawable(WND*, BOOL ); extern WND** WIN_BuildWinArray( WND *wndPtr, UINT bwa, UINT* pnum ); extern void WIN_ReleaseWinArray(WND **wndArray); +extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly ); extern HICON16 NC_IconForWindow( WND *wndPtr ); diff --git a/windows/win.c b/windows/win.c index 74c8f37bfde..f7103d6bc72 100644 --- a/windows/win.c +++ b/windows/win.c @@ -2633,6 +2633,66 @@ HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag ) return GetWindow16( hwnd, flag ); } +/*********************************************************************** + * WIN_InternalShowOwnedPopups + * + * Internal version of ShowOwnedPopups; Wine functions should use this + * to avoid interfering with application calls to ShowOwnedPopups + * and to make sure the application can't prevent showing/hiding. + * + * Set unmanagedOnly to TRUE to show/hide unmanaged windows only. + * + */ + +BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly ) +{ + INT totalChild=0, count=0; + + WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild); + + if (!pWnd) return TRUE; + + /* + * Show windows Lowest first, Highest last to preserve Z-Order + */ + for (count = totalChild-1 ; count >=0; count--) + { + if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP)) + { + if (fShow) + { + /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */ + if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP) + { + /* + * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages + */ + ShowWindow(pWnd[count]->hwndSelf,SW_SHOW); + pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */ + } + } + else + { + if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */ + !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */ + !( unmanagedOnly && (pWnd[count]->flags & WIN_MANAGED ) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */ + { + /* + * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages + */ + ShowWindow(pWnd[count]->hwndSelf,SW_HIDE); + /* flag the window for showing on next WIN_InternalShowOwnedPopups call */ + pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP; + } + } + } + } + WIN_ReleaseDesktop(); + WIN_ReleaseWinArray(pWnd); + + return TRUE; +} + /******************************************************************* * ShowOwnedPopups16 (USER.265) */ @@ -2661,7 +2721,11 @@ BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow ) { if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP) { - SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING); + /* + * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING, + * regardless of the state of the owner + */ + SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING); pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP; } } @@ -2669,7 +2733,11 @@ BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow ) { if (IsWindowVisible(pWnd[count]->hwndSelf)) { - SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING); + /* + * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING, + * regardless of the state of the owner + */ + SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING); pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP; } } diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c index 01f9321e7da..bfd9cffad61 100644 --- a/windows/x11drv/event.c +++ b/windows/x11drv/event.c @@ -1854,12 +1854,12 @@ void EVENT_MapNotify( HWND hWnd, XMapEvent *event ) HWND hwndFocus = GetFocus(); WND *wndFocus = WIN_FindWndPtr(hwndFocus); WND *pWnd = WIN_FindWndPtr(hWnd); - if (pWnd->flags & WIN_MANAGED) + if (pWnd && (pWnd->flags & WIN_MANAGED)) { DCE_InvalidateDCE( pWnd, &pWnd->rectWindow ); pWnd->dwStyle &= ~WS_MINIMIZE; pWnd->dwStyle |= WS_VISIBLE; - ShowOwnedPopups(hWnd,TRUE); + WIN_InternalShowOwnedPopups(hWnd,TRUE,TRUE); } WIN_ReleaseWndPtr(pWnd); @@ -1873,7 +1873,7 @@ void EVENT_MapNotify( HWND hWnd, XMapEvent *event ) /********************************************************************** - * EVENT_MapNotify + * EVENT_UnmapNotify */ void EVENT_UnmapNotify( HWND hWnd, XUnmapEvent *event ) { @@ -1885,7 +1885,7 @@ void EVENT_UnmapNotify( HWND hWnd, XUnmapEvent *event ) { pWnd->dwStyle |= WS_MINIMIZE; pWnd->dwStyle &= ~WS_VISIBLE; - ShowOwnedPopups(hWnd,FALSE); + WIN_InternalShowOwnedPopups(hWnd,FALSE,TRUE); } } WIN_ReleaseWndPtr(pWnd);