From 22ddec46ab442fa38c16c8ad2bc7207ac7b63025 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Tue, 12 Feb 2013 16:00:41 -0500 Subject: [PATCH] Place popup menus and other override-redirect windows on top of the panel https://bugzilla.gnome.org/show_bug.cgi?id=633620 --- js/ui/layout.js | 30 +++++++++++++++++++++++++++--- js/ui/overview.js | 2 ++ src/shell-global.c | 13 +++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/js/ui/layout.js b/js/ui/layout.js index 0a27ef54d..26d239328 100644 --- a/js/ui/layout.js +++ b/js/ui/layout.js @@ -25,6 +25,17 @@ const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff); const MESSAGE_TRAY_PRESSURE_THRESHOLD = 200; // pixels const MESSAGE_TRAY_PRESSURE_TIMEOUT = 3000; // ms +function isPopupMetaWindow(actor) { + switch(actor.meta_window.get_window_type()) { + case Meta.WindowType.DROPDOWN_MENU: + case Meta.WindowType.POPUP_MENU: + case Meta.WindowType.COMBO: + return true; + default: + return false; + } +} + const MonitorConstraint = new Lang.Class({ Name: 'MonitorConstraint', Extends: Clutter.Constraint, @@ -126,6 +137,7 @@ const LayoutManager = new Lang.Class({ this._updateRegionIdle = 0; this._trackedActors = []; + this._isPopupWindowVisible = false; // Normally, the stage is always covered so Clutter doesn't need to clear // it; however it becomes visible during the startup animation @@ -158,8 +170,10 @@ const LayoutManager = new Lang.Class({ // the GDM greeter inside an X11 compositor, to do this at the end... // However, hiding this is necessary to avoid showing the background during // the initial animation, before Gdm.LoginDialog covers everything - if (Main.sessionMode.isGreeter) + if (Main.sessionMode.isGreeter) { global.window_group.hide(); + global.top_window_group.hide(); + } global.stage.remove_actor(global.overlay_group); this.uiGroup.add_actor(global.overlay_group); @@ -190,6 +204,9 @@ const LayoutManager = new Lang.Class({ this.addChrome(this.keyboardBox); this._keyboardHeightNotifyId = 0; + global.stage.remove_actor(global.top_window_group); + this.uiGroup.add_actor(global.top_window_group); + // Need to update struts on new workspaces when they are added global.screen.connect('notify::n-workspaces', Lang.bind(this, this._queueUpdateRegions)); @@ -801,6 +818,9 @@ const LayoutManager = new Lang.Class({ } } + if (!changed && (this._isPopupWindowVisible != global.top_window_group.get_children().some(isPopupMetaWindow))) + changed = true; + if (changed) { this._updateVisibility(); this._queueUpdateRegions(); @@ -819,9 +839,12 @@ const LayoutManager = new Lang.Class({ delete this._updateRegionIdle; } + let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow); + let wantsInputRegion = !isPopupMenuVisible; + for (i = 0; i < this._trackedActors.length; i++) { let actorData = this._trackedActors[i]; - if (!actorData.affectsInputRegion && !actorData.affectsStruts) + if (!(actorData.affectsInputRegion && wantsInputRegion) && !actorData.affectsStruts) continue; let [x, y] = actorData.actor.get_transformed_position(); @@ -831,7 +854,7 @@ const LayoutManager = new Lang.Class({ w = Math.round(w); h = Math.round(h); - if (actorData.affectsInputRegion) { + if (actorData.affectsInputRegion && wantsInputRegion) { let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h}); if (actorData.actor.get_paint_visibility() && @@ -914,6 +937,7 @@ const LayoutManager = new Lang.Class({ } global.set_stage_input_region(rects); + this._isPopupWindowVisible = isPopupMenuVisible; let screen = global.screen; for (let w = 0; w < screen.n_workspaces; w++) { diff --git a/js/ui/overview.js b/js/ui/overview.js index a49d73697..5e9063be5 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -476,6 +476,7 @@ const Overview = new Lang.Class({ // Disable unredirection while in the overview Meta.disable_unredirect_for_screen(global.screen); global.window_group.hide(); + global.top_window_group.hide(); this._overview.show(); this._background.show(); this._viewSelector.show(); @@ -643,6 +644,7 @@ const Overview = new Lang.Class({ Meta.enable_unredirect_for_screen(global.screen); global.window_group.show(); + global.top_window_group.show(); this._viewSelector.hide(); this._desktopFade.hide(); diff --git a/src/shell-global.c b/src/shell-global.c index e8559ebca..817706735 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -107,6 +107,7 @@ enum { PROP_STAGE, PROP_STAGE_INPUT_MODE, PROP_WINDOW_GROUP, + PROP_TOP_WINDOW_GROUP, PROP_BACKGROUND_ACTOR, PROP_WINDOW_MANAGER, PROP_SETTINGS, @@ -203,6 +204,9 @@ shell_global_get_property(GObject *object, case PROP_WINDOW_GROUP: g_value_set_object (value, meta_get_window_group_for_screen (global->meta_screen)); break; + case PROP_TOP_WINDOW_GROUP: + g_value_set_object (value, meta_get_top_window_group_for_screen (global->meta_screen)); + break; case PROP_BACKGROUND_ACTOR: g_value_set_object (value, meta_get_background_actor_for_screen (global->meta_screen)); break; @@ -423,6 +427,15 @@ shell_global_class_init (ShellGlobalClass *klass) "Actor holding window actors", CLUTTER_TYPE_ACTOR, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TOP_WINDOW_GROUP, + g_param_spec_object ("top-window-group", + "Top Window Group", + "Actor holding override-redirect windows", + CLUTTER_TYPE_ACTOR, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_BACKGROUND_ACTOR, g_param_spec_object ("background-actor",