Lazy Cursor
approvedby AQiong 阿琼
Forked from TimoBechtel/obsidian-lazy-cursor
Hides the cursor when opening a note until you tap/click the editor. Mobile supported. - This plugin has not been manually reviewed by Obsidian staff.
Lazy Cursor — 移动版
Source: agarcabin/obsidian-lazy-cursor · Releases
打开 Obsidian 笔记时,光标会自动失焦;点击编辑器后即可开始输入。
✨ 相比 cursor-goaway 的优势
| 对比维度 | Lazy Cursor(本插件) | cursor-goaway |
|---|---|---|
| 失焦策略 | 单次 rAF → blur(),结束 | 500ms rAF 循环(约 30 次 blur) |
| 打开后的 CPU 开销 | 零 — 一击即退 | 持续 500ms,每帧都在 blur |
| 键盘监听 | ❌ 无 | 注册全局 keydown(监听 ↓ 键) |
| 内存泄漏风险 | ❌ 无(无状态) | ⚠️ 需手动清理 handler |
| 内部 API 访问 | ❌ 无 | 访问 editor.cm(CodeMirror 内部属性) |
| 恢复光标方式 | 点击编辑器任意位置 | 按 ↓ 键(移动端不可用) |
| 移动端支持 | ✅ 原生支持 | ❌ 移动端无 ↓ 键 |
| 文件过滤 | 所有文件(零配置) | 仅 .md 文件 |
| CSS 文件 | ❌ 无 | 附带空 styles.css |
| 逻辑代码量 | ~6 行 | ~50 行 |
一句话总结 — 一帧、一次 blur()、零持续开销;不监听键盘,也不依赖 CodeMirror 内部 API。
🔧 工作原理
file-open → requestAnimationFrame → editor.blur()
(一次性触发,零持续监听)
- 监听 Obsidian 的
file-open工作区事件。 requestAnimationFrame等待 WebView/DOM 完成渲染,这对移动端的异步布局尤其重要。- 执行完单次
blur()后插件进入空闲,直到下次打开文件。
🆚 相比原版 (TimoBechtel) 的改动
| 改动 | 原因 |
|---|---|
isDesktopOnly: false | 移动端 Obsidian 使用相同 API,无理由禁用。 |
requestAnimationFrame 包裹 | 移动端 WebView 编辑器可能尚未同步挂载,rAF 确保 DOM 就绪。 |
// manifest.json
- "isDesktopOnly": true
+ "isDesktopOnly": false
// main.js — file-open 处理
- editor.blur();
+ requestAnimationFrame(() => editor.blur());
📦 安装
手动安装
- 下载
main.js和manifest.json。 - 放入
<vault>/.obsidian/plugins/lazy-cursor/。 - 在设置 → 第三方插件中启用 Lazy Cursor。
Release 下载包含独立的 main.js 和 manifest.json,不需要下载 ZIP 压缩包。
从源码构建
npm ci
npm run build
npm run verify
仓库中的 main.ts 是源代码。生成的 main.js 由 Git 忽略,并作为独立资产附加到 GitHub Release。
📄 许可证
MIT License
版权所有 (c) 2023 Timo Bechtel 版权所有 (c) 2025 Reasonix
Lazy Cursor — Mobile Edition
Source: agarcabin/obsidian-lazy-cursor · Releases
When you open a note in Obsidian, the cursor is automatically blurred. Tap or click the editor to start typing.
✨ Why this over cursor-goaway?
| Aspect | Lazy Cursor (this) | cursor-goaway |
|---|---|---|
| Blur strategy | Single rAF → blur(), done | 500ms rAF loop (~30 blur() calls) |
| CPU cost after open | Zero — fires once, exits | Non-zero — 500ms of per-frame blur spam |
| Key listener | ❌ None | Registers global keydown (ArrowDown) |
| Memory leak risk | ❌ None (no state) | ⚠️ Manual handler cleanup required |
| Internal API access | ❌ None | Accesses editor.cm (CodeMirror internal) |
| Restore cursor | Tap/click anywhere | Press ↓ key (not intuitive on mobile) |
| Mobile support | ✅ Native | ❌ ArrowDown key not available on mobile |
| File filter | All files (zero-config) | .md only |
| CSS file | ❌ None | Ships empty styles.css |
| Code size (logic) | ~6 lines | ~50 lines |
TL;DR — Lazy Cursor does the same job with zero ongoing cost: one frame, one blur, done. No key listeners. No 500ms loop. No CodeMirror internals. Mobile-first.
🔧 How it works
file-open → requestAnimationFrame → editor.blur()
(one-shot, zero persistent listeners)
- Hooks Obsidian's
file-openworkspace event. requestAnimationFramewaits for the WebView / DOM to finish painting — critical on mobile where layout is asynchronous.- After that single
blur(), the plugin is idle until the next file-open.
🆚 Changes from the original (TimoBechtel)
| Change | Why |
|---|---|
isDesktopOnly: false | Mobile Obsidian uses the same API — no reason to block it. |
requestAnimationFrame wrapper | Mobile WebView may not have the editor mounted synchronously; rAF guarantees the DOM is ready. |
// manifest.json
- "isDesktopOnly": true
+ "isDesktopOnly": false
// main.js — file-open handler
- editor.blur();
+ requestAnimationFrame(() => editor.blur());
📦 Install
Manual
- Download
main.jsandmanifest.json. - Place them in
<vault>/.obsidian/plugins/lazy-cursor/. - Enable Lazy Cursor in Settings → Community plugins.
Release downloads contain main.js and manifest.json as separate assets. Do not download a ZIP archive; Obsidian does not install arbitrary extra release files.
Build from source
npm ci
npm run build
npm run verify
The repository contains main.ts as the source. The generated main.js is ignored by Git and is attached directly to each GitHub Release.
📄 License
MIT License
Copyright (c) 2023 Timo Bechtel Copyright (c) 2025 Reasonix
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.