Opened 2 months ago

Last modified 2 months ago

#19129 confirmed defect

Mac: Floating panes appear on top of all frame windows, not just their parent

Reported by: tonyvsuk Owned by:
Priority: low Milestone:
Component: wxOSX Version: 3.1.4
Keywords: Cc:
Blocked By: Blocking:
Patch: no

Description

Posting here after a quick discussion on the Google wx group. Vadim Zeitlin said to post here as well with some code to reproduce the error. I've attached a patch to samples/aui/auidemo.cpp that re-creates the problem. The patch is simple, it creates two "MyFrame" windows and starts with the tree pane undocked (this 2nd step is not necessary, I only did it to save having to manually undock the tree pane to demonstrate the problem).

Running 3.1.4 wxWidgets, MacOS 11.2.3 (Big Sur) on Apple Silicon.

I've got an application where each workspace window has a number of floating panes (all managed by a wxAuiManager).

The problem is that if I have two windows open on the Mac, each with a floating pane, the floating panes appear on top of all other windows. It's as if the floating panes have the wxSTAY_ON_TOP style, but they should only stay on top of their parent window (not other wxFrame windows).

All works fine on Windows, a pane floats on top of it's own parent only.

Thanks in advance,

Tony.

diff --git a/samples/aui/auidemo.cpp b/samples/aui/auidemo.cpp
index 008a26427a..3ff5330842 100644
--- a/samples/aui/auidemo.cpp
+++ b/samples/aui/auidemo.cpp
@@ -35,7 +35,7 @@
 #include "wx/textdlg.h"
 
 #include "wx/aui/aui.h"
-#include "../sample.xpm"
+//#include "../sample.xpm"
 
 // -- application --
 
@@ -564,12 +564,19 @@ bool MyApp::OnInit()
     if ( !wxApp::OnInit() )
         return false;
 
-    wxFrame* frame = new MyFrame(NULL,
-                                 wxID_ANY,
-                                 "wxAUI Sample Application",
-                                 wxDefaultPosition,
+    wxFrame* frame1 = new MyFrame(NULL,
+                                 1,
+                                 "wxAUI Sample Application First window",
+                                 wxPoint(20,20),
                                  wxWindow::FromDIP(wxSize(800, 600), NULL));
-    frame->Show();
+    frame1->Show();
+
+    wxFrame* frame2 = new MyFrame(NULL,
+                                 2,
+                                 "wxAUI Sample Application second window",
+                                  wxPoint(400,20),
+                                 wxWindow::FromDIP(wxSize(800, 600), NULL));
+    frame2->Show();
 
     return true;
 }
