mouse
Mouse Double-Clicking by Itself? Switch Chatter vs. Software
A mouse that double-clicks on its own is usually a bouncing switch, not a setting. How chatter works, how to prove it in a minute, and what a browser can measure.
You click a folder once and it opens. You drag a file and it lets go halfway across the screen. You check the settings, find nothing odd, and start wondering about drivers. Most of the time a mouse that double-clicks by itself has a worn switch whose contacts bounce, and you can tell that apart from a settings problem in about a minute by timing the gap between presses. A finger can’t press twice a few milliseconds apart. A failing switch can.
What a mouse switch actually does
Under each main button of most mice sits a small snap-action micro switch: a spring flips a metal contact against another contact when you press, and back when you let go. Omron, the best-known maker of these parts, describes its D2FC line as switches for “operations requiring high reliability with a long life and a clear click feeling” and calls them “ideal for applications such as mouse operations” (Omron D2FC).
Metal contacts never close cleanly. Omron says so directly in its switch FAQ: “chattering (the moment the contacts leave) and bouncing (the moment the contacts come in contact) always occurs in a basic switch with contacts,” and both “may vary depending on the switch operating speed, switch operating load, and contact corrosion” (Omron FAQ: chattering problems). A second FAQ is blunter: “Basic switches cannot completely eliminate chattering due to their structure” (Omron FAQ: switch without chattering).
So every click is really a short burst of on-off-on transitions. The mouse’s firmware hides this by debouncing: once it sees the contact change state, it ignores further changes for a short window and reports one clean press. Razer’s page on its optical switches describes mechanical ones by contrast, saying optical switches need no physical contact, “eliminating the need for debounce delay” (Razer optical mouse switches).
Debouncing only works while the bounce fits inside the window. When the bounce runs past it, the firmware sees what looks like a second press and sends it. That’s switch chatter, and your operating system can’t tell it from a real double-click.
Why it gets worse with age
Wear isn’t only mechanical. A mouse switch carries a tiny signal current, and Omron warns about exactly that case: “When the product is used under a load smaller than the minimum applied load, repeated switching generates oxide film, which may lead to poor contact mainly during microload switching” (Omron FAQ: microload). Oxide film or corrosion on the contacts makes the closure messier, the bounce gets longer, and eventually it outlasts the debounce window.
That fits the usual story people tell about these mice. They worked fine for a year or two, then started double-clicking, sometimes only now and then, sometimes only when clicked gently. Omron’s FAQ notes that “the slower the actuator is operated, the longer the amount of time contact resistance is unstable”, which is one reason a light, slow press can trigger chatter that a firm click doesn’t.
Optical switches avoid the contact problem entirely. In Razer’s description, “the switch’s shutter clears the path for an infrared light beam to pass through,” and with no contact there’s nothing to oxidise or bounce. Razer claims a “100-million CLICK LIFECYCLE” for its Gen-4 switch. That’s the vendor’s own figure. We haven’t tested it, and an optical switch can still fail in other ways: the spring, the plunger, or the sensor itself.
Rule out the settings first
There are three settings that can make a healthy mouse look broken.
| Setting | Where | What it does | Looks like |
|---|---|---|---|
| Double-click speed | Windows: Settings → Bluetooth & devices → Mouse → Additional mouse settings → Buttons | Longest gap that still counts as a double-click | Two slow, separate clicks count as a double-click |
| ClickLock | Same Buttons tab | Holding the button briefly “locks” it down | Drags that won’t let go, or grab a file you meant to click |
| Double-click speed | macOS: System Settings → Accessibility → Pointer Control | Same idea as on Windows | Same symptom as on Windows |
Sources: Microsoft’s Change mouse settings page (“ClickLock allows highlighting or dragging of items without holding down the mouse button”) and Apple’s Pointer Control help page.
Windows lets developers read and set these values, and the docs give the real numbers. SetDoubleClickTime says passing 0 restores “the default double-click time of 500 milliseconds”, and values above 5000 ms are clamped to 5000. For ClickLock, the SystemParametersInfo docs say the feature “temporarily locks down the primary mouse button when that button is clicked and held down”, is off by default, and has a default delay of 1200 ms.
Notice how far apart these numbers are from chatter. A double-click setting that’s too long merges two slow clicks, hundreds of milliseconds apart. ClickLock is about holding the button. Neither can turn one press into two presses milliseconds apart. Only hardware does that. If files open on a single click but you never see a second press, look at software instead: a file manager set to open items on a single click, a macro in the mouse’s own utility, or remote-desktop software. Your mouse is probably fine.
The one-minute chatter test
Open the mouse test, switch to the Double-click tab, and click the target slowly with the left button, about once a second, for thirty seconds or so. Then do a few firm clicks and a few deliberately light ones.
Our tool records the timestamp of every left-button pointerdown and computes the gap from the previous press. Any gap under the chatter threshold is flagged in red as “chatter?”. The default threshold is 50 ms (DEFAULT_CHATTER_THRESHOLD_MS in src/lib/device/mouse-test.ts), and you can tighten it to 40 or 30 ms. A gap exactly equal to the threshold counts as genuine, not chatter. Changing the threshold re-judges every interval already recorded, so you don’t have to click again.
We ran a made-up sequence of press times through the same recordClick function the tool uses (default 50 ms threshold):
| Press at (ms) | Gap from previous | Flagged? | Reading |
|---|---|---|---|
| 0 | — | — | first press |
| 6 | 6 ms | yes | classic bounce: a second “press” 6 ms after the real one |
| 1000 | 994 ms | no | a normal slow click |
| 1150 | 150 ms | no | a deliberate double-click |
| 1190 | 40 ms | yes | suspicious at 50 ms, would pass at 30 ms |
| 2000 | 810 ms | no | slow click |
| 2050 | 50 ms | no | exactly at the threshold, so it counts as genuine |
The panel also shows your fastest genuine double-click, the smallest gap at or above the threshold, so sub-threshold bounces don’t get mistaken for fast fingers.
How to read the result:
- Red flags while you click slowly point at the switch. You weren’t trying to double-click, so a second press milliseconds later came from the hardware.
- No flags, but the problem only happens during drags suggests the switch bounces on release. Our tool times press to press, so a release bounce after a long hold shows up as a gap about as long as the hold, not as a few milliseconds. Use short taps to test, and if drags still drop, the switch is still the prime suspect.
- No flags at all, ever, while the problem continues points back at software. Check the settings above.
Two honest limits. The Double-click tab listens to the left button only, since mixing buttons would corrupt the gaps. And because the Pointer Events spec says browsers “do not fire overlapping pointerdown and pointerup events for chorded button presses”, a second button pressed while another is held doesn’t produce a new pointerdown. It arrives as a pointermove with the changed button in event.button, and the Buttons & Scroll tab reads those too, so chords register.
The other tabs: buttons, scroll, and CPS
Buttons & Scroll lights each of the five buttons the Pointer Events button property can name (left, middle, right, back, forward) and counts wheel events by direction. We count one notch per wheel event and deliberately ignore the delta size. Browsers report it in pixels, lines or pages depending on the OS and smooth-scrolling settings, so the number of physical notches can’t be recovered reliably. The question here is simply: does the wheel register, and in the right direction?
Click speed (CPS) runs a 5 or 10 second timer that starts on your first click and reports average CPS and your best one-second burst. The tiers are labels, not a benchmark: under 5 is “slow”, 5 to under 8 “average”, 8 to 10 “fast”, above 10 “very fast”. A worn switch can inflate a CPS score with chatter, so if a run looks too good to be true, check the Double-click tab.
Polling rate: what a browser can and can’t tell you
Polling rate is how often the mouse sends a report: a 1000 Hz mouse sends one every 1 ms, a 125 Hz mouse every 8 ms. Our Polling rate tab estimates it from the gaps between pointer events while you move. Here’s exactly what it does, from the code:
- It takes timestamps from the last 200 events, drops gaps over 100 ms (you paused) and under 0.05 ms (duplicates), and needs at least 20 usable gaps before showing a number.
- It takes the median gap, averages every gap between a quarter and four times that median (which drops pauses and duplicate reports but lets rounding errors cancel), reports
1000 / average gapas the estimate, then snaps to the nearest standard rate (125, 250, 500, 1000, 2000, 4000 or 8000 Hz) when the estimate is within 15% of one.
The hard part is getting real report timestamps at all. Browsers merge movement events. Chrome’s Aligned input events post explains that continuous events like pointermove are held back and dispatched just before the requestAnimationFrame() callback, so a plain pointermove listener sees roughly one event per screen frame. Feed frame-rate timestamps into the same estimator and you get a believable but wrong answer: a simulated 60 fps stream reads 60 Hz, a 144 fps stream 144 Hz, whatever the mouse is actually doing.
There are two ways around this, and our tool uses both where they exist:
getCoalescedEvents()returns the individual events that were merged into onepointermove(MDN). The spec requires each to carry its own “monotonically increasing”timeStamp.pointerrawupdateis dispatched “as soon as possible and as frequently as the JavaScript can handle the events”, per the spec, only in a secure context. It can still be coalesced, so we read its coalesced list too.
The panel shows which source it’s using: pointerrawupdate, pointermove+coalesced, or plain pointermove. According to MDN’s compatibility data, getCoalescedEvents arrived in Chrome 58, Firefox 59 and Safari 18.2. pointerrawupdate exists in Chrome 77+ and Firefox 148+ (140 to 147 shipped a partial version) but not in Safari.
Even with raw events, the timestamp precision sets a ceiling. MDN’s Event.timeStamp page says Chrome rounds to 0.1 ms, while Safari and Firefox round to 1 ms (unless the page is cross-origin isolated, which ours isn’t). We simulated perfectly regular mice at each precision and ran the results through our estimator:
| True rate | Exact timestamps | Rounded to 0.1 ms (Chrome) | Rounded to 1 ms (Firefox, Safari) |
|---|---|---|---|
| 125 Hz | 125 | 125 | 125 |
| 1000 Hz | 1000 | 1000 | 1000 |
| 2000 Hz | 2000 | 2000 | 1000 |
| 4000 Hz | 4000 | 4000 (raw 3996–4004) | 1000 |
| 8000 Hz | 8000 | 8000 (raw 7992–8024) | 1000 |
So in practice our tool reads reliably up to 1000 Hz everywhere and up to 8000 Hz in Chrome. Rounding to 0.1 ms turns a 4000 Hz mouse’s 0.25 ms gaps into a mix of 0.2 and 0.3 ms. Taking the median of those gaps would read 3333 or 5000 Hz, which is what our first version did. The tool now averages the gaps near the median instead, so the rounding errors cancel out. At 1 ms precision there is nothing left to average: half of a 2000 Hz mouse’s gaps round to zero. A busy tab or a power-saving laptop can also drop events and pull the reading down. Treat the number as “does my 1000 Hz setting look like 1000 Hz, or like 125?”, which is a useful check after a firmware reset. For anything above that, trust the mouse’s own software.
A quick checklist
- Double-click tab, slow clicks for 30 seconds. Any red “chatter?” gap means the switch is bouncing. Try both firm and light presses.
- No red, but it still happens? Check the double-click speed slider and ClickLock (Windows) or Pointer Control (macOS), then the mouse vendor’s software for macros.
- Chatter confirmed? Under warranty, that’s the claim. Out of warranty, the fix is a replacement switch or a mouse with optical switches.
- Buttons & Scroll tab after any repair or spill: five buttons and four scroll directions.
If you’re checking a whole setup, the keyboard test finds dead keys and measures rollover (the matrix behind ghosting is explained in Keyboard ghosting and N-key rollover), and the gamepad tester and touchscreen test cover the controller and phone versions of phantom input, which we wrote up in Stick drift, dead zones and ghost touches. Everything in the mouse test runs in your browser. Clicks and movement are never sent anywhere, and the only tool-specific analytics event is an anonymous “click-speed run finished” with no timing data.