NUI focus, the mouse cursor and keyboard input

9 min read5 sections · 4 questions answered
Short answer

SetNuiFocus(hasFocus, hasCursor) sends keyboard (first argument) and mouse cursor (second) to your page. SetNuiFocusKeepInput(true) lets the game keep receiving input too, so players can walk with a UI open — then disable camera, attack and pause controls yourself. Always release focus when closing, including on Escape and when the resource stops.

A menu that opens but cannot be clicked, a cursor that never goes away, a player who can shoot while typing in a phone — all of these are focus bugs. NUI focus decides whether keyboard and mouse go to your page or to the game, and three natives cover almost everything.

SetNuiFocus

CallResult
SetNuiFocus(true, true)Keyboard and mouse to the UI — menus, forms
SetNuiFocus(true, false)Keyboard to the UI, no cursor
SetNuiFocus(false, false)Everything back to the game

IsNuiFocused() tells you whether any NUI currently has focus — useful before opening a second UI.

Closing properly

app.js — Escape closes and tells Lua
window.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    document.body.classList.remove('open');
    fetch(`https://${GetParentResourceName()}/close`, { method: 'POST', body: '{}' });
  }
});
client.lua
RegisterNuiCallback('close', function(_, cb)
    SetNuiFocus(false, false)
    cb('ok')
end)

AddEventHandler('onResourceStop', function(res)
    if res == GetCurrentResourceName() then
        SetNuiFocus(false, false)
    end
end)

Walking with a UI open

Phones and radial HUDs often let players keep moving. SetNuiFocusKeepInput(true) keeps game input active while the UI has focus — including the camera and the fire button, so disable what should not work.

client.lua
local open = false

local function setOpen(state)
    open = state
    SetNuiFocus(state, state)
    SetNuiFocusKeepInput(state)
    SendNUIMessage({ action = state and 'open' or 'close' })
    if not state then return end

    CreateThread(function()
        while open do
            DisableControlAction(0, 1, true)   -- look left/right
            DisableControlAction(0, 2, true)   -- look up/down
            DisableControlAction(0, 24, true)  -- attack
            DisableControlAction(0, 25, true)  -- aim
            DisableControlAction(0, 257, true) -- attack 2
            DisableControlAction(0, 199, true) -- pause (P)
            DisableControlAction(0, 200, true) -- pause (Esc)
            Wait(0)
        end
    end)
end

Fixing stuck focus

  1. 1Make sure every close path (button, Escape, event, death) calls SetNuiFocus(false, false).
  2. 2Release focus in onResourceStop — restarting a resource with focus on leaves the cursor behind.
  3. 3Check for two resources fighting: if another UI takes focus and releases it, yours may lose it.
  4. 4Use IsNuiFocused() in a debug command to see the current state.

Loading screens are different

A loading screen has no SetNuiFocus — the cursor is enabled with loadscreen_cursor 'yes' in the fxmanifest. See interactive loading screens.

Common questions

What do the two SetNuiFocus arguments mean?

The first gives keyboard focus to the UI, the second shows the mouse cursor.

Why is my cursor stuck on screen?

Focus was never released. Call SetNuiFocus(false, false) on every close path and in onResourceStop.

How can players walk with a UI open?

Use SetNuiFocusKeepInput(true) and disable the camera, attack and pause controls while it is open.

Why does Escape open the pause menu with my UI?

With KeepInput on, the game still receives Escape. Disable controls 199 and 200 while the UI is open.

Want a loading screen you never have to debug?

Build it in the browser, export once, and edit it whenever — no HTML, no re-uploads.

Start free

More guides