@gtkx/testing 1.0.0 → 1.1.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.
Files changed (124) hide show
  1. package/README.md +1 -1
  2. package/dist/act.d.ts +1 -3
  3. package/dist/act.d.ts.map +1 -1
  4. package/dist/act.js +1 -1
  5. package/dist/act.js.map +1 -1
  6. package/dist/config.d.ts +8 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +1 -0
  9. package/dist/config.js.map +1 -1
  10. package/dist/frame-sync.d.ts +2 -2
  11. package/dist/frame-sync.d.ts.map +1 -1
  12. package/dist/frame-sync.js +10 -10
  13. package/dist/frame-sync.js.map +1 -1
  14. package/dist/harness-window.d.ts +2 -1
  15. package/dist/harness-window.d.ts.map +1 -1
  16. package/dist/harness-window.js +12 -1
  17. package/dist/harness-window.js.map +1 -1
  18. package/dist/internal.d.ts +1 -0
  19. package/dist/internal.d.ts.map +1 -1
  20. package/dist/internal.js +1 -0
  21. package/dist/internal.js.map +1 -1
  22. package/dist/matchers.d.ts.map +1 -1
  23. package/dist/matchers.js +22 -2
  24. package/dist/matchers.js.map +1 -1
  25. package/dist/pretty-widget.d.ts.map +1 -1
  26. package/dist/pretty-widget.js +2 -1
  27. package/dist/pretty-widget.js.map +1 -1
  28. package/dist/production.d.ts.map +1 -1
  29. package/dist/production.js +2 -2
  30. package/dist/production.js.map +1 -1
  31. package/dist/render.d.ts +12 -1
  32. package/dist/render.d.ts.map +1 -1
  33. package/dist/render.js +45 -11
  34. package/dist/render.js.map +1 -1
  35. package/dist/role-helpers.d.ts.map +1 -1
  36. package/dist/role-helpers.js +2 -1
  37. package/dist/role-helpers.js.map +1 -1
  38. package/dist/screenshot.d.ts.map +1 -1
  39. package/dist/screenshot.js +8 -14
  40. package/dist/screenshot.js.map +1 -1
  41. package/dist/timers.d.ts +9 -0
  42. package/dist/timers.d.ts.map +1 -0
  43. package/dist/timers.js +21 -0
  44. package/dist/timers.js.map +1 -0
  45. package/dist/traversal.d.ts +4 -1
  46. package/dist/traversal.d.ts.map +1 -1
  47. package/dist/traversal.js +16 -1
  48. package/dist/traversal.js.map +1 -1
  49. package/dist/types.d.ts +6 -1
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/types.js.map +1 -1
  52. package/dist/user-event/adjustment.d.ts.map +1 -1
  53. package/dist/user-event/adjustment.js +2 -1
  54. package/dist/user-event/adjustment.js.map +1 -1
  55. package/dist/user-event/click.d.ts +5 -4
  56. package/dist/user-event/click.d.ts.map +1 -1
  57. package/dist/user-event/click.js +5 -4
  58. package/dist/user-event/click.js.map +1 -1
  59. package/dist/user-event/column-header-click.d.ts.map +1 -1
  60. package/dist/user-event/column-header-click.js +2 -12
  61. package/dist/user-event/column-header-click.js.map +1 -1
  62. package/dist/user-event/event-wrapper.d.ts.map +1 -1
  63. package/dist/user-event/event-wrapper.js +34 -21
  64. package/dist/user-event/event-wrapper.js.map +1 -1
  65. package/dist/user-event/index.d.ts +36 -10
  66. package/dist/user-event/index.d.ts.map +1 -1
  67. package/dist/user-event/index.js +4 -3
  68. package/dist/user-event/index.js.map +1 -1
  69. package/dist/user-event/keyboard.d.ts.map +1 -1
  70. package/dist/user-event/keyboard.js +93 -38
  71. package/dist/user-event/keyboard.js.map +1 -1
  72. package/dist/user-event/list-row-click.d.ts.map +1 -1
  73. package/dist/user-event/list-row-click.js +4 -5
  74. package/dist/user-event/list-row-click.js.map +1 -1
  75. package/dist/user-event/native-click.d.ts.map +1 -1
  76. package/dist/user-event/native-click.js +4 -0
  77. package/dist/user-event/native-click.js.map +1 -1
  78. package/dist/user-event/notebook-tab-click.d.ts +5 -0
  79. package/dist/user-event/notebook-tab-click.d.ts.map +1 -0
  80. package/dist/user-event/notebook-tab-click.js +39 -0
  81. package/dist/user-event/notebook-tab-click.js.map +1 -0
  82. package/dist/user-event/text.d.ts +6 -3
  83. package/dist/user-event/text.d.ts.map +1 -1
  84. package/dist/user-event/text.js +88 -33
  85. package/dist/user-event/text.js.map +1 -1
  86. package/dist/wait-for.d.ts.map +1 -1
  87. package/dist/wait-for.js +4 -3
  88. package/dist/wait-for.js.map +1 -1
  89. package/dist/widget-getters.d.ts +4 -1
  90. package/dist/widget-getters.d.ts.map +1 -1
  91. package/dist/widget-getters.js +29 -2
  92. package/dist/widget-getters.js.map +1 -1
  93. package/dist/window-state.d.ts +10 -0
  94. package/dist/window-state.d.ts.map +1 -0
  95. package/dist/window-state.js +41 -0
  96. package/dist/window-state.js.map +1 -0
  97. package/package.json +15 -7
  98. package/src/act.ts +1 -1
  99. package/src/config.ts +10 -1
  100. package/src/frame-sync.ts +15 -10
  101. package/src/harness-window.ts +15 -1
  102. package/src/internal.ts +1 -0
  103. package/src/matchers.ts +29 -2
  104. package/src/pretty-widget.ts +2 -1
  105. package/src/production.ts +2 -3
  106. package/src/render.tsx +67 -12
  107. package/src/role-helpers.ts +2 -1
  108. package/src/screenshot.ts +9 -16
  109. package/src/timers.ts +31 -0
  110. package/src/traversal.ts +22 -0
  111. package/src/types.ts +6 -1
  112. package/src/user-event/adjustment.ts +2 -1
  113. package/src/user-event/click.ts +5 -4
  114. package/src/user-event/column-header-click.ts +2 -16
  115. package/src/user-event/event-wrapper.ts +41 -25
  116. package/src/user-event/index.ts +40 -13
  117. package/src/user-event/keyboard.ts +124 -54
  118. package/src/user-event/list-row-click.ts +4 -7
  119. package/src/user-event/native-click.ts +5 -0
  120. package/src/user-event/notebook-tab-click.ts +57 -0
  121. package/src/user-event/text.ts +113 -38
  122. package/src/wait-for.ts +4 -4
  123. package/src/widget-getters.ts +55 -2
  124. package/src/window-state.ts +70 -0
