The Holy Grail of Cursor Ergonomics

By Anton Pyrogovskyi10 minutes read

Table of Contents

For as long as I can remember, I’ve been paying attention to ergonomics. I’ve had to – the wrist of my mouse hand has always been prone to RSI. Over the years I’ve tried:

All of these helped in some way, but none of them truly solved the problem.

Mechanical devices, however ergonomic, still require sustained small, precise movements. The RSI changes clothes but the Cramp Hand of Dread is never really gone. Depending on the shape of the device it may also bend the wrist or fingers away from the neutral stance, perhaps in novel directions that non-“ergonomic” devices do not.

For example, pressing and holding something with a bent finger tires my hands very quickly. This has never been a problem during actual physical work but cursor control devices, whether they claim to be ergonomic or not, tend to assume you like this motion, which otherwise seems to be uncommon in nature – I’d love to be corrected if I’m wrong!

Head or eye tracking works to get rid of physical stress completely. However it’s slow, awkward and requires a camera to be on at all times. It breaks up the flow state that is possible otherwise. It also ruins screen sharing in a video call somewhat. In short, immersion killer.

As often happens, my current Holy Grail of Cursor Ergonomics was found by accident.

Why I Switched to Sidecar Apple Pencil

Now this was something promising: using an iPad with Apple Pencil in Sidecar mode, mirroring the screen of the iMac. This makes it possible to work without wrist pain.

Here’s why this setup works so well:

Holding a pencil is much more natural than gripping a mouse as one does not need to flex or tense the wrist nearly as much. It also allows you to use the bigger muscles of the arm for positioning as opposed to being limited to the fine muscles of the hand. While there is still non-zero physical effort to move the cursor where you need it before clicking, it is almost effortless in comparison as you do not have to tense any hand muscles or wrist ligaments to do that – just move the arm.

If you can use a pencil, you can use an Apple Pencil. I don’t know if that’s the official tagline but maybe it should be. Pretty much anyone can hold a pencil, pen, brush, chalk or marker in a way that is most comfortable for them specifically, right? Decades of research in human-interface devices have not yielded anything that would be better than a pointy stick at pointing. There must be a biomechanical reason why this is the most obvious and natural shape for tools that we use for real-life, physical, meatspace “pointing”.

The Pencil can be held in many different ways, which keeps the wrist from locking into one posture and becoming stiff and tired. The rest position can also be basically anything that is comfortable for you personally. It is possible to type on the keyboard without putting the Pencil down (YMMV). It is also possible to put it down pretty much anywhere comfortably as opposed to a heavier or bigger device. And in fact, it does not require classical gripping to work at all as you can support it between the fingers in resting position.

When the iPad is lying flat, dragging becomes near-effortless. Just drop and lift the Pencil; gravity does most of the work supporting it in contact with the screen. Since time under tension is one of the biggest contributors to RSI, it makes a huge difference. With pointer devices, a click-drag gesture usually requires constant tension of the fingers until you end the drag gesture. Not so with the Pencil where this tension is provided by gravity.

While not a factor for me, this is another nice thing about this input method in general – it’s completely symmetrical so it’s equally suitable (or unsuitable) for people with any handedness. It would also be possible to use it completely hands-free by holding the Pencil using your toes, mouth etc in the context of accessibility.

It still wasn’t perfect, though.

The Problems

Using the Apple Pencil this way exposes a few big flaws:

When you tap the Pencil, macOS often generates a click-drag instead of a click. Native apps have a certain tolerance to that – I am assuming for accessibility reasons – but many 3rd party apps, most notably ChatGPT, take it on face value and assume you wanted to drag-and-drop something when you just pencil-tap it once. The result: buttons feel sticky, misclicks are common and actions need to be repeated.

In ChatGPT, this will cause trying to open a picture it sent you to instead attach it to your next message. Usually this will happen multiple times before you can land the click correctly and then you will have to clean up all of the attachments – annoying.

In Sidecar mode, the cursor vanishes when you’re using the Pencil. It only appears while you click or drag. That makes it challenging to accurately blind-tap the iPad while looking at the iMac screen which otherwise becomes perfectly natural after a while. Staring at the iPad instead ruins the ergonomics of the setup and negates the benefit of having a large screen in front of you at all. Besides, if it is lying flat as it should be to get the “gravity assist” effect described above, your neck and back will not be happy.

On higher-end combos like the iPad Pro with 2nd-gen Pencil, iPadOS actually supports hover. Unfortunately, Sidecar currently does not forward hover events to macOS regardless of the hardware you use. That means no tooltips, no hover highlights, no way to pre-position a cursor before clicking.

The Root Cause

Let’s take a look at the input events produced to find the solution.

When you tap somewhere new, this sequence happens:

That’s why clicks feel imprecise and why hover doesn’t exist at all – the only motion you can trigger reliably most of the time is this idiosyncratic jump-click-drag without hover.

The core issue is simple: there is absolutely no native way to hover with the Pencil in Sidecar and you need that to land a click precisely. There is also no way to ensure a click does not turn into a drag unless you have superhuman motor control.

