@gtkx/testing 0.20.0 → 1.0.0-rc.1
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 +122 -55
- package/dist/act.d.ts +19 -0
- package/dist/act.d.ts.map +1 -0
- package/dist/act.js +48 -0
- package/dist/act.js.map +1 -0
- package/dist/bound-queries.d.ts +32 -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 +103 -0
- package/dist/build-queries.js.map +1 -0
- package/dist/cleanup-registry.d.ts +4 -0
- package/dist/cleanup-registry.d.ts.map +1 -0
- package/dist/cleanup-registry.js +11 -0
- package/dist/cleanup-registry.js.map +1 -0
- package/dist/config.d.ts +18 -51
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -40
- package/dist/config.js.map +1 -1
- package/dist/editable.d.ts +7 -0
- package/dist/editable.d.ts.map +1 -0
- package/dist/editable.js +24 -0
- package/dist/editable.js.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +119 -0
- package/dist/errors.js.map +1 -0
- package/dist/fire-event.d.ts +7 -25
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +9 -29
- package/dist/fire-event.js.map +1 -1
- package/dist/frame-sync.d.ts +3 -0
- package/dist/frame-sync.d.ts.map +1 -0
- package/dist/frame-sync.js +30 -0
- package/dist/frame-sync.js.map +1 -0
- package/dist/index.d.ts +16 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -6
- package/dist/index.js.map +1 -1
- package/dist/matchers.d.ts +55 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/matchers.js +103 -0
- package/dist/matchers.js.map +1 -0
- package/dist/pretty-widget.d.ts +21 -25
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +69 -115
- package/dist/pretty-widget.js.map +1 -1
- package/dist/queries.d.ts +130 -177
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +212 -325
- 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 +15 -0
- package/dist/register-test-hooks.js.map +1 -0
- package/dist/render-hook.d.ts +14 -35
- package/dist/render-hook.d.ts.map +1 -1
- package/dist/render-hook.js +8 -45
- package/dist/render-hook.js.map +1 -1
- package/dist/render.d.ts +11 -41
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +129 -118
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts +16 -51
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +39 -58
- package/dist/role-helpers.js.map +1 -1
- package/dist/screen.d.ts +6 -63
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +21 -109
- package/dist/screen.js.map +1 -1
- package/dist/screenshot.d.ts +20 -23
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +89 -48
- package/dist/screenshot.js.map +1 -1
- package/dist/suggestions.d.ts +22 -0
- package/dist/suggestions.d.ts.map +1 -0
- package/dist/suggestions.js +56 -0
- package/dist/suggestions.js.map +1 -0
- package/dist/traversal.d.ts +10 -8
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +28 -13
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +103 -172
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +8 -0
- package/dist/user-event/adjustment.d.ts.map +1 -0
- package/dist/user-event/adjustment.js +33 -0
- package/dist/user-event/adjustment.js.map +1 -0
- package/dist/user-event/click.d.ts +7 -0
- package/dist/user-event/click.d.ts.map +1 -0
- package/dist/user-event/click.js +65 -0
- package/dist/user-event/click.js.map +1 -0
- package/dist/user-event/controller.d.ts +7 -0
- package/dist/user-event/controller.d.ts.map +1 -0
- package/dist/user-event/controller.js +28 -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 +10 -0
- package/dist/user-event/dispatch.js.map +1 -0
- package/dist/user-event/event-wrapper.d.ts +3 -0
- package/dist/user-event/event-wrapper.d.ts.map +1 -0
- package/dist/user-event/event-wrapper.js +48 -0
- package/dist/user-event/event-wrapper.js.map +1 -0
- package/dist/user-event/gesture.d.ts +31 -0
- package/dist/user-event/gesture.d.ts.map +1 -0
- package/dist/user-event/gesture.js +105 -0
- package/dist/user-event/gesture.js.map +1 -0
- package/dist/user-event/index.d.ts +44 -0
- package/dist/user-event/index.d.ts.map +1 -0
- package/dist/user-event/index.js +38 -0
- package/dist/user-event/index.js.map +1 -0
- package/dist/user-event/keyboard.d.ts +9 -0
- package/dist/user-event/keyboard.d.ts.map +1 -0
- package/dist/user-event/keyboard.js +173 -0
- package/dist/user-event/keyboard.js.map +1 -0
- package/dist/user-event/pointer.d.ts +6 -0
- package/dist/user-event/pointer.d.ts.map +1 -0
- package/dist/user-event/pointer.js +27 -0
- package/dist/user-event/pointer.js.map +1 -0
- package/dist/user-event/selection.d.ts +4 -0
- package/dist/user-event/selection.d.ts.map +1 -0
- package/dist/user-event/selection.js +106 -0
- package/dist/user-event/selection.js.map +1 -0
- package/dist/user-event/state.d.ts +6 -0
- package/dist/user-event/state.d.ts.map +1 -0
- package/dist/user-event/state.js +2 -0
- package/dist/user-event/state.js.map +1 -0
- package/dist/user-event/text.d.ts +17 -0
- package/dist/user-event/text.d.ts.map +1 -0
- package/dist/user-event/text.js +107 -0
- package/dist/user-event/text.js.map +1 -0
- package/dist/wait-for.d.ts +13 -32
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +62 -73
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts +33 -0
- package/dist/widget-accessible-properties.d.ts.map +1 -0
- package/dist/widget-accessible-properties.js +215 -0
- package/dist/widget-accessible-properties.js.map +1 -0
- package/dist/within.d.ts +9 -26
- package/dist/within.d.ts.map +1 -1
- package/dist/within.js +15 -25
- package/dist/within.js.map +1 -1
- package/package.json +21 -12
- package/src/act.ts +68 -0
- package/src/bound-queries.ts +36 -0
- package/src/build-queries.ts +185 -0
- package/src/cleanup-registry.ts +14 -0
- package/src/config.ts +28 -59
- package/src/editable.ts +30 -0
- package/src/errors.ts +130 -0
- package/src/fire-event.ts +11 -38
- package/src/frame-sync.ts +34 -0
- package/src/index.ts +60 -18
- package/src/matchers.ts +200 -0
- package/src/pretty-widget.ts +99 -138
- package/src/queries.ts +321 -425
- package/src/register-test-hooks.ts +16 -0
- package/src/render-hook.tsx +31 -44
- package/src/render.tsx +161 -149
- package/src/role-helpers.ts +47 -67
- package/src/screen.ts +21 -114
- package/src/screenshot.ts +104 -55
- package/src/suggestions.ts +87 -0
- package/src/traversal.ts +32 -18
- package/src/types.ts +115 -176
- package/src/user-event/adjustment.ts +49 -0
- package/src/user-event/click.ts +70 -0
- package/src/user-event/controller.ts +44 -0
- package/src/user-event/dispatch.ts +23 -0
- package/src/user-event/event-wrapper.ts +54 -0
- package/src/user-event/gesture.ts +154 -0
- package/src/user-event/index.ts +74 -0
- package/src/user-event/keyboard.ts +204 -0
- package/src/user-event/pointer.ts +34 -0
- package/src/user-event/selection.ts +122 -0
- package/src/user-event/state.ts +6 -0
- package/src/user-event/text.ts +137 -0
- package/src/wait-for.ts +79 -80
- package/src/widget-accessible-properties.ts +244 -0
- package/src/within.ts +26 -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,48 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import { runInAct } from "../act.js";
|
|
3
|
+
import { getConfig } from "../config.js";
|
|
4
|
+
import { formatRole } from "../role-helpers.js";
|
|
5
|
+
const NOT_SENSITIVE = "it is not sensitive (the widget or one of its ancestors is disabled)";
|
|
6
|
+
const WINDOW_NOT_ALLOCATED = "its window has not been allocated a size";
|
|
7
|
+
const NOT_MAPPED = "it is not mapped (it is not shown on screen, e.g. it is hidden or on a non-visible page)";
|
|
8
|
+
const WINDOW_NOT_ACTIVE = "its window never became active";
|
|
9
|
+
const actionableHop = () => new Promise((resolve) => setTimeout(resolve, 1));
|
|
10
|
+
const displayDeliversActivation = (window) => window.getDisplay().getDefaultSeat() !== null;
|
|
11
|
+
const findActionabilityFailure = (widget) => {
|
|
12
|
+
if (!widget.isSensitive())
|
|
13
|
+
return NOT_SENSITIVE;
|
|
14
|
+
const root = widget.getRoot();
|
|
15
|
+
if (!(root instanceof Gtk.Window) || !root.getVisible())
|
|
16
|
+
return null;
|
|
17
|
+
if (root.getAllocatedWidth() === 0)
|
|
18
|
+
return WINDOW_NOT_ALLOCATED;
|
|
19
|
+
if (!widget.getMapped())
|
|
20
|
+
return NOT_MAPPED;
|
|
21
|
+
if (displayDeliversActivation(root) && !root.isActive())
|
|
22
|
+
return WINDOW_NOT_ACTIVE;
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
const describeWidget = (widget) => {
|
|
26
|
+
const tag = widget.constructor.name;
|
|
27
|
+
const name = widget.getName();
|
|
28
|
+
const nameAttribute = name && !name.endsWith(tag) ? ` name="${name}"` : "";
|
|
29
|
+
return `<${tag}${nameAttribute} role="${formatRole(widget.getAccessibleRole())}">`;
|
|
30
|
+
};
|
|
31
|
+
const waitForActionable = async (widget) => {
|
|
32
|
+
const timeout = getConfig().actionabilityTimeout;
|
|
33
|
+
const deadline = Date.now() + timeout;
|
|
34
|
+
let failure = findActionabilityFailure(widget);
|
|
35
|
+
while (failure !== null && Date.now() < deadline) {
|
|
36
|
+
await actionableHop();
|
|
37
|
+
failure = findActionabilityFailure(widget);
|
|
38
|
+
}
|
|
39
|
+
if (failure !== null) {
|
|
40
|
+
throw new Error(`Cannot dispatch user event: ${describeWidget(widget)} did not become actionable within ${timeout}ms because ${failure}`);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export const wrapEvent = (widget, body) => Promise.resolve()
|
|
44
|
+
.then(() => waitForActionable(widget))
|
|
45
|
+
.then(() => runInAct(async () => {
|
|
46
|
+
await body();
|
|
47
|
+
}));
|
|
48
|
+
//# sourceMappingURL=event-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-wrapper.js","sourceRoot":"","sources":["../../src/user-event/event-wrapper.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { runInAct } from \"../act.js\";\nimport { getConfig } from \"../config.js\";\nimport { formatRole } from \"../role-helpers.js\";\n\nconst NOT_SENSITIVE = \"it is not sensitive (the widget or one of its ancestors is disabled)\";\nconst WINDOW_NOT_ALLOCATED = \"its window has not been allocated a size\";\nconst NOT_MAPPED = \"it is not mapped (it is not shown on screen, e.g. it is hidden or on a non-visible page)\";\nconst WINDOW_NOT_ACTIVE = \"its window never became active\";\n\nconst actionableHop = (): Promise<void> => new Promise((resolve) => setTimeout(resolve, 1));\n\nconst displayDeliversActivation = (window: Gtk.Window): boolean => window.getDisplay().getDefaultSeat() !== null;\n\nconst findActionabilityFailure = (widget: Gtk.Widget): string | null => {\n if (!widget.isSensitive()) return NOT_SENSITIVE;\n const root = widget.getRoot();\n if (!(root instanceof Gtk.Window) || !root.getVisible()) return null;\n if (root.getAllocatedWidth() === 0) return WINDOW_NOT_ALLOCATED;\n if (!widget.getMapped()) return NOT_MAPPED;\n if (displayDeliversActivation(root) && !root.isActive()) return WINDOW_NOT_ACTIVE;\n return null;\n};\n\nconst describeWidget = (widget: Gtk.Widget): string => {\n const tag = widget.constructor.name;\n const name = widget.getName();\n const nameAttribute = name && !name.endsWith(tag) ? ` name=\"${name}\"` : \"\";\n return `<${tag}${nameAttribute} role=\"${formatRole(widget.getAccessibleRole())}\">`;\n};\n\nconst waitForActionable = async (widget: Gtk.Widget): Promise<void> => {\n const timeout = getConfig().actionabilityTimeout;\n const deadline = Date.now() + timeout;\n let failure = findActionabilityFailure(widget);\n while (failure !== null && Date.now() < deadline) {\n await actionableHop();\n failure = findActionabilityFailure(widget);\n }\n if (failure !== null) {\n throw new Error(\n `Cannot dispatch user event: ${describeWidget(widget)} did not become actionable within ${timeout}ms because ${failure}`,\n );\n }\n};\n\nexport const wrapEvent = (widget: Gtk.Widget, body: () => void | PromiseLike<void>): Promise<void> =>\n Promise.resolve()\n .then(() => waitForActionable(widget))\n .then(() =>\n runInAct(async () => {\n await body();\n }),\n );\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as GObject from "@gtkx/gi/gobject";
|
|
2
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
+
/** The value delivered to a drop target: a primitive (converted to a GObject.Value) or an explicit GObject.Value. */
|
|
4
|
+
export type DropContent = string | number | boolean | GObject.Value;
|
|
5
|
+
/** Options for a drop: the drop coordinates within the target. */
|
|
6
|
+
export type DropOptions = {
|
|
7
|
+
x?: number;
|
|
8
|
+
y?: number;
|
|
9
|
+
};
|
|
10
|
+
/** A drag offset relative to the drag start point. */
|
|
11
|
+
export type DragOffset = {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
/** Options for a drag gesture: the starting point, the number of interpolated drag updates, or explicit intermediate offsets emitted before the final one. */
|
|
16
|
+
export type DragOptions = {
|
|
17
|
+
startX?: number;
|
|
18
|
+
startY?: number;
|
|
19
|
+
steps?: number;
|
|
20
|
+
offsets?: DragOffset[];
|
|
21
|
+
};
|
|
22
|
+
export declare const hover: (widget: Gtk.Widget) => Promise<void>;
|
|
23
|
+
export declare const unhover: (widget: Gtk.Widget) => Promise<void>;
|
|
24
|
+
export declare const rotate: (widget: Gtk.Widget, angle: number, deltaAngle?: number) => Promise<void>;
|
|
25
|
+
export declare const zoom: (widget: Gtk.Widget, scale: number) => Promise<void>;
|
|
26
|
+
export declare const swipe: (widget: Gtk.Widget, velocityX: number, velocityY: number) => Promise<void>;
|
|
27
|
+
export declare const longPress: (widget: Gtk.Widget, x?: number, y?: number) => Promise<void>;
|
|
28
|
+
export declare const drag: (widget: Gtk.Widget, dx: number, dy: number, options?: DragOptions) => Promise<void>;
|
|
29
|
+
export declare const drop: (widget: Gtk.Widget, content: DropContent, options?: DropOptions) => Promise<void>;
|
|
30
|
+
export declare const dragAndDrop: (source: Gtk.Widget, target: Gtk.Widget, content: DropContent, options?: DropOptions) => Promise<void>;
|
|
31
|
+
//# sourceMappingURL=gesture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture.d.ts","sourceRoot":"","sources":["../../src/user-event/gesture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAKpC,qHAAqH;AACrH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;AAEpE,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG;IACtB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,8JAA8J;AAC9J,MAAM,MAAM,WAAW,GAAG;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAaF,eAAO,MAAM,KAAK,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAC6D,CAAC;AAErH,eAAO,MAAM,OAAO,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CACqD,CAAC;AAE/G,eAAO,MAAM,MAAM,WAAY,GAAG,CAAC,MAAM,SAAS,MAAM,eAAc,MAAM,KAAW,OAAO,CAAC,IAAI,CAG9F,CAAC;AAEN,eAAO,MAAM,IAAI,WAAY,GAAG,CAAC,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CACsC,CAAC;AAE5G,eAAO,MAAM,KAAK,WAAY,GAAG,CAAC,MAAM,aAAa,MAAM,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CACsB,CAAC;AAEpH,eAAO,MAAM,SAAS,WAAY,GAAG,CAAC,MAAM,MAAK,MAAM,MAAS,MAAM,KAAO,OAAO,CAAC,IAAI,CACgB,CAAC;AAyD1G,eAAO,MAAM,IAAI,WAAkB,GAAG,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,YAAW,WAAW,KAAQ,OAAO,CAAC,IAAI,CAY9G,CAAC;AASF,eAAO,MAAM,IAAI,WAAY,GAAG,CAAC,MAAM,WAAW,WAAW,YAAW,WAAW,KAAQ,OAAO,CAAC,IAAI,CAGjG,CAAC;AAEP,eAAO,MAAM,WAAW,WACZ,GAAG,CAAC,MAAM,UACV,GAAG,CAAC,MAAM,WACT,WAAW,YACX,WAAW,KACrB,OAAO,CAAC,IAAI,CAOd,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as GObject from "@gtkx/gi/gobject";
|
|
2
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
+
import { getAllControllers } from "./controller.js";
|
|
4
|
+
import { dispatchOnControllers, dispatchOnOrCreateControllers } from "./dispatch.js";
|
|
5
|
+
import { wrapEvent } from "./event-wrapper.js";
|
|
6
|
+
const buildDropValue = (content) => {
|
|
7
|
+
if (content instanceof GObject.Value)
|
|
8
|
+
return content;
|
|
9
|
+
if (typeof content === "string") {
|
|
10
|
+
return GObject.buildValue(GObject.TYPE_STRING, (v) => v.setString(content));
|
|
11
|
+
}
|
|
12
|
+
if (typeof content === "boolean") {
|
|
13
|
+
return GObject.buildValue(GObject.TYPE_BOOLEAN, (v) => v.setBoolean(content));
|
|
14
|
+
}
|
|
15
|
+
return GObject.buildValue(GObject.TYPE_DOUBLE, (v) => v.setDouble(content));
|
|
16
|
+
};
|
|
17
|
+
export const hover = (widget) => dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => controller.emit("enter", 0, 0));
|
|
18
|
+
export const unhover = (widget) => dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => controller.emit("leave"));
|
|
19
|
+
export const rotate = (widget, angle, deltaAngle = angle) => dispatchOnControllers(widget, Gtk.GestureRotate, (controller) => controller.emit("angle-changed", angle, deltaAngle));
|
|
20
|
+
export const zoom = (widget, scale) => dispatchOnControllers(widget, Gtk.GestureZoom, (controller) => controller.emit("scale-changed", scale));
|
|
21
|
+
export const swipe = (widget, velocityX, velocityY) => dispatchOnControllers(widget, Gtk.GestureSwipe, (controller) => controller.emit("swipe", velocityX, velocityY));
|
|
22
|
+
export const longPress = (widget, x = 0, y = 0) => dispatchOnControllers(widget, Gtk.GestureLongPress, (controller) => controller.emit("pressed", x, y));
|
|
23
|
+
const patchDragState = (controller, start, offset) => {
|
|
24
|
+
const instance = controller;
|
|
25
|
+
const ownsStartPoint = Object.hasOwn(instance, "getStartPoint");
|
|
26
|
+
const ownsOffset = Object.hasOwn(instance, "getOffset");
|
|
27
|
+
const previousStartPoint = instance.getStartPoint;
|
|
28
|
+
const previousOffset = instance.getOffset;
|
|
29
|
+
instance.getStartPoint = () => [true, start.x, start.y];
|
|
30
|
+
instance.getOffset = () => {
|
|
31
|
+
const current = offset();
|
|
32
|
+
return [true, current.x, current.y];
|
|
33
|
+
};
|
|
34
|
+
return () => {
|
|
35
|
+
if (ownsStartPoint)
|
|
36
|
+
instance.getStartPoint = previousStartPoint;
|
|
37
|
+
else
|
|
38
|
+
delete instance.getStartPoint;
|
|
39
|
+
if (ownsOffset)
|
|
40
|
+
instance.getOffset = previousOffset;
|
|
41
|
+
else
|
|
42
|
+
delete instance.getOffset;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const runDragSequence = (controllers, start, updates) => {
|
|
46
|
+
let current = { x: 0, y: 0 };
|
|
47
|
+
const restores = controllers.map((controller) => patchDragState(controller, start, () => current));
|
|
48
|
+
try {
|
|
49
|
+
for (const controller of controllers) {
|
|
50
|
+
controller.emit("drag-begin", start.x, start.y);
|
|
51
|
+
}
|
|
52
|
+
for (const update of updates) {
|
|
53
|
+
current = update;
|
|
54
|
+
for (const controller of controllers) {
|
|
55
|
+
controller.emit("drag-update", update.x, update.y);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const controller of controllers) {
|
|
59
|
+
controller.emit("drag-end", current.x, current.y);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
for (const restore of restores)
|
|
64
|
+
restore();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const resolveDragUpdates = (dx, dy, options) => {
|
|
68
|
+
if (options.offsets)
|
|
69
|
+
return [...options.offsets, { x: dx, y: dy }];
|
|
70
|
+
const steps = Math.max(1, Math.floor(options.steps ?? 2));
|
|
71
|
+
const updates = [];
|
|
72
|
+
for (let i = 1; i <= steps; i++) {
|
|
73
|
+
updates.push({ x: (dx * i) / steps, y: (dy * i) / steps });
|
|
74
|
+
}
|
|
75
|
+
return updates;
|
|
76
|
+
};
|
|
77
|
+
export const drag = async (widget, dx, dy, options = {}) => {
|
|
78
|
+
if (widget instanceof Gtk.Range) {
|
|
79
|
+
throw new Error("userEvent.drag cannot drive a Gtk.Range's built-in slider (its drag reads pointer coordinates from the display); " +
|
|
80
|
+
"use userEvent.slide(range, value) or userEvent.keyboard for sliders");
|
|
81
|
+
}
|
|
82
|
+
const start = { x: options.startX ?? 0, y: options.startY ?? 0 };
|
|
83
|
+
const updates = resolveDragUpdates(dx, dy, options);
|
|
84
|
+
await wrapEvent(widget, () => {
|
|
85
|
+
runDragSequence(getAllControllers(widget, Gtk.GestureDrag), start, updates);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const emitDrop = (target, content, options) => {
|
|
89
|
+
const dropTargets = getAllControllers(target, Gtk.DropTarget);
|
|
90
|
+
for (const dropTarget of dropTargets) {
|
|
91
|
+
dropTarget.emit("drop", buildDropValue(content), options.x ?? 0, options.y ?? 0);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
export const drop = (widget, content, options = {}) => wrapEvent(widget, () => {
|
|
95
|
+
emitDrop(widget, content, options);
|
|
96
|
+
});
|
|
97
|
+
export const dragAndDrop = async (source, target, content, options = {}) => {
|
|
98
|
+
await wrapEvent(source, () => {
|
|
99
|
+
getAllControllers(source, Gtk.DragSource);
|
|
100
|
+
});
|
|
101
|
+
await wrapEvent(target, () => {
|
|
102
|
+
emitDrop(target, content, options);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=gesture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture.js","sourceRoot":"","sources":["../../src/user-event/gesture.ts"],"names":[],"mappings":"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","sourcesContent":["import * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { getAllControllers } from \"./controller.js\";\nimport { dispatchOnControllers, dispatchOnOrCreateControllers } from \"./dispatch.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\n/** The value delivered to a drop target: a primitive (converted to a GObject.Value) or an explicit GObject.Value. */\nexport type DropContent = string | number | boolean | GObject.Value;\n\n/** Options for a drop: the drop coordinates within the target. */\nexport type DropOptions = {\n x?: number;\n y?: number;\n};\n\n/** A drag offset relative to the drag start point. */\nexport type DragOffset = {\n x: number;\n y: number;\n};\n\n/** Options for a drag gesture: the starting point, the number of interpolated drag updates, or explicit intermediate offsets emitted before the final one. */\nexport type DragOptions = {\n startX?: number;\n startY?: number;\n steps?: number;\n offsets?: DragOffset[];\n};\n\nconst buildDropValue = (content: DropContent): GObject.Value => {\n if (content instanceof GObject.Value) return content;\n if (typeof content === \"string\") {\n return GObject.buildValue(GObject.TYPE_STRING, (v) => v.setString(content));\n }\n if (typeof content === \"boolean\") {\n return GObject.buildValue(GObject.TYPE_BOOLEAN, (v) => v.setBoolean(content));\n }\n return GObject.buildValue(GObject.TYPE_DOUBLE, (v) => v.setDouble(content));\n};\n\nexport const hover = (widget: Gtk.Widget): Promise<void> =>\n dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => controller.emit(\"enter\", 0, 0));\n\nexport const unhover = (widget: Gtk.Widget): Promise<void> =>\n dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => controller.emit(\"leave\"));\n\nexport const rotate = (widget: Gtk.Widget, angle: number, deltaAngle: number = angle): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureRotate, (controller) =>\n controller.emit(\"angle-changed\", angle, deltaAngle),\n );\n\nexport const zoom = (widget: Gtk.Widget, scale: number): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureZoom, (controller) => controller.emit(\"scale-changed\", scale));\n\nexport const swipe = (widget: Gtk.Widget, velocityX: number, velocityY: number): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureSwipe, (controller) => controller.emit(\"swipe\", velocityX, velocityY));\n\nexport const longPress = (widget: Gtk.Widget, x: number = 0, y: number = 0): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureLongPress, (controller) => controller.emit(\"pressed\", x, y));\n\ntype DragInstancePatch = {\n getStartPoint?: Gtk.GestureDrag[\"getStartPoint\"] | undefined;\n getOffset?: Gtk.GestureDrag[\"getOffset\"] | undefined;\n};\n\nconst patchDragState = (controller: Gtk.GestureDrag, start: DragOffset, offset: () => DragOffset): (() => void) => {\n const instance: DragInstancePatch = controller;\n const ownsStartPoint = Object.hasOwn(instance, \"getStartPoint\");\n const ownsOffset = Object.hasOwn(instance, \"getOffset\");\n const previousStartPoint = instance.getStartPoint;\n const previousOffset = instance.getOffset;\n instance.getStartPoint = () => [true, start.x, start.y];\n instance.getOffset = () => {\n const current = offset();\n return [true, current.x, current.y];\n };\n return () => {\n if (ownsStartPoint) instance.getStartPoint = previousStartPoint;\n else delete instance.getStartPoint;\n if (ownsOffset) instance.getOffset = previousOffset;\n else delete instance.getOffset;\n };\n};\n\nconst runDragSequence = (controllers: Gtk.GestureDrag[], start: DragOffset, updates: DragOffset[]): void => {\n let current: DragOffset = { x: 0, y: 0 };\n const restores = controllers.map((controller) => patchDragState(controller, start, () => current));\n try {\n for (const controller of controllers) {\n controller.emit(\"drag-begin\", start.x, start.y);\n }\n for (const update of updates) {\n current = update;\n for (const controller of controllers) {\n controller.emit(\"drag-update\", update.x, update.y);\n }\n }\n for (const controller of controllers) {\n controller.emit(\"drag-end\", current.x, current.y);\n }\n } finally {\n for (const restore of restores) restore();\n }\n};\n\nconst resolveDragUpdates = (dx: number, dy: number, options: DragOptions): DragOffset[] => {\n if (options.offsets) return [...options.offsets, { x: dx, y: dy }];\n const steps = Math.max(1, Math.floor(options.steps ?? 2));\n const updates: DragOffset[] = [];\n for (let i = 1; i <= steps; i++) {\n updates.push({ x: (dx * i) / steps, y: (dy * i) / steps });\n }\n return updates;\n};\n\nexport const drag = async (widget: Gtk.Widget, dx: number, dy: number, options: DragOptions = {}): Promise<void> => {\n if (widget instanceof Gtk.Range) {\n throw new Error(\n \"userEvent.drag cannot drive a Gtk.Range's built-in slider (its drag reads pointer coordinates from the display); \" +\n \"use userEvent.slide(range, value) or userEvent.keyboard for sliders\",\n );\n }\n const start = { x: options.startX ?? 0, y: options.startY ?? 0 };\n const updates = resolveDragUpdates(dx, dy, options);\n await wrapEvent(widget, () => {\n runDragSequence(getAllControllers(widget, Gtk.GestureDrag), start, updates);\n });\n};\n\nconst emitDrop = (target: Gtk.Widget, content: DropContent, options: DropOptions): void => {\n const dropTargets = getAllControllers(target, Gtk.DropTarget);\n for (const dropTarget of dropTargets) {\n dropTarget.emit(\"drop\", buildDropValue(content), options.x ?? 0, options.y ?? 0);\n }\n};\n\nexport const drop = (widget: Gtk.Widget, content: DropContent, options: DropOptions = {}): Promise<void> =>\n wrapEvent(widget, () => {\n emitDrop(widget, content, options);\n });\n\nexport const dragAndDrop = async (\n source: Gtk.Widget,\n target: Gtk.Widget,\n content: DropContent,\n options: DropOptions = {},\n): Promise<void> => {\n await wrapEvent(source, () => {\n getAllControllers(source, Gtk.DragSource);\n });\n await wrapEvent(target, () => {\n emitDrop(target, content, options);\n });\n};\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import { scroll, slide } from "./adjustment.js";
|
|
3
|
+
import { click, dblClick, tripleClick } from "./click.js";
|
|
4
|
+
import { drag, dragAndDrop, drop, hover, longPress, rotate, swipe, unhover, zoom } from "./gesture.js";
|
|
5
|
+
import { tab } from "./keyboard.js";
|
|
6
|
+
import { type PointerInput } from "./pointer.js";
|
|
7
|
+
import { deselectOptions, selectOptions } from "./selection.js";
|
|
8
|
+
import { clear, copy, cut, paste, type } from "./text.js";
|
|
9
|
+
export type { ScrollDelta } from "./adjustment.js";
|
|
10
|
+
export type { DragOffset, DragOptions, DropContent, DropOptions } from "./gesture.js";
|
|
11
|
+
export type { TabOptions } from "./keyboard.js";
|
|
12
|
+
export type { PointerInput } from "./pointer.js";
|
|
13
|
+
export type { TypeOptions } from "./text.js";
|
|
14
|
+
export { resetClipboard } from "./text.js";
|
|
15
|
+
/** The set of user interaction helpers exposed by {@link userEvent}, covering clicks, typing, keyboard, pointer, gestures, selection, and scrolling. */
|
|
16
|
+
export type UserEvent = {
|
|
17
|
+
click: typeof click;
|
|
18
|
+
dblClick: typeof dblClick;
|
|
19
|
+
tripleClick: typeof tripleClick;
|
|
20
|
+
tab: typeof tab;
|
|
21
|
+
type: typeof type;
|
|
22
|
+
clear: typeof clear;
|
|
23
|
+
copy: typeof copy;
|
|
24
|
+
cut: typeof cut;
|
|
25
|
+
paste: typeof paste;
|
|
26
|
+
selectOptions: typeof selectOptions;
|
|
27
|
+
deselectOptions: typeof deselectOptions;
|
|
28
|
+
hover: typeof hover;
|
|
29
|
+
unhover: typeof unhover;
|
|
30
|
+
rotate: typeof rotate;
|
|
31
|
+
zoom: typeof zoom;
|
|
32
|
+
swipe: typeof swipe;
|
|
33
|
+
longPress: typeof longPress;
|
|
34
|
+
drag: typeof drag;
|
|
35
|
+
drop: typeof drop;
|
|
36
|
+
dragAndDrop: typeof dragAndDrop;
|
|
37
|
+
slide: typeof slide;
|
|
38
|
+
scroll: typeof scroll;
|
|
39
|
+
keyboard: (widget: Gtk.Widget, input: string) => Promise<void>;
|
|
40
|
+
pointer: (widget: Gtk.Widget, input: PointerInput) => Promise<void>;
|
|
41
|
+
};
|
|
42
|
+
/** High-level helpers that drive widgets by dispatching the same events and gestures GTK4 delivers when someone clicks, types, or drags. */
|
|
43
|
+
export declare const userEvent: UserEvent;
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/user-event/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EAAY,GAAG,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,KAAK,YAAY,EAAW,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1D,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtF,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,wJAAwJ;AACxJ,MAAM,MAAM,SAAS,GAAG;IACpB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,GAAG,EAAE,OAAO,GAAG,CAAC;IAChB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,GAAG,EAAE,OAAO,GAAG,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,eAAe,EAAE,OAAO,eAAe,CAAC;IACxC,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE,CAAC;AAIF,4IAA4I;AAC5I,eAAO,MAAM,SAAS,EAAE,SAyBvB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { scroll, slide } from "./adjustment.js";
|
|
2
|
+
import { click, dblClick, tripleClick } from "./click.js";
|
|
3
|
+
import { drag, dragAndDrop, drop, hover, longPress, rotate, swipe, unhover, zoom } from "./gesture.js";
|
|
4
|
+
import { keyboard, tab } from "./keyboard.js";
|
|
5
|
+
import { pointer } from "./pointer.js";
|
|
6
|
+
import { deselectOptions, selectOptions } from "./selection.js";
|
|
7
|
+
import { createInitialState } from "./state.js";
|
|
8
|
+
import { clear, copy, cut, paste, type } from "./text.js";
|
|
9
|
+
export { resetClipboard } from "./text.js";
|
|
10
|
+
const state = createInitialState();
|
|
11
|
+
/** High-level helpers that drive widgets by dispatching the same events and gestures GTK4 delivers when someone clicks, types, or drags. */
|
|
12
|
+
export const userEvent = {
|
|
13
|
+
click,
|
|
14
|
+
dblClick,
|
|
15
|
+
tripleClick,
|
|
16
|
+
tab,
|
|
17
|
+
type,
|
|
18
|
+
clear,
|
|
19
|
+
copy,
|
|
20
|
+
cut,
|
|
21
|
+
paste,
|
|
22
|
+
selectOptions,
|
|
23
|
+
deselectOptions,
|
|
24
|
+
hover,
|
|
25
|
+
unhover,
|
|
26
|
+
rotate,
|
|
27
|
+
zoom,
|
|
28
|
+
swipe,
|
|
29
|
+
longPress,
|
|
30
|
+
drag,
|
|
31
|
+
drop,
|
|
32
|
+
dragAndDrop,
|
|
33
|
+
slide,
|
|
34
|
+
scroll,
|
|
35
|
+
keyboard: (widget, input) => keyboard(state, widget, input),
|
|
36
|
+
pointer: (widget, input) => pointer(state, widget, input),
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/user-event/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAqB,OAAO,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAO1D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA8B3C,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;AAEnC,4IAA4I;AAC5I,MAAM,CAAC,MAAM,SAAS,GAAc;IAChC,KAAK;IACL,QAAQ;IACR,WAAW;IACX,GAAG;IACH,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,GAAG;IACH,KAAK;IACL,aAAa;IACb,eAAe;IACf,KAAK;IACL,OAAO;IACP,MAAM;IACN,IAAI;IACJ,KAAK;IACL,SAAS;IACT,IAAI;IACJ,IAAI;IACJ,WAAW;IACX,KAAK;IACL,MAAM;IACN,QAAQ,EAAE,CAAC,MAAkB,EAAE,KAAa,EAAiB,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC;IAC9F,OAAO,EAAE,CAAC,MAAkB,EAAE,KAAmB,EAAiB,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC;CACrG,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { scroll, slide } from \"./adjustment.js\";\nimport { click, dblClick, tripleClick } from \"./click.js\";\nimport { drag, dragAndDrop, drop, hover, longPress, rotate, swipe, unhover, zoom } from \"./gesture.js\";\nimport { keyboard, tab } from \"./keyboard.js\";\nimport { type PointerInput, pointer } from \"./pointer.js\";\nimport { deselectOptions, selectOptions } from \"./selection.js\";\nimport { createInitialState } from \"./state.js\";\nimport { clear, copy, cut, paste, type } from \"./text.js\";\n\nexport type { ScrollDelta } from \"./adjustment.js\";\nexport type { DragOffset, DragOptions, DropContent, DropOptions } from \"./gesture.js\";\nexport type { TabOptions } from \"./keyboard.js\";\nexport type { PointerInput } from \"./pointer.js\";\nexport type { TypeOptions } from \"./text.js\";\nexport { resetClipboard } from \"./text.js\";\n\n/** The set of user interaction helpers exposed by {@link userEvent}, covering clicks, typing, keyboard, pointer, gestures, selection, and scrolling. */\nexport type UserEvent = {\n click: typeof click;\n dblClick: typeof dblClick;\n tripleClick: typeof tripleClick;\n tab: typeof tab;\n type: typeof type;\n clear: typeof clear;\n copy: typeof copy;\n cut: typeof cut;\n paste: typeof paste;\n selectOptions: typeof selectOptions;\n deselectOptions: typeof deselectOptions;\n hover: typeof hover;\n unhover: typeof unhover;\n rotate: typeof rotate;\n zoom: typeof zoom;\n swipe: typeof swipe;\n longPress: typeof longPress;\n drag: typeof drag;\n drop: typeof drop;\n dragAndDrop: typeof dragAndDrop;\n slide: typeof slide;\n scroll: typeof scroll;\n keyboard: (widget: Gtk.Widget, input: string) => Promise<void>;\n pointer: (widget: Gtk.Widget, input: PointerInput) => Promise<void>;\n};\n\nconst state = createInitialState();\n\n/** High-level helpers that drive widgets by dispatching the same events and gestures GTK4 delivers when someone clicks, types, or drags. */\nexport const userEvent: UserEvent = {\n click,\n dblClick,\n tripleClick,\n tab,\n type,\n clear,\n copy,\n cut,\n paste,\n selectOptions,\n deselectOptions,\n hover,\n unhover,\n rotate,\n zoom,\n swipe,\n longPress,\n drag,\n drop,\n dragAndDrop,\n slide,\n scroll,\n keyboard: (widget: Gtk.Widget, input: string): Promise<void> => keyboard(state, widget, input),\n pointer: (widget: Gtk.Widget, input: PointerInput): Promise<void> => pointer(state, widget, input),\n};\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import type { UserEventState } from "./state.js";
|
|
3
|
+
/** Options for {@link tab}: when `shift` is set, move focus backward instead of forward. */
|
|
4
|
+
export type TabOptions = {
|
|
5
|
+
shift?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const tab: (widget: Gtk.Widget, options?: TabOptions) => Promise<void>;
|
|
8
|
+
export declare const keyboard: (state: UserEventState, widget: Gtk.Widget, input: string) => Promise<void>;
|
|
9
|
+
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/user-event/keyboard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAKpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,4FAA4F;AAC5F,MAAM,MAAM,UAAU,GAAG;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,GAAG,WAAY,GAAG,CAAC,MAAM,YAAY,UAAU,KAAG,OAAO,CAAC,IAAI,CAQrE,CAAC;AAgLP,eAAO,MAAM,QAAQ,UAAW,cAAc,UAAU,GAAG,CAAC,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAM1F,CAAC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
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
|
+
export const tab = (widget, options) => wrapEvent(widget, () => {
|
|
8
|
+
const direction = options?.shift ? Gtk.DirectionType.TAB_BACKWARD : Gtk.DirectionType.TAB_FORWARD;
|
|
9
|
+
const root = widget.getRoot();
|
|
10
|
+
if (root) {
|
|
11
|
+
root.childFocus(direction);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
const KEY_MAP = {
|
|
15
|
+
Enter: Gdk.KEY_Return,
|
|
16
|
+
Tab: Gdk.KEY_Tab,
|
|
17
|
+
Escape: Gdk.KEY_Escape,
|
|
18
|
+
Backspace: Gdk.KEY_BackSpace,
|
|
19
|
+
Delete: Gdk.KEY_Delete,
|
|
20
|
+
ArrowUp: Gdk.KEY_Up,
|
|
21
|
+
ArrowDown: Gdk.KEY_Down,
|
|
22
|
+
ArrowLeft: Gdk.KEY_Left,
|
|
23
|
+
ArrowRight: Gdk.KEY_Right,
|
|
24
|
+
Home: Gdk.KEY_Home,
|
|
25
|
+
End: Gdk.KEY_End,
|
|
26
|
+
PageUp: Gdk.KEY_Page_Up,
|
|
27
|
+
PageDown: Gdk.KEY_Page_Down,
|
|
28
|
+
Space: Gdk.KEY_space,
|
|
29
|
+
Shift: Gdk.KEY_Shift_L,
|
|
30
|
+
Control: Gdk.KEY_Control_L,
|
|
31
|
+
Alt: Gdk.KEY_Alt_L,
|
|
32
|
+
Meta: Gdk.KEY_Meta_L,
|
|
33
|
+
F1: Gdk.KEY_F1,
|
|
34
|
+
F2: Gdk.KEY_F2,
|
|
35
|
+
F3: Gdk.KEY_F3,
|
|
36
|
+
F4: Gdk.KEY_F4,
|
|
37
|
+
F5: Gdk.KEY_F5,
|
|
38
|
+
F6: Gdk.KEY_F6,
|
|
39
|
+
F7: Gdk.KEY_F7,
|
|
40
|
+
F8: Gdk.KEY_F8,
|
|
41
|
+
F9: Gdk.KEY_F9,
|
|
42
|
+
F10: Gdk.KEY_F10,
|
|
43
|
+
F11: Gdk.KEY_F11,
|
|
44
|
+
F12: Gdk.KEY_F12,
|
|
45
|
+
};
|
|
46
|
+
const parseKeyToken = (token) => {
|
|
47
|
+
let keyName = token;
|
|
48
|
+
let press = true;
|
|
49
|
+
let release = true;
|
|
50
|
+
if (keyName.startsWith("/")) {
|
|
51
|
+
keyName = keyName.slice(1);
|
|
52
|
+
press = false;
|
|
53
|
+
}
|
|
54
|
+
else if (keyName.endsWith(">")) {
|
|
55
|
+
keyName = keyName.slice(0, -1);
|
|
56
|
+
release = false;
|
|
57
|
+
}
|
|
58
|
+
const keyval = KEY_MAP[keyName];
|
|
59
|
+
if (keyval === undefined) {
|
|
60
|
+
throw new Error(`Unknown key: {${keyName}}`);
|
|
61
|
+
}
|
|
62
|
+
return { keyval, press, release };
|
|
63
|
+
};
|
|
64
|
+
const parseKeyboardInput = (input) => {
|
|
65
|
+
const actions = [];
|
|
66
|
+
let i = 0;
|
|
67
|
+
while (i < input.length) {
|
|
68
|
+
if (input[i] !== "{") {
|
|
69
|
+
const keyval = input.codePointAt(i) ?? 0;
|
|
70
|
+
actions.push({ keyval, press: true }, { keyval, press: false });
|
|
71
|
+
i++;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const endBrace = input.indexOf("}", i);
|
|
75
|
+
if (endBrace === -1)
|
|
76
|
+
break;
|
|
77
|
+
const { keyval, press, release } = parseKeyToken(input.slice(i + 1, endBrace));
|
|
78
|
+
if (press)
|
|
79
|
+
actions.push({ keyval, press: true });
|
|
80
|
+
if (release)
|
|
81
|
+
actions.push({ keyval, press: false });
|
|
82
|
+
i = endBrace + 1;
|
|
83
|
+
}
|
|
84
|
+
return actions;
|
|
85
|
+
};
|
|
86
|
+
const MODIFIER_KEYVAL_TO_MASK = {
|
|
87
|
+
[Gdk.KEY_Shift_L]: Gdk.ModifierType.SHIFT_MASK,
|
|
88
|
+
[Gdk.KEY_Shift_R]: Gdk.ModifierType.SHIFT_MASK,
|
|
89
|
+
[Gdk.KEY_Control_L]: Gdk.ModifierType.CONTROL_MASK,
|
|
90
|
+
[Gdk.KEY_Control_R]: Gdk.ModifierType.CONTROL_MASK,
|
|
91
|
+
[Gdk.KEY_Alt_L]: Gdk.ModifierType.ALT_MASK,
|
|
92
|
+
[Gdk.KEY_Alt_R]: Gdk.ModifierType.ALT_MASK,
|
|
93
|
+
[Gdk.KEY_Meta_L]: Gdk.ModifierType.META_MASK,
|
|
94
|
+
[Gdk.KEY_Meta_R]: Gdk.ModifierType.META_MASK,
|
|
95
|
+
};
|
|
96
|
+
const updateModifierState = (state, action) => {
|
|
97
|
+
const mask = MODIFIER_KEYVAL_TO_MASK[action.keyval];
|
|
98
|
+
if (!mask)
|
|
99
|
+
return;
|
|
100
|
+
if (action.press) {
|
|
101
|
+
state.modifierState |= mask;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
state.modifierState &= ~mask;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const matchesTrigger = (trigger, keyval, modifiers) => {
|
|
108
|
+
if (trigger instanceof Gtk.KeyvalTrigger) {
|
|
109
|
+
return trigger.getKeyval() === keyval && trigger.getModifiers() === modifiers;
|
|
110
|
+
}
|
|
111
|
+
if (trigger instanceof Gtk.AlternativeTrigger) {
|
|
112
|
+
return (matchesTrigger(trigger.getFirst(), keyval, modifiers) ||
|
|
113
|
+
matchesTrigger(trigger.getSecond(), keyval, modifiers));
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
};
|
|
117
|
+
const activateMatchingShortcut = (controller, widget, keyval, modifiers) => {
|
|
118
|
+
const count = controller.getNItems();
|
|
119
|
+
for (let j = 0; j < count; j++) {
|
|
120
|
+
const shortcut = controller.getItem(j);
|
|
121
|
+
if (!(shortcut instanceof Gtk.Shortcut))
|
|
122
|
+
continue;
|
|
123
|
+
if (!matchesTrigger(shortcut.getTrigger(), keyval, modifiers))
|
|
124
|
+
continue;
|
|
125
|
+
const action = shortcut.getAction();
|
|
126
|
+
if (action instanceof Gtk.SignalAction && action.getSignalName() === "move-focus")
|
|
127
|
+
continue;
|
|
128
|
+
if (action?.activate(0, widget, shortcut.getArguments()))
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
};
|
|
133
|
+
const dispatchShortcutsOnWidget = (widget, keyval, modifiers) => {
|
|
134
|
+
const controllers = widget.observeControllers();
|
|
135
|
+
for (let i = 0; i < controllers.getNItems(); i++) {
|
|
136
|
+
const controller = controllers.getItem(i);
|
|
137
|
+
if (controller instanceof Gtk.ShortcutController &&
|
|
138
|
+
activateMatchingShortcut(controller, widget, keyval, modifiers)) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
};
|
|
144
|
+
const dispatchShortcuts = (widget, keyval, modifiers) => {
|
|
145
|
+
const delegate = getEditableDelegate(widget);
|
|
146
|
+
if (delegate && dispatchShortcutsOnWidget(delegate, keyval, modifiers))
|
|
147
|
+
return true;
|
|
148
|
+
for (let current = widget; current; current = current.getParent()) {
|
|
149
|
+
if (dispatchShortcutsOnWidget(current, keyval, modifiers))
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
};
|
|
154
|
+
const applyKeyAction = async (widget, controllers, state, action) => {
|
|
155
|
+
updateModifierState(state, action);
|
|
156
|
+
const signalName = action.press ? "key-pressed" : "key-released";
|
|
157
|
+
for (const controller of controllers) {
|
|
158
|
+
controller.emit(signalName, action.keyval, 0, state.modifierState);
|
|
159
|
+
}
|
|
160
|
+
if (action.press) {
|
|
161
|
+
const handled = dispatchShortcuts(widget, action.keyval, state.modifierState);
|
|
162
|
+
if (!handled && action.keyval === Gdk.KEY_Return && widget instanceof Gtk.Editable) {
|
|
163
|
+
await fireEvent(widget, "activate");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
export const keyboard = (state, widget, input) => wrapEvent(widget, async () => {
|
|
168
|
+
const controllers = getOrCreateControllers(widget, Gtk.EventControllerKey);
|
|
169
|
+
for (const action of parseKeyboardInput(input)) {
|
|
170
|
+
await applyKeyAction(widget, controllers, state, action);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
//# 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 { getEditableDelegate } from \"../editable.js\";\nimport { fireEvent } from \"../fire-event.js\";\nimport { getOrCreateControllers } from \"./controller.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\nimport type { UserEventState } from \"./state.js\";\n\n/** Options for {@link tab}: when `shift` is set, move focus backward instead of forward. */\nexport type TabOptions = {\n shift?: boolean;\n};\n\nexport const 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 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\ntype KeyAction = { keyval: number; press: boolean };\n\nconst parseKeyToken = (token: string): { keyval: number; press: boolean; release: boolean } => {\n let keyName = token;\n let press = true;\n let release = true;\n\n if (keyName.startsWith(\"/\")) {\n keyName = keyName.slice(1);\n press = false;\n } else if (keyName.endsWith(\">\")) {\n keyName = keyName.slice(0, -1);\n release = false;\n }\n\n const keyval = KEY_MAP[keyName];\n if (keyval === undefined) {\n throw new Error(`Unknown key: {${keyName}}`);\n }\n return { keyval, press, release };\n};\n\nconst parseKeyboardInput = (input: string): KeyAction[] => {\n const actions: KeyAction[] = [];\n let i = 0;\n\n while (i < input.length) {\n if (input[i] !== \"{\") {\n const keyval = input.codePointAt(i) ?? 0;\n actions.push({ keyval, press: true }, { keyval, press: false });\n i++;\n continue;\n }\n\n const endBrace = input.indexOf(\"}\", i);\n if (endBrace === -1) break;\n\n const { keyval, press, release } = parseKeyToken(input.slice(i + 1, endBrace));\n if (press) actions.push({ keyval, press: true });\n if (release) actions.push({ keyval, press: false });\n\n i = endBrace + 1;\n }\n\n return actions;\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 updateModifierState = (state: UserEventState, action: KeyAction): void => {\n const mask = MODIFIER_KEYVAL_TO_MASK[action.keyval];\n if (!mask) return;\n if (action.press) {\n state.modifierState |= mask;\n } else {\n state.modifierState &= ~mask;\n }\n};\n\nconst matchesTrigger = (trigger: Gtk.ShortcutTrigger | null, keyval: number, modifiers: number): boolean => {\n if (trigger instanceof Gtk.KeyvalTrigger) {\n return trigger.getKeyval() === keyval && trigger.getModifiers() === modifiers;\n }\n if (trigger instanceof Gtk.AlternativeTrigger) {\n return (\n matchesTrigger(trigger.getFirst(), keyval, modifiers) ||\n matchesTrigger(trigger.getSecond(), keyval, modifiers)\n );\n }\n return false;\n};\n\nconst activateMatchingShortcut = (\n controller: Gtk.ShortcutController,\n widget: Gtk.Widget,\n keyval: number,\n modifiers: number,\n): boolean => {\n const count = controller.getNItems();\n for (let j = 0; j < count; j++) {\n const shortcut = controller.getItem(j);\n if (!(shortcut instanceof Gtk.Shortcut)) continue;\n if (!matchesTrigger(shortcut.getTrigger(), keyval, modifiers)) continue;\n const action = shortcut.getAction();\n if (action instanceof Gtk.SignalAction && action.getSignalName() === \"move-focus\") continue;\n if (action?.activate(0 as Gtk.ShortcutActionFlags, widget, shortcut.getArguments())) return true;\n }\n return false;\n};\n\nconst dispatchShortcutsOnWidget = (widget: Gtk.Widget, keyval: number, modifiers: number): boolean => {\n const controllers = widget.observeControllers();\n for (let i = 0; i < controllers.getNItems(); i++) {\n const controller = controllers.getItem(i);\n if (\n controller instanceof Gtk.ShortcutController &&\n activateMatchingShortcut(controller, widget, keyval, modifiers)\n ) {\n return true;\n }\n }\n return false;\n};\n\nconst dispatchShortcuts = (widget: Gtk.Widget, keyval: number, modifiers: number): boolean => {\n const delegate = getEditableDelegate(widget);\n if (delegate && dispatchShortcutsOnWidget(delegate, keyval, modifiers)) return true;\n for (let current: Gtk.Widget | null = widget; current; current = current.getParent()) {\n if (dispatchShortcutsOnWidget(current, keyval, modifiers)) return true;\n }\n return false;\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 for (const controller of controllers) {\n controller.emit(signalName, action.keyval, 0, state.modifierState);\n }\n if (action.press) {\n const handled = dispatchShortcuts(widget, action.keyval, state.modifierState);\n if (!handled && action.keyval === Gdk.KEY_Return && widget instanceof Gtk.Editable) {\n await fireEvent(widget, \"activate\");\n }\n }\n};\n\nexport const keyboard = (state: UserEventState, widget: Gtk.Widget, input: string): Promise<void> =>\n wrapEvent(widget, async () => {\n const controllers = getOrCreateControllers(widget, Gtk.EventControllerKey);\n for (const action of parseKeyboardInput(input)) {\n await applyKeyAction(widget, controllers, state, action);\n }\n });\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import type { UserEventState } from "./state.js";
|
|
3
|
+
/** A pointer action token: a full click (`click`, `[MouseLeft]`), a button press (`down`, `[MouseLeft>]`), or a button release (`up`, `[/MouseLeft]`). */
|
|
4
|
+
export type PointerInput = "click" | "down" | "up" | "[MouseLeft]" | "[MouseLeft>]" | "[/MouseLeft]";
|
|
5
|
+
export declare const pointer: (state: UserEventState, widget: Gtk.Widget, input: PointerInput) => Promise<void>;
|
|
6
|
+
//# 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;AAIpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,0JAA0J;AAC1J,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAyBrG,eAAO,MAAM,OAAO,UAAW,cAAc,UAAU,GAAG,CAAC,MAAM,SAAS,YAAY,KAAG,OAAO,CAAC,IAAI,CACjC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
export const pointer = (state, widget, input) => wrapEvent(widget, () => applyPointerInput(widget, state, input));
|
|
27
|
+
//# 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;AACpC,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;AAM/C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAe,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AACrE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAe,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;AACrE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAe,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;AAErE,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;IACrE,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;QAC5B,OAAO;IACX,CAAC;IACD,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;QAC3B,OAAO;IACX,CAAC;IACD,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,CAAC,MAAM,OAAO,GAAG,CAAC,KAAqB,EAAE,MAAkB,EAAE,KAAmB,EAAiB,EAAE,CACrG,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { emitPress, emitRelease } from \"./click.js\";\nimport { getOrCreateControllers } from \"./controller.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\nimport type { UserEventState } from \"./state.js\";\n\n/** A pointer action token: a full click (`click`, `[MouseLeft]`), a button press (`down`, `[MouseLeft>]`), or a button release (`up`, `[/MouseLeft]`). */\nexport type PointerInput = \"click\" | \"down\" | \"up\" | \"[MouseLeft]\" | \"[MouseLeft>]\" | \"[/MouseLeft]\";\n\nconst PRESS_INPUTS = new Set<PointerInput>([\"[MouseLeft>]\", \"down\"]);\nconst RELEASE_INPUTS = new Set<PointerInput>([\"[/MouseLeft]\", \"up\"]);\nconst CLICK_INPUTS = new Set<PointerInput>([\"[MouseLeft]\", \"click\"]);\n\nconst applyPointerInput = (widget: Gtk.Widget, state: UserEventState, input: PointerInput): void => {\n const controllers = getOrCreateControllers(widget, Gtk.GestureClick);\n if (CLICK_INPUTS.has(input)) {\n emitPress(widget, controllers, 1);\n emitRelease(widget, controllers, 1);\n state.mouseLeftDown = false;\n return;\n }\n if (PRESS_INPUTS.has(input) && !state.mouseLeftDown) {\n emitPress(widget, controllers, 1);\n state.mouseLeftDown = true;\n return;\n }\n if (RELEASE_INPUTS.has(input) && state.mouseLeftDown) {\n emitRelease(widget, controllers, 1);\n state.mouseLeftDown = false;\n }\n};\n\nexport const pointer = (state: UserEventState, widget: Gtk.Widget, input: PointerInput): Promise<void> =>\n wrapEvent(widget, () => applyPointerInput(widget, state, input));\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
export declare const selectOptions: (widget: Gtk.Widget, values: number | number[]) => Promise<void>;
|
|
3
|
+
export declare const deselectOptions: (widget: Gtk.Widget, values: number | number[]) => Promise<void>;
|
|
4
|
+
//# 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;AA6FpC,eAAO,MAAM,aAAa,WAAY,GAAG,CAAC,MAAM,UAAU,MAAM,GAAG,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAQpF,CAAC;AASP,eAAO,MAAM,eAAe,WAAY,GAAG,CAAC,MAAM,UAAU,MAAM,GAAG,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAWtF,CAAC"}
|