[gnome-shell] Layout: show the OSK on the monitor where the focused window lives



commit 8a7c0313f64ffbf84489cc3de81e506b41252f44
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Oct 14 18:57:45 2012 +0200

    Layout: show the OSK on the monitor where the focused window lives
    
    In multimonitor scenarios, it makes sense to show the OSK close to
    the window that will actually receive keystrokes.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=685856

 js/ui/keyboard.js    |   13 +++---
 js/ui/layout.js      |  113 ++++++++++++++++++++++++++++++++++++++------------
 js/ui/messageTray.js |   12 ++++--
 3 files changed, 101 insertions(+), 37 deletions(-)
---
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index 482fb30..67f00ba 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -251,7 +251,7 @@ const Keyboard = new Lang.Class({
         this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
 
         if (show)
-            this.show();
+            this.show(Main.layoutManager.focusIndex);
         else
             this._createSource();
     },
@@ -375,7 +375,7 @@ const Keyboard = new Lang.Class({
         if (!this._enableKeyboard)
             return;
 
-        let monitor = Main.layoutManager.bottomMonitor;
+        let monitor = Main.layoutManager.keyboardMonitor;
         let maxHeight = monitor.height / 3;
         this.actor.width = monitor.width;
 
@@ -462,9 +462,9 @@ const Keyboard = new Lang.Class({
                actor._extended_keys || actor.extended_key;
     },
 
-    show: function () {
+    show: function (monitor) {
+        Main.layoutManager.keyboardIndex = monitor;
         this._redraw();
-
         Main.layoutManager.showKeyboard();
         this._destroySource();
     },
@@ -512,7 +512,7 @@ const Keyboard = new Lang.Class({
 
         if (timestamp != Clutter.CURRENT_TIME)
             this._timestamp = timestamp;
-        this.show();
+        this.show(Main.layoutManager.focusIndex);
     },
 
     Hide: function(timestamp) {
@@ -566,6 +566,7 @@ const KeyboardSource = new Lang.Class({
     },
 
     open: function() {
-        this._keyboard.show();
+        // Show the OSK below the message tray
+        this._keyboard.show(Main.layoutManager.bottomIndex);
     }
 });
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 0b3aa56..a84a9b0 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -103,6 +103,7 @@ const LayoutManager = new Lang.Class({
         this.monitors = [];
         this.primaryMonitor = null;
         this.primaryIndex = -1;
+        this._keyboardIndex = -1;
         this._hotCorners = [];
         this._background = null;
         this._leftPanelBarrier = 0;
@@ -240,9 +241,8 @@ const LayoutManager = new Lang.Class({
         this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
         this.panelBox.set_size(this.primaryMonitor.width, -1);
 
-        this.keyboardBox.set_position(this.bottomMonitor.x,
-                                      this.bottomMonitor.y + this.bottomMonitor.height);
-        this.keyboardBox.set_size(this.bottomMonitor.width, -1);
+        if (this.keyboardIndex < 0)
+            this.keyboardIndex = this.primaryIndex;
 
         this.trayBox.set_position(this.bottomMonitor.x,
                                   this.bottomMonitor.y + this.bottomMonitor.height);
@@ -305,6 +305,42 @@ const LayoutManager = new Lang.Class({
         return this.monitors[index];
     },
 
+    get keyboardMonitor() {
+        return this.monitors[this.keyboardIndex];
+    },
+
+    get focusIndex() {
+        let i = Main.layoutManager.primaryIndex;
+
+        if (global.stage_input_mode == Shell.StageInputMode.FOCUSED ||
+            global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) {
+            let focusActor = global.stage.key_focus;
+            if (focusActor)
+                i = this._chrome.findIndexForActor(focusActor);
+        } else {
+            let focusWindow = global.display.focus_window;
+            if (focusWindow)
+                i = this._chrome.findIndexForWindow(focusWindow.get_compositor_private());
+        }
+
+        return i;
+    },
+
+    get focusMonitor() {
+        return this.monitors[this.focusIndex];
+    },
+
+    set keyboardIndex(v) {
+        this._keyboardIndex = v;
+        this.keyboardBox.set_position(this.keyboardMonitor.x,
+                                      this.keyboardMonitor.y + this.keyboardMonitor.height);
+        this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
+    },
+
+    get keyboardIndex() {
+        return this._keyboardIndex;
+    },
+
     _startupAnimation: function() {
         this.panelBox.anchor_y = this.panelBox.height;
 
@@ -363,11 +399,14 @@ const LayoutManager = new Lang.Class({
                            onComplete: this._showKeyboardComplete,
                            onCompleteScope: this
                          });
-        Tweener.addTween(this.trayBox,
-                         { anchor_y: this.keyboardBox.height,
-                           time: KEYBOARD_ANIMATION_TIME,
-                           transition: 'easeOutQuad'
-                         });
+
+        if (this.keyboardIndex == this.bottomIndex) {
+            Tweener.addTween(this.trayBox,
+                             { anchor_y: this.keyboardBox.height,
+                               time: KEYBOARD_ANIMATION_TIME,
+                               transition: 'easeOutQuad'
+                             });
+        }
 
         this.emit('keyboard-visible-changed', true);
     },
@@ -379,7 +418,8 @@ const LayoutManager = new Lang.Class({
 
         this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
             this.keyboardBox.anchor_y = this.keyboardBox.height;
-            this.trayBox.anchor_y = this.keyboardBox.height;
+            if (this.keyboardIndex == this.bottomIndex)
+                this.trayBox.anchor_y = this.keyboardBox.height;
         }));
     },
 
@@ -395,11 +435,14 @@ const LayoutManager = new Lang.Class({
                            onComplete: this._hideKeyboardComplete,
                            onCompleteScope: this
                          });
-        Tweener.addTween(this.trayBox,
-                         { anchor_y: 0,
-                           time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
-                           transition: 'easeOutQuad'
-                         });
+
+        if (this.keyboardIndex == this.bottomIndex) {
+            Tweener.addTween(this.trayBox,
+                             { anchor_y: 0,
+                               time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
+                               transition: 'easeOutQuad'
+                             });
+        }
 
         this.emit('keyboard-visible-changed', false);
     },
@@ -463,7 +506,7 @@ const LayoutManager = new Lang.Class({
     },
 
     findMonitorForActor: function(actor) {
-        return this._chrome.findMonitorForActor(actor);
+        return this.monitors[this._chrome.findIndexForActor(actor)];
     }
 });
 Signals.addSignalMethods(LayoutManager.prototype);
@@ -812,6 +855,7 @@ const Chrome = new Lang.Class({
 
     _relayout: function() {
         this._monitors = this._layoutManager.monitors;
+        this._primaryIndex = this._layoutManager.primaryIndex;
         this._primaryMonitor = this._layoutManager.primaryMonitor;
 
         this._updateFullscreen();
@@ -827,32 +871,47 @@ const Chrome = new Lang.Class({
             let monitor = this._monitors[i];
             if (cx >= monitor.x && cx < monitor.x + monitor.width &&
                 cy >= monitor.y && cy < monitor.y + monitor.height)
-                return monitor;
+                return i;
         }
         // If the center is not on a monitor, return the first overlapping monitor
         for (let i = 0; i < this._monitors.length; i++) {
             let monitor = this._monitors[i];
             if (x + w > monitor.x && x < monitor.x + monitor.width &&
                 y + h > monitor.y && y < monitor.y + monitor.height)
-                return monitor;
+                return i;
         }
         // otherwise on no monitor
-        return null;
+        return -1;
     },
 
-    _findMonitorForWindow: function(window) {
-        return this._findMonitorForRect(window.x, window.y, window.width, window.height);
+    findIndexForWindow: function(window) {
+        let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
+        if (i >= 0)
+            return i;
+        return this._primaryIndex; // Not on any monitor, pretend its on the primary
     },
 
     // This call guarantees that we return some monitor to simplify usage of it
     // In practice all tracked actors should be visible on some monitor anyway
-    findMonitorForActor: function(actor) {
+    findIndexForActor: function(actor) {
         let [x, y] = actor.get_transformed_position();
         let [w, h] = actor.get_transformed_size();
-        let monitor = this._findMonitorForRect(x, y, w, h);
-        if (monitor)
-            return monitor;
-        return this._primaryMonitor; // Not on any monitor, pretend its on the primary
+        let i = this._findMonitorForRect(x, y, w, h);
+        if (i >= 0)
+            return i;
+        return this._primaryIndex; // Not on any monitor, pretend its on the primary
+    },
+
+    findMonitorForWindow: function(window) {
+        let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
+        if (i >= 0)
+            return this._monitors[i];
+        else
+            return null;
+    },
+
+    findMonitorForActor: function(actor) {
+        return this._monitors[this.findIndexForActor(actor)];
     },
 
     _queueUpdateRegions: function() {
@@ -900,7 +959,7 @@ const Chrome = new Lang.Class({
                 continue;
 
             if (layer == Meta.StackLayer.FULLSCREEN) {
-                let monitor = this._findMonitorForWindow(window);
+                let monitor = this.findMonitorForWindow(window);
                 if (monitor)
                     monitor.inFullscreen = true;
             }
@@ -917,7 +976,7 @@ const Chrome = new Lang.Class({
                 }
 
                 // Or whether it is monitor sized
-                let monitor = this._findMonitorForWindow(window);
+                let monitor = this.findMonitorForWindow(window);
                 if (monitor &&
                     window.x <= monitor.x &&
                     window.x + window.width >= monitor.x + monitor.width &&
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index fa1ea31..483b71d 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -1471,6 +1471,7 @@ const MessageTray = new Lang.Class({
         this._pointerInTray = false;
         this._pointerInKeyboard = false;
         this._keyboardVisible = false;
+        this._keyboardUnderMessageTray = false;
         this._summaryState = State.HIDDEN;
         this._pointerInSummary = false;
         this._notificationClosed = false;
@@ -1924,12 +1925,15 @@ const MessageTray = new Lang.Class({
     },
 
     _onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) {
-        if (this._keyboardVisible == keyboardVisible)
+        let keyboardUnderMessageTray = layoutManager.keyboardIndex == layoutManager.bottomIndex;
+        if (this._keyboardVisible == keyboardVisible &&
+            this._keyboardUnderMesssageTray == keyboardUnderMessageTray)
             return;
 
         this._keyboardVisible = keyboardVisible;
+        this._keyboardUnderMessageTray = keyboardUnderMessageTray;
 
-        if (keyboardVisible)
+        if (keyboardVisible && keyboardUnderMessageTray)
             this.actor.add_style_pseudo_class('keyboard');
         else
             this.actor.remove_style_pseudo_class('keyboard');
@@ -2086,12 +2090,12 @@ const MessageTray = new Lang.Class({
                                      this._desktopCloneState == State.SHOWN);
         let desktopCloneShouldBeVisible = (trayShouldBeVisible &&
                                            !this._overviewVisible &&
-                                           !this._keyboardVisible);
+                                           (!this._keyboardVisible || !this._keyboardUnderMessageTray));
 
         if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) {
             this._showDesktopClone();
         } else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) {
-            this._hideDesktopClone (this._keyboardVisible);
+            this._hideDesktopClone (this._keyboardVisible && this._keyboardUnderMessageTray);
         }
     },
 



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