Skip to content

Set Keyboard Focus / Set User Focus / Set Is Enabled

At a glance

Lives on: any UMG Widget - Set Keyboard Focus: requests focus through Slate's keyboard-focus route - Set User Focus: requests focus for the local user identified by a Player Controller - Set Is Enabled: allows or blocks normal interaction while keeping the widget in layout - Returns: no success value from any of the three nodes - Can fail by: targeting None, focusing a widget that is not constructed, present, visible, enabled, or focusable, or supplying the wrong/non-local controller - Official docs: Set Keyboard Focus, Set User Focus, and Set Is Enabled

Focus answers which control receives keyboard/gamepad UI input for a user. Enabled state answers whether a widget and its descendants may interact. Neither one displays the menu or changes the Player Controller's input mode.

The one-minute version

  • Slate tracks a focus path for each local user. Only one widget at the end of that user's path owns focus at a time.
  • Set Keyboard Focus has no Player Controller input. It uses the application's keyboard-focus route; it does not mean "focus this for all split-screen players."
  • Set User Focus takes a Player Controller and changes focus for that controller's local Slate user. Use it when the player must be explicit.
  • If the target belongs to its intended owning player, the Set Focus convenience is preferred by Epic because it selects that owning user.
  • A focus request needs a live Slate widget in the active widget hierarchy, and the target must support keyboard focus. Add/show/enable the menu before focusing its first Button or focusable User Widget.
  • Set Is Enabled(false) keeps the widget painted and in layout but blocks normal interaction. Controls often draw a disabled style; custom widgets may look unchanged unless you style them.
  • Disabling a parent effectively disables every descendant. A child can still store its own enabled flag, but it cannot escape a disabled ancestor.
  • Hiding, disabling, or removing the focused widget does not define a useful replacement. Move focus deliberately to the modal's first control, the previous menu control, the next enabled option, or back to gameplay.
  • Input mode, focus, cursor, visibility, enabled state, and widget lifetime are separate parts of opening and closing a menu.

Focus is a path for one user

Focus is not a Boolean that every widget can turn on independently. Slate stores a path from the active window through the widget hierarchy to one focus target for each user:

local user 0 focus path
game window
`-- Player 0 screen
    `-- PauseMenu
        `-- ResumeButton  <- focused widget

local user 1 focus path
game window
`-- Player 1 screen
    `-- Inventory
        `-- UseButton     <- focused widget

When one target receives focus for a user, the old target on that user's path loses it. Player 0 and Player 1 can have different focused controls in local multiplayer.

Focus is what lets a Button respond to Enter/gamepad Accept, an Editable Text control receive typed characters, and directional navigation know where to start. It is not the same as pointer hover, mouse capture, selected list item, or the Player Controller's gameplay input routing.

Set Keyboard Focus versus Set User Focus

Both Blueprint nodes target a Widget and return no success/failure value. They differ in how the user is chosen.

Set Keyboard Focus

Set Keyboard Focus supplies only the target widget. Underneath UMG, it asks Slate to change the application's keyboard focus to that widget.

That is convenient in a single-user game or an application screen where the keyboard owner is unambiguous. It is a poor selector for local multiplayer: the node does not carry a Player Controller, local-player index, or "all users" instruction. Which Slate user owns the physical keyboard route is an input/application mapping concern, not information encoded in this node.

Use it when the application keyboard focus is exactly what you mean. Do not read "Keyboard" as "Player 0" or "every local player."

Set User Focus

Set User Focus takes a Player Controller. UMG uses that local controller to identify the corresponding Slate user, then requests focus for only that user.

The controller must represent a local player on this machine. A server-only controller or a remote controller representation has no local screen/input user to focus. In split-screen, pass the same controller that owns the widget and whose player-screen section displays it.

Player1Controller
-> Create Widget(Owning Player = Player1Controller)
-> Add to Player Screen
-> FirstInventoryButton Set User Focus(Player1Controller)

Do not call Get Player Controller 0 from every widget. That makes every local menu compete for user 0's focus even when the widget belongs to another player.