@@ -669,7 +676,7 @@ MyFrame::MyFrame(wxWindow* parent,
     m_mgr.SetManagedWindow(this);
 
     // set frame icon
-    SetIcon(wxIcon(sample_xpm));
+//    SetIcon(wxIcon(sample_xpm));
 
     // set up default notebook style
     m_notebook_style = wxAUI_NB_DEFAULT_STYLE | wxAUI_NB_TAB_EXTERNAL_MOVE | wxNO_BORDER;
@@ -909,8 +916,9 @@ MyFrame::MyFrame(wxWindow* parent,
                   Left().Layer(1).
                   CloseButton(true).MaximizeButton(true));
 
+    wxString strLabel = wxString::Format("Tree Pane from parent %d", id);
     m_mgr.AddPane(CreateTreeCtrl(), wxAuiPaneInfo().
-                  Name("test8").Caption("Tree Pane").
+                  Name("test8").Caption(strLabel).Float().
                   Left().Layer(1).Position(1).
                   CloseButton(true).MaximizeButton(true));
 
@@ -1589,7 +1597,7 @@ wxTreeCtrl* MyFrame::CreateTreeCtrl()
 {
     wxTreeCtrl* tree = new wxTreeCtrl(this, wxID_ANY,
                                       wxPoint(0,0),
-                                      FromDIP(wxSize(160,250)),
+                                      FromDIP(wxSize(300,250)),
                                       wxTR_DEFAULT_STYLE | wxNO_BORDER);
 
     wxSize size = FromDIP(wxSize(16, 16));

Attachments (1)

auibug.patch download (2.4 KB) - added by tonyvsuk 2 months ago.

Download all attachments as: .zip

Change History (8)

Changed 2 months ago by tonyvsuk

comment:1 Changed 2 months ago by vadz

  • Component changed from wxAui to wxOSX
  • Priority changed from normal to low
  • Status changed from new to confirmed
  • Summary changed from wxAui problem on the Mac (floating panes appear on top of frame windows that do not own them). to Mac: Floating panes appear on top of all frame windows, not just their parent

Sorry, after looking at the code, I don't think it's going to be easy to fix this. The problem is that macOS provides only window levels for the windows and we can either use NSFloatingWindowLevel for the floating panes, as we do now, or not (i.e. use the default NSNormalWindowLevel). In the former case, the pane will always be above any normal windows because this is how the levels work, so we'd have to avoid doing this and instead manually maintain the pane above its parent. This is probably doable, but I don't know how exactly, i.e. which event should we use to ensure that we always raise the child pane above its parent.

I also suspect that it might be not such a great idea to do it in the first place under Mac, i.e. if the native window levels work like this, users would probably expect our windows to work like this too.

comment:2 Changed 2 months ago by tonyvsuk

  • Cc tony@… added

Don't know if it helps, dialog boxes behave the way I'd expect them to (they only float on top of their parent). It's just wxMiniframe that float on top of everything. When trying to figure out what was going wrong, I'm sure a wxMiniFrame is created to hold the floating AUI pane.

Is there a way of finding the floating levels for wxDialog and wxMiniFrames?

I'm thinking maybe wxMiniframe is assigned NSFloatingWindowLevel and wxDialog maybe gets NSPopUpMenuWindowLevel?

comment:3 Changed 2 months ago by tonyvsuk

  • Cc tony@… removed

I also suspect that it might be not such a great idea to do it in the first
place under Mac, i.e. if the native window levels work like this, users

would probably expect our windows to work like this too.

I completely agree.

My use case is that each window is a "workspace" so the docked windows only apply to that workspace. This workspace has a project file explorer, so it has to be tied to the parent window (if it appears on top of the incorrect workspace, users would be easily confused).

I also see that you might have a floating window that applies to all workspaces. So there is definitely room to have two modes, a floating window that really is "float on all", and something like a workspace floating window.

comment:4 Changed 2 months ago by vadz

AFAIU NSPopUpMenuWindowLevel is an even higher level and would be on top of other NSFloatingWindowLevel windows that are already on top of all the other ones.

But it's true that modeless dialogs do already behave like you'd like them to, so maybe we could just use NSNormalWindowLevel for the AUI frames (and wxMiniFrame?) when they have a parent?

comment:5 Changed 2 months ago by vadz

FWIW wxMiniFrame under Mac is definitely inconsistent with the other ports: in GTK and MSW it only stays on top of its parent, not on top of all the other windows, as under Mac. This can be easily seen with

  • samples/dialogs/dialogs.cpp

    diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp
    index a7ed02b5f5..6d0fb2d0be 100644
    a b bool MyApp::OnInit() 
    404404
    405405    // Create the main frame window
    406406    MyFrame *frame = new MyFrame("wxWidgets dialogs example");
     407    auto f = new MyFrame("Another");
     408    f->Show();
    407409
    408410    // Make a menubar
    409411    wxMenu *menuDlg = new wxMenu;

and using menu item to create a mini frame.

Stefan, is there some other reason to use NSFloatingWindowLevel than Z-order-related ones? Because it looks like wxFRAME_FLOAT_ON_PARENT works even without it.

comment:6 Changed 2 months ago by tonyvsuk

  • Cc tony@… added

The only example I can find on OSX is Microsoft Excel. If you have two spreadsheets open and insert a formula in one, you get a docked formula editor. If you undock this and click on the other spreadsheet, the formula box stays with it's parent.

Another difference here is that the undocked window does not look like a wxMiniFrame, it looks like a dialog (it has the three buttons top left of the window to close, minimise and maximise). Maybe wxMiniFrame on OSX should also look like this?

PS. I'm happy to experiment here (if I knew where to change things).

Last edited 2 months ago by tonyvsuk (previous) (diff)

comment:7 Changed 2 months ago by tonyvsuk

  • Cc tony@… removed

Some more info on this as I've been experimenting.

If I make the following two changes, I get pretty much what I need (the floating panes become dialogs instead). I know this doesn't fix the problem, but it makes my app work in a similar way to the Windows version and stops any confusion.

  1. Edit framemanager.h, and change the wxAuiPaneInfo.frame variable from a wxFrame to wxWindow.
  1. Edit floatpane.h, change

#define wxAuiFloatingFrameBaseClass wxMiniFrame

to

#define wxAuiFloatingFrameBaseClass wxDialog

Note: See TracTickets for help on using tickets.