Skip to content

Commit ad4707d

Browse files
committed
fix: Handle window drag by touch input
global.get_pointer() does not track touch input, so when initiating a drag via touchscreen we would be incorrectly tracking the mouse position instead. Unfortunately, in GNOME 50 there is no API to get information on the touch point that is driving the window drag from Display::grab-op-begin. The best we can do is track global events happening before grab-op-begin and try to infer which touch point is driving the drag. Specifically, the global stage receives a LEAVE event from the device starting the window drag immediatly prior to Display::grab-op-begin. For this implementation we use the Clutter.Sprite API which is new in GNOME 49, and specifically Cluter.Sprite::get_coords() which is new in GNOME 50, but we fall-back to global.get_pointer() to support older shell versions, where however the bug will not be fixed.
1 parent e9155aa commit ad4707d

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

tiling-assistant@leleat-on-github/src/extension/moveHandler.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ export default class TilingMoveHandler {
1818
constructor() {
1919
const moveOps = [Meta.GrabOp.MOVING, Meta.GrabOp.KEYBOARD_MOVING];
2020

21+
this._lastSprite = null;
22+
global.stage.connectObject(
23+
'captured-event',
24+
(actor, event) => {
25+
/* heuristic: the Clutter.Sprite that initiates the drag is
26+
* the last one getting a stage leave event */
27+
if (event.type() === Clutter.EventType.LEAVE)
28+
this._lastSprite = actor.get_context().get_backend().get_sprite?.(global.stage, event);
29+
},
30+
this
31+
);
32+
2133
global.display.connectObject(
2234
'grab-op-begin',
2335
(src, window, grabOp) => {
@@ -88,6 +100,7 @@ export default class TilingMoveHandler {
88100
this._wmPrefs = null;
89101

90102
global.display.disconnectObject(this);
103+
global.stage.dicconnectObject(this);
91104

92105
this._tilePreview.destroy();
93106

@@ -119,6 +132,13 @@ export default class TilingMoveHandler {
119132
this._preparePreviewModeChange(this._currPreviewMode, window);
120133
}
121134

135+
getDragCoords() {
136+
const coords = this._dragSprite?.get_coords?.();
137+
if (coords)
138+
return [coords.x, coords.y];
139+
return global.get_pointer().slice(0, 2);
140+
}
141+
122142
_onMoveStarted(window, grabOp) {
123143
if (window.is_skip_taskbar())
124144
return;
@@ -127,7 +147,9 @@ export default class TilingMoveHandler {
127147
// because it may have been tiled with this extension before being
128148
// maximized so we need to restore its size to pre-tiling.
129149
this._wasMaximizedOnStart = window.maximizedHorizontally || window.maximizedVertically;
130-
const [x, y] = global.get_pointer();
150+
151+
this._dragSprite = this._lastSprite;
152+
const [x, y] = this.getDragCoords();
131153

132154
// Try to restore the window size
133155
if (window.tiledRect || this._wasMaximizedOnStart) {
@@ -146,7 +168,7 @@ export default class TilingMoveHandler {
146168
return GLib.SOURCE_REMOVE;
147169
}
148170

149-
const [currX, currY] = global.get_pointer();
171+
const [currX, currY] = this.getDragCoords();
150172
const currPoint = { x: currX, y: currY };
151173
const oldPoint = { x, y };
152174
const moveDist = Util.getDistance(currPoint, oldPoint);
@@ -224,7 +246,7 @@ export default class TilingMoveHandler {
224246
let isCtrlReplacement = false;
225247
const ctrlReplacedTileGroup = [];
226248
const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true });
227-
const pointerPos = { x: global.get_pointer()[0], y: global.get_pointer()[1] };
249+
const pointerPos = { x: this.getDragCoords()[0], y: this.getDragCoords()[1] };
228250
const twHovered = topTileGroup.some(w => w.tiledRect.containsPoint(pointerPos));
229251
if (this._currPreviewMode === MoveModes.ADAPTIVE_TILING && !this._splitRects.size && twHovered) {
230252
isCtrlReplacement = true;
@@ -248,6 +270,8 @@ export default class TilingMoveHandler {
248270
// of a different tile group, with ctrl-(super)-drag. The window may
249271
// be maximized by ctrl-super-drag.
250272
isCtrlReplacement && window.isTiled && Twm.updateTileGroup(ctrlReplacedTileGroup);
273+
274+
this._dragSprite = null;
251275
}
252276
} finally {
253277
if (this._posChangedId) {
@@ -277,7 +301,7 @@ export default class TilingMoveHandler {
277301
// Without the lowPerfMode enabled this will be called whenever the window is
278302
// moved (by listening to the position-changed signal)
279303
_onMoving(grabOp, window, lowPerfMode = false) {
280-
const [x, y] = global.get_pointer();
304+
const [x, y] = this.getDragCoords();
281305
const currPointerPos = { x, y };
282306

283307
if (lowPerfMode) {

0 commit comments

Comments
 (0)