[gnome-shell/wip/rstrode/rhel-7.9: 38/86] closeDialog: Untrack chrome when window loses focus




commit 893a88424a0d214c943c2fa3c4d72ee1a42eca9a
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Sep 4 13:53:24 2018 +0200

    closeDialog: Untrack chrome when window loses focus
    
    On X11, reactive chrome must be added to the input region in order
    to work as expected. However that region works independently from
    any window stacking, with the result that the unresponsive-app dialog
    currently blocks all input in the "covered" area, even in windows
    stacked above the unresponsive window.
    
    The correct fix would be to track the unobscured parts of the dialog
    and set the input region from that, but that's quite cumbersome. So
    instead, only track chrome when the corresponding window is focused
    (or the dialog itself of course).
    
    https://gitlab.gnome.org/GNOME/gnome-shell/issues/273

 js/ui/closeDialog.js | 52 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)
---
diff --git a/js/ui/closeDialog.js b/js/ui/closeDialog.js
index 7943880d8e..c4b033230c 100644
--- a/js/ui/closeDialog.js
+++ b/js/ui/closeDialog.js
@@ -28,7 +28,10 @@ var CloseDialog = new Lang.Class({
         this.parent();
         this._window = window;
         this._dialog = null;
+        this._tracked = undefined;
         this._timeoutId = 0;
+        this._windowFocusChangedId = 0;
+        this._keyFocusChangedId = 0;
     },
 
     get window() {
@@ -96,6 +99,37 @@ var CloseDialog = new Lang.Class({
         this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
     },
 
+    _onFocusChanged() {
+        if (Meta.is_wayland_compositor())
+            return;
+
+        let focusWindow = global.display.focus_window;
+        let keyFocus = global.stage.key_focus;
+
+        let shouldTrack;
+        if (focusWindow != null)
+            shouldTrack = focusWindow == this._window;
+        else
+            shouldTrack = keyFocus && this._dialog.contains(keyFocus);
+
+        if (this._tracked === shouldTrack)
+            return;
+
+        if (shouldTrack)
+            Main.layoutManager.trackChrome(this._dialog,
+                                           { affectsInputRegion: true });
+        else
+            Main.layoutManager.untrackChrome(this._dialog);
+
+        // The buttons are broken when they aren't added to the input region,
+        // so disable them properly in that case
+        this._dialog.buttonLayout.get_children().forEach(b => {
+            b.reactive = shouldTrack;
+        });
+
+        this._tracked = shouldTrack;
+    },
+
     vfunc_show() {
         if (this._dialog != null)
             return;
@@ -108,6 +142,14 @@ var CloseDialog = new Lang.Class({
                 return GLib.SOURCE_CONTINUE;
             });
 
+        this._windowFocusChangedId =
+            global.display.connect('notify::focus-window',
+                                   this._onFocusChanged.bind(this));
+
+        this._keyFocusChangedId =
+            global.stage.connect('notify::key-focus',
+                                 this._onFocusChanged.bind(this));
+
         this._addWindowEffect();
         this._initDialog();
 
@@ -118,9 +160,7 @@ var CloseDialog = new Lang.Class({
                          { scale_y: 1,
                            transition: 'linear',
                            time: DIALOG_TRANSITION_TIME,
-                           onComplete: () => {
-                               Main.layoutManager.trackChrome(this._dialog, { affectsInputRegion: true });
-                           }
+                           onComplete: this._onFocusChanged.bind(this)
                          });
     },
 
@@ -133,6 +173,12 @@ var CloseDialog = new Lang.Class({
         GLib.source_remove(this._timeoutId);
         this._timeoutId = 0;
 
+        global.display.disconnect(this._windowFocusChangedId)
+        this._windowFocusChangedId = 0;
+
+        global.stage.disconnect(this._keyFocusChangedId);
+        this._keyFocusChangedId = 0;
+
         let dialog = this._dialog;
         this._dialog = null;
         this._removeWindowEffect();


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