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
This commit is contained in:
Giovanni Campagna 2012-10-14 18:57:45 +02:00
parent 00201f7e6c
commit 8a7c0313f6
3 changed files with 101 additions and 37 deletions

View File

@ -251,7 +251,7 @@ const Keyboard = new Lang.Class({
this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged)); this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
if (show) if (show)
this.show(); this.show(Main.layoutManager.focusIndex);
else else
this._createSource(); this._createSource();
}, },
@ -375,7 +375,7 @@ const Keyboard = new Lang.Class({
if (!this._enableKeyboard) if (!this._enableKeyboard)
return; return;
let monitor = Main.layoutManager.bottomMonitor; let monitor = Main.layoutManager.keyboardMonitor;
let maxHeight = monitor.height / 3; let maxHeight = monitor.height / 3;
this.actor.width = monitor.width; this.actor.width = monitor.width;
@ -462,9 +462,9 @@ const Keyboard = new Lang.Class({
actor._extended_keys || actor.extended_key; actor._extended_keys || actor.extended_key;
}, },
show: function () { show: function (monitor) {
Main.layoutManager.keyboardIndex = monitor;
this._redraw(); this._redraw();
Main.layoutManager.showKeyboard(); Main.layoutManager.showKeyboard();
this._destroySource(); this._destroySource();
}, },
@ -512,7 +512,7 @@ const Keyboard = new Lang.Class({
if (timestamp != Clutter.CURRENT_TIME) if (timestamp != Clutter.CURRENT_TIME)
this._timestamp = timestamp; this._timestamp = timestamp;
this.show(); this.show(Main.layoutManager.focusIndex);
}, },
Hide: function(timestamp) { Hide: function(timestamp) {
@ -566,6 +566,7 @@ const KeyboardSource = new Lang.Class({
}, },
open: function() { open: function() {
this._keyboard.show(); // Show the OSK below the message tray
this._keyboard.show(Main.layoutManager.bottomIndex);
} }
}); });

View File

