Skip to content

fix: preserve macOS window drag around annotation layers - #84

Draft
taekchef wants to merge 1 commit into
mainfrom
fix/macos-window-drag-81
Draft

taekchef wants to merge 1 commit into
mainfrom
fix/macos-window-drag-81

Conversation

@taekchef

@taekchef taekchef commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #81.

Cause

DSH dsh-v0.2.0-rc.2 marks every direct child of <body> outside #root as -webkit-app-region: no-drag. Both annotation layer shells currently fill the viewport, so their native no-drag rectangles cover host drag regions even with pointer-events: none.

Verified host source, following the issue investigation.

Change

  • Give both highlight and number shells a zero-size fixed box at the viewport origin, preserving visible overflow and their z-index stacking contexts.
  • Use viewport-pixel bounds for the clip polygon. Keeping the former 100% bounds on zero-size shells would collapse the clipping region and hide annotations.
  • Add a browser fixture using the macOS host selectors, with positive highlight visibility, number editing, header/composer/sidebar clipping, resize, scrolling, restore/delete and disposal coverage. Wire it into existing browser CI.
  • Add unit coverage for viewport clipping and resize.

No event-capture changes, version bump, release, or host-core modifications.

Verification

  • Passed locally: npm run check (build, syntax checks, 93 tests).
  • Passed locally: scripts/verify-pack.mjs with a writable npm cache; package contents checked.
  • Passed: browser-test syntax check, git diff --check, and independent static review.
  • CI passed on commit 686608b2bc2269817bad3e8b2387035cdcd174b5: Node 22/24 checks, historical/current Enter and IME integration, browser interaction regressions (including the new window-drag geometry test), package verification, and real DSH Web smoke.
  • Native macOS/Electron window movement, including dragging between monitors, remains unverified. Browser geometry tests do not prove native window movement.

Draft pending native macOS acceptance; all CI jobs are green.

@Fleta14

Fleta14 commented Oct 30, 2026

Copy link
Copy Markdown

Independent confirmation of the cause, plus a smaller alternative

Thanks for this — the diagnosis is correct. I hit the same symptom and independently confirmed the two layers are the cause on DSH desktop 0.2.1-rc.5 / macOS Apple Silicon with annotation 1.4.11:

data-annotation-overlay    510x820  display=block  no-drag
data-annotation-num-layer  510x820  display=block  no-drag

with every chrome row (topStrip, logoRow, conversation header) correctly carrying data-window-drag and computing to drag. Removing both layers restores dragging immediately.

A note on the keyword

This cost me a few rounds, so it may be worth knowing: -webkit-app-region: none is not a valid opt-out. Chromium parses the explicit none keyword as no-drag, so the layer keeps subtracting. Measured:

inline declaration getComputedStyle().webkitAppRegion
none no-drag (still subtracts)
initial none (leaves the composition)

The host already relies on this distinction for inert content in base.css:

html[data-platform='darwin'] [inert],
html[data-platform='darwin'] [inert] * {
  -webkit-app-region: initial;
}

so initial is the idiom the host itself uses to opt out.

Alternative that avoids touching clipWithHoles

Since the shells carry no geometry of their own — I checked, nothing reads getBoundingClientRect() / offsetWidth off overlay or numLayer, and every child (.dsh-ann-hl, .dsh-ann-num) is position: fixed with viewport coordinates — simply declaring the intent may be enough:

overlay.style.cssText  = 'position:fixed;inset:0;pointer-events:none;z-index:900;-webkit-app-region:initial;'
numLayer.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:1100;-webkit-app-region:initial;'

Because the box geometry stays untouched, the percentage outer ring in clipWithHoles() still resolves correctly and no change to the clip polygon is needed — the caveat raised in #81 (100% collapsing on a zero-size shell) does not arise.

Verified on my machine: with both layers still mounted, setting initial on them makes dragging work again (sidebar logo row and conversation header both move the window) and the plugin keeps working. No remove() involved.

Suggested next step

test/window-drag-browser.mjs from this PR asserts that the drag region is not eaten — that property is implementation-independent, so it should keep passing if the two cssText lines switch to initial while the clipWithHoles change is dropped. That would keep the coverage and shrink the diff by two hunks (the clip polygon rewrite and its unit test).

Entirely your call, of course — if the 0×0 shell is preferred for other reasons, this PR works as-is.

Evidence boundary

Measured: getComputedStyle results for both keywords, and drag behaviour before/after setting initial while the layers stay mounted. Static: the claim that nothing reads geometry off the two shells. I have not run this PR's browser fixture, and I have not re-verified native window movement across monitors.

@ysr666 ysr666 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Native macOS confirmation + a smaller alternative for #81

I reproduced this on the actual desktop shell (not only a browser fixture):

  • DSH desktop 0.2.1-rc.5, Electron 44.7.0, macOS 27.0 arm64
  • @changfenhuang/dsh-annotation 1.4.10
  • Live DOM: [data-annotation-overlay] is a direct child of <body>; with DevTools open its rect was 725×820, and its computed -webkit-app-region was no-drag. At the sidebar/header probe points it was the last app-region rectangle in DOM order, so it subtracted every [data-window-drag] rectangle below it.

A smaller rule fixes it natively without changing layer geometry or clip-path:

[data-annotation-overlay],
[data-annotation-num-layer],
[data-annotation-for-dsh] {
  -webkit-app-region: initial !important;
}

-webkit-app-region is not inherited, and the host's interactive-element no-drag rule still applies to buttons/inputs, so annotation clicks are unaffected. On the real DSH desktop this gave 3/3 native drags that moved the window exactly by the pointer delta:

  • (224,85) → (244,100) → (264,115) → (284,130), size stayed 1280×820
  • Without the rule, the same probe does not move the window.

The advantage over the zero-size shells is that the existing percentage-based clipWithHoles() and its pixel-conversion change are not needed; this also covers both 1.4.11 body layers plus the host in one place.

I also tried dropping the 1.4.11 client bundle from this PR into my 1.4.10 install on DSH 0.2.1-rc.5; the plugin entry failed to import in the web-boot log. That is likely a host/client-version mismatch in my test setup, not a judgment on this PR, so I am not claiming a clean full-DSH native run of #84. A minimal Electron 44.7.0 fixture with this PR's client bundle did show both shells at 0×0 and the 900×52 drag region moving the native window, so the geometry approach itself looks sound.

中文要点:真机 DSH 上实测,给三个 body 直属图层加 -webkit-app-region: initial !important 即可恢复拖拽;3/3 成功,且完全不动 DOM 几何与 clip-path。建议考虑把这条规则并进 #84,或作为更小的替代实现。

Happy to open a small PR against main with this rule plus a regression test if you prefer it over the zero-size shells; otherwise feel free to fold the rule into this PR.

@ysr666

ysr666 commented Oct 31, 2026

Copy link
Copy Markdown

One attribution correction to my review above: Fleta14 already proposed the -webkit-app-region: initial alternative earlier in this PR; I had not seen that comment when writing mine. My added value is the independent native DSH 3/3 drag verification and the CSS rule covering all three body-level layers ([data-annotation-overlay], [data-annotation-num-layer], [data-annotation-for-dsh]), not a claim of a new alternative.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document-wide pointer/selection capture breaks frameless window drag

3 participants