diff --git a/index.html b/index.html index 26eb8b6..fcb9073 100644 --- a/index.html +++ b/index.html @@ -9,9 +9,9 @@
-
+
-
+
untitled.md
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8c2d1c9..d74a012 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -31,4 +31,3 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" tauri-plugin-deep-link = "2.4.6" url = "2.5.8" - diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index d44f1ad..9d2896c 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -9,6 +9,7 @@ "core:window:allow-destroy", "core:window:allow-set-title", "core:window:allow-set-focus", + "core:window:allow-set-position", "opener:default", "dialog:default", "fs:default", diff --git a/src/main.ts b/src/main.ts index 438abf3..f06ff9c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,7 @@ import type { Editor } from '@tiptap/core' import { TextSelection } from '@tiptap/pm/state' +import { LogicalPosition } from '@tauri-apps/api/dpi' +import { getCurrentWindow } from '@tauri-apps/api/window' import { createQuillEditor, ensureGrammarsForDoc, getMarkdown, setMarkdown } from './editor-setup' import { FileOps } from './file-ops' import { selectStartupFiles } from './startup-files' @@ -86,6 +88,37 @@ document.addEventListener('DOMContentLoaded', async () => { const modifiedIndicator = document.getElementById('modified-indicator')! const wordCountEl = document.getElementById('word-count')! const editorEl = document.getElementById('editor')! + const titlebarEl = document.getElementById('titlebar')! + + // macOS 27 can reject AppKit's performWindowDragWithEvent for an overlay + // titlebar. Move only this header by cursor delta instead; the editor never + // receives this listener, so text selection and its own drag/drop are intact. + titlebarEl.addEventListener('mousedown', async event => { + if (event.button !== 0) return + event.preventDefault() + + try { + const win = getCurrentWindow() + const [position, scale] = await Promise.all([win.outerPosition(), win.scaleFactor()]) + const startX = event.screenX + const startY = event.screenY + + const move = (moveEvent: MouseEvent) => { + const x = position.x / scale + moveEvent.screenX - startX + const y = position.y / scale + moveEvent.screenY - startY + void win.setPosition(new LogicalPosition(x, y)) + } + const stop = () => { + window.removeEventListener('mousemove', move) + window.removeEventListener('mouseup', stop) + } + + window.addEventListener('mousemove', move) + window.addEventListener('mouseup', stop, { once: true }) + } catch { + // Browser-based harness: no native window. + } + }) // --- editor --- let fileOps: FileOps diff --git a/src/styles.css b/src/styles.css index dd8fa6b..2291ea5 100644 --- a/src/styles.css +++ b/src/styles.css @@ -84,7 +84,6 @@ button { background: var(--bg-primary); user-select: none; -webkit-user-select: none; - -webkit-app-region: drag; flex-shrink: 0; }