返回目录
其他 插件

dsh-top-drag

Mo3ter/dsh-top-drag

DSH Desktop (Windows): keeps the top of the window draggable and clickable at the same time.

Stars
0
Forks
0
Issues
0
更新
今天

PROJECT TOPICS

项目标签

INSTALL REFERENCE

安装参考

未验证
dsh plugin --profile web add github:Mo3ter/dsh-top-drag

该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。

PROJECT README

README

dsh-top-drag

DSH Desktop 客户端插件(仅 Windows):窗口顶部既能拖动、又不挡点击。

DSH Desktop client plugin (Windows only): keep the top of the window draggable and clickable at once.

这是 DSH Desktop 客户端专用插件 —— 它针对的是桌面端 preload 注入的那条窗口拖动条。 在 DSH Web / 命令行环境里它什么都不做(脚本会先判断平台,然后保持惰性)。

This is a DSH Desktop client plugin: it targets the drag overlay the desktop preload injects. In DSH Web or a CLI harness it stays inert.

中文说明

它修什么问题

DSH Desktop 在 Windows 下是自绘标题栏:窗口顶部 36 像素是一条窗口拖动条,而程序自己的顶部内容(会话标题行、子代理按钮、插件自己画在顶部的工具栏)就压在这条上。拖动条永远是最上层元素,点击先被它吃掉,所以:

  • 窗口最上方一片点不到
  • 会话标题 / 面包屑、子代理按钮点不到
  • 插件(例如记忆系统)在顶部画自己的界面时,按钮同样点不到
  • 给这些按钮加 -webkit-app-region: no-drag 也没用 —— 上面还盖着一层

它怎么做

把顶部这一条切成 16 个小格子,每格只看自己那一条竖条:

  • 那条里有可点元素(按钮、链接、输入框,以及带 role / tabindex / aria-label 的元素)→ 这一格让位,只留到元素上边缘(点击优先)
  • 那条里什么都没有 → 保留整条 36px(拖动优先)

app 的布局一个字都不改,插件也不需要任何配合;以后新装的插件在顶部画界面一样会被自动避让。弹出对话框时整条让位。

开销

按需测量,不轮询:鼠标进入顶部 44px 内、切换主面板、缩放窗口、手动触发 dsh-top-band-rescan 事件,外加 10 秒一次兜底。一次测量约 4 毫秒(一次元素查询 + 纯几何计算)。桌面端原有的蒙层保留作兜底,只有测量带成功跑起来才会隐藏它。

安装

  • 插件市场(收录后)一键安装
  • 从 GitHub:dsh plugin add github:Mo3ter/dsh-top-drag

调参lib/index.js 顶部的 COLUMNS / STRIP / SELECTOR / MIN_GAP_MS / SAFETY_TICK_MS


English

On Windows, DSH Desktop draws its own title bar: the window's top 36 px is a window-drag overlay and the session header sits underneath it. The overlay wins the hit test, so anything the app — or any plugin — draws there (session breadcrumbs, the subagent chip, a plugin's own toolbar) cannot be clicked. This plugin replaces the single overlay with a small measuring band: it yields exactly where UI needs clicks and keeps dragging everywhere else.

Windows only. On any other platform the plugin stays inert.

The problem it fixes

The desktop preload injects

#dsh-desktop-windows-drag-region
  position: fixed; top: 0; left: 0; right: calc(caption + 44px)
  height: 36px; -webkit-app-region: drag; z-index: 10

and pulls the app's own top content up into that strip (padding-top: 6px on the sidebar root and the conversation header), so the session header's title row starts at y = 6 — under the overlay. -webkit-app-region: no-drag on the buttons does not help: the overlay is the topmost element and wins the hit test. The same happens to any plugin that paints a toolbar or panel at the top of the window.

Narrowing the overlay fixes the clicks but makes the window impossible to grab; shaping it into a fixed handle turns that handle into a click dead zone. Both are the same mistake — drag area and content sharing one set of pixels.

How it works

  1. The layout is left exactly as shipped. No padding is added or removed.
  2. The band is split into 16 cells. Each cell looks at its own vertical slice of the top of the window:
    • something clickable in the slice → the cell collapses to just above it (clicks win),
    • nothing there → the cell keeps the full strip (drag wins).
  3. The preload's own overlay stays as the fallback and is hidden only once the band reports ready, so a broken script degrades to the shipped behaviour instead of losing window dragging.

"A clickable thing" is measured from real geometry: one querySelectorAll over button, a[href], input, select, textarea, summary, label, [role], [tabindex], [aria-label], [contenteditable], [data-dsh-no-drag], then a rect per candidate. No plugin has to opt in, and no per-surface patch is involved.

Cost

Measurement needs geometry, so it is on demand only — nothing polls:

trigger why
pointer within 44 px of the top the answer is fresh before a click or drag can land
main panel switch a plugin page usually brings its own top bar
window resize the columns move
window.dispatchEvent(new Event('dsh-top-band-rescan')) manual, from any button or script
one 10 s safety tick catches changes no pointer movement announces

A sweep over 385 candidates measures ~4 ms on a long session (one query ~1.5 ms, rects ~2.4 ms). Hit-testing per point was tried first and cost 245 µs per point — ~37 ms per sweep — which is why the band measures rects instead, and why MutationObserver is deliberately absent (it fires during chat streaming).

Install

  • Through the DSH plugin market, once listed.
  • From GitHub: dsh plugin add github:Mo3ter/dsh-top-drag
  • From npm: dsh plugin add dsh-top-drag
  • Locally from a checkout: dsh plugin add file:./dsh-top-drag

Harness restart required for a host-plane plugin; the DSH Desktop app picks it up on its next launch.

Configuration

Everything lives at the top of lib/index.js:

constant meaning
COLUMNS band cells (16)
STRIP band height in px (36)
PILL_* the small centred hint handle drawn when the middle column is free
MIN_GAP_MS minimum gap between two sweeps (700)
SAFETY_TICK_MS the safety tick (10000)

Caveats

  • Windows only, and it targets the desktop preload's own overlay id and the dsh-desktop-windows-titlebar-layout body class. If a future DSH Desktop version changes either, the plugin simply stays inert rather than breaking anything — it adds no padding and hides no element it did not measure.
  • Dialogs (dialog[open], [role=dialog], [aria-modal=true]) suppress the whole band, so a modal always keeps every click.
  • It adds no telemetry, no network access, and no client-side bundle: the whole plugin is one host file that contributes one <style> and one <script> row to the served index.html through webserver/index-inject.

Uninstall

dsh plugin remove dsh-top-drag, or remove the row from the profile's cordis.patch.yml. Nothing is written outside the profile.

License

MIT

CLASSIFICATION EVIDENCE

分类依据

项目类型插件
功能分类其他
规则置信度

系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。