winui-svelte 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +955 -22
- package/README.md +25 -5
- package/dist/app/activate.d.ts.map +1 -1
- package/dist/app/activate.js +3 -0
- package/dist/app/activate.js.map +1 -1
- package/dist/app/activation/index.d.ts +3 -0
- package/dist/app/activation/index.d.ts.map +1 -1
- package/dist/app/activation/index.js +2 -0
- package/dist/app/activation/index.js.map +1 -1
- package/dist/app/activation/login.d.ts +2 -1
- package/dist/app/activation/login.d.ts.map +1 -1
- package/dist/app/activation/login.js +2 -1
- package/dist/app/activation/login.js.map +1 -1
- package/dist/app/activation/native.js +1 -2
- package/dist/app/activation/native.js.map +1 -1
- package/dist/app/activation/packaged.d.ts +49 -0
- package/dist/app/activation/packaged.d.ts.map +1 -0
- package/dist/app/activation/packaged.js +90 -0
- package/dist/app/activation/packaged.js.map +1 -0
- package/dist/app/activation/receive.d.ts +11 -2
- package/dist/app/activation/receive.d.ts.map +1 -1
- package/dist/app/activation/receive.js +11 -4
- package/dist/app/activation/receive.js.map +1 -1
- package/dist/app/activation/registration.d.ts +3 -3
- package/dist/app/activation/registration.js +7 -7
- package/dist/app/activation/registration.js.map +1 -1
- package/dist/app/activation/scheme.d.ts +10 -0
- package/dist/app/activation/scheme.d.ts.map +1 -1
- package/dist/app/activation/scheme.js +17 -0
- package/dist/app/activation/scheme.js.map +1 -1
- package/dist/app/index.d.ts +4 -2
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +3 -1
- package/dist/app/index.js.map +1 -1
- package/dist/app/instance-running.d.ts +15 -0
- package/dist/app/instance-running.d.ts.map +1 -0
- package/dist/app/instance-running.js +20 -0
- package/dist/app/instance-running.js.map +1 -0
- package/dist/app/jump-list/native.d.ts.map +1 -1
- package/dist/app/jump-list/native.js +1 -2
- package/dist/app/jump-list/native.js.map +1 -1
- package/dist/app/launch-command.d.ts +11 -6
- package/dist/app/launch-command.d.ts.map +1 -1
- package/dist/app/launch-command.js +16 -5
- package/dist/app/launch-command.js.map +1 -1
- package/dist/app/native-messaging/browsers.d.ts +19 -0
- package/dist/app/native-messaging/browsers.d.ts.map +1 -0
- package/dist/app/native-messaging/browsers.js +17 -0
- package/dist/app/native-messaging/browsers.js.map +1 -0
- package/dist/app/native-messaging/index.d.ts +41 -0
- package/dist/app/native-messaging/index.d.ts.map +1 -0
- package/dist/app/native-messaging/index.js +84 -0
- package/dist/app/native-messaging/index.js.map +1 -0
- package/dist/app/native.d.ts +0 -6
- package/dist/app/native.d.ts.map +1 -1
- package/dist/app/native.js +1 -24
- package/dist/app/native.js.map +1 -1
- package/dist/app/notification-source.d.ts.map +1 -1
- package/dist/app/notification-source.js +1 -2
- package/dist/app/notification-source.js.map +1 -1
- package/dist/app/shell/native.js +1 -2
- package/dist/app/shell/native.js.map +1 -1
- package/dist/app/single-instance.d.ts +27 -1
- package/dist/app/single-instance.d.ts.map +1 -1
- package/dist/app/single-instance.js +32 -10
- package/dist/app/single-instance.js.map +1 -1
- package/dist/app/tray-instance.d.ts +4 -3
- package/dist/app/tray-instance.d.ts.map +1 -1
- package/dist/app/tray-instance.js +7 -5
- package/dist/app/tray-instance.js.map +1 -1
- package/dist/automation/backend.d.ts +51 -0
- package/dist/automation/backend.d.ts.map +1 -0
- package/dist/automation/backend.js +5 -0
- package/dist/automation/backend.js.map +1 -0
- package/dist/automation/client.d.ts +97 -0
- package/dist/automation/client.d.ts.map +1 -0
- package/dist/automation/client.js +203 -0
- package/dist/automation/client.js.map +1 -0
- package/dist/automation/ids.d.ts +90 -0
- package/dist/automation/ids.d.ts.map +1 -0
- package/dist/automation/ids.js +84 -0
- package/dist/automation/ids.js.map +1 -0
- package/dist/automation/index.d.ts +13 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js +8 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/native.d.ts +11 -0
- package/dist/automation/native.d.ts.map +1 -0
- package/dist/automation/native.js +594 -0
- package/dist/automation/native.js.map +1 -0
- package/dist/automation/text.d.ts +50 -0
- package/dist/automation/text.d.ts.map +1 -0
- package/dist/automation/text.js +110 -0
- package/dist/automation/text.js.map +1 -0
- package/dist/automation/with-client.d.ts +13 -0
- package/dist/automation/with-client.d.ts.map +1 -0
- package/dist/automation/with-client.js +19 -0
- package/dist/automation/with-client.js.map +1 -0
- package/dist/automation/worker-job.d.ts +32 -0
- package/dist/automation/worker-job.d.ts.map +1 -0
- package/dist/automation/worker-job.js +69 -0
- package/dist/automation/worker-job.js.map +1 -0
- package/dist/automation/worker.d.ts +44 -0
- package/dist/automation/worker.d.ts.map +1 -0
- package/dist/automation/worker.js +70 -0
- package/dist/automation/worker.js.map +1 -0
- package/dist/bindings/.dynwinrt-js-types +198 -0
- package/dist/bindings/.dynwinrt-managed +1 -1
- package/dist/bindings/index.d.ts +15 -0
- package/dist/bindings/index.js +20 -0
- package/dist/bindings/index.mjs +2902 -2882
- package/dist/bindings/index.proxy.js +10 -0
- package/dist/bindings/windows/application-model/activation/ActivationKind.d.ts +49 -0
- package/dist/bindings/windows/application-model/activation/ActivationKind.js +50 -0
- package/dist/bindings/windows/application-model/activation/ApplicationExecutionState.d.ts +9 -0
- package/dist/bindings/windows/application-model/activation/ApplicationExecutionState.js +10 -0
- package/dist/bindings/windows/application-model/activation/IActivatedEventArgs.d.ts +36 -0
- package/dist/bindings/windows/application-model/activation/IActivatedEventArgs.js +149 -0
- package/dist/bindings/windows/application-model/activation/IActivatedEventArgsWithUser.d.ts +28 -0
- package/dist/bindings/windows/application-model/activation/IActivatedEventArgsWithUser.js +119 -0
- package/dist/bindings/windows/application-model/activation/IApplicationViewActivatedEventArgs.d.ts +27 -0
- package/dist/bindings/windows/application-model/activation/IApplicationViewActivatedEventArgs.js +116 -0
- package/dist/bindings/windows/application-model/activation/IProtocolActivatedEventArgsWithCallerPackageFamilyNameAndData.d.ts +31 -0
- package/dist/bindings/windows/application-model/activation/IProtocolActivatedEventArgsWithCallerPackageFamilyNameAndData.js +131 -0
- package/dist/bindings/windows/application-model/activation/IViewSwitcherProvider.d.ts +28 -0
- package/dist/bindings/windows/application-model/activation/IViewSwitcherProvider.js +119 -0
- package/dist/bindings/windows/application-model/activation/ProtocolActivatedEventArgs.d.ts +25 -0
- package/dist/bindings/windows/application-model/activation/ProtocolActivatedEventArgs.js +166 -0
- package/dist/bindings/windows/application-model/activation/SplashScreen.d.ts +35 -0
- package/dist/bindings/windows/application-model/activation/SplashScreen.js +105 -0
- package/dist/bindings/windows/foundation/TypedEventHandler_WindowsApplicationModelActivationSplashScreen_Object_g7a7dbfa699cd28ff.d.ts +7 -0
- package/dist/bindings/windows/foundation/TypedEventHandler_WindowsApplicationModelActivationSplashScreen_Object_g7a7dbfa699cd28ff.js +7 -0
- package/dist/bindings/windows/ui/view-management/ActivationViewSwitcher.d.ts +12 -0
- package/dist/bindings/windows/ui/view-management/ActivationViewSwitcher.js +96 -0
- package/dist/chrome/context-menus/context-menu-schema.d.ts +4 -4
- package/dist/chrome/context-menus/context-menu-schema.d.ts.map +1 -1
- package/dist/chrome/context-menus/context-menu-schema.js +1 -7
- package/dist/chrome/context-menus/context-menu-schema.js.map +1 -1
- package/dist/chrome/notifications/notification-schema.d.ts +2 -2
- package/dist/chrome/parse-or-throw.d.ts +7 -0
- package/dist/chrome/parse-or-throw.d.ts.map +1 -0
- package/dist/chrome/parse-or-throw.js +9 -0
- package/dist/chrome/parse-or-throw.js.map +1 -0
- package/dist/chrome/permissions/permission-schema.d.ts.map +1 -1
- package/dist/chrome/permissions/permission-schema.js +1 -7
- package/dist/chrome/permissions/permission-schema.js.map +1 -1
- package/dist/chrome/windows/chrome-windows.d.ts.map +1 -1
- package/dist/chrome/windows/chrome-windows.js +1 -7
- package/dist/chrome/windows/chrome-windows.js.map +1 -1
- package/dist/components/hand-written/Window.svelte +2 -0
- package/dist/components/hand-written/items/keyed-rows.svelte.d.ts.map +1 -1
- package/dist/components/hand-written/items/keyed-rows.svelte.js +6 -0
- package/dist/components/hand-written/items/keyed-rows.svelte.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/runtime.svelte.d.ts.map +1 -1
- package/dist/components/runtime.svelte.js +7 -0
- package/dist/components/runtime.svelte.js.map +1 -1
- package/dist/components/window-context.d.ts +14 -0
- package/dist/components/window-context.d.ts.map +1 -0
- package/dist/components/window-context.js +20 -0
- package/dist/components/window-context.js.map +1 -0
- package/dist/composition/expression.d.ts +1 -1
- package/dist/css/runtime/containers.d.ts.map +1 -1
- package/dist/css/runtime/containers.js +1 -17
- package/dist/css/runtime/containers.js.map +1 -1
- package/dist/css/runtime/native.d.ts.map +1 -1
- package/dist/css/runtime/native.js +40 -20
- package/dist/css/runtime/native.js.map +1 -1
- package/dist/css/translate/property-kit.d.ts +9 -0
- package/dist/css/translate/property-kit.d.ts.map +1 -1
- package/dist/css/translate/property-kit.js.map +1 -1
- package/dist/css/translate/transition-properties.d.ts +1 -1
- package/dist/css/translate/transition-properties.d.ts.map +1 -1
- package/dist/css/translate/transition-properties.js +32 -5
- package/dist/css/translate/transition-properties.js.map +1 -1
- package/dist/data-transfer/data-transfer.d.ts +3 -3
- package/dist/data-transfer/data-transfer.d.ts.map +1 -1
- package/dist/data-transfer/data-transfer.js.map +1 -1
- package/dist/data-transfer/drag-effects.d.ts +25 -2
- package/dist/data-transfer/drag-effects.d.ts.map +1 -1
- package/dist/data-transfer/drag-effects.js +27 -2
- package/dist/data-transfer/drag-effects.js.map +1 -1
- package/dist/data-transfer/drag-helper.d.ts +50 -0
- package/dist/data-transfer/drag-helper.d.ts.map +1 -0
- package/dist/data-transfer/drag-helper.js +156 -0
- package/dist/data-transfer/drag-helper.js.map +1 -0
- package/dist/data-transfer/drop-target.d.ts +6 -5
- package/dist/data-transfer/drop-target.d.ts.map +1 -1
- package/dist/data-transfer/drop-target.js +68 -20
- package/dist/data-transfer/drop-target.js.map +1 -1
- package/dist/data-transfer/index.d.ts +1 -0
- package/dist/data-transfer/index.d.ts.map +1 -1
- package/dist/data-transfer/index.js.map +1 -1
- package/dist/data-transfer/launcher.d.ts +4 -3
- package/dist/data-transfer/launcher.d.ts.map +1 -1
- package/dist/data-transfer/launcher.js +58 -9
- package/dist/data-transfer/launcher.js.map +1 -1
- package/dist/data-transfer/native.d.ts +66 -0
- package/dist/data-transfer/native.d.ts.map +1 -0
- package/dist/data-transfer/native.js +148 -0
- package/dist/data-transfer/native.js.map +1 -0
- package/dist/data-transfer/ole-data-object.d.ts +62 -0
- package/dist/data-transfer/ole-data-object.d.ts.map +1 -0
- package/dist/data-transfer/ole-data-object.js +162 -0
- package/dist/data-transfer/ole-data-object.js.map +1 -0
- package/dist/data-transfer/ole-drop-target.d.ts +54 -0
- package/dist/data-transfer/ole-drop-target.d.ts.map +1 -0
- package/dist/data-transfer/ole-drop-target.js +192 -0
- package/dist/data-transfer/ole-drop-target.js.map +1 -0
- package/dist/data-transfer/share-interop.d.ts.map +1 -1
- package/dist/data-transfer/share-interop.js +1 -1
- package/dist/data-transfer/share-interop.js.map +1 -1
- package/dist/data-transfer/shell-items.d.ts +10 -0
- package/dist/data-transfer/shell-items.d.ts.map +1 -0
- package/dist/data-transfer/shell-items.js +67 -0
- package/dist/data-transfer/shell-items.js.map +1 -0
- package/dist/data-transfer/window-drop.d.ts +35 -0
- package/dist/data-transfer/window-drop.d.ts.map +1 -0
- package/dist/data-transfer/window-drop.js +311 -0
- package/dist/data-transfer/window-drop.js.map +1 -0
- package/dist/devices/native.js +1 -2
- package/dist/devices/native.js.map +1 -1
- package/dist/downloads/chrome-downloads.d.ts +8 -0
- package/dist/downloads/chrome-downloads.d.ts.map +1 -1
- package/dist/downloads/chrome-downloads.js +35 -6
- package/dist/downloads/chrome-downloads.js.map +1 -1
- package/dist/downloads/download-record.d.ts +3 -2
- package/dist/downloads/download-record.d.ts.map +1 -1
- package/dist/downloads/download-record.js.map +1 -1
- package/dist/downloads/download-transfer.d.ts.map +1 -1
- package/dist/downloads/download-transfer.js +3 -3
- package/dist/downloads/download-transfer.js.map +1 -1
- package/dist/downloads/download-types.d.ts +3 -1
- package/dist/downloads/download-types.d.ts.map +1 -1
- package/dist/downloads/download-types.js.map +1 -1
- package/dist/downloads/fetch-to-file.d.ts +11 -6
- package/dist/downloads/fetch-to-file.d.ts.map +1 -1
- package/dist/downloads/fetch-to-file.js +45 -16
- package/dist/downloads/fetch-to-file.js.map +1 -1
- package/dist/downloads/taskbar-progress.d.ts +3 -18
- package/dist/downloads/taskbar-progress.d.ts.map +1 -1
- package/dist/downloads/taskbar-progress.js +1 -38
- package/dist/downloads/taskbar-progress.js.map +1 -1
- package/dist/enums.d.ts +4 -0
- package/dist/enums.d.ts.map +1 -1
- package/dist/enums.js +4 -0
- package/dist/enums.js.map +1 -1
- package/dist/forms/form-field-props.d.ts +2 -2
- package/dist/input/index.d.ts +2 -0
- package/dist/input/index.d.ts.map +1 -1
- package/dist/input/index.js +1 -0
- package/dist/input/index.js.map +1 -1
- package/dist/input/modifier-keys.d.ts +24 -0
- package/dist/input/modifier-keys.d.ts.map +1 -0
- package/dist/input/modifier-keys.js +20 -0
- package/dist/input/modifier-keys.js.map +1 -0
- package/dist/media/pixel-buffer.d.ts.map +1 -1
- package/dist/media/pixel-buffer.js +1 -1
- package/dist/media/pixel-buffer.js.map +1 -1
- package/dist/messaging/web-view2/core.d.ts +56 -0
- package/dist/messaging/web-view2/core.d.ts.map +1 -1
- package/dist/messaging/web-view2/core.js +6 -0
- package/dist/messaging/web-view2/core.js.map +1 -1
- package/dist/messaging/web-view2/environment.d.ts +41 -0
- package/dist/messaging/web-view2/environment.d.ts.map +1 -0
- package/dist/messaging/web-view2/environment.js +91 -0
- package/dist/messaging/web-view2/environment.js.map +1 -0
- package/dist/messaging/web-view2/index.d.ts +9 -1
- package/dist/messaging/web-view2/index.d.ts.map +1 -1
- package/dist/messaging/web-view2/index.js +5 -0
- package/dist/messaging/web-view2/index.js.map +1 -1
- package/dist/messaging/web-view2/input.d.ts +68 -0
- package/dist/messaging/web-view2/input.d.ts.map +1 -0
- package/dist/messaging/web-view2/input.js +108 -0
- package/dist/messaging/web-view2/input.js.map +1 -0
- package/dist/messaging/web-view2/protocol.d.ts +24 -0
- package/dist/messaging/web-view2/protocol.d.ts.map +1 -0
- package/dist/messaging/web-view2/protocol.js +31 -0
- package/dist/messaging/web-view2/protocol.js.map +1 -0
- package/dist/messaging/web-view2/recovery.d.ts +65 -0
- package/dist/messaging/web-view2/recovery.d.ts.map +1 -0
- package/dist/messaging/web-view2/recovery.js +138 -0
- package/dist/messaging/web-view2/recovery.js.map +1 -0
- package/dist/messaging/web-view2/requests.d.ts +88 -0
- package/dist/messaging/web-view2/requests.d.ts.map +1 -0
- package/dist/messaging/web-view2/requests.js +169 -0
- package/dist/messaging/web-view2/requests.js.map +1 -0
- package/dist/messaging/web-view2/transport.d.ts.map +1 -1
- package/dist/messaging/web-view2/transport.js +1 -4
- package/dist/messaging/web-view2/transport.js.map +1 -1
- package/dist/native-identity.d.ts +10 -0
- package/dist/native-identity.d.ts.map +1 -0
- package/dist/native-identity.js +20 -0
- package/dist/native-identity.js.map +1 -0
- package/dist/progress/TaskbarProgress.d.svelte.ts +6 -0
- package/dist/progress/TaskbarProgress.svelte +32 -0
- package/dist/progress/aggregate.d.ts +23 -0
- package/dist/progress/aggregate.d.ts.map +1 -0
- package/dist/progress/aggregate.js +59 -0
- package/dist/progress/aggregate.js.map +1 -0
- package/dist/progress/core.d.ts +14 -0
- package/dist/progress/core.d.ts.map +1 -0
- package/dist/progress/core.js +8 -0
- package/dist/progress/core.js.map +1 -0
- package/dist/progress/index.d.ts +5 -0
- package/dist/progress/index.d.ts.map +1 -0
- package/dist/progress/index.js +4 -0
- package/dist/progress/index.js.map +1 -0
- package/dist/progress/progress-event.d.ts +18 -0
- package/dist/progress/progress-event.d.ts.map +1 -0
- package/dist/progress/progress-event.js +19 -0
- package/dist/progress/progress-event.js.map +1 -0
- package/dist/progress/progress-operation.d.ts +163 -0
- package/dist/progress/progress-operation.d.ts.map +1 -0
- package/dist/progress/progress-operation.js +356 -0
- package/dist/progress/progress-operation.js.map +1 -0
- package/dist/progress/progress-registry.d.ts +89 -0
- package/dist/progress/progress-registry.d.ts.map +1 -0
- package/dist/progress/progress-registry.js +187 -0
- package/dist/progress/progress-registry.js.map +1 -0
- package/dist/progress/progress-source.d.ts +46 -0
- package/dist/progress/progress-source.d.ts.map +1 -0
- package/dist/progress/progress-source.js +31 -0
- package/dist/progress/progress-source.js.map +1 -0
- package/dist/progress/progress-state.d.ts +54 -0
- package/dist/progress/progress-state.d.ts.map +1 -0
- package/dist/progress/progress-state.js +35 -0
- package/dist/progress/progress-state.js.map +1 -0
- package/dist/progress/progress-text.d.ts +10 -0
- package/dist/progress/progress-text.d.ts.map +1 -0
- package/dist/progress/progress-text.js +23 -0
- package/dist/progress/progress-text.js.map +1 -0
- package/dist/progress/scoped-source.d.ts +31 -0
- package/dist/progress/scoped-source.d.ts.map +1 -0
- package/dist/progress/scoped-source.js +46 -0
- package/dist/progress/scoped-source.js.map +1 -0
- package/dist/progress/taskbar-progress-props.d.ts +15 -0
- package/dist/progress/taskbar-progress-props.d.ts.map +1 -0
- package/dist/progress/taskbar-progress-props.js +2 -0
- package/dist/progress/taskbar-progress-props.js.map +1 -0
- package/dist/progress/taskbar-progress.d.ts +44 -0
- package/dist/progress/taskbar-progress.d.ts.map +1 -0
- package/dist/progress/taskbar-progress.js +62 -0
- package/dist/progress/taskbar-progress.js.map +1 -0
- package/dist/progress/track-operation.d.ts +36 -0
- package/dist/progress/track-operation.d.ts.map +1 -0
- package/dist/progress/track-operation.js +53 -0
- package/dist/progress/track-operation.js.map +1 -0
- package/dist/renderer/host/host.d.ts.map +1 -1
- package/dist/renderer/host/host.js +33 -16
- package/dist/renderer/host/host.js.map +1 -1
- package/dist/renderer/host/structure-sync.d.ts +9 -0
- package/dist/renderer/host/structure-sync.d.ts.map +1 -0
- package/dist/renderer/host/structure-sync.js +24 -0
- package/dist/renderer/host/structure-sync.js.map +1 -0
- package/dist/security/data-protection-error.d.ts +14 -0
- package/dist/security/data-protection-error.d.ts.map +1 -0
- package/dist/security/data-protection-error.js +15 -0
- package/dist/security/data-protection-error.js.map +1 -0
- package/dist/security/index.d.ts +48 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +32 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/native.d.ts +43 -0
- package/dist/security/native.d.ts.map +1 -0
- package/dist/security/native.js +170 -0
- package/dist/security/native.js.map +1 -0
- package/dist/security/protection-scope.d.ts +13 -0
- package/dist/security/protection-scope.d.ts.map +1 -0
- package/dist/security/protection-scope.js +11 -0
- package/dist/security/protection-scope.js.map +1 -0
- package/dist/store/states.d.ts +2 -2
- package/dist/store/windows-identity.d.ts +2 -6
- package/dist/store/windows-identity.d.ts.map +1 -1
- package/dist/store/windows-identity.js +2 -29
- package/dist/store/windows-identity.js.map +1 -1
- package/dist/store/windows-packages.d.ts +2 -2
- package/dist/store/windows-store.d.ts +2 -2
- package/dist/tray/click-detector.d.ts.map +1 -1
- package/dist/tray/click-detector.js.map +1 -1
- package/dist/tray/flyout-model.d.ts +4 -3
- package/dist/tray/flyout-model.d.ts.map +1 -1
- package/dist/tray/flyout-model.js +12 -2
- package/dist/tray/flyout-model.js.map +1 -1
- package/dist/tray/menu/icon.d.ts +17 -0
- package/dist/tray/menu/icon.d.ts.map +1 -0
- package/dist/tray/menu/icon.js +31 -0
- package/dist/tray/menu/icon.js.map +1 -0
- package/dist/tray/menu/index.d.ts +1 -1
- package/dist/tray/menu/index.d.ts.map +1 -1
- package/dist/tray/menu/index.js.map +1 -1
- package/dist/tray/menu/types.d.ts +23 -6
- package/dist/tray/menu/types.d.ts.map +1 -1
- package/dist/tray/menu/types.js.map +1 -1
- package/dist/tray/menu-svelte/TrayMenuOperations.d.svelte.ts +6 -0
- package/dist/tray/menu-svelte/TrayMenuOperations.svelte +33 -0
- package/dist/tray/menu-svelte/TrayMenuProgress.d.svelte.ts +6 -0
- package/dist/tray/menu-svelte/TrayMenuProgress.svelte +28 -0
- package/dist/tray/menu-svelte/index.d.ts +3 -1
- package/dist/tray/menu-svelte/index.d.ts.map +1 -1
- package/dist/tray/menu-svelte/index.js +2 -0
- package/dist/tray/menu-svelte/index.js.map +1 -1
- package/dist/tray/menu-svelte/menu-node.d.ts +9 -9
- package/dist/tray/menu-svelte/menu-props.d.ts +16 -0
- package/dist/tray/menu-svelte/menu-props.d.ts.map +1 -1
- package/dist/tray/menu-svelte/operation-ids.d.ts +8 -0
- package/dist/tray/menu-svelte/operation-ids.d.ts.map +1 -0
- package/dist/tray/menu-svelte/operation-ids.js +20 -0
- package/dist/tray/menu-svelte/operation-ids.js.map +1 -0
- package/dist/tray/native.d.ts +15 -5
- package/dist/tray/native.d.ts.map +1 -1
- package/dist/tray/native.js +27 -45
- package/dist/tray/native.js.map +1 -1
- package/dist/tray/personalize.d.ts +18 -0
- package/dist/tray/personalize.d.ts.map +1 -0
- package/dist/tray/personalize.js +42 -0
- package/dist/tray/personalize.js.map +1 -0
- package/dist/tray/pointer-share.d.ts +27 -0
- package/dist/tray/pointer-share.d.ts.map +1 -0
- package/dist/tray/pointer-share.js +61 -0
- package/dist/tray/pointer-share.js.map +1 -0
- package/dist/tray/standalone/icon-raster.d.ts +72 -0
- package/dist/tray/standalone/icon-raster.d.ts.map +1 -0
- package/dist/tray/standalone/icon-raster.js +161 -0
- package/dist/tray/standalone/icon-raster.js.map +1 -0
- package/dist/tray/standalone/index.d.ts +4 -2
- package/dist/tray/standalone/index.d.ts.map +1 -1
- package/dist/tray/standalone/index.js +2 -0
- package/dist/tray/standalone/index.js.map +1 -1
- package/dist/tray/standalone/menu-icons.d.ts +9 -0
- package/dist/tray/standalone/menu-icons.d.ts.map +1 -0
- package/dist/tray/standalone/menu-icons.js +280 -0
- package/dist/tray/standalone/menu-icons.js.map +1 -0
- package/dist/tray/standalone/menu-theme.d.ts +38 -0
- package/dist/tray/standalone/menu-theme.d.ts.map +1 -0
- package/dist/tray/standalone/menu-theme.js +74 -0
- package/dist/tray/standalone/menu-theme.js.map +1 -0
- package/dist/tray/standalone/native.d.ts +24 -7
- package/dist/tray/standalone/native.d.ts.map +1 -1
- package/dist/tray/standalone/native.js +63 -16
- package/dist/tray/standalone/native.js.map +1 -1
- package/dist/tray/standalone/standalone-tray.d.ts +17 -2
- package/dist/tray/standalone/standalone-tray.d.ts.map +1 -1
- package/dist/tray/standalone/standalone-tray.js +34 -2
- package/dist/tray/standalone/standalone-tray.js.map +1 -1
- package/dist/tray/themed-icon.d.ts.map +1 -1
- package/dist/tray/themed-icon.js +4 -28
- package/dist/tray/themed-icon.js.map +1 -1
- package/dist/tray/tray-core.d.ts.map +1 -1
- package/dist/tray/tray-core.js +6 -1
- package/dist/tray/tray-core.js.map +1 -1
- package/dist/tray/tray-extras.d.ts +26 -2
- package/dist/tray/tray-extras.d.ts.map +1 -1
- package/dist/tray/tray-manifest.d.ts +44 -4
- package/dist/tray/tray-manifest.d.ts.map +1 -1
- package/dist/tray/tray-manifest.js +48 -4
- package/dist/tray/tray-manifest.js.map +1 -1
- package/dist/vite/entrypoints/build-tray.d.ts +3 -1
- package/dist/vite/entrypoints/build-tray.d.ts.map +1 -1
- package/dist/vite/entrypoints/build-tray.js +22 -16
- package/dist/vite/entrypoints/build-tray.js.map +1 -1
- package/dist/vite/entrypoints/extract-tray.d.ts +7 -6
- package/dist/vite/entrypoints/extract-tray.d.ts.map +1 -1
- package/dist/vite/entrypoints/extract-tray.js +35 -15
- package/dist/vite/entrypoints/extract-tray.js.map +1 -1
- package/dist/vite/entrypoints/tray-module.d.ts +2 -1
- package/dist/vite/entrypoints/tray-module.d.ts.map +1 -1
- package/dist/vite/entrypoints/tray-module.js +8 -4
- package/dist/vite/entrypoints/tray-module.js.map +1 -1
- package/dist/web-apis/eye-dropper.d.ts.map +1 -1
- package/dist/web-apis/eye-dropper.js +8 -5
- package/dist/web-apis/eye-dropper.js.map +1 -1
- package/dist/web-apis/file-read.d.ts +14 -0
- package/dist/web-apis/file-read.d.ts.map +1 -0
- package/dist/web-apis/file-read.js +37 -0
- package/dist/web-apis/file-read.js.map +1 -0
- package/dist/web-apis/file-system.d.ts +9 -0
- package/dist/web-apis/file-system.d.ts.map +1 -1
- package/dist/web-apis/file-system.js +24 -0
- package/dist/web-apis/file-system.js.map +1 -1
- package/dist/web-apis/media-devices-source.d.ts +1 -1
- package/dist/web-apis/native.d.ts +0 -7
- package/dist/web-apis/native.d.ts.map +1 -1
- package/dist/web-apis/native.js +0 -19
- package/dist/web-apis/native.js.map +1 -1
- package/dist/win2d/activation-failure.d.ts +10 -0
- package/dist/win2d/activation-failure.d.ts.map +1 -0
- package/dist/win2d/activation-failure.js +30 -0
- package/dist/win2d/activation-failure.js.map +1 -0
- package/dist/win2d/element-lifecycle.d.ts.map +1 -1
- package/dist/win2d/element-lifecycle.js +6 -1
- package/dist/win2d/element-lifecycle.js.map +1 -1
- package/dist/win2d/manifest.d.ts +29 -0
- package/dist/win2d/manifest.d.ts.map +1 -0
- package/dist/win2d/manifest.js +67 -0
- package/dist/win2d/manifest.js.map +1 -0
- package/dist/win32/index.d.ts +3 -0
- package/dist/win32/index.d.ts.map +1 -0
- package/dist/win32/index.js +11 -0
- package/dist/win32/index.js.map +1 -0
- package/dist/win32-calls.d.ts +6 -0
- package/dist/win32-calls.d.ts.map +1 -1
- package/dist/win32-calls.js +6 -1
- package/dist/win32-calls.js.map +1 -1
- package/dist/win32-foreground.d.ts +34 -0
- package/dist/win32-foreground.d.ts.map +1 -0
- package/dist/win32-foreground.js +91 -0
- package/dist/win32-foreground.js.map +1 -0
- package/dist/win32-icons.d.ts.map +1 -1
- package/dist/win32-icons.js +1 -2
- package/dist/win32-icons.js.map +1 -1
- package/dist/win32-key-state.d.ts +31 -0
- package/dist/win32-key-state.d.ts.map +1 -0
- package/dist/win32-key-state.js +41 -0
- package/dist/win32-key-state.js.map +1 -0
- package/dist/window/anchor.d.ts +15 -0
- package/dist/window/anchor.d.ts.map +1 -1
- package/dist/window/anchor.js +23 -0
- package/dist/window/anchor.js.map +1 -1
- package/dist/window/apply-frame.d.ts +4 -2
- package/dist/window/apply-frame.d.ts.map +1 -1
- package/dist/window/apply-frame.js +2 -3
- package/dist/window/apply-frame.js.map +1 -1
- package/dist/window/bootstrap-core.d.ts +69 -0
- package/dist/window/bootstrap-core.d.ts.map +1 -0
- package/dist/window/bootstrap-core.js +93 -0
- package/dist/window/bootstrap-core.js.map +1 -0
- package/dist/window/bootstrap-mode.d.ts +21 -0
- package/dist/window/bootstrap-mode.d.ts.map +1 -0
- package/dist/window/bootstrap-mode.js +17 -0
- package/dist/window/bootstrap-mode.js.map +1 -0
- package/dist/window/bootstrap.d.ts +12 -28
- package/dist/window/bootstrap.d.ts.map +1 -1
- package/dist/window/bootstrap.js +18 -66
- package/dist/window/bootstrap.js.map +1 -1
- package/dist/window/cover.d.ts +43 -0
- package/dist/window/cover.d.ts.map +1 -0
- package/dist/window/cover.js +64 -0
- package/dist/window/cover.js.map +1 -0
- package/dist/window/create-window.d.ts +1 -1
- package/dist/window/create-window.d.ts.map +1 -1
- package/dist/window/create-window.js +2 -0
- package/dist/window/create-window.js.map +1 -1
- package/dist/window/dpi-awareness.d.ts +71 -0
- package/dist/window/dpi-awareness.d.ts.map +1 -0
- package/dist/window/dpi-awareness.js +127 -0
- package/dist/window/dpi-awareness.js.map +1 -0
- package/dist/window/foreground-filter.d.ts +71 -0
- package/dist/window/foreground-filter.d.ts.map +1 -0
- package/dist/window/foreground-filter.js +108 -0
- package/dist/window/foreground-filter.js.map +1 -0
- package/dist/window/foreground-native.d.ts +25 -0
- package/dist/window/foreground-native.d.ts.map +1 -0
- package/dist/window/foreground-native.js +86 -0
- package/dist/window/foreground-native.js.map +1 -0
- package/dist/window/foreground.d.ts +49 -0
- package/dist/window/foreground.d.ts.map +1 -0
- package/dist/window/foreground.js +78 -0
- package/dist/window/foreground.js.map +1 -0
- package/dist/window/index.d.ts +2 -0
- package/dist/window/index.d.ts.map +1 -1
- package/dist/window/index.js +1 -0
- package/dist/window/index.js.map +1 -1
- package/dist/window/native.d.ts.map +1 -1
- package/dist/window/native.js +1 -2
- package/dist/window/native.js.map +1 -1
- package/dist/window/package-identity.d.ts +17 -0
- package/dist/window/package-identity.d.ts.map +1 -0
- package/dist/window/package-identity.js +97 -0
- package/dist/window/package-identity.js.map +1 -0
- package/dist/window/system-dispatcher-queue.d.ts.map +1 -1
- package/dist/window/system-dispatcher-queue.js +1 -2
- package/dist/window/system-dispatcher-queue.js.map +1 -1
- package/dist/window/taskbar-calls.d.ts +1 -1
- package/dist/window/taskbar-native.d.ts.map +1 -1
- package/dist/window/taskbar-native.js +1 -2
- package/dist/window/taskbar-native.js.map +1 -1
- package/dist/window/window-handle.d.ts +25 -1
- package/dist/window/window-handle.d.ts.map +1 -1
- package/dist/window/window-handle.js +27 -1
- package/dist/window/window-handle.js.map +1 -1
- package/dist/window/window-host.svelte.d.ts +11 -2
- package/dist/window/window-host.svelte.d.ts.map +1 -1
- package/dist/window/window-host.svelte.js +38 -4
- package/dist/window/window-host.svelte.js.map +1 -1
- package/package.json +43 -4
- package/src/app/activate.ts +3 -0
- package/src/app/activation/index.ts +3 -0
- package/src/app/activation/login.ts +2 -1
- package/src/app/activation/native.ts +1 -1
- package/src/app/activation/packaged.ts +118 -0
- package/src/app/activation/receive.ts +24 -4
- package/src/app/activation/registration.ts +7 -7
- package/src/app/activation/scheme.ts +19 -0
- package/src/app/index.ts +4 -2
- package/src/app/instance-running.ts +22 -0
- package/src/app/jump-list/native.ts +1 -2
- package/src/app/launch-command.ts +19 -5
- package/src/app/native-messaging/browsers.ts +21 -0
- package/src/app/native-messaging/index.ts +124 -0
- package/src/app/native.ts +1 -32
- package/src/app/notification-source.ts +1 -3
- package/src/app/shell/native.ts +1 -1
- package/src/app/single-instance.ts +34 -10
- package/src/app/tray-instance.ts +7 -5
- package/src/automation/backend.ts +56 -0
- package/src/automation/client.ts +327 -0
- package/src/automation/ids.ts +97 -0
- package/src/automation/index.ts +23 -0
- package/src/automation/native.ts +688 -0
- package/src/automation/text.ts +174 -0
- package/src/automation/with-client.ts +20 -0
- package/src/automation/worker-job.ts +97 -0
- package/src/automation/worker.ts +116 -0
- package/src/chrome/context-menus/context-menu-schema.ts +1 -12
- package/src/chrome/parse-or-throw.ts +14 -0
- package/src/chrome/permissions/permission-schema.ts +1 -12
- package/src/chrome/windows/chrome-windows.ts +1 -13
- package/src/components/hand-written/items/keyed-rows.svelte.ts +6 -0
- package/src/components/index.ts +1 -0
- package/src/components/runtime.svelte.ts +8 -0
- package/src/components/window-context.ts +23 -0
- package/src/css/runtime/containers.ts +1 -20
- package/src/css/runtime/native.ts +46 -21
- package/src/css/translate/property-kit.ts +9 -0
- package/src/css/translate/transition-properties.ts +44 -10
- package/src/data-transfer/data-transfer.ts +3 -3
- package/src/data-transfer/drag-effects.ts +48 -4
- package/src/data-transfer/drag-helper.ts +216 -0
- package/src/data-transfer/drop-target.ts +90 -26
- package/src/data-transfer/index.ts +1 -0
- package/src/data-transfer/launcher.ts +65 -9
- package/src/data-transfer/native.ts +184 -0
- package/src/data-transfer/ole-data-object.ts +200 -0
- package/src/data-transfer/ole-drop-target.ts +263 -0
- package/src/data-transfer/share-interop.ts +1 -1
- package/src/data-transfer/shell-items.ts +81 -0
- package/src/data-transfer/window-drop.ts +411 -0
- package/src/devices/native.ts +1 -1
- package/src/downloads/chrome-downloads.ts +46 -6
- package/src/downloads/download-record.ts +3 -2
- package/src/downloads/download-transfer.ts +3 -3
- package/src/downloads/download-types.ts +3 -0
- package/src/downloads/fetch-to-file.ts +47 -17
- package/src/downloads/taskbar-progress.ts +3 -49
- package/src/enums.ts +4 -0
- package/src/input/index.ts +2 -0
- package/src/input/modifier-keys.ts +30 -0
- package/src/media/pixel-buffer.ts +1 -1
- package/src/messaging/web-view2/core.ts +64 -0
- package/src/messaging/web-view2/environment.ts +131 -0
- package/src/messaging/web-view2/index.ts +11 -0
- package/src/messaging/web-view2/input.ts +154 -0
- package/src/messaging/web-view2/protocol.ts +41 -0
- package/src/messaging/web-view2/recovery.ts +177 -0
- package/src/messaging/web-view2/requests.ts +238 -0
- package/src/messaging/web-view2/transport.ts +1 -5
- package/src/native-identity.ts +22 -0
- package/src/progress/TaskbarProgress.d.svelte.ts +6 -0
- package/src/progress/aggregate.ts +68 -0
- package/src/progress/core.ts +13 -0
- package/src/progress/index.ts +4 -0
- package/src/progress/progress-event.ts +25 -0
- package/src/progress/progress-operation.ts +469 -0
- package/src/progress/progress-registry.ts +224 -0
- package/src/progress/progress-source.ts +66 -0
- package/src/progress/progress-state.ts +72 -0
- package/src/progress/progress-text.ts +27 -0
- package/src/progress/scoped-source.ts +56 -0
- package/src/progress/taskbar-progress-props.ts +18 -0
- package/src/progress/taskbar-progress.ts +80 -0
- package/src/progress/track-operation.ts +81 -0
- package/src/renderer/host/host.ts +39 -17
- package/src/renderer/host/structure-sync.ts +25 -0
- package/src/security/data-protection-error.ts +18 -0
- package/src/security/index.ts +57 -0
- package/src/security/native.ts +234 -0
- package/src/security/protection-scope.ts +13 -0
- package/src/store/windows-identity.ts +3 -35
- package/src/tray/click-detector.ts +6 -7
- package/src/tray/flyout-model.ts +14 -3
- package/src/tray/menu/icon.ts +40 -0
- package/src/tray/menu/index.ts +3 -0
- package/src/tray/menu/types.ts +27 -6
- package/src/tray/menu-svelte/TrayMenuOperations.d.svelte.ts +6 -0
- package/src/tray/menu-svelte/TrayMenuProgress.d.svelte.ts +6 -0
- package/src/tray/menu-svelte/index.ts +4 -0
- package/src/tray/menu-svelte/menu-props.ts +20 -0
- package/src/tray/menu-svelte/operation-ids.ts +21 -0
- package/src/tray/native.ts +44 -49
- package/src/tray/personalize.ts +57 -0
- package/src/tray/pointer-share.ts +71 -0
- package/src/tray/standalone/icon-raster.ts +208 -0
- package/src/tray/standalone/index.ts +5 -1
- package/src/tray/standalone/menu-icons.ts +317 -0
- package/src/tray/standalone/menu-theme.ts +90 -0
- package/src/tray/standalone/native.ts +83 -16
- package/src/tray/standalone/standalone-tray.ts +68 -5
- package/src/tray/themed-icon.ts +4 -36
- package/src/tray/tray-core.ts +7 -1
- package/src/tray/tray-extras.ts +31 -2
- package/src/tray/tray-manifest.ts +53 -4
- package/src/vite/entrypoints/build-tray.ts +23 -16
- package/src/vite/entrypoints/extract-tray.ts +41 -15
- package/src/vite/entrypoints/tray-module.ts +8 -4
- package/src/web-apis/eye-dropper.ts +9 -5
- package/src/web-apis/file-read.ts +43 -0
- package/src/web-apis/file-system.ts +33 -0
- package/src/web-apis/native.ts +0 -20
- package/src/win2d/activation-failure.ts +35 -0
- package/src/win2d/element-lifecycle.ts +6 -1
- package/src/win2d/manifest.ts +78 -0
- package/src/win32/index.ts +19 -0
- package/src/win32-calls.ts +8 -1
- package/src/win32-foreground.ts +100 -0
- package/src/win32-icons.ts +7 -2
- package/src/win32-key-state.ts +48 -0
- package/src/window/anchor.ts +28 -0
- package/src/window/apply-frame.ts +6 -4
- package/src/window/bootstrap-core.ts +165 -0
- package/src/window/bootstrap-mode.ts +23 -0
- package/src/window/bootstrap.ts +20 -103
- package/src/window/cover.ts +100 -0
- package/src/window/create-window.ts +4 -0
- package/src/window/dpi-awareness.ts +162 -0
- package/src/window/foreground-filter.ts +167 -0
- package/src/window/foreground-native.ts +91 -0
- package/src/window/foreground.ts +106 -0
- package/src/window/index.ts +2 -0
- package/src/window/native.ts +1 -1
- package/src/window/package-identity.ts +112 -0
- package/src/window/system-dispatcher-queue.ts +7 -2
- package/src/window/taskbar-native.ts +1 -2
- package/src/window/window-handle.ts +29 -1
- package/src/window/window-host.svelte.ts +59 -6
- package/web-types.json +11 -3
package/API.md
CHANGED
|
@@ -35,16 +35,20 @@ monorepo needs no build step (the repository is a pnpm workspace, see
|
|
|
35
35
|
| `winui-svelte/runner` | `src/vite/runner.ts` | `createWindowModuleRunner()`, the window thread's side of the module server |
|
|
36
36
|
| `winui-svelte/compile` | `src/vite/compile.ts` | `compileSvelte()` for bundlers (esbuild) and tests, `WINUI_COMPILE_OPTIONS`, `withElementAnimation()` |
|
|
37
37
|
| `winui-svelte/testing` | `src/vite/loader.ts` | `svelteHooks()`: Node module hooks that run `.svelte` files, with Svelte's runtime read through the package's edits (pure tests) |
|
|
38
|
-
| `winui-svelte/bootstrap` | `src/window/bootstrap.ts` | `initWindowsAppSdk()`; imports nothing of WinRT, safe on the host's main thread |
|
|
38
|
+
| `winui-svelte/bootstrap` | `src/window/bootstrap.ts` | `initWindowsAppSdk()`, `hasPackageIdentity()`, `processDpiAwareness()`, `BootstrapMode`, `DpiAwareness`; imports nothing of WinRT, safe on the host's main thread |
|
|
39
39
|
| `winui-svelte/thread` | `src/window/thread.ts` | `runOnUiThread()`; imports only dynwinrt, so the apartment comes first |
|
|
40
40
|
| `winui-svelte/window` | `src/window/index.ts` | `runWindow()`, `exitApplication()`, `createWindow()`, `startTimer()`, `systemSettings()`, the picker options (see App services) |
|
|
41
|
-
| `winui-svelte/
|
|
41
|
+
| `winui-svelte/window/foreground` | `src/window/foreground.ts` | `trackForeground()`, `bringWindowToFront()`, `shouldRestore()` (opt-in; see Following the foreground app) |
|
|
42
|
+
| `winui-svelte/app` | `src/app/index.ts` | `ensureSingleInstance()`, `claimInstance()`, `isInstanceRunning()`, `notify()`, `activateInstance()`, `activateOrLaunch()`, `launchApp()`, `startTray()`, `relaunch()`, `restartAfterCrash()` (opt-in; see App lifecycle) |
|
|
42
43
|
| `winui-svelte/app/shell` | `src/app/shell/index.ts` | `trash()`, `openWith()`, `createShortcut()`, `readShortcut()`, `registerAppPath()`, `ShellFailure` (opt-in; see Shell verbs) |
|
|
43
44
|
| `winui-svelte/app/activation` | `src/app/activation/index.ts` | `installProtocolHandlers()`, `registerFileTypes()`, `launchAtLogin()`, `startActivation()`, `ActivationKind` (opt-in; see Activation) |
|
|
45
|
+
| `winui-svelte/app/native-messaging` | `src/app/native-messaging/index.ts` | `registerNativeMessagingHost()`, `unregisterNativeMessagingHost()`, `NativeMessagingBrowser` (opt-in; see Native messaging host) |
|
|
46
|
+
| `winui-svelte/win32` | `src/win32/index.ts` | `bindDll()`, `bind()`, `hasPackageIdentity()` and the memory helpers (opt-in escape hatch; see Win32 seam) |
|
|
44
47
|
| `winui-svelte/app/jump-list` | `src/app/jump-list/index.ts` | `setJumpListTasks()`, `clearJumpList()` (opt-in; see Jump list tasks) |
|
|
45
48
|
| `winui-svelte/data-transfer` | `src/data-transfer/index.ts` | `enableDragEvents()`, `dropzone`, `draggable`, `filePicker`, `pickFiles`, `pickSaveFile`, `clipboard`, `launchUri` / `launchFile` / `openFolder` / `revealInExplorer`, `share`, `NativeFile`, `DataTransfer`, `DragEvent` (opt-in; see Data transfer) |
|
|
46
49
|
| `winui-svelte/incremental` | `src/incremental/index.ts` | `createIncrementalSource()`, `IncrementalSource`, `IncrementalStatus`, `IncrementalState` (opt-in; see Incremental loading) |
|
|
47
50
|
| `winui-svelte/downloads` | `src/downloads/index.ts` | `Downloads` (`chrome.downloads`), `fetchToFile()`, `markOfTheWeb()`, `DownloadError` (opt-in; see Downloads) |
|
|
51
|
+
| `winui-svelte/security` | `src/security/index.ts` | `protectData()`, `unprotectData()`, `wipe()`, `ProtectionScope`, `DataProtectionError`: Windows DPAPI, compatible with .NET `ProtectedData` (opt-in; see Security) |
|
|
48
52
|
| `winui-svelte/chrome/runtime` | `src/chrome/runtime/index.ts` | `Runtime` (`chrome.runtime`), `Port`, `InstallReason`, the native messaging codec (opt-in; see Chrome runtime) |
|
|
49
53
|
| `winui-svelte/chrome/notifications` | `src/chrome/notifications/index.ts` | `ChromeNotifications` (`chrome.notifications`), `NotificationTemplateType`, `NotificationPermissionLevel` (opt-in; see Chrome notifications) |
|
|
50
54
|
|
|
@@ -52,17 +56,20 @@ monorepo needs no build step (the repository is a pnpm workspace, see
|
|
|
52
56
|
| `winui-svelte/chrome/action` | `src/chrome/action/index.ts` | `ChromeAction` (`chrome.action`), `createChromeAction()` (opt-in; see Chrome action) |
|
|
53
57
|
| `winui-svelte/chrome/i18n` | `src/chrome/i18n/index.ts` | `ChromeI18n` (`chrome.i18n`), `installLanguageDefaults()` (opt-in; see Chrome i18n) |
|
|
54
58
|
| `winui-svelte/chrome/install` | `src/chrome/install.ts` | `installChromeApis()`, `ChromeGlobal`, `ChromeAlarms`, `ChromeSystem` (opt-in; see Chrome global) |
|
|
55
|
-
| `winui-svelte/input` | `src/input/index.ts` | `enableInputEvents()`, `setPointerCapture` / `releasePointerCapture` / `hasPointerCapture`, `activeElement()`, `moveFocus()`, `trapFocus()`, `PointerType`, `PointerEvent` / `WheelEvent` / `KeyboardEvent` / `FocusEvent` (opt-in; see Input events and focus) |
|
|
59
|
+
| `winui-svelte/input` | `src/input/index.ts` | `enableInputEvents()`, `setPointerCapture` / `releasePointerCapture` / `hasPointerCapture`, `activeElement()`, `modifierKeysHeld()`, `moveFocus()`, `trapFocus()`, `PointerType`, `PointerEvent` / `WheelEvent` / `KeyboardEvent` / `FocusEvent` (opt-in; see Input events and focus) |
|
|
56
60
|
| `winui-svelte/media` | `src/media/index.ts` | `bitmapImageOf()`, `svgImageSourceOf()`, `decodeDataUri()`, `createMediaPlayer()`, `mediaSourceOfBytes()`, `observePlayback()`, `PlaybackState` (opt-in; see Media) |
|
|
57
61
|
| `winui-svelte/win2d` | `src/win2d/index.ts` | `Canvas`, the Win2D controls, the drawing helpers and Win2D classes, `applyEffect` (opt-in; see Win2D) |
|
|
58
62
|
| `winui-svelte/enums` | `src/enums.ts` | every closed set a prop or option takes: WinUI's enums, `ThemeBrush`, `ColorKeyword`, `Backdrop`, `WindowTheme`, `TrayBalloonIcon` and the rest (see Closed sets) |
|
|
63
|
+
| `winui-svelte/win2d/manifest` | `src/win2d/manifest.ts` | `win2dActivatableClasses`, `win2dClassNames`: the manifest fragment a packaged app needs for Win2D (see Packaged apps) |
|
|
59
64
|
| `winui-svelte/win2d/context-2d` | `src/win2d/context-2d/index.ts` | `Canvas2D`, `createCanvas2D`, `CanvasElement`, `Context2D`, `Path2D` and the rest of the HTML Canvas 2D API over Win2D (opt-in; see Canvas 2D) |
|
|
60
65
|
| `winui-svelte/tray` | `src/tray/index.ts` | `TrayIcon` (with its `menu`), `createTrayIcon()`, `placeMenuWindow()`, `hideToTray()`, `restoreFromTray()`, `toggleInTray()`, `removeAllTrayIcons()`, `TrayGesture` (opt-in; see System tray) |
|
|
66
|
+
| `winui-svelte/progress/core` | `src/progress/core.ts` | `ProgressRegistry`, `defaultProgressRegistry()`, `ProgressOperation`, `trackOperation()`, `progressText()` and the types, with no Svelte component and no taskbar code, for a process with no window (opt-in; see Progress) |
|
|
61
67
|
| `winui-svelte/tray/standalone` | `src/tray/standalone/index.ts` | `createStandaloneTray()`, `defineTray()`, its opt-in parts `balloons`, `bounds` and `themedIcon`, `MenuItemKind`, `MenuLevel`, and the `winui-svelte/app` calls that start or signal the app: a tray with no window, no WinUI and no components (opt-in; see Tray with no window) |
|
|
62
68
|
| `winui-svelte/notice` | `src/notice/index.ts` | `showNotice()`, `NoticeIcon`, `NoticeButtons`, `NoticeButton`: a message box with no window or app (opt-in; see Notice with no app) |
|
|
63
69
|
| `winui-svelte/forms` | `src/forms/index.ts` | `Form`, `FormField`, `textField`, `numberField`, `selectField` and the other field attachments, `formButton`, `FormValues`, `validityOf` (opt-in; see Forms) |
|
|
64
70
|
| `winui-svelte/store` | `src/store/index.ts` | `getAppLicense`, `watchLicense`, `checkForUpdates`, `watchPackages`, `getStartupTask`, `getPackageInfo`: the Store and package APIs, answering `hasPackage: false` outside a package (opt-in) |
|
|
65
71
|
| `winui-svelte/accessibility`, `/accessibility/audit` | `src/accessibility/index.ts`, `src/accessibility/audit/index.ts` | `announce`, `liveRegion`, `LivePriority`; `auditAccessibility`, `accessibilityRules` (opt-in; see Accessibility) |
|
|
72
|
+
| `winui-svelte/automation` | `src/automation/index.ts` | `withUiaClient`, `createUiaWorker`, `readWindowText`, `UiaControlType`: a UI Automation client that reads the text of another window (opt-in; see UI Automation client) |
|
|
66
73
|
| `winui-svelte/devices` | `src/devices/index.ts` | device enumeration, input devices, Bluetooth, printers, power, network, display, audio, gamepads and sensors, each also at `winui-svelte/devices/<area>` (opt-in; see Windows devices) |
|
|
67
74
|
|
|
68
75
|
The table is the source layout: `exports` point at `.ts` files so the monorepo
|
|
@@ -706,14 +713,75 @@ for tools; `compileSvelte()` throws an `Error` with that message
|
|
|
706
713
|
// match wins), sets WINAPPSDK_BOOTSTRAP_DLL_PATH, puts the folder it was found
|
|
707
714
|
// in on PATH (WebView2's native libraries are there) and initialises the
|
|
708
715
|
// Windows App SDK. Sets WEBVIEW2_USER_DATA_FOLDER to `webViewUserDataFolder`
|
|
709
|
-
// unless it is already set
|
|
710
|
-
//
|
|
716
|
+
// unless it is already set; `false` leaves it alone (the variable overrides the
|
|
717
|
+
// folder of a createWebView2Environment). Throws WindowsAppRuntimeMissing when the runtime is
|
|
718
|
+
// not installed. In a process whose package graph holds the Windows App SDK
|
|
719
|
+
// (an MSIX whose manifest declares the PackageDependency) it skips the
|
|
720
|
+
// bootstrapper, which refuses to run there with 0x80070032; the environment
|
|
721
|
+
// and PATH steps still run, and the bootstrapper need not be found.
|
|
711
722
|
function initWindowsAppSdk(options?: {
|
|
712
723
|
major?: number;
|
|
713
724
|
minor?: number;
|
|
714
725
|
folders?: string[];
|
|
715
|
-
webViewUserDataFolder?: string;
|
|
716
|
-
|
|
726
|
+
webViewUserDataFolder?: string | false;
|
|
727
|
+
dpiAwareness?: DpiAwareness | undefined; // default "per-monitor-v2"; undefined leaves the process as it is
|
|
728
|
+
bootstrap?: BootstrapMode; // default "auto"
|
|
729
|
+
}): { runtime: RuntimeSource }; // "package" or "bootstrapper", for a log line
|
|
730
|
+
|
|
731
|
+
// auto: skip the bootstrapper when the package graph holds a Microsoft.WindowsAppRuntime
|
|
732
|
+
// framework package, call it otherwise; always: call it (an error surfaces as
|
|
733
|
+
// WindowsAppRuntimeMissing with the original in `cause`); never: skip it
|
|
734
|
+
const BootstrapMode = { auto: "auto", always: "always", never: "never" } as const;
|
|
735
|
+
const RuntimeSource = { bootstrapper: "bootstrapper", package: "package" } as const;
|
|
736
|
+
|
|
737
|
+
// Whether this process has a package identity (MSIX or sparse package); cheap,
|
|
738
|
+
// kernel32 only, no WinRT
|
|
739
|
+
function hasPackageIdentity(): boolean;
|
|
740
|
+
|
|
741
|
+
// The process's DPI awareness. node.exe is unaware, so every window reads 96
|
|
742
|
+
// DPI (`scaleOf` 1) and screen captures and monitor rectangles are virtualized
|
|
743
|
+
// on a display above 100%. `initWindowsAppSdk` asks for per-monitor v2 first,
|
|
744
|
+
// before WinUI starts: Windows allows it once per process and only before the
|
|
745
|
+
// first window exists, so a library that creates a window before the call
|
|
746
|
+
// keeps an unaware process. A refusal is success when the process already has
|
|
747
|
+
// at least that awareness (a manifest set it); otherwise it throws
|
|
748
|
+
// DpiAwarenessTooLow, naming both values.
|
|
749
|
+
const DpiAwareness = {
|
|
750
|
+
unaware: "unaware", system: "system", perMonitor: "per-monitor", perMonitorV2: "per-monitor-v2"
|
|
751
|
+
} as const;
|
|
752
|
+
type DpiAwareness = (typeof DpiAwareness)[keyof typeof DpiAwareness];
|
|
753
|
+
function processDpiAwareness(): DpiAwareness; // from GetThreadDpiAwarenessContext
|
|
754
|
+
|
|
755
|
+
const { runtime } = initWindowsAppSdk(); // per-monitor v2; "package" when packaged
|
|
756
|
+
initWindowsAppSdk({ bootstrap: BootstrapMode.always });
|
|
757
|
+
initWindowsAppSdk({ dpiAwareness: undefined }); // leave the process alone
|
|
758
|
+
processDpiAwareness(); // "per-monitor-v2"
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### Packaged apps
|
|
762
|
+
|
|
763
|
+
An MSIX app whose manifest declares
|
|
764
|
+
`<PackageDependency Name="Microsoft.WindowsAppRuntime.2" .../>` runs with the
|
|
765
|
+
runtime already in its package graph, so WinRT and WinUI activate with no
|
|
766
|
+
bootstrapper; `initWindowsAppSdk` sees that and skips it (`runtime: "package"`)
|
|
767
|
+
A child process has the identity only when the packaged parent started it
|
|
768
|
+
A package that has an identity but no such dependency (a sparse package) still
|
|
769
|
+
calls the bootstrapper, which Windows refuses with `0x80070032` in any packaged
|
|
770
|
+
process; declare the dependency
|
|
771
|
+
`test/packaged-bootstrap.test.ts` proves it with a throwaway package
|
|
772
|
+
(`WINUI_SVELTE_PACKAGED_TEST=1 pnpm test:windows test/packaged-bootstrap.test.ts`),
|
|
773
|
+
and `test/support/test-package.ts` is the harness for any test that needs an
|
|
774
|
+
identity: register a loose layout package, run a script under it, remove it
|
|
775
|
+
|
|
776
|
+
An application manifest is the static route for a single executable: embed it
|
|
777
|
+
as the `RT_MANIFEST` resource (id 1, type 24) with `<dpiAware>true/pm</dpiAware>`
|
|
778
|
+
and `<dpiAwareness>PerMonitorV2,PerMonitor</dpiAwareness>` after the injection
|
|
779
|
+
and before signing, with a PE resource editor (`postject` cannot write it);
|
|
780
|
+
the call is then a no-op that reports success, and stays as the safety net for
|
|
781
|
+
`pnpm dev` under plain `node.exe`; the repository has no single-executable
|
|
782
|
+
build yet, so the embedding step belongs to that work
|
|
783
|
+
|
|
784
|
+
```ts
|
|
717
785
|
|
|
718
786
|
// thread (in the worker that owns the UI thread; WinUI's loop never gives its
|
|
719
787
|
// thread back): enters the single-threaded apartment first, so everything
|
|
@@ -752,6 +820,7 @@ type WindowOptions<Props> = {
|
|
|
752
820
|
size?: { width: number; height: number }; // device pixels
|
|
753
821
|
backdrop?: Backdrop; // "acrylic" | "acrylicBase" | "acrylicThin" | "mica" | "micaAlt" | "none" | "transparent"
|
|
754
822
|
extendsIntoTitleBar?: boolean;
|
|
823
|
+
onclosing?: () => boolean | void; // AppWindow.Closing: return true to keep the window open
|
|
755
824
|
isBackground?: boolean; // shown without activating (tests, captures)
|
|
756
825
|
} & ({ component: Component<Props>; props: Props } | { control: FrameworkElement });
|
|
757
826
|
|
|
@@ -1187,6 +1256,8 @@ Items come in two forms
|
|
|
1187
1256
|
keep a row only for each item the control has realized; a `TreeView` also takes
|
|
1188
1257
|
`children` (the items under an item) and `bind:expandedKeys`, and a `ListView`
|
|
1189
1258
|
or `GridView` can show its items in groups (`groupBy`, `groupHeader`)
|
|
1259
|
+
A hot update of a component an `item` snippet uses shows in the rows already
|
|
1260
|
+
realized, with no restart
|
|
1190
1261
|
A
|
|
1191
1262
|
control whose items are controls takes them as Svelte's own blocks: `{#each}`
|
|
1192
1263
|
in the children of `ComboBox`, `FlipView` and `ListBox`, or in the snippet of
|
|
@@ -1684,13 +1755,152 @@ const bridge = defineMessaging<AppProtocol>({ transport: createPageTransport() }
|
|
|
1684
1755
|
| `executeScript({ control, code })` | runs script in the page and resolves with its JSON value, checked |
|
|
1685
1756
|
| `addDocumentCreatedScript({ control, code })` | runs script before every page script; resolves with the function that removes it |
|
|
1686
1757
|
| `openDevTools(control)` | opens the developer tools window |
|
|
1758
|
+
| `createWebView2Environment({ browserExecutableFolder, userDataFolder, additionalBrowserArguments, language })` | builds an environment: a profile folder and Chromium switches (an array, joined with spaces) |
|
|
1759
|
+
| `startWebView2({ control, environment, profileName, isInPrivateMode })` | starts the control's browser in that environment and resolves with its `CoreWebView2`; a second call on the control resolves with the same core |
|
|
1760
|
+
| `keepWebView2Alive({ control, setup, rebuild, maxCrashes, windowMilliseconds, onRecovering, onGaveUp })` | brings a control back after a browser crash (see below); resolves with a guard that has `retry()` and `dispose()` |
|
|
1687
1761
|
| `getCookies`, `setCookie`, `deleteCookie` | the profile's cookies as plain data (`CookieSameSite`) |
|
|
1688
1762
|
| `onPermissionRequested({ control, decide })` | answers permission requests with a `PermissionState` (`default`, `allow`, `deny`) for a `PermissionKind` |
|
|
1689
1763
|
| `onDownloadStarting({ control, pathFor })` | sends a download to a path with no dialog, or cancels it with `null` |
|
|
1690
1764
|
| `onNavigationStarting({ control, isAllowed })` | cancels the navigations `isAllowed` refuses |
|
|
1765
|
+
| `blockRequests({ control, uri, context, statusCode })` | answers every request to a URI pattern (`*` and `?` wildcards) with an empty `204` until the returned function is called |
|
|
1766
|
+
| `onWebResourceRequested({ control, filters, respond })` | `respond(request)` returns `null` to let a request through or `{ statusCode, reasonPhrase, headers, body }` to answer it; `filters` are `{ uri, context }` with a `ResourceContext` |
|
|
1767
|
+
| `callDevToolsMethod({ control, method, parameters })` | calls a DevTools protocol method, resolves with its result as checked JSON, rejects with the protocol's error |
|
|
1768
|
+
| `onDevToolsEvent({ control, event, handler })` | hands the parsed parameters of a protocol event to `handler`; the domain must be enabled first (`Network.enable`) |
|
|
1769
|
+
| `dispatchKey`, `dispatchMouseClick`, `typeText`, `keyEventParameters`, `KeyEventType`, `MouseButton` | trusted input through `Input.dispatchKeyEvent` and `Input.dispatchMouseEvent`; `typeText` takes a `TypeMode` (`keys`, or `insertAfterFirst`) |
|
|
1770
|
+
|
|
1771
|
+
#### Crash recovery
|
|
1772
|
+
|
|
1773
|
+
When Chromium's browser process dies the control is dead: every later call
|
|
1774
|
+
throws, and starting it again in place is not something to rely on
|
|
1775
|
+
`keepWebView2Alive` follows `CoreProcessFailed` and applies one policy
|
|
1776
|
+
|
|
1777
|
+
```ts
|
|
1778
|
+
import { keepWebView2Alive } from "winui-svelte/messaging/web-view2";
|
|
1779
|
+
|
|
1780
|
+
const guard = keepWebView2Alive({
|
|
1781
|
+
control,
|
|
1782
|
+
maxCrashes: 3,
|
|
1783
|
+
windowMilliseconds: 30_000,
|
|
1784
|
+
async setup(core) {
|
|
1785
|
+
// runs for the first core and after every rebuild
|
|
1786
|
+
await core.addScriptToExecuteOnDocumentCreatedAsync(bridgeScript);
|
|
1787
|
+
},
|
|
1788
|
+
onRecovering: ({ kind }) => status("reconnecting"),
|
|
1789
|
+
onGaveUp: ({ reason }) => status("down"),
|
|
1790
|
+
rebuild: async () => remount()
|
|
1791
|
+
});
|
|
1792
|
+
guard.dispose();
|
|
1793
|
+
```
|
|
1794
|
+
|
|
1795
|
+
- `ProcessFailureKind` (`winui-svelte/enums`) is `BROWSER_EXITED`,
|
|
1796
|
+
`RENDER_EXITED`, `UNRESPONSIVE` or `OTHER`, mapped from
|
|
1797
|
+
`CoreWebView2ProcessFailedKind`
|
|
1798
|
+
- `BROWSER_EXITED` calls `rebuild`, which resolves with a new control that is
|
|
1799
|
+
already started (`startWebView2`), then runs `setup` with its core; any other
|
|
1800
|
+
kind calls `core.reload()` and keeps the core
|
|
1801
|
+
- More than `maxCrashes` failures within `windowMilliseconds` (3 within 30
|
|
1802
|
+
seconds by default) call `onGaveUp` once and stop; `retry()` forgets the
|
|
1803
|
+
failures and rebuilds
|
|
1804
|
+
- A failure while a recovery is running is ignored; a `rebuild` or `setup` that
|
|
1805
|
+
throws gives up with the error's text as the reason
|
|
1806
|
+
- After a rebuild, redo in `setup` whatever is bound to the old core: scripts
|
|
1807
|
+
from `addDocumentCreatedScript`, `onNavigationStarting`,
|
|
1808
|
+
`onPermissionRequested`, `onWebResourceRequested`, the DevTools subscriptions
|
|
1809
|
+
and a `webView2Transport` with its messaging; cookies and storage live in
|
|
1810
|
+
the profile folder and survive; after a reload only the page's own state is
|
|
1811
|
+
lost
|
|
1812
|
+
- In a Svelte app, key the component on a `$state` counter: `rebuild` bumps
|
|
1813
|
+
it and resolves with the control that the new `WebView2` hands to
|
|
1814
|
+
`oncorewebview2initialized`; `examples/web-recovery` shows it, and
|
|
1815
|
+
`test/web-recovery.test.ts` kills its browser process and sees the page come
|
|
1816
|
+
back
|
|
1817
|
+
- Several controls on one profile folder share a browser process, so one kill
|
|
1818
|
+
fails all of them; each control has its own guard, and each rebuilds itself
|
|
1819
|
+
- Resuming what a page was doing (a live conversation) is the app's job;
|
|
1820
|
+
`onRecovering` is its hook
|
|
1821
|
+
|
|
1822
|
+
A profile folder and Chromium switches per control
|
|
1823
|
+
|
|
1824
|
+
```ts
|
|
1825
|
+
import { createWebView2Environment, startWebView2 } from "winui-svelte/messaging/web-view2";
|
|
1826
|
+
|
|
1827
|
+
const environment = await createWebView2Environment({
|
|
1828
|
+
userDataFolder: path.join(process.env.LOCALAPPDATA, "MyApp", "WebView2Home"),
|
|
1829
|
+
additionalBrowserArguments: ["--autoplay-policy=no-user-gesture-required"],
|
|
1830
|
+
language: "en-US"
|
|
1831
|
+
});
|
|
1832
|
+
// control is the WebView2 (the sender of onloaded), already in a window
|
|
1833
|
+
const core = await startWebView2({ control, environment, profileName: "home" });
|
|
1834
|
+
```
|
|
1835
|
+
|
|
1836
|
+
- The first start of a control wins: call `startWebView2` before anything that
|
|
1837
|
+
starts it with the default environment (`waitForCoreWebView2` and every
|
|
1838
|
+
helper that calls it); a second call resolves with the same core
|
|
1839
|
+
- `WEBVIEW2_USER_DATA_FOLDER` overrides the folder of an environment (measured:
|
|
1840
|
+
with it set, two environments with two folders both ran in the variable's
|
|
1841
|
+
folder), so the app starts with `initWindowsAppSdk({ webViewUserDataFolder: false })`
|
|
1842
|
+
and the variable unset
|
|
1843
|
+
- One browser process runs per folder; two controls in one folder with different
|
|
1844
|
+
options, or a process that cannot launch the browser, fail with 0x8007139F,
|
|
1845
|
+
and a folder another browser has open with 0x800700AA; the rejection's message
|
|
1846
|
+
names the causes
|
|
1847
|
+
- `additionalBrowserArguments` reach the browser process (the test reads its
|
|
1848
|
+
command line); profiles of different folders share no cookies
|
|
1849
|
+
- `core.browserProcessId` and `core.environment.userDataFolder` are on
|
|
1850
|
+
`CoreWebView2Like`
|
|
1851
|
+
- `examples/web-profiles` and `test/web-profiles.test.ts` run two controls in
|
|
1852
|
+
one window with two folders; it needs an ordinary desktop session
|
|
1853
|
+
|
|
1854
|
+
Request filters and the protocol
|
|
1855
|
+
|
|
1856
|
+
```ts
|
|
1857
|
+
import {
|
|
1858
|
+
blockRequests,
|
|
1859
|
+
callDevToolsMethod,
|
|
1860
|
+
ResourceContext,
|
|
1861
|
+
typeText
|
|
1862
|
+
} from "winui-svelte/messaging/web-view2";
|
|
1863
|
+
|
|
1864
|
+
const unblock = await blockRequests({
|
|
1865
|
+
control,
|
|
1866
|
+
uri: "https://accounts.google.com/RotateCookies*",
|
|
1867
|
+
context: ResourceContext.ALL
|
|
1868
|
+
});
|
|
1869
|
+
await callDevToolsMethod({ control, method: "Runtime.evaluate", parameters: { expression: "document.title" } });
|
|
1870
|
+
await typeText({ control, text: "hello" });
|
|
1871
|
+
unblock();
|
|
1872
|
+
```
|
|
1873
|
+
|
|
1874
|
+
- A filter added before the first navigation applies to it; one added later
|
|
1875
|
+
does not apply to requests already in flight
|
|
1876
|
+
- Every handler hears the requests of every filter of the control, so each
|
|
1877
|
+
checks its own filters; `respond` is a plain function (the answer is given
|
|
1878
|
+
before the event's handler returns), and a body holds the request until it
|
|
1879
|
+
is written to a stream
|
|
1880
|
+
- The empty answer uses an empty `InMemoryRandomAccessStream`; a `null` stream
|
|
1881
|
+
for `createWebResourceResponse` was not tried
|
|
1882
|
+
- Typing 300 characters with `typeText` takes 5 to 7.5 seconds in a window on
|
|
1883
|
+
this machine (two protocol calls per character, sent in order: sending them
|
|
1884
|
+
all at once reorders the keys); `TypeMode.INSERT_AFTER_FIRST` takes about
|
|
1885
|
+
0.1 second, but whether a page enables its Submit button from inserted text
|
|
1886
|
+
is the page's
|
|
1887
|
+
- `coreWebView2` is not set yet inside `oncorewebview2initialized`; the helpers
|
|
1888
|
+
that wait for it need a turn of the event loop first (`setTimeout`)
|
|
1889
|
+
|
|
1890
|
+
Porting a C# WebView2 host
|
|
1891
|
+
|
|
1892
|
+
| C# | Here |
|
|
1893
|
+
|---|---|
|
|
1894
|
+
| `CookieManager` | `getCookies`, `setCookie`, `deleteCookie` |
|
|
1895
|
+
| `PermissionRequested` | `onPermissionRequested` |
|
|
1896
|
+
| `NavigationStarting` | `onNavigationStarting` |
|
|
1897
|
+
| `AddWebResourceRequestedFilter` and `WebResourceRequested` | `StatusCode`, `blockRequests`, `onWebResourceRequested` |
|
|
1898
|
+
| `CallDevToolsProtocolMethodAsync` | `callDevToolsMethod`, `dispatchKey`, `dispatchMouseClick` |
|
|
1899
|
+
| `GetDevToolsProtocolEventReceiver` | `onDevToolsEvent` |
|
|
1691
1900
|
|
|
1692
1901
|
`examples/web-bridge` is an app talking to a hosted page, and
|
|
1693
|
-
`test/web-bridge.test.ts` runs it in a real window;
|
|
1902
|
+
`test/web-bridge.test.ts` runs it in a real window; `examples/web-requests` and
|
|
1903
|
+
`test/web-requests.test.ts` do the same for a blocked request and typed input; it needs an ordinary
|
|
1694
1904
|
desktop session (a sandboxed process cannot launch the browser, 0x8007139F)
|
|
1695
1905
|
|
|
1696
1906
|
### ListView and GridView
|
|
@@ -1883,6 +2093,15 @@ exists on Windows 11 only
|
|
|
1883
2093
|
A window on a desktop of its own (a hidden desktop) is never composed by
|
|
1884
2094
|
Windows, so there is nothing to see through to: `test/transparent-window.test.ts`
|
|
1885
2095
|
reads the screen of the ordinary desktop for that reason
|
|
2096
|
+
`isClickThrough` with `backdrop="transparent"` works on build 26300, measured
|
|
2097
|
+
by `test/click-through.test.ts` (examples/click-through, a 3 px ring drawn by
|
|
2098
|
+
content): the window stays clear (the hole reads the desktop, the ring its
|
|
2099
|
+
color, not black), and a click on the ring and one in the hole reach the window
|
|
2100
|
+
below, as Windows hit-tests it (`WindowFromPoint`, the root's owner); the same
|
|
2101
|
+
ring without `isClickThrough` answers itself, which is the control
|
|
2102
|
+
No region (`clipToRing`) is needed, and the host's own order of the frame and
|
|
2103
|
+
the backdrop is the one that was measured
|
|
2104
|
+
The test sends no click, so a person still confirms it in Notepad (CONTRIBUTING)
|
|
1886
2105
|
Not checked: a filter or a drop shadow (`filter: drop-shadow()`) on content
|
|
1887
2106
|
over a transparent window
|
|
1888
2107
|
The window's own `cornerRadius` clips with an edge that is not anti-aliased, so
|
|
@@ -1970,11 +2189,40 @@ along the top, until `isResizable={false}` takes it away),
|
|
|
1970
2189
|
`isShownInSwitchers` and `isToolWindow` (no taskbar button or Alt+Tab entry),
|
|
1971
2190
|
`isActivatable={false}` (a click never takes focus), `isClickThrough`,
|
|
1972
2191
|
`isExcludedFromCapture` (black in screenshots and screen sharing),
|
|
1973
|
-
`isHidden` (opens hidden, hides and shows later) and `cornerRadius` (clips the
|
|
2192
|
+
`isHidden` (opens hidden, hides and shows later), `isParked` (see below) and `cornerRadius` (clips the
|
|
1974
2193
|
window to a rounded rectangle; the edge is not anti-aliased, so on a
|
|
1975
2194
|
transparent window round the card's own `corner-radius` instead, which is)
|
|
1976
2195
|
A prop left out leaves the window as it is, and dropped again it puts the
|
|
1977
2196
|
window back
|
|
2197
|
+
|
|
2198
|
+
A window that must run but never be seen (a host for a page with no UI) is
|
|
2199
|
+
`isParked`: shown, so that Chromium keeps its page at full speed, but a tool
|
|
2200
|
+
window that is not activatable, opened without taking focus, and placed left of
|
|
2201
|
+
the virtual screen, clear of every display
|
|
2202
|
+
`placement` and `width`/`height` give only its size; dropping the prop moves it
|
|
2203
|
+
back
|
|
2204
|
+
It is the per-window form of the `WINUI_SVELTE_BACKGROUND` run, and uses the
|
|
2205
|
+
same code
|
|
2206
|
+
`isHidden` is not a substitute: a hidden window is a hidden page
|
|
2207
|
+
(`document.visibilityState` is `hidden`, timers are throttled)
|
|
2208
|
+
`test/parked-window.test.ts` measures it: the page of a parked window reports
|
|
2209
|
+
`visible`, a heartbeat of 100 milliseconds keeps its pace and
|
|
2210
|
+
`requestAnimationFrame` keeps firing, where the same window with `isHidden`
|
|
2211
|
+
reports `hidden`
|
|
2212
|
+
Measured over 5 seconds, no Chromium flags set (the default WebView2
|
|
2213
|
+
environment):
|
|
2214
|
+
|
|
2215
|
+
| Window | `visibilityState` | Heartbeat gap (100 ms timer) | Frames |
|
|
2216
|
+
|---|---|---|---|
|
|
2217
|
+
| `isParked` | `visible` | under 150 ms on average | above 10 a second |
|
|
2218
|
+
| `isHidden` | `hidden` | slower, throttled | not measured |
|
|
2219
|
+
|
|
2220
|
+
So the three Chromium flags the C# host sets are not needed for a parked window
|
|
2221
|
+
```svelte
|
|
2222
|
+
<Window isParked width={900} height={720}>
|
|
2223
|
+
<WebView2 source="about:blank" />
|
|
2224
|
+
</Window>
|
|
2225
|
+
```
|
|
1978
2226
|
`createWindow` takes them too
|
|
1979
2227
|
`handle.setShownInSwitchers(isShown)` does not throw for a window that has no
|
|
1980
2228
|
taskbar button (WinUI answers 0x80004001 there); `hideToTray` uses it
|
|
@@ -2033,6 +2281,46 @@ at the size it has after Windows rescaled it
|
|
|
2033
2281
|
The arithmetic is plain functions (`anchoredBounds`, `dockedBounds`,
|
|
2034
2282
|
`fittedBounds` in `src/window/anchor.ts`) over device pixels
|
|
2035
2283
|
|
|
2284
|
+
### Covering a display
|
|
2285
|
+
|
|
2286
|
+
```ts
|
|
2287
|
+
// the whole display the user is on, in physical pixels
|
|
2288
|
+
handle.cover({ display: DockDisplay.active })
|
|
2289
|
+
// a rectangle of the display, from its top left
|
|
2290
|
+
handle.cover({ display: DockDisplay.current, region: { x: 240, y: 120, width: 800, height: 600 } })
|
|
2291
|
+
// one display by the id that displays() lists
|
|
2292
|
+
handle.cover({ display: displayId })
|
|
2293
|
+
```
|
|
2294
|
+
|
|
2295
|
+
A covering window needs `isBorderless` and `isResizable={false}`: without the
|
|
2296
|
+
second, the 8 device pixel resize frame stays, shrinks the client area and
|
|
2297
|
+
paints a strip along the top; `cover` does not set either, because a prop left
|
|
2298
|
+
out leaves the window as it is
|
|
2299
|
+
`dock` is a corner of the **work area** at the window's own size; `cover` is
|
|
2300
|
+
the **whole display** (or a part of it) at the display's size;
|
|
2301
|
+
`handle.geometry` is in CSS pixels at the window's scale and can do neither
|
|
2302
|
+
exactly
|
|
2303
|
+
`display` is a `DockDisplay` or a display id (a `bigint`); the active display by
|
|
2304
|
+
default
|
|
2305
|
+
`region` is in the target display's own physical pixels, relative to its top
|
|
2306
|
+
left, and is not clipped to it, so a frame drawn 4 pixels outside a region at
|
|
2307
|
+
the display's edge stays where it was asked for; a region measured on another
|
|
2308
|
+
display has to be mapped by the caller
|
|
2309
|
+
It returns the bounds it applied (`WindowBounds`), so a frame or a canvas can
|
|
2310
|
+
follow them
|
|
2311
|
+
A window sent to a display with another scale first goes to that display's
|
|
2312
|
+
origin, so Windows rescales it there, and is then placed once at the bounds in
|
|
2313
|
+
that display's pixels; a rescale that changed the size anyway is placed again
|
|
2314
|
+
(at most twice)
|
|
2315
|
+
`coverWindow({ appWindow, display, region })` (`winui-svelte/window`) does the
|
|
2316
|
+
same for a bare `AppWindow`, and `coveredBounds` in `src/window/anchor.ts` is
|
|
2317
|
+
the plain arithmetic
|
|
2318
|
+
`outerBounds` and `appWindow` are physical pixels only in a PerMonitorV2
|
|
2319
|
+
process
|
|
2320
|
+
Not verified: whether a topmost window that equals a monitor's bounds changes
|
|
2321
|
+
the taskbar for that monitor, and whether a `backdrop="transparent"` cover is
|
|
2322
|
+
see-through at its edge pixels; try both before shipping an overlay on them
|
|
2323
|
+
|
|
2036
2324
|
`handle.geometry` is the window's own `window.outerWidth`, `outerHeight`,
|
|
2037
2325
|
`screenX`, `screenY`, `devicePixelRatio`, `resizeTo(width, height)`,
|
|
2038
2326
|
`resizeBy`, `moveTo(x, y)` and `moveBy`, in CSS pixels (WinUI's
|
|
@@ -2560,9 +2848,22 @@ An opt-in subpath: an app that does not import it does not bundle it
|
|
|
2560
2848
|
The running copy's `onRedirect` receives `activation`
|
|
2561
2849
|
- `launchApp({ command, arguments, workingDirectory })` starts a program
|
|
2562
2850
|
that outlives the caller: detached, no console window, no shared handles
|
|
2851
|
+
- `claimInstance({ key, source, activation, runOnUiThread, onRedirect })` is `ensureSingleInstance` over any source of the link
|
|
2852
|
+
Pass `createPipeSource()` to claim the pipe early on a plain main thread,
|
|
2853
|
+
before any WinUI loads, so a second copy exits in about 50 ms; it needs no
|
|
2854
|
+
dispatcher queue, and `runOnUiThread` relays `onRedirect` to the thread that
|
|
2855
|
+
owns the windows (`pipeNameFor` and `currentUserSid` are the pipe's name
|
|
2856
|
+
and its user)
|
|
2563
2857
|
- `activateOrLaunch({ key, activation, launch })` is the two together: it
|
|
2564
2858
|
activates the running copy, or else starts the app with `launch`, and
|
|
2565
2859
|
resolves with true for the first and false for the second
|
|
2860
|
+
- `activateInstance` and `launchApp` first call `AllowSetForegroundWindow` for
|
|
2861
|
+
any process, as does the standalone tray after a menu pick and before a
|
|
2862
|
+
click's handler: Windows' foreground lock refuses the window of another
|
|
2863
|
+
process, and only the process that received the user's input can lift it
|
|
2864
|
+
`handle.bringToFront()` also joins the foreground thread's input (the same
|
|
2865
|
+
call as `bringWindowToFront`), so a window asked from another process comes
|
|
2866
|
+
to the front instead of flashing on the taskbar
|
|
2566
2867
|
- `relaunch({ arguments })` starts the same Node with the same flags, entry
|
|
2567
2868
|
script (`process.argv[1]`) and then `arguments`, detached, and calls
|
|
2568
2869
|
`exitApplication`, so the new copy outlives this one
|
|
@@ -2571,9 +2872,13 @@ An opt-in subpath: an app that does not import it does not bundle it
|
|
|
2571
2872
|
redirects to it
|
|
2572
2873
|
An app whose windows run in a worker thread passes `entryScript`, the script
|
|
2573
2874
|
that starts the process, because `process.argv[1]` there is the worker's
|
|
2875
|
+
A single executable application (a Node `node:sea` build, where
|
|
2876
|
+
`process.execPath` is the app's own exe) is relaunched as the exe and
|
|
2877
|
+
`arguments`, with no script and no Node flags
|
|
2574
2878
|
- `restartAfterCrash({ arguments, conditions })` is
|
|
2575
2879
|
`RegisterApplicationRestart`: Windows starts the same Node and entry
|
|
2576
|
-
script with `arguments` after a crash,
|
|
2880
|
+
script (a single executable: its own exe) with `arguments` after a crash,
|
|
2881
|
+
a hang, an update that closes the
|
|
2577
2882
|
app or a reboot for one; `conditions` is a subset of `RestartCondition`
|
|
2578
2883
|
(`crash`, `hang`, `update`, `reboot`; all by default)
|
|
2579
2884
|
Limits: no callback (a crashed Node cannot run code, so
|
|
@@ -2595,10 +2900,12 @@ import {
|
|
|
2595
2900
|
ActivationKind,
|
|
2596
2901
|
installProtocolHandlers,
|
|
2597
2902
|
launchAtLogin,
|
|
2903
|
+
packagedActivation,
|
|
2598
2904
|
registerFileTypes,
|
|
2599
2905
|
startActivation,
|
|
2600
2906
|
} from "winui-svelte/app/activation";
|
|
2601
2907
|
|
|
2908
|
+
const packaged = packagedActivation(); // { kind: "protocol", uri } or { kind: "startup" }
|
|
2602
2909
|
installProtocolHandlers();
|
|
2603
2910
|
navigator.registerProtocolHandler("note", "https://notes.example/open?uri=%s");
|
|
2604
2911
|
registerFileTypes({ id: "com.example.notes", extensions: [".note"] });
|
|
@@ -2626,6 +2933,7 @@ if (!single.isPrimary) {
|
|
|
2626
2933
|
| `unregisterFileTypes({ id, extensions })` | deletes both and the empty keys left | returns the extensions removed |
|
|
2627
2934
|
| `launchAtLogin({ id, isEnabled, arguments })` | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` value `id` | listed in Settings, Apps, Startup; the start arrives as `startup` |
|
|
2628
2935
|
| `getLaunchAtLogin({ id })` | reads that value | `{ isEnabled, commandLine }`; the user's switch in Settings is not read |
|
|
2936
|
+
| `packagedActivation()` | `AppInstance.getActivatedEventArgs()` | how a packaged process was started; `undefined` outside a package |
|
|
2629
2937
|
| `startActivation({ key, onActivation })` | `ensureSingleInstance` and the command line | one `ActivationEvent` per start or redirect |
|
|
2630
2938
|
|
|
2631
2939
|
- `ActivationEvent` is a union on `kind` (`ActivationKind`, also from
|
|
@@ -2665,18 +2973,116 @@ if (!single.isPrimary) {
|
|
|
2665
2973
|
characters at most) and handed to your code, never run
|
|
2666
2974
|
Windows can pass a quote in a link through `"%1"` unescaped, so treat the
|
|
2667
2975
|
whole of `uri` as untrusted
|
|
2976
|
+
- Packaged apps: a package declares its scheme in the manifest, so
|
|
2977
|
+
`installProtocolHandlers` is not needed; `startActivation` reads the start
|
|
2978
|
+
from two places and merges them, the command line first
|
|
2979
|
+
1. Route A, the command line: give the protocol `Parameters`, and Windows
|
|
2980
|
+
passes the address as an argument, for a cold start
|
|
2981
|
+
|
|
2982
|
+
```xml
|
|
2983
|
+
<Extensions>
|
|
2984
|
+
<uap3:Extension Category="windows.protocol" Executable="my-app.exe"
|
|
2985
|
+
EntryPoint="Windows.FullTrustApplication">
|
|
2986
|
+
<uap3:Protocol Name="my-scheme" Parameters=""%1"" />
|
|
2987
|
+
</uap3:Extension>
|
|
2988
|
+
</Extensions>
|
|
2989
|
+
```
|
|
2990
|
+
|
|
2991
|
+
2. Route B, the Windows App SDK: `packagedActivation()` reads
|
|
2992
|
+
`AppInstance.getCurrent().getActivatedEventArgs()`; a `Protocol`
|
|
2993
|
+
activation gives its address and a `StartupTask` activation is a
|
|
2994
|
+
`startup` event, which Route A cannot say (a startup task takes no
|
|
2995
|
+
`Parameters`)
|
|
2996
|
+
|
|
2997
|
+
```xml
|
|
2998
|
+
<desktop:Extension Category="windows.startupTask" Executable="my-app.exe"
|
|
2999
|
+
EntryPoint="Windows.FullTrustApplication">
|
|
3000
|
+
<desktop:StartupTask TaskId="Startup" Enabled="false" DisplayName="My app" />
|
|
3001
|
+
</desktop:Extension>
|
|
3002
|
+
```
|
|
3003
|
+
|
|
3004
|
+
An address the command line holds wins over the activation's; a later
|
|
3005
|
+
copy's address arrives through the single instance link as a redirect, as
|
|
3006
|
+
everywhere, so never call `redirectActivationToAsync`
|
|
3007
|
+
`packagedActivation()` answers `undefined` outside a package, for a plain
|
|
3008
|
+
launch and for any failure; it never throws
|
|
3009
|
+
Call `startActivation` after `initWindowsAppSdk` (`initWindowsAppSdk`)
|
|
2668
3010
|
- Needs packaging for: the share target and a default-app claim (a package
|
|
2669
3011
|
manifest declares them); unpackaged, the app is offered in Open with and the
|
|
2670
3012
|
user picks the default
|
|
2671
3013
|
- `installProtocolHandlers()` returns the function that removes the two
|
|
2672
3014
|
navigator methods; the registrations stay until you unregister them
|
|
2673
3015
|
Each registration function takes `registry` (a fake in tests) and `command`
|
|
3016
|
+
- `test/packaged-activation.test.ts` (opt in with `WINUI_SVELTE_PACKAGED_TEST=1`)
|
|
3017
|
+
registers a throwaway package with both routes and starts it with a link
|
|
2674
3018
|
- `src/app/activation/native.test.ts` registers a protocol, a file type and a
|
|
2675
3019
|
startup entry under HKCU with a unique name, reads them with `reg query`,
|
|
2676
3020
|
removes them and checks nothing is left, even when it fails;
|
|
2677
3021
|
`test/activation.test.ts` starts real second copies with a link, a file and
|
|
2678
3022
|
nothing, and checks the first hears each as one event
|
|
2679
3023
|
|
|
3024
|
+
### Native messaging host (`winui-svelte/app/native-messaging`)
|
|
3025
|
+
|
|
3026
|
+
Telling the browsers where a native messaging host lives, for the current user
|
|
3027
|
+
|
|
3028
|
+
```ts
|
|
3029
|
+
import { registerNativeMessagingHost } from "winui-svelte/app/native-messaging";
|
|
3030
|
+
import { isInstanceRunning } from "winui-svelte/app";
|
|
3031
|
+
|
|
3032
|
+
registerNativeMessagingHost({
|
|
3033
|
+
name: "com.example.notes",
|
|
3034
|
+
manifestPath: "C:\Users\me\AppData\Local\Notes\host.json",
|
|
3035
|
+
});
|
|
3036
|
+
|
|
3037
|
+
const isAppUp = isInstanceRunning({ key: "com.example.notes" });
|
|
3038
|
+
```
|
|
3039
|
+
|
|
3040
|
+
- `registerNativeMessagingHost({ name, manifestPath, browsers, registry })`
|
|
3041
|
+
writes the manifest's path as the default value of
|
|
3042
|
+
`HKCU\Software\<browser>\NativeMessagingHosts\<name>` for Chrome, Edge,
|
|
3043
|
+
Brave and Chromium (`NativeMessagingBrowser`; pass `browsers` for fewer)
|
|
3044
|
+
It writes the registry only: the JSON manifest is the caller's file
|
|
3045
|
+
Calling it again rewrites the same values; a name other than lowercase
|
|
3046
|
+
letters, digits, `_` and `.` between them, or a relative path, is a
|
|
3047
|
+
`TypeError`
|
|
3048
|
+
- `unregisterNativeMessagingHost({ name, browsers, registry })` deletes the
|
|
3049
|
+
host's own keys and each parent left empty; a key that holds anything else
|
|
3050
|
+
stays
|
|
3051
|
+
- Under a package identity the write is virtualized unless the manifest
|
|
3052
|
+
declares `desktop6:RegistryWriteVirtualization` as disabled and the
|
|
3053
|
+
`unvirtualizedResources` capability; browsers read the real registry
|
|
3054
|
+
- `isInstanceRunning({ key })` is true while a copy serves `key`
|
|
3055
|
+
(`ensureSingleInstance` or `claimInstance`); it asks the pipe's existence,
|
|
3056
|
+
sends nothing and never starts or claims anything, so a host can ask
|
|
3057
|
+
before it starts the app
|
|
3058
|
+
|
|
3059
|
+
### Win32 seam (`winui-svelte/win32`)
|
|
3060
|
+
|
|
3061
|
+
An escape hatch for a Win32 function that WinRT has no equivalent for, over
|
|
3062
|
+
the binder the package uses itself
|
|
3063
|
+
|
|
3064
|
+
```ts
|
|
3065
|
+
import { bindDll, hasPackageIdentity } from "winui-svelte/win32";
|
|
3066
|
+
|
|
3067
|
+
const user32 = bindDll({
|
|
3068
|
+
dll: "user32.dll",
|
|
3069
|
+
functions: { foreground: ["GetForegroundWindow", [], "pointer"] },
|
|
3070
|
+
});
|
|
3071
|
+
const hwnd = user32.foreground();
|
|
3072
|
+
```
|
|
3073
|
+
|
|
3074
|
+
- `bindDll({ dll, functions })` takes one `[entryPoint, parameters,
|
|
3075
|
+
returnType]` row per name and calls with plain values (numbers, bigints,
|
|
3076
|
+
strings as wide text, memory, null) and gives back a number or an address
|
|
3077
|
+
- `bind(...)` is the lower level one, over `DynWin32` values
|
|
3078
|
+
`pointerOf`, `wideMemory`, `numberOf`, `addressOf`, `withMemory` and
|
|
3079
|
+
`WIDE_CHAR_BYTES` are its helpers; the caller owns the memory it allocates
|
|
3080
|
+
- `hasPackageIdentity()` tells a packaged process from plain Node
|
|
3081
|
+
- Types are strings and `@microsoft/dynwinrt` is a preview, so this entry may
|
|
3082
|
+
change with it; the registry has its own typed entry
|
|
3083
|
+
(`createWindowsRegistry` in `winui-svelte/app/activation`, string values of
|
|
3084
|
+
the current user only)
|
|
3085
|
+
|
|
2680
3086
|
### Jump list tasks (`winui-svelte/app/jump-list`)
|
|
2681
3087
|
|
|
2682
3088
|
Entries in the Tasks section of the taskbar button's right-click menu
|
|
@@ -2926,6 +3332,65 @@ const hotkey = registerHotkey({
|
|
|
2926
3332
|
posts `WM_HOTKEY` to the thread itself with `PostThreadMessageW`; no key is
|
|
2927
3333
|
pressed
|
|
2928
3334
|
|
|
3335
|
+
### Following the foreground app (`winui-svelte/window/foreground`)
|
|
3336
|
+
|
|
3337
|
+
Opt-in; nothing runs at import
|
|
3338
|
+
|
|
3339
|
+
```ts
|
|
3340
|
+
import {
|
|
3341
|
+
bringWindowToFront,
|
|
3342
|
+
shouldRestore,
|
|
3343
|
+
trackForeground
|
|
3344
|
+
} from "winui-svelte/window/foreground";
|
|
3345
|
+
|
|
3346
|
+
const tracker = trackForeground({
|
|
3347
|
+
ownWindows: () => [pillHwnd],
|
|
3348
|
+
onChanged: ({ hwnd, isRealApp }) => {}
|
|
3349
|
+
});
|
|
3350
|
+
tracker.lastRealApp; // bigint | null, the last real app that was in front
|
|
3351
|
+
tracker.current; // bigint | null
|
|
3352
|
+
tracker.stop(); // idempotent
|
|
3353
|
+
|
|
3354
|
+
const isBack = shouldRestore({
|
|
3355
|
+
lastRealApp: tracker.lastRealApp,
|
|
3356
|
+
foreground: tracker.foreground
|
|
3357
|
+
});
|
|
3358
|
+
if (isBack && tracker.lastRealApp !== null) {
|
|
3359
|
+
bringWindowToFront(tracker.lastRealApp); // true when Windows took it
|
|
3360
|
+
}
|
|
3361
|
+
```
|
|
3362
|
+
|
|
3363
|
+
- `trackForeground({ onChanged, ownWindows, ignoredClasses, tracking,
|
|
3364
|
+
intervalMilliseconds })` runs on the UI thread of a `runWindow` app
|
|
3365
|
+
- `tracking: "events"` (default, `ForegroundTracking.events`): the shell posts
|
|
3366
|
+
a message to a hidden window of the app on each change
|
|
3367
|
+
(`RegisterShellHookWindow` and `SHELLHOOK`), the message pump reads it, and
|
|
3368
|
+
`GetForegroundWindow` is read once; an idle foreground costs nothing
|
|
3369
|
+
dynwinrt delivers no native callbacks, so `SetWinEventHook` cannot be used
|
|
3370
|
+
If Windows refuses the registration, use `tracking: "polling"`
|
|
3371
|
+
- `tracking: "polling"`: one `GetForegroundWindow` per `intervalMilliseconds`
|
|
3372
|
+
(100 by default, 16 at least); latency is one tick
|
|
3373
|
+
The class and the process of a window are read once, when it is first seen
|
|
3374
|
+
- The filter: a real app is not the desktop, not a shell class
|
|
3375
|
+
(`ForegroundShellClass`: `Progman`, `WorkerW`, `Shell_TrayWnd`,
|
|
3376
|
+
`Shell_SecondaryTrayWnd`, `CopilotKeyPressFocusFrame`), not a window of
|
|
3377
|
+
this process, and not in `ownWindows()` or `ignoredClasses`
|
|
3378
|
+
`lastRealApp` changes only on a real app
|
|
3379
|
+
- `bringWindowToFront(hwnd)` joins this thread to the foreground thread's
|
|
3380
|
+
input for `BringWindowToTop` and `SetForegroundWindow`, then detaches,
|
|
3381
|
+
because a hotkey's key releases went to the app in front and Windows'
|
|
3382
|
+
foreground lock refuses a plain call; it restores a minimized window first,
|
|
3383
|
+
sends no input and returns whether the window ended in front
|
|
3384
|
+
It is best effort: a foreground window of a higher integrity level or a hung
|
|
3385
|
+
one still refuses; the tray menu window takes the foreground through it
|
|
3386
|
+
- Not measured yet: the idle cost of each mode (the tray's 30 Hz timer costs
|
|
3387
|
+
about 2 percent of a core in an idle window)
|
|
3388
|
+
|
|
3389
|
+
Manual checklist: press the app's hotkey from Notepad, then from the desktop,
|
|
3390
|
+
then from a browser on a second monitor; each time the key goes back to where
|
|
3391
|
+
it was; then Alt+Tab to another app while the overlay is up and confirm it is
|
|
3392
|
+
not pulled back
|
|
3393
|
+
|
|
2929
3394
|
### System tray (`winui-svelte/tray`)
|
|
2930
3395
|
|
|
2931
3396
|
WinUI and the Windows App SDK have no notification-area API (apps call
|
|
@@ -3127,8 +3592,13 @@ const lines = resolveMenu({
|
|
|
3127
3592
|
labels and ticks only); `closeThenRun` (true unless set to false) runs
|
|
3128
3593
|
`onselect` after the menu has closed, so that a dialog can open
|
|
3129
3594
|
- A submenu may have its own `onselect` and `autoExpand`
|
|
3130
|
-
- `icon` is a path, a glyph
|
|
3131
|
-
|
|
3595
|
+
- `icon` is a path, a glyph, `IconPixels`, `{ forLightMenu, forDarkMenu }` (one
|
|
3596
|
+
picture for each menu theme) or `{ tinted }` (a single-color glyph that the
|
|
3597
|
+
menu paints in its text color, so one picture serves both themes); each
|
|
3598
|
+
renderer draws what it can (the popup menu of `winui-svelte/tray/standalone`
|
|
3599
|
+
draws files and pixels, a flyout draws paths and glyphs, and takes the light
|
|
3600
|
+
member of a pair)
|
|
3601
|
+
`shortcut` is display text only, the menu does not bind the key
|
|
3132
3602
|
- `MenuProfile` is plain JSON: `level`, `hidden` (ids the level shows that
|
|
3133
3603
|
the user hid), `shown` (ids above the level that the user turned on) and
|
|
3134
3604
|
`order` (child ids in the user order, keyed by parent id, `""` for the root)
|
|
@@ -3324,13 +3794,19 @@ createStandaloneTray({
|
|
|
3324
3794
|
`bounds` when their extras are passed
|
|
3325
3795
|
The icon keeps the process alive; `remove()` or the process ending takes it
|
|
3326
3796
|
out of the tray
|
|
3797
|
+
- `colorScheme` is the menu's `color-scheme` as the web says it: `"light dark"`
|
|
3798
|
+
(the default) makes the popup dark when Windows' app theme is, `"light"` and
|
|
3799
|
+
`"dark"` force one; `MenuColorScheme` names the three values
|
|
3800
|
+
It uses uxtheme's `SetPreferredAppMode` and `FlushMenuThemes` (ordinals 135
|
|
3801
|
+
and 136), applied before each menu opens, so it affects the process's other
|
|
3802
|
+
native menus too
|
|
3327
3803
|
- The default is the smallest tray: an icon from one `.ico` path, clicks,
|
|
3328
3804
|
`update`, `remove` and the menu
|
|
3329
|
-
|
|
3805
|
+
Four parts are opt-in, each one import from the same entry, passed in
|
|
3330
3806
|
`extras`, and none of their code is in the bundle unless passed:
|
|
3331
|
-
`balloons` adds `notify`, `bounds` adds `bounds()`,
|
|
3807
|
+
`balloons` adds `notify`, `bounds` adds `bounds()`, `themedIcon` lets
|
|
3332
3808
|
`icon` be `{ forLightTaskbar, forDarkTaskbar }`, swapped as the taskbar theme
|
|
3333
|
-
changes
|
|
3809
|
+
changes, and `menuIcons` draws the icons of the menu's lines (below)
|
|
3334
3810
|
The handle has `notify` or `bounds` only when its extra is passed, and a
|
|
3335
3811
|
theme pair is accepted only with `themedIcon`; otherwise it fails to compile
|
|
3336
3812
|
`createTrayIcon` and `TrayIcon` of `winui-svelte/tray` include all three
|
|
@@ -3369,12 +3845,29 @@ tray.notify({ title: "Ready" });
|
|
|
3369
3845
|
labels and ticks, right after the line runs; `onselect` otherwise runs on
|
|
3370
3846
|
the next turn after the menu is gone (`closeThenRun: false` runs it as the
|
|
3371
3847
|
menu closes)
|
|
3372
|
-
A submenu's own `onselect` and `autoExpand
|
|
3373
|
-
|
|
3374
|
-
|
|
3848
|
+
A submenu's own `onselect` and `autoExpand` do nothing here: Windows opens a
|
|
3849
|
+
submenu row without reporting a pick
|
|
3850
|
+
Without `menuIcons` in `extras` no line shows an icon, and the roughly 6 KB
|
|
3851
|
+
of the decoder and the bitmap code stay out of the bundle
|
|
3852
|
+
With it, every `icon` is drawn as a bitmap beside the label, on commands,
|
|
3853
|
+
checks, radios and submenu rows at any depth: a path to a png, ico, bmp, jpeg, gif
|
|
3854
|
+
or tiff (decoded by GDI+, kept by path and modification time, so a menu that
|
|
3855
|
+
opens again does not decode again), `IconPixels`, a `{ forLightMenu,
|
|
3856
|
+
forDarkMenu }` pair, or `{ tinted }` for a monochrome glyph (only its alpha is
|
|
3857
|
+
used, and it takes the menu's text color)
|
|
3858
|
+
The theme is read each time the menu opens, by the rule `colorScheme` sets
|
|
3859
|
+
(the system's app mode for `"light dark"`), so a pair and a tinted glyph
|
|
3860
|
+
follow a theme change; the bitmap is a 32-bit premultiplied DIB section, the
|
|
3861
|
+
size of the menu's check mark at the screen's scale (at least the small icon
|
|
3862
|
+
size), and is freed with the menu
|
|
3863
|
+
A disabled line gets a grey, fainter icon (Windows does not dim a bitmap),
|
|
3864
|
+
and a ticked line or radio gets a frame around its icon, because Windows
|
|
3865
|
+
draws the icon where the tick would be
|
|
3866
|
+
A path that cannot be read leaves the line without an icon; the rest of the
|
|
3867
|
+
menu opens as usual
|
|
3375
3868
|
The menu is modal: the thread runs its own message loop until it closes
|
|
3376
|
-
|
|
3377
|
-
|
|
3869
|
+
`colorScheme` makes it follow the system theme through an undocumented
|
|
3870
|
+
uxtheme call; a menu that must be drawn in WinUI belongs in
|
|
3378
3871
|
`winui-svelte/tray` with `TrayIcon`'s `menu` snippet
|
|
3379
3872
|
- The same entry re-exports `activateInstance`, `activateOrLaunch` and
|
|
3380
3873
|
`launchApp` from `winui-svelte/app` (App lifecycle), so a tray imports from
|
|
@@ -3385,6 +3878,76 @@ tray.notify({ title: "Ready" });
|
|
|
3385
3878
|
component, window or renderer module, or a component's name, is in the
|
|
3386
3879
|
output, or if it grows past its budget
|
|
3387
3880
|
|
|
3881
|
+
### Trays and windows are independent
|
|
3882
|
+
|
|
3883
|
+
Neither needs the other
|
|
3884
|
+
A process can have zero windows and several tray icons, or windows and
|
|
3885
|
+
taskbar buttons and no tray; nothing is created for the part you leave out
|
|
3886
|
+
|
|
3887
|
+
```ts
|
|
3888
|
+
// Zero windows, two icons, one Node process
|
|
3889
|
+
import { createStandaloneTray, MenuColorScheme, MenuItemKind } from "winui-svelte/tray/standalone";
|
|
3890
|
+
import { defaultProgressRegistry, progressText } from "winui-svelte/progress/core";
|
|
3891
|
+
|
|
3892
|
+
createStandaloneTray({
|
|
3893
|
+
icon: "recorder.ico",
|
|
3894
|
+
tooltip: "Recorder",
|
|
3895
|
+
colorScheme: MenuColorScheme.DARK,
|
|
3896
|
+
menu: () => [{
|
|
3897
|
+
kind: MenuItemKind.COMMAND,
|
|
3898
|
+
id: "status",
|
|
3899
|
+
label: progressText(defaultProgressRegistry().snapshot),
|
|
3900
|
+
onselect() {}
|
|
3901
|
+
}]
|
|
3902
|
+
});
|
|
3903
|
+
|
|
3904
|
+
createStandaloneTray({
|
|
3905
|
+
icon: "uploads.ico",
|
|
3906
|
+
tooltip: "Uploads",
|
|
3907
|
+
colorScheme: MenuColorScheme.LIGHT,
|
|
3908
|
+
menu: [{ kind: MenuItemKind.COMMAND, id: "quit", label: "Quit", onselect: () => process.exit(0) }]
|
|
3909
|
+
});
|
|
3910
|
+
```
|
|
3911
|
+
|
|
3912
|
+
```svelte
|
|
3913
|
+
<!-- Windows and a taskbar button, no tray -->
|
|
3914
|
+
<script lang="ts">
|
|
3915
|
+
import { Window } from "winui-svelte/components";
|
|
3916
|
+
import { TaskbarProgress } from "winui-svelte/progress";
|
|
3917
|
+
</script>
|
|
3918
|
+
|
|
3919
|
+
<Window>
|
|
3920
|
+
<TaskbarProgress />
|
|
3921
|
+
</Window>
|
|
3922
|
+
```
|
|
3923
|
+
|
|
3924
|
+
- Each `createStandaloneTray` has an identity of its own (its own hidden owner
|
|
3925
|
+
window and a unique id, and its own `guid` when you pass one), its own
|
|
3926
|
+
timer, its own menu and its own state; `remove()` takes out that icon only
|
|
3927
|
+
and the exit hook takes out all of them
|
|
3928
|
+
- Clicks are polled, and Windows keeps one "pressed since the last read"
|
|
3929
|
+
flag for the whole process, which the first read clears; the trays of a
|
|
3930
|
+
process share that read, so each icon hears a click shorter than its
|
|
3931
|
+
polling interval (the flag can still be cleared by another process or by
|
|
3932
|
+
other code of yours that calls `GetAsyncKeyState`)
|
|
3933
|
+
- The menu theme is one setting per process (uxtheme's preferred app mode);
|
|
3934
|
+
a tray sets its own `colorScheme` right before each of its menus opens, so
|
|
3935
|
+
two trays with different schemes each get theirs, because only one menu is
|
|
3936
|
+
open at a time
|
|
3937
|
+
The setting then stays until the next menu opens, so another popup menu in
|
|
3938
|
+
the same process (a window's) shows in the scheme of the tray that spoke
|
|
3939
|
+
last
|
|
3940
|
+
- `winui-svelte/progress/core` is the progress registry, operations and
|
|
3941
|
+
`progressText` with no Svelte component and no taskbar code, so a
|
|
3942
|
+
tray-only process can show progress; `winui-svelte/progress` adds
|
|
3943
|
+
`TaskbarProgress` and `bindTaskbarProgress`, which are the only part that
|
|
3944
|
+
needs a window
|
|
3945
|
+
- `scripts/pack/independence.test.ts` walks the imports and fails if the
|
|
3946
|
+
standalone tray reaches a component, the renderer, the window runtime or
|
|
3947
|
+
taskbar code, if the taskbar progress reaches a tray, or if a window
|
|
3948
|
+
reaches a tray; `scripts/pack/tray-only.test.ts` bundles two trays with the
|
|
3949
|
+
registry and fails on the same, or on a growing size
|
|
3950
|
+
|
|
3388
3951
|
### Tray as an entrypoint (`entrypoints/tray.ts`)
|
|
3389
3952
|
|
|
3390
3953
|
The app does not have to know it has a tray; the tray is its own file, found
|
|
@@ -3425,6 +3988,14 @@ export default defineTray({
|
|
|
3425
3988
|
- `guid` is required: it keeps the icon's place in the tray and names the one
|
|
3426
3989
|
tray process, so a second `tray.js` exits at once
|
|
3427
3990
|
- `onactivate` runs on a left click when `onclick` is not given
|
|
3991
|
+
- `export default [defineTray({ ... }), defineTray({ ... })]` defines several
|
|
3992
|
+
trays in one entrypoint: one `tray.js`, one process, each tray with its own
|
|
3993
|
+
`guid`, icon, tooltip, menu and `colorScheme` (every `guid` must differ)
|
|
3994
|
+
The first tray's `guid` names the process, so keep the order; `tray.json` is
|
|
3995
|
+
the single manifest for one tray and `{ "trays": [ ... ] }` for several, and
|
|
3996
|
+
`startTray()` reads the first `guid` from either
|
|
3997
|
+
The markup form (`tray.svelte`) is one tray; use `tray.ts` for several
|
|
3998
|
+
`examples/tray-multiple` is a two-icon entrypoint with no window
|
|
3428
3999
|
- The build reads `icon`, `tooltip` and `guid` from the syntax tree, never by
|
|
3429
4000
|
running the file, so a top-level import of WinRT in `tray.ts` does not
|
|
3430
4001
|
execute at build; `icon` and `guid` must be string literals, and the icon a
|
|
@@ -3773,6 +4344,46 @@ const lines = menus.menu(ContextMenuSurface.TRAY);
|
|
|
3773
4344
|
`ContextMenuSurface`, `ContextType`, `ChromeEvent`, and the types
|
|
3774
4345
|
`CreateProperties`, `OnClickData` and `UpdateProperties`
|
|
3775
4346
|
|
|
4347
|
+
## Security (`winui-svelte/security`)
|
|
4348
|
+
|
|
4349
|
+
Windows DPAPI for secrets an app keeps on disk, with nothing to install: no
|
|
4350
|
+
native addon, no WinRT, only the Win32 calls through the package's own binder
|
|
4351
|
+
Opt-in: nothing is bundled until an app imports it (about 3 KB), and importing
|
|
4352
|
+
does no work
|
|
4353
|
+
|
|
4354
|
+
The blob is the one .NET's `ProtectedData.Protect` makes, so a TypeScript app
|
|
4355
|
+
reads the files a .NET app wrote with `CurrentUser` scope, and the other way
|
|
4356
|
+
round; `ProtectionScope` is `DataProtectionScope`'s two values
|
|
4357
|
+
|
|
4358
|
+
```ts
|
|
4359
|
+
import { ProtectionScope, protectData, unprotectData, wipe } from "winui-svelte/security";
|
|
4360
|
+
|
|
4361
|
+
const sealed = protectData({
|
|
4362
|
+
data: new TextEncoder().encode(apiKey),
|
|
4363
|
+
scope: ProtectionScope.CURRENT_USER
|
|
4364
|
+
});
|
|
4365
|
+
await writeFile("settings.bin", sealed);
|
|
4366
|
+
|
|
4367
|
+
const plain = unprotectData({ data: await readFile("settings.bin") });
|
|
4368
|
+
useKey(new TextDecoder().decode(plain));
|
|
4369
|
+
wipe(plain);
|
|
4370
|
+
```
|
|
4371
|
+
|
|
4372
|
+
- `protectData({ data, entropy?, scope?, description? })` returns the sealed
|
|
4373
|
+
bytes; `entropy` is mixed into the key and needed again to unseal
|
|
4374
|
+
- `unprotectData({ data, entropy?, scope? })` returns the plain bytes
|
|
4375
|
+
- `wipe(buffer)` zeroes a buffer; the native buffers the helper used are zeroed
|
|
4376
|
+
before release, the copies you hold are yours to wipe, and a string cannot be
|
|
4377
|
+
wiped, so keep secrets as bytes
|
|
4378
|
+
- `DataProtectionError` carries the Win32 `code` (87 for bytes that are no
|
|
4379
|
+
blob, 13 for a corrupted blob or the wrong entropy); the message never holds
|
|
4380
|
+
the data
|
|
4381
|
+
- `MAX_DATA_BYTES` (64 MiB) is the limit of one call; more throws `RangeError`
|
|
4382
|
+
- A UI prompt can never appear (`CRYPTPROTECT_UI_FORBIDDEN`)
|
|
4383
|
+
- DPAPI offers no recovery: keys follow the user's logon secret, so an
|
|
4384
|
+
administrator's password reset can make old blobs unreadable; a packaged app
|
|
4385
|
+
keeps the same user keys as an unpackaged one
|
|
4386
|
+
|
|
3776
4387
|
## Downloads (`winui-svelte/downloads`)
|
|
3777
4388
|
|
|
3778
4389
|
Downloads on the two APIs an app already knows: the web's `fetch` with the File
|
|
@@ -4447,8 +5058,12 @@ pixels), `offsetX`/`offsetY` (the control), `altKey`, `ctrlKey`, `shiftKey`,
|
|
|
4447
5058
|
`DataTransfer` has `types`, `files`, `items` (`DataTransferItemList`: `length`,
|
|
4448
5059
|
`at`, `add`, iteration; items have `kind`, `type`, `getAsString`, `getAsFile`),
|
|
4449
5060
|
`getData(type)`, `setData(type, value)`, `clearData(type?)`, `effectAllowed`
|
|
4450
|
-
(`
|
|
4451
|
-
draws its own preview) and `bitmap` (a picture to drag)
|
|
5061
|
+
(`EffectAllowedName`), `dropEffect` (`DropEffectName`), `setDragImage` (accepted,
|
|
5062
|
+
WinUI draws its own preview) and `bitmap` (a picture to drag)
|
|
5063
|
+
`DropEffect` and `EffectAllowed` hold the names, so an editor suggests
|
|
5064
|
+
`DropEffect.link`; `DropEffectName` and `EffectAllowedName` are those names or
|
|
5065
|
+
any other string, and an unknown string counts as `none` for a drop effect and
|
|
5066
|
+
as `uninitialized` (everything allowed) for `effectAllowed`
|
|
4452
5067
|
The standard formats are `text/plain` (Text), `text/html` (the fragment of the
|
|
4453
5068
|
HTML format), `text/uri-list` (Uri), `Files` (StorageItems) and, for a picture,
|
|
4454
5069
|
a `NativeFile` in `files`; any other format id is a custom text format, listed
|
|
@@ -4485,6 +5100,36 @@ window's content to take drops anywhere on the window
|
|
|
4485
5100
|
`onDragEnter`, `onDragOver`, `onDragLeave` and `onDrop` take the same
|
|
4486
5101
|
`DragEvent` as the web names
|
|
4487
5102
|
|
|
5103
|
+
Which part of the window takes a drag (accepting selectively):
|
|
5104
|
+
|
|
5105
|
+
- only a zone takes a drag; a point outside every zone shows the forbidden sign,
|
|
5106
|
+
so a section of the window is the only place that accepts when it alone has
|
|
5107
|
+
`dropzone`
|
|
5108
|
+
- the zone under the cursor answers; with nested zones the innermost one
|
|
5109
|
+
decides, and a zone that refuses (its `accept` takes nothing the drag
|
|
5110
|
+
carries) refuses for its whole area even when an outer zone would accept
|
|
5111
|
+
- a zone on the root element of the window is the window-wide default; put a
|
|
5112
|
+
zone with a narrower `accept` (or one that refuses) on a section to
|
|
5113
|
+
override it there
|
|
5114
|
+
- `accept` is judged per zone, so one window can have a folder-only zone and a
|
|
5115
|
+
text-only zone side by side
|
|
5116
|
+
- a drag that started inside the window (a list reordering its own items)
|
|
5117
|
+
carries no files, so a zone with `accept: ["directory", ".zip"]` leaves it to
|
|
5118
|
+
the control
|
|
5119
|
+
|
|
5120
|
+
A drag from another app (Explorer, a browser) reaches a WinUI 3 window as an OLE
|
|
5121
|
+
drag, and WinUI 3 registers no OLE drop target on its window: without one,
|
|
5122
|
+
Windows shows the forbidden sign over the whole window and no `dragenter` ever
|
|
5123
|
+
fires
|
|
5124
|
+
The first zone of a window registers one (`RegisterDragDrop` on the top-level
|
|
5125
|
+
window, `src/data-transfer/ole-drop-target.ts`), and it is revoked with the
|
|
5126
|
+
last zone or when the window is destroyed; each call is routed to the zone under
|
|
5127
|
+
the cursor by a hit test of the visual tree (`src/data-transfer/window-drop.ts`)
|
|
5128
|
+
The data object is read through the classic formats (files and folders as
|
|
5129
|
+
`CF_HDROP`, text, a link, HTML); a dragged picture from another app is not read
|
|
5130
|
+
yet
|
|
5131
|
+
`simulateDrop` stays the way to test a zone without any OLE call
|
|
5132
|
+
|
|
4488
5133
|
`draggable(options)`: `text`, `html`, `uri`, `files`, `bitmap`, `effectAllowed`,
|
|
4489
5134
|
and `onDragStart` / `onDrag` / `onDragEnd`
|
|
4490
5135
|
Drag out to Explorer works with `files` (paths become `StorageFile` and
|
|
@@ -4556,6 +5201,170 @@ takes drops, through the handlers a real drop reaches, and resolves with the
|
|
|
4556
5201
|
operation the control accepted (`0` when it refused); it sends no input, so an
|
|
4557
5202
|
app can test its drop handling in a real window
|
|
4558
5203
|
|
|
5204
|
+
## Progress (`winui-svelte/progress`)
|
|
5205
|
+
|
|
5206
|
+
One progress object for any long work: a download, a file read, a copy, an OCR
|
|
5207
|
+
pass; it is a promise, an `EventTarget` with the platform events, and
|
|
5208
|
+
reactive state, in one value
|
|
5209
|
+
Operations list themselves in an app-wide registry, so the taskbar button and
|
|
5210
|
+
the tray show them with no setup
|
|
5211
|
+
Opt-in: nothing is bundled until an app imports it, and importing does no work
|
|
5212
|
+
|
|
5213
|
+
### Five call sites
|
|
5214
|
+
|
|
5215
|
+
```svelte
|
|
5216
|
+
<script lang="ts">
|
|
5217
|
+
import { Button, ProgressBar, TextBlock, Window } from "winui-svelte/components";
|
|
5218
|
+
import { fetchToFile } from "winui-svelte/downloads";
|
|
5219
|
+
import { TaskbarProgress } from "winui-svelte/progress";
|
|
5220
|
+
|
|
5221
|
+
// 1. A download with a bar: fetchToFile returns the operation at once
|
|
5222
|
+
const download = fetchToFile({ url, handle });
|
|
5223
|
+
download.then(size => console.log("saved", size)); // or: await download
|
|
5224
|
+
</script>
|
|
5225
|
+
|
|
5226
|
+
<Window>
|
|
5227
|
+
<TaskbarProgress /> <!-- 4. the taskbar shows every running operation -->
|
|
5228
|
+
<ProgressBar {...download.barProps} /> <!-- value, isIndeterminate, showPaused, showError -->
|
|
5229
|
+
<TextBlock>{download.loaded} of {download.total ?? "?"}</TextBlock>
|
|
5230
|
+
<Button onclick={() => download.cancel()}>Cancel</Button>
|
|
5231
|
+
</Window>
|
|
5232
|
+
```
|
|
5233
|
+
|
|
5234
|
+
```ts
|
|
5235
|
+
// 2. Reading a file from disk, with progress and cancel
|
|
5236
|
+
const read = handle.read({ onprogress: event => console.log(event.loaded, event.total) });
|
|
5237
|
+
const file = await read; // a File, like getFile()
|
|
5238
|
+
read.cancel(); // or abort the signal given in the options
|
|
5239
|
+
|
|
5240
|
+
// 3. Any other long work: one call, no lifecycle code
|
|
5241
|
+
const copy = trackOperation({
|
|
5242
|
+
label: "Copying photos",
|
|
5243
|
+
group: "sync",
|
|
5244
|
+
async run(operation) {
|
|
5245
|
+
for await (const chunk of source) {
|
|
5246
|
+
await write(chunk);
|
|
5247
|
+
operation.update({ loaded: (written += chunk.byteLength), total });
|
|
5248
|
+
operation.signal.throwIfAborted();
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
});
|
|
5252
|
+
|
|
5253
|
+
// 5. Retry: a failed fetchToFile continues where it stopped
|
|
5254
|
+
await fetchToFile({ url, handle, resume: true });
|
|
5255
|
+
```
|
|
5256
|
+
|
|
5257
|
+
```svelte
|
|
5258
|
+
<!-- Tray menu, in tray.svelte markup -->
|
|
5259
|
+
<TrayMenu>
|
|
5260
|
+
<TrayMenuProgress id="progress" /> <!-- "setup.exe - 45%", hidden when idle -->
|
|
5261
|
+
<TrayMenuOperations id="operations" label="Running" emptyLabel="Nothing running" />
|
|
5262
|
+
</TrayMenu>
|
|
5263
|
+
```
|
|
5264
|
+
|
|
5265
|
+
`{...download.barProps}` spreads onto a `ProgressBar`; Svelte then cannot tell
|
|
5266
|
+
at build time whether a scoped class selector matches that bar, so write the
|
|
5267
|
+
five props out when the same component has a `<style>` rule for its siblings
|
|
5268
|
+
|
|
5269
|
+
### Several windows and tray icons
|
|
5270
|
+
|
|
5271
|
+
The registry is app-wide; what a taskbar button or a tray line shows is scoped
|
|
5272
|
+
by `group` (a name an operation is given) or by an operation or registry given
|
|
5273
|
+
as `of`
|
|
5274
|
+
A `<TaskbarProgress />` drives the taskbar button of the window it sits in;
|
|
5275
|
+
`window={handle}` picks another
|
|
5276
|
+
|
|
5277
|
+
```svelte
|
|
5278
|
+
<script lang="ts">
|
|
5279
|
+
const upload = trackOperation({ group: "uploads", run });
|
|
5280
|
+
const download = fetchToFile({ url, handle, group: "downloads" });
|
|
5281
|
+
</script>
|
|
5282
|
+
|
|
5283
|
+
<!-- Window A: its taskbar button shows the downloads only -->
|
|
5284
|
+
<Window bind:handle={windowA}>
|
|
5285
|
+
<TaskbarProgress group="downloads" />
|
|
5286
|
+
</Window>
|
|
5287
|
+
|
|
5288
|
+
<!-- Window B: its own button shows one upload; window A is not touched -->
|
|
5289
|
+
<Window>
|
|
5290
|
+
<TaskbarProgress of={upload} />
|
|
5291
|
+
</Window>
|
|
5292
|
+
|
|
5293
|
+
<!-- The main window drives window A from outside -->
|
|
5294
|
+
<TaskbarProgress window={windowA} group="downloads" />
|
|
5295
|
+
|
|
5296
|
+
<!-- Two tray icons, each with its own menu and its own scope -->
|
|
5297
|
+
<TrayIcon>
|
|
5298
|
+
<TrayMenu>
|
|
5299
|
+
<TrayMenuProgress id="downloads" group="downloads" />
|
|
5300
|
+
</TrayMenu>
|
|
5301
|
+
</TrayIcon>
|
|
5302
|
+
<TrayIcon>
|
|
5303
|
+
<TrayMenu>
|
|
5304
|
+
<TrayMenuOperations id="uploads" label="Uploads" group="uploads" />
|
|
5305
|
+
</TrayMenu>
|
|
5306
|
+
</TrayIcon>
|
|
5307
|
+
```
|
|
5308
|
+
|
|
5309
|
+
### `ProgressOperation`
|
|
5310
|
+
|
|
5311
|
+
- It is `PromiseLike`: `await operation` gives the value passed to `complete`
|
|
5312
|
+
and throws the reason of `fail` or `cancel` (an `AbortError` by default); an
|
|
5313
|
+
operation nobody awaits raises no unhandled rejection
|
|
5314
|
+
- It is an `EventTarget` that fires `loadstart`, `progress`, `load`, `error`,
|
|
5315
|
+
`abort` and `loadend` as `OperationProgressEvent` (`lengthComputable`,
|
|
5316
|
+
`loaded`, `total`), in the order `XMLHttpRequest` and `FileReader` use, plus
|
|
5317
|
+
`pause`, `resume` and `change`; `onprogress` and its kin work as properties
|
|
5318
|
+
and as options
|
|
5319
|
+
- `value` (0 to 1), `loaded`, `total`, `state`, `isIndeterminate`,
|
|
5320
|
+
`showPaused`, `showError`, `label` and `barProps` are reactive in markup and
|
|
5321
|
+
in `$effect`, with the meaning `ProgressBar` gives them: a total that is
|
|
5322
|
+
unknown is indeterminate
|
|
5323
|
+
- `$operation` works too: it has `subscribe` and so is a Svelte store
|
|
5324
|
+
- `signal` is an `AbortSignal` that aborts on `cancel()`; a `signal` given to
|
|
5325
|
+
the constructor cancels the operation when it aborts
|
|
5326
|
+
- `start`, `update({ loaded, total })`, `pause`, `resume`, `complete(value)`
|
|
5327
|
+
and `fail(reason)` are for the code doing the work; `resume` also retries an
|
|
5328
|
+
errored operation (the other final states are final)
|
|
5329
|
+
- `ProgressState` is the closed set of states: `idle`, `running`, `paused`,
|
|
5330
|
+
`complete`, `error`, `canceled`
|
|
5331
|
+
|
|
5332
|
+
### Registry and scopes
|
|
5333
|
+
|
|
5334
|
+
- `defaultProgressRegistry()` is the app-wide registry; an operation lists
|
|
5335
|
+
itself there unless it gets `registry: otherRegistry` or `registry: false`
|
|
5336
|
+
- A finished or canceled operation leaves; a failed one stays so a red bar
|
|
5337
|
+
is not lost, until `clearFailed()` or `remove(operation)`
|
|
5338
|
+
- `registry.where("sync")` or `registry.where(operation => ...)` is a scoped
|
|
5339
|
+
registry that follows the first (call `dispose()` when done);
|
|
5340
|
+
`<TaskbarProgress group>` and the tray components do this for you
|
|
5341
|
+
- `snapshot`, `value`, `count`, `state`, `isIndeterminate`, `showPaused` and
|
|
5342
|
+
`showError` are the aggregate: the bar covers the operations that know their
|
|
5343
|
+
total, and is indeterminate only when none does; `paused` when all that are
|
|
5344
|
+
left are paused; `error` when only failed ones are left; `count` is the
|
|
5345
|
+
number unfinished
|
|
5346
|
+
- `aggregateSnapshots` is that rule as a pure function
|
|
5347
|
+
|
|
5348
|
+
### Taskbar and tray
|
|
5349
|
+
|
|
5350
|
+
- `<TaskbarProgress of group window taskbar />` draws nothing and keeps the
|
|
5351
|
+
taskbar button in step: a bar, a marquee when the total is unknown, paused
|
|
5352
|
+
yellow, error red, gone when nothing is left; the shell is told only when the
|
|
5353
|
+
bar moves by a thousandth
|
|
5354
|
+
- `bindTaskbarProgress({ source, taskbar })` is the same without markup (the
|
|
5355
|
+
`taskbar` option of `Downloads.download` uses it); `taskbarOptionsOf` is the
|
|
5356
|
+
mapping
|
|
5357
|
+
- `<TrayMenuProgress id of group />` is a command line with the text of
|
|
5358
|
+
`progressText(snapshot)`, hidden while nothing runs; `onselect` is yours
|
|
5359
|
+
- `<TrayMenuOperations id label of group />` is a submenu with a line per
|
|
5360
|
+
running operation; picking a line cancels it
|
|
5361
|
+
- `Downloads` gives each download an operation (`progress: registry` in its
|
|
5362
|
+
options picks the registry, `group` in `download({ ... })` the group), and
|
|
5363
|
+
`fetchToFile` returns one; `FileSystemFileHandle.read` is the extra (WinUI
|
|
5364
|
+
only) that reads a file in 1 MiB chunks
|
|
5365
|
+
- `trackStream({ stream, operation })` passes a `ReadableStream` through and
|
|
5366
|
+
reports the bytes; `trackOperation` is the whole lifecycle for any async work
|
|
5367
|
+
|
|
4559
5368
|
## Incremental loading (`winui-svelte/incremental`)
|
|
4560
5369
|
|
|
4561
5370
|
A list that loads its next batch as the user scrolls near the end, for
|
|
@@ -4666,6 +5475,10 @@ Everything runs on the UI thread
|
|
|
4666
5475
|
</border>
|
|
4667
5476
|
```
|
|
4668
5477
|
|
|
5478
|
+
`modifierKeysHeld()` reads which of Shift, Control and Alt are held right now, as
|
|
5479
|
+
`{ shiftKey, ctrlKey, altKey }`, for an action that carries no key state of its
|
|
5480
|
+
own (a form submitted with the keyboard, a file picker's result)
|
|
5481
|
+
|
|
4669
5482
|
`enableInputEvents()` adds the eleven names to the renderer's event-alias table
|
|
4670
5483
|
(`src/renderer/host/event-adapters.ts`, the one `enableDragEvents()` fills), so a
|
|
4671
5484
|
raw element takes them
|
|
@@ -6210,6 +7023,54 @@ The effect graph is checked on pixels without a window
|
|
|
6210
7023
|
(`src/win2d/effect-graph.test.ts`), and the effects in a real window through
|
|
6211
7024
|
`PrintWindow` (`test/effects.test.ts`, with `examples/effects`)
|
|
6212
7025
|
|
|
7026
|
+
### Packaged apps
|
|
7027
|
+
|
|
7028
|
+
A process with a package identity (an MSIX, or a registered loose layout) finds
|
|
7029
|
+
a class through its package's registration catalogue, which lists the classes
|
|
7030
|
+
of its framework packages and the `ActivatableClass` entries of its own
|
|
7031
|
+
manifest; the `PATH` that `initWindowsAppSdk` sets is not consulted
|
|
7032
|
+
Win2D ships no framework package, so every Win2D class fails there with
|
|
7033
|
+
`0x80040154` (class not registered) until the manifest names it, and CSS
|
|
7034
|
+
`filter: blur()` and every Win2D effect do nothing
|
|
7035
|
+
The same app unpackaged (`pnpm dev`) is fine
|
|
7036
|
+
|
|
7037
|
+
`win2dActivatableClasses` writes the entries, one `ActivatableClass` of one
|
|
7038
|
+
`InProcessServer` per Win2D class the bindings hold; put the result in the
|
|
7039
|
+
package's own `<Extensions>` (a child of `<Package>`, after `<Capabilities>`,
|
|
7040
|
+
not the application's), with `Microsoft.Graphics.Canvas.dll` in the package at
|
|
7041
|
+
`libraryPath`, which `buildApp` writes to `bin/<architecture>`
|
|
7042
|
+
|
|
7043
|
+
```ts
|
|
7044
|
+
import { win2dActivatableClasses } from "winui-svelte/win2d/manifest";
|
|
7045
|
+
|
|
7046
|
+
const fragment = win2dActivatableClasses({
|
|
7047
|
+
libraryPath: "bin/x64/Microsoft.Graphics.Canvas.dll"
|
|
7048
|
+
});
|
|
7049
|
+
```
|
|
7050
|
+
|
|
7051
|
+
```xml
|
|
7052
|
+
<Extensions>
|
|
7053
|
+
<Extension Category="windows.activatableClass.inProcessServer">
|
|
7054
|
+
<InProcessServer>
|
|
7055
|
+
<Path>bind\Microsoft.Graphics.Canvas.dll</Path>
|
|
7056
|
+
<ActivatableClass ActivatableClassId="Microsoft.Graphics.Canvas.Effects.GaussianBlurEffect" ThreadingModel="both" />
|
|
7057
|
+
</InProcessServer>
|
|
7058
|
+
</Extension>
|
|
7059
|
+
</Extensions>
|
|
7060
|
+
```
|
|
7061
|
+
|
|
7062
|
+
- `classes` limits the list (an app that only blurs needs a few); by default it
|
|
7063
|
+
is every class the bindings activate by name (`win2dClassNames()`, which
|
|
7064
|
+
reads them from the bindings; `bindings` names another folder)
|
|
7065
|
+
- `libraryPath` is per architecture: an x64 and an arm64 package each have
|
|
7066
|
+
their own manifest, and the path is relative to the package root
|
|
7067
|
+
- Without the entries a packaged app writes one line to stderr that names this
|
|
7068
|
+
fragment, not one per class
|
|
7069
|
+
- `test/win2d-packaged.test.ts` proves it in a real registered package
|
|
7070
|
+
(`WINUI_SVELTE_PACKAGED_TEST=1`, `examples/win2d-packaged`): without the
|
|
7071
|
+
entries the canvas never draws and `0x80040154` is reported; with them it
|
|
7072
|
+
redraws and stderr is empty
|
|
7073
|
+
|
|
6213
7074
|
### Canvas 2D (`winui-svelte/win2d/context-2d`)
|
|
6214
7075
|
|
|
6215
7076
|
Opt-in, and a separate subpath: an app that imports only `winui-svelte/win2d`
|
|
@@ -6331,6 +7192,78 @@ The working example is `examples/win2d` (`test/win2d.test.ts` runs it in a real
|
|
|
6331
7192
|
window and checks the redraw; `src/win2d/win2d.test.ts` draws on a render
|
|
6332
7193
|
target and checks the pixels)
|
|
6333
7194
|
|
|
7195
|
+
## UI Automation client (`winui-svelte/automation`)
|
|
7196
|
+
|
|
7197
|
+
Read the exact text and headings of another window, instead of OCR; the
|
|
7198
|
+
counterpart of the Accessibility section, which provides automation to
|
|
7199
|
+
others, while this one consumes it; no web API reads another application's
|
|
7200
|
+
window, so this mirrors none; it is opt-in and bundles COM only when imported
|
|
7201
|
+
|
|
7202
|
+
```ts
|
|
7203
|
+
import { createUiaWorker } from "winui-svelte/automation";
|
|
7204
|
+
|
|
7205
|
+
const worker = createUiaWorker();
|
|
7206
|
+
const text = await worker.readText({
|
|
7207
|
+
target: "foreground",
|
|
7208
|
+
excludeProcessId: process.pid,
|
|
7209
|
+
hardMilliseconds: 1500
|
|
7210
|
+
});
|
|
7211
|
+
// { title, blocks: [{ kind: "heading", level: 1, text }, ...], version, end }
|
|
7212
|
+
```
|
|
7213
|
+
|
|
7214
|
+
`readText` runs in a worker thread in the multithreaded COM apartment; a target
|
|
7215
|
+
that hangs makes the call reject with `UiaTimeout` after `hardMilliseconds`,
|
|
7216
|
+
the worker is ended and the next call starts a new one (a blocked COM call
|
|
7217
|
+
cannot be cancelled); it resolves null when there is no window to read, the
|
|
7218
|
+
window is the excluded process's or an elevated one
|
|
7219
|
+
|
|
7220
|
+
For the lower level, `withUiaClient` gives a client on the calling thread
|
|
7221
|
+
(call it from a thread that joined a COM apartment) and releases every COM
|
|
7222
|
+
pointer it made when the callback ends:
|
|
7223
|
+
|
|
7224
|
+
```ts
|
|
7225
|
+
import { UiaControlType, withUiaClient } from "winui-svelte/automation";
|
|
7226
|
+
|
|
7227
|
+
const lines = await withUiaClient(client => {
|
|
7228
|
+
const root = client.elementFromHandle(hwnd);
|
|
7229
|
+
if (root === null) {
|
|
7230
|
+
return [];
|
|
7231
|
+
}
|
|
7232
|
+
|
|
7233
|
+
const found: string[] = [];
|
|
7234
|
+
const walk = client.walk({
|
|
7235
|
+
root,
|
|
7236
|
+
maxElements: 400,
|
|
7237
|
+
maxMilliseconds: 400,
|
|
7238
|
+
shouldVisit: ({ controlType, isOffscreen }) => !isOffscreen && controlType !== UiaControlType.button
|
|
7239
|
+
});
|
|
7240
|
+
for (const node of walk) {
|
|
7241
|
+
const ranges = node.pattern("text")?.visibleRanges() ?? [];
|
|
7242
|
+
found.push(...ranges.map(range => range.getText(1000)));
|
|
7243
|
+
}
|
|
7244
|
+
|
|
7245
|
+
return found;
|
|
7246
|
+
});
|
|
7247
|
+
```
|
|
7248
|
+
|
|
7249
|
+
| Call | What |
|
|
7250
|
+
|---|---|
|
|
7251
|
+
| `withUiaClient(use)` | creates `CUIAutomation`, runs `use(client)`, releases everything; an element used after that throws `UiaScopeEndedError` |
|
|
7252
|
+
| `client.elementFromHandle(hwnd)`, `client.focusedElement()` | an element, or null when it is gone or cannot be read |
|
|
7253
|
+
| `element.properties()` | `name`, `className`, `automationId`, `controlType`, `processId`, `isOffscreen`, `boundingRectangle`, `headingLevel` (0 for none, 1 to 9), `hasTextPattern`, `hasValuePattern` |
|
|
7254
|
+
| `client.walk({ root, maxElements, maxMilliseconds, shouldVisit })` | breadth first over the control view, one cached call per parent (`FindAllBuildCache`); `walk.end` is `complete`, `maxElements` or `deadline`; an element that went away is skipped; `node.skipSubtree()` prunes |
|
|
7255
|
+
| `element.pattern("text")` | `visibleRanges()`, `documentRange()`, and `range.getText(maxLength)` |
|
|
7256
|
+
| `element.pattern("value")` | `value` |
|
|
7257
|
+
| `readWindowText({ client, root })` | the headings and text of a window, skipping chrome and off screen elements (`UIA_CHROME_CONTROL_TYPES`); `version` changes when the text does |
|
|
7258
|
+
| `createUiaWorker()` | `readText({ target, excludeProcessId, hardMilliseconds, ... })` with the hard deadline; `close()` |
|
|
7259
|
+
| `UiaControlType`, `UiaPropertyId`, `UiaPatternName`, `HEADING_LEVEL_NONE`, `HEADING_LEVEL_FIRST` | the header's ids as `as const` sets and constants (the sets also under `winui-svelte/enums`) |
|
|
7260
|
+
| `UiaWalkEnd`, `TextBlockKind`, `UiaTarget` | the closed sets of a walk's end, a block's kind and a worker target (`foreground`, `focused`, or `{ hwnd }`) |
|
|
7261
|
+
| `UiaElementUnavailableError`, `UiaScopeEndedError`, `UiaTimeout` | the errors: an element went away, a client was used after its scope, a target did not answer in time |
|
|
7262
|
+
|
|
7263
|
+
Elements an app cannot read (elevated windows) come back as null, never an
|
|
7264
|
+
exception; browsers and Electron build their tree when the first client asks,
|
|
7265
|
+
so the first walk of such a window can be slower
|
|
7266
|
+
|
|
6334
7267
|
## Windows devices (`winui-svelte/devices`)
|
|
6335
7268
|
|
|
6336
7269
|
Windows' own device APIs (`Windows.Devices.*`, `Windows.System.Power`,
|