feat(ohos): bridge plugin architecture + 3-round audit fixes + dead-code cleanup - #79
Draft
ljy9812 wants to merge 79 commits into
Draft
feat(ohos): bridge plugin architecture + 3-round audit fixes + dead-code cleanup#79ljy9812 wants to merge 79 commits into
ljy9812 wants to merge 79 commits into
Conversation
… version detection, autostart, and WebView transparency
This commit brings a comprehensive set of new features and improvements
to openharmony-ability, transforming it from a basic single-window
ability framework into a feature-rich platform for OpenHarmony/HarmonyOS
native applications.
74 files changed, ~8,500 lines added, ~875 lines removed.
New Features:
1. Menu System (crates/ability/src/menu/ — 6 new files, ~1,640 lines)
Complete menu system with menubar and context popup support:
- mod.rs: Channel-based architecture using crossbeam_channel for
bidirectional Rust (muda) <-> ArkTS communication. Background
forwarder thread dispatches via TSFN callback. Per-window menubar
visibility state in RwLock<HashMap>. Buffered menubar JSON per
window for late ArkTS callback registration.
- types.rs: MenuRequest/MenuRequestData (NAPI object), MenuItemData
(recursive submenu), AboutMetadataData, NAPI classes Menu,
MenuItem, Submenu.
- event.rs: MenuEvent struct with MenuEventDispatcher and global
GLOBAL_DISPATCHER (LazyLock<Mutex>).
- predefined.rs: PredefinedType enum (Copy, Cut, Paste, SelectAll,
Undo, Redo, Minimize, Maximize, Quit, etc.) with factory methods
and default accelerators (Ctrl+C, Ctrl+V, etc.).
- state.rs: MenuStateController NAPI class for create/append/destroy.
- popup.rs: MenuPopup NAPI class for context menu show/hide.
2. System Tray / StatusBar (crates/ability/src/statusbar/ — 5 new files, ~855 lines)
Full system tray integration:
- types.rs: StatusBarItem, StatusBarIcon (RGBA pixel data),
QuickOperation, StatusBarMenuItem/SubMenuItem, StatusBarMenuAction,
StatusBarClickEvent enum.
- event.rs: Dual crossbeam_channel pairs for icon click and menu
click events with register/unregister handlers.
- manager.rs: 6 TSFNs (Add, Remove, UpdateIcon, UpdateMenu,
UpdateTips, PredefinedAction) with thread-safe main-thread dispatch.
- validate.rs: Input validation (max 20 menu items, max 20 sub-items,
hover tips 1-128 chars, height > 0).
3. Clipboard (crates/ability/src/clipboard/mod.rs — 178 lines)
clipboard_write_image(rgba, width, height) async function writing
RGBA image data to system clipboard via TSFN bridge to ArkTS
writeImageToClipboard (Promise-based with 10-second timeout).
4. App Updater / AppGallery Integration (crates/ability/src/updater.rs + helper/updater.rs — ~420 lines)
- Updater::check() queries AppGallery for available updates, returns
CheckResult with version, body, and date.
- Updater::download_and_install() shows update dialog and drives
download+install flow.
- 3 TSFNs for check, show dialog, and download/install operations.
5. Version Detection (crates/ability/src/version.rs — 316 lines)
- sdk_api_version(): OpenHarmony base API Level (e.g., 12, 14, 20).
- distribution_api_version(): HarmonyOS distribution version
(M*10000 + S*100 + F).
- can_i_use(syscap): queries device system capabilities via ArkTS
canIUse().
- Includes device tests for worker thread safety.
6. Multi-Window Support (crates/ability/src/window/mod.rs — 200+ lines)
- create_os_window(name, window_type) creates OS-level sub-windows
with global atomic NEXT_WINDOW_ID for unique ID generation.
- Window decorations support (title bar, border, etc.).
- WindowManager with destroyWindow() for proper resource cleanup.
7. Float Window (native_ability/.../FloatPage.ets — 300 lines)
Floating window page component with drag and resize functionality
using createSubWindow API.
8. Autostart Support (crates/ability/src/autostart.rs + helper/autostart.rs — 412 lines)
- AutostartManager for managing app auto-start on device boot.
- TSFN bridge for ArkTS autostart registration/unregistration.
- Integration with HarmonyOS AbilityManagerService.
9. WebView Transparency (native_ability/.../DefaultWebview.ets — 71+ lines)
- Transparent background support for WebView.
- Window transparency synchronization.
- TransparencyTest demo page for validation.
Improvements & Refactoring:
App Enhancements (app.rs):
- restart(): hard process restart via TSFN with 3-second cooldown.
- set_color_mode(mode: ColorMode): dark/light/system theme switching.
- updater(): get updater handle for AppGallery integration.
- AbilityInitContext now includes sdk_api_version and
distribution_api_version.
- New NAPI export: is_desktop_device() for compile-time device type
detection.
Helper Infrastructure (helper/):
- Refactored from thread_local to global Mutex for HELPER storage,
enables cross-thread access via SendableHelper wrapper.
- New helper/restart.rs: restart TSFN with LazyLock<RwLock> pattern.
- New helper/updater.rs: three TSFN pairs for updater operations.
- New helper/autostart.rs: autostart TSFN management.
WebView Enhancements (webview/):
- window_id field on WebViewInitData and WebViewBuilder for per-window
webview creation.
- on_page_begin / on_page_end lifecycle callbacks.
- Fixed callback argument indexing (off-by-one in NAPI extraction).
- Added 'static bound to custom protocol callback closures.
- Fixed closure invocation to avoid holding lock during callback.
- Full URL matching for close-window intercept.
Lifecycle & Events:
- onWindowStageDestroy lifecycle hook.
- NewWant event support.
- runJavaScript error handling.
ArkTS Side (Native Layer — ~2,500+ lines, 18 new files):
- ArkHelper.ets (650+ lines): Full ArkHelper interface covering exit,
restart, updater, permissions, window, webview, statusbar, clipboard,
autostart.
- MenuBarComponent.ets (451 lines): Per-window menubar UI with click
handlers and keyboard accelerator support.
- FloatPage.ets (300 lines): Floating window page component.
- menu.ets (239 lines): MenuManager and PredefinedActionExecutor.
- WindowManager.ets (350+ lines): Multi-window management singleton
with proper destroyWindow() cleanup.
- StatusBarUtils.ets (182 lines): Status bar pixel map creation.
- accelerator_matcher.ets (142 lines): Keyboard shortcut matching.
- Utils.ets (140+ lines): JsHelper and ProxyJsHelper for deferred
webview init.
- updater.ets (115 lines): AppGallery updater using AppGalleryKit.
- predefined.ets (109 lines): Predefined menu action implementations.
- menu_state.ets (85 lines): Menu state management.
- MenuPopup.ets (80 lines): Context popup menu component.
- menu_types.ets (74 lines): Type definitions for menu system.
- autostart.ets (63 lines): Autostart registration helper.
- os.ets (37 lines): OS-level utility functions.
- ClipboardHelper.ets (33 lines): Clipboard write image implementation.
- TransparencyTest.ets (167 lines): Demo page for transparency testing.
Bug Fixes:
- fix(statusbar): re-register click handlers after addToStatusBar to
survive receiver rebuilds.
- fix(statusbar): prevent FloatPage from overwriting main window
helperRef.
- fix(ohos): tray icon click events — abilityName null check and
one-time on() guard, support relaunch.
- fix(tray): close/fullscreen behavior, menubar startup timing.
- fix(webview): callback argument off-by-one in NAPI extraction.
- fix(webview): closure lock held during callback (potential deadlock).
- fix(webview): use full URL for close-window intercept.
- fix(NativeAbility): duplicate onWindowStageDestroy method.
- fix(WindowManager): proper destroyWindow() cleanup on sub-window close.
- refactor: renamed TAURI_OHOS_DEVICE_TYPE to OHOS_DEVICE_TYPE for
framework-agnostic naming.
- docs: changed Chinese doc comments to English in helper/mod.rs.
Design Patterns:
- TSFN Bridge Pattern for safe ArkTS calls from Rust worker threads.
- Channel-based Event Distribution via crossbeam_channel.
- OnceLock/LazyLock for thread-safe lazy initialization.
- Per-Window State Maps (HashMap<String, bool>) for menubar state.
- Promise-to-Future Bridge via oneshot::channel + PromiseRaw + timeout.
Testing:
- Added device tests for the version module.
- Added TransparencyTest demo page for WebView transparency validation.
…dedWebBuilder Call ctrl.setCustomUserAgent(data.userAgent) in onControllerAttached callback when userAgent is provided. Enables OHOS WebView custom User-Agent via WebviewController API.
Round 1: - Extract shared DOMAIN constant into helper/constants.ets (10 files) - Use system icon for FloatPage close button - Replace eprintln! with crate::error! in xcomponent.rs and app.rs Round 2: - Add feature flags for modular compilation (statusbar, updater, version, window, clipboard, webview, menu) - Define cfg-gated crate::error!/info!/warn!/debug! macros replacing direct log::*/hilog_*! usage - Make log/hilog dependencies optional behind 'log' feature flag - Add cfg gates for version-dependent and module-dependent code paths Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix: address upstream PR harmony-contrib#63 review feedback and code quality cleanups
…-user-agent feat(webview): add setCustomUserAgent support in WebBuilder and EmbeddedWebBuilder
…ialog and code review fixes
feat(ohos): add window close lifecycle mechanism via NAPI queue
- Extend onNewWant ArkTS callback to extract and serialize want.parameters - Log parametersJson.length in NativeAbility for debugging - Define NewWantData interface in type.ets for type-safe parameter passing - Update NAPI bridge from Function<String> to Function<Object> - Add #[cfg(target_env = "ohos")] gate on WANT_PARAMETERS static and functions - Add static Mutex storage with store/take semantics and poison-safe error logging - Use ? for property extraction (consistent with other lifecycle callbacks) - Document concurrency contract: store on ArkTS main thread, take on tauri event loop - Update index.d.ts to match new onNewWant signature - Add single combined unit test for store/take/clear/overwrite (avoids parallel races)
feat(ohos): forward want.parameters through onNewWant event chain
- Add SnapshotData interface and JsHelper.webPageSnapshot method (ArkTS) - Implement webPageSnapshot with PixelMap to RGBA conversion and resource cleanup - Add Rust web_page_snapshot() callback API on Webview struct - Add unsafe impl Send for Webview (main thread only access)
feat(webview): add webPageSnapshot support for WebView content capture
- Restore PdfConfig struct with to_napi_map() for NAPI transport - Add scale field to PdfConfig (SDK PdfConfiguration.scale support) - Restore config parameter in ArkTS createPdf with merge logic - Update JsHelper/ProxyJsHelper interface to include config - Revert pdfArrayBuffer().buffer removal (Uint8Array -> ArrayBuffer) - Revert async fileIo.write back to fileIo.writeSync - Restore explanatory NAPI callback behavior comments
feat: add PdfConfig, createPdf NAPI + ArkTS implementation
- Add predefined menu actions: hide, close, minimize, showAll, bringAllToFront - Add clipboard ops (copy, cut, paste, selectAll, undo, redo) using target window webview - Align predefined menu actions with macOS Key Window semantics - Add MAIN_WINDOW_ID constant for main window identification - Centralize resetUserInteractionTracking in WindowManager wrapper methods - Add getPrimaryWebviewController for clipboard operations on primary webview - Fix FloatPage aboutToAppear async declaration - Remove Bug 6 references from comments
feat(menu): predefined multi-window clipboard ops and WindowManager fixes
…lper pending path fix, setBounds in controllers
feat(ohos): add WebViewStyle width/height, set_bounds NAPI, ProxyJsHelper pending path fix
Add Webview::set_cookie NAPI method and ArkTS setCookie (JsHelper interface, ProxyJsHelper pending-replay, DefaultWebview buildJsHelper) delegating to WebCookieManager.configCookieSync.
Add comprehensive mouse input handling for OHOS 2in1 desktop devices: - MouseEventData struct wrapping OH_NativeXComponent_MouseEvent FFI - MouseAction enum with Press/Release/Move/HoverEnter/HoverLeave variants - dispatch_mouse_event: NDK DispatchMouseEvent callback - dispatch_hover_event: NDK DispatchHoverEvent callback for cursor enter/leave - AxisEventData struct for scroll wheel delta (delta_x, delta_y) - dispatch_axis_event: ArkUI UIInputEvent AXIS callback for scroll wheel - register_mouse_callbacks: registers all three callbacks with NDK - InputEvent::MouseEvent and InputEvent::AxisEvent variants - Added ohos-xcomponent-sys and ohos-arkui-sys as direct dependencies Co-Authored-By: Claude <noreply@anthropic.com>
- Add InputSourceType enum (Mouse/TouchScreen/Touchpad/Joystick/Keyboard) - Add pinch_scale and source_type fields to AxisEventData - Extract pinch scale via OH_ArkUI_AxisEvent_GetPinchAxisScaleValue - Extract source type via OH_ArkUI_UIInputEvent_GetSourceType - Skip axis events with no scroll delta AND no pinch data Co-Authored-By: Claude <noreply@anthropic.com>
feat(ohos): add setCookie NAPI bridge for webview cookie management
OHOS NDK DispatchMouseEvent doesn't fire when cursor is over WebView, so we track cursor position from ArkTS onMouse events instead. - Add CURSOR_POSITION_X/Y atomic statics in app.rs - Add update_cursor_position() NAPI function for ArkTS to call - Add .onMouse() handler in MainPage.ets that calls NAPI on Move/Press - Export CURSOR_POSITION_X/Y for tao to read Co-Authored-By: Claude <noreply@anthropic.com>
Add a native ArkTS overlay for testing key repeat detection: - Floating '⌨ Key Test' button (bottom-right corner) - Focusable overlay panel with HashSet-based repeat tracking - .onKeyEvent() captures keys at ArkUI level (bypasses WebView) - ESC or ✕ to close overlay - repeat=true shown in green bold when key hold is detected Co-Authored-By: Claude <noreply@anthropic.com>
Add Webview::set_web_debugging_access(bool) and is_web_debugging_access() NAPI methods. ArkTS side (Utils.ets) tracks webDebuggingEnabled state (setWebDebuggingAccess const calls the static API first then updates the var; isWebDebuggingAccess returns the var). DefaultWebview.ets init routes through the const to keep state in sync. Uses domain socket (setWebDebuggingAccess(true), no port) — connect Chrome DevTools via examples/api/devtools.bat which auto-discovers the socket and forwards via hdc fport.
feat(ohos): add setWebDebuggingAccess NAPI bridge for devtools toggle
…ents feat(ohos): add mouse event, hover event, and scroll wheel support
…mer API - Forwarder thread + crossbeam channel + run_on_main_thread architecture - inputConsumer API (API 14+) for hotkey registration - 60+ key code mapping (Rust/ArkTS consistent) - Error code handling (801/4200002/4200003) - Duplicate modifier dedup, blocking send in unregister_all - Documented fire-and-forget design and synthetic Released event - SAFETY comments, dispatch_to_main_thread returns Result Co-Authored-By: Claude <noreply@anthropic.com>
feat(global_shortcut): add OHOS global shortcut bridge via inputConsumer API
- Phase 6/7: on_window_new Create + window focus NAPI bridge - Fix crash from napi_reference_unref on tokio worker threads: napi_ohos::Error's Drop calls napi_reference_unref which must run on main thread. Convert Error to String before sending through oneshot channels (clipboard, autostart, updater). Wrap ObjectRef in ManuallyDrop in thread-local cache.
feat(ohos): add window focus NAPI and fix napi_reference_unref crash
…on and plugin migrations - pluginize native bridge capabilities (harmony-contrib#67), normalize node surface (harmony-contrib#70), transparent XComponent background (harmony-contrib#73), webview controller release safety (harmony-contrib#69) - plugin module agnostic refactor (harmony-contrib#75), serialize ability plugin lifecycle (harmony-contrib#74) - account/updater bridge migration and clipboard write-html API - dead code cleanup superseded by the bridge plugin architecture - deps upgrade, format + git hook Co-Authored-By: Claude <noreply@anthropic.com>
…ableDrag, fix setPointerStyle C5 - instanceKey: 'specified launchType' mechanism doesn't exist (template is standard, SDK 12 has no abilityStage/onAcceptWant) — delete the whole passthrough (window/mod.rs want.set, ArkHelper.ets, type.ets field) and correct the type.ets comment back to launchType:standard - setWindowDraggable: enableDrag is API20+; add deviceInfo.sdkApiVersion < 20 guard (safeLogError + return) matching the startMoving/setWindowTopmost pattern - setPointerStyle: bare hilog in the NAPI-reentrant sync body throws 'Argc mismatch' (C5) — success log misreported failures, catch log swallowed the original err; switch to console fallback like safeLogError/getRealWindowId
feat(ohos): window ops bridge + status readback + FloatPage decorations
…on and plugin migrations - pluginize native bridge capabilities (harmony-contrib#67), normalize node surface (harmony-contrib#70), transparent XComponent background (harmony-contrib#73), webview controller release safety (harmony-contrib#69) - plugin module agnostic refactor (harmony-contrib#75), serialize ability plugin lifecycle (harmony-contrib#74) - account/updater bridge migration and clipboard write-html API - dead code cleanup superseded by the bridge plugin architecture - deps upgrade, format + git hook Co-Authored-By: Claude <noreply@anthropic.com>
Replace AppInner.window_rect (single shared field) with
window_rects: HashMap<i64, Rect> keyed by windowId (0 = main window,
>0 = Float sub-window via NEXT_WINDOW_ID). Add window_rect_for /
set_window_rect; release_render_owner clears only key 0.
ArkTS: wrap native window.RectChangeOptions / size-change options into
{ windowId, reason, rect } before invoking the Rust lifecycle closures
(NativeAbility.ets main window id=0, BridgeHost.ets component-window
second registration id=0). Float sub-windows never reach attachComponent
(DefaultXComponent early-returns), so register windowRectChange in
WindowManager.createSubWindow with callback injection
(registerRectChangeCallback) and off() cleanup in removeWindow.
Rust closures (lifecycle.rs) read windowId from the wrapped options and
store each rect under its own key; MainEvent::WindowResize and
ContentRect now carry window_id for tao event routing (Phase 3).
Part of openspec change p1-window-state-per-window-rect (Phase 2, D1-D5).
Co-Authored-By: Claude <noreply@anthropic.com>
…+trailing) openspec p2-mainthread-event-hygiene layer 2: high-frequency window operations (30+ subwindow create/destroy bursts) previously queued 12+ Immediate/Low events on the main thread and could trip the 6s watchdog even without lock contention. - WindowManager: per-windowId leading+trailing 16ms throttle for windowRectChange/windowSizeChange (rect and size have independent throttle state; leading keeps first-event immediacy, trailing guarantees final-state delivery — required for window-state cache freshness), WindowEntry.destroying flag drops events for windows being torn down, timer cleanup in removeWindow/unregisterUIAbilityStage - NativeAbility/BridgeHost: all four registration points routed through the same throttledRectDispatch; RECOVER→menubar restore stays synchronous (not throttled) - typed WindowSizeEventWrap/WindowRectEventWrap interfaces replace ESObject (arkts-limited-esobj WARN eliminated) Verified on device: THROTTLE 104 IN / 98 OUT (5.8% suppression, 0 failures), full suite 281 pass / 1 fail / 1 skip, zero new appfreeze. Co-Authored-By: Claude <noreply@anthropic.com>
Feature-gated behind `fault-injection` (zero overhead when off): - Rust wire types (FaultRuleWire etc.) + OpenHarmonyApp facade (set_fault_rule/clear_fault_rules, auto-enables the registry on first call) + call_fault_injection on the bridge client - ArkTS FaultInjection.ets: always compiled but short-circuits at match() when disabled — injects failures into bridge calls to light up error-handling branches that never run naturally Co-Authored-By: Claude <noreply@anthropic.com>
…ge ramp-up) Appended to existing test modules: expect_engine_phase / engine_scheme_pairs variants, plugin-window and mouse-event pure-transform cases — host-side inputs for branches that never occur naturally on device. Co-Authored-By: Claude <noreply@anthropic.com>
Rebase of upstream/ohdev (through a25848a) onto the pluginized local architecture; upstream features were built on the old ArkHelper TSFN framework, so they are ported semantically instead of textually: - window/mod.rs: cursor grab FFI (dlopen libnative_window_manager.so, OH_WindowManager_LockCursor/UnlockCursor) with set_cursor_grab taking the real OHOS window id directly - app.rs: notify_window_status NAPI + PENDING_WINDOW_STATUS queue, mirroring the notify_window_close drain pattern - WindowPlugin.ets: 7 new bridge actions — set-topmost, set-title, set-limits (delegate to ported WindowManager methods), request-user-attention (static notificationManager import, monotonic id, 1600004 enable-retry), set-ime-position (await updateCursor, result returned directly — no poll), set-draggable (API20 guard), get-real-window-id - plugin-window WindowClient: matching async facade methods - DefaultWebview: naturalLayout guard ported from upstream d530828 — explicit child webview bounds restored, natural-layout webviews keep 100% sizing and strip set_bounds width/height - windowCommand 'show': delegate to WindowManager.showWindowMethod so a minimized main window is restored instead of no-op showWindow() cargo check passes on host and aarch64-unknown-linux-ohos (0 errors). Co-Authored-By: Claude <noreply@anthropic.com>
…e actions Two facade actions tao needs beyond the PR#45 port set: - set-cursor-icon: delegates to WindowManager.setPointerStyle (resolves the real OHOS window id internally, pointer.setPointerStyleSync). Fire-and-forget — per-window failures are logged on the ArkTS side, the ack only confirms dispatch (tao's setter is void). - set-decoration-flags: applies the FLAG bit-field (closable=1, maximizable=2, minimizable=4, resizable=8) to a Float sub-window's LocalStorage; the UIAbility main window is a system-managed no-op. WindowClient gains the matching async methods; requests are validated windowId + integer style / flags in [0, 15]. Co-Authored-By: Claude <noreply@anthropic.com>
…e escape pack.bat invokes this script as "...pack-plugins.ps1" "%SCRIPT_DIR%"; the trailing backslash escapes the closing quote in cmd's parser, so arrives with a literal trailing quote. Join-Path bakes that quote into every derived path and Test-Path fails with ItemExistsArgumentError, aborting the whole pack at "plugin aggregation failed". Trim both quotes and backslashes from the incoming value. Co-Authored-By: Claude <noreply@anthropic.com>
…usChange The rebase-brought windowStatusChange registration in onWindowStageCreate referenced a bare 'windowId' identifier (upstream defines it via readWindowId() for multi-UIAbility; local single-UIAbility architecture has no such binding), failing ArkTS compilation. The main window is always tao windowId=0 (same sentinel as the surrounding WindowSizeEventWrap/WindowRectEventWrap wraps), and runtime-wry routes by tao window_id, so notify with the literal 0. Float sub-windows keep using the NEXT_WINDOW_ID(>=1) virtual id via FloatPage. Co-Authored-By: Claude <noreply@anthropic.com>
The WM rect (windowRectChange) and the XComponent surface rect update asynchronously; a live window_rect - content_rect diff read in the gap produced garbage decor estimates (824/770/292 instead of the real 146), which corrupted tao's inner_size reads and compounded through window-state save/restore into a shrinking main window. - latch decor height ONLY on surface events (activate/update), where both rects are consistent: diff==0 -> 0, 0<diff<=320 -> latch, otherwise keep the previous estimate - add decor_change_callbacks: listeners fired while the app write lock is held whenever the latched value actually changes (contract: lock-free listeners only — channel sends/atomics); returning false removes the listener after the call - expose register/remove_decor_change_callback for tao's event-driven set_inner_size self-correction - unit tests for the latch rules and the callback firing semantics Co-Authored-By: Claude <noreply@anthropic.com>
…en to WindowManager 1. Restore CURSOR_POSITION_X/Y atomics + update_cursor_position NAPI in app.rs (dropped during the pluginize refactor, restored from 5941dfb). The ArkTS MainPage.onMouse handler is the only viable cursor tracking source — the NDK DispatchMouseEvent path never fires while the cursor is over the WebView. tao's cursor_position() reads these atomics. 2. WindowPlugin.ets set-fullscreen: delegate to WindowManager.setFullscreen instead of the inline setWindowLayoutFullScreen mobile-only path the pluginize migration left behind. WindowManager implements the dual path (desktop/2in1: maximize(ENTER_IMMERSIVE) + setTitleAndDockHoverShown; mobile: setWindowLayoutFullScreen + setWindowSystemBarEnable with serializeOp race guard); the inline version was a visual no-op on desktop while still acking OK. Verified on HUAWEI MateBook Pro (2in1): cursorPosition() non-zero; fullscreen toggle enters (ENTER_IMMERSIVE) and exits (recover()). Co-Authored-By: Claude <noreply@anthropic.com>
Remote-only commit is the pre-rebase push of work that was replayed (and further refined) during the upstream-ohdev rebase; local content is authoritative (-s ours). See upstream-ohdev-rebase-window-ops.
…swap JsStatusbarManager builds its ScbServerMessageReceiver asynchronously (~14ms) after the sync addToStatusBar() call returns. Registering click handlers on the sync return binds them to the previous receiver, which the new receiver then replaces - rightMenuClick and statusBarIconClick listeners were silently dropped on re-add (set_title/set_visible/set_quick_operation all re-run add). Switch to the AsyncCallback overload (API 14+) and re-register in the completion callback, which runs strictly after the new receiver exists. The sync registration is kept as a baseline (harmless off+on) in case the callback never fires. Co-Authored-By: Claude <noreply@anthropic.com>
Predefined menu fullscreen (tray/menubar Fullscreen items) used an inline implementation that only did a bare immersive maximize on desktop - the system title bar / Dock stayed visible, diverging from WindowPlugin set-fullscreen. Delegate both 'fullscreen' and 'recover' predefined actions to WindowManager.setFullscreen so every entry point shares the dual-path (desktop maximize(ENTER_IMMERSIVE) + hide title bar/Dock hover, mobile layout fullscreen + hide system bars) and the serializeOp race guard. WindowManager.setFullscreen now also drives the Tauri menubar via MW-5 callbacks (macOS semantics, design.md D3): hide on entry, restore on exit. Previously only the predefined path hid the menubar, so the window-API Toggle Fullscreen button kept it visible - and Esc could not exit because the MainPage Esc handler is gated on menubar-invisible. Centralizing the callbacks makes Esc exit work for all fullscreen flavours through the existing condition. The Esc recoverFn (NativeAbility) delegates to setFullscreen(0, false) so the title bar / Dock hidden on entry are restored as well. Verified on device (MateBook Pro): button/tray/menubar fullscreen all hide system chrome + menubar; Esc and button toggle both restore. Co-Authored-By: Claude <noreply@anthropic.com>
Restores set_cursor_visible, which the bridge facade migration (tao 73212e1e) dropped to a no-op on the Rust side while the ArkTS WindowManager.setPointerVisible implementation survived. Adds the set-cursor-visible action to the WindowPlugin (delegating to WindowManager.setPointerVisible) and a CursorVisibleRequest facade method. The request carries no window id - pointer.setPointerVisible is process-wide (global vs window-level semantics documented as 遗留问题六). Verified on device (MateBook Pro): setCursorVisible(false) (3s) hides the pointer globally and restores it after 3s. Co-Authored-By: Claude <noreply@anthropic.com>
…store - createSubWindow: on API19+ use createSubWindowWithOptions with maximizeSupported:true — sub-window win.maximize() is rejected by WMS (1300004) unless maximize capability was declared at creation; decorEnabled:false keeps FloatPage's custom title bar - FloatPage un-maximize: use recoverWindow() (MAXIMIZE/FULL_SCREEN → FLOATING, the documented inverse of maximize) instead of restoreWindow() which is main-window-only Co-Authored-By: Claude <noreply@anthropic.com>
…g while maximized - WMS recover() re-anchors the floating rect to the pointer (GetFullScreenToFloatingRect), so programmatic restore landed the window near the cursor instead of its pre-maximize position. Snapshot the floating rect before maximize (preMaximizeRects, has-guard against double-maximize overwriting with the fullscreen rect) and moveTo() back after recover, on both the FloatPage button path and the WindowPlugin bridge path (shared snapshotPreMaximizeRect/restorePreMaximizeRect helpers; the bridge keeps its await-completion semantics and cannot delegate to the fire-and-forget maximizeWindow). - FloatPage title-bar onTouch(Down)->startMoving() also fires for child button touches (ArkUI touch bubbling); while maximized it triggered WMS drag-off-maximize at touch-down, moving the window away so the touch-up landed out of region and the click gesture was rejected — onClick never ran. Skip startMoving while maximized (drag-off restore sacrificed; restore via the button). Device-verified 2026-08-27: maximizeWindow 1 OK -> recoverWindow 1 OK (restored pre-maximize rect), window returns to its original position; bridge path verified via WMS rect chain [0,0]->[0,0,3120,1955]->[0,0,1140,760]. Co-Authored-By: Claude <noreply@anthropic.com>
Bridge-side counterpart to the wry https-scheme fix. The previous bridge migration dropped the create-time https_intercept_protocols field from WebviewCreateRequest, causing the ArkTS httpsInterceptProtocols Set to be empty at first loadUrl and onInterceptRequest to early-return null. - WebviewCreateRequest (lib.rs:385): add https_intercept_protocol_list: Option<Vec<String>>, populated by wry when use_https && protocols exist. - WebviewCreatePayload (WebviewPlugin.ets:148): add matching httpsInterceptProtocolList field; seed httpsInterceptProtocols Set at create (WebviewPlugin.ets:1625) so the Set is non-empty before loadUrl. - callbacks.rs / WebviewPlugin.ets: add full [bridge https-intercept] and [https-intercept] hilog chain (received/enter/extracted/reverted/calling/ returned/success/passthrough) for observability — the previous path was silent, masking the empty-Set early-return. - plugin-webview Cargo.toml: add log = "0.4" dependency (callbacks.rs/lib.rs use log::warn!/log::info! but the crate never declared log -> E0433). Verified 2026-08-28 on HUAWEI MateBook Pro desktop with the wry fix: all 4 https-scheme cases PASS (page-load/secure-context/subresource/external). Co-Authored-By: Claude <noreply@anthropic.com>
…t want.uri The file manager (com.huawei.hmos.filemanager MainAbility) reads the target from want.parameters.fileUri + want.parameters.external_storage_uuid, NOT from top-level want.uri. The previous code put the virtual uri in want.uri, which FM ignores -> FM defaulted to home (stayed on the homepage instead of navigating to the parent directory). This was the real root cause of §22-3 failing; the earlier "subPath empty" hypothesis was wrong (subPath-non-empty paths also stayed on home). Fix: move the mapped uri into parameters.fileUri and add external_storage_uuid = "LOCAL" (the local disk id, verified via FM diskNameArray; cloud = "cloud"). Device experiment (2026-08-28, aa start matrix): with parameters.fileUri + external_storage_uuid="LOCAL", FM does a two-stage setCurrentUri (myPC intermediate -> target uri) and navigates to Documents/Download/Desktop. In app semantics Rust takes path.parent() so reveal always opens the top-level public folder containing the file — this is within OHOS FM capabilities (the launch entry only resolves top-level virtual folder names; deeper subpaths hit isFolder error and fall back). Note: the 2026-08-20 "PASS" was a misread — FM actually stayed on the home/My Computer page; "empty uri when get uuid" is per-startup noise, not a URI rejection. Verified 2026-08-28 on HUAWEI MateBook Pro desktop: setCurrentUri reaches file://docs/storage/Users/currentUser/Documents (was: home). Co-Authored-By: Claude <noreply@anthropic.com>
ProcessInitializer.initialize() never set __native_module__ in AppStorage, so every AppStorage.get(NATIVE_MODULE_STORAGE_KEY) reader (FloatPage × button / aboutToDisappear, menu.ets closeWindow, NativeAbility windowStatusChange) returned undefined → notifyWindowClose / notifyWindowStatus were never invoked. On Float sub-window close, the Rust tauri manager kept a zombie entry → getByLabel returned a dead handle → same-label windows couldn't be rebuilt (manual_tests §二十八 close lifecycle defect). Fix: publish the primary native module to AppStorage at the end of ProcessInitializer.initialize(). One write fixes all readers. Verified on HUAWEI MateBook Pro (API 23): hilog shows "Window N close notified via NAPI" (was "not available"); windowId increments 1→2→3 on repeated create/close of the same-label overlay. Co-Authored-By: Claude <noreply@anthropic.com>
ArkWeb routes physical keyboard input through the IME pipeline: native DOM keydown/keyup are degenerate (empty key/code, no auto-repeat, fake D/U pair per repeat cycle). MainPage.onKeyPreIme receives clean continuous Down events with keyCode intact (~51ms interval) - the only viable synthesis mount point. - helper/key_synthesis.ets: keyCode->DOM mapping table, Set-method repeat detection (mirrors tao PRESSED_KEYS), modifier self-tracking, controller registry (executor pattern), synthesizeDomKeyEvent entry + KEY_SYNTHESIS_SHIM (window capture-phase stopImmediatePropagation, no preventDefault so IME text insertion is unaffected) - MainPage.onKeyPreIme: fall-through feeds synthesizer; consumed accelerators never leak into the page - WebviewPlugin: register controllers (incl. main window) via notifyKeySynthesisController; append shim to javaScriptOnDocumentStart for main window only (Float sub-windows lack onKeyPreIme wiring - injecting there would drop all key events). scriptRules = union of app init-script rules (empty array matches no document; '*' does not match tauri:// custom protocol - both observed on device) Verified on API 23 desktop: hold->continuous repeat=true with key/code, no grey native pairs, no text doubling; tap->repeat=false; accelerator interception consumes without leaking.
feat(webview): synthesize DOM key repeat events on OHOS (key-synthesis)
…ugins with lifecycle and window/webview/url fixes - New facade crates: plugin-accessibility, plugin-screenshot, plugin-continuation; ArkTS accessibility plugin; pack-plugins now aggregates 16 bridge plugins - app.rs: continuation snapshot store/take/peek APIs (pure Mutex, no bridge signalling) with unit tests; lifecycle wires optional isContinuation/parametersJson on onNewWant and onCreate - webview: create_pdf accepts WebviewPdfConfig layout (forwarded from wry); NewWindowDialog/WebviewPlugin window fixes - url: reveal-in-dir passes target via want.parameters.fileUri so the file manager navigates to the item - window: WindowPlugin fixes (pre-maximize rect recovery, focusable)
…se class The override must be (windowStage) => void without want/launchParam and non-async, otherwise the framework does not invoke it and cold-start continuation falls back to a blank window. Delegate to the full window-stage setup via a fire-and-forget call to onWindowStageCreate.
…n menubar StatusbarPlugin: answer remove/add only after the AsyncCallback settles, fixing the double-click race when replacing a tray icon. MenuBarComponent: extract nativeIconResource() with a sys.symbol.folder case and render top-level nativeIcon items as SymbolGlyph (previously top-level only rendered bitmap images, so mapped symbols were invisible). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tauri-ohos适配