The Fix: Pure Hover Mode

The good news: this is all software. Nothing’s wrong with the hardware; macOS just doesn’t handle the events flexibly enough.

That means we can fix it ourselves.

The tool that makes this possible is Hammerspoon – a well-established open source macOS automation utility that lets you intercept and emit input events.

It is also possible to implement this in your own Swift app using the same event tap approach but I have not tried that as it seemed like more work for the same outcome. It might be slightly faster but I have not noticed any latency with the Hammerspoon approach so far.

Install and set up Hammerspoon with the correct permissions. Then save this Lua script to ~/.hammerspoon/init.lua:

-- just a convenience alias
local props = hs.eventtap.event.properties

-- identifier to tell apart the events Hammerspoon emits from the others
-- you can change this to something else
local userData = 0x1234567890

-- tap into mouseDown and mouseUp events
-- block them unless emitted by this script
-- return false = pass through, true = block event
local hoverOnly = hs.eventtap.new({
    hs.eventtap.event.types.leftMouseDown,
    hs.eventtap.event.types.leftMouseUp,
    hs.eventtap.event.types.rightMouseDown,
    hs.eventtap.event.types.rightMouseUp,
  },
  function(e)
    if e:getProperty(props.eventSourceUserData) == userData then
      return false
    else
      return true
    end
  end
)

-- emit instant left mouse button click at current cursor position on ctrl+option+1
hs.hotkey.bind({"ctrl", "alt"}, "1", function() -- change the hotkey here if you use it for something else
  local e1 = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseDown, hs.mouse.absolutePosition())
  e1:setProperty(props.eventSourceUserData, userData)
  e1:post()

  local e2 = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseUp, hs.mouse.absolutePosition())
  e2:setProperty(props.eventSourceUserData, userData)
  e2:post()
end)

-- emit instant right mouse button click at current cursor position on ctrl+option+2
hs.hotkey.bind({"ctrl", "alt"}, "2", function() -- change the hotkey here if you use it for something else
  local e1 = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.rightMouseDown, hs.mouse.absolutePosition())
  e1:setProperty(props.eventSourceUserData, userData)
  e1:post()

  local e2 = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.rightMouseUp, hs.mouse.absolutePosition())
  e2:setProperty(props.eventSourceUserData, userData)
  e2:post()
end)

-- toggle the mouse event tap with a hotkey
hs.hotkey.bind({"ctrl", "alt"}, "escape", function() -- change the hotkey here if you use it for something else
  if hoverOnly:isEnabled() then
    hoverOnly:stop()
  else
    hoverOnly:start()
  end

  -- show a message
  hs.alert.show("Hover mode " .. (hoverOnly:isEnabled() and "ON" or "OFF"))
end)

Then run Hammerspoon and press ⌃⌥Esc to toggle hover mode.

If you end up tweaking the behavior or changing the hotkeys and something gets stuck, running killall Hammerspoon in a terminal window will get you back to default.

Hammerspoon also provides a console window you can use to test and debug your changes. To open it, you might have to just open the app twice, i.e. open Hammerspoon again while it’s already running. This is useful if you do end up changing the hotkeys as input events on macOS are sometimes handled in special ways. For example, I could not set up fn as a modifier.

When changing the hotkeys, remember that you will need your mouse hand to position the Pencil so it is best if you can press the hotkeys comfortably using only your keyboard hand. With the above setup, I press both modifiers at once with the thumb and 1 or 2 with the middle or index finger of the left hand. This has been comfortable so far.

What the Script Does

Here’s how it works in practice:

With ⌃⌥Esc, you can switch the Pencil into “hover only” mode. Taps no longer send clicks; they just move the cursor. The cursor stays visible while being tap-dragged and you can point naturally on the big screen without triggering any input elements earlier than needed or selecting a random bunch of text.

⌃⌥1 and ⌃⌥2 emit synthetic left and right clicks at the current cursor location. They send perfectly matched mouseDown/mouseUp event pairs, so apps never confuse them with a drag. You can click multiple times during a single tap-drag motion with the Pencil.

In fact, you can also simply leave the cursor where you want it and then trigger a click or multiple clicks at exactly the last location. Even though the cursor stops being visible when you lift the Pencil, it will stay in the same place indefinitely as long as you do not tap elsewhere. This is a lifesaver in repetitive mouse-based workflows where that particular button does not have a shortcut for some reason; once hovered, its shortcut is now ⌃⌥1 😎

In short:

Actually want to drag something or do not need the extra precision for now?

Just toggle hover mode to OFF with ⌃⌥Esc. This restores the default behavior.

Next Steps

Right now, I use keyboard shortcuts for clicks. But the next step is to connect and configure the Olympus foot pedals that I currently don’t use. That way, my feet will handle left and right clicks, leaving the hands completely free of strain. This hybrid setup – Pencil for pointing, pedals for clicking – feels like it might finally be the most ergonomic cursor input method so far.

In principle you could also use any other input device to trigger the clicks as long as its events can be tapped by Hammerspoon. In practice that means it is best if the device pretends to be a keyboard.