Input & Output Desktop Internals · Sheet 354

Systems Programming

Why your cursor escapes mid-game — and how cursor lock stops it

A gamer "vibecoded" a tool overnight that locks the cursor inside one monitor with a toggle, saving PUBG and CS2 players from fatal alt-tab slips. The fix is one classic OS call. Here's the whole mechanism, simulated in 3D.

Two Monitors, One Runaway Cursor

Drag empty space to rotate · toggle the clip
Escapes onto monitor 2: 0 Saves by cursor lock: 0 Status: unlocked

Why it happens

Windows treats all monitors as one continuous virtual desktop — a single coordinate space. With two 1920-px-wide displays, x runs from 0 to 3839. A fast flick in a game that uses the system cursor (many menus, some third-person and strategy titles, borderless-windowed FPS lobbies) simply slides x past 1919 into the neighbor screen.

Click while it's there and the game loses focus: on a taskbar, a browser, a stream chat. In CS2 or PUBG, a two-second alt-tab is usually a death.

Why fullscreen doesn't always save you

Exclusive fullscreen usually confines the cursor, but borderless windowed — the mode most players prefer for fast alt-tabbing — often doesn't, especially in menus, inventory screens, and map views where the real cursor comes back.

The one-call fix

Windows has had the answer since the 1990s: ClipCursor, a Win32 function that takes a rectangle and refuses to let the cursor leave it. A "cursor lock" utility is essentially:

  • Read the target monitor's bounds (EnumDisplayMonitors / GetMonitorInfo).
  • On hotkey toggle, call ClipCursor(&rect) with those bounds.
  • On toggle-off (or on focus loss), call ClipCursor(NULL) to release.

That's why one person can build it in an evening. The subtle parts are re-applying the clip when Windows clears it (some system events reset it) and playing nicely when games call ClipCursor themselves.

Related mechanisms

Browsers use the Pointer Lock API (games get raw movement deltas, no cursor at all). Engines with raw input skip the cursor entirely for aiming — which is why your aim never escapes, only your menu cursor does.

Worked example — the whole tool in pseudocode

// Toggle cursor confinement to monitor 1 on Ctrl+F10
RECT r = GetMonitorInfo(monitor1).rcMonitor; // e.g. {0, 0, 1920, 1080}

onHotkey(CTRL_F10):
  locked = !locked
  if (locked) ClipCursor(&r); // cursor cannot leave the rect
  else ClipCursor(NULL); // restore free movement

onDisplayChange | onFocusChange:
  if (locked) ClipCursor(&r); // Windows may silently clear the clip

The math of an escape: at 1600 DPI with in-game flicks, a hard 12 cm swipe produces roughly 7,500 counts ≈ 7,500 px of travel. From the center of a 1920-px screen, that overshoots the right edge by more than 6,500 px — deep into monitor 2 in a single frame. With the clip active, the OS clamps x to 1919 that same frame; the cursor hits the edge like a wall. Try it above: raise flick intensity to 100%, watch escapes count up, then switch the lock on and watch the wall work.

Enjoy this tool? Build your own with Super