From df1810bae3e60a7e54f9f78b81248ccf4931c5d0 Mon Sep 17 00:00:00 2001 From: Frank Levine Date: Sun, 27 Sep 2026 13:49:12 -0400 Subject: [PATCH] Add mac-cursor-ring.lua: show the Mac pointer in the VNC mirror macOS leaves the pointer out of the Screen Sharing framebuffer, and neither Remmina showcursor setting brings it back. A Hammerspoon ring around the pointer is a real window, so it gets mirrored. Co-Authored-By: Claude Opus 5.5 --- scripts/mac-cursor-ring.lua | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 scripts/mac-cursor-ring.lua diff --git a/scripts/mac-cursor-ring.lua b/scripts/mac-cursor-ring.lua new file mode 100644 index 0000000..edcfe20 --- /dev/null +++ b/scripts/mac-cursor-ring.lua @@ -0,0 +1,40 @@ +-- Hammerspoon: draw a ring around the Mac pointer so it shows in the VNC +-- mirror on the Frame. macOS Screen Sharing leaves the pointer out of the +-- framebuffer; a real on-screen window is captured like anything else. +-- +-- Install: brew install --cask hammerspoon, then in ~/.hammerspoon/init.lua: +-- dofile("/path/to/frame-control/scripts/mac-cursor-ring.lua") +-- Toggle: ctrl+alt+cmd+M. Polls the pointer position, so no Accessibility +-- permission is needed. + +local SIZE, WIDTH = 34, 3 +local COLOR = { red = 1, green = 0.2, blue = 0.2, alpha = 0.9 } + +local ring = hs.canvas.new({ x = 0, y = 0, w = SIZE, h = SIZE }) +ring:appendElements({ + type = "circle", action = "stroke", + strokeColor = COLOR, strokeWidth = WIDTH, + radius = (SIZE - WIDTH) / 2, +}) +ring:level(hs.canvas.windowLevels.cursor) +ring:behavior({ "canJoinAllSpaces", "stationary", "ignoresCycle" }) + +local last = {} +local function follow() + local p = hs.mouse.absolutePosition() + if p.x ~= last.x or p.y ~= last.y then + ring:topLeft({ x = p.x - SIZE / 2, y = p.y - SIZE / 2 }) + last = p + end +end + +frameCursorRing = { canvas = ring, timer = hs.timer.new(1 / 60, follow) } + +local function show() follow(); ring:show(); frameCursorRing.timer:start() end +local function hide() frameCursorRing.timer:stop(); ring:hide() end + +hs.hotkey.bind({ "ctrl", "alt", "cmd" }, "M", function() + if ring:isShowing() then hide() else show() end +end) + +show()