@gtkx/testing 0.21.0 → 1.0.0-rc.2
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/README.md +137 -34
- package/dist/act.d.ts +19 -0
- package/dist/act.d.ts.map +1 -0
- package/dist/act.js +56 -0
- package/dist/act.js.map +1 -0
- package/dist/bound-queries.d.ts +33 -0
- package/dist/bound-queries.d.ts.map +1 -0
- package/dist/bound-queries.js +2 -0
- package/dist/bound-queries.js.map +1 -0
- package/dist/build-queries.d.ts +16 -0
- package/dist/build-queries.d.ts.map +1 -0
- package/dist/build-queries.js +115 -0
- package/dist/build-queries.js.map +1 -0
- package/dist/cleanup-registry.d.ts +5 -0
- package/dist/cleanup-registry.d.ts.map +1 -0
- package/dist/cleanup-registry.js +21 -0
- package/dist/cleanup-registry.js.map +1 -0
- package/dist/config.d.ts +20 -52
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -46
- package/dist/config.js.map +1 -1
- package/dist/editable.d.ts +8 -0
- package/dist/editable.d.ts.map +1 -0
- package/dist/editable.js +26 -0
- package/dist/editable.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +135 -0
- package/dist/errors.js.map +1 -0
- package/dist/fire-event.d.ts +8 -25
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +11 -30
- package/dist/fire-event.js.map +1 -1
- package/dist/frame-sync.d.ts +4 -0
- package/dist/frame-sync.d.ts.map +1 -0
- package/dist/frame-sync.js +37 -0
- package/dist/frame-sync.js.map +1 -0
- package/dist/index.d.ts +17 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/matchers.d.ts +59 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/matchers.js +117 -0
- package/dist/matchers.js.map +1 -0
- package/dist/pretty-widget.d.ts +24 -26
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +111 -117
- package/dist/pretty-widget.js.map +1 -1
- package/dist/queries.d.ts +190 -180
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +291 -320
- package/dist/queries.js.map +1 -1
- package/dist/register-test-hooks.d.ts +2 -0
- package/dist/register-test-hooks.d.ts.map +1 -0
- package/dist/register-test-hooks.js +16 -0
- package/dist/register-test-hooks.js.map +1 -0
- package/dist/render-hook.d.ts +15 -35
- package/dist/render-hook.d.ts.map +1 -1
- package/dist/render-hook.js +9 -45
- package/dist/render-hook.js.map +1 -1
- package/dist/render.d.ts +13 -42
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +138 -121
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts +19 -53
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +48 -63
- package/dist/role-helpers.js.map +1 -1
- package/dist/screen.d.ts +7 -63
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +24 -110
- package/dist/screen.js.map +1 -1
- package/dist/screenshot.d.ts +21 -23
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +98 -50
- package/dist/screenshot.js.map +1 -1
- package/dist/suggestions.d.ts +27 -0
- package/dist/suggestions.d.ts.map +1 -0
- package/dist/suggestions.js +61 -0
- package/dist/suggestions.js.map +1 -0
- package/dist/traversal.d.ts +12 -10
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +36 -15
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +115 -169
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +10 -0
- package/dist/user-event/adjustment.d.ts.map +1 -0
- package/dist/user-event/adjustment.js +35 -0
- package/dist/user-event/adjustment.js.map +1 -0
- package/dist/user-event/click.d.ts +8 -0
- package/dist/user-event/click.d.ts.map +1 -0
- package/dist/user-event/click.js +73 -0
- package/dist/user-event/click.js.map +1 -0
- package/dist/user-event/controller.d.ts +8 -0
- package/dist/user-event/controller.d.ts.map +1 -0
- package/dist/user-event/controller.js +31 -0
- package/dist/user-event/controller.js.map +1 -0
- package/dist/user-event/dispatch.d.ts +7 -0
- package/dist/user-event/dispatch.d.ts.map +1 -0
- package/dist/user-event/dispatch.js +11 -0
- package/dist/user-event/dispatch.js.map +1 -0
- package/dist/user-event/event-wrapper.d.ts +4 -0
- package/dist/user-event/event-wrapper.d.ts.map +1 -0
- package/dist/user-event/event-wrapper.js +59 -0
- package/dist/user-event/event-wrapper.js.map +1 -0
- package/dist/user-event/gesture.d.ts +35 -0
- package/dist/user-event/gesture.d.ts.map +1 -0
- package/dist/user-event/gesture.js +138 -0
- package/dist/user-event/gesture.js.map +1 -0
- package/dist/user-event/index.d.ts +51 -0
- package/dist/user-event/index.d.ts.map +1 -0
- package/dist/user-event/index.js +42 -0
- package/dist/user-event/index.js.map +1 -0
- package/dist/user-event/keyboard.d.ts +10 -0
- package/dist/user-event/keyboard.d.ts.map +1 -0
- package/dist/user-event/keyboard.js +204 -0
- package/dist/user-event/keyboard.js.map +1 -0
- package/dist/user-event/pointer.d.ts +10 -0
- package/dist/user-event/pointer.d.ts.map +1 -0
- package/dist/user-event/pointer.js +30 -0
- package/dist/user-event/pointer.js.map +1 -0
- package/dist/user-event/selection.d.ts +5 -0
- package/dist/user-event/selection.d.ts.map +1 -0
- package/dist/user-event/selection.js +105 -0
- package/dist/user-event/selection.js.map +1 -0
- package/dist/user-event/state.d.ts +7 -0
- package/dist/user-event/state.d.ts.map +1 -0
- package/dist/user-event/state.js +3 -0
- package/dist/user-event/state.js.map +1 -0
- package/dist/user-event/text.d.ts +18 -0
- package/dist/user-event/text.d.ts.map +1 -0
- package/dist/user-event/text.js +113 -0
- package/dist/user-event/text.js.map +1 -0
- package/dist/wait-for.d.ts +16 -36
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +74 -70
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts +34 -0
- package/dist/widget-accessible-properties.d.ts.map +1 -0
- package/dist/widget-accessible-properties.js +260 -0
- package/dist/widget-accessible-properties.js.map +1 -0
- package/dist/within.d.ts +10 -26
- package/dist/within.d.ts.map +1 -1
- package/dist/within.js +16 -25
- package/dist/within.js.map +1 -1
- package/package.json +23 -12
- package/src/act.ts +77 -0
- package/src/bound-queries.ts +37 -0
- package/src/build-queries.ts +226 -0
- package/src/cleanup-registry.ts +27 -0
- package/src/config.ts +35 -62
- package/src/editable.ts +37 -0
- package/src/errors.ts +191 -0
- package/src/fire-event.ts +13 -38
- package/src/frame-sync.ts +51 -0
- package/src/index.ts +58 -15
- package/src/matchers.ts +251 -0
- package/src/pretty-widget.ts +163 -130
- package/src/queries.ts +485 -396
- package/src/register-test-hooks.ts +19 -0
- package/src/render-hook.tsx +38 -45
- package/src/render.tsx +192 -155
- package/src/role-helpers.ts +65 -72
- package/src/screen.ts +26 -114
- package/src/screenshot.ts +128 -56
- package/src/suggestions.ts +106 -0
- package/src/traversal.ts +56 -22
- package/src/types.ts +144 -172
- package/src/user-event/adjustment.ts +62 -0
- package/src/user-event/click.ts +99 -0
- package/src/user-event/controller.ts +58 -0
- package/src/user-event/dispatch.ts +25 -0
- package/src/user-event/event-wrapper.ts +80 -0
- package/src/user-event/gesture.ts +239 -0
- package/src/user-event/index.ts +81 -0
- package/src/user-event/keyboard.ts +290 -0
- package/src/user-event/pointer.ts +46 -0
- package/src/user-event/selection.ts +159 -0
- package/src/user-event/state.ts +8 -0
- package/src/user-event/text.ts +172 -0
- package/src/wait-for.ts +117 -78
- package/src/widget-accessible-properties.ts +388 -0
- package/src/within.ts +29 -27
- package/dist/bind-queries.d.ts +0 -14
- package/dist/bind-queries.d.ts.map +0 -1
- package/dist/bind-queries.js +0 -29
- package/dist/bind-queries.js.map +0 -1
- package/dist/error-builder.d.ts +0 -28
- package/dist/error-builder.d.ts.map +0 -1
- package/dist/error-builder.js +0 -81
- package/dist/error-builder.js.map +0 -1
- package/dist/timing.d.ts +0 -18
- package/dist/timing.d.ts.map +0 -1
- package/dist/timing.js +0 -18
- package/dist/timing.js.map +0 -1
- package/dist/user-event.d.ts +0 -138
- package/dist/user-event.d.ts.map +0 -1
- package/dist/user-event.js +0 -411
- package/dist/user-event.js.map +0 -1
- package/dist/widget-text.d.ts +0 -69
- package/dist/widget-text.d.ts.map +0 -1
- package/dist/widget-text.js +0 -177
- package/dist/widget-text.js.map +0 -1
- package/dist/widget.d.ts +0 -3
- package/dist/widget.d.ts.map +0 -1
- package/dist/widget.js +0 -13
- package/dist/widget.js.map +0 -1
- package/src/bind-queries.ts +0 -52
- package/src/error-builder.ts +0 -102
- package/src/timing.ts +0 -17
- package/src/user-event.ts +0 -492
- package/src/widget-text.ts +0 -202
- package/src/widget.ts +0 -15
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import * as Gdk from "@gtkx/gi/gdk";
|
|
2
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
+
import { getEditableDelegate } from "../editable.js";
|
|
4
|
+
import { fireEvent } from "../fire-event.js";
|
|
5
|
+
import { getOrCreateControllers } from "./controller.js";
|
|
6
|
+
import { wrapEvent } from "./event-wrapper.js";
|
|
7
|
+
const KEY_MAP = {
|
|
8
|
+
Enter: Gdk.KEY_Return,
|
|
9
|
+
Tab: Gdk.KEY_Tab,
|
|
10
|
+
Escape: Gdk.KEY_Escape,
|
|
11
|
+
Backspace: Gdk.KEY_BackSpace,
|
|
12
|
+
Delete: Gdk.KEY_Delete,
|
|
13
|
+
ArrowUp: Gdk.KEY_Up,
|
|
14
|
+
ArrowDown: Gdk.KEY_Down,
|
|
15
|
+
ArrowLeft: Gdk.KEY_Left,
|
|
16
|
+
ArrowRight: Gdk.KEY_Right,
|
|
17
|
+
Home: Gdk.KEY_Home,
|
|
18
|
+
End: Gdk.KEY_End,
|
|
19
|
+
PageUp: Gdk.KEY_Page_Up,
|
|
20
|
+
PageDown: Gdk.KEY_Page_Down,
|
|
21
|
+
Space: Gdk.KEY_space,
|
|
22
|
+
Shift: Gdk.KEY_Shift_L,
|
|
23
|
+
Control: Gdk.KEY_Control_L,
|
|
24
|
+
Alt: Gdk.KEY_Alt_L,
|
|
25
|
+
Meta: Gdk.KEY_Meta_L,
|
|
26
|
+
F1: Gdk.KEY_F1,
|
|
27
|
+
F2: Gdk.KEY_F2,
|
|
28
|
+
F3: Gdk.KEY_F3,
|
|
29
|
+
F4: Gdk.KEY_F4,
|
|
30
|
+
F5: Gdk.KEY_F5,
|
|
31
|
+
F6: Gdk.KEY_F6,
|
|
32
|
+
F7: Gdk.KEY_F7,
|
|
33
|
+
F8: Gdk.KEY_F8,
|
|
34
|
+
F9: Gdk.KEY_F9,
|
|
35
|
+
F10: Gdk.KEY_F10,
|
|
36
|
+
F11: Gdk.KEY_F11,
|
|
37
|
+
F12: Gdk.KEY_F12,
|
|
38
|
+
};
|
|
39
|
+
const MODIFIER_KEYVAL_TO_MASK = {
|
|
40
|
+
[Gdk.KEY_Shift_L]: Gdk.ModifierType.SHIFT_MASK,
|
|
41
|
+
[Gdk.KEY_Shift_R]: Gdk.ModifierType.SHIFT_MASK,
|
|
42
|
+
[Gdk.KEY_Control_L]: Gdk.ModifierType.CONTROL_MASK,
|
|
43
|
+
[Gdk.KEY_Control_R]: Gdk.ModifierType.CONTROL_MASK,
|
|
44
|
+
[Gdk.KEY_Alt_L]: Gdk.ModifierType.ALT_MASK,
|
|
45
|
+
[Gdk.KEY_Alt_R]: Gdk.ModifierType.ALT_MASK,
|
|
46
|
+
[Gdk.KEY_Meta_L]: Gdk.ModifierType.META_MASK,
|
|
47
|
+
[Gdk.KEY_Meta_R]: Gdk.ModifierType.META_MASK,
|
|
48
|
+
};
|
|
49
|
+
const tab = (widget, options) => wrapEvent(widget, () => {
|
|
50
|
+
const direction = options?.shift ? Gtk.DirectionType.TAB_BACKWARD : Gtk.DirectionType.TAB_FORWARD;
|
|
51
|
+
const root = widget.getRoot();
|
|
52
|
+
if (root) {
|
|
53
|
+
root.childFocus(direction);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const parseKeyToken = (token) => {
|
|
57
|
+
let keyName = token;
|
|
58
|
+
let isPress = true;
|
|
59
|
+
let isRelease = true;
|
|
60
|
+
if (keyName.startsWith("/")) {
|
|
61
|
+
keyName = keyName.slice(1);
|
|
62
|
+
isPress = false;
|
|
63
|
+
}
|
|
64
|
+
else if (keyName.endsWith(">")) {
|
|
65
|
+
keyName = keyName.slice(0, -1);
|
|
66
|
+
isRelease = false;
|
|
67
|
+
}
|
|
68
|
+
const keyval = KEY_MAP[keyName];
|
|
69
|
+
if (keyval === undefined) {
|
|
70
|
+
throw new Error(`Unknown key: {${keyName}}`);
|
|
71
|
+
}
|
|
72
|
+
return { keyval, press: isPress, release: isRelease };
|
|
73
|
+
};
|
|
74
|
+
const parseCharAt = (input, i) => {
|
|
75
|
+
const keyval = input.codePointAt(i) ?? 0;
|
|
76
|
+
return {
|
|
77
|
+
actions: [
|
|
78
|
+
{ keyval, press: true },
|
|
79
|
+
{ keyval, press: false },
|
|
80
|
+
],
|
|
81
|
+
next: i + 1,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
const parseBraceAt = (input, i) => {
|
|
85
|
+
const endBrace = input.indexOf("}", i);
|
|
86
|
+
if (endBrace === -1) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const { keyval, press, release } = parseKeyToken(input.slice(i + 1, endBrace));
|
|
90
|
+
const actions = [];
|
|
91
|
+
if (press) {
|
|
92
|
+
actions.push({ keyval, press: true });
|
|
93
|
+
}
|
|
94
|
+
if (release) {
|
|
95
|
+
actions.push({ keyval, press: false });
|
|
96
|
+
}
|
|
97
|
+
return { actions, next: endBrace + 1 };
|
|
98
|
+
};
|
|
99
|
+
const parseStepAt = (input, i) => input[i] === "{" ? parseBraceAt(input, i) : parseCharAt(input, i);
|
|
100
|
+
const parseKeyboardInput = (input) => {
|
|
101
|
+
const actions = [];
|
|
102
|
+
let i = 0;
|
|
103
|
+
while (i < input.length) {
|
|
104
|
+
const step = parseStepAt(input, i);
|
|
105
|
+
if (step === null) {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
actions.push(...step.actions);
|
|
109
|
+
i = step.next;
|
|
110
|
+
}
|
|
111
|
+
return actions;
|
|
112
|
+
};
|
|
113
|
+
const updateModifierState = (state, action) => {
|
|
114
|
+
const mask = MODIFIER_KEYVAL_TO_MASK[action.keyval];
|
|
115
|
+
if (!mask) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (action.press) {
|
|
119
|
+
state.modifierState |= mask;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
state.modifierState &= ~mask;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const isTriggerMatch = (trigger, keyval, modifiers) => {
|
|
126
|
+
if (trigger instanceof Gtk.KeyvalTrigger) {
|
|
127
|
+
return trigger.getKeyval() === keyval && trigger.getModifiers() === modifiers;
|
|
128
|
+
}
|
|
129
|
+
if (trigger instanceof Gtk.AlternativeTrigger) {
|
|
130
|
+
return (isTriggerMatch(trigger.getFirst(), keyval, modifiers) ||
|
|
131
|
+
isTriggerMatch(trigger.getSecond(), keyval, modifiers));
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
};
|
|
135
|
+
const didActivateShortcut = (shortcut, widget, keyval, modifiers) => {
|
|
136
|
+
if (!isTriggerMatch(shortcut.getTrigger(), keyval, modifiers)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
const action = shortcut.getAction();
|
|
140
|
+
if (action instanceof Gtk.SignalAction && action.getSignalName() === "move-focus") {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
return action?.activate(0, widget, shortcut.getArguments()) ?? false;
|
|
144
|
+
};
|
|
145
|
+
const didActivateMatchingShortcut = (controller, widget, keyval, modifiers) => {
|
|
146
|
+
const count = controller.getNItems();
|
|
147
|
+
for (let j = 0; j < count; j++) {
|
|
148
|
+
const shortcut = controller.getItem(j);
|
|
149
|
+
if (!(shortcut instanceof Gtk.Shortcut)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (didActivateShortcut(shortcut, widget, keyval, modifiers)) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return false;
|
|
157
|
+
};
|
|
158
|
+
const didDispatchShortcutsOnWidget = (widget, keyval, modifiers) => {
|
|
159
|
+
const controllers = widget.observeControllers();
|
|
160
|
+
for (let i = 0; i < controllers.getNItems(); i++) {
|
|
161
|
+
const controller = controllers.getItem(i);
|
|
162
|
+
if (controller instanceof Gtk.ShortcutController &&
|
|
163
|
+
didActivateMatchingShortcut(controller, widget, keyval, modifiers)) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
};
|
|
169
|
+
const didDispatchShortcuts = (widget, keyval, modifiers) => {
|
|
170
|
+
const delegate = getEditableDelegate(widget);
|
|
171
|
+
if (delegate && didDispatchShortcutsOnWidget(delegate, keyval, modifiers)) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
for (let current = widget; current; current = current.getParent()) {
|
|
175
|
+
if (didDispatchShortcutsOnWidget(current, keyval, modifiers)) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return false;
|
|
180
|
+
};
|
|
181
|
+
const handleKeyPress = async (widget, keyval, modifiers) => {
|
|
182
|
+
const isHandled = didDispatchShortcuts(widget, keyval, modifiers);
|
|
183
|
+
if (!isHandled && keyval === Gdk.KEY_Return && widget instanceof Gtk.Editable) {
|
|
184
|
+
await fireEvent(widget, "activate");
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const applyKeyAction = async (widget, controllers, state, action) => {
|
|
188
|
+
updateModifierState(state, action);
|
|
189
|
+
const signalName = action.press ? "key-pressed" : "key-released";
|
|
190
|
+
for (const controller of controllers) {
|
|
191
|
+
controller.emit(signalName, action.keyval, 0, state.modifierState);
|
|
192
|
+
}
|
|
193
|
+
if (action.press) {
|
|
194
|
+
await handleKeyPress(widget, action.keyval, state.modifierState);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const keyboard = (state, widget, input) => wrapEvent(widget, async () => {
|
|
198
|
+
const controllers = getOrCreateControllers(widget, Gtk.EventControllerKey);
|
|
199
|
+
for (const action of parseKeyboardInput(input)) {
|
|
200
|
+
await applyKeyAction(widget, controllers, state, action);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
export { tab, keyboard };
|
|
204
|
+
//# sourceMappingURL=keyboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../../src/user-event/keyboard.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport type { UserEventState } from \"./state.js\";\nimport { getEditableDelegate } from \"../editable.js\";\nimport { fireEvent } from \"../fire-event.js\";\nimport { getOrCreateControllers } from \"./controller.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\n/** Options for {@link tab}: when `shift` is set, move focus backward instead of forward. */\ntype TabOptions = {\n shift?: boolean;\n};\n\ntype KeyAction = { keyval: number; press: boolean };\ntype ParseStep = { actions: KeyAction[]; next: number };\n\nconst KEY_MAP: Record<string, number> = {\n Enter: Gdk.KEY_Return,\n Tab: Gdk.KEY_Tab,\n Escape: Gdk.KEY_Escape,\n Backspace: Gdk.KEY_BackSpace,\n Delete: Gdk.KEY_Delete,\n ArrowUp: Gdk.KEY_Up,\n ArrowDown: Gdk.KEY_Down,\n ArrowLeft: Gdk.KEY_Left,\n ArrowRight: Gdk.KEY_Right,\n Home: Gdk.KEY_Home,\n End: Gdk.KEY_End,\n PageUp: Gdk.KEY_Page_Up,\n PageDown: Gdk.KEY_Page_Down,\n Space: Gdk.KEY_space,\n Shift: Gdk.KEY_Shift_L,\n Control: Gdk.KEY_Control_L,\n Alt: Gdk.KEY_Alt_L,\n Meta: Gdk.KEY_Meta_L,\n F1: Gdk.KEY_F1,\n F2: Gdk.KEY_F2,\n F3: Gdk.KEY_F3,\n F4: Gdk.KEY_F4,\n F5: Gdk.KEY_F5,\n F6: Gdk.KEY_F6,\n F7: Gdk.KEY_F7,\n F8: Gdk.KEY_F8,\n F9: Gdk.KEY_F9,\n F10: Gdk.KEY_F10,\n F11: Gdk.KEY_F11,\n F12: Gdk.KEY_F12,\n};\n\nconst MODIFIER_KEYVAL_TO_MASK: Record<number, number> = {\n [Gdk.KEY_Shift_L]: Gdk.ModifierType.SHIFT_MASK,\n [Gdk.KEY_Shift_R]: Gdk.ModifierType.SHIFT_MASK,\n [Gdk.KEY_Control_L]: Gdk.ModifierType.CONTROL_MASK,\n [Gdk.KEY_Control_R]: Gdk.ModifierType.CONTROL_MASK,\n [Gdk.KEY_Alt_L]: Gdk.ModifierType.ALT_MASK,\n [Gdk.KEY_Alt_R]: Gdk.ModifierType.ALT_MASK,\n [Gdk.KEY_Meta_L]: Gdk.ModifierType.META_MASK,\n [Gdk.KEY_Meta_R]: Gdk.ModifierType.META_MASK,\n};\n\nconst tab = (widget: Gtk.Widget, options?: TabOptions): Promise<void> =>\n wrapEvent(widget, () => {\n const direction = options?.shift ? Gtk.DirectionType.TAB_BACKWARD : Gtk.DirectionType.TAB_FORWARD;\n const root = widget.getRoot();\n\n if (root) {\n root.childFocus(direction);\n }\n });\n\nconst parseKeyToken = (token: string): { keyval: number; press: boolean; release: boolean } => {\n let keyName = token;\n let isPress = true;\n let isRelease = true;\n\n if (keyName.startsWith(\"/\")) {\n keyName = keyName.slice(1);\n isPress = false;\n } else if (keyName.endsWith(\">\")) {\n keyName = keyName.slice(0, -1);\n isRelease = false;\n }\n\n const keyval = KEY_MAP[keyName];\n\n if (keyval === undefined) {\n throw new Error(`Unknown key: {${keyName}}`);\n }\n\n return { keyval, press: isPress, release: isRelease };\n};\n\nconst parseCharAt = (input: string, i: number): ParseStep => {\n const keyval = input.codePointAt(i) ?? 0;\n\n return {\n actions: [\n { keyval, press: true },\n { keyval, press: false },\n ],\n next: i + 1,\n };\n};\n\nconst parseBraceAt = (input: string, i: number): ParseStep | null => {\n const endBrace = input.indexOf(\"}\", i);\n\n if (endBrace === -1) {\n return null;\n }\n\n const { keyval, press, release } = parseKeyToken(input.slice(i + 1, endBrace));\n const actions: KeyAction[] = [];\n\n if (press) {\n actions.push({ keyval, press: true });\n }\n\n if (release) {\n actions.push({ keyval, press: false });\n }\n\n return { actions, next: endBrace + 1 };\n};\n\nconst parseStepAt = (input: string, i: number): ParseStep | null =>\n input[i] === \"{\" ? parseBraceAt(input, i) : parseCharAt(input, i);\n\nconst parseKeyboardInput = (input: string): KeyAction[] => {\n const actions: KeyAction[] = [];\n let i = 0;\n\n while (i < input.length) {\n const step = parseStepAt(input, i);\n\n if (step === null) {\n break;\n }\n\n actions.push(...step.actions);\n i = step.next;\n }\n\n return actions;\n};\n\nconst updateModifierState = (state: UserEventState, action: KeyAction): void => {\n const mask = MODIFIER_KEYVAL_TO_MASK[action.keyval];\n\n if (!mask) {\n return;\n }\n\n if (action.press) {\n state.modifierState |= mask;\n } else {\n state.modifierState &= ~mask;\n }\n};\n\nconst isTriggerMatch = (\n trigger: Gtk.ShortcutTrigger | null,\n keyval: number,\n modifiers: Gdk.ModifierType,\n): boolean => {\n if (trigger instanceof Gtk.KeyvalTrigger) {\n return trigger.getKeyval() === keyval && trigger.getModifiers() === modifiers;\n }\n\n if (trigger instanceof Gtk.AlternativeTrigger) {\n return (\n isTriggerMatch(trigger.getFirst(), keyval, modifiers) ||\n isTriggerMatch(trigger.getSecond(), keyval, modifiers)\n );\n }\n\n return false;\n};\n\nconst didActivateShortcut = (\n shortcut: Gtk.Shortcut,\n widget: Gtk.Widget,\n keyval: number,\n modifiers: Gdk.ModifierType,\n): boolean => {\n if (!isTriggerMatch(shortcut.getTrigger(), keyval, modifiers)) {\n return false;\n }\n\n const action = shortcut.getAction();\n\n if (action instanceof Gtk.SignalAction && action.getSignalName() === \"move-focus\") {\n return false;\n }\n\n return action?.activate(0 as Gtk.ShortcutActionFlags, widget, shortcut.getArguments()) ?? false;\n};\n\nconst didActivateMatchingShortcut = (\n controller: Gtk.ShortcutController,\n widget: Gtk.Widget,\n keyval: number,\n modifiers: number,\n): boolean => {\n const count = controller.getNItems();\n\n for (let j = 0; j < count; j++) {\n const shortcut = controller.getItem(j);\n\n if (!(shortcut instanceof Gtk.Shortcut)) {\n continue;\n }\n\n if (didActivateShortcut(shortcut, widget, keyval, modifiers)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst didDispatchShortcutsOnWidget = (widget: Gtk.Widget, keyval: number, modifiers: number): boolean => {\n const controllers = widget.observeControllers();\n\n for (let i = 0; i < controllers.getNItems(); i++) {\n const controller = controllers.getItem(i);\n\n if (\n controller instanceof Gtk.ShortcutController &&\n didActivateMatchingShortcut(controller, widget, keyval, modifiers)\n ) {\n return true;\n }\n }\n\n return false;\n};\n\nconst didDispatchShortcuts = (widget: Gtk.Widget, keyval: number, modifiers: number): boolean => {\n const delegate = getEditableDelegate(widget);\n\n if (delegate && didDispatchShortcutsOnWidget(delegate, keyval, modifiers)) {\n return true;\n }\n\n for (let current: Gtk.Widget | null = widget; current; current = current.getParent()) {\n if (didDispatchShortcutsOnWidget(current, keyval, modifiers)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst handleKeyPress = async (widget: Gtk.Widget, keyval: number, modifiers: number): Promise<void> => {\n const isHandled = didDispatchShortcuts(widget, keyval, modifiers);\n\n if (!isHandled && keyval === Gdk.KEY_Return && widget instanceof Gtk.Editable) {\n await fireEvent(widget, \"activate\");\n }\n};\n\nconst applyKeyAction = async (\n widget: Gtk.Widget,\n controllers: Gtk.EventControllerKey[],\n state: UserEventState,\n action: KeyAction,\n): Promise<void> => {\n updateModifierState(state, action);\n const signalName = action.press ? \"key-pressed\" : \"key-released\";\n\n for (const controller of controllers) {\n controller.emit(signalName, action.keyval, 0, state.modifierState);\n }\n\n if (action.press) {\n await handleKeyPress(widget, action.keyval, state.modifierState);\n }\n};\n\nconst keyboard = (state: UserEventState, widget: Gtk.Widget, input: string): Promise<void> =>\n wrapEvent(widget, async () => {\n const controllers = getOrCreateControllers(widget, Gtk.EventControllerKey);\n\n for (const action of parseKeyboardInput(input)) {\n await applyKeyAction(widget, controllers, state, action);\n }\n });\n\nexport { tab, keyboard, type TabOptions };\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import type { UserEventState } from "./state.js";
|
|
3
|
+
/**
|
|
4
|
+
* A pointer action token: a full click (`click`, `[MouseLeft]`), a button press (`down`,
|
|
5
|
+
* `[MouseLeft>]`), or a button release (`up`, `[/MouseLeft]`).
|
|
6
|
+
*/
|
|
7
|
+
type PointerInput = "click" | "down" | "up" | "[MouseLeft]" | "[MouseLeft>]" | "[/MouseLeft]";
|
|
8
|
+
declare const pointer: (state: UserEventState, widget: Gtk.Widget, input: PointerInput) => Promise<void>;
|
|
9
|
+
export { pointer, type PointerInput };
|
|
10
|
+
//# sourceMappingURL=pointer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer.d.ts","sourceRoot":"","sources":["../../src/user-event/pointer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjD;;;GAGG;AACH,KAAK,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AA8B9F,QAAA,MAAM,OAAO,GAAI,OAAO,cAAc,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAGxF,CAAC;AAEP,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import { emitPress, emitRelease } from "./click.js";
|
|
3
|
+
import { getOrCreateControllers } from "./controller.js";
|
|
4
|
+
import { wrapEvent } from "./event-wrapper.js";
|
|
5
|
+
const PRESS_INPUTS = new Set(["[MouseLeft>]", "down"]);
|
|
6
|
+
const RELEASE_INPUTS = new Set(["[/MouseLeft]", "up"]);
|
|
7
|
+
const CLICK_INPUTS = new Set(["[MouseLeft]", "click"]);
|
|
8
|
+
const applyPointerInput = (widget, state, input) => {
|
|
9
|
+
const controllers = getOrCreateControllers(widget, Gtk.GestureClick);
|
|
10
|
+
if (CLICK_INPUTS.has(input)) {
|
|
11
|
+
emitPress(widget, controllers, 1);
|
|
12
|
+
emitRelease(widget, controllers, 1);
|
|
13
|
+
state.mouseLeftDown = false;
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (PRESS_INPUTS.has(input) && !state.mouseLeftDown) {
|
|
17
|
+
emitPress(widget, controllers, 1);
|
|
18
|
+
state.mouseLeftDown = true;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (RELEASE_INPUTS.has(input) && state.mouseLeftDown) {
|
|
22
|
+
emitRelease(widget, controllers, 1);
|
|
23
|
+
state.mouseLeftDown = false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const pointer = (state, widget, input) => wrapEvent(widget, () => {
|
|
27
|
+
applyPointerInput(widget, state, input);
|
|
28
|
+
});
|
|
29
|
+
export { pointer };
|
|
30
|
+
//# sourceMappingURL=pointer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer.js","sourceRoot":"","sources":["../../src/user-event/pointer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQ/C,MAAM,YAAY,GAAsB,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AAC1E,MAAM,cAAc,GAAsB,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;AAC1E,MAAM,YAAY,GAAsB,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1E,MAAM,iBAAiB,GAAG,CAAC,MAAkB,EAAE,KAAqB,EAAE,KAAmB,EAAQ,EAAE;IAC/F,MAAM,WAAW,GAAG,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAErE,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QAClC,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QACpC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;QAE5B,OAAO;IACX,CAAC;IAED,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QAClD,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QAClC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;QAE3B,OAAO;IACX,CAAC;IAED,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACnD,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QACpC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;IAChC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,KAAqB,EAAE,MAAkB,EAAE,KAAmB,EAAiB,EAAE,CAC9F,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;IACnB,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEP,OAAO,EAAE,OAAO,EAAqB,CAAC","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport type { UserEventState } from \"./state.js\";\nimport { emitPress, emitRelease } from \"./click.js\";\nimport { getOrCreateControllers } from \"./controller.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\n/**\n * A pointer action token: a full click (`click`, `[MouseLeft]`), a button press (`down`,\n * `[MouseLeft>]`), or a button release (`up`, `[/MouseLeft]`).\n */\ntype PointerInput = \"click\" | \"down\" | \"up\" | \"[MouseLeft]\" | \"[MouseLeft>]\" | \"[/MouseLeft]\";\n\nconst PRESS_INPUTS: Set<PointerInput> = new Set([\"[MouseLeft>]\", \"down\"]);\nconst RELEASE_INPUTS: Set<PointerInput> = new Set([\"[/MouseLeft]\", \"up\"]);\nconst CLICK_INPUTS: Set<PointerInput> = new Set([\"[MouseLeft]\", \"click\"]);\n\nconst applyPointerInput = (widget: Gtk.Widget, state: UserEventState, input: PointerInput): void => {\n const controllers = getOrCreateControllers(widget, Gtk.GestureClick);\n\n if (CLICK_INPUTS.has(input)) {\n emitPress(widget, controllers, 1);\n emitRelease(widget, controllers, 1);\n state.mouseLeftDown = false;\n\n return;\n }\n\n if (PRESS_INPUTS.has(input) && !state.mouseLeftDown) {\n emitPress(widget, controllers, 1);\n state.mouseLeftDown = true;\n\n return;\n }\n\n if (RELEASE_INPUTS.has(input) && state.mouseLeftDown) {\n emitRelease(widget, controllers, 1);\n state.mouseLeftDown = false;\n }\n};\n\nconst pointer = (state: UserEventState, widget: Gtk.Widget, input: PointerInput): Promise<void> =>\n wrapEvent(widget, () => {\n applyPointerInput(widget, state, input);\n });\n\nexport { pointer, type PointerInput };\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
declare const selectOptions: (widget: Gtk.Widget, values: number | number[]) => Promise<void>;
|
|
3
|
+
declare const deselectOptions: (widget: Gtk.Widget, values: number | number[]) => Promise<void>;
|
|
4
|
+
export { selectOptions, deselectOptions };
|
|
5
|
+
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/user-event/selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAwIpC,QAAA,MAAM,aAAa,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,MAAM,GAAG,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CACd,CAAC;AAkBtE,QAAA,MAAM,eAAe,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,MAAM,GAAG,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CACZ,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import { formatRoleList } from "../role-helpers.js";
|
|
3
|
+
import { wrapEvent } from "./event-wrapper.js";
|
|
4
|
+
const SELECTABLE_ROLES = new Set([Gtk.AccessibleRole.COMBO_BOX, Gtk.AccessibleRole.LIST]);
|
|
5
|
+
const isSelectable = (widget) => {
|
|
6
|
+
return SELECTABLE_ROLES.has(widget.getAccessibleRole());
|
|
7
|
+
};
|
|
8
|
+
const selectListViewItems = (selectionModel, positions, isExclusive) => {
|
|
9
|
+
if (positions.length === 0) {
|
|
10
|
+
selectionModel.unselectRange(0, selectionModel.getNItems());
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const [first] = positions;
|
|
14
|
+
if (isExclusive && first !== undefined && positions.length === 1) {
|
|
15
|
+
selectionModel.selectItem(first, true);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const nItems = selectionModel.getNItems();
|
|
19
|
+
const selected = Gtk.Bitset.newEmpty();
|
|
20
|
+
const mask = Gtk.Bitset.newRange(0, nItems);
|
|
21
|
+
for (const pos of positions) {
|
|
22
|
+
selected.add(pos);
|
|
23
|
+
}
|
|
24
|
+
selectionModel.setSelection(selected, mask);
|
|
25
|
+
};
|
|
26
|
+
const isListView = (widget) => widget instanceof Gtk.ListView || widget instanceof Gtk.GridView || widget instanceof Gtk.ColumnView;
|
|
27
|
+
const selectComboBoxOption = (widget, valueArray) => {
|
|
28
|
+
if (valueArray.length > 1) {
|
|
29
|
+
throw new Error("Cannot select multiple options: ComboBox only supports single selection");
|
|
30
|
+
}
|
|
31
|
+
const [selection] = valueArray;
|
|
32
|
+
if (selection === undefined) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (widget instanceof Gtk.DropDown) {
|
|
36
|
+
widget.setSelected(selection);
|
|
37
|
+
}
|
|
38
|
+
else if (widget instanceof Gtk.ComboBox) {
|
|
39
|
+
widget.setActive(selection);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const selectListBoxRow = (listBox, row) => {
|
|
43
|
+
listBox.selectRow(row);
|
|
44
|
+
row.activate();
|
|
45
|
+
};
|
|
46
|
+
const unselectListBoxRow = (listBox, row) => {
|
|
47
|
+
listBox.unselectRow(row);
|
|
48
|
+
};
|
|
49
|
+
const applyListBoxRows = (listBox, valueArray, apply) => {
|
|
50
|
+
for (const value of valueArray) {
|
|
51
|
+
const row = listBox.getRowAtIndex(value);
|
|
52
|
+
if (!row) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
apply(listBox, row);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const requireSelectionModel = (widget, verb) => {
|
|
59
|
+
const selectionModel = widget.getModel();
|
|
60
|
+
if (selectionModel === null) {
|
|
61
|
+
throw new Error(`Cannot ${verb} options: list view has no selection model`);
|
|
62
|
+
}
|
|
63
|
+
return selectionModel;
|
|
64
|
+
};
|
|
65
|
+
const selectInListView = (widget, valueArray) => {
|
|
66
|
+
const selectionModel = requireSelectionModel(widget, "select");
|
|
67
|
+
const isMultiSelection = selectionModel instanceof Gtk.MultiSelection;
|
|
68
|
+
selectListViewItems(selectionModel, valueArray, !isMultiSelection);
|
|
69
|
+
};
|
|
70
|
+
const selectByRole = (widget, valueArray) => {
|
|
71
|
+
if (!isSelectable(widget)) {
|
|
72
|
+
throw new Error(`Cannot select options: expected selectable widget (${formatRoleList(SELECTABLE_ROLES)})`);
|
|
73
|
+
}
|
|
74
|
+
const role = widget.getAccessibleRole();
|
|
75
|
+
if (role === Gtk.AccessibleRole.COMBO_BOX) {
|
|
76
|
+
selectComboBoxOption(widget, valueArray);
|
|
77
|
+
}
|
|
78
|
+
else if (widget instanceof Gtk.ListBox) {
|
|
79
|
+
applyListBoxRows(widget, valueArray, selectListBoxRow);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const runSelectionEvent = (widget, values, inListView, byRole) => wrapEvent(widget, () => {
|
|
83
|
+
const valueArray = Array.isArray(values) ? values : [values];
|
|
84
|
+
if (isListView(widget)) {
|
|
85
|
+
inListView(widget, valueArray);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
byRole(widget, valueArray);
|
|
89
|
+
});
|
|
90
|
+
const selectOptions = (widget, values) => runSelectionEvent(widget, values, selectInListView, selectByRole);
|
|
91
|
+
const deselectInListView = (widget, valueArray) => {
|
|
92
|
+
const selectionModel = requireSelectionModel(widget, "deselect");
|
|
93
|
+
for (const pos of valueArray) {
|
|
94
|
+
selectionModel.unselectItem(pos);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const deselectByRole = (widget, valueArray) => {
|
|
98
|
+
if (!(widget instanceof Gtk.ListBox)) {
|
|
99
|
+
throw new TypeError("Cannot deselect options: only ListBox supports deselection");
|
|
100
|
+
}
|
|
101
|
+
applyListBoxRows(widget, valueArray, unselectListBoxRow);
|
|
102
|
+
};
|
|
103
|
+
const deselectOptions = (widget, values) => runSelectionEvent(widget, values, deselectInListView, deselectByRole);
|
|
104
|
+
export { selectOptions, deselectOptions };
|
|
105
|
+
//# sourceMappingURL=selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/user-event/selection.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\ntype CollectionWidget = Gtk.ListView | Gtk.GridView | Gtk.ColumnView;\ntype ListBoxRowAction = (listBox: Gtk.ListBox, row: Gtk.ListBoxRow) => void;\n\nconst SELECTABLE_ROLES: Set<Gtk.AccessibleRole> = new Set([Gtk.AccessibleRole.COMBO_BOX, Gtk.AccessibleRole.LIST]);\n\nconst isSelectable = (widget: Gtk.Widget): boolean => {\n return SELECTABLE_ROLES.has(widget.getAccessibleRole());\n};\n\nconst selectListViewItems = (\n selectionModel: Gtk.SelectionModel,\n positions: number[],\n isExclusive: boolean,\n): void => {\n if (positions.length === 0) {\n selectionModel.unselectRange(0, selectionModel.getNItems());\n\n return;\n }\n\n const [first] = positions;\n\n if (isExclusive && first !== undefined && positions.length === 1) {\n selectionModel.selectItem(first, true);\n\n return;\n }\n\n const nItems = selectionModel.getNItems();\n const selected = Gtk.Bitset.newEmpty();\n const mask = Gtk.Bitset.newRange(0, nItems);\n\n for (const pos of positions) {\n selected.add(pos);\n }\n\n selectionModel.setSelection(selected, mask);\n};\n\nconst isListView = (widget: Gtk.Widget): widget is CollectionWidget =>\n widget instanceof Gtk.ListView || widget instanceof Gtk.GridView || widget instanceof Gtk.ColumnView;\n\nconst selectComboBoxOption = (widget: Gtk.Widget, valueArray: number[]): void => {\n if (valueArray.length > 1) {\n throw new Error(\"Cannot select multiple options: ComboBox only supports single selection\");\n }\n\n const [selection] = valueArray;\n\n if (selection === undefined) {\n return;\n }\n\n if (widget instanceof Gtk.DropDown) {\n widget.setSelected(selection);\n } else if (widget instanceof Gtk.ComboBox) {\n widget.setActive(selection);\n }\n};\n\nconst selectListBoxRow = (listBox: Gtk.ListBox, row: Gtk.ListBoxRow): void => {\n listBox.selectRow(row);\n row.activate();\n};\n\nconst unselectListBoxRow = (listBox: Gtk.ListBox, row: Gtk.ListBoxRow): void => {\n listBox.unselectRow(row);\n};\n\nconst applyListBoxRows = (listBox: Gtk.ListBox, valueArray: number[], apply: ListBoxRowAction): void => {\n for (const value of valueArray) {\n const row = listBox.getRowAtIndex(value);\n\n if (!row) {\n continue;\n }\n\n apply(listBox, row);\n }\n};\n\nconst requireSelectionModel = (\n widget: CollectionWidget,\n verb: string,\n): Gtk.SelectionModel => {\n const selectionModel = widget.getModel();\n\n if (selectionModel === null) {\n throw new Error(`Cannot ${verb} options: list view has no selection model`);\n }\n\n return selectionModel;\n};\n\nconst selectInListView = (widget: CollectionWidget, valueArray: number[]): void => {\n const selectionModel = requireSelectionModel(widget, \"select\");\n const isMultiSelection = selectionModel instanceof Gtk.MultiSelection;\n selectListViewItems(selectionModel, valueArray, !isMultiSelection);\n};\n\nconst selectByRole = (widget: Gtk.Widget, valueArray: number[]): void => {\n if (!isSelectable(widget)) {\n throw new Error(`Cannot select options: expected selectable widget (${formatRoleList(SELECTABLE_ROLES)})`);\n }\n\n const role = widget.getAccessibleRole();\n\n if (role === Gtk.AccessibleRole.COMBO_BOX) {\n selectComboBoxOption(widget, valueArray);\n } else if (widget instanceof Gtk.ListBox) {\n applyListBoxRows(widget, valueArray, selectListBoxRow);\n }\n};\n\nconst runSelectionEvent = (\n widget: Gtk.Widget,\n values: number | number[],\n inListView: (view: Gtk.ListView | Gtk.GridView | Gtk.ColumnView, valueArray: number[]) => void,\n byRole: (widget: Gtk.Widget, valueArray: number[]) => void,\n): Promise<void> =>\n wrapEvent(widget, () => {\n const valueArray = Array.isArray(values) ? values : [values];\n\n if (isListView(widget)) {\n inListView(widget, valueArray);\n\n return;\n }\n\n byRole(widget, valueArray);\n });\n\nconst selectOptions = (widget: Gtk.Widget, values: number | number[]): Promise<void> =>\n runSelectionEvent(widget, values, selectInListView, selectByRole);\n\nconst deselectInListView = (widget: Gtk.ListView | Gtk.GridView | Gtk.ColumnView, valueArray: number[]): void => {\n const selectionModel = requireSelectionModel(widget, \"deselect\");\n\n for (const pos of valueArray) {\n selectionModel.unselectItem(pos);\n }\n};\n\nconst deselectByRole = (widget: Gtk.Widget, valueArray: number[]): void => {\n if (!(widget instanceof Gtk.ListBox)) {\n throw new TypeError(\"Cannot deselect options: only ListBox supports deselection\");\n }\n\n applyListBoxRows(widget, valueArray, unselectListBoxRow);\n};\n\nconst deselectOptions = (widget: Gtk.Widget, values: number | number[]): Promise<void> =>\n runSelectionEvent(widget, values, deselectInListView, deselectByRole);\n\nexport { selectOptions, deselectOptions };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/user-event/state.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAO,cAA8D,CAAC;AAE9F,OAAO,EAAE,kBAAkB,EAAE,KAAK,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/user-event/state.ts"],"names":[],"mappings":"AAKA,MAAM,kBAAkB,GAAG,GAAmB,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;AAE9F,OAAO,EAAE,kBAAkB,EAAuB,CAAC","sourcesContent":["type UserEventState = {\n modifierState: number;\n mouseLeftDown: boolean;\n};\n\nconst createInitialState = (): UserEventState => ({ modifierState: 0, mouseLeftDown: false });\n\nexport { createInitialState, type UserEventState };\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
/** Options for {@link type}. */
|
|
3
|
+
type TypeOptions = {
|
|
4
|
+
/** Do not focus the widget before typing. */
|
|
5
|
+
skipClick?: boolean | undefined;
|
|
6
|
+
/** Select from this offset before typing, replacing the selected range with the typed text. */
|
|
7
|
+
initialSelectionStart?: number | undefined;
|
|
8
|
+
/** End offset of the initial selection (defaults to the start offset). */
|
|
9
|
+
initialSelectionEnd?: number | undefined;
|
|
10
|
+
};
|
|
11
|
+
declare const resetClipboard: () => void;
|
|
12
|
+
declare const type: (widget: Gtk.Widget, text: string, options?: TypeOptions) => Promise<void>;
|
|
13
|
+
declare const clear: (widget: Gtk.Widget) => Promise<void>;
|
|
14
|
+
declare const copy: (widget: Gtk.Widget) => Promise<void>;
|
|
15
|
+
declare const cut: (widget: Gtk.Widget) => Promise<void>;
|
|
16
|
+
declare const paste: (widget: Gtk.Widget, text?: string) => Promise<void>;
|
|
17
|
+
export { resetClipboard, type, clear, copy, cut, paste, type TypeOptions };
|
|
18
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAKpC,gCAAgC;AAChC,KAAK,WAAW,GAAG;IACf,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,+FAA+F;IAC/F,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAqGF,QAAA,MAAM,cAAc,QAAO,IAE1B,CAAC;AAeF,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,EAAE,UAAU,WAAW,KAAG,OAAO,CAAC,IAAI,CAQ9E,CAAC;AAEP,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAG1C,CAAC;AAEP,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAGzC,CAAC;AAEP,QAAA,MAAM,GAAG,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAIxC,CAAC;AAEP,QAAA,MAAM,KAAK,GAAU,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAUpE,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as Gdk from "@gtkx/gi/gdk";
|
|
2
|
+
import * as GObject from "@gtkx/gi/gobject";
|
|
3
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
+
import { EDITABLE_ROLES, getEditableDelegate, isEditable } from "../editable.js";
|
|
5
|
+
import { formatRoleList } from "../role-helpers.js";
|
|
6
|
+
import { wrapEvent } from "./event-wrapper.js";
|
|
7
|
+
const EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;
|
|
8
|
+
const insertEditableText = (widget, text) => {
|
|
9
|
+
if (widget instanceof Gtk.TextView) {
|
|
10
|
+
widget.emit("insert-at-cursor", text);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const target = getEditableDelegate(widget) ?? widget;
|
|
14
|
+
if (target instanceof Gtk.Text) {
|
|
15
|
+
target.emit("insert-at-cursor", text);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const position = widget.getPosition();
|
|
19
|
+
const newPosition = widget.insertText(text, text.length, position);
|
|
20
|
+
widget.setPosition(newPosition);
|
|
21
|
+
};
|
|
22
|
+
const readSelection = (widget) => {
|
|
23
|
+
if (widget instanceof Gtk.TextView) {
|
|
24
|
+
const buffer = widget.getBuffer();
|
|
25
|
+
const [hasSelection, start, end] = buffer.getSelectionBounds();
|
|
26
|
+
return hasSelection ? buffer.getText(start, end, true) : "";
|
|
27
|
+
}
|
|
28
|
+
const [hasSelection, start, end] = widget.getSelectionBounds();
|
|
29
|
+
return hasSelection ? widget.getChars(start, end) : "";
|
|
30
|
+
};
|
|
31
|
+
const deleteSelection = (widget) => {
|
|
32
|
+
if (widget instanceof Gtk.TextView) {
|
|
33
|
+
widget.getBuffer().deleteSelection(false, true);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
widget.deleteSelection();
|
|
37
|
+
};
|
|
38
|
+
const setEditableText = (widget, text) => {
|
|
39
|
+
if (widget instanceof Gtk.TextView) {
|
|
40
|
+
widget.getBuffer().setText(text, text.length);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
widget.setText(text);
|
|
44
|
+
};
|
|
45
|
+
const applyTextViewSelection = (widget, start, end) => {
|
|
46
|
+
const buffer = widget.getBuffer();
|
|
47
|
+
buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));
|
|
48
|
+
if (end !== start) {
|
|
49
|
+
deleteSelection(widget);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const applyEditableSelection = (widget, start, end) => {
|
|
53
|
+
widget.selectRegion(start, end);
|
|
54
|
+
if (end !== start) {
|
|
55
|
+
widget.deleteSelection();
|
|
56
|
+
}
|
|
57
|
+
widget.setPosition(start);
|
|
58
|
+
};
|
|
59
|
+
const applyInitialSelection = (widget, options) => {
|
|
60
|
+
if (options.initialSelectionStart === undefined) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const start = options.initialSelectionStart;
|
|
64
|
+
const end = options.initialSelectionEnd ?? start;
|
|
65
|
+
if (widget instanceof Gtk.TextView) {
|
|
66
|
+
applyTextViewSelection(widget, start, end);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
applyEditableSelection(widget, start, end);
|
|
70
|
+
};
|
|
71
|
+
const writeClipboardText = (widget, text) => {
|
|
72
|
+
const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {
|
|
73
|
+
v.setString(text);
|
|
74
|
+
});
|
|
75
|
+
widget.getClipboard().set(value);
|
|
76
|
+
};
|
|
77
|
+
const resetClipboard = () => {
|
|
78
|
+
Gdk.Display.getDefault()?.getClipboard().setContent(null);
|
|
79
|
+
};
|
|
80
|
+
const runEditableEvent = (widget, failure, action) => wrapEvent(widget, () => {
|
|
81
|
+
if (!isEditable(widget)) {
|
|
82
|
+
throw new Error(`${failure}: ${EDITABLE_REQUIRED}`);
|
|
83
|
+
}
|
|
84
|
+
action(widget);
|
|
85
|
+
});
|
|
86
|
+
const type = (widget, text, options) => runEditableEvent(widget, "Cannot type into element", (editable) => {
|
|
87
|
+
if (!options?.skipClick) {
|
|
88
|
+
editable.grabFocus();
|
|
89
|
+
}
|
|
90
|
+
applyInitialSelection(editable, options ?? {});
|
|
91
|
+
insertEditableText(editable, text);
|
|
92
|
+
});
|
|
93
|
+
const clear = (widget) => runEditableEvent(widget, "Cannot clear element", (editable) => {
|
|
94
|
+
setEditableText(editable, "");
|
|
95
|
+
});
|
|
96
|
+
const copy = (widget) => runEditableEvent(widget, "Cannot copy", (editable) => {
|
|
97
|
+
writeClipboardText(editable, readSelection(editable));
|
|
98
|
+
});
|
|
99
|
+
const cut = (widget) => runEditableEvent(widget, "Cannot cut", (editable) => {
|
|
100
|
+
writeClipboardText(editable, readSelection(editable));
|
|
101
|
+
deleteSelection(editable);
|
|
102
|
+
});
|
|
103
|
+
const paste = async (widget, text) => {
|
|
104
|
+
if (!isEditable(widget)) {
|
|
105
|
+
throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);
|
|
106
|
+
}
|
|
107
|
+
const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? "";
|
|
108
|
+
await wrapEvent(widget, () => {
|
|
109
|
+
insertEditableText(widget, content);
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
export { resetClipboard, type, clear, copy, cut, paste };
|
|
113
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable } from \"../editable.js\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\n/** Options for {@link type}. */\ntype TypeOptions = {\n /** Do not focus the widget before typing. */\n skipClick?: boolean | undefined;\n /** Select from this offset before typing, replacing the selected range with the typed text. */\n initialSelectionStart?: number | undefined;\n /** End offset of the initial selection (defaults to the start offset). */\n initialSelectionEnd?: number | undefined;\n};\n\nconst EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;\n\nconst insertEditableText = (widget: EditableTarget, text: string): void => {\n if (widget instanceof Gtk.TextView) {\n widget.emit(\"insert-at-cursor\", text);\n\n return;\n }\n\n const target = getEditableDelegate(widget) ?? widget;\n\n if (target instanceof Gtk.Text) {\n target.emit(\"insert-at-cursor\", text);\n\n return;\n }\n\n const position = widget.getPosition();\n const newPosition = widget.insertText(text, text.length, position);\n widget.setPosition(newPosition);\n};\n\nconst readSelection = (widget: EditableTarget): string => {\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n const [hasSelection, start, end] = buffer.getSelectionBounds();\n\n return hasSelection ? buffer.getText(start, end, true) : \"\";\n }\n\n const [hasSelection, start, end] = widget.getSelectionBounds();\n\n return hasSelection ? widget.getChars(start, end) : \"\";\n};\n\nconst deleteSelection = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.getBuffer().deleteSelection(false, true);\n\n return;\n }\n\n widget.deleteSelection();\n};\n\nconst setEditableText = (widget: EditableTarget, text: string): void => {\n if (widget instanceof Gtk.TextView) {\n widget.getBuffer().setText(text, text.length);\n\n return;\n }\n\n widget.setText(text);\n};\n\nconst applyTextViewSelection = (widget: Gtk.TextView, start: number, end: number): void => {\n const buffer = widget.getBuffer();\n buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));\n\n if (end !== start) {\n deleteSelection(widget);\n }\n};\n\nconst applyEditableSelection = (widget: Gtk.Editable, start: number, end: number): void => {\n widget.selectRegion(start, end);\n\n if (end !== start) {\n widget.deleteSelection();\n }\n\n widget.setPosition(start);\n};\n\nconst applyInitialSelection = (widget: EditableTarget, options: TypeOptions): void => {\n if (options.initialSelectionStart === undefined) {\n return;\n }\n\n const start = options.initialSelectionStart;\n const end = options.initialSelectionEnd ?? start;\n\n if (widget instanceof Gtk.TextView) {\n applyTextViewSelection(widget, start, end);\n\n return;\n }\n\n applyEditableSelection(widget, start, end);\n};\n\nconst writeClipboardText = (widget: Gtk.Widget, text: string): void => {\n const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {\n v.setString(text);\n });\n\n widget.getClipboard().set(value);\n};\n\nconst resetClipboard = (): void => {\n Gdk.Display.getDefault()?.getClipboard().setContent(null);\n};\n\nconst runEditableEvent = (\n widget: Gtk.Widget,\n failure: string,\n action: (editable: EditableTarget) => void,\n): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`${failure}: ${EDITABLE_REQUIRED}`);\n }\n\n action(widget);\n });\n\nconst type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>\n runEditableEvent(widget, \"Cannot type into element\", (editable) => {\n if (!options?.skipClick) {\n editable.grabFocus();\n }\n\n applyInitialSelection(editable, options ?? {});\n insertEditableText(editable, text);\n });\n\nconst clear = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot clear element\", (editable) => {\n setEditableText(editable, \"\");\n });\n\nconst copy = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot copy\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n });\n\nconst cut = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot cut\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n deleteSelection(editable);\n });\n\nconst paste = async (widget: Gtk.Widget, text?: string): Promise<void> => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);\n }\n\n const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? \"\";\n\n await wrapEvent(widget, () => {\n insertEditableText(widget, content);\n });\n};\n\nexport { resetClipboard, type, clear, copy, cut, paste, type TypeOptions };\n"]}
|