NUI and CEFintermediate11 min readupdated 19 Sept 2026

SetNuiFocusKeepInput in depth: letting the game keep its input

The short answer

SetNuiFocusKeepInput(true) tells FiveM to keep passing keyboard and mouse input to the game while an NUI page has focus from SetNuiFocus. It does nothing on its own: focus must be on first. Once it is on, the game sees everything, including mouse look, fire and Escape, so run a per-frame loop that either blocks the dangerous controls or, better, blocks everything and re-enables only movement, voice and driving. Turn it off while a text field is focused and on every close path, and check it with IsNuiFocusKeepingInput() when debugging.

Phones, radial menus, radios and target menus all share one requirement: the player should still be able to walk, drive or talk while the interface is on screen. FiveM has exactly one native for that, SetNuiFocusKeepInput, and it is simple to call and surprisingly easy to get wrong. This guide goes past the one-line explanation and covers the control lists, the voice and vehicle cases, text fields, and the bugs that show up once two UIs compete for focus.

SetNuiFocusKeepInput in depth: letting the game keep its input — illustrated with a FiveM-compatible minimap render

#What the native actually changes

The declaration is one line: SetNuiFocusKeepInput(keepInput), a client-only CFX native that takes a boolean. Its partner IsNuiFocusKeepingInput() returns the current state. Neither has any effect until an NUI frame holds focus through SetNuiFocus, which is why the basics are covered first in NUI focus and cursor.

Normally, when your page has focus, FiveM routes the keyboard (and the mouse, if the cursor is on) to the browser and the game stops receiving them. With keep input switched on, input goes to both: the page still gets keydown and mouse events, and the game still sees the same keys as controls. That is the whole feature. Everything else in this article is about living with the consequences.

CallsPage receivesGame receivesTypical use
SetNuiFocus(true, true)Keyboard + mouseNothingInventories, shops, forms
SetNuiFocus(true, true) + SetNuiFocusKeepInput(true)Keyboard + mouseKeyboard + mousePhones, radios, radial menus
SetNuiFocus(true, false) + SetNuiFocusKeepInput(true)KeyboardKeyboard + mouse lookKey-driven overlays without a cursor
SetNuiFocus(false, false)NothingEverythingUI closed or display-only HUD

The combinations you will actually use

#A correct open and close pair

Keep the three calls together in one function so no code path can forget one of them. The page is told to show itself after focus is set, which avoids a frame where the UI is visible but cannot be clicked.

client.lua
local isOpen = false

local function setPhone(state)
    if state == isOpen then return end
    isOpen = state

    SetNuiFocus(state, state)
    SetNuiFocusKeepInput(state)
    SendNUIMessage({ action = 'visible', value = state })

    if state then
        StartControlLoop()
    end
end

RegisterNuiCallback('close', function(_, cb)
    setPhone(false)
    cb({})
end)

AddEventHandler('onResourceStop', function(name)
    if name ~= GetCurrentResourceName() then return end
    SetNuiFocusKeepInput(false)
    SetNuiFocus(false, false)
end)

Resetting keep input on stop matters more than it looks. A resource restarted during development with keep input still on can leave the next UI that takes focus in a strange half state. Treat both flags as something you own and must hand back.

#The block-list approach and its gaps

The first thing players notice with keep input on is the camera: moving the mouse over your phone also swings the view, and clicking an app fires the weapon in their hand. The usual fix is a per-frame thread that disables the controls you do not want.

IDControlWhy
1, 2Look left/right, up/downMouse movement over the UI would turn the camera
24, 257Attack, attack 2Clicking the UI fires the weapon
25AimRight-click on the UI aims
140, 141, 142Melee light, heavy, alternateClicks punch people
37Weapon wheel (Tab)Tab opens the wheel over your UI
199, 200Pause (P) and pause alternate (Esc)Escape opens the map instead of closing your UI
245Text chat (T)Typing T opens chat
14, 15, 16, 17Weapon scroll next/prevMouse wheel over the UI changes weapons

Controls most keep-input UIs disable (input group 0)

The problem with a block-list is that it is never complete. Every framework adds its own keybinds, and emotes, hands-up or the target eye can still fire through your UI. The list above is a good minimum; the allow-list below is the robust version.

#The allow-list approach (recommended)

Instead of guessing which controls to block, block all of them and re-enable the handful the player should keep. DisableAllControlActions(0) followed by EnableControlAction calls in the same frame gives you exact control.

client.lua — allow only movement, voice and driving
local ON_FOOT = { 30, 31, 32, 33, 34, 35, 21, 22 }
local IN_VEHICLE = { 59, 63, 64, 71, 72, 76 }
local ALWAYS = { 249 }

function StartControlLoop()
    CreateThread(function()
        while isOpen do
            DisableAllControlActions(0)

            for i = 1, #ALWAYS do EnableControlAction(0, ALWAYS[i], true) end

            if IsPedInAnyVehicle(PlayerPedId(), false) then
                for i = 1, #IN_VEHICLE do EnableControlAction(0, IN_VEHICLE[i], true) end
            else
                for i = 1, #ON_FOOT do EnableControlAction(0, ON_FOOT[i], true) end
            end

            Wait(0)
        end
    end)
