Quick answer: In windowed and borderless fullscreen modes the operating system does not keep the cursor inside the game, so on a two-monitor setup it slides onto the other screen and the next click minimizes the game or focuses another app. Confine the cursor from code (Unity CursorLockMode.Confined, Godot MOUSE_MODE_CONFINED, Unreal Lock Always, GameMaker window_mouse_set_locked or manual clamping), re-apply it whenever the window regains focus, release it when the player alt-tabs, and expose the behaviour as a setting.

It is the top complaint from strategy, management and point-and-click players with two monitors: they edge-scroll the camera to the right, the cursor leaves the game, and a click on the desktop drops the game to the taskbar in the middle of a fight. First-person games get a version of it too, when a menu unlocks the cursor and the player’s first click lands on the other screen. Exclusive fullscreen used to hide the problem; borderless, the default most engines now ship with, does not. Here is how to confine the cursor in every major engine without trapping the player.

What players report

“The mouse goes to my second monitor and the game minimizes.” “Edge scrolling doesn’t work on the right side.” “Clicking during combat alt-tabs me out.” “The cursor disappears when I open the inventory” (it is on the other screen). On ultrawide-plus-side-monitor setups, players sometimes also report that the game opened on the wrong display, which is a sibling bug in window placement rather than cursor handling.

What causes it

  1. Windowed and borderless modes do not clip the cursor. The OS treats the game like any other window. Only exclusive fullscreen confines the cursor to the display on its own, and most engines default to borderless because it alt-tabs cleanly.
  2. The game never asks for confinement, or asks once at startup and loses it. On Windows, cursor clipping is reset whenever another window takes focus, so a confinement set in the first frame is gone after the first alt-tab.
  3. Menus unlock the cursor without confining it. First-person games lock and hide the cursor during play, then switch to a free visible cursor for menus, which is exactly when it can leave.
  4. Edge scrolling uses the cursor position rather than a confined cursor, so on the side facing the second monitor the cursor passes the edge instead of resting on it.

The behaviour to aim for

Players want the cursor to stay in the game while they are playing and to leave freely when they are not. That translates to four rules: confine while the game window is focused and the cursor is visible; release on focus loss and when the game is paused with an on-screen menu that invites alt-tabbing; re-confine when focus returns; and make confinement a toggle in the options, defaulting on for borderless fullscreen and off for a resizable window. A player who streams or uses a second-monitor guide needs the switch.

Fix in Unity

Unity has the mode you need built in. CursorLockMode.Confined keeps a visible cursor inside the game view, and it is supported on Windows and Linux desktop players (on macOS the mode is not available, which is why the toggle matters). Re-apply it on focus because Unity resets the lock state when the window loses focus:

void ApplyCursorMode(bool confine)
{
    Cursor.lockState = confine ? CursorLockMode.Confined : CursorLockMode.None;
    Cursor.visible = true;
}

void OnApplicationFocus(bool hasFocus)
{
    if (hasFocus) ApplyCursorMode(settings.confineCursor);
    else Cursor.lockState = CursorLockMode.None;
}

For a first-person game, switch between Locked in play and Confined (not None) in menus. With the Input System package, read the cursor from Mouse.current.position as usual; confinement does not change the values, it just stops them from passing the edge.

Fix in Godot

Set the mouse mode from an autoload and respond to the window’s focus notifications:

func _ready() -> void:
    _apply(Settings.confine_cursor)

func _apply(confine: bool) -> void:
    Input.mouse_mode = Input.MOUSE_MODE_CONFINED if confine else Input.MOUSE_MODE_VISIBLE

func _notification(what: int) -> void:
    if what == NOTIFICATION_APPLICATION_FOCUS_IN:
        _apply(Settings.confine_cursor)
    elif what == NOTIFICATION_APPLICATION_FOCUS_OUT:
        Input.mouse_mode = Input.MOUSE_MODE_VISIBLE

MOUSE_MODE_CONFINED_HIDDEN is the matching mode for a custom-drawn cursor, and MOUSE_MODE_CAPTURED is the first-person lock. When a first-person game opens its pause menu, go from captured to confined rather than to visible.

Fix in Unreal Engine

Unreal decides this through the input mode. In Blueprint, Set Input Mode Game and UI (or Game Only) has a Mouse Lock Mode pin; set it to Lock Always, or to Lock On Capture if you only want the cursor held while a button is down. The same thing in C++:

FInputModeGameAndUI Mode;
Mode.SetLockMouseToViewportBehavior(EMouseLockMode::LockAlways);
Mode.SetHideCursorDuringCapture(false);
PlayerController->SetInputMode(Mode);
PlayerController->bShowMouseCursor = true;

For a project-wide default, Project Settings > Engine > Input > Mouse Properties has Default Viewport Mouse Lock Mode and Default Viewport Mouse Capture Mode. Note that every SetInputMode call you make later (for a menu, a dialogue, a map screen) sets its own lock mode, and the UI-only mode defaults to not locking, which is where most Unreal games lose the cursor. Wrap the calls in one helper that always passes your setting.

Fix in GameMaker

Recent GameMaker versions provide window_mouse_set_locked(true), which holds the cursor in the window for games that draw their own cursor and read movement with window_mouse_get_delta_x/_y. For a game that uses the system cursor, there is no confine mode, so clamp it yourself in a controller object’s Step event: when window_mouse_get_x() or _y() leaves the window’s bounds, call window_mouse_set() to push it back to the edge. Skip the clamp when window_has_focus() is false so the player can leave with alt-tab.

How to test it

Plug in a second display (or use a virtual one on Windows via a headless display adapter, or Sidecar on a Mac), run the game in borderless fullscreen on the primary, and push the cursor against all four edges, then alt-tab out and back and repeat, then open every menu and repeat. Try the same with the game on the secondary display. Confirm that with the setting off the cursor moves freely, and that the game does not re-confine while a Steam overlay or a file dialog is open. Multi-monitor bugs are the kind that pass every test on a laptop and fail for a third of your players, so the test rig needs two screens.

Finding the setups you cannot test

You cannot own every arrangement of monitors, scales and refresh rates. Bugnet’s Unity, Godot and Unreal SDKs attach display and OS context to each report, and a tagged public tracker entry for “cursor leaves the window” lets players upvote and add their setup instead of posting the same complaint in ten reviews, so you learn that it is always the left-of-primary configuration before you spend a day guessing.

Frequently asked questions

Why does the mouse leave my game on a second monitor?

In windowed and borderless fullscreen modes the operating system treats the game like any other window and does not clip the cursor to it. The game has to ask for confinement itself, and re-ask each time it regains focus.

How do I keep the cursor inside the game window in Unity?

Set Cursor.lockState to CursorLockMode.Confined while the window is focused, and set it again in OnApplicationFocus because Unity clears it when focus is lost. Use Locked for first-person play and Confined, not None, for menus.

Does exclusive fullscreen fix the cursor escaping?

Usually, because the display owns the cursor in exclusive mode, but it brings slow alt-tabbing and flicker on mode switches. Confining the cursor in borderless mode gives the same result without those costs.

Should cursor confinement be a setting?

Yes. Streamers, players following a guide on a second screen and anyone running in a resizable window need to turn it off. Default it on in borderless fullscreen and off in windowed mode.

Confinement is not “set once at startup”. Windows throws it away on every focus change, so the code that restores it on focus is the fix.