[gnome-shell/gnome-3-28] keyboard: Implement standalone FocusTracker
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/gnome-3-28] keyboard: Implement standalone FocusTracker
- Date: Wed, 11 Jul 2018 17:05:02 +0000 (UTC)
commit df57829ea1c9467b0d684a9d67d4e180e528b9e1
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri May 25 11:35:49 2018 +0200
keyboard: Implement standalone FocusTracker
And stop using FocusCaretTracker for caret position purposes. This
new object uses 1) the text-input protocol in wayland and 2) Info
from IBusPanelService for X11 (which is meant to work for XIM too).
This drops the usage of AtspiEventListener for OSK purposes, which
is best to avoid.
js/misc/ibusManager.js | 5 ++
js/ui/keyboard.js | 236 +++++++++++++++++++++++--------------------------
2 files changed, 117 insertions(+), 124 deletions(-)
---
diff --git a/js/misc/ibusManager.js b/js/misc/ibusManager.js
index 782b9ad28..6452e492f 100644
--- a/js/misc/ibusManager.js
+++ b/js/misc/ibusManager.js
@@ -115,6 +115,11 @@ var IBusManager = new Lang.Class({
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', this._updateProperty.bind(this));
+ this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
+ let cursorLocation = { x, y, width: w, height: h };
+ this.emit('set-cursor-location', cursorLocation);
+ });
+
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index e13c7b724..5fcdf988a 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -1,6 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const FocusCaretTracker = imports.ui.focusCaretTracker;
const Atspi = imports.gi.Atspi;
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
@@ -13,6 +12,7 @@ const Signals = imports.signals;
const St = imports.gi.St;
const InputSourceManager = imports.ui.status.keyboard;
+const IBusManager = imports.misc.ibusManager;
const BoxPointer = imports.ui.boxpointer;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
@@ -261,6 +261,7 @@ var Key = new Lang.Class({
this._extended_keyboard = null;
this._pressTimeoutId = 0;
this._capturedPress = false;
+
this._capturedEventId = 0;
this._unmapId = 0;
this._longPress = false;
@@ -484,6 +485,71 @@ var KeyboardModel = new Lang.Class({
}
});
+var FocusTracker = new Lang.Class({
+ Name: 'FocusTracker',
+
+ _init() {
+ this._currentWindow = null;
+ this._currentWindowPositionId = 0;
+
+ global.screen.get_display().connect('notify::focus-window', () => {
+ this._setCurrentWindow(global.screen.get_display().focus_window);
+ this.emit('window-changed', this._currentWindow);
+ });
+
+ /* Valid for wayland clients */
+ Main.inputMethod.connect('cursor-location-changed', (o, rect) => {
+ let newRect = { x: rect.get_x(), y: rect.get_y(), width: rect.get_width(), height:
rect.get_height() };
+ this._setCurrentRect(newRect);
+ });
+
+ this._ibusManager = IBusManager.getIBusManager();
+ this._ibusManager.connect('set-cursor-location', (manager, rect) => {
+ /* Valid for X11 clients only */
+ if (Main.inputMethod.currentFocus)
+ return;
+
+ this._setCurrentRect(rect);
+ });
+ },
+
+ get currentWindow() {
+ return this._currentWindow;
+ },
+
+ _setCurrentWindow(window) {
+ if (this._currentWindow)
+ this._currentWindow.disconnect(this._currentWindowPositionId);
+
+ this._currentWindow = window;
+ if (window) {
+ this._currentWindowPositionId = this._currentWindow.connect('position-changed', () => {
+ if (global.display.get_grab_op() == Meta.GrabOp.NONE)
+ this.emit('position-changed');
+ else
+ this.emit('reset');
+ });
+ }
+ },
+
+ _setCurrentRect(rect) {
+ let frameRect = this._currentWindow.get_frame_rect();
+ rect.x -= frameRect.x;
+ rect.y -= frameRect.y;
+
+ this._rect = rect;
+ this.emit('position-changed');
+ },
+
+ getCurrentRect() {
+ let frameRect = this._currentWindow.get_frame_rect();
+ let rect = { x: this._rect.x + frameRect.x, y: this._rect.y + frameRect.y, width: this._rect.width,
height: this._rect.height };
+
+ return rect;
+ }
+});
+Signals.addSignalMethods(FocusTracker.prototype);
+
var Keyboard = new Lang.Class({
Name: 'Keyboard',
@@ -491,15 +557,10 @@ var Keyboard = new Lang.Class({
this.actor = null;
this._focusInExtendedKeys = false;
- this._focusCaretTracker = new FocusCaretTracker.FocusCaretTracker();
- this._focusCaretTracker.connect('focus-changed', this._onFocusChanged.bind(this));
- this._focusCaretTracker.connect('caret-moved', this._onCaretMoved.bind(this));
this._languagePopup = null;
- this._currentAccessible = null;
- this._caretTrackingEnabled = false;
- this._updateCaretPositionId = 0;
this._currentFocusWindow = null;
- this._originalWindowY = null;
+ this._animFocusedWindow = null;
+ this._delayedAnimFocusWindow = null;
this._enableKeyboard = false; // a11y settings value
this._enabled = false; // enabled state (by setting or device type)
@@ -510,6 +571,14 @@ var Keyboard = new Lang.Class({
this._lastDeviceId = null;
this._suggestions = null;
+ this._focusTracker = new FocusTracker();
+ this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
+ this._focusTracker.connect('reset', () => {
+ this._delayedAnimFocusWindow = null;
+ this._animFocusedWindow = null;
+ this._oskFocusWindow = null;
+ });
+
Meta.get_backend().connect('last-device-changed',
(backend, deviceId) => {
let manager = Clutter.DeviceManager.get_default();
@@ -532,102 +601,15 @@ var Keyboard = new Lang.Class({
this._keyboardRestingId = 0;
Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
- //Main.inputMethod.connect('cursor-location-changed', (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() {
return this._keyboardVisible;
},
- _setCaretTrackerEnabled(enabled) {
- if (this._caretTrackingEnabled == enabled)
- return;
-
- this._caretTrackingEnabled = enabled;
-
- if (enabled) {
- this._focusCaretTracker.registerFocusListener();
- this._focusCaretTracker.registerCaretListener();
- } else {
- this._focusCaretTracker.deregisterFocusListener();
- this._focusCaretTracker.deregisterCaretListener();
- }
- },
-
- _updateCaretPosition(accessible) {
- if (this._updateCaretPositionId)
- GLib.source_remove(this._updateCaretPositionId);
- if (!this._keyboardRequested)
- return;
- this._updateCaretPositionId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- this._updateCaretPositionId = 0;
-
- let currentWindow = global.screen.get_display().focus_window;
- if (!currentWindow) {
- this.setCursorLocation(null);
- return GLib.SOURCE_REMOVE;
- }
-
- let windowRect = currentWindow.get_frame_rect();
- let text = accessible.get_text_iface();
- let component = accessible.get_component_iface();
-
- try {
- let caretOffset = text.get_caret_offset();
- let caretRect = text.get_character_extents(caretOffset, Atspi.CoordType.WINDOW);
- let focusRect = component.get_extents(Atspi.CoordType.WINDOW);
-
- if (caretRect.width == 0 && caretRect.height == 0)
- caretRect = focusRect;
-
- this.setCursorLocation(currentWindow, caretRect.x, caretRect.y, caretRect.width,
caretRect.height);
- } catch (e) {
- log('Error updating caret position for OSK: ' + e.message);
- }
-
- return GLib.SOURCE_REMOVE;
- });
-
- GLib.Source.set_name_by_id(this._updateCaretPositionId, '[gnome-shell] this._updateCaretPosition');
- },
-
- _focusIsTextEntry(accessible) {
- try {
- let role = accessible.get_role();
- let stateSet = accessible.get_state_set();
- return stateSet.contains(Atspi.StateType.EDITABLE) || role == Atspi.Role.TERMINAL;
- } catch (e) {
- log('Error determining accessible role: ' + e.message);
- return false;
- }
- },
-
- _onFocusChanged(caretTracker, event) {
- let accessible = event.source;
- if (!this._focusIsTextEntry(accessible))
- return;
-
- let focused = event.detail1 != 0;
- if (focused) {
- this._currentAccessible = accessible;
- this._updateCaretPosition(accessible);
- this.show(Main.layoutManager.focusIndex);
- } else if (this._currentAccessible == accessible) {
- this._currentAccessible = null;
- this.hide();
- }
- },
-
- _onCaretMoved(caretTracker, event) {
- let accessible = event.source;
- if (this._currentAccessible == accessible)
- this._updateCaretPosition(accessible);
+ _onFocusPositionChanged(focusTracker) {
+ let rect = focusTracker.getCurrentRect();
+ this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
},
_lastDeviceIsTouchscreen() {
@@ -650,8 +632,6 @@ var Keyboard = new Lang.Class({
if (!this._enabled && !this._keyboardController)
return;
- this._setCaretTrackerEnabled(this._enabled);
-
if (this._enabled && !this._keyboardController)
this._setupKeyboard();
else if (!this._enabled)
@@ -1027,11 +1007,14 @@ var Keyboard = new Lang.Class({
if (!this._keyboardRequested)
return;
- if (this._currentAccessible)
- this._updateCaretPosition(this._currentAccessible);
Main.layoutManager.keyboardIndex = monitor;
this._relayout();
Main.layoutManager.showKeyboard();
+
+ if (this._delayedAnimFocusWindow) {
+ this._setAnimationWindow(this._delayedAnimFocusWindow);
+ this._delayedAnimFocusWindow = null;
+ }
},
hide() {
@@ -1102,8 +1085,9 @@ var Keyboard = new Lang.Class({
window.move_frame(true, frameRect.x, frameRect.y);
},
- _animateWindow(window, show, deltaY) {
+ _animateWindow(window, show) {
let windowActor = window.get_compositor_private();
+ let deltaY = Main.layoutManager.keyboardBox.height;
if (!windowActor)
return;
@@ -1124,35 +1108,39 @@ var Keyboard = new Lang.Class({
}
},
- setCursorLocation(window, x, y , w, h) {
- if (window == this._oskFocusWindow)
+ _setAnimationWindow(window) {
+ if (this._animFocusedWindow == window)
return;
- if (this._oskFocusWindow) {
- let display = global.screen.get_display();
+ if (this._animFocusedWindow)
+ this._animateWindow(this._animFocusedWindow, false);
+ if (window)
+ this._animateWindow(window, true);
- if (display.get_grab_op() == Meta.GrabOp.NONE ||
- display.get_focus_window() != this._oskFocusWindow)
- this._animateWindow(this._oskFocusWindow, false, this._oskFocusWindowDelta);
+ this._animFocusedWindow = window;
+ },
- this._oskFocusWindow = null;
- this._oskFocusWindowDelta = null;
- }
+ setCursorLocation(window, x, y , w, h) {
+ let monitor = Main.layoutManager.keyboardMonitor;
- if (window) {
- let monitor = Main.layoutManager.keyboardMonitor;
+ if (window && monitor) {
let keyboardHeight = Main.layoutManager.keyboardBox.height;
- let frameRect = window.get_frame_rect();
- let windowActor = window.get_compositor_private();
- let delta = 0;
+ let focusObscured = false;
- if (frameRect.y + y + h >= monitor.height - keyboardHeight)
- delta = keyboardHeight;
-
- this._animateWindow(window, true, delta);
- this._oskFocusWindow = window;
- this._oskFocusWindowDelta = delta;
+ if (y + h >= monitor.y + monitor.height - keyboardHeight) {
+ if (this._keyboardVisible)
+ this._setAnimationWindow(window);
+ else
+ this._delayedAnimFocusWindow = window;
+ } else if (y < keyboardHeight) {
+ this._delayedAnimFocusWindow = null;
+ this._setAnimationWindow(null);
+ }
+ } else {
+ this._setAnimationWindow(null);
}
+
+ this._oskFocusWindow = window;
},
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]