From a9a980a71b4bc3961a5310f983a9cca2b12b21d8 Mon Sep 17 00:00:00 2001 From: Lauri Nurmi Date: Fri, 10 Feb 2017 13:44:23 +0200 Subject: [PATCH 1/4] Set proper level for modal dialogs of float-on-parent frames on wxOSX This prevents the dialog from getting hidden behind its parent after task switching the application into background and back to front. Related to #4355, but not a fix. --- src/osx/cocoa/nonownedwnd.mm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index bba75c0afc..6f12bed1ad 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -812,8 +812,16 @@ bool wxNonOwnedWindowCocoaImpl::Show(bool show) if ( parentView ) { NSWindow* parentNSWindow = [parentView window]; - if ( parentNSWindow ) + if ( parentNSWindow ) { [parentNSWindow addChildWindow:m_macWindow ordered:NSWindowAbove]; + // If the parent is modal, windows with wxFRAME_FLOAT_ON_PARENT style need + // to be in kCGUtilityWindowLevel and not kCGFloatingWindowLevel to stay + // above the parent. + if ([m_macWindow level] == kCGFloatingWindowLevel) { + m_macWindowLevel = kCGUtilityWindowLevel; + [m_macWindow setLevel:m_macWindowLevel]; + } + } } } From 246fa6aa98bcb8d15fd952ed49a279e24354f12b Mon Sep 17 00:00:00 2001 From: Lauri Nurmi Date: Fri, 10 Feb 2017 21:54:22 +0200 Subject: [PATCH 2/4] Use a lower level for wxSTAY_ON_TOP frames in wxOSX Use NSModalPanelWindowLevel instead of kCGUtilityWindowLevel. This prevents dialogs parented to stay-on-top frames from ending up behind their parent. --- src/osx/cocoa/nonownedwnd.mm | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index 6f12bed1ad..a3c1faba5e 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -709,10 +709,10 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) windowstyle |= NSTexturedBackgroundWindowMask; if ( ( style & wxFRAME_FLOAT_ON_PARENT ) || ( style & wxFRAME_TOOL_WINDOW ) ) - level = kCGFloatingWindowLevel; + level = NSFloatingWindowLevel; if ( ( style & wxSTAY_ON_TOP ) ) - level = kCGUtilityWindowLevel; + level = NSModalPanelWindowLevel; NSRect r = wxToNSRect( NULL, wxRect( pos, size) ); @@ -734,20 +734,20 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) } // If the parent is modal, windows with wxFRAME_FLOAT_ON_PARENT style need - // to be in kCGUtilityWindowLevel and not kCGFloatingWindowLevel to stay + // to be in NSModalPanelWindowLevel and not NSFloatingWindowLevel to stay // above the parent. wxDialog * const parentDialog = parent == NULL ? NULL : wxDynamicCast(parent->MacGetTopLevelWindow(), wxDialog); if (parentDialog && parentDialog->IsModal()) { - if (level == kCGFloatingWindowLevel) + if (level == NSFloatingWindowLevel) { - level = kCGUtilityWindowLevel; + level = NSModalPanelWindowLevel; } // Cocoa's modal loop does not process other windows by default, but // don't call this on normal window levels so nested modal dialogs will // still behave modally. - if (level != kCGNormalWindowLevel) + if (level != NSNormalWindowLevel) { if ([m_macWindow isKindOfClass:[NSPanel class]]) { @@ -815,10 +815,11 @@ bool wxNonOwnedWindowCocoaImpl::Show(bool show) if ( parentNSWindow ) { [parentNSWindow addChildWindow:m_macWindow ordered:NSWindowAbove]; // If the parent is modal, windows with wxFRAME_FLOAT_ON_PARENT style need - // to be in kCGUtilityWindowLevel and not kCGFloatingWindowLevel to stay + // to be in NSModalPanelWindowLevel and not NSFloatingWindowLevel to stay // above the parent. - if ([m_macWindow level] == kCGFloatingWindowLevel) { - m_macWindowLevel = kCGUtilityWindowLevel; + if ([m_macWindow level] == NSFloatingWindowLevel || + [m_macWindow level] == NSModalPanelWindowLevel) { + m_macWindowLevel = NSModalPanelWindowLevel; [m_macWindow setLevel:m_macWindowLevel]; } } @@ -892,9 +893,9 @@ void wxNonOwnedWindowCocoaImpl::SetWindowStyleFlag( long style ) CGWindowLevel level = kCGNormalWindowLevel; if (style & wxSTAY_ON_TOP) - level = kCGUtilityWindowLevel; + level = NSModalPanelWindowLevel; else if (( style & wxFRAME_FLOAT_ON_PARENT ) || ( style & wxFRAME_TOOL_WINDOW )) - level = kCGFloatingWindowLevel; + level = NSFloatingWindowLevel; [m_macWindow setLevel: level]; m_macWindowLevel = level; From 2e2881f4de2ec655836450a35a4ea8c134d3c6cf Mon Sep 17 00:00:00 2001 From: Lauri Nurmi Date: Fri, 10 Feb 2017 21:54:22 +0200 Subject: [PATCH 3/4] Use NS* window levels rather than kCG* The NS* names are available since OS X 10.0. --- src/osx/cocoa/nonownedwnd.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index a3c1faba5e..5557331347 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -671,7 +671,7 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) [m_macWindow setAcceptsMouseMovedEvents:YES]; - CGWindowLevel level = kCGNormalWindowLevel; + NSInteger level = NSNormalWindowLevel; if ( style & wxFRAME_TOOL_WINDOW ) { @@ -679,7 +679,7 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) } else if ( ( style & wxPOPUP_WINDOW ) ) { - level = kCGPopUpMenuWindowLevel; + level = NSPopUpMenuWindowLevel; } else if ( ( style & wxFRAME_DRAWER ) ) { @@ -890,7 +890,7 @@ void wxNonOwnedWindowCocoaImpl::SetWindowStyleFlag( long style ) // don't mess with native wrapped windows, they might throw an exception when their level is changed if (!m_wxPeer->IsNativeWindowWrapper() && m_macWindow) { - CGWindowLevel level = kCGNormalWindowLevel; + NSInteger level = NSNormalWindowLevel; if (style & wxSTAY_ON_TOP) level = NSModalPanelWindowLevel; From e36aa6475219d3e2fbbbdd97eb46429bd8851880 Mon Sep 17 00:00:00 2001 From: Lauri Nurmi Date: Fri, 10 Feb 2017 23:06:08 +0200 Subject: [PATCH 4/4] Set proper level also for non-modal dialogs in wxOSX Fixes #4355 --- src/osx/cocoa/nonownedwnd.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index 5557331347..b722a7e042 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -806,7 +806,7 @@ bool wxNonOwnedWindowCocoaImpl::Show(bool show) { // add to parent window before showing wxDialog * const dialog = wxDynamicCast(wxpeer, wxDialog); - if ( wxpeer->GetParent() && dialog && dialog->IsModal()) + if ( wxpeer->GetParent() && dialog ) { NSView * parentView = wxpeer->GetParent()->GetPeer()->GetWXWidget(); if ( parentView )