@gtkx/testing 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,7 +98,7 @@ GTK4 is mature, and GtkBuilder XML can lay out a static interface, but nothing r
98
98
  - a React reconciler that exposes every GObject as a JSX element,
99
99
  - a CLI for scaffolding, development, and production builds,
100
100
  - a dev server with Fast Refresh that patches your running UI in place,
101
- - CSS-in-JS styling and high-level list, grid, and dialog components,
101
+ - CSS-in-JS styling, React Spring animations, and high-level list, grid, and dialog components,
102
102
  - a Testing Library-style API for querying and driving your widgets in tests,
103
103
  - and a Model Context Protocol (MCP) server that exposes your live app to AI agents.
104
104
 
@@ -157,6 +157,7 @@ Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
157
157
  - [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world): the counter above.
158
158
  - [`gtk-demo`](https://github.com/gtkx-org/gtkx/tree/main/examples/gtk-demo): a React port of the official GTK4 widget showcase, covering lists, dialogs, gestures, CSS, and OpenGL.
159
159
  - [`browser`](https://github.com/gtkx-org/gtkx/tree/main/examples/browser): a WebKitWebView-based web browser.
160
+ - [`animations`](https://github.com/gtkx-org/gtkx/tree/main/examples/animations): a tour of `@gtkx/animated`, React Spring animations driven by the GTK frame clock.
160
161
  - [`tutorial`](https://github.com/gtkx-org/gtkx/tree/main/examples/tutorial): the Tasks app the documentation builds.
161
162
 
162
163
  ## Status
package/dist/act.d.ts CHANGED
@@ -13,7 +13,9 @@ type ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;
13
13
  * @returns A promise that resolves with the callback's result after updates flush.
14
14
  */
15
15
  declare const act: ActImplementation;
16
+ declare const getIsReactActEnvironment: () => boolean | undefined;
17
+ declare const setIsReactActEnvironment: (value: boolean | undefined) => void;
16
18
  declare const runWithActEnvironment: <T>(isForced: boolean, fn: () => T | PromiseLike<T>) => Promise<T>;
17
19
  declare const runInAct: (callback: () => unknown) => Promise<void>;
18
- export { act, runWithActEnvironment, runInAct };
20
+ export { act, getIsReactActEnvironment, runWithActEnvironment, runInAct, setIsReactActEnvironment };
19
21
  //# sourceMappingURL=act.d.ts.map
package/dist/act.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;CACrD;AAED,+EAA+E;AAC/E,KAAK,WAAW,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/C,qGAAqG;AACrG,KAAK,iBAAiB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzE;;;;;;GAMG;AACH,QAAA,MAAM,GAAG,EAAE,iBAA+D,CAAC;AA2B3E,QAAA,MAAM,qBAAqB,GAAI,CAAC,EAAE,UAAU,OAAO,EAAE,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAkB5F,CAAC;AAUF,QAAA,MAAM,QAAQ,GAAU,UAAU,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CAE7D,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;CACrD;AAED,+EAA+E;AAC/E,KAAK,WAAW,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/C,qGAAqG;AACrG,KAAK,iBAAiB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzE;;;;;;GAMG;AACH,QAAA,MAAM,GAAG,EAAE,iBAA+D,CAAC;AAU3E,QAAA,MAAM,wBAAwB,QAAO,OAAO,GAAG,SAAqD,CAAC;AAErG,QAAA,MAAM,wBAAwB,GAAI,OAAO,OAAO,GAAG,SAAS,KAAG,IAE9D,CAAC;AAaF,QAAA,MAAM,qBAAqB,GAAI,CAAC,EAAE,UAAU,OAAO,EAAE,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAkB5F,CAAC;AAUF,QAAA,MAAM,QAAQ,GAAU,UAAU,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CAE7D,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC"}
package/dist/act.js CHANGED
@@ -52,5 +52,5 @@ function withGlobalActEnvironment(actImplementation) {
52
52
  const runInAct = async (callback) => {
53
53
  await act(() => callback());
54
54
  };
55
- export { act, runWithActEnvironment, runInAct };
55
+ export { act, getIsReactActEnvironment, runWithActEnvironment, runInAct, setIsReactActEnvironment };
56
56
  //# sourceMappingURL=act.js.map
package/dist/act.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"act.js","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC;AAWxC,MAAM,iBAAiB,GAAsB,QAAQ,CAAC;AACtD;;;;;;GAMG;AACH,MAAM,GAAG,GAAsB,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAE3E,MAAM,aAAa,GAAG,GAAsB,EAAE;IAC1C,IAAI,OAAO,UAAU,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,GAAwB,EAAE,CAAC,aAAa,EAAE,CAAC,wBAAwB,CAAC;AAErG,MAAM,wBAAwB,GAAG,CAAC,KAA0B,EAAQ,EAAE;IAClE,aAAa,EAAE,CAAC,wBAAwB,GAAG,KAAK,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAI,KAAc,EAA2B,EAAE,CAC9D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAExG,MAAM,YAAY,GAAG,KAAK,EAAK,MAAsB,EAAE,QAA6B,EAAc,EAAE;IAChG,IAAI,CAAC;QACD,OAAO,MAAM,MAAM,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAI,QAAiB,EAAE,EAA4B,EAAc,EAAE;IAC7F,MAAM,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;IAC1D,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,MAAM,GAAuB,EAAE,EAAE,CAAC;QAExC,IAAI,UAAU,CAAI,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,YAAY,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QACxD,CAAC;QAED,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QAEjD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,wBAAwB,CAAC,iBAAoC;IAClE,OAAO,CAAI,QAAwB,EAAkB,EAAE;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEvF,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAuB,EAAiB,EAAE;IAC9D,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["import { act as reactAct } from \"react\";\n\ndeclare global {\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\n/** Work run inside the act environment, either synchronous or asynchronous. */\ntype ActCallback<T> = () => T | PromiseLike<T>;\n/** Runs a callback inside React's act environment and settles with its result once updates flush. */\ntype ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;\n\nconst actImplementation: ActImplementation = reactAct;\n/**\n * Runs a callback inside React's act environment, flushing pending state\n * updates and effects, and resolves once the work has settled.\n *\n * @param callback Work to run within the act environment.\n * @returns A promise that resolves with the callback's result after updates flush.\n */\nconst act: ActImplementation = withGlobalActEnvironment(actImplementation);\n\nconst getGlobalThis = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") {\n return globalThis;\n }\n\n throw new Error(\"unable to locate global object\");\n};\n\nconst getIsReactActEnvironment = (): boolean | undefined => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;\n\nconst setIsReactActEnvironment = (value: boolean | undefined): void => {\n getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;\n};\n\nconst isThenable = <T>(value: unknown): value is PromiseLike<T> =>\n value !== null && typeof value === \"object\" && typeof (value as PromiseLike<T>).then === \"function\";\n\nconst restoreAfter = async <T>(result: PromiseLike<T>, previous: boolean | undefined): Promise<T> => {\n try {\n return await result;\n } finally {\n setIsReactActEnvironment(previous);\n }\n};\n\nconst runWithActEnvironment = <T>(isForced: boolean, fn: () => T | PromiseLike<T>): Promise<T> => {\n const previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(isForced);\n\n try {\n const result: T | PromiseLike<T> = fn();\n\n if (isThenable<T>(result)) {\n return restoreAfter(result, previousActEnvironment);\n }\n\n setIsReactActEnvironment(previousActEnvironment);\n\n return Promise.resolve(result);\n } catch (error) {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n }\n};\n\nfunction withGlobalActEnvironment(actImplementation: ActImplementation): ActImplementation {\n return <T>(callback: ActCallback<T>): PromiseLike<T> => {\n const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));\n\n return Promise.resolve(settled);\n };\n}\n\nconst runInAct = async (callback: () => unknown): Promise<void> => {\n await act(() => callback());\n};\n\nexport { act, runWithActEnvironment, runInAct };\n"]}
1
+ {"version":3,"file":"act.js","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC;AAWxC,MAAM,iBAAiB,GAAsB,QAAQ,CAAC;AACtD;;;;;;GAMG;AACH,MAAM,GAAG,GAAsB,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAE3E,MAAM,aAAa,GAAG,GAAsB,EAAE;IAC1C,IAAI,OAAO,UAAU,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,GAAwB,EAAE,CAAC,aAAa,EAAE,CAAC,wBAAwB,CAAC;AAErG,MAAM,wBAAwB,GAAG,CAAC,KAA0B,EAAQ,EAAE;IAClE,aAAa,EAAE,CAAC,wBAAwB,GAAG,KAAK,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAI,KAAc,EAA2B,EAAE,CAC9D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAExG,MAAM,YAAY,GAAG,KAAK,EAAK,MAAsB,EAAE,QAA6B,EAAc,EAAE;IAChG,IAAI,CAAC;QACD,OAAO,MAAM,MAAM,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAI,QAAiB,EAAE,EAA4B,EAAc,EAAE;IAC7F,MAAM,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;IAC1D,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,MAAM,GAAuB,EAAE,EAAE,CAAC;QAExC,IAAI,UAAU,CAAI,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,YAAY,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QACxD,CAAC;QAED,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QAEjD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,wBAAwB,CAAC,iBAAoC;IAClE,OAAO,CAAI,QAAwB,EAAkB,EAAE;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEvF,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAuB,EAAiB,EAAE;IAC9D,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC","sourcesContent":["import { act as reactAct } from \"react\";\n\ndeclare global {\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\n/** Work run inside the act environment, either synchronous or asynchronous. */\ntype ActCallback<T> = () => T | PromiseLike<T>;\n/** Runs a callback inside React's act environment and settles with its result once updates flush. */\ntype ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;\n\nconst actImplementation: ActImplementation = reactAct;\n/**\n * Runs a callback inside React's act environment, flushing pending state\n * updates and effects, and resolves once the work has settled.\n *\n * @param callback Work to run within the act environment.\n * @returns A promise that resolves with the callback's result after updates flush.\n */\nconst act: ActImplementation = withGlobalActEnvironment(actImplementation);\n\nconst getGlobalThis = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") {\n return globalThis;\n }\n\n throw new Error(\"unable to locate global object\");\n};\n\nconst getIsReactActEnvironment = (): boolean | undefined => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;\n\nconst setIsReactActEnvironment = (value: boolean | undefined): void => {\n getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;\n};\n\nconst isThenable = <T>(value: unknown): value is PromiseLike<T> =>\n value !== null && typeof value === \"object\" && typeof (value as PromiseLike<T>).then === \"function\";\n\nconst restoreAfter = async <T>(result: PromiseLike<T>, previous: boolean | undefined): Promise<T> => {\n try {\n return await result;\n } finally {\n setIsReactActEnvironment(previous);\n }\n};\n\nconst runWithActEnvironment = <T>(isForced: boolean, fn: () => T | PromiseLike<T>): Promise<T> => {\n const previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(isForced);\n\n try {\n const result: T | PromiseLike<T> = fn();\n\n if (isThenable<T>(result)) {\n return restoreAfter(result, previousActEnvironment);\n }\n\n setIsReactActEnvironment(previousActEnvironment);\n\n return Promise.resolve(result);\n } catch (error) {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n }\n};\n\nfunction withGlobalActEnvironment(actImplementation: ActImplementation): ActImplementation {\n return <T>(callback: ActCallback<T>): PromiseLike<T> => {\n const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));\n\n return Promise.resolve(settled);\n };\n}\n\nconst runInAct = async (callback: () => unknown): Promise<void> => {\n await act(() => callback());\n};\n\nexport { act, getIsReactActEnvironment, runWithActEnvironment, runInAct, setIsReactActEnvironment };\n"]}
@@ -1,4 +1,5 @@
1
1
  import { quit } from "@gtkx/runtime";
2
+ import { getIsReactActEnvironment, setIsReactActEnvironment } from "./act.js";
2
3
  import { registerMatchers } from "./matchers.js";
3
4
  import { cleanup } from "./render.js";
4
5
  const callRunnerHook = (name, callback) => {
@@ -7,7 +8,18 @@ const callRunnerHook = (name, callback) => {
7
8
  hook(callback);
8
9
  }
9
10
  };
11
+ const registerActEnvironment = () => {
12
+ let previousActEnvironment;
13
+ callRunnerHook("beforeAll", () => {
14
+ previousActEnvironment = getIsReactActEnvironment();
15
+ setIsReactActEnvironment(true);
16
+ });
17
+ callRunnerHook("afterAll", () => {
18
+ setIsReactActEnvironment(previousActEnvironment);
19
+ });
20
+ };
10
21
  const registerTestRuntimeHooks = () => {
22
+ registerActEnvironment();
11
23
  callRunnerHook("afterEach", cleanup);
12
24
  callRunnerHook("afterAll", quit);
13
25
  registerMatchers();
@@ -1 +1 @@
1
- {"version":3,"file":"register-test-hooks.js","sourceRoot":"","sources":["../src/register-test-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,cAAc,GAAG,CAAC,IAA8B,EAAE,QAAuB,EAAQ,EAAE;IACrF,MAAM,IAAI,GAAY,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEpD,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5B,IAA0C,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,GAAS,EAAE;IACxC,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACrC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC;AACvB,CAAC,CAAC;AAEF,wBAAwB,EAAE,CAAC","sourcesContent":["import { quit } from \"@gtkx/runtime\";\nimport { registerMatchers } from \"./matchers.js\";\nimport { cleanup } from \"./render.js\";\n\nconst callRunnerHook = (name: \"afterEach\" | \"afterAll\", callback: () => unknown): void => {\n const hook: unknown = Reflect.get(globalThis, name);\n\n if (typeof hook === \"function\") {\n (hook as (callback: () => unknown) => void)(callback);\n }\n};\n\nconst registerTestRuntimeHooks = (): void => {\n callRunnerHook(\"afterEach\", cleanup);\n callRunnerHook(\"afterAll\", quit);\n registerMatchers();\n};\n\nregisterTestRuntimeHooks();\n"]}
1
+ {"version":3,"file":"register-test-hooks.js","sourceRoot":"","sources":["../src/register-test-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAItC,MAAM,cAAc,GAAG,CAAC,IAAgB,EAAE,QAAuB,EAAQ,EAAE;IACvE,MAAM,IAAI,GAAY,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEpD,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5B,IAA0C,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,GAAS,EAAE;IACtC,IAAI,sBAA2C,CAAC;IAEhD,cAAc,CAAC,WAAW,EAAE,GAAG,EAAE;QAC7B,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;QACpD,wBAAwB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,cAAc,CAAC,UAAU,EAAE,GAAG,EAAE;QAC5B,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,GAAS,EAAE;IACxC,sBAAsB,EAAE,CAAC;IACzB,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACrC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC;AACvB,CAAC,CAAC;AAEF,wBAAwB,EAAE,CAAC","sourcesContent":["import { quit } from \"@gtkx/runtime\";\nimport { getIsReactActEnvironment, setIsReactActEnvironment } from \"./act.js\";\nimport { registerMatchers } from \"./matchers.js\";\nimport { cleanup } from \"./render.js\";\n\ntype RunnerHook = \"beforeAll\" | \"afterEach\" | \"afterAll\";\n\nconst callRunnerHook = (name: RunnerHook, callback: () => unknown): void => {\n const hook: unknown = Reflect.get(globalThis, name);\n\n if (typeof hook === \"function\") {\n (hook as (callback: () => unknown) => void)(callback);\n }\n};\n\nconst registerActEnvironment = (): void => {\n let previousActEnvironment: boolean | undefined;\n\n callRunnerHook(\"beforeAll\", () => {\n previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(true);\n });\n\n callRunnerHook(\"afterAll\", () => {\n setIsReactActEnvironment(previousActEnvironment);\n });\n};\n\nconst registerTestRuntimeHooks = (): void => {\n registerActEnvironment();\n callRunnerHook(\"afterEach\", cleanup);\n callRunnerHook(\"afterAll\", quit);\n registerMatchers();\n};\n\nregisterTestRuntimeHooks();\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC;AAgM7E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,MAAM,GAAU,CAAC,SAAS,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC3D,SAAS,SAAS,EAClB,UAAU,aAAa,CAAC,CAAC,CAAC,KAC3B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAoDzB,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,OAAO,QAAa,OAAO,CAAC,IAAI,CAErC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC;AAoM7E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,MAAM,GAAU,CAAC,SAAS,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC3D,SAAS,SAAS,EAClB,UAAU,aAAa,CAAC,CAAC,CAAC,KAC3B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAoDzB,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,OAAO,QAAa,OAAO,CAAC,IAAI,CAErC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
package/dist/render.js CHANGED
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import * as Gtk from "@gtkx/gi/gtk";
3
3
  import { createReconcilerRoot, isRootElement, setReconcilerErrorHandler, settleAccessible, } from "@gtkx/react/internal";
4
4
  import { StrictMode } from "react";
5
- import { runInAct } from "./act.js";
5
+ import { runInAct, runWithActEnvironment } from "./act.js";
6
6
  import { addToCleanupQueue, runCleanup } from "./cleanup-registry.js";
7
7
  import { getConfig } from "./config.js";
8
8
  import { scheduleWhenWindowReady } from "./frame-sync.js";
@@ -19,9 +19,9 @@ const reconcilerErrors = { lastError: null, isHandlerInstalled: false };
19
19
  const activeRenders = new Set();
20
20
  const settleWindow = async (window, findFailure, action) => {
21
21
  const timeout = getConfig().windowActivationTimeout;
22
- await new Promise((resolve) => {
22
+ await runWithActEnvironment(false, () => new Promise((resolve) => {
23
23
  scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);
24
- });
24
+ }));
25
25
  settleAccessible();
26
26
  const failure = window === null ? null : findFailure(window);
27
27
  if (failure !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { RootElement } from \"@gtkx/react\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n createReconcilerRoot,\n isRootElement,\n type ReconcilerRoot,\n setReconcilerErrorHandler,\n settleAccessible,\n} from \"@gtkx/react/internal\";\nimport { type ErrorInfo, type ReactNode, StrictMode } from \"react\";\nimport type { RenderResult } from \"./bound-queries.js\";\nimport type { QueryMap, RenderOptions, ScreenshotOptions } from \"./types.js\";\nimport { runInAct } from \"./act.js\";\nimport { addToCleanupQueue, runCleanup } from \"./cleanup-registry.js\";\nimport { getConfig } from \"./config.js\";\nimport { scheduleWhenWindowReady } from \"./frame-sync.js\";\nimport { createHarnessWindow, presentHarnessWindow } from \"./harness-window.js\";\nimport { logWidget, type PrettyWidgetOptions } from \"./pretty-widget.js\";\nimport { logRoles } from \"./role-helpers.js\";\nimport { clearScreen, setScreen } from \"./screen.js\";\nimport { captureScreen } from \"./screenshot.js\";\nimport { type Container, roots, TOPLEVELS } from \"./traversal.js\";\nimport { resetClipboard } from \"./user-event/index.js\";\nimport { findPresentedWindowFailure, findRenderedWindowFailure, mappedToplevels } from \"./window-state.js\";\nimport { within } from \"./within.js\";\n\n/** A mounted render tracked so cleanup can unmount it. */\ntype ActiveRender = {\n /** Root that rerenders drive and that cleanup tears the tree down through. */\n root: ReconcilerRoot;\n /** Harness window created for the render, null when it renders into a container the caller supplied. */\n window: Gtk.Window | null;\n};\n\ntype ResolvedContainer = {\n containerInfo: Gtk.Widget | RootElement;\n window: Gtk.Window | null;\n};\n\ntype ReconcilerErrorState = {\n lastError: Error | null;\n isHandlerInstalled: boolean;\n};\n\ntype WindowFailureReporter = (window: Gtk.Window) => string | null;\ntype SettleAction = \"render\" | \"rerender\";\n\nconst reconcilerErrors: ReconcilerErrorState = { lastError: null, isHandlerInstalled: false };\nconst activeRenders: Set<ActiveRender> = new Set();\n\nconst settleWindow = async (\n window: Gtk.Window | null,\n findFailure: WindowFailureReporter,\n action: SettleAction,\n): Promise<void> => {\n const timeout = getConfig().windowActivationTimeout;\n\n await new Promise<void>((resolve) => {\n scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);\n });\n\n settleAccessible();\n const failure = window === null ? null : findFailure(window);\n\n if (failure !== null) {\n throw new Error(\n `${action} timed out after ${String(timeout)}ms waiting for the window it rendered into: ${failure}. ` +\n \"Platform state such as focus is only readable once that window is allocated and active.\",\n );\n }\n};\n\nconst update = async (element: ReactNode, root: ReconcilerRoot): Promise<void> => {\n await runInAct(() => {\n root.update(element);\n });\n\n if (reconcilerErrors.lastError) {\n const captured = reconcilerErrors.lastError;\n reconcilerErrors.lastError = null;\n throw captured;\n }\n};\n\nconst disposeActiveRender = async (active: ActiveRender): Promise<void> => {\n if (!activeRenders.delete(active)) {\n return;\n }\n\n await active.root.unmount(async (root) => {\n await update(null, root);\n active.window?.destroy();\n });\n};\n\nconst disposeAllActiveRenders = async (): Promise<void> => {\n for (const active of activeRenders) {\n await disposeActiveRender(active);\n }\n};\n\nconst handleError = (error: unknown): void => {\n reconcilerErrors.lastError = error instanceof Error ? error : new Error(String(error));\n};\n\nconst installErrorHandler = (): void => {\n if (reconcilerErrors.isHandlerInstalled) {\n return;\n }\n\n setReconcilerErrorHandler(handleError);\n reconcilerErrors.isHandlerInstalled = true;\n};\n\nconst resolveContainer = (container: RenderOptions[\"container\"]): ResolvedContainer => {\n if (isRootElement(container)) {\n return { containerInfo: container, window: null };\n }\n\n if (container instanceof Gtk.Widget) {\n return { containerInfo: container, window: null };\n }\n\n const window = createHarnessWindow();\n window.setDecorated(false);\n\n return { containerInfo: window, window };\n};\n\nconst firstToplevelWidget = (baseElement: Container): Gtk.Widget => {\n if (baseElement instanceof Gtk.Widget) {\n return baseElement;\n }\n\n const [first] = roots(baseElement);\n\n if (first) {\n return first;\n }\n\n throw new Error(\"render() produced no widgets: ensure the element renders visible content\");\n};\n\nconst resolveResultContainer = (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n baseElement: Container,\n): Gtk.Widget => {\n if (resolved.window) {\n return resolved.window;\n }\n\n if (container instanceof Gtk.Widget) {\n return container;\n }\n\n return firstToplevelWidget(baseElement);\n};\n\nconst realizedWindow = (root: Gtk.Root | null): Gtk.Window | null =>\n root instanceof Gtk.Window && root.getFrameClock() !== null ? root : null;\n\nconst settleTarget = (resolved: ResolvedContainer, container: RenderOptions[\"container\"]): Gtk.Window | null => {\n if (resolved.window) {\n return realizedWindow(resolved.window);\n }\n\n if (container instanceof Gtk.Widget) {\n return realizedWindow(container.getRoot());\n }\n\n return realizedWindow(mappedToplevels()[0] ?? null);\n};\n\nconst settleRender = async (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n action: SettleAction,\n): Promise<void> => {\n const isPresentedNow = action === \"render\" && resolved.window !== null;\n const findFailure = isPresentedNow ? findPresentedWindowFailure : findRenderedWindowFailure;\n await settleWindow(settleTarget(resolved, container), findFailure, action);\n};\n\nconst renderErrorHandlers = <Q extends QueryMap>(options: RenderOptions<Q> | undefined) => ({\n onUncaughtError: handleError,\n onCaughtError: (error: unknown, errorInfo: ErrorInfo): void => {\n handleError(error);\n options?.onCaughtError?.(error, errorInfo);\n },\n onRecoverableError: (error: unknown, errorInfo: ErrorInfo): void => {\n options?.onRecoverableError?.(error, errorInfo);\n },\n});\n\nconst applyEnableAnimations = (areAnimationsEnabled: boolean): void => {\n const settings = Gtk.Settings.getDefault();\n\n if (settings) {\n settings.gtkEnableAnimations = areAnimationsEnabled;\n }\n};\n\n/**\n * Renders a React element into a GTK4 widget tree and returns queries\n * scoped to it along with controls for rerendering and unmounting. When no\n * container is supplied, a harness window is created and presented, and the editable it hands the\n * focus to keeps its text unselected, with its caret at the end. The returned promise settles once\n * the window the tree is shown in has been laid out and activation has arrived, so platform state\n * such as focus is already readable when it resolves. A presented harness window is waited on until\n * it is itself active; a window the caller or the tree owns is waited on until the application holds\n * activation, since only a present can claim it. Rendering into a container that is not shown waits\n * for nothing, and a window that never becomes readable within `windowActivationTimeout` throws an\n * error naming the condition that failed rather than resolving with unreadable platform state. A\n * tree mounted into a container that sits outside every toplevel, or inside a window that is not\n * visible, is out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it\n * rejects after `actionabilityTimeout` naming that condition, and `fireEvent` drives it instead.\n *\n * @param element The React element to render.\n * @param options Optional container, wrapper, custom queries, and other render settings.\n * @returns A render result with bound queries, debug helpers, and lifecycle controls.\n * @throws When the window the tree is shown in is not laid out and activated in time.\n */\nconst render = async <Q extends QueryMap = Record<never, never>>(\n element: ReactNode,\n options?: RenderOptions<Q>,\n): Promise<RenderResult<Q>> => {\n installErrorHandler();\n applyEnableAnimations(options?.areAnimationsEnabled === true);\n const baseElement: Container = options?.baseElement ?? TOPLEVELS;\n const Wrapper = options?.wrapper;\n const resolved = resolveContainer(options?.container);\n\n const root = createReconcilerRoot({\n containerInfo: resolved.containerInfo,\n ...renderErrorHandlers(options),\n });\n\n const active: ActiveRender = { root, window: resolved.window };\n activeRenders.add(active);\n addToCleanupQueue(disposeAllActiveRenders);\n addToCleanupQueue(clearScreen);\n addToCleanupQueue(resetClipboard);\n\n const wrap = (node: ReactNode): ReactNode => {\n const wrapped = Wrapper ? <Wrapper>{node}</Wrapper> : node;\n\n return options?.isReactStrictMode ? <StrictMode>{wrapped}</StrictMode> : wrapped;\n };\n\n await update(wrap(element), root);\n presentHarnessWindow(resolved.window);\n await settleRender(resolved, options?.container, \"render\");\n const container = resolveResultContainer(resolved, options?.container, baseElement);\n\n const result: RenderResult<Q> = {\n ...within(baseElement, options?.queries),\n container,\n baseElement,\n unmount: async () => {\n await disposeActiveRender(active);\n },\n rerender: async (newElement: ReactNode) => {\n await update(wrap(newElement), root);\n await settleRender(resolved, options?.container, \"rerender\");\n },\n debug: (element: Container | Container[] = baseElement, debugOptions?: PrettyWidgetOptions) => {\n logWidget(element, debugOptions);\n },\n logRoles: () => {\n logRoles(baseElement);\n },\n screenshot: (screenshotOptions?: ScreenshotOptions) => captureScreen(screenshotOptions),\n };\n\n setScreen(result);\n\n return result;\n};\n\n/**\n * Unmounts every active render and runs all registered cleanup callbacks,\n * resetting the screen and clipboard. Called automatically after each test.\n */\nconst cleanup = async (): Promise<void> => {\n await runCleanup();\n};\n\nexport { render, cleanup };\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EACH,oBAAoB,EACpB,aAAa,EAEb,yBAAyB,EACzB,gBAAgB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAkC,UAAU,EAAE,MAAM,OAAO,CAAC;AAGnE,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,SAAS,EAA4B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAkB,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3G,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAuBrC,MAAM,gBAAgB,GAAyB,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAC9F,MAAM,aAAa,GAAsB,IAAI,GAAG,EAAE,CAAC;AAEnD,MAAM,YAAY,GAAG,KAAK,EACtB,MAAyB,EACzB,WAAkC,EAClC,MAAoB,EACP,EAAE;IACf,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,uBAAuB,CAAC;IAEpD,MAAM,qBAAqB,CACvB,KAAK,EACL,GAAG,EAAE,CACD,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC1B,uBAAuB,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChG,CAAC,CAAC,CACT,CAAC;IAEF,gBAAgB,EAAE,CAAC;IACnB,MAAM,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAE7D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACX,GAAG,MAAM,oBAAoB,MAAM,CAAC,OAAO,CAAC,+CAA+C,OAAO,IAAI;YACtG,yFAAyF,CAC5F,CAAC;IACN,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,KAAK,EAAE,OAAkB,EAAE,IAAoB,EAAiB,EAAE;IAC7E,MAAM,QAAQ,CAAC,GAAG,EAAE;QAChB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,IAAI,gBAAgB,CAAC,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC;QAC5C,gBAAgB,CAAC,SAAS,GAAG,IAAI,CAAC;QAClC,MAAM,QAAQ,CAAC;IACnB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,EAAE,MAAoB,EAAiB,EAAE;IACtE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO;IACX,CAAC;IAED,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrC,MAAM,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,KAAK,IAAmB,EAAE;IACtD,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,KAAc,EAAQ,EAAE;IACzC,gBAAgB,CAAC,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3F,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,GAAS,EAAE;IACnC,IAAI,gBAAgB,CAAC,kBAAkB,EAAE,CAAC;QACtC,OAAO;IACX,CAAC;IAED,yBAAyB,CAAC,WAAW,CAAC,CAAC;IACvC,gBAAgB,CAAC,kBAAkB,GAAG,IAAI,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,SAAqC,EAAqB,EAAE;IAClF,IAAI,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtD,CAAC;IAED,IAAI,SAAS,YAAY,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAE3B,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,WAAsB,EAAc,EAAE;IAC/D,IAAI,WAAW,YAAY,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAEnC,IAAI,KAAK,EAAE,CAAC;QACR,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;AAChG,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC3B,QAA2B,EAC3B,SAAqC,EACrC,WAAsB,EACZ,EAAE;IACZ,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS,YAAY,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,mBAAmB,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,IAAqB,EAAqB,EAAE,CAChE,IAAI,YAAY,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAE9E,MAAM,YAAY,GAAG,CAAC,QAA2B,EAAE,SAAqC,EAAqB,EAAE;IAC3G,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,SAAS,YAAY,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,cAAc,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AACxD,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,EACtB,QAA2B,EAC3B,SAAqC,EACrC,MAAoB,EACP,EAAE;IACf,MAAM,cAAc,GAAG,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC;IACvE,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,yBAAyB,CAAC;IAC5F,MAAM,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAqB,OAAqC,EAAE,EAAE,CAAC,CAAC;IACxF,eAAe,EAAE,WAAW;IAC5B,aAAa,EAAE,CAAC,KAAc,EAAE,SAAoB,EAAQ,EAAE;QAC1D,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,EAAE,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC;IACD,kBAAkB,EAAE,CAAC,KAAc,EAAE,SAAoB,EAAQ,EAAE;QAC/D,OAAO,EAAE,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACpD,CAAC;CACJ,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,oBAA6B,EAAQ,EAAE;IAClE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IAE3C,IAAI,QAAQ,EAAE,CAAC;QACX,QAAQ,CAAC,mBAAmB,GAAG,oBAAoB,CAAC;IACxD,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,GAAG,KAAK,EAChB,OAAkB,EAClB,OAA0B,EACF,EAAE;IAC1B,mBAAmB,EAAE,CAAC;IACtB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAc,OAAO,EAAE,WAAW,IAAI,SAAS,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IACjC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEtD,MAAM,IAAI,GAAG,oBAAoB,CAAC;QAC9B,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,GAAG,mBAAmB,CAAC,OAAO,CAAC;KAClC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC/D,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;IAC3C,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/B,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAElC,MAAM,IAAI,GAAG,CAAC,IAAe,EAAa,EAAE;QACxC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,KAAC,OAAO,cAAE,IAAI,GAAW,CAAC,CAAC,CAAC,IAAI,CAAC;QAE3D,OAAO,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAC,UAAU,cAAE,OAAO,GAAc,CAAC,CAAC,CAAC,OAAO,CAAC;IACrF,CAAC,CAAC;IAEF,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IAClC,oBAAoB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAEpF,MAAM,MAAM,GAAoB;QAC5B,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC;QACxC,SAAS;QACT,WAAW;QACX,OAAO,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,UAAqB,EAAE,EAAE;YACtC,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACjE,CAAC;QACD,KAAK,EAAE,CAAC,UAAmC,WAAW,EAAE,YAAkC,EAAE,EAAE;YAC1F,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACrC,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACX,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;QACD,UAAU,EAAE,CAAC,iBAAqC,EAAE,EAAE,CAAC,aAAa,CAAC,iBAAiB,CAAC;KAC1F,CAAC;IAEF,SAAS,CAAC,MAAM,CAAC,CAAC;IAElB,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;IACtC,MAAM,UAAU,EAAE,CAAC;AACvB,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC","sourcesContent":["import type { RootElement } from \"@gtkx/react\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n createReconcilerRoot,\n isRootElement,\n type ReconcilerRoot,\n setReconcilerErrorHandler,\n settleAccessible,\n} from \"@gtkx/react/internal\";\nimport { type ErrorInfo, type ReactNode, StrictMode } from \"react\";\nimport type { RenderResult } from \"./bound-queries.js\";\nimport type { QueryMap, RenderOptions, ScreenshotOptions } from \"./types.js\";\nimport { runInAct, runWithActEnvironment } from \"./act.js\";\nimport { addToCleanupQueue, runCleanup } from \"./cleanup-registry.js\";\nimport { getConfig } from \"./config.js\";\nimport { scheduleWhenWindowReady } from \"./frame-sync.js\";\nimport { createHarnessWindow, presentHarnessWindow } from \"./harness-window.js\";\nimport { logWidget, type PrettyWidgetOptions } from \"./pretty-widget.js\";\nimport { logRoles } from \"./role-helpers.js\";\nimport { clearScreen, setScreen } from \"./screen.js\";\nimport { captureScreen } from \"./screenshot.js\";\nimport { type Container, roots, TOPLEVELS } from \"./traversal.js\";\nimport { resetClipboard } from \"./user-event/index.js\";\nimport { findPresentedWindowFailure, findRenderedWindowFailure, mappedToplevels } from \"./window-state.js\";\nimport { within } from \"./within.js\";\n\n/** A mounted render tracked so cleanup can unmount it. */\ntype ActiveRender = {\n /** Root that rerenders drive and that cleanup tears the tree down through. */\n root: ReconcilerRoot;\n /** Harness window created for the render, null when it renders into a container the caller supplied. */\n window: Gtk.Window | null;\n};\n\ntype ResolvedContainer = {\n containerInfo: Gtk.Widget | RootElement;\n window: Gtk.Window | null;\n};\n\ntype ReconcilerErrorState = {\n lastError: Error | null;\n isHandlerInstalled: boolean;\n};\n\ntype WindowFailureReporter = (window: Gtk.Window) => string | null;\ntype SettleAction = \"render\" | \"rerender\";\n\nconst reconcilerErrors: ReconcilerErrorState = { lastError: null, isHandlerInstalled: false };\nconst activeRenders: Set<ActiveRender> = new Set();\n\nconst settleWindow = async (\n window: Gtk.Window | null,\n findFailure: WindowFailureReporter,\n action: SettleAction,\n): Promise<void> => {\n const timeout = getConfig().windowActivationTimeout;\n\n await runWithActEnvironment(\n false,\n () =>\n new Promise<void>((resolve) => {\n scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);\n }),\n );\n\n settleAccessible();\n const failure = window === null ? null : findFailure(window);\n\n if (failure !== null) {\n throw new Error(\n `${action} timed out after ${String(timeout)}ms waiting for the window it rendered into: ${failure}. ` +\n \"Platform state such as focus is only readable once that window is allocated and active.\",\n );\n }\n};\n\nconst update = async (element: ReactNode, root: ReconcilerRoot): Promise<void> => {\n await runInAct(() => {\n root.update(element);\n });\n\n if (reconcilerErrors.lastError) {\n const captured = reconcilerErrors.lastError;\n reconcilerErrors.lastError = null;\n throw captured;\n }\n};\n\nconst disposeActiveRender = async (active: ActiveRender): Promise<void> => {\n if (!activeRenders.delete(active)) {\n return;\n }\n\n await active.root.unmount(async (root) => {\n await update(null, root);\n active.window?.destroy();\n });\n};\n\nconst disposeAllActiveRenders = async (): Promise<void> => {\n for (const active of activeRenders) {\n await disposeActiveRender(active);\n }\n};\n\nconst handleError = (error: unknown): void => {\n reconcilerErrors.lastError = error instanceof Error ? error : new Error(String(error));\n};\n\nconst installErrorHandler = (): void => {\n if (reconcilerErrors.isHandlerInstalled) {\n return;\n }\n\n setReconcilerErrorHandler(handleError);\n reconcilerErrors.isHandlerInstalled = true;\n};\n\nconst resolveContainer = (container: RenderOptions[\"container\"]): ResolvedContainer => {\n if (isRootElement(container)) {\n return { containerInfo: container, window: null };\n }\n\n if (container instanceof Gtk.Widget) {\n return { containerInfo: container, window: null };\n }\n\n const window = createHarnessWindow();\n window.setDecorated(false);\n\n return { containerInfo: window, window };\n};\n\nconst firstToplevelWidget = (baseElement: Container): Gtk.Widget => {\n if (baseElement instanceof Gtk.Widget) {\n return baseElement;\n }\n\n const [first] = roots(baseElement);\n\n if (first) {\n return first;\n }\n\n throw new Error(\"render() produced no widgets: ensure the element renders visible content\");\n};\n\nconst resolveResultContainer = (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n baseElement: Container,\n): Gtk.Widget => {\n if (resolved.window) {\n return resolved.window;\n }\n\n if (container instanceof Gtk.Widget) {\n return container;\n }\n\n return firstToplevelWidget(baseElement);\n};\n\nconst realizedWindow = (root: Gtk.Root | null): Gtk.Window | null =>\n root instanceof Gtk.Window && root.getFrameClock() !== null ? root : null;\n\nconst settleTarget = (resolved: ResolvedContainer, container: RenderOptions[\"container\"]): Gtk.Window | null => {\n if (resolved.window) {\n return realizedWindow(resolved.window);\n }\n\n if (container instanceof Gtk.Widget) {\n return realizedWindow(container.getRoot());\n }\n\n return realizedWindow(mappedToplevels()[0] ?? null);\n};\n\nconst settleRender = async (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n action: SettleAction,\n): Promise<void> => {\n const isPresentedNow = action === \"render\" && resolved.window !== null;\n const findFailure = isPresentedNow ? findPresentedWindowFailure : findRenderedWindowFailure;\n await settleWindow(settleTarget(resolved, container), findFailure, action);\n};\n\nconst renderErrorHandlers = <Q extends QueryMap>(options: RenderOptions<Q> | undefined) => ({\n onUncaughtError: handleError,\n onCaughtError: (error: unknown, errorInfo: ErrorInfo): void => {\n handleError(error);\n options?.onCaughtError?.(error, errorInfo);\n },\n onRecoverableError: (error: unknown, errorInfo: ErrorInfo): void => {\n options?.onRecoverableError?.(error, errorInfo);\n },\n});\n\nconst applyEnableAnimations = (areAnimationsEnabled: boolean): void => {\n const settings = Gtk.Settings.getDefault();\n\n if (settings) {\n settings.gtkEnableAnimations = areAnimationsEnabled;\n }\n};\n\n/**\n * Renders a React element into a GTK4 widget tree and returns queries\n * scoped to it along with controls for rerendering and unmounting. When no\n * container is supplied, a harness window is created and presented, and the editable it hands the\n * focus to keeps its text unselected, with its caret at the end. The returned promise settles once\n * the window the tree is shown in has been laid out and activation has arrived, so platform state\n * such as focus is already readable when it resolves. A presented harness window is waited on until\n * it is itself active; a window the caller or the tree owns is waited on until the application holds\n * activation, since only a present can claim it. Rendering into a container that is not shown waits\n * for nothing, and a window that never becomes readable within `windowActivationTimeout` throws an\n * error naming the condition that failed rather than resolving with unreadable platform state. A\n * tree mounted into a container that sits outside every toplevel, or inside a window that is not\n * visible, is out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it\n * rejects after `actionabilityTimeout` naming that condition, and `fireEvent` drives it instead.\n *\n * @param element The React element to render.\n * @param options Optional container, wrapper, custom queries, and other render settings.\n * @returns A render result with bound queries, debug helpers, and lifecycle controls.\n * @throws When the window the tree is shown in is not laid out and activated in time.\n */\nconst render = async <Q extends QueryMap = Record<never, never>>(\n element: ReactNode,\n options?: RenderOptions<Q>,\n): Promise<RenderResult<Q>> => {\n installErrorHandler();\n applyEnableAnimations(options?.areAnimationsEnabled === true);\n const baseElement: Container = options?.baseElement ?? TOPLEVELS;\n const Wrapper = options?.wrapper;\n const resolved = resolveContainer(options?.container);\n\n const root = createReconcilerRoot({\n containerInfo: resolved.containerInfo,\n ...renderErrorHandlers(options),\n });\n\n const active: ActiveRender = { root, window: resolved.window };\n activeRenders.add(active);\n addToCleanupQueue(disposeAllActiveRenders);\n addToCleanupQueue(clearScreen);\n addToCleanupQueue(resetClipboard);\n\n const wrap = (node: ReactNode): ReactNode => {\n const wrapped = Wrapper ? <Wrapper>{node}</Wrapper> : node;\n\n return options?.isReactStrictMode ? <StrictMode>{wrapped}</StrictMode> : wrapped;\n };\n\n await update(wrap(element), root);\n presentHarnessWindow(resolved.window);\n await settleRender(resolved, options?.container, \"render\");\n const container = resolveResultContainer(resolved, options?.container, baseElement);\n\n const result: RenderResult<Q> = {\n ...within(baseElement, options?.queries),\n container,\n baseElement,\n unmount: async () => {\n await disposeActiveRender(active);\n },\n rerender: async (newElement: ReactNode) => {\n await update(wrap(newElement), root);\n await settleRender(resolved, options?.container, \"rerender\");\n },\n debug: (element: Container | Container[] = baseElement, debugOptions?: PrettyWidgetOptions) => {\n logWidget(element, debugOptions);\n },\n logRoles: () => {\n logRoles(baseElement);\n },\n screenshot: (screenshotOptions?: ScreenshotOptions) => captureScreen(screenshotOptions),\n };\n\n setScreen(result);\n\n return result;\n};\n\n/**\n * Unmounts every active render and runs all registered cleanup callbacks,\n * resetting the screen and clipboard. Called automatically after each test.\n */\nconst cleanup = async (): Promise<void> => {\n await runCleanup();\n};\n\nexport { render, cleanup };\n"]}
@@ -1,5 +1,5 @@
1
1
  import * as Gtk from "@gtkx/gi/gtk";
2
- import { runInAct } from "../act.js";
2
+ import { runInAct, runWithActEnvironment } from "../act.js";
3
3
  import { getConfig } from "../config.js";
4
4
  import { formatRole } from "../role-helpers.js";
5
5
  import { delay, now } from "../timers.js";
@@ -64,7 +64,7 @@ const waitForActionable = async (widget) => {
64
64
  }
65
65
  };
66
66
  const wrapEvent = async (widget, body) => {
67
- await waitForActionable(widget);
67
+ await runWithActEnvironment(false, () => waitForActionable(widget));
68
68
  await runInAct(async () => {
69
69
  await body();
70
70
  });
@@ -1 +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\";\nimport { delay, now } from \"../timers.js\";\nimport { getWidgetAccessibleName } from \"../widget-accessible-properties.js\";\nimport { getTypeTag, isDefaultWidgetName } from \"../widget-getters.js\";\nimport { isWindowAllocated, isWindowBlockedByModal } from \"../window-state.js\";\n\nconst NOT_SENSITIVE = \"it is not sensitive (the widget or one of its ancestors is disabled)\";\nconst NOT_ROOTED = \"it is not inside a toplevel (it was removed from the widget tree, or was never added to one)\";\nconst WINDOW_NOT_VISIBLE = \"its window is not visible (it was hidden, or it was never shown)\";\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 BLOCKED_BY_MODAL = \"its window is blocked by a modal window holding the grab\";\nconst ACTIONABLE_HOP_MS = 1;\n\nconst findWindowActionabilityFailure = (window: Gtk.Window): string | null => {\n if (!window.getVisible()) {\n return WINDOW_NOT_VISIBLE;\n }\n\n if (!isWindowAllocated(window)) {\n return WINDOW_NOT_ALLOCATED;\n }\n\n if (isWindowBlockedByModal(window)) {\n return BLOCKED_BY_MODAL;\n }\n\n return null;\n};\n\nconst findRootActionabilityFailure = (root: Gtk.Root): string | null =>\n root instanceof Gtk.Window ? findWindowActionabilityFailure(root) : null;\n\nconst findActionabilityFailure = (widget: Gtk.Widget): string | null => {\n if (!widget.isSensitive()) {\n return NOT_SENSITIVE;\n }\n\n const root = widget.getRoot();\n\n if (root === null) {\n return NOT_ROOTED;\n }\n\n const rootFailure = findRootActionabilityFailure(root);\n\n if (rootFailure !== null) {\n return rootFailure;\n }\n\n return widget.getMapped() ? null : NOT_MAPPED;\n};\n\nconst attribute = (key: string, value: string | null): string => (value === null ? \"\" : ` ${key}=\"${value}\"`);\n\nconst widgetNameAttribute = (widget: Gtk.Widget): string => {\n const name = widget.getName();\n\n return attribute(\"name\", isDefaultWidgetName(widget, name) ? null : name);\n};\n\nconst describeWidget = (widget: Gtk.Widget): string => {\n const accessibleName = attribute(\"accessible-name\", getWidgetAccessibleName(widget));\n const role = attribute(\"role\", formatRole(widget.getAccessibleRole()));\n\n return `<${getTypeTag(widget)}${accessibleName}${widgetNameAttribute(widget)}${role}>`;\n};\n\nconst waitForActionable = async (widget: Gtk.Widget): Promise<void> => {\n const timeout = getConfig().actionabilityTimeout;\n const deadline = now() + timeout;\n let failure = findActionabilityFailure(widget);\n\n while (failure !== null && now() < deadline) {\n await delay(ACTIONABLE_HOP_MS);\n failure = findActionabilityFailure(widget);\n }\n\n if (failure !== null) {\n throw new Error(\n `Cannot dispatch user event: ${describeWidget(widget)} did not become actionable ` +\n `within ${String(timeout)}ms because ${failure}`,\n );\n }\n};\n\nconst wrapEvent = async (widget: Gtk.Widget, body: () => void | PromiseLike<void>): Promise<void> => {\n await waitForActionable(widget);\n\n await runInAct(async () => {\n await body();\n });\n};\n\nexport { wrapEvent };\n"]}
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, runWithActEnvironment } from \"../act.js\";\nimport { getConfig } from \"../config.js\";\nimport { formatRole } from \"../role-helpers.js\";\nimport { delay, now } from \"../timers.js\";\nimport { getWidgetAccessibleName } from \"../widget-accessible-properties.js\";\nimport { getTypeTag, isDefaultWidgetName } from \"../widget-getters.js\";\nimport { isWindowAllocated, isWindowBlockedByModal } from \"../window-state.js\";\n\nconst NOT_SENSITIVE = \"it is not sensitive (the widget or one of its ancestors is disabled)\";\nconst NOT_ROOTED = \"it is not inside a toplevel (it was removed from the widget tree, or was never added to one)\";\nconst WINDOW_NOT_VISIBLE = \"its window is not visible (it was hidden, or it was never shown)\";\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 BLOCKED_BY_MODAL = \"its window is blocked by a modal window holding the grab\";\nconst ACTIONABLE_HOP_MS = 1;\n\nconst findWindowActionabilityFailure = (window: Gtk.Window): string | null => {\n if (!window.getVisible()) {\n return WINDOW_NOT_VISIBLE;\n }\n\n if (!isWindowAllocated(window)) {\n return WINDOW_NOT_ALLOCATED;\n }\n\n if (isWindowBlockedByModal(window)) {\n return BLOCKED_BY_MODAL;\n }\n\n return null;\n};\n\nconst findRootActionabilityFailure = (root: Gtk.Root): string | null =>\n root instanceof Gtk.Window ? findWindowActionabilityFailure(root) : null;\n\nconst findActionabilityFailure = (widget: Gtk.Widget): string | null => {\n if (!widget.isSensitive()) {\n return NOT_SENSITIVE;\n }\n\n const root = widget.getRoot();\n\n if (root === null) {\n return NOT_ROOTED;\n }\n\n const rootFailure = findRootActionabilityFailure(root);\n\n if (rootFailure !== null) {\n return rootFailure;\n }\n\n return widget.getMapped() ? null : NOT_MAPPED;\n};\n\nconst attribute = (key: string, value: string | null): string => (value === null ? \"\" : ` ${key}=\"${value}\"`);\n\nconst widgetNameAttribute = (widget: Gtk.Widget): string => {\n const name = widget.getName();\n\n return attribute(\"name\", isDefaultWidgetName(widget, name) ? null : name);\n};\n\nconst describeWidget = (widget: Gtk.Widget): string => {\n const accessibleName = attribute(\"accessible-name\", getWidgetAccessibleName(widget));\n const role = attribute(\"role\", formatRole(widget.getAccessibleRole()));\n\n return `<${getTypeTag(widget)}${accessibleName}${widgetNameAttribute(widget)}${role}>`;\n};\n\nconst waitForActionable = async (widget: Gtk.Widget): Promise<void> => {\n const timeout = getConfig().actionabilityTimeout;\n const deadline = now() + timeout;\n let failure = findActionabilityFailure(widget);\n\n while (failure !== null && now() < deadline) {\n await delay(ACTIONABLE_HOP_MS);\n failure = findActionabilityFailure(widget);\n }\n\n if (failure !== null) {\n throw new Error(\n `Cannot dispatch user event: ${describeWidget(widget)} did not become actionable ` +\n `within ${String(timeout)}ms because ${failure}`,\n );\n }\n};\n\nconst wrapEvent = async (widget: Gtk.Widget, body: () => void | PromiseLike<void>): Promise<void> => {\n await runWithActEnvironment(false, () => waitForActionable(widget));\n\n await runInAct(async () => {\n await body();\n });\n};\n\nexport { wrapEvent };\n"]}
@@ -1 +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,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;AAE7D,kEAAkE;AAClE,KAAK,WAAW,GAAG;IACf,+DAA+D;IAC/D,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,CAAC,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAIF,sDAAsD;AACtD,KAAK,UAAU,GAAG;IACd,gEAAgE;IAChE,CAAC,EAAE,MAAM,CAAC;IACV,8DAA8D;IAC9D,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;GAGG;AACH,KAAK,WAAW,GAAG;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAqCF,mGAAmG;AACnG,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAG1C,CAAC;AAEP,qFAAqF;AACrF,QAAA,MAAM,OAAO,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAG5C,CAAC;AAEP;;;;;;GAMG;AACH,QAAA,MAAM,MAAM,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,aAAY,MAAc,KAAG,OAAO,CAAC,IAAI,CAIvF,CAAC;AAEN;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAGxD,CAAC;AAEP;;;;GAIG;AACH,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAAC,IAAI,CAGhF,CAAC;AAEP;;;;GAIG;AACH,QAAA,MAAM,SAAS,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,UAAK,EAAE,UAAK,KAAG,OAAO,CAAC,IAAI,CAG5D,CAAC;AAmFP;;;;;;;GAOG;AACH,QAAA,MAAM,IAAI,GAAU,QAAQ,GAAG,CAAC,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,UAAS,WAAgB,KAAG,OAAO,CAAC,IAAI,CAevG,CAAC;AAUF;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,UAAS,WAAgB,KAAG,OAAO,CAAC,IAAI,CAG1F,CAAC;AAEP;;;;;GAKG;AACH,QAAA,MAAM,WAAW,GACb,QAAQ,GAAG,CAAC,MAAM,EAClB,QAAQ,GAAG,CAAC,MAAM,EAClB,SAAS,WAAW,EACpB,UAAS,WAAgB,KAC1B,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF,OAAO,EACH,KAAK,EACL,OAAO,EACP,MAAM,EACN,IAAI,EACJ,KAAK,EACL,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,WAAW,GACnB,CAAC"}
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,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;AAE7D,kEAAkE;AAClE,KAAK,WAAW,GAAG;IACf,+DAA+D;IAC/D,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,CAAC,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAIF,sDAAsD;AACtD,KAAK,UAAU,GAAG;IACd,gEAAgE;IAChE,CAAC,EAAE,MAAM,CAAC;IACV,8DAA8D;IAC9D,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;GAGG;AACH,KAAK,WAAW,GAAG;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AA6CF,mGAAmG;AACnG,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAG1C,CAAC;AAEP,qFAAqF;AACrF,QAAA,MAAM,OAAO,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAG5C,CAAC;AAEP;;;;;;GAMG;AACH,QAAA,MAAM,MAAM,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,aAAY,MAAc,KAAG,OAAO,CAAC,IAAI,CAIvF,CAAC;AAEN;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAGxD,CAAC;AAEP;;;;GAIG;AACH,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAAC,IAAI,CAGhF,CAAC;AAEP;;;;GAIG;AACH,QAAA,MAAM,SAAS,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,UAAK,EAAE,UAAK,KAAG,OAAO,CAAC,IAAI,CAG5D,CAAC;AAmFP;;;;;;;GAOG;AACH,QAAA,MAAM,IAAI,GAAU,QAAQ,GAAG,CAAC,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,UAAS,WAAgB,KAAG,OAAO,CAAC,IAAI,CAevG,CAAC;AAUF;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,UAAS,WAAgB,KAAG,OAAO,CAAC,IAAI,CAG1F,CAAC;AAEP;;;;;GAKG;AACH,QAAA,MAAM,WAAW,GACb,QAAQ,GAAG,CAAC,MAAM,EAClB,QAAQ,GAAG,CAAC,MAAM,EAClB,SAAS,WAAW,EACpB,UAAS,WAAgB,KAC1B,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF,OAAO,EACH,KAAK,EACL,OAAO,EACP,MAAM,EACN,IAAI,EACJ,KAAK,EACL,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,WAAW,GACnB,CAAC"}
@@ -3,21 +3,27 @@ import * as Gtk from "@gtkx/gi/gtk";
3
3
  import { getAllControllers } from "./controller.js";
4
4
  import { dispatchOnControllers, dispatchOnOrCreateControllers } from "./dispatch.js";
5
5
  import { wrapEvent } from "./event-wrapper.js";
6
+ const initValue = (gtype, populate) => {
7
+ const value = new GObject.Value();
8
+ value.init(gtype);
9
+ populate(value);
10
+ return value;
11
+ };
6
12
  const buildDropValue = (content) => {
7
13
  if (content instanceof GObject.Value) {
8
14
  return content;
9
15
  }
10
16
  if (typeof content === "string") {
11
- return GObject.buildValue(GObject.TYPE_STRING, (v) => {
17
+ return initValue(GObject.TYPE_STRING, (v) => {
12
18
  v.setString(content);
13
19
  });
14
20
  }
15
21
  if (typeof content === "boolean") {
16
- return GObject.buildValue(GObject.TYPE_BOOLEAN, (v) => {
22
+ return initValue(GObject.TYPE_BOOLEAN, (v) => {
17
23
  v.setBoolean(content);
18
24
  });
19
25
  }
20
- return GObject.buildValue(GObject.TYPE_DOUBLE, (v) => {
26
+ return initValue(GObject.TYPE_DOUBLE, (v) => {
21
27
  v.setDouble(content);
22
28
  });
23
29
  };
@@ -1 +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. */\ntype DropContent = string | number | boolean | GObject.Value;\n\n/** Options for a drop: the drop coordinates within the target. */\ntype DropOptions = {\n /** Horizontal drop coordinate within the target, in pixels. */\n x?: number;\n /** Vertical drop coordinate within the target, in pixels. */\n y?: number;\n};\n\ntype DragPhase = \"drag-begin\" | \"drag-update\" | \"drag-end\";\n\n/** A drag offset relative to the drag start point. */\ntype DragOffset = {\n /** Horizontal distance from the drag start point, in pixels. */\n x: number;\n /** Vertical distance from the drag start point, in pixels. */\n y: number;\n};\n\n/**\n * Options for a drag gesture: the starting point, the number of interpolated drag updates, or\n * explicit intermediate offsets emitted before the final one.\n */\ntype DragOptions = {\n /** Horizontal coordinate the drag begins at; defaults to 0. */\n startX?: number;\n /** Vertical coordinate the drag begins at; defaults to 0. */\n startY?: number;\n /** Number of evenly interpolated drag updates, the last of which is the requested offset; defaults to 2. */\n steps?: number;\n /** Explicit intermediate offsets emitted before the requested one, used instead of `steps`. */\n offsets?: DragOffset[];\n};\n\ntype DragInstancePatch = {\n getStartPoint?: Gtk.GestureDrag[\"getStartPoint\"] | undefined;\n getOffset?: Gtk.GestureDrag[\"getOffset\"] | undefined;\n};\n\ntype SavedDragState = {\n instance: DragInstancePatch;\n hasOwnStartPoint: boolean;\n hasOwnOffset: boolean;\n previousStartPoint: DragInstancePatch[\"getStartPoint\"];\n previousOffset: DragInstancePatch[\"getOffset\"];\n};\n\nconst buildDropValue = (content: DropContent): GObject.Value => {\n if (content instanceof GObject.Value) {\n return content;\n }\n\n if (typeof content === \"string\") {\n return GObject.buildValue(GObject.TYPE_STRING, (v) => {\n v.setString(content);\n });\n }\n\n if (typeof content === \"boolean\") {\n return GObject.buildValue(GObject.TYPE_BOOLEAN, (v) => {\n v.setBoolean(content);\n });\n }\n\n return GObject.buildValue(GObject.TYPE_DOUBLE, (v) => {\n v.setDouble(content);\n });\n};\n\n/** Emits `enter` at the widget's origin on its motion controllers, adding one when it has none. */\nconst hover = (widget: Gtk.Widget): Promise<void> =>\n dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {\n controller.emit(\"enter\", 0, 0);\n });\n\n/** Emits `leave` on the widget's motion controllers, adding one when it has none. */\nconst unhover = (widget: Gtk.Widget): Promise<void> =>\n dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {\n controller.emit(\"leave\");\n });\n\n/**\n * Emits `angle-changed` on the widget's rotate gestures.\n *\n * @param angle Current angle, in radians.\n * @param deltaAngle Difference from the angle the gesture started at; defaults to `angle`.\n * @throws When the widget has no Gtk.GestureRotate.\n */\nconst 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 );\n\n/**\n * Emits `scale-changed` with the given scale delta on the widget's zoom gestures.\n *\n * @throws When the widget has no Gtk.GestureZoom.\n */\nconst zoom = (widget: Gtk.Widget, scale: number): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureZoom, (controller) => {\n controller.emit(\"scale-changed\", scale);\n });\n\n/**\n * Emits `swipe` with the given per-axis velocity, in pixels per second, on the widget's swipe gestures.\n *\n * @throws When the widget has no Gtk.GestureSwipe.\n */\nconst swipe = (widget: Gtk.Widget, velocityX: number, velocityY: number): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureSwipe, (controller) => {\n controller.emit(\"swipe\", velocityX, velocityY);\n });\n\n/**\n * Emits `pressed` at the given point in widget coordinates on the widget's long-press gestures.\n *\n * @throws When the widget has no Gtk.GestureLongPress.\n */\nconst longPress = (widget: Gtk.Widget, x = 0, y = 0): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureLongPress, (controller) => {\n controller.emit(\"pressed\", x, y);\n });\n\nconst restoreDragState = (saved: SavedDragState): void => {\n const { instance } = saved;\n\n if (saved.hasOwnStartPoint) {\n instance.getStartPoint = saved.previousStartPoint;\n } else {\n delete instance.getStartPoint;\n }\n\n if (saved.hasOwnOffset) {\n instance.getOffset = saved.previousOffset;\n } else {\n delete instance.getOffset;\n }\n};\n\nconst patchDragState = (controller: Gtk.GestureDrag, start: DragOffset, offset: () => DragOffset): (() => void) => {\n const instance: DragInstancePatch = controller;\n\n const saved: SavedDragState = {\n instance,\n hasOwnStartPoint: Object.hasOwn(instance, \"getStartPoint\"),\n hasOwnOffset: Object.hasOwn(instance, \"getOffset\"),\n previousStartPoint: instance.getStartPoint,\n previousOffset: instance.getOffset,\n };\n\n instance.getStartPoint = () => [true, start.x, start.y];\n\n instance.getOffset = () => {\n const current = offset();\n\n return [true, current.x, current.y];\n };\n\n return () => {\n restoreDragState(saved);\n };\n};\n\nconst emitToControllers = (controllers: Gtk.GestureDrag[], signal: DragPhase, x: number, y: number): void => {\n for (const controller of controllers) {\n controller.emit(signal, x, y);\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\n try {\n emitToControllers(controllers, \"drag-begin\", start.x, start.y);\n\n for (const update of updates) {\n current = update;\n emitToControllers(controllers, \"drag-update\", update.x, update.y);\n }\n\n emitToControllers(controllers, \"drag-end\", current.x, current.y);\n } finally {\n for (const restore of restores) {\n restore();\n }\n }\n};\n\nconst resolveDragUpdates = (dx: number, dy: number, options: DragOptions): DragOffset[] => {\n if (options.offsets) {\n return [...options.offsets, { x: dx, y: dy }];\n }\n\n const steps = Math.max(1, Math.floor(options.steps ?? 2));\n const updates: DragOffset[] = [];\n\n for (let i = 1; i <= steps; i++) {\n updates.push({ x: (dx * i) / steps, y: (dy * i) / steps });\n }\n\n return updates;\n};\n\n/**\n * Runs a `drag-begin`, `drag-update`, `drag-end` sequence ending at the offset `dx`, `dy` on the\n * widget's drag gestures, overriding each gesture's start point and offset for the duration so\n * handlers read the simulated values back.\n *\n * @throws When the widget is a Gtk.Range, whose slider reads pointer coordinates from the display,\n * or when it has no Gtk.GestureDrag.\n */\nconst drag = async (widget: Gtk.Widget, dx: number, dy: number, options: DragOptions = {}): Promise<void> => {\n if (widget instanceof Gtk.Range) {\n throw new TypeError(\n \"userEvent.drag cannot drive a Gtk.Range's built-in slider \" +\n \"(its drag reads pointer coordinates from the display); \" +\n \"use userEvent.slide(range, value) or userEvent.keyboard for sliders\",\n );\n }\n\n const start = { x: options.startX ?? 0, y: options.startY ?? 0 };\n const updates = resolveDragUpdates(dx, dy, options);\n\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\n for (const dropTarget of dropTargets) {\n dropTarget.emit(\"drop\", buildDropValue(content), options.x ?? 0, options.y ?? 0);\n }\n};\n\n/**\n * Emits `drop` with the given content on every drop target attached to the widget.\n *\n * @throws When the widget has no Gtk.DropTarget.\n */\nconst drop = (widget: Gtk.Widget, content: DropContent, options: DropOptions = {}): Promise<void> =>\n wrapEvent(widget, () => {\n emitDrop(widget, content, options);\n });\n\n/**\n * Emits `drop` with the given content on the target's drop targets, after checking that the source\n * carries a drag source.\n *\n * @throws When the source has no Gtk.DragSource, or the target no Gtk.DropTarget.\n */\nconst 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\n await wrapEvent(target, () => {\n emitDrop(target, content, options);\n });\n};\n\nexport {\n hover,\n unhover,\n rotate,\n zoom,\n swipe,\n longPress,\n drag,\n drop,\n dragAndDrop,\n type DropContent,\n type DropOptions,\n type DragOffset,\n type DragOptions,\n};\n"]}
1
+ {"version":3,"file":"gesture.js","sourceRoot":"","sources":["../../src/user-event/gesture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAmD/C,MAAM,SAAS,GAAG,CAAC,KAAmB,EAAE,QAAwC,EAAiB,EAAE;IAC/F,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhB,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,OAAoB,EAAiB,EAAE;IAC3D,IAAI,OAAO,YAAY,OAAO,CAAC,KAAK,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;YACxC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;YACzC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;QACxC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,mGAAmG;AACnG,MAAM,KAAK,GAAG,CAAC,MAAkB,EAAiB,EAAE,CAChD,6BAA6B,CAAC,MAAM,EAAE,GAAG,CAAC,qBAAqB,EAAE,CAAC,UAAU,EAAE,EAAE;IAC5E,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEP,qFAAqF;AACrF,MAAM,OAAO,GAAG,CAAC,MAAkB,EAAiB,EAAE,CAClD,6BAA6B,CAAC,MAAM,EAAE,GAAG,CAAC,qBAAqB,EAAE,CAAC,UAAU,EAAE,EAAE;IAC5E,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEP;;;;;;GAMG;AACH,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAE,aAAqB,KAAK,EAAiB,EAAE,CAC5F,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,UAAU,EAAE,EAAE;IAC5D,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC,CACA,CAAC;AAEN;;;;GAIG;AACH,MAAM,IAAI,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAiB,EAAE,CAC9D,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,EAAE;IAC1D,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEP;;;;GAIG;AACH,MAAM,KAAK,GAAG,CAAC,MAAkB,EAAE,SAAiB,EAAE,SAAiB,EAAiB,EAAE,CACtF,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,EAAE;IAC3D,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEP;;;;GAIG;AACH,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAiB,EAAE,CAClE,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,gBAAgB,EAAE,CAAC,UAAU,EAAE,EAAE;IAC/D,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEP,MAAM,gBAAgB,GAAG,CAAC,KAAqB,EAAQ,EAAE;IACrD,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAE3B,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACzB,QAAQ,CAAC,aAAa,GAAG,KAAK,CAAC,kBAAkB,CAAC;IACtD,CAAC;SAAM,CAAC;QACJ,OAAO,QAAQ,CAAC,aAAa,CAAC;IAClC,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACrB,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC;IAC9C,CAAC;SAAM,CAAC;QACJ,OAAO,QAAQ,CAAC,SAAS,CAAC;IAC9B,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,UAA2B,EAAE,KAAiB,EAAE,MAAwB,EAAgB,EAAE;IAC9G,MAAM,QAAQ,GAAsB,UAAU,CAAC;IAE/C,MAAM,KAAK,GAAmB;QAC1B,QAAQ;QACR,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC;QAC1D,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC;QAClD,kBAAkB,EAAE,QAAQ,CAAC,aAAa;QAC1C,cAAc,EAAE,QAAQ,CAAC,SAAS;KACrC,CAAC;IAEF,QAAQ,CAAC,aAAa,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAExD,QAAQ,CAAC,SAAS,GAAG,GAAG,EAAE;QACtB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;QAEzB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,OAAO,GAAG,EAAE;QACR,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,WAA8B,EAAE,MAAiB,EAAE,CAAS,EAAE,CAAS,EAAQ,EAAE;IACxG,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACnC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,WAA8B,EAAE,KAAiB,EAAE,OAAqB,EAAQ,EAAE;IACvG,IAAI,OAAO,GAAe,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnG,IAAI,CAAC;QACD,iBAAiB,CAAC,WAAW,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAE/D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,OAAO,GAAG,MAAM,CAAC;YACjB,iBAAiB,CAAC,WAAW,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;YAAS,CAAC;QACP,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;QACd,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,OAAoB,EAAgB,EAAE;IACtF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,IAAI,GAAG,KAAK,EAAE,MAAkB,EAAE,EAAU,EAAE,EAAU,EAAE,UAAuB,EAAE,EAAiB,EAAE;IACxG,IAAI,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CACf,4DAA4D;YAC5D,yDAAyD;YACzD,qEAAqE,CACxE,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;IACjE,MAAM,OAAO,GAAG,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAEpD,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;QACzB,eAAe,CAAC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,MAAkB,EAAE,OAAoB,EAAE,OAAoB,EAAQ,EAAE;IACtF,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAE9D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACnC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACrF,CAAC;AACL,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,IAAI,GAAG,CAAC,MAAkB,EAAE,OAAoB,EAAE,UAAuB,EAAE,EAAiB,EAAE,CAChG,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;IACnB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEP;;;;;GAKG;AACH,MAAM,WAAW,GAAG,KAAK,EACrB,MAAkB,EAClB,MAAkB,EAClB,OAAoB,EACpB,UAAuB,EAAE,EACZ,EAAE;IACf,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;QACzB,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;QACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,OAAO,EACH,KAAK,EACL,OAAO,EACP,MAAM,EACN,IAAI,EACJ,KAAK,EACL,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,WAAW,GAKd,CAAC","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. */\ntype DropContent = string | number | boolean | GObject.Value;\n\n/** Options for a drop: the drop coordinates within the target. */\ntype DropOptions = {\n /** Horizontal drop coordinate within the target, in pixels. */\n x?: number;\n /** Vertical drop coordinate within the target, in pixels. */\n y?: number;\n};\n\ntype DragPhase = \"drag-begin\" | \"drag-update\" | \"drag-end\";\n\n/** A drag offset relative to the drag start point. */\ntype DragOffset = {\n /** Horizontal distance from the drag start point, in pixels. */\n x: number;\n /** Vertical distance from the drag start point, in pixels. */\n y: number;\n};\n\n/**\n * Options for a drag gesture: the starting point, the number of interpolated drag updates, or\n * explicit intermediate offsets emitted before the final one.\n */\ntype DragOptions = {\n /** Horizontal coordinate the drag begins at; defaults to 0. */\n startX?: number;\n /** Vertical coordinate the drag begins at; defaults to 0. */\n startY?: number;\n /** Number of evenly interpolated drag updates, the last of which is the requested offset; defaults to 2. */\n steps?: number;\n /** Explicit intermediate offsets emitted before the requested one, used instead of `steps`. */\n offsets?: DragOffset[];\n};\n\ntype DragInstancePatch = {\n getStartPoint?: Gtk.GestureDrag[\"getStartPoint\"] | undefined;\n getOffset?: Gtk.GestureDrag[\"getOffset\"] | undefined;\n};\n\ntype SavedDragState = {\n instance: DragInstancePatch;\n hasOwnStartPoint: boolean;\n hasOwnOffset: boolean;\n previousStartPoint: DragInstancePatch[\"getStartPoint\"];\n previousOffset: DragInstancePatch[\"getOffset\"];\n};\n\nconst initValue = (gtype: GObject.Type, populate: (value: GObject.Value) => void): GObject.Value => {\n const value = new GObject.Value();\n value.init(gtype);\n populate(value);\n\n return value;\n};\n\nconst buildDropValue = (content: DropContent): GObject.Value => {\n if (content instanceof GObject.Value) {\n return content;\n }\n\n if (typeof content === \"string\") {\n return initValue(GObject.TYPE_STRING, (v) => {\n v.setString(content);\n });\n }\n\n if (typeof content === \"boolean\") {\n return initValue(GObject.TYPE_BOOLEAN, (v) => {\n v.setBoolean(content);\n });\n }\n\n return initValue(GObject.TYPE_DOUBLE, (v) => {\n v.setDouble(content);\n });\n};\n\n/** Emits `enter` at the widget's origin on its motion controllers, adding one when it has none. */\nconst hover = (widget: Gtk.Widget): Promise<void> =>\n dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {\n controller.emit(\"enter\", 0, 0);\n });\n\n/** Emits `leave` on the widget's motion controllers, adding one when it has none. */\nconst unhover = (widget: Gtk.Widget): Promise<void> =>\n dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {\n controller.emit(\"leave\");\n });\n\n/**\n * Emits `angle-changed` on the widget's rotate gestures.\n *\n * @param angle Current angle, in radians.\n * @param deltaAngle Difference from the angle the gesture started at; defaults to `angle`.\n * @throws When the widget has no Gtk.GestureRotate.\n */\nconst 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 );\n\n/**\n * Emits `scale-changed` with the given scale delta on the widget's zoom gestures.\n *\n * @throws When the widget has no Gtk.GestureZoom.\n */\nconst zoom = (widget: Gtk.Widget, scale: number): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureZoom, (controller) => {\n controller.emit(\"scale-changed\", scale);\n });\n\n/**\n * Emits `swipe` with the given per-axis velocity, in pixels per second, on the widget's swipe gestures.\n *\n * @throws When the widget has no Gtk.GestureSwipe.\n */\nconst swipe = (widget: Gtk.Widget, velocityX: number, velocityY: number): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureSwipe, (controller) => {\n controller.emit(\"swipe\", velocityX, velocityY);\n });\n\n/**\n * Emits `pressed` at the given point in widget coordinates on the widget's long-press gestures.\n *\n * @throws When the widget has no Gtk.GestureLongPress.\n */\nconst longPress = (widget: Gtk.Widget, x = 0, y = 0): Promise<void> =>\n dispatchOnControllers(widget, Gtk.GestureLongPress, (controller) => {\n controller.emit(\"pressed\", x, y);\n });\n\nconst restoreDragState = (saved: SavedDragState): void => {\n const { instance } = saved;\n\n if (saved.hasOwnStartPoint) {\n instance.getStartPoint = saved.previousStartPoint;\n } else {\n delete instance.getStartPoint;\n }\n\n if (saved.hasOwnOffset) {\n instance.getOffset = saved.previousOffset;\n } else {\n delete instance.getOffset;\n }\n};\n\nconst patchDragState = (controller: Gtk.GestureDrag, start: DragOffset, offset: () => DragOffset): (() => void) => {\n const instance: DragInstancePatch = controller;\n\n const saved: SavedDragState = {\n instance,\n hasOwnStartPoint: Object.hasOwn(instance, \"getStartPoint\"),\n hasOwnOffset: Object.hasOwn(instance, \"getOffset\"),\n previousStartPoint: instance.getStartPoint,\n previousOffset: instance.getOffset,\n };\n\n instance.getStartPoint = () => [true, start.x, start.y];\n\n instance.getOffset = () => {\n const current = offset();\n\n return [true, current.x, current.y];\n };\n\n return () => {\n restoreDragState(saved);\n };\n};\n\nconst emitToControllers = (controllers: Gtk.GestureDrag[], signal: DragPhase, x: number, y: number): void => {\n for (const controller of controllers) {\n controller.emit(signal, x, y);\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\n try {\n emitToControllers(controllers, \"drag-begin\", start.x, start.y);\n\n for (const update of updates) {\n current = update;\n emitToControllers(controllers, \"drag-update\", update.x, update.y);\n }\n\n emitToControllers(controllers, \"drag-end\", current.x, current.y);\n } finally {\n for (const restore of restores) {\n restore();\n }\n }\n};\n\nconst resolveDragUpdates = (dx: number, dy: number, options: DragOptions): DragOffset[] => {\n if (options.offsets) {\n return [...options.offsets, { x: dx, y: dy }];\n }\n\n const steps = Math.max(1, Math.floor(options.steps ?? 2));\n const updates: DragOffset[] = [];\n\n for (let i = 1; i <= steps; i++) {\n updates.push({ x: (dx * i) / steps, y: (dy * i) / steps });\n }\n\n return updates;\n};\n\n/**\n * Runs a `drag-begin`, `drag-update`, `drag-end` sequence ending at the offset `dx`, `dy` on the\n * widget's drag gestures, overriding each gesture's start point and offset for the duration so\n * handlers read the simulated values back.\n *\n * @throws When the widget is a Gtk.Range, whose slider reads pointer coordinates from the display,\n * or when it has no Gtk.GestureDrag.\n */\nconst drag = async (widget: Gtk.Widget, dx: number, dy: number, options: DragOptions = {}): Promise<void> => {\n if (widget instanceof Gtk.Range) {\n throw new TypeError(\n \"userEvent.drag cannot drive a Gtk.Range's built-in slider \" +\n \"(its drag reads pointer coordinates from the display); \" +\n \"use userEvent.slide(range, value) or userEvent.keyboard for sliders\",\n );\n }\n\n const start = { x: options.startX ?? 0, y: options.startY ?? 0 };\n const updates = resolveDragUpdates(dx, dy, options);\n\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\n for (const dropTarget of dropTargets) {\n dropTarget.emit(\"drop\", buildDropValue(content), options.x ?? 0, options.y ?? 0);\n }\n};\n\n/**\n * Emits `drop` with the given content on every drop target attached to the widget.\n *\n * @throws When the widget has no Gtk.DropTarget.\n */\nconst drop = (widget: Gtk.Widget, content: DropContent, options: DropOptions = {}): Promise<void> =>\n wrapEvent(widget, () => {\n emitDrop(widget, content, options);\n });\n\n/**\n * Emits `drop` with the given content on the target's drop targets, after checking that the source\n * carries a drag source.\n *\n * @throws When the source has no Gtk.DragSource, or the target no Gtk.DropTarget.\n */\nconst 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\n await wrapEvent(target, () => {\n emitDrop(target, content, options);\n });\n};\n\nexport {\n hover,\n unhover,\n rotate,\n zoom,\n swipe,\n longPress,\n drag,\n drop,\n dragAndDrop,\n type DropContent,\n type DropOptions,\n type DragOffset,\n type DragOptions,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAcpC,oCAAoC;AACpC,KAAK,WAAW,GAAG;IACf,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,+FAA+F;IAC/F,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAoKF,QAAA,MAAM,cAAc,QAAO,IAE1B,CAAC;AAeF;;;;;;;;GAQG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,EAAE,UAAU,WAAW,KAAG,OAAO,CAAC,IAAI,CAQ9E,CAAC;AAuEP;;;;;;;;GAQG;AACH,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CACmB,CAAC;AAEpE;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAGzC,CAAC;AAEP;;;;GAIG;AACH,QAAA,MAAM,GAAG,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAIxC,CAAC;AAEP;;;;;GAKG;AACH,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"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAcpC,oCAAoC;AACpC,KAAK,WAAW,GAAG;IACf,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,+FAA+F;IAC/F,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAgKF,QAAA,MAAM,cAAc,QAAO,IAE1B,CAAC;AAeF;;;;;;;;GAQG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,EAAE,UAAU,WAAW,KAAG,OAAO,CAAC,IAAI,CAQ9E,CAAC;AAuEP;;;;;;;;GAQG;AACH,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CACmB,CAAC;AAEpE;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAGzC,CAAC;AAEP;;;;GAIG;AACH,QAAA,MAAM,GAAG,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAIxC,CAAC;AAEP;;;;;GAKG;AACH,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"}
@@ -1,5 +1,4 @@
1
1
  import * as Gdk from "@gtkx/gi/gdk";
2
- import * as GObject from "@gtkx/gi/gobject";
3
2
  import * as Gtk from "@gtkx/gi/gtk";
4
3
  import { EDITABLE_ROLES, getEditableDelegate, isEditable, readEditableText } from "../editable.js";
5
4
  import { formatRoleList } from "../role-helpers.js";
@@ -118,10 +117,7 @@ const applyInitialSelection = (widget, options) => {
118
117
  widget.selectRegion(start, end);
119
118
  };
120
119
  const writeClipboardText = (widget, text) => {
121
- const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {
122
- v.setString(text);
123
- });
124
- widget.getClipboard().set(value);
120
+ widget.getClipboard().set(text);
125
121
  };
126
122
  const resetClipboard = () => {
127
123
  Gdk.Display.getDefault()?.getClipboard().setContent(null);
@@ -1 +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, readEditableText } from \"../editable.js\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { getWidgetSelection } from \"../widget-accessible-properties.js\";\nimport { callBooleanGetter } from \"../widget-getters.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\ntype SignalWatchTarget = {\n on(signal: string, handler: (...args: unknown[]) => unknown, isAfter?: boolean): unknown;\n off(signal: string, handler: (...args: unknown[]) => unknown): unknown;\n};\n\ntype InsertKind = \"typing\" | \"pasting\";\n\n/** Options for `userEvent.type`. */\ntype TypeOptions = {\n /** Focus the widget before typing; defaults to true. */\n shouldFocus?: 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)})`;\nconst CLEAR_REFUSED = \"Cannot clear element: the widget refuses to delete part of its text\";\nconst SELECTION_DELETE_COUNT = 1;\nconst SINGLE_CHARACTER_LENGTH = 1;\nconst TEXT_END_POSITION = -1;\n\nconst isWidgetEditable = (widget: Gtk.Widget): boolean => callBooleanGetter(widget, \"getEditable\") ?? true;\nconst readSelection = (widget: EditableTarget): string => getWidgetSelection(widget) ?? \"\";\nconst hasSelectedText = (widget: Gtk.Editable): boolean => widget.getSelectionBounds()[0];\n\nconst getDelegateText = (widget: Gtk.Editable): Gtk.Text | null => {\n const delegate = getEditableDelegate(widget) ?? widget;\n\n return delegate instanceof Gtk.Text ? delegate : null;\n};\n\nconst getSelectionLength = (buffer: Gtk.TextBuffer): number => {\n const [isSelected, start, end] = buffer.getSelectionBounds();\n\n return isSelected ? end.getOffset() - start.getOffset() : 0;\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 focusPlainEditable = (widget: Gtk.Editable): void => {\n const [isSelected, start, end] = widget.getSelectionBounds();\n widget.grabFocus();\n\n if (isSelected) {\n widget.selectRegion(start, end);\n\n return;\n }\n\n widget.setPosition(TEXT_END_POSITION);\n};\n\nconst focusEditable = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.grabFocus();\n\n return;\n }\n\n const target = getDelegateText(widget);\n\n if (target === null) {\n focusPlainEditable(widget);\n\n return;\n }\n\n target.grabFocusWithoutSelecting();\n\n if (!hasSelectedText(widget)) {\n widget.setPosition(TEXT_END_POSITION);\n }\n};\n\nconst insertTextViewText = (widget: Gtk.TextView, text: string, kind: InsertKind): void => {\n const buffer = widget.getBuffer();\n const length = getSelectionLength(buffer);\n buffer.beginUserAction();\n\n if (length > 0) {\n widget.emit(\"delete-from-cursor\", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);\n\n if (kind === \"typing\" && length > SINGLE_CHARACTER_LENGTH) {\n buffer.endUserAction();\n buffer.beginUserAction();\n }\n }\n\n widget.emit(\"insert-at-cursor\", text);\n buffer.endUserAction();\n};\n\nconst insertDelegateText = (target: Gtk.Text, text: string): void => {\n if (hasSelectedText(target)) {\n target.emit(\"delete-from-cursor\", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);\n }\n\n target.emit(\"insert-at-cursor\", text);\n};\n\nconst insertPlainText = (widget: Gtk.Editable, text: string): void => {\n if (!isWidgetEditable(widget)) {\n return;\n }\n\n if (hasSelectedText(widget)) {\n widget.deleteSelection();\n }\n\n const position = widget.getPosition();\n const newPosition = widget.insertText(text, text.length, position);\n widget.setPosition(newPosition);\n};\n\nconst insertEditableText = (widget: EditableTarget, text: string, kind: InsertKind): void => {\n if (widget instanceof Gtk.TextView) {\n insertTextViewText(widget, text, kind);\n\n return;\n }\n\n const target = getDelegateText(widget);\n\n if (target === null) {\n insertPlainText(widget, text);\n\n return;\n }\n\n insertDelegateText(target, text);\n};\n\nconst deleteAllText = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n buffer.deleteInteractive(buffer.getStartIter(), buffer.getEndIter(), widget.getEditable());\n\n return;\n }\n\n widget.deleteText(0, -1);\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 const buffer = widget.getBuffer();\n buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));\n\n return;\n }\n\n widget.selectRegion(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\n/**\n * Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the\n * text at the cursor, deleting the text the widget has selected first, the way typing over a\n * selection does in GTK4. Focusing works the way clicking into the widget does, leaving its text\n * unselected: a `Gtk.Editable` takes its caret to the end of its text, a `Gtk.TextView` keeps the\n * caret where it stands, and the replaced text stays on the widget's undo stack either way.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>\n runEditableEvent(widget, \"Cannot type into element\", (editable) => {\n if (options?.shouldFocus ?? true) {\n focusEditable(editable);\n }\n\n applyInitialSelection(editable, options ?? {});\n insertEditableText(editable, text, \"typing\");\n });\n\nconst hasNonEditableChar = (iter: Gtk.TextIter, isDefaultEditable: boolean): boolean => {\n while (!iter.isEnd()) {\n if (!iter.editable(isDefaultEditable)) {\n return true;\n }\n\n if (!iter.forwardChar()) {\n return false;\n }\n }\n\n return false;\n};\n\nconst hasProtectedText = (widget: EditableTarget): boolean =>\n widget instanceof Gtk.TextView && hasNonEditableChar(widget.getBuffer().getStartIter(), widget.getEditable());\n\nconst requireClearableText = (editable: EditableTarget): void => {\n if (!isWidgetEditable(editable)) {\n throw new Error(\"Cannot clear element: the widget is not editable\");\n }\n\n if (hasProtectedText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\nconst deletionSignalFor = (widget: EditableTarget): [SignalWatchTarget, string] =>\n widget instanceof Gtk.TextView ? [widget.getBuffer(), \"delete-range\"] : [widget, \"delete-text\"];\n\nconst isDeletionApplied = (emitter: SignalWatchTarget, signal: string, apply: () => void): boolean => {\n let isApplied = false;\n\n const watch = (): void => {\n isApplied = true;\n };\n\n emitter.on(signal, watch, true);\n\n try {\n apply();\n } finally {\n emitter.off(signal, watch);\n }\n\n return isApplied;\n};\n\nconst didDeleteAllText = (widget: EditableTarget): boolean => {\n const [emitter, signal] = deletionSignalFor(widget);\n\n return isDeletionApplied(emitter, signal, () => {\n deleteAllText(widget);\n });\n};\n\nconst clearEditable = (editable: EditableTarget): void => {\n requireClearableText(editable);\n focusEditable(editable);\n\n if (readEditableText(editable) === \"\") {\n return;\n }\n\n if (!didDeleteAllText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\n/**\n * Focuses an editable widget and deletes its whole text through the widget's own editing API, so the\n * deletion emits the signals an edit made by hand emits. Text a tag protects is detected before the\n * deletion runs, leaving such a widget untouched. A widget that writes a new value back in response\n * to the deletion, as an input mask does, is cleared successfully and keeps whatever it wrote.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView, when it refuses edits, when\n * a tag protects part of its text, or when a handler blocks the deletion.\n */\nconst clear = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot clear element\", clearEditable);\n\n/**\n * Writes an editable widget's selected text to its clipboard, or the empty string when nothing is selected.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst copy = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot copy\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n });\n\n/**\n * Writes an editable widget's selected text to its clipboard, then deletes that selection.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst cut = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot cut\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n deleteSelection(editable);\n });\n\n/**\n * Inserts the given text at an editable widget's cursor, reading the clipboard instead when no text\n * is given, and deleting the text the widget has selected first, the way a paste does in GTK4.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\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, \"pasting\");\n });\n};\n\nexport { resetClipboard, type, clear, copy, cut, paste, type TypeOptions };\n"]}
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 Gtk from \"@gtkx/gi/gtk\";\nimport { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable, readEditableText } from \"../editable.js\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { getWidgetSelection } from \"../widget-accessible-properties.js\";\nimport { callBooleanGetter } from \"../widget-getters.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\ntype SignalWatchTarget = {\n on(signal: string, handler: (...args: unknown[]) => unknown, isAfter?: boolean): unknown;\n off(signal: string, handler: (...args: unknown[]) => unknown): unknown;\n};\n\ntype InsertKind = \"typing\" | \"pasting\";\n\n/** Options for `userEvent.type`. */\ntype TypeOptions = {\n /** Focus the widget before typing; defaults to true. */\n shouldFocus?: 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)})`;\nconst CLEAR_REFUSED = \"Cannot clear element: the widget refuses to delete part of its text\";\nconst SELECTION_DELETE_COUNT = 1;\nconst SINGLE_CHARACTER_LENGTH = 1;\nconst TEXT_END_POSITION = -1;\n\nconst isWidgetEditable = (widget: Gtk.Widget): boolean => callBooleanGetter(widget, \"getEditable\") ?? true;\nconst readSelection = (widget: EditableTarget): string => getWidgetSelection(widget) ?? \"\";\nconst hasSelectedText = (widget: Gtk.Editable): boolean => widget.getSelectionBounds()[0];\n\nconst getDelegateText = (widget: Gtk.Editable): Gtk.Text | null => {\n const delegate = getEditableDelegate(widget) ?? widget;\n\n return delegate instanceof Gtk.Text ? delegate : null;\n};\n\nconst getSelectionLength = (buffer: Gtk.TextBuffer): number => {\n const [isSelected, start, end] = buffer.getSelectionBounds();\n\n return isSelected ? end.getOffset() - start.getOffset() : 0;\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 focusPlainEditable = (widget: Gtk.Editable): void => {\n const [isSelected, start, end] = widget.getSelectionBounds();\n widget.grabFocus();\n\n if (isSelected) {\n widget.selectRegion(start, end);\n\n return;\n }\n\n widget.setPosition(TEXT_END_POSITION);\n};\n\nconst focusEditable = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.grabFocus();\n\n return;\n }\n\n const target = getDelegateText(widget);\n\n if (target === null) {\n focusPlainEditable(widget);\n\n return;\n }\n\n target.grabFocusWithoutSelecting();\n\n if (!hasSelectedText(widget)) {\n widget.setPosition(TEXT_END_POSITION);\n }\n};\n\nconst insertTextViewText = (widget: Gtk.TextView, text: string, kind: InsertKind): void => {\n const buffer = widget.getBuffer();\n const length = getSelectionLength(buffer);\n buffer.beginUserAction();\n\n if (length > 0) {\n widget.emit(\"delete-from-cursor\", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);\n\n if (kind === \"typing\" && length > SINGLE_CHARACTER_LENGTH) {\n buffer.endUserAction();\n buffer.beginUserAction();\n }\n }\n\n widget.emit(\"insert-at-cursor\", text);\n buffer.endUserAction();\n};\n\nconst insertDelegateText = (target: Gtk.Text, text: string): void => {\n if (hasSelectedText(target)) {\n target.emit(\"delete-from-cursor\", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);\n }\n\n target.emit(\"insert-at-cursor\", text);\n};\n\nconst insertPlainText = (widget: Gtk.Editable, text: string): void => {\n if (!isWidgetEditable(widget)) {\n return;\n }\n\n if (hasSelectedText(widget)) {\n widget.deleteSelection();\n }\n\n const position = widget.getPosition();\n const newPosition = widget.insertText(text, text.length, position);\n widget.setPosition(newPosition);\n};\n\nconst insertEditableText = (widget: EditableTarget, text: string, kind: InsertKind): void => {\n if (widget instanceof Gtk.TextView) {\n insertTextViewText(widget, text, kind);\n\n return;\n }\n\n const target = getDelegateText(widget);\n\n if (target === null) {\n insertPlainText(widget, text);\n\n return;\n }\n\n insertDelegateText(target, text);\n};\n\nconst deleteAllText = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n buffer.deleteInteractive(buffer.getStartIter(), buffer.getEndIter(), widget.getEditable());\n\n return;\n }\n\n widget.deleteText(0, -1);\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 const buffer = widget.getBuffer();\n buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));\n\n return;\n }\n\n widget.selectRegion(start, end);\n};\n\nconst writeClipboardText = (widget: Gtk.Widget, text: string): void => {\n widget.getClipboard().set(text);\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\n/**\n * Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the\n * text at the cursor, deleting the text the widget has selected first, the way typing over a\n * selection does in GTK4. Focusing works the way clicking into the widget does, leaving its text\n * unselected: a `Gtk.Editable` takes its caret to the end of its text, a `Gtk.TextView` keeps the\n * caret where it stands, and the replaced text stays on the widget's undo stack either way.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>\n runEditableEvent(widget, \"Cannot type into element\", (editable) => {\n if (options?.shouldFocus ?? true) {\n focusEditable(editable);\n }\n\n applyInitialSelection(editable, options ?? {});\n insertEditableText(editable, text, \"typing\");\n });\n\nconst hasNonEditableChar = (iter: Gtk.TextIter, isDefaultEditable: boolean): boolean => {\n while (!iter.isEnd()) {\n if (!iter.editable(isDefaultEditable)) {\n return true;\n }\n\n if (!iter.forwardChar()) {\n return false;\n }\n }\n\n return false;\n};\n\nconst hasProtectedText = (widget: EditableTarget): boolean =>\n widget instanceof Gtk.TextView && hasNonEditableChar(widget.getBuffer().getStartIter(), widget.getEditable());\n\nconst requireClearableText = (editable: EditableTarget): void => {\n if (!isWidgetEditable(editable)) {\n throw new Error(\"Cannot clear element: the widget is not editable\");\n }\n\n if (hasProtectedText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\nconst deletionSignalFor = (widget: EditableTarget): [SignalWatchTarget, string] =>\n widget instanceof Gtk.TextView ? [widget.getBuffer(), \"delete-range\"] : [widget, \"delete-text\"];\n\nconst isDeletionApplied = (emitter: SignalWatchTarget, signal: string, apply: () => void): boolean => {\n let isApplied = false;\n\n const watch = (): void => {\n isApplied = true;\n };\n\n emitter.on(signal, watch, true);\n\n try {\n apply();\n } finally {\n emitter.off(signal, watch);\n }\n\n return isApplied;\n};\n\nconst didDeleteAllText = (widget: EditableTarget): boolean => {\n const [emitter, signal] = deletionSignalFor(widget);\n\n return isDeletionApplied(emitter, signal, () => {\n deleteAllText(widget);\n });\n};\n\nconst clearEditable = (editable: EditableTarget): void => {\n requireClearableText(editable);\n focusEditable(editable);\n\n if (readEditableText(editable) === \"\") {\n return;\n }\n\n if (!didDeleteAllText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\n/**\n * Focuses an editable widget and deletes its whole text through the widget's own editing API, so the\n * deletion emits the signals an edit made by hand emits. Text a tag protects is detected before the\n * deletion runs, leaving such a widget untouched. A widget that writes a new value back in response\n * to the deletion, as an input mask does, is cleared successfully and keeps whatever it wrote.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView, when it refuses edits, when\n * a tag protects part of its text, or when a handler blocks the deletion.\n */\nconst clear = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot clear element\", clearEditable);\n\n/**\n * Writes an editable widget's selected text to its clipboard, or the empty string when nothing is selected.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst copy = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot copy\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n });\n\n/**\n * Writes an editable widget's selected text to its clipboard, then deletes that selection.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst cut = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot cut\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n deleteSelection(editable);\n });\n\n/**\n * Inserts the given text at an editable widget's cursor, reading the clipboard instead when no text\n * is given, and deleting the text the widget has selected first, the way a paste does in GTK4.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\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, \"pasting\");\n });\n};\n\nexport { resetClipboard, type, clear, copy, cut, paste, type TypeOptions };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/testing",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Testing Library-style queries, user events, and screenshots for GTK4 widget trees rendered by GTKX",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -58,11 +58,11 @@
58
58
  "node": ">=24"
59
59
  },
60
60
  "dependencies": {
61
- "@vitest/expect": "^4.1.10",
62
- "@vitest/pretty-format": "^4.1.10",
63
- "@gtkx/utils": "1.2.2",
64
- "@gtkx/runtime": "1.2.2",
65
- "@gtkx/react": "1.2.2"
61
+ "@vitest/expect": "^4.1.11",
62
+ "@vitest/pretty-format": "^4.1.11",
63
+ "@gtkx/runtime": "1.3.0",
64
+ "@gtkx/react": "1.3.0",
65
+ "@gtkx/utils": "1.3.0"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@types/react": "^19.2",
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/react": "^19.2.18",
73
- "@gtkx/config": "1.2.2"
73
+ "@gtkx/config": "1.3.0"
74
74
  },
75
75
  "scripts": {
76
76
  "release": "tsx ../../scripts/release-package.ts"
package/src/act.ts CHANGED
@@ -76,4 +76,4 @@ const runInAct = async (callback: () => unknown): Promise<void> => {
76
76
  await act(() => callback());
77
77
  };
78
78
 
79
- export { act, runWithActEnvironment, runInAct };
79
+ export { act, getIsReactActEnvironment, runWithActEnvironment, runInAct, setIsReactActEnvironment };
@@ -1,8 +1,11 @@
1
1
  import { quit } from "@gtkx/runtime";
2
+ import { getIsReactActEnvironment, setIsReactActEnvironment } from "./act.js";
2
3
  import { registerMatchers } from "./matchers.js";
3
4
  import { cleanup } from "./render.js";
4
5
 
5
- const callRunnerHook = (name: "afterEach" | "afterAll", callback: () => unknown): void => {
6
+ type RunnerHook = "beforeAll" | "afterEach" | "afterAll";
7
+
8
+ const callRunnerHook = (name: RunnerHook, callback: () => unknown): void => {
6
9
  const hook: unknown = Reflect.get(globalThis, name);
7
10
 
8
11
  if (typeof hook === "function") {
@@ -10,7 +13,21 @@ const callRunnerHook = (name: "afterEach" | "afterAll", callback: () => unknown)
10
13
  }
11
14
  };
12
15
 
16
+ const registerActEnvironment = (): void => {
17
+ let previousActEnvironment: boolean | undefined;
18
+
19
+ callRunnerHook("beforeAll", () => {
20
+ previousActEnvironment = getIsReactActEnvironment();
21
+ setIsReactActEnvironment(true);
22
+ });
23
+
24
+ callRunnerHook("afterAll", () => {
25
+ setIsReactActEnvironment(previousActEnvironment);
26
+ });
27
+ };
28
+
13
29
  const registerTestRuntimeHooks = (): void => {
30
+ registerActEnvironment();
14
31
  callRunnerHook("afterEach", cleanup);
15
32
  callRunnerHook("afterAll", quit);
16
33
  registerMatchers();
package/src/render.tsx CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  import { type ErrorInfo, type ReactNode, StrictMode } from "react";
11
11
  import type { RenderResult } from "./bound-queries.js";
12
12
  import type { QueryMap, RenderOptions, ScreenshotOptions } from "./types.js";
13
- import { runInAct } from "./act.js";
13
+ import { runInAct, runWithActEnvironment } from "./act.js";
14
14
  import { addToCleanupQueue, runCleanup } from "./cleanup-registry.js";
15
15
  import { getConfig } from "./config.js";
16
16
  import { scheduleWhenWindowReady } from "./frame-sync.js";
@@ -55,9 +55,13 @@ const settleWindow = async (
55
55
  ): Promise<void> => {
56
56
  const timeout = getConfig().windowActivationTimeout;
57
57
 
58
- await new Promise<void>((resolve) => {
59
- scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);
60
- });
58
+ await runWithActEnvironment(
59
+ false,
60
+ () =>
61
+ new Promise<void>((resolve) => {
62
+ scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);
63
+ }),
64
+ );
61
65
 
62
66
  settleAccessible();
63
67
  const failure = window === null ? null : findFailure(window);
@@ -1,5 +1,5 @@
1
1
  import * as Gtk from "@gtkx/gi/gtk";
2
- import { runInAct } from "../act.js";
2
+ import { runInAct, runWithActEnvironment } from "../act.js";
3
3
  import { getConfig } from "../config.js";
4
4
  import { formatRole } from "../role-helpers.js";
5
5
  import { delay, now } from "../timers.js";
@@ -88,7 +88,7 @@ const waitForActionable = async (widget: Gtk.Widget): Promise<void> => {
88
88
  };
89
89
 
90
90
  const wrapEvent = async (widget: Gtk.Widget, body: () => void | PromiseLike<void>): Promise<void> => {
91
- await waitForActionable(widget);
91
+ await runWithActEnvironment(false, () => waitForActionable(widget));
92
92
 
93
93
  await runInAct(async () => {
94
94
  await body();
@@ -53,24 +53,32 @@ type SavedDragState = {
53
53
  previousOffset: DragInstancePatch["getOffset"];
54
54
  };
55
55
 
56
+ const initValue = (gtype: GObject.Type, populate: (value: GObject.Value) => void): GObject.Value => {
57
+ const value = new GObject.Value();
58
+ value.init(gtype);
59
+ populate(value);
60
+
61
+ return value;
62
+ };
63
+
56
64
  const buildDropValue = (content: DropContent): GObject.Value => {
57
65
  if (content instanceof GObject.Value) {
58
66
  return content;
59
67
  }
60
68
 
61
69
  if (typeof content === "string") {
62
- return GObject.buildValue(GObject.TYPE_STRING, (v) => {
70
+ return initValue(GObject.TYPE_STRING, (v) => {
63
71
  v.setString(content);
64
72
  });
65
73
  }
66
74
 
67
75
  if (typeof content === "boolean") {
68
- return GObject.buildValue(GObject.TYPE_BOOLEAN, (v) => {
76
+ return initValue(GObject.TYPE_BOOLEAN, (v) => {
69
77
  v.setBoolean(content);
70
78
  });
71
79
  }
72
80
 
73
- return GObject.buildValue(GObject.TYPE_DOUBLE, (v) => {
81
+ return initValue(GObject.TYPE_DOUBLE, (v) => {
74
82
  v.setDouble(content);
75
83
  });
76
84
  };
@@ -1,5 +1,4 @@
1
1
  import * as Gdk from "@gtkx/gi/gdk";
2
- import * as GObject from "@gtkx/gi/gobject";
3
2
  import * as Gtk from "@gtkx/gi/gtk";
4
3
  import { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable, readEditableText } from "../editable.js";
5
4
  import { formatRoleList } from "../role-helpers.js";
@@ -179,11 +178,7 @@ const applyInitialSelection = (widget: EditableTarget, options: TypeOptions): vo
179
178
  };
180
179
 
181
180
  const writeClipboardText = (widget: Gtk.Widget, text: string): void => {
182
- const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {
183
- v.setString(text);
184
- });
185
-
186
- widget.getClipboard().set(value);
181
+ widget.getClipboard().set(text);
187
182
  };
188
183
 
189
184
  const resetClipboard = (): void => {