@@ -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 { scheduleAfterLayout } from \"./frame-sync.js\";\nimport { createHarnessWindow } 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 { 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\nconst reconcilerErrors: ReconcilerErrorState = { lastError: null, isHandlerInstalled: false };\nconst activeRenders: Set<ActiveRender> = new Set();\n\nconst flushLayout = (window: Gtk.Window | null): Promise<void> =>\n new Promise<void>((resolve) => {\n scheduleAfterLayout(window, () => {\n settleAccessible();\n resolve();\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 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.\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 */\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 resolved.window?.present();\n await flushLayout(resolved.window);\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 flushLayout(resolved.window);\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":"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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 +1 @@
1
- {"version":3,"file":"role-helpers.d.ts","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,gBAAgB,CAAC;AAa1D;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAI,MAAM,GAAG,CAAC,cAAc,KAAG,MAQ9C,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,OAAO,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,KAAG,MAe7D,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,QAAQ,GAAI,WAAW,SAAS,KAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAehE,CAAC;AAUF;;;;;;GAMG;AACH,QAAA,MAAM,WAAW,GAAI,WAAW,SAAS,KAAG,MAqB3C,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,QAAQ,GAAI,WAAW,SAAS,KAAG,IAExC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,SAAgD,CAAC;AAE5G,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"role-helpers.d.ts","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,gBAAgB,CAAC;AAc1D;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAI,MAAM,GAAG,CAAC,cAAc,KAAG,MAQ9C,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,OAAO,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,KAAG,MAe7D,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,QAAQ,GAAI,WAAW,SAAS,KAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAehE,CAAC;AAUF;;;;;;GAMG;AACH,QAAA,MAAM,WAAW,GAAI,WAAW,SAAS,KAAG,MAqB3C,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,QAAQ,GAAI,WAAW,SAAS,KAAG,IAExC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,SAAgD,CAAC;AAE5G,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC"}
@@ -2,6 +2,7 @@ import * as Gtk from "@gtkx/gi/gtk";
2
2
  import { sortStringsBy } from "@gtkx/utils";
3
3
  import { traverse } from "./traversal.js";
4
4
  import { getWidgetAccessibleName, getWidgetLevel } from "./widget-accessible-properties.js";
5
+ import { getTypeTag } from "./widget-getters.js";
5
6
  const ROLE_NAMES_BY_VALUE = enumNamesByValue(Gtk.AccessibleRole);
6
7
  function enumNamesByValue(enumObject) {
7
8
  return new Map(Object.entries(enumObject)
@@ -55,7 +56,7 @@ const getRoles = (container) => {
55
56
  return roles;
56
57
  };
57
58
  const formatWidgetPreview = (widget, name) => {
58
- const tagName = widget.constructor.name;
59
+ const tagName = getTypeTag(widget);
59
60
  const roleAttr = formatRole(widget.getAccessibleRole());
60
61
  const nameDisplay = name ? `Name "${name}"` : 'Name ""';
61
62
  return `${nameDisplay}: <${tagName} role="${roleAttr}">${name ?? ""}</${tagName}>`;
@@ -1 +1 @@
1
- {"version":3,"file":"role-helpers.js","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Container, traverse } from \"./traversal.js\";\nimport { getWidgetAccessibleName, getWidgetLevel } from \"./widget-accessible-properties.js\";\n\nconst ROLE_NAMES_BY_VALUE = enumNamesByValue(Gtk.AccessibleRole);\n\nfunction enumNamesByValue(enumObject: Record<string, string | number>): Map<number, string> {\n return new Map<number, string>(\n Object.entries(enumObject)\n .filter((entry): entry is [string, number] => typeof entry[1] === \"number\")\n .map(([name, value]) => [value, name]),\n );\n}\n\n/**\n * Converts an accessible role enum value into its lowercase name, falling back\n * to the numeric value when the role is unknown.\n *\n * @param role The accessible role to format.\n */\nconst formatRole = (role: Gtk.AccessibleRole): string => {\n const name = ROLE_NAMES_BY_VALUE.get(role);\n\n if (!name) {\n return String(role);\n }\n\n return name.toLowerCase();\n};\n\nconst formatRoleList = (roles: Iterable<Gtk.AccessibleRole>): string => {\n const names = [...roles].map((role) => formatRole(role).toUpperCase());\n\n if (names.length <= 1) {\n return names.join(\"\");\n }\n\n if (names.length === 2) {\n return names.join(\" or \");\n }\n\n const head = names.slice(0, -1);\n const last = names.at(-1) ?? \"\";\n\n return `${head.join(\", \")}, or ${last}`;\n};\n\n/**\n * Groups every mapped widget in a container's tree by its accessible role name. Widgets that are not\n * mapped are left out.\n *\n * @param container The scope to traverse.\n * @returns A map from role name to the mapped widgets that have that role.\n */\nconst getRoles = (container: Container): Map<string, Gtk.Widget[]> => {\n const roles: Map<string, Gtk.Widget[]> = new Map();\n\n for (const widget of traverse(container)) {\n const roleName = formatRole(widget.getAccessibleRole());\n const existing = roles.get(roleName);\n\n if (existing) {\n existing.push(widget);\n } else {\n roles.set(roleName, [widget]);\n }\n }\n\n return roles;\n};\n\nconst formatWidgetPreview = (widget: Gtk.Widget, name: string | null): string => {\n const tagName = widget.constructor.name;\n const roleAttr = formatRole(widget.getAccessibleRole());\n const nameDisplay = name ? `Name \"${name}\"` : 'Name \"\"';\n\n return `${nameDisplay}: <${tagName} role=\"${roleAttr}\">${name ?? \"\"}</${tagName}>`;\n};\n\n/**\n * Formats the accessible roles in a container's tree as a readable string,\n * listing each role together with its widgets and their accessible names.\n * Widgets that are not mapped are left out.\n *\n * @param container The scope to inspect.\n */\nconst prettyRoles = (container: Container): string => {\n const roles = getRoles(container);\n\n if (roles.size === 0) {\n return \"No accessible roles found in the widget tree.\";\n }\n\n const lines: string[] = [];\n const sortedRoles = sortStringsBy([...roles], ([roleName]) => roleName);\n\n for (const [roleName, widgets] of sortedRoles) {\n lines.push(`${roleName}:`);\n\n for (const widget of widgets) {\n lines.push(` ${formatWidgetPreview(widget, getWidgetAccessibleName(widget))}`);\n }\n\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n};\n\n/**\n * Prints the accessible roles in a container's tree to the console using\n * {@link prettyRoles}.\n *\n * @param container The scope to inspect.\n */\nconst logRoles = (container: Container): void => {\n console.log(prettyRoles(container));\n};\n\n/**\n * Returns the heading or hierarchy level GTK reports for a widget, or undefined when it declares\n * none.\n *\n * @param widget The widget to read the level from.\n */\nconst computeHeadingLevel = (widget: Gtk.Widget): number | undefined => getWidgetLevel(widget) ?? undefined;\n\nexport { computeHeadingLevel, formatRole, formatRoleList, getRoles, prettyRoles, logRoles };\n"]}
1
+ {"version":3,"file":"role-helpers.js","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Container, traverse } from \"./traversal.js\";\nimport { getWidgetAccessibleName, getWidgetLevel } from \"./widget-accessible-properties.js\";\nimport { getTypeTag } from \"./widget-getters.js\";\n\nconst ROLE_NAMES_BY_VALUE = enumNamesByValue(Gtk.AccessibleRole);\n\nfunction enumNamesByValue(enumObject: Record<string, string | number>): Map<number, string> {\n return new Map<number, string>(\n Object.entries(enumObject)\n .filter((entry): entry is [string, number] => typeof entry[1] === \"number\")\n .map(([name, value]) => [value, name]),\n );\n}\n\n/**\n * Converts an accessible role enum value into its lowercase name, falling back\n * to the numeric value when the role is unknown.\n *\n * @param role The accessible role to format.\n */\nconst formatRole = (role: Gtk.AccessibleRole): string => {\n const name = ROLE_NAMES_BY_VALUE.get(role);\n\n if (!name) {\n return String(role);\n }\n\n return name.toLowerCase();\n};\n\nconst formatRoleList = (roles: Iterable<Gtk.AccessibleRole>): string => {\n const names = [...roles].map((role) => formatRole(role).toUpperCase());\n\n if (names.length <= 1) {\n return names.join(\"\");\n }\n\n if (names.length === 2) {\n return names.join(\" or \");\n }\n\n const head = names.slice(0, -1);\n const last = names.at(-1) ?? \"\";\n\n return `${head.join(\", \")}, or ${last}`;\n};\n\n/**\n * Groups every mapped widget in a container's tree by its accessible role name. Widgets that are not\n * mapped are left out.\n *\n * @param container The scope to traverse.\n * @returns A map from role name to the mapped widgets that have that role.\n */\nconst getRoles = (container: Container): Map<string, Gtk.Widget[]> => {\n const roles: Map<string, Gtk.Widget[]> = new Map();\n\n for (const widget of traverse(container)) {\n const roleName = formatRole(widget.getAccessibleRole());\n const existing = roles.get(roleName);\n\n if (existing) {\n existing.push(widget);\n } else {\n roles.set(roleName, [widget]);\n }\n }\n\n return roles;\n};\n\nconst formatWidgetPreview = (widget: Gtk.Widget, name: string | null): string => {\n const tagName = getTypeTag(widget);\n const roleAttr = formatRole(widget.getAccessibleRole());\n const nameDisplay = name ? `Name \"${name}\"` : 'Name \"\"';\n\n return `${nameDisplay}: <${tagName} role=\"${roleAttr}\">${name ?? \"\"}</${tagName}>`;\n};\n\n/**\n * Formats the accessible roles in a container's tree as a readable string,\n * listing each role together with its widgets and their accessible names.\n * Widgets that are not mapped are left out.\n *\n * @param container The scope to inspect.\n */\nconst prettyRoles = (container: Container): string => {\n const roles = getRoles(container);\n\n if (roles.size === 0) {\n return \"No accessible roles found in the widget tree.\";\n }\n\n const lines: string[] = [];\n const sortedRoles = sortStringsBy([...roles], ([roleName]) => roleName);\n\n for (const [roleName, widgets] of sortedRoles) {\n lines.push(`${roleName}:`);\n\n for (const widget of widgets) {\n lines.push(` ${formatWidgetPreview(widget, getWidgetAccessibleName(widget))}`);\n }\n\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n};\n\n/**\n * Prints the accessible roles in a container's tree to the console using\n * {@link prettyRoles}.\n *\n * @param container The scope to inspect.\n */\nconst logRoles = (container: Container): void => {\n console.log(prettyRoles(container));\n};\n\n/**\n * Returns the heading or hierarchy level GTK reports for a widget, or undefined when it declares\n * none.\n *\n * @param widget The widget to read the level from.\n */\nconst computeHeadingLevel = (widget: Gtk.Widget): number | undefined => getWidgetLevel(widget) ?? undefined;\n\nexport { computeHeadingLevel, formatRole, formatRoleList, getRoles, prettyRoles, logRoles };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAGpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA2RtE;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,UAAU,GAAU,QAAQ,GAAG,CAAC,MAAM,EAAE,UAAU,iBAAiB,KAAG,OAAO,CAAC,gBAAgB,CAkBnG,CAAC;AAkBF,QAAA,MAAM,aAAa,GAAU,UAAU,iBAAiB,KAAG,OAAO,CAAC,gBAAgB,CAIlF,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAGpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA6RtE;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,UAAU,GAAU,QAAQ,GAAG,CAAC,MAAM,EAAE,UAAU,iBAAiB,KAAG,OAAO,CAAC,gBAAgB,CAkBnG,CAAC;AAYF,QAAA,MAAM,aAAa,GAAU,UAAU,iBAAiB,KAAG,OAAO,CAAC,gBAAgB,CAC5C,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC"}
@@ -5,8 +5,10 @@ import * as Gtk from "@gtkx/gi/gtk";
5
5
  import { mkdirSync, writeFileSync } from "node:fs";
6
6
  import { dirname } from "node:path";
7
7
  import { getConfig } from "./config.js";
8
+ import { now } from "./timers.js";
8
9
  import { descendants } from "./traversal.js";
9
10
  import { waitFor } from "./wait-for.js";
11
+ import { activeToplevel, mappedToplevels } from "./window-state.js";
10
12
  const DEFAULT_SCREENSHOT_INTERVAL = 10;
11
13
  const PRESENTATION_PROBE_MS = 250;
12
14
  const NOT_PRESENTING_MESSAGE = "Screenshot failed: the display is not presenting frames to this window, so GTK has no rendered " +
@@ -58,7 +60,7 @@ const requestFrame = (widget) => {
58
60
  };
59
61
  const startFrameProbe = (widget) => {
60
62
  requestFrame(widget);
61
- return { counter: getFrameCounter(widget), startedAt: Date.now() };
63
+ return { counter: getFrameCounter(widget), startedAt: now() };
62
64
  };
63
65
  const updateFrameProbe = (widget, probe) => {
64
66
  requestFrame(widget);
@@ -68,7 +70,7 @@ const updateFrameProbe = (widget, probe) => {
68
70
  const counter = getFrameCounter(widget);
69
71
  if (counter !== null) {
70
72
  probe.counter = counter;
71
- probe.startedAt = Date.now();
73
+ probe.startedAt = now();
72
74
  }
73
75
  };
74
76
  const hasFrameAdvanced = (widget, probe) => {
@@ -76,7 +78,7 @@ const hasFrameAdvanced = (widget, probe) => {
76
78
  return counter !== null && probe.counter !== null && counter > probe.counter;
77
79
  };
78
80
  const isPresenting = (widget, probe) => isSurfaceOnScreen(widget) && hasFrameAdvanced(widget, probe);
79
- const isPresentationStalled = (widget, probe) => Date.now() - probe.startedAt >= PRESENTATION_PROBE_MS && !isPresenting(widget, probe);
81
+ const isPresentationStalled = (widget, probe) => now() - probe.startedAt >= PRESENTATION_PROBE_MS && !isPresenting(widget, probe);
80
82
  const allocateRoot = (widget) => {
81
83
  const root = widget.getRoot();
82
84
  if (!root) {
@@ -207,21 +209,13 @@ const screenshot = async (widget, options) => {
207
209
  }
208
210
  return outcome.result;
209
211
  };
210
- const isWindow = (widget) => widget instanceof Gtk.Window;
211
- const isOnScreen = (window) => window.getMapped();
212
- const isActiveWindow = (window) => window.isActive();
213
- const activeToplevel = () => {
214
- const toplevels = Gtk.Window.listToplevels().filter((widget) => isWindow(widget));
215
- const onScreen = toplevels.filter((window) => isOnScreen(window));
216
- const target = onScreen.find((window) => isActiveWindow(window)) ?? onScreen[0];
212
+ const screenTarget = () => {
213
+ const target = activeToplevel() ?? mappedToplevels()[0];
217
214
  if (!target) {
218
215
  throw new Error(NOTHING_ON_SCREEN_MESSAGE);
219
216
  }
220
217
  return target;
221
218
  };
222
- const captureScreen = async (options) => {
223
- const target = activeToplevel();
224
- return screenshot(target, options);
225
- };
219
+ const captureScreen = async (options) => screenshot(screenTarget(), options);
226
220
  export { captureScreen, screenshot };
227
221
  //# sourceMappingURL=screenshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as Graphene from \"@gtkx/gi/graphene\";\nimport * as Gsk from \"@gtkx/gi/gsk\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { ScreenshotOptions, ScreenshotResult } from \"./types.js\";\nimport { getConfig } from \"./config.js\";\nimport { descendants } from \"./traversal.js\";\nimport { waitFor } from \"./wait-for.js\";\n\ntype FrameProbe = {\n counter: bigint | null;\n startedAt: number;\n};\n\ntype CaptureFailure = \"no-size\" | \"no-content\";\n\ntype CaptureState = {\n probe: FrameProbe;\n failure: CaptureFailure | null;\n};\n\ntype CaptureResult =\n { status: \"captured\"; result: ScreenshotResult } |\n { status: \"failed\"; failure: CaptureFailure };\n\ntype CaptureOutcome =\n { status: \"captured\"; result: ScreenshotResult } |\n { status: \"stalled\"; failure: CaptureFailure };\n\nconst DEFAULT_SCREENSHOT_INTERVAL = 10;\nconst PRESENTATION_PROBE_MS = 250;\n\nconst NOT_PRESENTING_MESSAGE =\n \"Screenshot failed: the display is not presenting frames to this window, so GTK has no rendered \" +\n \"content to capture. The window is hidden, minimized, or its compositor is not presenting it; this \" +\n \"is a display problem, not a widget problem.\";\n\nconst EMPTY_WIDGET_HINT =\n \"The display is presenting frames to this window, so the widget itself is empty: it painted nothing.\";\n\nconst OTHER_FAILURE_HINT =\n \"The display is presenting frames to this window, so the capture failed for another reason.\";\n\nconst NOTHING_ON_SCREEN_MESSAGE = \"Nothing is on screen to capture: no toplevel window is mapped\";\n\nconst bytesToBase64 = (bytes: number[]): string => {\n return Buffer.from(bytes).toString(\"base64\");\n};\n\nconst describeWidgetState = (widget: Gtk.Widget): string =>\n `realized=${String(widget.getRealized())} mapped=${String(widget.getMapped())} ` +\n `visible=${String(widget.getVisible())}`;\n\nconst getMappedPopovers = (widget: Gtk.Widget): Gtk.Popover[] => {\n const popovers: Gtk.Popover[] = [];\n\n for (const descendant of descendants(widget)) {\n if (descendant instanceof Gtk.Popover && descendant.getMapped()) {\n popovers.push(descendant);\n }\n }\n\n return popovers;\n};\n\nconst appendPopover = (snapshot: Gtk.Snapshot, target: Gtk.Widget, popover: Gtk.Popover): void => {\n const [hasBounds, bounds] = popover.computeBounds(target);\n const paintable = new Gtk.WidgetPaintable({ widget: popover });\n const width = paintable.getIntrinsicWidth();\n const height = paintable.getIntrinsicHeight();\n\n if (!hasBounds || width <= 0 || height <= 0) {\n return;\n }\n\n snapshot.save();\n snapshot.translate(new Graphene.Point({ x: bounds.origin.x, y: bounds.origin.y }));\n paintable.snapshot(snapshot, width, height);\n snapshot.restore();\n};\n\nconst appendPopovers = (snapshot: Gtk.Snapshot, target: Gtk.Widget): void => {\n for (const popover of getMappedPopovers(target)) {\n appendPopover(snapshot, target, popover);\n }\n};\n\nconst getSurface = (widget: Gtk.Widget): Gdk.Surface | null => widget.getNative()?.getSurface() ?? null;\nconst isSurfaceOnScreen = (widget: Gtk.Widget): boolean => getSurface(widget)?.getMapped() ?? false;\n\nconst getFrameClock = (widget: Gtk.Widget): Gdk.FrameClock | null =>\n widget.getRoot()?.getFrameClock() ?? widget.getFrameClock();\n\nconst getFrameCounter = (widget: Gtk.Widget): bigint | null => getFrameClock(widget)?.getFrameCounter() ?? null;\n\nconst describePresentation = (widget: Gtk.Widget): string =>\n `${describeWidgetState(widget)} surfaceMapped=${String(isSurfaceOnScreen(widget))} ` +\n `frameCounter=${String(getFrameCounter(widget))}`;\n\nconst requestFrame = (widget: Gtk.Widget): void => {\n getFrameClock(widget)?.requestPhase(Gdk.FrameClockPhase.UPDATE);\n};\n\nconst startFrameProbe = (widget: Gtk.Widget): FrameProbe => {\n requestFrame(widget);\n\n return { counter: getFrameCounter(widget), startedAt: Date.now() };\n};\n\nconst updateFrameProbe = (widget: Gtk.Widget, probe: FrameProbe): void => {\n requestFrame(widget);\n\n if (probe.counter !== null) {\n return;\n }\n\n const counter = getFrameCounter(widget);\n\n if (counter !== null) {\n probe.counter = counter;\n probe.startedAt = Date.now();\n }\n};\n\nconst hasFrameAdvanced = (widget: Gtk.Widget, probe: FrameProbe): boolean => {\n const counter = getFrameCounter(widget);\n\n return counter !== null && probe.counter !== null && counter > probe.counter;\n};\n\nconst isPresenting = (widget: Gtk.Widget, probe: FrameProbe): boolean =>\n isSurfaceOnScreen(widget) && hasFrameAdvanced(widget, probe);\n\nconst isPresentationStalled = (widget: Gtk.Widget, probe: FrameProbe): boolean =>\n Date.now() - probe.startedAt >= PRESENTATION_PROBE_MS && !isPresenting(widget, probe);\n\nconst allocateRoot = (widget: Gtk.Widget): void => {\n const root = widget.getRoot();\n\n if (!root) {\n return;\n }\n\n const width = root.getWidth();\n const height = root.getHeight();\n\n if (width > 0 && height > 0) {\n root.allocate(width, height, -1, null);\n }\n};\n\nconst isDirectlyPaintable = (child: Gtk.Widget): boolean =>\n child.getMapped() && child.getWidth() > 0 && !(child instanceof Gtk.Popover);\n\nconst getPaintableNode = (widget: Gtk.Widget, scale: number, width: number, height: number): Gsk.RenderNode | null => {\n const paintable = new Gtk.WidgetPaintable({ widget });\n const snapshot = new Gtk.Snapshot();\n snapshot.scale(scale, scale);\n paintable.snapshot(snapshot, width, height);\n appendPopovers(snapshot, widget);\n\n return snapshot.toNode();\n};\n\nconst getChildrenNode = (widget: Gtk.Widget, scale: number): Gsk.RenderNode | null => {\n const snapshot = new Gtk.Snapshot();\n snapshot.scale(scale, scale);\n\n for (let child = widget.getFirstChild(); child !== null; child = child.getNextSibling()) {\n if (isDirectlyPaintable(child)) {\n widget.snapshotChild(child, snapshot);\n }\n }\n\n appendPopovers(snapshot, widget);\n\n return snapshot.toNode();\n};\n\nconst getRenderNode = (widget: Gtk.Widget, scale: number, width: number, height: number): Gsk.RenderNode | null => {\n const presented = getPaintableNode(widget, scale, width, height);\n\n if (presented) {\n return presented;\n }\n\n allocateRoot(widget);\n\n return getPaintableNode(widget, scale, width, height) ?? getChildrenNode(widget, scale);\n};\n\nconst renderToPng = (widget: Gtk.Widget, node: Gsk.RenderNode, width: number, height: number): ScreenshotResult => {\n const renderer = new Gsk.CairoRenderer();\n renderer.realizeForDisplay(widget.getDisplay());\n\n try {\n const viewport = Graphene.Rect.alloc().init(0, 0, width, height);\n const texture = renderer.renderTexture(node, viewport);\n const data = texture.saveToPngBytes().getData();\n\n if (!data) {\n throw new Error(\"Failed to serialize screenshot to PNG\");\n }\n\n return { data: bytesToBase64(data), mimeType: \"image/png\", width, height };\n } finally {\n renderer.unrealize();\n }\n};\n\nconst captureSnapshot = (widget: Gtk.Widget, scale: number): CaptureResult => {\n const paintable = new Gtk.WidgetPaintable({ widget });\n const width = paintable.getIntrinsicWidth();\n const height = paintable.getIntrinsicHeight();\n\n if (width <= 0 || height <= 0) {\n return { status: \"failed\", failure: \"no-size\" };\n }\n\n const renderNode = getRenderNode(widget, scale, width, height);\n\n if (!renderNode) {\n return { status: \"failed\", failure: \"no-content\" };\n }\n\n const scaledWidth = Math.round(width * scale);\n const scaledHeight = Math.round(height * scale);\n\n return { status: \"captured\", result: renderToPng(widget, renderNode, scaledWidth, scaledHeight) };\n};\n\nconst failureMessage = (widget: Gtk.Widget, failure: CaptureFailure): string =>\n failure === \"no-size\"\n ? `Widget has no size: ensure it is realized and visible (${describeWidgetState(widget)})`\n : `Widget produced no render content (${describeWidgetState(widget)})`;\n\nconst notPresentingMessage = (widget: Gtk.Widget): string =>\n `${NOT_PRESENTING_MESSAGE} (${describePresentation(widget)})`;\n\nconst stalledMessage = (widget: Gtk.Widget, failure: CaptureFailure): string =>\n `${notPresentingMessage(widget)}\\n\\n${failureMessage(widget, failure)}`;\n\nconst presentingHint = (failure: CaptureFailure | null): string =>\n failure === \"no-content\" ? EMPTY_WIDGET_HINT : OTHER_FAILURE_HINT;\n\nconst timeoutHint = (widget: Gtk.Widget, state: CaptureState): string =>\n isPresenting(widget, state.probe) ? presentingHint(state.failure) : notPresentingMessage(widget);\n\nconst explainTimeout = (error: Error, widget: Gtk.Widget, state: CaptureState): Error =>\n getConfig().getElementError(`${error.message}\\n\\n${timeoutHint(widget, state)}`);\n\nconst attemptCapture = (widget: Gtk.Widget, scale: number, state: CaptureState): CaptureOutcome => {\n const attempt = captureSnapshot(widget, scale);\n\n if (attempt.status === \"captured\") {\n return attempt;\n }\n\n state.failure = attempt.failure;\n updateFrameProbe(widget, state.probe);\n\n if (isPresentationStalled(widget, state.probe)) {\n return { status: \"stalled\", failure: attempt.failure };\n }\n\n throw new Error(failureMessage(widget, attempt.failure));\n};\n\nconst writeScreenshot = (result: ScreenshotResult, path: string): void => {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, Buffer.from(result.data, \"base64\"));\n};\n\nconst captureUntilPaintable = (\n widget: Gtk.Widget,\n scale: number,\n options: ScreenshotOptions | undefined,\n): Promise<CaptureOutcome> => {\n const state: CaptureState = { probe: startFrameProbe(widget), failure: null };\n\n return waitFor(() => attemptCapture(widget, scale, state), {\n timeout: options?.timeout,\n interval: options?.interval ?? DEFAULT_SCREENSHOT_INTERVAL,\n onTimeout: (error) => explainTimeout(error, widget, state),\n });\n};\n\n/**\n * Captures a PNG snapshot of a widget, retrying until it has a paintable size,\n * and writes the image to `options.path` when one is given, creating any\n * missing parent directories. Popovers open inside the widget render on their\n * own surfaces, so they are composited into the image at their on-screen\n * positions. A display that never presents a frame leaves GTK without a cached\n * render node, so the widget's contents are then snapshotted directly; when\n * even that yields nothing, the failure names the display instead of blaming\n * the widget.\n *\n * @param widget The widget to render to an image.\n * @param options Optional scale, timeout, retry interval, and output path.\n * @returns The base64-encoded PNG data along with its mime type and dimensions.\n */\nconst screenshot = async (widget: Gtk.Widget, options?: ScreenshotOptions): Promise<ScreenshotResult> => {\n const scale = options?.scale ?? 1;\n\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new Error(`Screenshot scale must be a positive number, got ${String(scale)}`);\n }\n\n const outcome = await captureUntilPaintable(widget, scale, options);\n\n if (outcome.status === \"stalled\") {\n throw new Error(stalledMessage(widget, outcome.failure));\n }\n\n if (options?.path) {\n writeScreenshot(outcome.result, options.path);\n }\n\n return outcome.result;\n};\n\nconst isWindow = (widget: Gtk.Widget): widget is Gtk.Window => widget instanceof Gtk.Window;\nconst isOnScreen = (window: Gtk.Window): boolean => window.getMapped();\nconst isActiveWindow = (window: Gtk.Window): boolean => window.isActive();\n\nconst activeToplevel = (): Gtk.Window => {\n const toplevels = Gtk.Window.listToplevels().filter((widget) => isWindow(widget));\n const onScreen = toplevels.filter((window) => isOnScreen(window));\n const target = onScreen.find((window) => isActiveWindow(window)) ?? onScreen[0];\n\n if (!target) {\n throw new Error(NOTHING_ON_SCREEN_MESSAGE);\n }\n\n return target;\n};\n\nconst captureScreen = async (options?: ScreenshotOptions): Promise<ScreenshotResult> => {\n const target = activeToplevel();\n\n return screenshot(target, options);\n};\n\nexport { captureScreen, screenshot };\n"]}
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAsBpE,MAAM,2BAA2B,GAAG,EAAE,CAAC;AACvC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC,MAAM,sBAAsB,GACxB,iGAAiG;IACjG,oGAAoG;IACpG,6CAA6C,CAAC;AAElD,MAAM,iBAAiB,GACnB,qGAAqG,CAAC;AAE1G,MAAM,kBAAkB,GACpB,4FAA4F,CAAC;AAEjG,MAAM,yBAAyB,GAAG,+DAA+D,CAAC;AAElG,MAAM,aAAa,GAAG,CAAC,KAAe,EAAU,EAAE;IAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,MAAkB,EAAU,EAAE,CACvD,YAAY,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,GAAG;IAChF,WAAW,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AAE7C,MAAM,iBAAiB,GAAG,CAAC,MAAkB,EAAiB,EAAE;IAC5D,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,UAAU,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,IAAI,UAAU,YAAY,GAAG,CAAC,OAAO,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;YAC9D,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,QAAsB,EAAE,MAAkB,EAAE,OAAoB,EAAQ,EAAE;IAC7F,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,SAAS,CAAC,iBAAiB,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,kBAAkB,EAAE,CAAC;IAE9C,IAAI,CAAC,SAAS,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO;IACX,CAAC;IAED,QAAQ,CAAC,IAAI,EAAE,CAAC;IAChB,QAAQ,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,QAAsB,EAAE,MAAkB,EAAQ,EAAE;IACxE,KAAK,MAAM,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,MAAkB,EAAsB,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC;AACxG,MAAM,iBAAiB,GAAG,CAAC,MAAkB,EAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,KAAK,CAAC;AAEpG,MAAM,aAAa,GAAG,CAAC,MAAkB,EAAyB,EAAE,CAChE,MAAM,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;AAEhE,MAAM,eAAe,GAAG,CAAC,MAAkB,EAAiB,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,IAAI,IAAI,CAAC;AAEhH,MAAM,oBAAoB,GAAG,CAAC,MAAkB,EAAU,EAAE,CACxD,GAAG,mBAAmB,CAAC,MAAM,CAAC,kBAAkB,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG;IACpF,gBAAgB,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;AAEtD,MAAM,YAAY,GAAG,CAAC,MAAkB,EAAQ,EAAE;IAC9C,aAAa,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,MAAkB,EAAc,EAAE;IACvD,YAAY,CAAC,MAAM,CAAC,CAAC;IAErB,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC;AAClE,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,MAAkB,EAAE,KAAiB,EAAQ,EAAE;IACrE,YAAY,CAAC,MAAM,CAAC,CAAC;IAErB,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO;IACX,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAExC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACxB,KAAK,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;IAC5B,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,MAAkB,EAAE,KAAiB,EAAW,EAAE;IACxE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAExC,OAAO,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AACjF,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,MAAkB,EAAE,KAAiB,EAAW,EAAE,CACpE,iBAAiB,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAEjE,MAAM,qBAAqB,GAAG,CAAC,MAAkB,EAAE,KAAiB,EAAW,EAAE,CAC7E,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,qBAAqB,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAErF,MAAM,YAAY,GAAG,CAAC,MAAkB,EAAQ,EAAE;IAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IAE9B,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO;IACX,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAEhC,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAW,EAAE,CACvD,KAAK,CAAC,SAAS,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,OAAO,CAAC,CAAC;AAEjF,MAAM,gBAAgB,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAE,KAAa,EAAE,MAAc,EAAyB,EAAE;IACjH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC7B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEjC,OAAO,QAAQ,CAAC,MAAM,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAyB,EAAE;IACjF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE7B,KAAK,IAAI,KAAK,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;QACtF,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;IAED,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEjC,OAAO,QAAQ,CAAC,MAAM,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAE,KAAa,EAAE,MAAc,EAAyB,EAAE;IAC9G,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAEjE,IAAI,SAAS,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,YAAY,CAAC,MAAM,CAAC,CAAC;IAErB,OAAO,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC5F,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,MAAkB,EAAE,IAAoB,EAAE,KAAa,EAAE,MAAc,EAAoB,EAAE;IAC9G,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAEhD,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACjE,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,OAAO,EAAE,CAAC;QAEhD,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC/E,CAAC;YAAS,CAAC;QACP,QAAQ,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAiB,EAAE;IACzE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,SAAS,CAAC,iBAAiB,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,kBAAkB,EAAE,CAAC;IAE9C,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IACpD,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;IAEhD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,CAAC;AACtG,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,MAAkB,EAAE,OAAuB,EAAU,EAAE,CAC3E,OAAO,KAAK,SAAS;IACjB,CAAC,CAAC,0DAA0D,mBAAmB,CAAC,MAAM,CAAC,GAAG;IAC1F,CAAC,CAAC,sCAAsC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC;AAE/E,MAAM,oBAAoB,GAAG,CAAC,MAAkB,EAAU,EAAE,CACxD,GAAG,sBAAsB,KAAK,oBAAoB,CAAC,MAAM,CAAC,GAAG,CAAC;AAElE,MAAM,cAAc,GAAG,CAAC,MAAkB,EAAE,OAAuB,EAAU,EAAE,CAC3E,GAAG,oBAAoB,CAAC,MAAM,CAAC,OAAO,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;AAE5E,MAAM,cAAc,GAAG,CAAC,OAA8B,EAAU,EAAE,CAC9D,OAAO,KAAK,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CAAC;AAEtE,MAAM,WAAW,GAAG,CAAC,MAAkB,EAAE,KAAmB,EAAU,EAAE,CACpE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAErG,MAAM,cAAc,GAAG,CAAC,KAAY,EAAE,MAAkB,EAAE,KAAmB,EAAS,EAAE,CACpF,SAAS,EAAE,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,OAAO,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;AAErF,MAAM,cAAc,GAAG,CAAC,MAAkB,EAAE,KAAa,EAAE,KAAmB,EAAkB,EAAE;IAC9F,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE/C,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,MAAwB,EAAE,IAAY,EAAQ,EAAE;IACrE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAC1B,MAAkB,EAClB,KAAa,EACb,OAAsC,EACf,EAAE;IACzB,MAAM,KAAK,GAAiB,EAAE,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAE9E,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE;QACvD,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,2BAA2B;QAC1D,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC;KAC7D,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,GAAG,KAAK,EAAE,MAAkB,EAAE,OAA2B,EAA6B,EAAE;IACpG,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC;IAElC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,mDAAmD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAEpE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;QAChB,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,GAAe,EAAE;IAClC,MAAM,MAAM,GAAG,cAAc,EAAE,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;IAExD,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,KAAK,EAAE,OAA2B,EAA6B,EAAE,CACnF,UAAU,CAAC,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as Graphene from \"@gtkx/gi/graphene\";\nimport * as Gsk from \"@gtkx/gi/gsk\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { ScreenshotOptions, ScreenshotResult } from \"./types.js\";\nimport { getConfig } from \"./config.js\";\nimport { now } from \"./timers.js\";\nimport { descendants } from \"./traversal.js\";\nimport { waitFor } from \"./wait-for.js\";\nimport { activeToplevel, mappedToplevels } from \"./window-state.js\";\n\ntype FrameProbe = {\n counter: bigint | null;\n startedAt: number;\n};\n\ntype CaptureFailure = \"no-size\" | \"no-content\";\n\ntype CaptureState = {\n probe: FrameProbe;\n failure: CaptureFailure | null;\n};\n\ntype CaptureResult =\n { status: \"captured\"; result: ScreenshotResult } |\n { status: \"failed\"; failure: CaptureFailure };\n\ntype CaptureOutcome =\n { status: \"captured\"; result: ScreenshotResult } |\n { status: \"stalled\"; failure: CaptureFailure };\n\nconst DEFAULT_SCREENSHOT_INTERVAL = 10;\nconst PRESENTATION_PROBE_MS = 250;\n\nconst NOT_PRESENTING_MESSAGE =\n \"Screenshot failed: the display is not presenting frames to this window, so GTK has no rendered \" +\n \"content to capture. The window is hidden, minimized, or its compositor is not presenting it; this \" +\n \"is a display problem, not a widget problem.\";\n\nconst EMPTY_WIDGET_HINT =\n \"The display is presenting frames to this window, so the widget itself is empty: it painted nothing.\";\n\nconst OTHER_FAILURE_HINT =\n \"The display is presenting frames to this window, so the capture failed for another reason.\";\n\nconst NOTHING_ON_SCREEN_MESSAGE = \"Nothing is on screen to capture: no toplevel window is mapped\";\n\nconst bytesToBase64 = (bytes: number[]): string => {\n return Buffer.from(bytes).toString(\"base64\");\n};\n\nconst describeWidgetState = (widget: Gtk.Widget): string =>\n `realized=${String(widget.getRealized())} mapped=${String(widget.getMapped())} ` +\n `visible=${String(widget.getVisible())}`;\n\nconst getMappedPopovers = (widget: Gtk.Widget): Gtk.Popover[] => {\n const popovers: Gtk.Popover[] = [];\n\n for (const descendant of descendants(widget)) {\n if (descendant instanceof Gtk.Popover && descendant.getMapped()) {\n popovers.push(descendant);\n }\n }\n\n return popovers;\n};\n\nconst appendPopover = (snapshot: Gtk.Snapshot, target: Gtk.Widget, popover: Gtk.Popover): void => {\n const [hasBounds, bounds] = popover.computeBounds(target);\n const paintable = new Gtk.WidgetPaintable({ widget: popover });\n const width = paintable.getIntrinsicWidth();\n const height = paintable.getIntrinsicHeight();\n\n if (!hasBounds || width <= 0 || height <= 0) {\n return;\n }\n\n snapshot.save();\n snapshot.translate(new Graphene.Point({ x: bounds.origin.x, y: bounds.origin.y }));\n paintable.snapshot(snapshot, width, height);\n snapshot.restore();\n};\n\nconst appendPopovers = (snapshot: Gtk.Snapshot, target: Gtk.Widget): void => {\n for (const popover of getMappedPopovers(target)) {\n appendPopover(snapshot, target, popover);\n }\n};\n\nconst getSurface = (widget: Gtk.Widget): Gdk.Surface | null => widget.getNative()?.getSurface() ?? null;\nconst isSurfaceOnScreen = (widget: Gtk.Widget): boolean => getSurface(widget)?.getMapped() ?? false;\n\nconst getFrameClock = (widget: Gtk.Widget): Gdk.FrameClock | null =>\n widget.getRoot()?.getFrameClock() ?? widget.getFrameClock();\n\nconst getFrameCounter = (widget: Gtk.Widget): bigint | null => getFrameClock(widget)?.getFrameCounter() ?? null;\n\nconst describePresentation = (widget: Gtk.Widget): string =>\n `${describeWidgetState(widget)} surfaceMapped=${String(isSurfaceOnScreen(widget))} ` +\n `frameCounter=${String(getFrameCounter(widget))}`;\n\nconst requestFrame = (widget: Gtk.Widget): void => {\n getFrameClock(widget)?.requestPhase(Gdk.FrameClockPhase.UPDATE);\n};\n\nconst startFrameProbe = (widget: Gtk.Widget): FrameProbe => {\n requestFrame(widget);\n\n return { counter: getFrameCounter(widget), startedAt: now() };\n};\n\nconst updateFrameProbe = (widget: Gtk.Widget, probe: FrameProbe): void => {\n requestFrame(widget);\n\n if (probe.counter !== null) {\n return;\n }\n\n const counter = getFrameCounter(widget);\n\n if (counter !== null) {\n probe.counter = counter;\n probe.startedAt = now();\n }\n};\n\nconst hasFrameAdvanced = (widget: Gtk.Widget, probe: FrameProbe): boolean => {\n const counter = getFrameCounter(widget);\n\n return counter !== null && probe.counter !== null && counter > probe.counter;\n};\n\nconst isPresenting = (widget: Gtk.Widget, probe: FrameProbe): boolean =>\n isSurfaceOnScreen(widget) && hasFrameAdvanced(widget, probe);\n\nconst isPresentationStalled = (widget: Gtk.Widget, probe: FrameProbe): boolean =>\n now() - probe.startedAt >= PRESENTATION_PROBE_MS && !isPresenting(widget, probe);\n\nconst allocateRoot = (widget: Gtk.Widget): void => {\n const root = widget.getRoot();\n\n if (!root) {\n return;\n }\n\n const width = root.getWidth();\n const height = root.getHeight();\n\n if (width > 0 && height > 0) {\n root.allocate(width, height, -1, null);\n }\n};\n\nconst isDirectlyPaintable = (child: Gtk.Widget): boolean =>\n child.getMapped() && child.getWidth() > 0 && !(child instanceof Gtk.Popover);\n\nconst getPaintableNode = (widget: Gtk.Widget, scale: number, width: number, height: number): Gsk.RenderNode | null => {\n const paintable = new Gtk.WidgetPaintable({ widget });\n const snapshot = new Gtk.Snapshot();\n snapshot.scale(scale, scale);\n paintable.snapshot(snapshot, width, height);\n appendPopovers(snapshot, widget);\n\n return snapshot.toNode();\n};\n\nconst getChildrenNode = (widget: Gtk.Widget, scale: number): Gsk.RenderNode | null => {\n const snapshot = new Gtk.Snapshot();\n snapshot.scale(scale, scale);\n\n for (let child = widget.getFirstChild(); child !== null; child = child.getNextSibling()) {\n if (isDirectlyPaintable(child)) {\n widget.snapshotChild(child, snapshot);\n }\n }\n\n appendPopovers(snapshot, widget);\n\n return snapshot.toNode();\n};\n\nconst getRenderNode = (widget: Gtk.Widget, scale: number, width: number, height: number): Gsk.RenderNode | null => {\n const presented = getPaintableNode(widget, scale, width, height);\n\n if (presented) {\n return presented;\n }\n\n allocateRoot(widget);\n\n return getPaintableNode(widget, scale, width, height) ?? getChildrenNode(widget, scale);\n};\n\nconst renderToPng = (widget: Gtk.Widget, node: Gsk.RenderNode, width: number, height: number): ScreenshotResult => {\n const renderer = new Gsk.CairoRenderer();\n renderer.realizeForDisplay(widget.getDisplay());\n\n try {\n const viewport = Graphene.Rect.alloc().init(0, 0, width, height);\n const texture = renderer.renderTexture(node, viewport);\n const data = texture.saveToPngBytes().getData();\n\n if (!data) {\n throw new Error(\"Failed to serialize screenshot to PNG\");\n }\n\n return { data: bytesToBase64(data), mimeType: \"image/png\", width, height };\n } finally {\n renderer.unrealize();\n }\n};\n\nconst captureSnapshot = (widget: Gtk.Widget, scale: number): CaptureResult => {\n const paintable = new Gtk.WidgetPaintable({ widget });\n const width = paintable.getIntrinsicWidth();\n const height = paintable.getIntrinsicHeight();\n\n if (width <= 0 || height <= 0) {\n return { status: \"failed\", failure: \"no-size\" };\n }\n\n const renderNode = getRenderNode(widget, scale, width, height);\n\n if (!renderNode) {\n return { status: \"failed\", failure: \"no-content\" };\n }\n\n const scaledWidth = Math.round(width * scale);\n const scaledHeight = Math.round(height * scale);\n\n return { status: \"captured\", result: renderToPng(widget, renderNode, scaledWidth, scaledHeight) };\n};\n\nconst failureMessage = (widget: Gtk.Widget, failure: CaptureFailure): string =>\n failure === \"no-size\"\n ? `Widget has no size: ensure it is realized and visible (${describeWidgetState(widget)})`\n : `Widget produced no render content (${describeWidgetState(widget)})`;\n\nconst notPresentingMessage = (widget: Gtk.Widget): string =>\n `${NOT_PRESENTING_MESSAGE} (${describePresentation(widget)})`;\n\nconst stalledMessage = (widget: Gtk.Widget, failure: CaptureFailure): string =>\n `${notPresentingMessage(widget)}\\n\\n${failureMessage(widget, failure)}`;\n\nconst presentingHint = (failure: CaptureFailure | null): string =>\n failure === \"no-content\" ? EMPTY_WIDGET_HINT : OTHER_FAILURE_HINT;\n\nconst timeoutHint = (widget: Gtk.Widget, state: CaptureState): string =>\n isPresenting(widget, state.probe) ? presentingHint(state.failure) : notPresentingMessage(widget);\n\nconst explainTimeout = (error: Error, widget: Gtk.Widget, state: CaptureState): Error =>\n getConfig().getElementError(`${error.message}\\n\\n${timeoutHint(widget, state)}`);\n\nconst attemptCapture = (widget: Gtk.Widget, scale: number, state: CaptureState): CaptureOutcome => {\n const attempt = captureSnapshot(widget, scale);\n\n if (attempt.status === \"captured\") {\n return attempt;\n }\n\n state.failure = attempt.failure;\n updateFrameProbe(widget, state.probe);\n\n if (isPresentationStalled(widget, state.probe)) {\n return { status: \"stalled\", failure: attempt.failure };\n }\n\n throw new Error(failureMessage(widget, attempt.failure));\n};\n\nconst writeScreenshot = (result: ScreenshotResult, path: string): void => {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, Buffer.from(result.data, \"base64\"));\n};\n\nconst captureUntilPaintable = (\n widget: Gtk.Widget,\n scale: number,\n options: ScreenshotOptions | undefined,\n): Promise<CaptureOutcome> => {\n const state: CaptureState = { probe: startFrameProbe(widget), failure: null };\n\n return waitFor(() => attemptCapture(widget, scale, state), {\n timeout: options?.timeout,\n interval: options?.interval ?? DEFAULT_SCREENSHOT_INTERVAL,\n onTimeout: (error) => explainTimeout(error, widget, state),\n });\n};\n\n/**\n * Captures a PNG snapshot of a widget, retrying until it has a paintable size,\n * and writes the image to `options.path` when one is given, creating any\n * missing parent directories. Popovers open inside the widget render on their\n * own surfaces, so they are composited into the image at their on-screen\n * positions. A display that never presents a frame leaves GTK without a cached\n * render node, so the widget's contents are then snapshotted directly; when\n * even that yields nothing, the failure names the display instead of blaming\n * the widget.\n *\n * @param widget The widget to render to an image.\n * @param options Optional scale, timeout, retry interval, and output path.\n * @returns The base64-encoded PNG data along with its mime type and dimensions.\n */\nconst screenshot = async (widget: Gtk.Widget, options?: ScreenshotOptions): Promise<ScreenshotResult> => {\n const scale = options?.scale ?? 1;\n\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new Error(`Screenshot scale must be a positive number, got ${String(scale)}`);\n }\n\n const outcome = await captureUntilPaintable(widget, scale, options);\n\n if (outcome.status === \"stalled\") {\n throw new Error(stalledMessage(widget, outcome.failure));\n }\n\n if (options?.path) {\n writeScreenshot(outcome.result, options.path);\n }\n\n return outcome.result;\n};\n\nconst screenTarget = (): Gtk.Window => {\n const target = activeToplevel() ?? mappedToplevels()[0];\n\n if (!target) {\n throw new Error(NOTHING_ON_SCREEN_MESSAGE);\n }\n\n return target;\n};\n\nconst captureScreen = async (options?: ScreenshotOptions): Promise<ScreenshotResult> =>\n screenshot(screenTarget(), options);\n\nexport { captureScreen, screenshot };\n"]}
@@ -0,0 +1,9 @@
1
+ import { setTimeout } from "node:timers";
2
+ type TimeoutHandle = ReturnType<typeof setTimeout>;
3
+ declare const now: () => number;
4
+ declare const scheduleTimeout: (callback: () => void, ms: number) => TimeoutHandle;
5
+ declare const cancelTimeout: (handle: TimeoutHandle) => void;
6
+ declare const delay: (ms: number) => Promise<void>;
7
+ declare const advanceFakeClock: (ms: number) => Promise<void>;
8
+ export { advanceFakeClock, cancelTimeout, delay, now, scheduleTimeout };
9
+ //# sourceMappingURL=timers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../src/timers.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,UAAU,EAAE,MAAM,aAAa,CAAC;AAGvD,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAEnD,QAAA,MAAM,GAAG,QAAO,MAA2B,CAAC;AAC5C,QAAA,MAAM,eAAe,GAAI,UAAU,MAAM,IAAI,EAAE,IAAI,MAAM,KAAG,aAAyC,CAAC;AAEtG,QAAA,MAAM,aAAa,GAAI,QAAQ,aAAa,KAAG,IAE9C,CAAC;AAEF,QAAA,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CAKlC,CAAC;AAQP,QAAA,MAAM,gBAAgB,GAAU,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CAExD,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC"}
package/dist/timers.js ADDED
@@ -0,0 +1,21 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { clearTimeout, setTimeout } from "node:timers";
3
+ const now = () => performance.now();
4
+ const scheduleTimeout = (callback, ms) => setTimeout(callback, ms);
5
+ const cancelTimeout = (handle) => {
6
+ clearTimeout(handle);
7
+ };
8
+ const delay = (ms) => new Promise((resolve) => {
9
+ scheduleTimeout(() => {
10
+ resolve();
11
+ }, ms);
12
+ });
13
+ const getFakeClock = () => {
14
+ const { clock } = globalThis.setTimeout;
15
+ return clock ?? null;
16
+ };
17
+ const advanceFakeClock = async (ms) => {
18
+ await getFakeClock()?.tickAsync(ms);
19
+ };
20
+ export { advanceFakeClock, cancelTimeout, delay, now, scheduleTimeout };
21
+ //# sourceMappingURL=timers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timers.js","sourceRoot":"","sources":["../src/timers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKvD,MAAM,GAAG,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;AAC5C,MAAM,eAAe,GAAG,CAAC,QAAoB,EAAE,EAAU,EAAiB,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAEtG,MAAM,aAAa,GAAG,CAAC,MAAqB,EAAQ,EAAE;IAClD,YAAY,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CACxC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACpB,eAAe,CAAC,GAAG,EAAE;QACjB,OAAO,EAAE,CAAC;IACd,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC,CAAC,CAAC;AAEP,MAAM,YAAY,GAAG,GAAqB,EAAE;IACxC,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,UAAkE,CAAC;IAEhG,OAAO,KAAK,IAAI,IAAI,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAAE,EAAU,EAAiB,EAAE;IACzD,MAAM,YAAY,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import { performance } from \"node:perf_hooks\";\nimport { clearTimeout, setTimeout } from \"node:timers\";\n\ntype FakeClock = { tickAsync: (ms: number) => Promise<unknown> };\ntype TimeoutHandle = ReturnType<typeof setTimeout>;\n\nconst now = (): number => performance.now();\nconst scheduleTimeout = (callback: () => void, ms: number): TimeoutHandle => setTimeout(callback, ms);\n\nconst cancelTimeout = (handle: TimeoutHandle): void => {\n clearTimeout(handle);\n};\n\nconst delay = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n scheduleTimeout(() => {\n resolve();\n }, ms);\n });\n\nconst getFakeClock = (): FakeClock | null => {\n const { clock } = globalThis.setTimeout as typeof globalThis.setTimeout & { clock?: FakeClock };\n\n return clock ?? null;\n};\n\nconst advanceFakeClock = async (ms: number): Promise<void> => {\n await getFakeClock()?.tickAsync(ms);\n};\n\nexport { advanceFakeClock, cancelTimeout, delay, now, scheduleTimeout };\n"]}
@@ -10,14 +10,17 @@ type QueryContainer = Gtk.Widget | Gtk.EventController | Gtk.LayoutManager | Gtk
10
10
  * sentinel representing all current toplevel windows.
11
11
  */
12
12
  type Container = QueryContainer | Gtk.Application | typeof TOPLEVELS;
13
+ type WidgetClass<T extends Gtk.Widget> = abstract new (...args: never[]) => T;
13
14
  /** Container sentinel that widens a query to every toplevel window currently open. */
14
15
  declare const TOPLEVELS: unique symbol;
15
16
  declare const isOnScreen: (widget: Gtk.Widget) => boolean;
16
17
  declare const children: (widget: Gtk.Widget) => Generator<Gtk.Widget>;
17
18
  declare const descendants: (widget: Gtk.Widget) => Generator<Gtk.Widget>;
19
+ declare const ancestors: (widget: Gtk.Widget) => Generator<Gtk.Widget>;
20
+ declare const ancestorFor: <T extends Gtk.Widget>(widget: Gtk.Widget, type: WidgetClass<T>) => T | null;
18
21
  declare const relationCandidates: (widget: Gtk.Widget) => Gtk.Accessible[];
19
22
  declare const roots: (container: Container) => Generator<Gtk.Widget>;
20
23
  declare const traverse: (container: Container) => Generator<Gtk.Widget>;
21
24
  declare const findAll: (container: Container, isMatch: (node: Gtk.Widget) => boolean) => Gtk.Widget[];
22
- export { TOPLEVELS, children, descendants, findAll, isOnScreen, relationCandidates, roots, traverse, type Container, };
25
+ export { TOPLEVELS, ancestorFor, ancestors, children, descendants, findAll, isOnScreen, relationCandidates, roots, traverse, type Container, };
23
26
  //# sourceMappingURL=traversal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"traversal.d.ts","sourceRoot":"","sources":["../src/traversal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC;;;GAGG;AACH,KAAK,cAAc,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC;AAC3G;;;;GAIG;AACH,KAAK,SAAS,GAAG,cAAc,GAAG,GAAG,CAAC,WAAW,GAAG,OAAO,SAAS,CAAC;AAErE,sFAAsF;AACtF,QAAA,MAAM,SAAS,EAAE,OAAO,MAAiC,CAAC;AAI1D,QAAA,MAAM,UAAU,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAA6B,CAAC;AAkBvE,QAAA,MAAM,QAAQ,GAAc,QAAQ,GAAG,CAAC,MAAM,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAOpE,CAAC;AAEF,QAAA,MAAM,WAAW,GAAc,QAAQ,GAAG,CAAC,MAAM,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAIvE,CAAC;AAEF,QAAA,MAAM,kBAAkB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,GAAG,CAAC,UAAU,EAS9D,CAAC;AAsBF,QAAA,MAAM,KAAK,GAAc,WAAW,SAAS,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAYnE,CAAC;AAEF,QAAA,MAAM,QAAQ,GAAc,WAAW,SAAS,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAItE,CAAC;AAEF,QAAA,MAAM,OAAO,GAAI,WAAW,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO,KAAG,GAAG,CAAC,MAAM,EAUzF,CAAC;AAEF,OAAO,EACH,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,QAAQ,EACR,KAAK,SAAS,GACjB,CAAC"}
1
+ {"version":3,"file":"traversal.d.ts","sourceRoot":"","sources":["../src/traversal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC;;;GAGG;AACH,KAAK,cAAc,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC;AAC3G;;;;GAIG;AACH,KAAK,SAAS,GAAG,cAAc,GAAG,GAAG,CAAC,WAAW,GAAG,OAAO,SAAS,CAAC;AACrE,KAAK,WAAW,CAAC,CAAC,SAAS,GAAG,CAAC,MAAM,IAAI,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE9E,sFAAsF;AACtF,QAAA,MAAM,SAAS,EAAE,OAAO,MAAiC,CAAC;AAI1D,QAAA,MAAM,UAAU,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAA6B,CAAC;AAkBvE,QAAA,MAAM,QAAQ,GAAc,QAAQ,GAAG,CAAC,MAAM,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAOpE,CAAC;AAEF,QAAA,MAAM,WAAW,GAAc,QAAQ,GAAG,CAAC,MAAM,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAIvE,CAAC;AAEF,QAAA,MAAM,SAAS,GAAc,QAAQ,GAAG,CAAC,MAAM,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAOrE,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,WAAW,CAAC,CAAC,CAAC,KAAG,CAAC,GAAG,IAQzF,CAAC;AAEF,QAAA,MAAM,kBAAkB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,GAAG,CAAC,UAAU,EAS9D,CAAC;AAsBF,QAAA,MAAM,KAAK,GAAc,WAAW,SAAS,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAYnE,CAAC;AAEF,QAAA,MAAM,QAAQ,GAAc,WAAW,SAAS,KAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAItE,CAAC;AAEF,QAAA,MAAM,OAAO,GAAI,WAAW,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO,KAAG,GAAG,CAAC,MAAM,EAUzF,CAAC;AAEF,OAAO,EACH,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,QAAQ,EACR,KAAK,SAAS,GACjB,CAAC"}
package/dist/traversal.js CHANGED
@@ -26,6 +26,21 @@ const descendants = function* (widget) {
26
26
  tree.next();
27
27
  yield* tree;
28
28
  };
29
+ const ancestors = function* (widget) {
30
+ let parent = widget.getParent();
31
+ while (parent) {
32
+ yield parent;
33
+ parent = parent.getParent();
34
+ }
35
+ };
36
+ const ancestorFor = (widget, type) => {
37
+ for (const ancestor of ancestors(widget)) {
38
+ if (ancestor instanceof type) {
39
+ return ancestor;
40
+ }
41
+ }
42
+ return null;
43
+ };
29
44
  const relationCandidates = (widget) => {
30
45
  const pool = [...widget.listMnemonicLabels(), ...descendants(widget)];
31
46
  const root = widget.getRoot();
@@ -73,5 +88,5 @@ const findAll = (container, isMatch) => {
73
88
  }
74
89
  return results;
75
90
  };
76
- export { TOPLEVELS, children, descendants, findAll, isOnScreen, relationCandidates, roots, traverse, };
91
+ export { TOPLEVELS, ancestorFor, ancestors, children, descendants, findAll, isOnScreen, relationCandidates, roots, traverse, };
77
92
  //# sourceMappingURL=traversal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"traversal.js","sourceRoot":"","sources":["../src/traversal.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\n\n/**\n * A scope that resolves to a single root widget: the widget itself, the widget a controller or\n * layout manager is attached to, or a list item's or header's child.\n */\ntype QueryContainer = Gtk.Widget | Gtk.EventController | Gtk.LayoutManager | Gtk.ListItem | Gtk.ListHeader;\n/**\n * A scope that queries and traversal can run against: a widget, an event\n * controller, a layout manager, a list item or header, an application, or the\n * sentinel representing all current toplevel windows.\n */\ntype Container = QueryContainer | Gtk.Application | typeof TOPLEVELS;\n\n/** Container sentinel that widens a query to every toplevel window currently open. */\nconst TOPLEVELS: unique symbol = Symbol(\"gtkx.toplevels\");\n\nconst isApplication = (container: Container): container is Gtk.Application => container instanceof Gtk.Application;\nconst isAnyWidget = (): boolean => true;\nconst isOnScreen = (widget: Gtk.Widget): boolean => widget.getMapped();\n\nconst traverseWidgetTree = function* (\n root: Gtk.Widget,\n isIncluded: (widget: Gtk.Widget) => boolean,\n): Generator<Gtk.Widget> {\n if (isIncluded(root)) {\n yield root;\n }\n\n let child = root.getFirstChild();\n\n while (child) {\n yield* traverseWidgetTree(child, isIncluded);\n child = child.getNextSibling();\n }\n};\n\nconst children = function* (widget: Gtk.Widget): Generator<Gtk.Widget> {\n let child = widget.getFirstChild();\n\n while (child) {\n yield child;\n child = child.getNextSibling();\n }\n};\n\nconst descendants = function* (widget: Gtk.Widget): Generator<Gtk.Widget> {\n const tree = traverseWidgetTree(widget, isAnyWidget);\n tree.next();\n yield* tree;\n};\n\nconst relationCandidates = (widget: Gtk.Widget): Gtk.Accessible[] => {\n const pool: Gtk.Accessible[] = [...widget.listMnemonicLabels(), ...descendants(widget)];\n const root = widget.getRoot();\n\n if (root instanceof Gtk.Widget) {\n pool.push(...traverseWidgetTree(root, isAnyWidget));\n }\n\n return [...new Set(pool)];\n};\n\nconst resolveRoot = (container: QueryContainer): Gtk.Widget | null => {\n if (container instanceof Gtk.Widget) {\n return container;\n }\n\n if (container instanceof Gtk.EventController) {\n return container.getWidget();\n }\n\n if (container instanceof Gtk.LayoutManager) {\n return container.getWidget();\n }\n\n if (container instanceof Gtk.ListItem || container instanceof Gtk.ListHeader) {\n return container.getChild();\n }\n\n return null;\n};\n\nconst roots = function* (container: Container): Generator<Gtk.Widget> {\n if (container === TOPLEVELS || isApplication(container)) {\n yield* Gtk.Window.listToplevels();\n\n return;\n }\n\n const root = resolveRoot(container);\n\n if (root) {\n yield root;\n }\n};\n\nconst traverse = function* (container: Container): Generator<Gtk.Widget> {\n for (const root of roots(container)) {\n yield* traverseWidgetTree(root, isOnScreen);\n }\n};\n\nconst findAll = (container: Container, isMatch: (node: Gtk.Widget) => boolean): Gtk.Widget[] => {\n const results: Gtk.Widget[] = [];\n\n for (const node of traverse(container)) {\n if (isMatch(node)) {\n results.push(node);\n }\n }\n\n return results;\n};\n\nexport {\n TOPLEVELS,\n children,\n descendants,\n findAll,\n isOnScreen,\n relationCandidates,\n roots,\n traverse,\n type Container,\n};\n"]}
1
+ {"version":3,"file":"traversal.js","sourceRoot":"","sources":["../src/traversal.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\n\n/**\n * A scope that resolves to a single root widget: the widget itself, the widget a controller or\n * layout manager is attached to, or a list item's or header's child.\n */\ntype QueryContainer = Gtk.Widget | Gtk.EventController | Gtk.LayoutManager | Gtk.ListItem | Gtk.ListHeader;\n/**\n * A scope that queries and traversal can run against: a widget, an event\n * controller, a layout manager, a list item or header, an application, or the\n * sentinel representing all current toplevel windows.\n */\ntype Container = QueryContainer | Gtk.Application | typeof TOPLEVELS;\ntype WidgetClass<T extends Gtk.Widget> = abstract new (...args: never[]) => T;\n\n/** Container sentinel that widens a query to every toplevel window currently open. */\nconst TOPLEVELS: unique symbol = Symbol(\"gtkx.toplevels\");\n\nconst isApplication = (container: Container): container is Gtk.Application => container instanceof Gtk.Application;\nconst isAnyWidget = (): boolean => true;\nconst isOnScreen = (widget: Gtk.Widget): boolean => widget.getMapped();\n\nconst traverseWidgetTree = function* (\n root: Gtk.Widget,\n isIncluded: (widget: Gtk.Widget) => boolean,\n): Generator<Gtk.Widget> {\n if (isIncluded(root)) {\n yield root;\n }\n\n let child = root.getFirstChild();\n\n while (child) {\n yield* traverseWidgetTree(child, isIncluded);\n child = child.getNextSibling();\n }\n};\n\nconst children = function* (widget: Gtk.Widget): Generator<Gtk.Widget> {\n let child = widget.getFirstChild();\n\n while (child) {\n yield child;\n child = child.getNextSibling();\n }\n};\n\nconst descendants = function* (widget: Gtk.Widget): Generator<Gtk.Widget> {\n const tree = traverseWidgetTree(widget, isAnyWidget);\n tree.next();\n yield* tree;\n};\n\nconst ancestors = function* (widget: Gtk.Widget): Generator<Gtk.Widget> {\n let parent = widget.getParent();\n\n while (parent) {\n yield parent;\n parent = parent.getParent();\n }\n};\n\nconst ancestorFor = <T extends Gtk.Widget>(widget: Gtk.Widget, type: WidgetClass<T>): T | null => {\n for (const ancestor of ancestors(widget)) {\n if (ancestor instanceof type) {\n return ancestor;\n }\n }\n\n return null;\n};\n\nconst relationCandidates = (widget: Gtk.Widget): Gtk.Accessible[] => {\n const pool: Gtk.Accessible[] = [...widget.listMnemonicLabels(), ...descendants(widget)];\n const root = widget.getRoot();\n\n if (root instanceof Gtk.Widget) {\n pool.push(...traverseWidgetTree(root, isAnyWidget));\n }\n\n return [...new Set(pool)];\n};\n\nconst resolveRoot = (container: QueryContainer): Gtk.Widget | null => {\n if (container instanceof Gtk.Widget) {\n return container;\n }\n\n if (container instanceof Gtk.EventController) {\n return container.getWidget();\n }\n\n if (container instanceof Gtk.LayoutManager) {\n return container.getWidget();\n }\n\n if (container instanceof Gtk.ListItem || container instanceof Gtk.ListHeader) {\n return container.getChild();\n }\n\n return null;\n};\n\nconst roots = function* (container: Container): Generator<Gtk.Widget> {\n if (container === TOPLEVELS || isApplication(container)) {\n yield* Gtk.Window.listToplevels();\n\n return;\n }\n\n const root = resolveRoot(container);\n\n if (root) {\n yield root;\n }\n};\n\nconst traverse = function* (container: Container): Generator<Gtk.Widget> {\n for (const root of roots(container)) {\n yield* traverseWidgetTree(root, isOnScreen);\n }\n};\n\nconst findAll = (container: Container, isMatch: (node: Gtk.Widget) => boolean): Gtk.Widget[] => {\n const results: Gtk.Widget[] = [];\n\n for (const node of traverse(container)) {\n if (isMatch(node)) {\n results.push(node);\n }\n }\n\n return results;\n};\n\nexport {\n TOPLEVELS,\n ancestorFor,\n ancestors,\n children,\n descendants,\n findAll,\n isOnScreen,\n relationCandidates,\n roots,\n traverse,\n type Container,\n};\n"]}
package/dist/types.d.ts CHANGED
@@ -140,7 +140,12 @@ type QueryFamilies<Head extends unknown[]> = QueryFamily<"Role", "role", Head> &
140
140
  * React behavior toggles, error callbacks, and custom queries to bind.
141
141
  */
142
142
  type RenderOptions<Q extends QueryMap = Record<never, never>> = {
143
- /** Widget or root element to mount into; an undecorated harness window is created when omitted. */
143
+ /**
144
+ * Widget or root element to mount into; an undecorated harness window is created when omitted.
145
+ * A widget container that sits outside every toplevel, such as a bare `Gtk.Box`, keeps the tree
146
+ * out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it rejects
147
+ * after `actionabilityTimeout`; `fireEvent` drives such a tree instead.
148
+ */
144
149
  container?: Gtk.Widget | RootElement | undefined;
145
150
  /** Root of the subtree that bound queries search. */
146
151
  baseElement?: Container | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAiQA,OAAO,EAoBN,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { RootElement } from \"@gtkx/react\";\nimport type { ComponentType, ErrorInfo, ReactNode } from \"react\";\nimport type { PrettyWidgetOptions } from \"./pretty-widget.js\";\nimport type { Container } from \"./traversal.js\";\n\n/**\n * A custom matcher predicate: given a candidate widget's normalized text content and the widget\n * itself, returns whether it matches.\n */\ntype MatcherFunction = (content: string, widget: Gtk.Widget) => boolean;\n/** A value used to match widget text: a string or number, a regular expression, or a custom {@link MatcherFunction}. */\ntype Matcher = string | number | RegExp | MatcherFunction;\n/** Normalizes a widget's text before it is compared against a matcher. */\ntype NormalizerFn = (text: string) => string;\n/**\n * A widget class usable as a query's `as` constraint, such as `Gtk.Button`. Abstract classes and\n * generated GInterface pseudo-classes are accepted.\n */\ntype WidgetType<T extends Gtk.Widget = Gtk.Widget> = abstract new (...args: never[]) => T;\n\n/** Options controlling the default text normalizer. */\ntype NormalizerOptions = {\n /** Trim leading and trailing whitespace. */\n trim?: boolean | undefined;\n /** Collapse runs of whitespace into a single space. */\n collapseWhitespace?: boolean | undefined;\n};\n\n/** Options controlling how asynchronous queries and waits poll for a condition. */\ntype WaitForOptions = {\n /** Maximum time in milliseconds to keep retrying before failing. */\n timeout?: number | undefined;\n /** Delay in milliseconds between retries. */\n interval?: number | undefined;\n /** Transforms the error thrown when the timeout elapses. */\n onTimeout?: ((error: Error) => Error) | undefined;\n /** Error whose stack trace attributes the timeout failure to the calling code. */\n stackTraceError?: Error | undefined;\n};\n\n/** Options controlling text matching and, for asynchronous queries, polling behavior. */\ntype MatcherOptions<T extends Gtk.Widget = Gtk.Widget> = {\n /** When true (the default), require an exact match; when false, match case-insensitively as a substring. */\n exact?: boolean | undefined;\n /** Custom normalizer replacing the default; cannot be combined with `trim` or `collapseWhitespace`. */\n normalizer?: NormalizerFn | undefined;\n /** Forwarded to the default normalizer when no custom `normalizer` is given. */\n trim?: boolean | undefined;\n /** Forwarded to the default normalizer when no custom `normalizer` is given. */\n collapseWhitespace?: boolean | undefined;\n /** Whether to include a suggested better query in error messages. */\n suggest?: boolean | undefined;\n /** Restricts matches to instances of this widget class, and narrows the query's return type to it. */\n as?: WidgetType<T> | undefined;\n} & WaitForOptions;\n\n/**\n * Constraints on a widget's numeric range value used by role queries. The numbers come from the\n * accessibility tree and match within 0.001, the resolution GTK keeps them to.\n */\ntype ByRoleValue = {\n /** The current value. */\n now?: number | undefined;\n /** The lower bound of the value's range. */\n min?: number | undefined;\n /**\n * The highest value the widget can reach, which on a paged widget such as a scrollbar is its\n * adjustment's upper bound less one page.\n */\n max?: number | undefined;\n /** Matcher for the value's textual representation. */\n text?: Matcher | undefined;\n};\n\n/** Options for role queries: an accessible name matcher plus accessible state and value constraints. */\ntype ByRoleOptions<T extends Gtk.Widget = Gtk.Widget> = MatcherOptions<T> & {\n /** Matcher for the widget's accessible name. */\n name?: Matcher | undefined;\n /** Required checked state; a mixed check button reads as neither, so it matches neither value. */\n checked?: boolean | undefined;\n /** Required active state of a toggle button; any other widget matches neither value. */\n pressed?: boolean | undefined;\n /** Required selected state of a row, list item, grid cell, option or tree item. */\n selected?: boolean | undefined;\n /** Required expanded state of an expander or tree expander. */\n expanded?: boolean | undefined;\n /** Heading or hierarchy level. */\n level?: number | undefined;\n /** Required busy state, which an unset state satisfies as false. */\n busy?: boolean | undefined;\n /** Matcher for the widget's own accessible description, ignoring its `described-by` targets. */\n description?: Matcher | undefined;\n /** Constraints on the widget's range value, each checked only when given. */\n value?: ByRoleValue | undefined;\n /** When true, include widgets excluded from the accessibility tree. Widgets that are not mapped stay excluded. */\n hidden?: boolean | undefined;\n};\n\n/** A React component that wraps rendered content, receiving it as its children. */\ntype WrapperComponent = ComponentType<{\n children: ReactNode;\n}>;\n\n/** A custom query, taking the scope to search as its first argument and its matcher arguments after it. */\ntype Query = (container: Container, ...args: never[]) => unknown;\n/** Custom queries keyed by the name each is bound under. */\ntype QueryMap = Record<string, Query>;\n\n/** A query with its container argument already applied. */\ntype BoundQuery<Q extends Query> = Q extends (container: Container, ...args: infer A) => infer R\n ? (...args: A) => R\n : never;\n\n/** Custom queries with their container argument already applied, keyed as they were passed in. */\ntype BoundCustomQueries<Q extends QueryMap> = { [K in keyof Q]: BoundQuery<Q[K]> };\n\n/** What each variant of a query family yields for the widget type it matched. */\ntype QueryFamilyReturns<T extends Gtk.Widget> = {\n /** The single match, or null when nothing matched; throws when more than one matched. */\n queryBy: T | null;\n /** Every match, empty when nothing matched. */\n queryAllBy: T[];\n /** The single match; throws when nothing or more than one matched. */\n getBy: T;\n /** Every match; throws when nothing matched. */\n getAllBy: T[];\n /** The single match, retried until it appears or the timeout elapses. */\n findBy: Promise<T>;\n /** Every match, retried until at least one appears or the timeout elapses. */\n findAllBy: Promise<T[]>;\n};\n\n/** What a query family matches against, which fixes the arguments it takes. */\ntype QueryKind = \"role\" | \"text\" | \"name\" | \"value\";\n\n/** The arguments a query of the given kind takes after the family's leading ones. */\ntype QueryArgs<Kind extends QueryKind, T extends Gtk.Widget> = Kind extends \"role\"\n ? [role: Gtk.AccessibleRole, options?: ByRoleOptions<T>]\n : Kind extends \"name\"\n ? [name: Matcher, options?: MatcherOptions<T>]\n : Kind extends \"value\"\n ? [value: Matcher, options?: MatcherOptions<T>]\n : [text: Matcher, options?: MatcherOptions<T>];\n\n/**\n * One family's query variants, each named for its variant followed by `Suffix` and taking `Head`\n * ahead of the family's own arguments.\n */\ntype QueryFamily<Suffix extends string, Kind extends QueryKind, Head extends unknown[]> = {\n [K in keyof QueryFamilyReturns<Gtk.Widget> as `${K & string}${Suffix}`]: <T extends Gtk.Widget = Gtk.Widget>(\n ...args: [...Head, ...QueryArgs<Kind, T>]\n ) => QueryFamilyReturns<T>[K];\n};\n\n/**\n * Every built-in query, spanning the Role, LabelText, Text, Name, PlaceholderText, and DisplayValue\n * families, with `Head` prepended to each signature.\n */\ntype QueryFamilies<Head extends unknown[]> = QueryFamily<\"Role\", \"role\", Head> &\n QueryFamily<\"LabelText\", \"text\", Head> &\n QueryFamily<\"Text\", \"text\", Head> &\n QueryFamily<\"Name\", \"name\", Head> &\n QueryFamily<\"PlaceholderText\", \"text\", Head> &\n QueryFamily<\"DisplayValue\", \"value\", Head>;\n\n/**\n * Options for {@link render}: the container and base element to mount into, an optional wrapper,\n * React behavior toggles, error callbacks, and custom queries to bind.\n */\ntype RenderOptions<Q extends QueryMap = Record<never, never>> = {\n /** Widget or root element to mount into; an undecorated harness window is created when omitted. */\n container?: Gtk.Widget | RootElement | undefined;\n /** Root of the subtree that bound queries search. */\n baseElement?: Container | undefined;\n /** Component wrapped around the rendered element, such as a context provider. */\n wrapper?: WrapperComponent | undefined;\n /** Render inside React StrictMode. */\n isReactStrictMode?: boolean | undefined;\n /** Enable widget animations during the test. */\n areAnimationsEnabled?: boolean | undefined;\n /** Called for errors caught by React error boundaries. */\n onCaughtError?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;\n /** Called for errors React recovered from automatically. */\n onRecoverableError?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;\n /** Custom queries to bind to the rendered result. */\n queries?: Q | undefined;\n};\n\n/** Console helpers bundled with the bound queries on {@link screen} and on a render result. */\ntype DebugUtilities = {\n /** Prints the widget tree of the given containers, or of the whole scope, to the console. */\n debug: (element?: Container | Container[], options?: PrettyWidgetOptions) => void;\n /** Prints the accessible roles found in the scope, with the widgets carrying each one. */\n logRoles: () => void;\n /**\n * Captures what is on screen, which is the active toplevel window: GTK4 exposes no position for\n * a toplevel, so windows cannot be composited into a single image.\n */\n screenshot: (options?: ScreenshotOptions) => Promise<ScreenshotResult>;\n};\n\n/** A captured screenshot: base64-encoded image data, its MIME type, and pixel dimensions. */\ntype ScreenshotResult = {\n /** Base64-encoded image bytes. */\n data: string;\n /** MIME type of the encoded image, always `image/png`. */\n mimeType: string;\n /** Image width in pixels, after the scale factor is applied. */\n width: number;\n /** Image height in pixels, after the scale factor is applied. */\n height: number;\n};\n\n/**\n * Options for capturing a screenshot: the poll timeout and interval, a rendering scale factor, and\n * a file to write the PNG to.\n */\ntype ScreenshotOptions = Pick<WaitForOptions, \"timeout\" | \"interval\"> & {\n /** Device scale factor applied when rendering. */\n scale?: number | undefined;\n /** File the PNG is written to, with its parent directories created as needed. */\n path?: string | undefined;\n};\n\n/**\n * Options for {@link renderHook}: an optional wrapper and the initial props (required unless the\n * props type permits undefined).\n */\ntype RenderHookOptions<Props> = {\n /** Component wrapped around the one calling the hook, such as a context provider. */\n wrapper?: WrapperComponent;\n} & (undefined extends Props\n ? {\n /** Props the hook is invoked with until `rerender` is given new ones. */\n initialProps?: Props;\n }\n : {\n initialProps: Props;\n });\n\n/**\n * The result of {@link renderHook}: the latest hook return value plus functions to rerender with new\n * props and to unmount.\n */\ntype RenderHookResult<Result, Props> = {\n /** Stable object the hook's return value is written to on every render. */\n result: {\n /** The hook's latest return value. */\n current: Result;\n };\n /** Re-invokes the hook, keeping the previous props when none are given. */\n rerender: (newProps?: Props) => Promise<void>;\n /** Unmounts the component that calls the hook. */\n unmount: () => Promise<void>;\n};\n\nexport {\n type MatcherFunction,\n type Matcher,\n type NormalizerFn,\n type NormalizerOptions,\n type WaitForOptions,\n type MatcherOptions,\n type ByRoleValue,\n type ByRoleOptions,\n type WidgetType,\n type WrapperComponent,\n type QueryMap,\n type BoundCustomQueries,\n type QueryFamilies,\n type RenderOptions,\n type DebugUtilities,\n type ScreenshotResult,\n type ScreenshotOptions,\n type RenderHookOptions,\n type RenderHookResult,\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsQA,OAAO,EAoBN,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { RootElement } from \"@gtkx/react\";\nimport type { ComponentType, ErrorInfo, ReactNode } from \"react\";\nimport type { PrettyWidgetOptions } from \"./pretty-widget.js\";\nimport type { Container } from \"./traversal.js\";\n\n/**\n * A custom matcher predicate: given a candidate widget's normalized text content and the widget\n * itself, returns whether it matches.\n */\ntype MatcherFunction = (content: string, widget: Gtk.Widget) => boolean;\n/** A value used to match widget text: a string or number, a regular expression, or a custom {@link MatcherFunction}. */\ntype Matcher = string | number | RegExp | MatcherFunction;\n/** Normalizes a widget's text before it is compared against a matcher. */\ntype NormalizerFn = (text: string) => string;\n/**\n * A widget class usable as a query's `as` constraint, such as `Gtk.Button`. Abstract classes and\n * generated GInterface pseudo-classes are accepted.\n */\ntype WidgetType<T extends Gtk.Widget = Gtk.Widget> = abstract new (...args: never[]) => T;\n\n/** Options controlling the default text normalizer. */\ntype NormalizerOptions = {\n /** Trim leading and trailing whitespace. */\n trim?: boolean | undefined;\n /** Collapse runs of whitespace into a single space. */\n collapseWhitespace?: boolean | undefined;\n};\n\n/** Options controlling how asynchronous queries and waits poll for a condition. */\ntype WaitForOptions = {\n /** Maximum time in milliseconds to keep retrying before failing. */\n timeout?: number | undefined;\n /** Delay in milliseconds between retries. */\n interval?: number | undefined;\n /** Transforms the error thrown when the timeout elapses. */\n onTimeout?: ((error: Error) => Error) | undefined;\n /** Error whose stack trace attributes the timeout failure to the calling code. */\n stackTraceError?: Error | undefined;\n};\n\n/** Options controlling text matching and, for asynchronous queries, polling behavior. */\ntype MatcherOptions<T extends Gtk.Widget = Gtk.Widget> = {\n /** When true (the default), require an exact match; when false, match case-insensitively as a substring. */\n exact?: boolean | undefined;\n /** Custom normalizer replacing the default; cannot be combined with `trim` or `collapseWhitespace`. */\n normalizer?: NormalizerFn | undefined;\n /** Forwarded to the default normalizer when no custom `normalizer` is given. */\n trim?: boolean | undefined;\n /** Forwarded to the default normalizer when no custom `normalizer` is given. */\n collapseWhitespace?: boolean | undefined;\n /** Whether to include a suggested better query in error messages. */\n suggest?: boolean | undefined;\n /** Restricts matches to instances of this widget class, and narrows the query's return type to it. */\n as?: WidgetType<T> | undefined;\n} & WaitForOptions;\n\n/**\n * Constraints on a widget's numeric range value used by role queries. The numbers come from the\n * accessibility tree and match within 0.001, the resolution GTK keeps them to.\n */\ntype ByRoleValue = {\n /** The current value. */\n now?: number | undefined;\n /** The lower bound of the value's range. */\n min?: number | undefined;\n /**\n * The highest value the widget can reach, which on a paged widget such as a scrollbar is its\n * adjustment's upper bound less one page.\n */\n max?: number | undefined;\n /** Matcher for the value's textual representation. */\n text?: Matcher | undefined;\n};\n\n/** Options for role queries: an accessible name matcher plus accessible state and value constraints. */\ntype ByRoleOptions<T extends Gtk.Widget = Gtk.Widget> = MatcherOptions<T> & {\n /** Matcher for the widget's accessible name. */\n name?: Matcher | undefined;\n /** Required checked state; a mixed check button reads as neither, so it matches neither value. */\n checked?: boolean | undefined;\n /** Required active state of a toggle button; any other widget matches neither value. */\n pressed?: boolean | undefined;\n /** Required selected state of a row, list item, grid cell, option or tree item. */\n selected?: boolean | undefined;\n /** Required expanded state of an expander or tree expander. */\n expanded?: boolean | undefined;\n /** Heading or hierarchy level. */\n level?: number | undefined;\n /** Required busy state, which an unset state satisfies as false. */\n busy?: boolean | undefined;\n /** Matcher for the widget's own accessible description, ignoring its `described-by` targets. */\n description?: Matcher | undefined;\n /** Constraints on the widget's range value, each checked only when given. */\n value?: ByRoleValue | undefined;\n /** When true, include widgets excluded from the accessibility tree. Widgets that are not mapped stay excluded. */\n hidden?: boolean | undefined;\n};\n\n/** A React component that wraps rendered content, receiving it as its children. */\ntype WrapperComponent = ComponentType<{\n children: ReactNode;\n}>;\n\n/** A custom query, taking the scope to search as its first argument and its matcher arguments after it. */\ntype Query = (container: Container, ...args: never[]) => unknown;\n/** Custom queries keyed by the name each is bound under. */\ntype QueryMap = Record<string, Query>;\n\n/** A query with its container argument already applied. */\ntype BoundQuery<Q extends Query> = Q extends (container: Container, ...args: infer A) => infer R\n ? (...args: A) => R\n : never;\n\n/** Custom queries with their container argument already applied, keyed as they were passed in. */\ntype BoundCustomQueries<Q extends QueryMap> = { [K in keyof Q]: BoundQuery<Q[K]> };\n\n/** What each variant of a query family yields for the widget type it matched. */\ntype QueryFamilyReturns<T extends Gtk.Widget> = {\n /** The single match, or null when nothing matched; throws when more than one matched. */\n queryBy: T | null;\n /** Every match, empty when nothing matched. */\n queryAllBy: T[];\n /** The single match; throws when nothing or more than one matched. */\n getBy: T;\n /** Every match; throws when nothing matched. */\n getAllBy: T[];\n /** The single match, retried until it appears or the timeout elapses. */\n findBy: Promise<T>;\n /** Every match, retried until at least one appears or the timeout elapses. */\n findAllBy: Promise<T[]>;\n};\n\n/** What a query family matches against, which fixes the arguments it takes. */\ntype QueryKind = \"role\" | \"text\" | \"name\" | \"value\";\n\n/** The arguments a query of the given kind takes after the family's leading ones. */\ntype QueryArgs<Kind extends QueryKind, T extends Gtk.Widget> = Kind extends \"role\"\n ? [role: Gtk.AccessibleRole, options?: ByRoleOptions<T>]\n : Kind extends \"name\"\n ? [name: Matcher, options?: MatcherOptions<T>]\n : Kind extends \"value\"\n ? [value: Matcher, options?: MatcherOptions<T>]\n : [text: Matcher, options?: MatcherOptions<T>];\n\n/**\n * One family's query variants, each named for its variant followed by `Suffix` and taking `Head`\n * ahead of the family's own arguments.\n */\ntype QueryFamily<Suffix extends string, Kind extends QueryKind, Head extends unknown[]> = {\n [K in keyof QueryFamilyReturns<Gtk.Widget> as `${K & string}${Suffix}`]: <T extends Gtk.Widget = Gtk.Widget>(\n ...args: [...Head, ...QueryArgs<Kind, T>]\n ) => QueryFamilyReturns<T>[K];\n};\n\n/**\n * Every built-in query, spanning the Role, LabelText, Text, Name, PlaceholderText, and DisplayValue\n * families, with `Head` prepended to each signature.\n */\ntype QueryFamilies<Head extends unknown[]> = QueryFamily<\"Role\", \"role\", Head> &\n QueryFamily<\"LabelText\", \"text\", Head> &\n QueryFamily<\"Text\", \"text\", Head> &\n QueryFamily<\"Name\", \"name\", Head> &\n QueryFamily<\"PlaceholderText\", \"text\", Head> &\n QueryFamily<\"DisplayValue\", \"value\", Head>;\n\n/**\n * Options for {@link render}: the container and base element to mount into, an optional wrapper,\n * React behavior toggles, error callbacks, and custom queries to bind.\n */\ntype RenderOptions<Q extends QueryMap = Record<never, never>> = {\n /**\n * Widget or root element to mount into; an undecorated harness window is created when omitted.\n * A widget container that sits outside every toplevel, such as a bare `Gtk.Box`, keeps the tree\n * out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it rejects\n * after `actionabilityTimeout`; `fireEvent` drives such a tree instead.\n */\n container?: Gtk.Widget | RootElement | undefined;\n /** Root of the subtree that bound queries search. */\n baseElement?: Container | undefined;\n /** Component wrapped around the rendered element, such as a context provider. */\n wrapper?: WrapperComponent | undefined;\n /** Render inside React StrictMode. */\n isReactStrictMode?: boolean | undefined;\n /** Enable widget animations during the test. */\n areAnimationsEnabled?: boolean | undefined;\n /** Called for errors caught by React error boundaries. */\n onCaughtError?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;\n /** Called for errors React recovered from automatically. */\n onRecoverableError?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;\n /** Custom queries to bind to the rendered result. */\n queries?: Q | undefined;\n};\n\n/** Console helpers bundled with the bound queries on {@link screen} and on a render result. */\ntype DebugUtilities = {\n /** Prints the widget tree of the given containers, or of the whole scope, to the console. */\n debug: (element?: Container | Container[], options?: PrettyWidgetOptions) => void;\n /** Prints the accessible roles found in the scope, with the widgets carrying each one. */\n logRoles: () => void;\n /**\n * Captures what is on screen, which is the active toplevel window: GTK4 exposes no position for\n * a toplevel, so windows cannot be composited into a single image.\n */\n screenshot: (options?: ScreenshotOptions) => Promise<ScreenshotResult>;\n};\n\n/** A captured screenshot: base64-encoded image data, its MIME type, and pixel dimensions. */\ntype ScreenshotResult = {\n /** Base64-encoded image bytes. */\n data: string;\n /** MIME type of the encoded image, always `image/png`. */\n mimeType: string;\n /** Image width in pixels, after the scale factor is applied. */\n width: number;\n /** Image height in pixels, after the scale factor is applied. */\n height: number;\n};\n\n/**\n * Options for capturing a screenshot: the poll timeout and interval, a rendering scale factor, and\n * a file to write the PNG to.\n */\ntype ScreenshotOptions = Pick<WaitForOptions, \"timeout\" | \"interval\"> & {\n /** Device scale factor applied when rendering. */\n scale?: number | undefined;\n /** File the PNG is written to, with its parent directories created as needed. */\n path?: string | undefined;\n};\n\n/**\n * Options for {@link renderHook}: an optional wrapper and the initial props (required unless the\n * props type permits undefined).\n */\ntype RenderHookOptions<Props> = {\n /** Component wrapped around the one calling the hook, such as a context provider. */\n wrapper?: WrapperComponent;\n} & (undefined extends Props\n ? {\n /** Props the hook is invoked with until `rerender` is given new ones. */\n initialProps?: Props;\n }\n : {\n initialProps: Props;\n });\n\n/**\n * The result of {@link renderHook}: the latest hook return value plus functions to rerender with new\n * props and to unmount.\n */\ntype RenderHookResult<Result, Props> = {\n /** Stable object the hook's return value is written to on every render. */\n result: {\n /** The hook's latest return value. */\n current: Result;\n };\n /** Re-invokes the hook, keeping the previous props when none are given. */\n rerender: (newProps?: Props) => Promise<void>;\n /** Unmounts the component that calls the hook. */\n unmount: () => Promise<void>;\n};\n\nexport {\n type MatcherFunction,\n type Matcher,\n type NormalizerFn,\n type NormalizerOptions,\n type WaitForOptions,\n type MatcherOptions,\n type ByRoleValue,\n type ByRoleOptions,\n type WidgetType,\n type WrapperComponent,\n type QueryMap,\n type BoundCustomQueries,\n type QueryFamilies,\n type RenderOptions,\n type DebugUtilities,\n type ScreenshotResult,\n type ScreenshotOptions,\n type RenderHookOptions,\n type RenderHookResult,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"adjustment.d.ts","sourceRoot":"","sources":["../../src/user-event/adjustment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAIpC,mDAAmD;AACnD,KAAK,WAAW,GAAG;IACf,mDAAmD;IACnD,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,CAAC,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAOF;;;;GAIG;AACH,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CASzD,CAAC;AA8CP;;;;;;;;GAQG;AACH,QAAA,MAAM,MAAM,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,WAAW,KAAG,OAAO,CAAC,IAAI,CAa/D,CAAC;AAEP,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"adjustment.d.ts","sourceRoot":"","sources":["../../src/user-event/adjustment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAKpC,mDAAmD;AACnD,KAAK,WAAW,GAAG;IACf,mDAAmD;IACnD,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,CAAC,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAOF;;;;GAIG;AACH,QAAA,MAAM,KAAK,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CASzD,CAAC;AA8CP;;;;;;;;GAQG;AACH,QAAA,MAAM,MAAM,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,OAAO,WAAW,KAAG,OAAO,CAAC,IAAI,CAa/D,CAAC;AAEP,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,CAAC"}