Skip to content

Enable lock-screen input callbacks

When the host PC switches to the Windows lock screen, keyboard and mouse input at the operating system (OS) level is blocked by OS security policy. In a remote environment, screen and audio streaming remain available, but actual game control becomes unavailable.

Previously, remote users had to enter the Windows account password to unlock the PC. However, this exposed the risk of granting full PC control and made the connection process inconvenient.

The Remote Play Plugin provides the Play without unlocking the lock screen feature in the Remote Play settings of Hive Console. When this feature is enabled, all input events, such as keyboard, mouse, touch, joystick, wheel, and zoom events, are delivered directly to the game callback.

Key behavior

  • Callback-based delivery: All input events are delivered to the callback function registered with RegisterCallback as eventType: "Control". This behavior is the same regardless of the lock state, and callback delivery continues even after the lock screen is unlocked.
  • OS input path bypass: The OS SendInput path is no longer used. Input events are received consistently regardless of whether Windows is locked.
  • Direct injection into the game: The game directly injects the input data received through the callback into its internal input system and handles controls the same way in both locked and normal states.

Prerequisites

Prepare the following before applying this feature.

Warning

If you enable the Play without unlocking the lock screen feature in Hive Console without registering a callback through RegisterCallback, all input events are lost, making remote control difficult. Make sure to register the callback first.

Control event protocol

After the Play without unlocking the lock screen feature is enabled, input events delivered through the callback use the same JSON format as chat events, and the eventType value is fixed to "Control". The actual input type is identified by the inner controlType.

Common envelope structure

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "<Key | Click | Wheel | Zoom>",
            "controlValue": {
                "value"  : "<controlType-specific-value>",
                "action" : "<controlType-specific-action>"
            }
        }
    },
    "etc"       : { }
}
Field Description
version Fixed to "1.02.00"
eventType Always "Control"
eventValue.value.controlType Input type. One of four values: "Key" / "Click" / "Wheel" / "Zoom"
eventValue.value.controlValue.value Data by controlType, such as coordinates or key codes
eventValue.value.controlValue.action State or action by controlType
etc Empty object

controlType = "Key" - keyboard input

Delivers the pressed or released state of a single keyboard key. Both keyboard input and joystick input generated by the user in the web client are converted to controlType.

Field Value
controlValue.value Hexadecimal string of a Windows Virtual-Key Code, such as "0x41" = 'A', "0x57" = 'W', or "0x20" = Space
controlValue.action "Down" or "Up"

Joystick direction codes are split into single key events according to the mapping setting (WASD / DIRECTION) and delivered as controlType. In other words, the game sees keyboard input and joystick input in the same format. The host also splits diagonal movement into two single key events before sending it.

Example - pressing the 'A' key

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Key",
            "controlValue": { "value": "0x41", "action": "Down" }
        }
    },
    "etc"       : { }
}

Example - joystick up (the 'W' key when using WASD mapping)

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Key",
            "controlValue": { "value": "0x57", "action": "Down" }
        }
    },
    "etc"       : { }
}

controlType = "Click" - mouse and touch coordinate input

Delivers mouse click, mouse movement, and touch coordinates. Both mouse input and touch input generated by the user in the web client are automatically converted to pixel coordinates in the client area of the game window, based on GetClientRect(), before delivery.

Field Value
controlValue.value "x#y" format. The unit is the pixel coordinate of the game window client area, with one decimal place. Normalized coordinates from 0 to 1000 in the web client are converted to pixels by the host before delivery.
controlValue.action "Down", "Up", or "Move"

Note

For touch input, touchID information is not preserved during conversion to the Click type.

Coordinate conversion reference

curWidth and curHeight are the client area size of the game window based on GetClientRect(). Therefore, apply these values directly as window coordinates in the game.

Web client position Normalized coordinate (inbound) Pixel coordinate example (curWidth=1053, curHeight=1585)
Top left "0.0#0.0" "0.0#0.0"
Top right "1000.0#0.0" "1053.0#0.0"
Bottom left "0.0#1000.0" "0.0#1585.0"
Bottom right "1000.0#1000.0" "1053.0#1585.0"
Center "500.0#500.0" "526.5#792.5"

Example - mouse click (Down -> Up)

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Click",
            "controlValue": { "value": "526.5#792.5", "action": "Down" }
        }
    },
    "etc"       : { }
}

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Click",
            "controlValue": { "value": "526.5#792.5", "action": "Up" }
        }
    },
    "etc"       : { }
}

Example - drag (Move)

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Click",
            "controlValue": { "value": "645.1#681.7", "action": "Move" }
        }
    },
    "etc"       : { }
}

controlType = "Wheel" - mouse wheel

Delivers mouse wheel scroll actions.

Field Value
controlValue.value "x.0#y.0" format. The value is the current pixel coordinate of the mouse cursor, based on the game window client area. Scroll step information sent by the web client is lost.
controlValue.action "Up" (scroll up) or "Down" (scroll down)

Example - wheel down (mouse position: 1234.0 px, 567.0 px)

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Wheel",
            "controlValue": { "value": "1234.0#567.0", "action": "Down" }
        }
    },
    "etc"       : { }
}

controlType = "Zoom" - zoom in and out

Delivers zoom-in and zoom-out actions for a camera or map screen.