end
GroupIDsControls
On foot30, 31Move left/right, move up/down (analogue axes)
On foot32, 33, 34, 35W, S, A, D as individual controls
On foot21, 22Sprint and jump
Vehicle59, 63, 64Steering axis and steer left/right
Vehicle71, 72, 76Accelerate, brake/reverse, handbrake
Always249Push-to-talk (N)

Leave the vehicle exit control (75, F) disabled so a mis-click does not throw the player out of a moving car. If you want sprint to stay disabled while a phone is up for roleplay reasons, remove 21 from the list; the point of an allow-list is that these decisions become explicit.

#Reading keys while they are disabled

A disabled control still registers presses; it just stops the game acting on them. That means your Lua loop can listen for Backspace or Escape and close the UI without the pause menu opening. Use the IsDisabledControl… family, because IsControlJustPressed returns false for disabled controls.

client.lua — inside the control loop
if IsDisabledControlJustPressed(0, 200) or IsDisabledControlJustPressed(0, 177) then
    setPhone(false)
end

Control 200 is the Escape pause alternate and 177 is the phone cancel control (Backspace, Escape or right mouse by default). Handling the close in Lua rather than in the page has a bonus: it also works when the page has lost keyboard focus to an input field, which is the next topic.

#Typing in a text field with keep input on

With keep input on, every letter a player types into a message box also reaches the game. W walks forward, T opens chat and a number key might swap weapons. An allow-list reduces the damage but movement keys are, by design, still enabled. The clean fix is to switch keep input off while any text field has focus and restore it afterwards.

app.js — toggle keep input around text fields
const isTextField = (el) =>
  el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable);

document.addEventListener('focusin', (e) => {
  if (isTextField(e.target)) fetchNui('keepInput', { value: false });
});

document.addEventListener('focusout', (e) => {
  if (isTextField(e.target)) fetchNui('keepInput', { value: true });
});
client.lua
RegisterNuiCallback('keepInput', function(data, cb)
    if isOpen then
        SetNuiFocusKeepInput(data.value == true)
    end
    cb({})
end)

The isOpen guard stops a late focusout (fired as the page hides) from switching keep input back on after the UI has closed. focusin and focusout bubble, unlike focus and blur, so one listener on the document covers every field. The fetchNui helper is the one from NUI callbacks with fetch. More keyboard edge cases are collected in NUI text inputs and keyboard bugs.

#When two UIs compete for focus

Focus is per frame, but the way keep input interacts between frames is less predictable. There is an open report on the FiveM tracker where a first UI sets keep input to true and a second UI then sets it to false, yet input keeps flowing to the game. In practice, three habits avoid most of these problems:

  1. Always set keep input explicitly when you take focus, even to false. Never rely on the default.
  2. Always set it back to false when you release focus, before SetNuiFocus(false, false).
  3. Check IsNuiFocused() before opening; if another UI already holds focus, close it through its own export or event instead of stacking a second focused UI on top.

Frameworks with a central UI manager solve this once: every resource asks the manager to open, and the manager owns the focus flags. If you maintain several of your own UIs, a tiny shared export (requestFocus(name, cursor, keepInput) and releaseFocus(name)) is worth the ten lines it takes.

#Debugging focus state

When a player reports a stuck camera or an unclosable menu, you need to know the state at that moment. A small command prints it:

client.lua
RegisterCommand('focusdebug', function()
    print(('focused=%s keepInput=%s'):format(
        tostring(IsNuiFocused()),
        tostring(IsNuiFocusKeepingInput())
    ))
end, false)
SymptomLikely cause
Camera spins while using the UIKeep input on, look controls (1, 2) not disabled
Clicking the UI shootsAttack controls (24, 257) not disabled
Escape opens the mapPause controls (199, 200) not disabled, or close handled on keydown
Player walks while typingKeep input still on while a text field is focused
Cannot talk with phone openPush-to-talk (249) disabled by DisableAllControlActions
Camera stuck after closingKeep input or focus never released on one close path

Check the page side too: open the NUI devtools and confirm the keepInput callback requests actually go out when a field gains and loses focus.

Share this guideXRedditFacebook

Questions

What does SetNuiFocusKeepInput do?
It lets the game keep receiving keyboard and mouse input while an NUI page has focus, so players can move, drive or talk with a UI open.
Do I still need SetNuiFocus with SetNuiFocusKeepInput?
Yes. Keep input only changes behaviour while a frame has focus from SetNuiFocus(true, …). On its own it does nothing.
Why does my camera move when I use my phone UI?
With keep input on, mouse movement also reaches the game. Disable controls 1 and 2 every frame, or use DisableAllControlActions(0) and re-enable only what you need.
Why can I not use push-to-talk while my UI is open?
Your control loop disables control 249. Re-enable it with EnableControlAction(0, 249, true) each frame.
How do I stop the player walking while typing?
Send a callback on focusin of a text field that calls SetNuiFocusKeepInput(false), and switch it back on focusout.
How can I check whether keep input is active?
Call IsNuiFocusKeepingInput() on the client. Pair it with IsNuiFocused() in a debug command.

Ready to pick a map?

Twelve themes on three base map styles, $8 each, instant download.

Relevant to what you just read

Look it up while you work

The reference tables this guide leans on, free and without an account.