@ -103,6 +103,7 @@ const LayoutManager = new Lang.Class({
this.monitors = []; this.monitors = [];
this.primaryMonitor = null; this.primaryMonitor = null;
this.primaryIndex = -1; this.primaryIndex = -1;
this._keyboardIndex = -1;
this._hotCorners = []; this._hotCorners = [];
this._background = null; this._background = null;
this._leftPanelBarrier = 0; 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_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelBox.set_size(this.primaryMonitor.width, -1); this.panelBox.set_size(this.primaryMonitor.width, -1);
this.keyboardBox.set_position(this.bottomMonitor.x, if (this.keyboardIndex < 0)
this.bottomMonitor.y + this.bottomMonitor.height); this.keyboardIndex = this.primaryIndex;
this.keyboardBox.set_size(this.bottomMonitor.width, -1);
this.trayBox.set_position(this.bottomMonitor.x, this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height); this.bottomMonitor.y + this.bottomMonitor.height);
@ -305,6 +305,42 @@ const LayoutManager = new Lang.Class({
return this.monitors[index]; 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() { _startupAnimation: function() {
this.panelBox.anchor_y = this.panelBox.height; this.panelBox.anchor_y = this.panelBox.height;
@ -363,11 +399,14 @@ const LayoutManager = new Lang.Class({
onComplete: this._showKeyboardComplete, onComplete: this._showKeyboardComplete,
onCompleteScope: this onCompleteScope: this
}); });
if (this.keyboardIndex == this.bottomIndex) {
Tweener.addTween(this.trayBox, Tweener.addTween(this.trayBox,
{ anchor_y: this.keyboardBox.height, { anchor_y: this.keyboardBox.height,
time: KEYBOARD_ANIMATION_TIME, time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
}
this.emit('keyboard-visible-changed', true); this.emit('keyboard-visible-changed', true);
}, },
@ -379,6 +418,7 @@ const LayoutManager = new Lang.Class({
this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () { this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
this.keyboardBox.anchor_y = this.keyboardBox.height; this.keyboardBox.anchor_y = this.keyboardBox.height;
if (this.keyboardIndex == this.bottomIndex)
this.trayBox.anchor_y = this.keyboardBox.height; this.trayBox.anchor_y = this.keyboardBox.height;
})); }));
}, },
@ -395,11 +435,14 @@ const LayoutManager = new Lang.Class({
onComplete: this._hideKeyboardComplete, onComplete: this._hideKeyboardComplete,
onCompleteScope: this onCompleteScope: this
}); });
if (this.keyboardIndex == this.bottomIndex) {
Tweener.addTween(this.trayBox, Tweener.addTween(this.trayBox,
{ anchor_y: 0, { anchor_y: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME, time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
}
this.emit('keyboard-visible-changed', false); this.emit('keyboard-visible-changed', false);
}, },
@ -463,7 +506,7 @@ const LayoutManager = new Lang.Class({
}, },
findMonitorForActor: function(actor) { findMonitorForActor: function(actor) {
return this._chrome.findMonitorForActor(actor); return this.monitors[this._chrome.findIndexForActor(actor)];
} }
}); });
Signals.addSignalMethods(LayoutManager.prototype); Signals.addSignalMethods(LayoutManager.prototype);
@ -812,6 +855,7 @@ const Chrome = new Lang.Class({
_relayout: function() { _relayout: function() {
this._monitors = this._layoutManager.monitors; this._monitors = this._layoutManager.monitors;
this._primaryIndex = this._layoutManager.primaryIndex;
this._primaryMonitor = this._layoutManager.primaryMonitor; this._primaryMonitor = this._layoutManager.primaryMonitor;
this._updateFullscreen(); this._updateFullscreen();
@ -827,32 +871,47 @@ const Chrome = new Lang.Class({
let monitor = this._monitors[i]; let monitor = this._monitors[i];
if (cx >= monitor.x && cx < monitor.x + monitor.width && if (cx >= monitor.x && cx < monitor.x + monitor.width &&
cy >= monitor.y && cy < monitor.y + monitor.height) 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 // If the center is not on a monitor, return the first overlapping monitor
for (let i = 0; i < this._monitors.length; i++) { for (let i = 0; i < this._monitors.length; i++) {
let monitor = this._monitors[i]; let monitor = this._monitors[i];
if (x + w > monitor.x && x < monitor.x + monitor.width && if (x + w > monitor.x && x < monitor.x + monitor.width &&
y + h > monitor.y && y < monitor.y + monitor.height) y + h > monitor.y && y < monitor.y + monitor.height)
return monitor; return i;
} }
// otherwise on no monitor // otherwise on no monitor
return null; return -1;
}, },
_findMonitorForWindow: function(window) { findIndexForWindow: function(window) {
return this._findMonitorForRect(window.x, window.y, window.width, window.height); 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 // 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 // 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 [x, y] = actor.get_transformed_position();
let [w, h] = actor.get_transformed_size(); let [w, h] = actor.get_transformed_size();
let monitor = this._findMonitorForRect(x, y, w, h); let i = this._findMonitorForRect(x, y, w, h);
if (monitor) if (i >= 0)
return monitor; return i;
return this._primaryMonitor; // Not on any monitor, pretend its on the primary 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() { _queueUpdateRegions: function() {
@ -900,7 +959,7 @@ const Chrome = new Lang.Class({
continue; continue;
if (layer == Meta.StackLayer.FULLSCREEN) { if (layer == Meta.StackLayer.FULLSCREEN) {
let monitor = this._findMonitorForWindow(window); let monitor = this.findMonitorForWindow(window);
if (monitor) if (monitor)
monitor.inFullscreen = true; monitor.inFullscreen = true;
} }
@ -917,7 +976,7 @@ const Chrome = new Lang.Class({
} }
// Or whether it is monitor sized // Or whether it is monitor sized
let monitor = this._findMonitorForWindow(window); let monitor = this.findMonitorForWindow(window);
if (monitor && if (monitor &&
window.x <= monitor.x && window.x <= monitor.x &&
window.x + window.width >= monitor.x + monitor.width && window.x + window.width >= monitor.x + monitor.width &&

View File

@ -1471,6 +1471,7 @@ const MessageTray = new Lang.Class({
this._pointerInTray = false; this._pointerInTray = false;
this._pointerInKeyboard = false; this._pointerInKeyboard = false;
this._keyboardVisible = false; this._keyboardVisible = false;
this._keyboardUnderMessageTray = false;
this._summaryState = State.HIDDEN; this._summaryState = State.HIDDEN;
this._pointerInSummary = false; this._pointerInSummary = false;
this._notificationClosed = false; this._notificationClosed = false;
@ -1924,12 +1925,15 @@ const MessageTray = new Lang.Class({
}, },
_onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) { _onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) {
if (this._keyboardVisible == keyboardVisible) let keyboardUnderMessageTray = layoutManager.keyboardIndex == layoutManager.bottomIndex;
if (this._keyboardVisible == keyboardVisible &&
this._keyboardUnderMesssageTray == keyboardUnderMessageTray)
return; return;
this._keyboardVisible = keyboardVisible; this._keyboardVisible = keyboardVisible;
this._keyboardUnderMessageTray = keyboardUnderMessageTray;
if (keyboardVisible) if (keyboardVisible && keyboardUnderMessageTray)
this.actor.add_style_pseudo_class('keyboard'); this.actor.add_style_pseudo_class('keyboard');
else else
this.actor.remove_style_pseudo_class('keyboard'); this.actor.remove_style_pseudo_class('keyboard');
@ -2086,12 +2090,12 @@ const MessageTray = new Lang.Class({
this._desktopCloneState == State.SHOWN); this._desktopCloneState == State.SHOWN);
let desktopCloneShouldBeVisible = (trayShouldBeVisible && let desktopCloneShouldBeVisible = (trayShouldBeVisible &&
!this._overviewVisible && !this._overviewVisible &&
!this._keyboardVisible); (!this._keyboardVisible || !this._keyboardUnderMessageTray));
if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) { if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) {
this._showDesktopClone(); this._showDesktopClone();
} else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) { } else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) {
this._hideDesktopClone (this._keyboardVisible); this._hideDesktopClone (this._keyboardVisible && this._keyboardUnderMessageTray);
} }
}, },