Field Value
controlValue.value Always fixed to "1". Scroll step information sent by the web client is lost.
controlValue.action "In" (zoom in) or "Out" (zoom out)

Example - zoom in

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Zoom",
            "controlValue": { "value": "1", "action": "In" }
        }
    },
    "etc"       : { }
}

Example - zoom out

{
    "version"   : "1.02.00",
    "eventType" : "Control",
    "eventValue": {
        "value": {
            "controlType" : "Zoom",
            "controlValue": { "value": "1", "action": "Out" }
        }
    },
    "etc"       : { }
}

Input type conversion mapping summary

The following mapping shows how the original input types sent by the web client are converted into host callback events.

Web client input Callback controlType Main conversion / information loss
Key "Key" VK hexadecimal value remains unchanged
Joystick "Key" Direction code -> WASD / DIRECTION mapping -> split into single keys
Click "Click" Normalized coordinates -> pixel conversion
Touch "Click" Normalized coordinates -> pixel conversion; touchID is not delivered. Multiple touches are determined by duplicate Down events.
Wheel "Wheel" Step information -> replaced with mouse pixel coordinates
Zoom "Zoom" Step information -> always fixed to "1"

Status (Event) and chat (Message) events are not delivered through this Control event. They are delivered separately according to the existing protocol.

Game-side input handling guide

When the Play without unlocking the lock screen feature is enabled in the Remote Play settings of Hive Console, Remote Play does not send input events to the input queue of the operating system (OS). Instead, it delivers them directly to the game through the registered callback.

Therefore, input events received through the callback must be sent directly to the game's internal input system, such as Unity Input System or Unreal Input Subsystem, and handled there.

This method bypasses the Windows lock screen restriction that limits OS-level input injection, such as SendInput and SendKey. Because input events are dispatched directly inside the game process, we recommend using the same handling path regardless of whether the system is locked or in a normal state.

In other words, after enabling the Play without unlocking the lock screen feature, implement the game to receive all input events delivered through this callback and forward them to the game's internal input system. This ensures consistent input handling and remote play behavior regardless of the lock screen state.

  • Unity: Dispatch with InputSystem.QueueEvent or a custom input manager.
  • Unreal Engine: Dispatch with Slate events such as FSlateApplication::OnKeyDown / OnMouseButtonDown, or use the game's custom input manager.

Background rendering and audio handling guide for lock-screen environments

To use Remote Play in a Windows lock screen environment, the game must be able to operate normally while in the background. Most game engines stop rendering, limit frames, or pause audio playback to reduce CPU usage when they lose focus or enter the background. To maintain remote streaming normally, configure the game process to keep running in the background.

The game must check the Remote Play connection status to determine whether a remote user is connected. The recommended behavior is as follows.

Connection status Recommended behavior
Not connected Keep the existing game policy. Rendering and audio may stop when the game enters the background.
Connected Continue rendering while in the background. Continue audio output while in the background.

You can determine the connection status through the status event callback (eventType: "Event", value REMOTE_PLAY_CONNECTED / REMOTE_PLAY_DISCONNECTED).

2. Keep background rendering active

The rendering loop must keep running so that Remote Play can capture the screen even when Windows is locked. Check items such as the following.

  • Do not stop frame updates.
  • Keep the render loop running.
  • Keep camera rendering active.
  • Keep the UI updated.
  • Review background frame limit policies.

Warning

If rendering stops in the background, Remote Play may continue sending the last screen or display a black screen.

3. Keep background audio output active

Remote Play captures audio output from the game process and delivers it to the remote player. Therefore, disable background audio blocking policies such as the following.

  • Pausing audio on focus lost
  • Stopping the audio engine when the window is deactivated
  • Enabling background mute

Warning

If audio output stops in the background, the remote player cannot hear the game sound.

Engine-specific checks and notes

Unity

Unity may limit updates by default when the game enters the background. When using the lock-screen Remote Play feature, we recommend enabling background execution as follows.

Application.runInBackground = true;

If custom logic stops audio when focus is lost, handle it as an exception based on the Remote Play connection status.

Unreal Engine

In Unreal Engine projects, check whether any settings limit tick, rendering, or audio processing when focus is lost. We especially recommend checking the following items.

  • Whether background tick works
  • Whether pause handling is applied on focus lost
  • Whether the Audio Mixer works
  • Background FPS limit policies

While connected to Remote Play, implement the game so that the normal game loop is maintained even in the background.

  1. The user switches to the Windows lock screen.
  2. The Remote Play client connects.
  3. The game detects the connection status and keeps background rendering and audio output active.
    • Game rendering continues.
    • Game audio output continues.
  4. The Remote Play Plugin captures and sends the screen and audio normally.
  5. The remote user receives the game screen and sound in real time.
  6. Input events are delivered to the game's internal input system through the Remote Play input Control callback.

Required check summary

For Remote Play to work normally in a lock screen environment, both of the following conditions must be met.

  • Enable the Play without unlocking the lock screen feature in the Remote Play settings of Hive Console so that input events are delivered to the game's internal input system.
  • Keep rendering and audio processing active in the background while Remote Play is connected.

If either condition is not met, Remote Play may not work normally due to issues such as a frozen screen, audio output errors, or difficulty controlling the game.