[gnome-shell] Place popup menus and other override-redirect windows on top of the panel



commit 22ddec46ab442fa38c16c8ad2bc7207ac7b63025
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Feb 12 16:00:41 2013 -0500

    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 0a27ef5..26d2393 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 a49d736..5e9063b 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 e8559eb..8177067 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",


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]