react-x11 2.13.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -8
- package/src/Reconciler.js +34 -21
- package/src/components/Select.js +8 -2
- package/src/events.js +8 -2
- package/src/glnodes.js +15 -3
- package/src/index.d.ts +5 -0
- package/src/nodes/boxpaint.js +9 -0
- package/src/nodes/preedit.js +64 -14
- package/src/ntk.js +10 -1
- package/src/scale.js +52 -22
- package/src/screencolor.js +104 -17
- package/src/types/system.d.ts +14 -1
- package/src/wayland/app.js +574 -0
- package/src/wayland/backendwindow.js +1199 -0
- package/src/wayland/clipboard.js +326 -0
- package/src/wayland/connection.js +485 -0
- package/src/wayland/context2d.js +2290 -0
- package/src/wayland/decorations.js +476 -0
- package/src/wayland/device.js +55 -0
- package/src/wayland/dmabuf.js +89 -0
- package/src/wayland/dnd.js +581 -0
- package/src/wayland/fdutil.js +108 -0
- package/src/wayland/framestyle.js +257 -0
- package/src/wayland/framewatch.js +190 -0
- package/src/wayland/glarea.js +372 -0
- package/src/wayland/glcontext.js +415 -0
- package/src/wayland/glyphatlas.js +237 -0
- package/src/wayland/input.js +417 -0
- package/src/wayland/keysymnames.js +35 -0
- package/src/wayland/layershell.js +363 -0
- package/src/wayland/outputs.js +601 -0
- package/src/wayland/protocols/cursor-shape-v1.json +1 -0
- package/src/wayland/protocols/ext-idle-notify-v1.json +1 -0
- package/src/wayland/protocols/ext-image-capture-source-v1.json +1 -0
- package/src/wayland/protocols/ext-image-copy-capture-v1.json +1 -0
- package/src/wayland/protocols/fractional-scale-v1.json +1 -0
- package/src/wayland/protocols/index.json +131 -0
- package/src/wayland/protocols/kde-server-decoration.json +1 -0
- package/src/wayland/protocols/keyboard-shortcuts-inhibit-unstable-v1.json +1 -0
- package/src/wayland/protocols/linux-dmabuf-v1.json +1 -0
- package/src/wayland/protocols/pointer-constraints-unstable-v1.json +1 -0
- package/src/wayland/protocols/presentation-time.json +1 -0
- package/src/wayland/protocols/primary-selection-unstable-v1.json +1 -0
- package/src/wayland/protocols/relative-pointer-unstable-v1.json +1 -0
- package/src/wayland/protocols/tablet-v2.json +1 -0
- package/src/wayland/protocols/text-input-unstable-v3.json +1 -0
- package/src/wayland/protocols/viewporter.json +1 -0
- package/src/wayland/protocols/wayland.json +1 -0
- package/src/wayland/protocols/wlr-layer-shell-unstable-v1.json +1 -0
- package/src/wayland/protocols/wlr-screencopy-unstable-v1.json +1 -0
- package/src/wayland/protocols/xdg-activation-v1.json +1 -0
- package/src/wayland/protocols/xdg-decoration-unstable-v1.json +1 -0
- package/src/wayland/protocols/xdg-output-unstable-v1.json +1 -0
- package/src/wayland/protocols/xdg-shell.json +1 -0
- package/src/wayland/protocols/xdg-toplevel-icon-v1.json +1 -0
- package/src/wayland/readback.js +99 -0
- package/src/wayland/screencopy.js +584 -0
- package/src/wayland/seat.js +584 -0
- package/src/wayland/shm.js +226 -0
- package/src/wayland/ssd.js +234 -0
- package/src/wayland/surface.js +141 -0
- package/src/wayland/swapchain.js +411 -0
- package/src/wayland/tablet.js +522 -0
- package/src/wayland/target.js +269 -0
- package/src/wayland/text.js +113 -0
- package/src/wayland/textinput.js +671 -0
- package/src/wayland/touch.js +284 -0
- package/src/wayland/window.js +854 -0
- package/src/wayland/xkb.js +425 -0
- package/src/windowstate.js +41 -1
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// Touch: `wl_touch`, the seat's third capability.
|
|
2
|
+
//
|
|
3
|
+
// A touchscreen speaks in *points*. `down` names a surface and gives the
|
|
4
|
+
// point an id, `motion` and `up` refer to the id, and `frame` closes a group
|
|
5
|
+
// of events that happened together — two fingers landing at once are two
|
|
6
|
+
// `down`s and one `frame`. Nothing about a point is a button, there is no
|
|
7
|
+
// cursor, and `cancel` means the compositor took the gesture for itself
|
|
8
|
+
// (a three-finger swipe to the overview) and the client is to forget every
|
|
9
|
+
// point it had.
|
|
10
|
+
//
|
|
11
|
+
// Two things come out of this file, kept deliberately apart:
|
|
12
|
+
//
|
|
13
|
+
// - **Pointer emulation.** Every control in the tree is written against
|
|
14
|
+
// `mousedown`/`mousemove`/`mouseup`, and a finger has to work on all of
|
|
15
|
+
// them without each learning about touch. So the first point of a gesture
|
|
16
|
+
// *becomes the pointer*, the way XI2's pointer emulation makes it the core
|
|
17
|
+
// pointer on X: its `down` is an `enter` and a button-1 press carrying the
|
|
18
|
+
// down's serial (which is what `xdg_toplevel.move` needs when the finger
|
|
19
|
+
// lands on the titlebar), its `motion` is pointer motion, its `up` — or a
|
|
20
|
+
// `cancel` — a release and a `leave`. A second finger while the first is
|
|
21
|
+
// down emulates nothing, so a two-finger gesture never turns into a
|
|
22
|
+
// second click. The emulated events are the seat's own pointer events,
|
|
23
|
+
// shaped identically and routed by `input.js` through exactly the same
|
|
24
|
+
// path — frame hit-testing, popup grabs, cursor hover and all — with
|
|
25
|
+
// `pointerType: 'touch'` and the `touchId` on them, so a handler that
|
|
26
|
+
// cares can tell a finger from a mouse and nothing else has to.
|
|
27
|
+
// - **Raw touch events.** `touchstart`/`touchmove`/`touchend`/`touchcancel`
|
|
28
|
+
// — ntk's names for XI2's TouchBegin/Update/End, with its `touchId` — for
|
|
29
|
+
// every point, each carrying the list of active `touches`, so a gesture
|
|
30
|
+
// that wants more than one finger can be built from them. They ride the
|
|
31
|
+
// same batch as the emulated events and are flushed at `frame`.
|
|
32
|
+
//
|
|
33
|
+
// Coordinates stay surface-local and logical here, as the pointer's are;
|
|
34
|
+
// `input.js` owns the conversion to content-relative device pixels.
|
|
35
|
+
|
|
36
|
+
import { SEAT_CAP, BUTTON_MASK } from './seat.js';
|
|
37
|
+
|
|
38
|
+
/** evdev's code for a touch contact, filling the slot a pointer button has. */
|
|
39
|
+
export const BTN_TOUCH = 0x14a;
|
|
40
|
+
|
|
41
|
+
const BUTTON1 = BUTTON_MASK[1];
|
|
42
|
+
|
|
43
|
+
export class WaylandTouch {
|
|
44
|
+
/**
|
|
45
|
+
* Attach to a seat: `get_touch` now if the capability is already there
|
|
46
|
+
* (the first `capabilities` event arrived during `WaylandSeat.bind`), and
|
|
47
|
+
* follow it as touchscreens come and go.
|
|
48
|
+
*
|
|
49
|
+
* @param {import('./seat.js').WaylandSeat} seat
|
|
50
|
+
*/
|
|
51
|
+
static attach(seat) {
|
|
52
|
+
const touch = new WaylandTouch(seat);
|
|
53
|
+
seat.touch = touch;
|
|
54
|
+
touch._sync(seat.capabilities);
|
|
55
|
+
seat.on('capabilities', touch._onCapabilities);
|
|
56
|
+
return touch;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
constructor(seat) {
|
|
60
|
+
this.seat = seat;
|
|
61
|
+
/** the `wl_touch`, or null while the seat has no touch capability */
|
|
62
|
+
this.touch = null;
|
|
63
|
+
/**
|
|
64
|
+
* Active points by id: `{ id, serial, time, surface, x, y, major, minor,
|
|
65
|
+
* orientation }`, surface-local logical.
|
|
66
|
+
*/
|
|
67
|
+
this.points = new Map();
|
|
68
|
+
/** the id of the point standing in for the pointer, or null */
|
|
69
|
+
this.emulated = null;
|
|
70
|
+
this._batch = [];
|
|
71
|
+
this._onCapabilities = (caps) => this._sync(caps);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_sync(caps) {
|
|
75
|
+
if (caps & SEAT_CAP.TOUCH) this._acquire();
|
|
76
|
+
else this._release();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_acquire() {
|
|
80
|
+
if (this.touch) return;
|
|
81
|
+
const t = this.seat.seat.$.get_touch();
|
|
82
|
+
this.touch = t;
|
|
83
|
+
|
|
84
|
+
t.on('down', (serial, time, surfaceId, id, x, y) => {
|
|
85
|
+
const seat = this.seat;
|
|
86
|
+
seat.lastSerial = serial;
|
|
87
|
+
seat.lastPressSerial = serial;
|
|
88
|
+
const pt = {
|
|
89
|
+
id,
|
|
90
|
+
serial,
|
|
91
|
+
time,
|
|
92
|
+
surface: surfaceId,
|
|
93
|
+
x,
|
|
94
|
+
y,
|
|
95
|
+
major: 0,
|
|
96
|
+
minor: 0,
|
|
97
|
+
orientation: 0,
|
|
98
|
+
};
|
|
99
|
+
this.points.set(id, pt);
|
|
100
|
+
this._raw('touchstart', pt, serial);
|
|
101
|
+
if (this.emulated == null) {
|
|
102
|
+
this.emulated = id;
|
|
103
|
+
this._batch.push({
|
|
104
|
+
type: 'enter',
|
|
105
|
+
serial,
|
|
106
|
+
surface: surfaceId,
|
|
107
|
+
x,
|
|
108
|
+
y,
|
|
109
|
+
device: this._device(pt, true),
|
|
110
|
+
});
|
|
111
|
+
const before = seat.buttonMask;
|
|
112
|
+
seat.buttonMask |= BUTTON1;
|
|
113
|
+
this._batch.push(this._button('buttonpress', pt, serial, before, true));
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
t.on('motion', (time, id, x, y) => {
|
|
117
|
+
const pt = this.points.get(id);
|
|
118
|
+
if (!pt) return;
|
|
119
|
+
pt.x = x;
|
|
120
|
+
pt.y = y;
|
|
121
|
+
pt.time = time;
|
|
122
|
+
this._raw('touchmove', pt, this.seat.lastSerial);
|
|
123
|
+
if (this.emulated === id) {
|
|
124
|
+
this._batch.push({
|
|
125
|
+
type: 'motion',
|
|
126
|
+
time,
|
|
127
|
+
x,
|
|
128
|
+
y,
|
|
129
|
+
surface: pt.surface,
|
|
130
|
+
device: this._device(pt, true),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
t.on('up', (serial, time, id) => {
|
|
135
|
+
const pt = this.points.get(id);
|
|
136
|
+
if (!pt) return;
|
|
137
|
+
this.seat.lastSerial = serial;
|
|
138
|
+
pt.time = time;
|
|
139
|
+
this.points.delete(id);
|
|
140
|
+
this._raw('touchend', pt, serial);
|
|
141
|
+
if (this.emulated === id) this._endEmulation(pt, serial);
|
|
142
|
+
});
|
|
143
|
+
t.on('cancel', () => {
|
|
144
|
+
// Every point is gone at once, and no frame need follow: finalise
|
|
145
|
+
// them here, the emulated one with its release.
|
|
146
|
+
const gone = [...this.points.values()];
|
|
147
|
+
this.points.clear();
|
|
148
|
+
const serial = this.seat.lastSerial;
|
|
149
|
+
for (const pt of gone) {
|
|
150
|
+
this._raw('touchcancel', pt, serial);
|
|
151
|
+
if (this.emulated === pt.id) this._endEmulation(pt, serial);
|
|
152
|
+
}
|
|
153
|
+
this._flush();
|
|
154
|
+
});
|
|
155
|
+
// The contact's shape (v6): an ellipse, in surface-local units. It can
|
|
156
|
+
// arrive after the point's own event within the frame, so a raw event
|
|
157
|
+
// still waiting in the batch is brought up to date too.
|
|
158
|
+
t.on('shape', (id, major, minor) => {
|
|
159
|
+
const pt = this.points.get(id);
|
|
160
|
+
if (!pt) return;
|
|
161
|
+
pt.major = major;
|
|
162
|
+
pt.minor = minor;
|
|
163
|
+
for (const ev of this._batch) {
|
|
164
|
+
if (ev.touchId === id) {
|
|
165
|
+
ev.radiusX = major / 2;
|
|
166
|
+
ev.radiusY = minor / 2;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
t.on('orientation', (id, orientation) => {
|
|
171
|
+
const pt = this.points.get(id);
|
|
172
|
+
if (!pt) return;
|
|
173
|
+
pt.orientation = orientation;
|
|
174
|
+
for (const ev of this._batch)
|
|
175
|
+
if (ev.touchId === id) ev.rotationAngle = orientation;
|
|
176
|
+
});
|
|
177
|
+
t.on('frame', () => this._flush());
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** The touchscreen went away: whatever was down is cancelled. */
|
|
181
|
+
_release() {
|
|
182
|
+
const t = this.touch;
|
|
183
|
+
if (!t) return;
|
|
184
|
+
this.touch = null;
|
|
185
|
+
t.emit('cancel');
|
|
186
|
+
t.removeAllListeners();
|
|
187
|
+
// `release` is v3; a compositor older than that just sees us stop asking
|
|
188
|
+
t.$.release?.();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* A raw event for the point, with a snapshot of every active point and
|
|
193
|
+
* — as a button event carries it — the buttons held *before* it, so a
|
|
194
|
+
* touchstart does not yet show the press it is about to emulate.
|
|
195
|
+
*/
|
|
196
|
+
_raw(type, pt, serial) {
|
|
197
|
+
this._batch.push({
|
|
198
|
+
type,
|
|
199
|
+
id: pt.id,
|
|
200
|
+
touchId: pt.id,
|
|
201
|
+
serial,
|
|
202
|
+
time: pt.time,
|
|
203
|
+
surface: pt.surface,
|
|
204
|
+
x: pt.x,
|
|
205
|
+
y: pt.y,
|
|
206
|
+
state: this.seat.buttonMask,
|
|
207
|
+
radiusX: pt.major / 2,
|
|
208
|
+
radiusY: pt.minor / 2,
|
|
209
|
+
rotationAngle: pt.orientation,
|
|
210
|
+
touches: [...this.points.values()].map((p) => ({
|
|
211
|
+
id: p.id,
|
|
212
|
+
surface: p.surface,
|
|
213
|
+
x: p.x,
|
|
214
|
+
y: p.y,
|
|
215
|
+
})),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** The device tag the emulated events carry. */
|
|
220
|
+
_device(pt, down) {
|
|
221
|
+
// the DOM's answer for hardware without pressure: half while in contact
|
|
222
|
+
return { pointerType: 'touch', touchId: pt.id, pressure: down ? 0.5 : 0 };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
_button(type, pt, serial, state, down) {
|
|
226
|
+
return {
|
|
227
|
+
type,
|
|
228
|
+
serial,
|
|
229
|
+
time: pt.time,
|
|
230
|
+
button: 1,
|
|
231
|
+
evdev: BTN_TOUCH,
|
|
232
|
+
x: pt.x,
|
|
233
|
+
y: pt.y,
|
|
234
|
+
surface: pt.surface,
|
|
235
|
+
state,
|
|
236
|
+
device: this._device(pt, down),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The emulating finger lifted: release, leave — and if a real pointer is
|
|
242
|
+
* over one of our surfaces, it is the pointer again, so `input.js` gets
|
|
243
|
+
* its enter back and its window-under-the-pointer is right.
|
|
244
|
+
*/
|
|
245
|
+
_endEmulation(pt, serial) {
|
|
246
|
+
const seat = this.seat;
|
|
247
|
+
this.emulated = null;
|
|
248
|
+
const before = seat.buttonMask;
|
|
249
|
+
seat.buttonMask &= ~BUTTON1;
|
|
250
|
+
this._batch.push(this._button('buttonrelease', pt, serial, before, false));
|
|
251
|
+
this._batch.push({
|
|
252
|
+
type: 'leave',
|
|
253
|
+
serial,
|
|
254
|
+
surface: pt.surface,
|
|
255
|
+
device: this._device(pt, false),
|
|
256
|
+
});
|
|
257
|
+
if (seat.pointerSurface != null) {
|
|
258
|
+
this._batch.push({
|
|
259
|
+
type: 'enter',
|
|
260
|
+
serial,
|
|
261
|
+
surface: seat.pointerSurface,
|
|
262
|
+
x: seat.pointerX,
|
|
263
|
+
y: seat.pointerY,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
_flush() {
|
|
269
|
+
const batch = this._batch;
|
|
270
|
+
if (batch.length === 0) return;
|
|
271
|
+
this._batch = [];
|
|
272
|
+
for (const ev of batch) this.seat.emit(ev.type, ev);
|
|
273
|
+
this.seat.emit('frame', batch);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
destroy() {
|
|
277
|
+
this.seat.off('capabilities', this._onCapabilities);
|
|
278
|
+
this.points.clear();
|
|
279
|
+
this._batch.length = 0;
|
|
280
|
+
const t = this.touch;
|
|
281
|
+
this.touch = null;
|
|
282
|
+
t?.removeAllListeners();
|
|
283
|
+
}
|
|
284
|
+
}
|