From 5d87c70eba739dd1478ffa819a7bebefeecdfee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Fri, 6 Jan 2017 16:45:35 +0100 Subject: [PATCH] Mimic native focus handling in wxStatusBar on macOS Improve the logic for determining whether the statusbar should be renderer as for active/key window or a background one. wxTopLevelWindow::IsActive() is not a sufficient test because it returns false in some situations when the statusbar need to appear as active (another floating window) and also didn't account for window-modal sheets (which don't change statusbar appearance either). --- include/wx/osx/cocoa/private.h | 1 + src/osx/carbon/statbrma.cpp | 19 ++++++++++++++++++- src/osx/carbon/utilscocoa.mm | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index 8c6553e5ac..c2611295ab 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -40,6 +40,7 @@ CGContextRef WXDLLIMPEXP_CORE wxOSXCreateBitmapContextFromNSImage( WX_NSImage ns wxBitmap WXDLLIMPEXP_CORE wxOSXCreateSystemBitmap(const wxString& id, const wxString &client, const wxSize& size); WXWindow WXDLLIMPEXP_CORE wxOSXGetMainWindow(); +WXWindow WXDLLIMPEXP_CORE wxOSXGetKeyWindow(); class WXDLLIMPEXP_FWD_CORE wxDialog; diff --git a/src/osx/carbon/statbrma.cpp b/src/osx/carbon/statbrma.cpp index 8cd90d1b67..506e8a1671 100644 --- a/src/osx/carbon/statbrma.cpp +++ b/src/osx/carbon/statbrma.cpp @@ -18,6 +18,7 @@ #ifndef WX_PRECOMP #include "wx/dc.h" #include "wx/dcclient.h" + #include "wx/dialog.h" #include "wx/toplevel.h" #endif @@ -147,8 +148,24 @@ void wxStatusBarMac::OnPaint(wxPaintEvent& WXUNUSED(event)) int w, h; GetSize( &w, &h ); + // Notice that wxOSXGetKeyWindow (aka [NSApp keyWindow] used below is + // subtly different from IsActive() (aka [NSWindow iskeyWindow]): the + // former remains non-NULL if another application shows a temporary + // floating window or a status icon's menu is used. That's what we want: in + // that case, statusbar appearance shouldn't change. It also shouldn't + // change if a window-modal sheet attached to this window is key. wxTopLevelWindow *tlw = wxDynamicCast(MacGetTopLevelWindow(), wxTopLevelWindow); - if ( tlw && tlw->IsActive() ) + wxWindow *keyWindow = wxNonOwnedWindow::GetFromWXWindow(wxOSXGetKeyWindow())->MacGetTopLevelWindow(); + while ( keyWindow && keyWindow != tlw ) + { + wxDialog *dlg = wxDynamicCast(keyWindow, wxDialog); + if ( dlg && dlg->GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL ) + keyWindow = dlg->GetParent(); + else + break; + } + + if ( tlw == keyWindow ) { dc.GradientFillLinear(dc.GetSize(), m_bgActiveFrom, m_bgActiveTo, wxBOTTOM); diff --git a/src/osx/carbon/utilscocoa.mm b/src/osx/carbon/utilscocoa.mm index 34b3003a23..c3f2c11501 100644 --- a/src/osx/carbon/utilscocoa.mm +++ b/src/osx/carbon/utilscocoa.mm @@ -345,6 +345,11 @@ WXWindow wxOSXGetMainWindow() return [NSApp mainWindow]; } +WXWindow wxOSXGetKeyWindow() +{ + return [NSApp keyWindow]; +} + #endif // ---------------------------------------------------------------------------- // NSImage Utils