Set Focus: the owning-user convenience

Set Focus targets the widget without a controller pin, but its contract is different from Set Keyboard Focus: it selects the widget's owning user. Epic's current UWidget API recommends it when that is the user you mean.

For that to be reliable, create the root User Widget with the correct Owning Player, keep child controls inside that owned widget hierarchy, and use Add to Player Screen for split-screen presentation. Use explicit Set User Focus when code outside the widget is selecting a particular local player.

What a focus request needs

A valid UObject reference is necessary but not sufficient. The target needs a usable Slate focus path.

1. The underlying widget must exist

UMG objects wrap Slate widgets. A freshly allocated object that has not built its Slate representation cannot become the active screen focus target. Adding the root User Widget to a viewport/player screen builds and registers the visible hierarchy.

For normal menus:

Create Widget
-> Add to Player Screen / Add to Viewport
-> make panel Visible and enabled
-> set input mode
-> focus the first real control

Calling focus before the hierarchy is present usually does nothing useful; there is no pending success pin or automatic retry.

2. The widget must support keyboard focus

Not every Widget is a focus stop. Buttons, text-entry controls, and other interactive widgets can support focus. Decorative Images and Text Blocks normally should not. A root User Widget has an Is Focusable setting when you intend the root itself to handle keyboard events.

Supports Keyboard Focus is the direct query when debugging. If a menu root is only a container, focusing its first Button is usually clearer than making the whole root focusable.

Current UE also offers Set Desired Focus Widget on UserWidget: it can name a child that should receive focus when the root receives it. That setter returns false if the supplied Widget is not a child of that User Widget.

3. The active path must allow focus

The target must be in the active hierarchy and effectively visible/enabled. A Hidden or Collapsed target has no usable visible focus path. A disabled target, or a target under a disabled ancestor, cannot serve as a normal interactive focus stop.

Pointer hit-test visibility is related but different. Hit Test Invisible controls pointer discovery; it is not a substitute for enabled state or a complete keyboard-focus policy. Likewise, Render Opacity 0 can make a focused control visually disappear without making it Hidden.

4. Input must be routed to UI

Focus can be set correctly while gameplay input mode still owns the keys. Opening an interactive menu normally pairs focus with Set Input Mode UI Only or Set Input Mode Game and UI, plus cursor and pause policy. A focus setter does not change any of those settings.

What Set Is Enabled actually changes

Set Is Enabled writes one widget's enabled flag. The Blueprint node has an execution output and no Boolean return; the C++ call shape is void UWidget::SetIsEnabled(bool).

Disabled means the widget is unavailable for normal user interaction. It does not mean absent:

Property while disabled Typical result
Paint still painted
Layout still occupies its normal space
Pointer/keyboard interaction blocked as an enabled control
Disabled visual often supplied by the control/style
UObject variables/functions still exist and can be changed by code
Animations/timers/update logic not automatically stopped
Parent/viewport relationship unchanged

That makes disabled state useful for a visible unavailable action:

CraftButton.SetIsEnabled(CanAffordRecipe)
CraftRequirementText.SetText(reason when false)

Do not use a disabled style as the only explanation. Show why an important action is unavailable, especially when color alone would be ambiguous.

Disabled state composes through parents

An ancestor gates its descendants:

MainMenuPanel = disabled
|-- ResumeButton = enabled
`-- SettingsButton = enabled

effective result: both buttons are disabled

The child flags can remain true; re-enabling the parent allows each child to resume according to its own stored flag. Setting one child enabled while its ancestor remains disabled cannot override the ancestor.

This matters for modal dialogs. If the confirmation dialog is nested under the panel you disable, the dialog is disabled too. Put the modal in a sibling overlay/layer above the disabled background panel:

MenuRoot Overlay
|-- MainMenuPanel       <- disable while modal is open
`-- ConfirmDialog       <- separate sibling, stays enabled

Disabled style is presentation, not proof

Standard controls commonly draw a disabled appearance, but style choice can make enabled and disabled states look identical. Conversely, dimming a Widget with Render Opacity does not disable it.

