From 8a7c0313f64ffbf84489cc3de81e506b41252f44 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Sun, 14 Oct 2012 18:57:45 +0200 Subject: [PATCH] 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 482fb3068..67f00ba34 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 0b3aa56f0..a84a9b02f 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 fa1ea31d0..483b71dc4 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); } },