Request window-relative coordinates in focus tracking

Resolves: #2009350
This commit is contained in:
Florian Müllner 2023-01-18 20:16:49 +01:00
parent 97040a32ad
commit af5c85c6c9
2 changed files with 154 additions and 1 deletions

View File

@ -0,0 +1,148 @@
From ea7e7acd45e428cc17306de2bf65730c90d7e118 Mon Sep 17 00:00:00 2001
From: Sebastian Keller <skeller@gnome.org>
Date: Mon, 23 May 2022 23:01:23 +0200
Subject: [PATCH] magnifier: Request window-relative coordinates for
focus/caret events
Absolute screen coordinates are impossible for Wayland clients to
provide, because the clients don't know where the window is positioned.
Some clients, such as the ones using GTK 3 were providing window
relative coordinates even when screen coordinates were requested,
while others, such as GTK 4 clients, were just returning an error for
caret events or also window-relative coordinates for focus events.
So for this to work on Wayland we have to request window-relative
coordinates and translate them to the current focus window.
To ensure the correct coordinates, we have to only consider events
coming from the current focus window. All other events are filtered out
now. As a side effect this also fixes the magnifier always jumping
to a terminal cursor whenever there was some output, even if the window
was not focused.
This also needs some special handling for events coming from the shell
itself, which should not be translated to the focus window either. As
another side effect this fixes another bug that was caused by these
events already including scaling and getting scaled again.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5509
Part-of:
<https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2301>
---
js/ui/magnifier.js | 77 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 70 insertions(+), 7 deletions(-)
diff --git a/js/ui/magnifier.js b/js/ui/magnifier.js
index 4c2e88f1a..9813664be 100644
--- a/js/ui/magnifier.js
+++ b/js/ui/magnifier.js
@@ -789,21 +789,81 @@ var ZoomRegion = class ZoomRegion {
}
}
+ _convertExtentsToScreenSpace(accessible, extents) {
+ const toplevelWindowTypes = new Set([
+ Atspi.Role.FRAME,
+ Atspi.Role.DIALOG,
+ Atspi.Role.WINDOW,
+ ]);
+
+ try {
+ let app = null;
+ let parentWindow = null;
+ let iter = accessible;
+ while (iter) {
+ if (iter.get_role() === Atspi.Role.APPLICATION) {
+ app = iter;
+ /* This is the last Accessible we are interested in */
+ break;
+ } else if (toplevelWindowTypes.has(iter.get_role())) {
+ parentWindow = iter;
+ }
+ iter = iter.get_parent();
+ }
+
+ /* We don't want to translate our own events to the focus window.
+ * They are also already scaled by clutter before being sent, so
+ * we don't need to do that here either. */
+ if (app && app.get_name() === 'gnome-shell')
+ return extents;
+
+ /* Only events from the focused widget of the focused window. Some
+ * widgets seem to claim to have focus when the window does not so
+ * check both. */
+ const windowActive = parentWindow &&
+ parentWindow.get_state_set().contains(Atspi.StateType.ACTIVE);
+ const accessibleFocused =
+ accessible.get_state_set().contains(Atspi.StateType.FOCUSED);
+ if (!windowActive || !accessibleFocused)
+ return null;
+ } catch (e) {
+ throw new Error(`Failed to validate parent window: ${e}`);
+ }
+
+ const focusWindowRect = global.display.focus_window?.get_frame_rect();
+ if (!focusWindowRect)
+ return null;
+
+ const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
+ const screenSpaceExtents = new Atspi.Rect({
+ x: focusWindowRect.x + (scaleFactor * extents.x),
+ y: focusWindowRect.y + (scaleFactor * extents.y),
+ width: scaleFactor * extents.width,
+ height: scaleFactor * extents.height,
+ });
+
+ return screenSpaceExtents;
+ }
+
_updateFocus(caller, event) {
let component = event.source.get_component_iface();
if (!component || event.detail1 != 1)
return;
let extents;
try {
- extents = component.get_extents(Atspi.CoordType.SCREEN);
+ extents = component.get_extents(Atspi.CoordType.WINDOW);
+ extents = this._convertExtentsToScreenSpace(event.source, extents);
+ if (!extents)
+ return;
} catch (e) {
log(`Failed to read extents of focused component: ${e.message}`);
return;
}
- let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
- let [xFocus, yFocus] = [(extents.x + (extents.width / 2)) * scaleFactor,
- (extents.y + (extents.height / 2)) * scaleFactor];
+ const [xFocus, yFocus] = [
+ extents.x + (extents.width / 2),
+ extents.y + (extents.height / 2),
+ ];
if (this._xFocus !== xFocus || this._yFocus !== yFocus) {
[this._xFocus, this._yFocus] = [xFocus, yFocus];
@@ -817,14 +877,17 @@ var ZoomRegion = class ZoomRegion {
return;
let extents;
try {
- extents = text.get_character_extents(text.get_caret_offset(), 0);
+ extents = text.get_character_extents(text.get_caret_offset(),
+ Atspi.CoordType.WINDOW);
+ extents = this._convertExtentsToScreenSpace(text, extents);
+ if (!extents)
+ return;
} catch (e) {
log(`Failed to read extents of text caret: ${e.message}`);
return;
}
- let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
- let [xCaret, yCaret] = [extents.x * scaleFactor, extents.y * scaleFactor];
+ const [xCaret, yCaret] = [extents.x, extents.y];
// Ignore event(s) if the caret size is none (0x0). This happens a lot if
// the cursor offset can't be translated into a location. This is a work
--
2.38.1

View File

@ -2,7 +2,7 @@
Name: gnome-shell Name: gnome-shell
Version: 40.10 Version: 40.10
Release: 5%{?dist} Release: 6%{?dist}
Summary: Window management and application launching for GNOME Summary: Window management and application launching for GNOME
License: GPLv2+ License: GPLv2+
@ -49,6 +49,7 @@ Patch47: 0001-layout-Initialize-regions-unconditionally.patch
Patch48: 0001-introspect-Allowlist-GNOME-portal.patch Patch48: 0001-introspect-Allowlist-GNOME-portal.patch
Patch49: 0001-introspect-Add-WindowsChanged-signal.patch Patch49: 0001-introspect-Add-WindowsChanged-signal.patch
Patch50: 0001-window-tracker-Emit-tracked-windows-changed-on-title.patch Patch50: 0001-window-tracker-Emit-tracked-windows-changed-on-title.patch
Patch51: 0001-magnifier-Request-window-relative-coordinates-for-fo.patch
%define eds_version 3.33.1 %define eds_version 3.33.1
%define gnome_desktop_version 3.35.91 %define gnome_desktop_version 3.35.91
@ -267,6 +268,10 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de
%{_mandir}/man1/gnome-shell.1* %{_mandir}/man1/gnome-shell.1*
%changelog %changelog
* Wed Jan 18 2023 Florian Müllner <fmuellner@redhat.com> - 40.10-6
- Request window-relative coordinates in focus tracker
Resolves: #2009350
* Fri Dec 02 2022 Jonas Ådahl <jadahl@redhat.com> - 40.10-5 * Fri Dec 02 2022 Jonas Ådahl <jadahl@redhat.com> - 40.10-5
- Backport 'WindowsChanged' introspect signal - Backport 'WindowsChanged' introspect signal
Related: #2148362 Related: #2148362