When a button looks disabled but still clicks, inspect Get Is Enabled on the exact instance and its ancestors. When it is disabled but looks normal, inspect the Button style or add a deliberate state treatment; do not reimplement the interaction gate with a second Boolean click check unless gameplay eligibility also needs validation at the action boundary.

How focus moves after the first setter

Calling a setter establishes the current focus target; it does not lock focus there forever.

  • Keyboard/gamepad navigation moves from the current target according to UMG navigation rules and the available visible, enabled, focusable widgets.
  • Mouse/pointer interaction can move focus when the clicked control's behavior accepts focus. Not every visible control does.
  • Opening a new window/menu/modal can replace the focus path.
  • Code can call another focus setter later in the frame.
  • Hiding, disabling, or removing a target makes it unsuitable, but does not express which remaining control your design wants next.

UMG can infer simple directional navigation from layout. Dense grids, wrap-around rows, inventory screens, and modal boundaries often need explicit navigation rules. Set Navigation Rule Explicit can name the next widget for a direction, but only for widgets already in a widget tree.

A missing focus outline is not proof that focus failed. Project Render Focus Rule can show the focus brush always, only for non-pointer or navigation focus, or never. Check Has User Focus with the intended Player Controller or Has Keyboard Focus before diagnosing only from the artwork.

Restore focus deliberately

The safe pattern chooses a stable destination for every transition.

Open a menu

Create/store MenuWidget with Owning Player = LocalPC
-> Add to Player Screen
-> MenuRoot Set Visibility Visible
-> MenuRoot Set Is Enabled true
-> Set Input Mode UI Only(LocalPC, Widget to Focus = FirstButton)
-> FirstButton Set User Focus(LocalPC)
-> LocalPC Show Mouse Cursor true

The input-mode node can set a focus target itself; the explicit final setter is useful when a later visibility/activation step determines the real first control. Choose one ordered open function so two systems do not fight.

Open and close a confirmation modal

OpenConfirm:
    remember ReturnFocusWidget = DeleteButton
    MainPanel Set Is Enabled false
    ConfirmPanel Set Visibility Visible
    ConfirmPanel Set Is Enabled true
    ConfirmYesButton Set User Focus(LocalPC)

CloseConfirm:
    ConfirmPanel Set Visibility Collapsed
    MainPanel Set Is Enabled true
    if ReturnFocusWidget is valid, visible, enabled, and focusable:
        ReturnFocusWidget Set User Focus(LocalPC)
    else:
        FirstMainMenuButton Set User Focus(LocalPC)

Store a reference to a known return control, not a promise that "whatever had focus" will still exist. List entries can be regenerated, buttons can become disabled, and a screen transition can destroy the old Widget instance.

Disable the currently focused action

Before disabling a focused Button, choose the next eligible Button and move focus to it. Re-enabling the old Button later does not communicate that it should steal focus back.

if PurchaseButton HasUserFocus(LocalPC):
    BackButton Set User Focus(LocalPC)
PurchaseButton Set Is Enabled false

Close the menu into gameplay

MenuRoot Remove from Parent (or hide it)
-> Set Input Mode Game Only(LocalPC)
-> LocalPC Show Mouse Cursor false
-> restore any movement/look gates or mapping contexts changed on open

If another menu replaces it, add/show/enable the new menu and focus its first control for the same user. Do not focus a Widget and then immediately remove its root from the hierarchy.

Split-screen and network boundary

Each local player needs a coherent bundle:

  • its own local Player Controller;
  • its own User Widget instance with that controller as Owning Player;
  • Add to Player Screen for that player's screen region;
  • input mode/cursor policy applied to that controller; and
  • Set Focus/Set User Focus for that same user.

One player's menu should not disable or focus the other player's controls unless the game deliberately implements a shared pause/modal policy.

Screen UI and focus are local cosmetic/input state. They are not replicated. The server may replicate "this purchase is unavailable" or "the match is paused," but each client updates enabled state and focus on its own widget instances. A dedicated server has no local viewport focus target.

When it fails (and what failure does)

