summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2014-06-16 10:59:46 +0000
committerPierre Ossman <ossman@cendio.se>2014-06-16 10:59:46 +0000
commitb4013ef60225b91af17d664b0938a074b7115202 (patch)
treef37a68f66d64d4012f22c0afa750626858e14828 /src
parentd55fac2243973baf1fa34d44a27ad54d3f4d832c (diff)
Make sure that modal and non-modal windows are at a higher level
than "normal" windows. This is mostly necessary when full screen windows are present as those are raised to a higher level in order to obscure the dock and main menu. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10195 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl_cocoa.mm144
1 files changed, 112 insertions, 32 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 12f83e4d6..c9fe2db44 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -777,6 +777,107 @@ double fl_mac_flush_and_wait(double time_to_wait) {
}
+static NSInteger max_normal_window_level(void)
+{
+ Fl_X *x;
+ NSInteger max_level;
+
+ max_level = 0;
+
+ for (x = Fl_X::first;x;x = x->next) {
+ NSInteger level;
+ FLWindow *cw = x->xid;
+ Fl_Window *win = x->w;
+ if (!win || !cw || ![cw isVisible])
+ continue;
+ if (win->modal() || win->non_modal())
+ continue;
+ level = [cw level];
+ if (level >= max_level)
+ max_level = level;
+ }
+
+ return max_level;
+}
+
+// appropriate window level for modal windows
+static NSInteger modal_window_level(void)
+{
+ NSInteger level;
+
+ level = max_normal_window_level();
+ if (level < NSModalPanelWindowLevel)
+ return NSModalPanelWindowLevel;
+
+ // Need some room for non-modal windows
+ level += 2;
+
+ // We cannot exceed this
+ if (level > CGShieldingWindowLevel())
+ return CGShieldingWindowLevel();
+
+ return level;
+}
+
+// appropriate window level for non-modal windows
+static NSInteger non_modal_window_level(void)
+{
+ NSInteger level;
+
+ level = max_normal_window_level();
+ if (level < NSFloatingWindowLevel)
+ return NSFloatingWindowLevel;
+
+ level += 1;
+
+ if (level > CGShieldingWindowLevel())
+ return CGShieldingWindowLevel();
+
+ return level;
+}
+
+// makes sure modal and non-modal windows stay on top
+static void fixup_window_levels(void)
+{
+ NSInteger modal_level, non_modal_level;
+
+ Fl_X *x;
+ FLWindow *prev_modal, *prev_non_modal;
+
+ modal_level = modal_window_level();
+ non_modal_level = non_modal_window_level();
+
+ prev_modal = NULL;
+ prev_non_modal = NULL;
+
+ for (x = Fl_X::first;x;x = x->next) {
+ FLWindow *cw = x->xid;
+ Fl_Window *win = x->w;
+ if (!win || !cw || ![cw isVisible])
+ continue;
+ if (win->modal()) {
+ if ([cw level] != modal_level) {
+ [cw setLevel:modal_level];
+ // changing level puts then in front, so make sure the
+ // stacking isn't messed up
+ if (prev_modal != NULL)
+ [cw orderWindow:NSWindowBelow
+ relativeTo:[prev_modal windowNumber]];
+ }
+ prev_modal = cw;
+ } else if (win->non_modal()) {
+ if ([cw level] != non_modal_level) {
+ [cw setLevel:non_modal_level];
+ if (prev_non_modal != NULL)
+ [cw orderWindow:NSWindowBelow
+ relativeTo:[prev_non_modal windowNumber]];
+ }
+ prev_non_modal = cw;
+ }
+ }
+}
+
+
// updates Fl::e_x, Fl::e_y, Fl::e_x_root, and Fl::e_y_root
static void update_e_xy_and_e_xy_root(NSWindow *nsw)
{
@@ -1011,8 +1112,10 @@ static void cocoaMouseHandler(NSEvent *theEvent)
Fl_Window *window = [nsw getFl_Window];
/* Fullscreen windows obscure all other windows so we need to return
to a "normal" level when the user switches to another window */
- if (window->fullscreen_active())
+ if (window->fullscreen_active()) {
[nsw setLevel:NSNormalWindowLevel];
+ fixup_window_levels();
+ }
Fl::handle( FL_UNFOCUS, window);
fl_unlock_function();
}
@@ -1022,8 +1125,10 @@ static void cocoaMouseHandler(NSEvent *theEvent)
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *w = [nsw getFl_Window];
/* Restore previous fullscreen level */
- if (w->fullscreen_active())
+ if (w->fullscreen_active()) {
[nsw setLevel:NSStatusWindowLevel];
+ fixup_window_levels();
+ }
if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle( FL_FOCUS, w);
fl_unlock_function();
}
@@ -1126,9 +1231,6 @@ static void cocoaMouseHandler(NSEvent *theEvent)
}
- (void)applicationDidBecomeActive:(NSNotification *)notify
{
- Fl_X *x;
- FLWindow *top = 0, *topModal = 0, *topNonModal = 0;
-
fl_lock_function();
// update clipboard status
@@ -1139,30 +1241,8 @@ static void cocoaMouseHandler(NSEvent *theEvent)
* expects the window manager to organize Z level by application. The trickery
* below will change Z order during activation and deactivation.
*/
- for (x = Fl_X::first;x;x = x->next) {
- FLWindow *cw = x->xid;
- Fl_Window *win = x->w;
- if (win && cw && [cw isVisible]) {
- if (win->modal()) {
- [cw setLevel:NSModalPanelWindowLevel];
- if (topModal)
- [cw orderWindow:NSWindowBelow relativeTo:[topModal windowNumber]];
- else
- topModal = cw;
- } else if (win->non_modal()) {
- [cw setLevel:NSFloatingWindowLevel];
- if (topNonModal)
- [cw orderWindow:NSWindowBelow relativeTo:[topNonModal windowNumber]];
- else
- topNonModal = cw;
- } else {
- if (top)
- ;
- else
- top = cw;
- }
- }
- }
+ fixup_window_levels();
+
fl_unlock_function();
}
- (void)applicationDidChangeScreenParameters:(NSNotification *)unused
@@ -2347,17 +2427,17 @@ void Fl_X::make(Fl_Window* w)
// menu windows and tooltips
if (w->modal()||w->tooltip_window()) {
winstyle = NSBorderlessWindowMask;
- winlevel = NSModalPanelWindowLevel;
+ winlevel = modal_window_level();
} else {
winstyle = NSBorderlessWindowMask;
}
} else if (w->modal()) {
winstyle &= ~NSMiniaturizableWindowMask;
// winstyle &= ~(NSResizableWindowMask | NSMiniaturizableWindowMask);
- winlevel = NSModalPanelWindowLevel;
+ winlevel = modal_window_level();
}
else if (w->non_modal()) {
- winlevel = NSFloatingWindowLevel;
+ winlevel = non_modal_window_level();
}
if (by+bt) {