keyboard: slide focused window on OSK visibility

The focused window will move up/down together with the OSK if the focus
area happens to be covered by the area to be covered by the OSK. This
state is reverted whenever the window loses focus, given it wasn't
relayout in between.
This commit is contained in:
Carlos Garnacho 2017-10-11 09:58:58 +02:00
parent 083d11a032
commit d7f8a39023

View File

@ -16,6 +16,7 @@ const InputSourceManager = imports.ui.status.keyboard;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000; var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
var KEY_LONG_PRESS_TIME = 250; var KEY_LONG_PRESS_TIME = 250;
@ -410,6 +411,8 @@ var Keyboard = new Lang.Class({
this._currentAccessible = null; this._currentAccessible = null;
this._caretTrackingEnabled = false; this._caretTrackingEnabled = false;
this._updateCaretPositionId = 0; this._updateCaretPositionId = 0;
this._currentFocusWindow = null;
this._originalWindowY = null;
this._enableKeyboard = false; // a11y settings value this._enableKeyboard = false; // a11y settings value
this._enabled = false; // enabled state (by setting or device type) this._enabled = false; // enabled state (by setting or device type)
@ -441,6 +444,13 @@ var Keyboard = new Lang.Class({
this._keyboardRestingId = 0; this._keyboardRestingId = 0;
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout)); Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
//Main.inputMethod.connect('cursor-location-changed', Lang.bind(this, function(o, rect) {
// if (this._keyboardVisible) {
// let currentWindow = global.screen.get_display().focus_window;
// this.setCursorLocation(currentWindow, rect.get_x(), rect.get_y(),
// rect.get_width(), rect.get_height());
// }
//}));
}, },
get visible() { get visible() {
@ -465,12 +475,16 @@ var Keyboard = new Lang.Class({
_updateCaretPosition: function (accessible) { _updateCaretPosition: function (accessible) {
if (this._updateCaretPositionId) if (this._updateCaretPositionId)
GLib.source_remove(this._updateCaretPositionId); GLib.source_remove(this._updateCaretPositionId);
if (!this._keyboardRequested)
return;
this._updateCaretPositionId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, Lang.bind(this, function() { this._updateCaretPositionId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, Lang.bind(this, function() {
this._updateCaretPositionId = 0; this._updateCaretPositionId = 0;
let currentWindow = global.screen.get_display().focus_window; let currentWindow = global.screen.get_display().focus_window;
if (!currentWindow) if (!currentWindow) {
this.setCursorLocation(null);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}
let windowRect = currentWindow.get_frame_rect(); let windowRect = currentWindow.get_frame_rect();
let text = accessible.get_text_iface(); let text = accessible.get_text_iface();
@ -481,16 +495,10 @@ var Keyboard = new Lang.Class({
let caretRect = text.get_character_extents(caretOffset, Atspi.CoordType.WINDOW); let caretRect = text.get_character_extents(caretOffset, Atspi.CoordType.WINDOW);
let focusRect = component.get_extents(Atspi.CoordType.WINDOW); let focusRect = component.get_extents(Atspi.CoordType.WINDOW);
caretRect.x += windowRect.x;
caretRect.y += windowRect.y;
focusRect.x += windowRect.x;
focusRect.y += windowRect.y;
if (caretRect.width == 0 && caretRect.height == 0) if (caretRect.width == 0 && caretRect.height == 0)
caretRect = focusRect; caretRect = focusRect;
this.setEntryLocation(focusRect.x, focusRect.y, focusRect.width, focusRect.height); this.setCursorLocation(currentWindow, caretRect.x, caretRect.y, caretRect.width, caretRect.height);
this.setCursorLocation(caretRect.x, caretRect.y, caretRect.width, caretRect.height);
} catch (e) { } catch (e) {
log('Error updating caret position for OSK: ' + e.message); log('Error updating caret position for OSK: ' + e.message);
} }
@ -558,6 +566,8 @@ var Keyboard = new Lang.Class({
if (this._enabled && !this._keyboardController) if (this._enabled && !this._keyboardController)
this._setupKeyboard(); this._setupKeyboard();
else if (!this._enabled)
this.setCursorLocation(null);
if (!this._enabled && wasEnabled) if (!this._enabled && wasEnabled)
Main.layoutManager.hideKeyboard(true); Main.layoutManager.hideKeyboard(true);
@ -893,6 +903,8 @@ var Keyboard = new Lang.Class({
if (!this._keyboardRequested) if (!this._keyboardRequested)
return; return;
if (this._currentAccessible)
this._updateCaretPosition(this._currentAccessible);
Main.layoutManager.keyboardIndex = monitor; Main.layoutManager.keyboardIndex = monitor;
this._relayout(); this._relayout();
Main.layoutManager.showKeyboard(); Main.layoutManager.showKeyboard();
@ -924,6 +936,7 @@ var Keyboard = new Lang.Class({
return; return;
Main.layoutManager.hideKeyboard(); Main.layoutManager.hideKeyboard();
this.setCursorLocation(null);
}, },
_hideSubkeys: function() { _hideSubkeys: function() {
@ -950,20 +963,6 @@ var Keyboard = new Lang.Class({
this._suggestions.actor.show(); this._suggestions.actor.show();
}, },
_moveTemporarily: function () {
let currentWindow = global.screen.get_display().focus_window;
let rect = currentWindow.get_frame_rect();
let newX = rect.x;
let newY = 3 * this.actor.height / 2;
currentWindow.move_frame(true, newX, newY);
},
_setLocation: function (x, y) {
if (y >= 2 * this.actor.height)
this._moveTemporarily();
},
_clearShowIdle: function() { _clearShowIdle: function() {
if (!this._showIdleId) if (!this._showIdleId)
return; return;
@ -971,18 +970,65 @@ var Keyboard = new Lang.Class({
this._showIdleId = 0; this._showIdleId = 0;
}, },
setCursorLocation: function(x, y, w, h) { _windowSlideAnimationComplete: function(window, delta) {
if (!this._enabled) // Synchronize window and actor positions again.
return; let windowActor = window.get_compositor_private();
let frameRect = window.get_frame_rect();
// this._setLocation(x, y); frameRect.y += delta;
window.move_frame(true, frameRect.x, frameRect.y);
}, },
setEntryLocation: function(x, y, w, h) { _animateWindow: function(window, show, deltaY) {
if (!this._enabled) let windowActor = window.get_compositor_private();
if (!windowActor)
return; return;
// this._setLocation(x, y); if (show) {
Tweener.addTween(windowActor,
{ y: windowActor.y - deltaY,
time: Layout.KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._windowSlideAnimationComplete,
onCompleteParams: [window, -deltaY] });
} else {
Tweener.addTween(windowActor,
{ y: windowActor.y + deltaY,
time: Layout.KEYBOARD_ANIMATION_TIME,
transition: 'easeInQuad',
onComplete: this._windowSlideAnimationComplete,
onCompleteParams: [window, deltaY] });
}
},
setCursorLocation: function(window, x, y , w, h) {
if (window == this._oskFocusWindow)
return;
if (this._oskFocusWindow) {
let display = global.screen.get_display();
if (display.get_grab_op() == Meta.GrabOp.NONE ||
display.get_focus_window() != this._oskFocusWindow)
this._animateWindow(this._oskFocusWindow, false, this._oskFocusWindowDelta);
this._oskFocusWindow = null;
this._oskFocusWindowDelta = null;
}
if (window) {
let monitor = Main.layoutManager.keyboardMonitor;
let keyboardHeight = Main.layoutManager.keyboardBox.height;
let frameRect = window.get_frame_rect();
let windowActor = window.get_compositor_private();
let delta = 0;
if (frameRect.y + y + h >= monitor.height - keyboardHeight)
delta = keyboardHeight;
this._animateWindow(window, true, delta);
this._oskFocusWindow = window;
this._oskFocusWindowDelta = delta;
}
}, },
}); });