None of these setters returns a success flag or throws a gameplay exception. Common failures are:

  1. Target is None. Blueprint can report Accessed None; no intended focus or enabled state changes.
  2. The widget is not constructed or present. The UObject exists, but there is no active Slate path to focus.
  3. The target does not support focus. A decorative/root container was targeted instead of a Button or focusable User Widget.
  4. An ancestor hides or disables it. The child's own settings look right, but the effective path is unavailable.
  5. The Player Controller is None, remote, or the wrong local player. Set User Focus cannot select the intended Slate user.
  6. Another step immediately moves focus. Input-mode setup, a second open function, navigation, a pointer click, or another setter wins later.
  7. The wrong widget instance was targeted. A regenerated ListView entry or duplicate menu is visible while an old stored reference receives the call.
  8. The focus is real but the brush is hidden. Render Focus Rule or style makes diagnosis by appearance misleading.
  9. The control is enabled but pointer clicks still fail. Visibility, hit-test visibility, Z order, input mode, or another overlay blocks it.
  10. The control was re-enabled but focus never returned. Enabled state does not encode focus-restoration policy.

Use Supports Keyboard Focus, Has User Focus, Has User Focused Descendants, Get Is Enabled, Get Visibility, and Get Owning Player on the exact runtime instance. Then inspect the path and effective state in Widget Reflector. A Delay can hide construction/order mistakes temporarily; it does not identify the wrong user, ancestor, or instance.

The C++ shape

The C++ equivalents return void, so validate the references and policy before the call:

void USettingsMenu::FocusFirstOption(
    APlayerController* LocalController,
    UWidget* FirstOption)
{
    if (!IsValid(LocalController) || !IsValid(FirstOption))
    {
        return;
    }

    FirstOption->SetIsEnabled(true);
    FirstOption->SetUserFocus(LocalController);
}

For a control inside the correctly owned User Widget, FirstOption->SetFocus() is the owning-user convenience. SetKeyboardFocus() is the no-controller keyboard route.

What these nodes do not do

They do not:

  • create, add, show, hide, remove, or destroy a Widget;
  • make an inherently non-focusable widget support focus;
  • focus every local user when Set Keyboard Focus is called;
  • turn a remote/server Player Controller into a local Slate user;
  • set the Player Controller's Game/UI input mode;
  • show or hide the mouse cursor;
  • pause gameplay or block pawn movement/look by themselves;
  • guarantee a visible focus brush;
  • configure directional navigation or wrap-around policy;
  • make disabled state remove layout space or hide the widget;
  • stop code, animations, timers, bindings, or dispatcher calls on a disabled Widget;
  • choose a replacement when the focused Widget disappears; or
  • replicate focus/enabled state to another machine.

Lookalikes - which one do I want?

Node / property Use when Watch out
Set Focus A widget should receive focus for its owning user. Correct Owning Player context is the foundation.
Set User Focus Code must name the specific local Player Controller/user. A remote or wrong controller cannot focus the intended local UI.
Set Keyboard Focus The application's keyboard focus target is unambiguous. No Player Controller pin; not an all-users operation.
Set Desired Focus Widget A User Widget should forward root focus to a known child. Returns false when the target is not its child.
Set Input Mode UI Only / Game and UI The controller must route incoming input toward UI. Display, enabled state, cursor, and pause remain separate.
Navigation Rules D-pad/arrow movement needs explicit next/stop/wrap behavior. Rules act from an existing focus target in the live tree.
Set Is Enabled A visible control/subtree should be unavailable for interaction. Ancestors gate descendants; layout remains.
Set Visibility Painting, layout participation, or pointer hit testing should change. It does not define focus recovery or enabled style.
Hit Test Invisible A visible decoration should not receive pointer hits. Pointer policy is not the same as keyboard focus or enabled state.
Remove from Parent The Widget should detach from its panel or viewport. Restore focus/input mode before relying on gameplay controls.

Rule of thumb: identify the local user, make one real control present and eligible, focus it after activation, and name the destination for every disable/hide/remove transition.

Going deeper