dsh-mini 0.1.5 → 0.1.6
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/README.md +20 -11
- package/app/SelectionWatcher.cs +24 -10
- package/app/Service.cs +1 -1
- package/app/bin/DSH/345/260/217/347/252/227.exe +0 -0
- package/lib/client.js +2 -2
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -179,12 +179,17 @@ cd app
|
|
|
179
179
|
|
|
180
180
|
* 实现在 `app/SelectionWatcher.cs`:全局鼠标轮询(90ms)→ 松开时若拖动距离 ≥6 逻辑像素、
|
|
181
181
|
且不在小窗/药丸自己身上 → 后台线程等 130ms(双击选词等 320ms)→ 校验仍在前台 → 取选区。
|
|
182
|
-
*
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
182
|
+
* **取选区三级阶梯**(`SelectionReader.ReadHit`),从最无侵入的一档开始:
|
|
183
|
+
1. **UI Automation**(`TextPattern`)—— 不碰键盘、不碰剪贴板,还能拿到选区最后一行/一个字的矩形,
|
|
184
|
+
药丸因此能精确贴在它右下角。Notepad、Word、WPS、VS Code、WinForms/WPF、DSH 自己都走这一档。
|
|
185
|
+
2. **`WM_COPY`** —— 发给焦点控件,不发按键。部分老式编辑框只认这条。
|
|
186
|
+
3. **合成一次 `Ctrl+C`** —— 只有前两档都拿不到时才用。**浏览器正文(Chromium)、部分 Electron 应用、
|
|
187
|
+
某些游戏/自绘控件根本没有 `TextPattern` 也没有 `WM_COPY`,这是唯一可行的手段**。
|
|
188
|
+
* **绝不做「备份剪贴板 → 复制 → 还原」**。之前那套是"选中后复制不上"的元凶:还原那一步会把你刚按的
|
|
189
|
+
`Ctrl+C` 覆盖回旧内容。现在第三档会**把选区留在剪贴板里**(你在浏览器里划一下就发现 `Ctrl+V` 有内容了),
|
|
190
|
+
代价是<u>占用</u>剪贴板,而不是<u>破坏</u>它 —— 这是读取 Chromium 选区的唯一代价,取舍写在明处。
|
|
191
|
+
* 设置页的「选区读取:辅助功能读不到时改用复制」**默认打开**;关掉后浏览器正文里就不会再弹按钮,
|
|
192
|
+
但剪贴板绝对不会被碰(适合只用 Office/记事本、或对剪贴板敏感的场景)。
|
|
188
193
|
* 保护:按住 Ctrl/Alt/Shift 时的拖动直接跳过(那是复制/扩选,不是重新选词);终端
|
|
189
194
|
(console/cascadia/mintty/putty)不发按键;资源管理器/桌面/任务栏(Progman/WorkerW/CabinetWClass…)
|
|
190
195
|
一律跳过(否则会真的复制文件、污染 `Win+V` 历史);用户按着修饰键期间完全不介入。
|
|
@@ -192,8 +197,9 @@ cd app
|
|
|
192
197
|
`%LOCALAPPDATA%\dsh-hud\ask.txt`。
|
|
193
198
|
* 因此**标题条 ✕ 只是收进托盘**(不是退出)——watcher 活在这个进程里,退出了就没法划词。
|
|
194
199
|
彻底退出用托盘菜单「退出」。
|
|
195
|
-
* 诊断:`hud.log` 里 `[pill]` 开头的行会写每次 `kick / skip / read N chars
|
|
196
|
-
|
|
200
|
+
* 诊断:`hud.log` 里 `[pill]` 开头的行会写每次 `kick / skip / read N chars`,以及实际走了哪一档:
|
|
201
|
+
`copy: wm_copy N chars`、`copy: key_chord N chars seq A->B`(`0 chars` 且序号没动,说明那儿没有真选中
|
|
202
|
+
或目标程序忽略了合成按键);往 `%LOCALAPPDATA%\dsh-hud\seltest.txt` 写任意内容可触发一次「只读不弹」的自检。
|
|
197
203
|
|
|
198
204
|
## 常驻划词服务、全局快捷键与设置页
|
|
199
205
|
|
|
@@ -261,9 +267,12 @@ cd ..; npm pack # → dsh-mini-0.1.0.tgz(约 600 KB)
|
|
|
261
267
|
* 截图只有「整屏」和「框选/吸附窗口」两种,没有滚动长截图;框选吸附依赖窗口标题非空,
|
|
262
268
|
无标题窗口(部分全屏游戏、自绘界面)会退化成「该点所在的整块屏幕」。
|
|
263
269
|
(滚动长截图评估过:要拼接滚动帧 + 去重 + 处理懒加载,工作量明显大于本轮其它几项,先没做。)
|
|
264
|
-
*
|
|
265
|
-
|
|
266
|
-
|
|
270
|
+
* 划词按三级阶梯取选区:UIA `TextPattern`(无侵入、带选区矩形)→ `WM_COPY`(发消息、不发按键)→
|
|
271
|
+
合成一次 `Ctrl+C`。**Chromium 正文没有 `TextPattern`、也不响应 `WM_COPY`**(我实测过 UIA 与
|
|
272
|
+
IAccessible2 两条路都拿不到选区),所以浏览器里必然走到第三档,会占用剪贴板;不想被碰可在设置页关掉
|
|
273
|
+
「选区读取:辅助功能读不到时改用复制」。终端(console/cascadia/mintty/putty)和桌面/资源管理器窗口
|
|
274
|
+
直接跳过,避免 Ctrl+C 变成 SIGINT 或真的复制文件。**任何情况都不再还原旧剪贴板内容**——那正是以前
|
|
275
|
+
「选中后 Ctrl+C 复制不上」的根因。
|
|
267
276
|
* 主题色与小窗边框:导航完成后同步两次,另外每 6 秒复查一次页面背景色;
|
|
268
277
|
跨显示器拖到不同 DPI 的屏会收到 `WM_DPICHANGED` 并重算标题条/图标/最小尺寸。
|
|
269
278
|
* 标题条图标是 `Segoe MDL2 Assets` 字体,字号偏小(E8BB 关闭键取 8.5f 才和其它图标一样大)。
|
package/app/SelectionWatcher.cs
CHANGED
|
@@ -318,12 +318,17 @@ namespace DshHud
|
|
|
318
318
|
internal static class SelectionReader
|
|
319
319
|
{
|
|
320
320
|
/// <summary>
|
|
321
|
-
///
|
|
322
|
-
///
|
|
323
|
-
///
|
|
324
|
-
/// the
|
|
321
|
+
/// On by default, but only ever consulted after UIA came back empty — so modern text
|
|
322
|
+
/// surfaces (Notepad, WinForms, WPF, Office, the browser's own chrome) never touch the
|
|
323
|
+
/// clipboard. Chromium content and legacy controls expose no TextPattern at all, and for
|
|
324
|
+
/// those a copy is the only way to read the selection.
|
|
325
|
+
///
|
|
326
|
+
/// Crucially the copy is *not* undone: the old implementation restored the previous
|
|
327
|
+
/// clipboard contents afterwards, and that restore raced the user's own Ctrl+C and
|
|
328
|
+
/// overwrote what they had just copied. Losing the previous clipboard contents is the
|
|
329
|
+
/// price of reading a selection here; breaking Ctrl+C is not.
|
|
325
330
|
/// </summary>
|
|
326
|
-
internal static bool ClipboardFallback;
|
|
331
|
+
internal static bool ClipboardFallback = true;
|
|
327
332
|
|
|
328
333
|
/// <summary>
|
|
329
334
|
/// Read the current selection. UIA first: it is passive (no keystrokes, no clipboard
|
|
@@ -453,14 +458,21 @@ namespace DshHud
|
|
|
453
458
|
if (ShellWin.IsModifierDown()) return "";
|
|
454
459
|
|
|
455
460
|
uint seq = ShellWin.GetClipboardSequenceNumber();
|
|
456
|
-
|
|
457
|
-
|
|
461
|
+
// WM_COPY is best effort only: Win32 edits answer it, Chromium and most
|
|
462
|
+
// modern renderers ignore it, and SendMessageTimeout also returns false
|
|
463
|
+
// when the target window is busy. Never treat "no answer" as "no selection".
|
|
464
|
+
ShellWin.SendCopyMessage();
|
|
458
465
|
|
|
459
466
|
string text = WaitForClipboardText(seq, 320);
|
|
460
|
-
if (!string.IsNullOrEmpty(text))
|
|
467
|
+
if (!string.IsNullOrEmpty(text))
|
|
468
|
+
{
|
|
469
|
+
SelectionWatcher.Log("copy: wm_copy " + text.Length + " chars");
|
|
470
|
+
return Finish(text);
|
|
471
|
+
}
|
|
461
472
|
|
|
462
|
-
//
|
|
463
|
-
//
|
|
473
|
+
// A real key chord is the only thing that works for Chromium content and
|
|
474
|
+
// legacy controls. Only when the user has opted in, and never while they
|
|
475
|
+
// are holding a modifier themselves.
|
|
464
476
|
if (!ClipboardFallback || ShellWin.IsModifierDown()) return "";
|
|
465
477
|
try
|
|
466
478
|
{
|
|
@@ -471,6 +483,8 @@ namespace DshHud
|
|
|
471
483
|
return "";
|
|
472
484
|
}
|
|
473
485
|
text = WaitForClipboardText(seq, 700);
|
|
486
|
+
SelectionWatcher.Log("copy: key_chord " + (text == null ? 0 : text.Length) +
|
|
487
|
+
" chars seq " + seq + "->" + ShellWin.GetClipboardSequenceNumber());
|
|
474
488
|
return string.IsNullOrEmpty(text) ? "" : Finish(text);
|
|
475
489
|
}
|
|
476
490
|
|
package/app/Service.cs
CHANGED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -551,8 +551,8 @@ window.__ModuleLoader__.load({
|
|
|
551
551
|
react.createElement('h3', { style: { fontSize: '14px', margin: '0 0 4px' } }, '小窗与截图'),
|
|
552
552
|
react.createElement('p', { style: hintStyle }, '设置对原生小窗和后台划词服务同时生效,保存后约 3 秒内应用。'),
|
|
553
553
|
checkbox('copyShot', '截图自动复制到剪贴板', '全屏、框选两种截图都会复制'),
|
|
554
|
-
checkbox('textFallback', '
|
|
555
|
-
'
|
|
554
|
+
checkbox('textFallback', '选区读取:辅助功能读不到时改用复制',
|
|
555
|
+
'默认打开。先走系统辅助功能(不发按键、不碰剪贴板);浏览器正文、老控件没有这个接口,只能复制一次来读选区 —— 会占用剪贴板,但不会再还原,所以不会覆盖你刚按的 Ctrl+C。关掉后这些地方就不出按钮。'),
|
|
556
556
|
hotkey('hotkeyFull', '全屏截图快捷键'),
|
|
557
557
|
hotkey('hotkeyRegion', '框选截图快捷键'),
|
|
558
558
|
react.createElement('p', { style: hintStyle }, '写法:Ctrl+Shift+1、Ctrl+Shift+S、Alt+PrintScreen、F8 等。组合里必须带 Ctrl/Alt/Shift/Win 之一。'),
|
package/lib/index.js
CHANGED
|
@@ -202,7 +202,7 @@ function advertise(ctx) {
|
|
|
202
202
|
|
|
203
203
|
const CONFIG_PATH = join(WORK_DIR, 'config.ini')
|
|
204
204
|
|
|
205
|
-
const CONFIG_DEFAULTS = { copyShot: true, ask: true, textFallback:
|
|
205
|
+
const CONFIG_DEFAULTS = { copyShot: true, ask: true, textFallback: true, hotkeyFull: 'Ctrl+Shift+1', hotkeyRegion: 'Ctrl+Shift+2' }
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
208
|
* Settings live in a flat `key=value` file because the window shell (C# 5) and this
|