Someone's Hack is Someone Else's Bug

Story of how a 16 years old hack causes glitches even today

Someone's Hack is Someone Else's Bug

I am still trying to figure out why on a Saturday morning I had the cursed thought of opening Oodle Playground in this obscure, god-forsaken, niche browser called Safari. Since we had recently launched a bunch of stuff for agent observability, I fired up the command pallet and in no time ran into a glitch.

A Jumpy Command Palette

0:00
/0:13

Command Palette Safari Glitch

Huh! Why is it jumping like that? I sure would have noticed it if this is a long-standing bug. Sure enough, there was no such glitch in my trusty old Firefox. The Command Palette behaved sane in Chrome too.

Why was the selected menu jumping from the bottom to an arbitrary place in the middle, though?

I know that you know that I have deliberately phrased this question like that. The "spawning place" for the selection was not arbitrary. Take a closer look:

0:00
/0:13

Notice the mouse pointer?

When the list scrolls, instead of highlighting the last item in the visible section of the list, it always highlighted the item right under the mouse pointer. It's just more difficult to notice because once you start pressing the keys, the mouse pointer is no longer visible on the screen.

Not Just My Bug!

I quickly opened up my favorite implementation of command palette in Safari just to see whether we were alone in this bug: Linear! When I saw that they have the glitch too, I felt reassured that we are in good company.

0:00
/0:14

Linear's Command Palette glitches too!

The Bug Hunt Begins

We all know the mouse moved the cheese, but who moved the mouse?
  • Only Safari is affected
  • Bug is not specific to Oodle's command palette

Given these facts, it made sense to look through the bug reports for Safari for cmdk, the library we use. A bug report from four years ago popped up immediately.

Safari will fire pointer events when navigating via the keyboard, annoyingly causing the active index to jump back up to where the cursor is resting. Instead, these should be ignored when caused via keyboard navigation.

The issue was acknowledged and closed, but not fixed.

Digging Deeper

Safari will fire pointer events when navigating via the keyboard.

Safari does WHAT?! Did I read that right? A quick prototype confirmed it! 🤯

Here, see all those mouse moved: 0, 0 logs that follow button prossed: ArrowDown, ArrowDown? That is Safari firing a mousemove event at each press of the "down" key!

0:00
/0:08

The "Source" of the Troubles

Thank you, Safari, for making it clear in source code: these are "fake mouse events".

Why would you fake a mouse event, though? Sounds like a hack to me. You bet!

As it always is the case, the hack is to fix a bug:

When an overflow: scroll; section is scrolled and different elements move under the mosue cursor, hover states don’t update to reflect the change, tool tips don’t update, and mouseover/mouseout events aren’t fired.

Fake Events: Is that a "Standard" Practice?

Safari decided to do something hacky all those years ago. But do the standards allow it? The W3C explicitly calls this out:

A stationary pointing device (that neither moved relative to the screen surface nor underwent any change in any properties) never fires a pointermove event.

That makes the WebKit folks sound super ignorant, till you start looking at the dates:

This discussion less than a couple of years ago is where they decided to clarify that browsers should not say stuff moved unless stuff actually moved! (duh)

Better late than sorry, I guess 🤷🏻‍♂️

Why Write about a Small Bug?

Frankly, there is nothing super complex going on here. Since the big bang, multiple browsers have always had diverging implementations, and standards have only been a myth.

This one felt special because it is somewhat philosophical. When something below the mouse moves, will you characterize it as "the mouse has moved"? High school physics teaches us motion is relative. Someone who says the mouse moved is right. Someone who says the thing beneath the mouse moved is also right. Just that poor users end up with glitchy software because browsers don't agree.


AI Credits

  • GPT Sol in pi: read through cmdk bug reports, the WebKit source code, W3C discussions.
  • GPT (not sure which exact model 😅): generated the feature image of this blog post along with the "Who Moved My Mouse" poster.