Skip to content

Input configuration

Finalspace edited this page May 29, 2026 · 2 revisions

Table of Contents

Overview

The input subsystem is split into three independent sources - Keyboard, Mouse and Gamepad - and into multiple backends per platform (XInput, Win32 keyboard/mouse, X11 keyboard/mouse, Linux Joystick, etc.).

Sources are selected through the fplInitFlags passed to fplPlatformInit, while backends are selected through the fplInputSettings structure or compiled out via preprocessor switches.

Input can be used with or without a window. When no window is present, the backends operate in detached mode and the application drives the subsystem itself - see Using input without a window.

Selecting input sources via init flags

Each input source has its own flag in fplInitFlags :

The composite fplInitFlags_Input is the bitwise OR of all three. fplInitFlags_All also enables every input source.

fplInitFlags_Window implies fplInitFlags_Keyboard and fplInitFlags_Mouse, so windowed applications keep working without changes. Gamepads must always be requested explicitly with fplInitFlags_Gamepad.

// Console-only application that polls a gamepad
 settings;
(&settings);
if ((, &settings)) {
    // ...
}

Selecting input backends

A backend is a concrete implementation that talks to the operating system (XInput, /dev/input/jsX, X11, etc.). Several backends can be active at once - for example XInput and DirectInput cover different gamepad classes on Windows.

By default all backends compiled into the build are enabled. To restrict which backends are used at runtime, populate fplInputSettings::enabledBackends with fplInputBackendMaskEnable / fplInputBackendMaskDisable :

 settings;
(&settings);
 *backends = &settings..;

// Use only XInput for gamepads
 *backends = (){0};
(backends, );
(backends, );

if ((, &settings)) {
    // ...
}

Bits for backends that are not compiled in (or not supported on the current platform) are silently ignored at init time.

To inspect which backends the build supports use fplGetInputBackendSupport :

 supports[16];
uint32_t count = (supports, (supports));
for (uint32_t i = 0; i < count; ++i) {
    // supports[i].name, supports[i].type, supports[i].supportedSources, ...
}

A single backend descriptor can be looked up via fplGetInputBackendSupportByType.

Enumerating input devices

After fplPlatformInit, the input subsystem maintains a list of devices visible to all enabled backends. Use fplGetInputDevices to enumerate them, optionally filtered by source:

 devices[];
uint32_t count = (, devices, (devices));
for (uint32_t i = 0; i < count; ++i) {
     *dev = &devices[i];
    // dev->name, dev->backend, dev->connection, dev->state.gamepad, ...
}

Each device exposes a stable fplInputDeviceGuid that survives reconnects on the same backend slot. Use fplFindInputDevice to look up a single device by GUID later.

Convenience wrappers fplGetKeyboardDevices, fplGetMouseDevices, fplGetGamepadDevices return only devices of the requested source type.

Using input without a window

When fplInitFlags_Window is not set (or fplInputSettings::detachFromWindow is enabled), the keyboard and mouse backends initialize in detached mode:

  • On Windows the Win32 backend creates a hidden HWND_MESSAGE window for raw input.
  • On Linux the X11 backend opens its own Display connection.

The application is responsible for driving the subsystem each frame, since there is no window event loop. Either of the following works:

  • Call fplUpdateInputDevices once per frame; gamepad connect/disconnect/state events are pushed to the internal event queue and polled state is refreshed.
  • Call fplPollEvent / fplPollEvents in a loop - they call into the input system internally when no window is present.
while (running) {
    ();

     pads;
    if ((&pads)) {
        // ...
    }
    (16);
}

See the FPL_ConsoleGamepad demo for a complete FPL_NO_WINDOW example.

Controller detection frequency

Use fplGamepadSettings::detectionFrequency (accessed via fplInputSettings::gamepad) to change the frequency (in milliseconds) at which gamepad backends scan for newly connected or removed controllers.

Setting this to zero forces a scan every frame, which is not recommended due to its cost. The default value is suitable for most games.

Disable input events

Set fplInputSettings::disabledEvents to true to suppress all input events. Polling functions like fplPollKeyboardState, fplPollMouseState and fplPollGamepadStates continue to work regardless of this flag.

Compile-time switches

Define FPL_NO_INPUT before the implementation include to remove the entire input subsystem. To remove a single backend without disabling the rest, define one of:

  • FPL_NO_INPUT_XINPUT
  • FPL_NO_INPUT_DINPUT
  • FPL_NO_INPUT_WIN32
  • FPL_NO_INPUT_X11
  • FPL_NO_INPUT_LINUX_JOYSTICK

See Compiler Options for the full list.

Initialize to default settings

If needed you can use fplSetDefaultInputSettings to reset the fplInputSettings structure to a default state.

You don't have to use this call if you have already initialized the fplSettings structure via fplMakeDefaultSettings or fplSetDefaultSettings.

Final Platform Layer

Pages

Topics

Data Structures

Clone this wiki locally