Request window-relative coordinates in focus tracking
Resolves: #2009350
This commit is contained in:
parent
97040a32ad
commit
af5c85c6c9
148
0001-magnifier-Request-window-relative-coordinates-for-fo.patch
Normal file
148
0001-magnifier-Request-window-relative-coordinates-for-fo.patch
Normal 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Name: gnome-shell
|
||||
Version: 40.10
|
||||
Release: 5%{?dist}
|
||||
Release: 6%{?dist}
|
||||
Summary: Window management and application launching for GNOME
|
||||
|
||||
License: GPLv2+
|
||||
@ -49,6 +49,7 @@ Patch47: 0001-layout-Initialize-regions-unconditionally.patch
|
||||
Patch48: 0001-introspect-Allowlist-GNOME-portal.patch
|
||||
Patch49: 0001-introspect-Add-WindowsChanged-signal.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 gnome_desktop_version 3.35.91
|
||||
@ -267,6 +268,10 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de
|
||||
%{_mandir}/man1/gnome-shell.1*
|
||||
|
||||
%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
|
||||
- Backport 'WindowsChanged' introspect signal
|
||||
Related: #2148362
|
||||
|
Loading…
Reference in New Issue
Block a user