- PR1: gamescope detection at boot — X11 backend, scale 1, kiosk fullscreen; tray + miniplayer suppressed (click-offset fix). - PR2: full keyboard navigation for the kiosk (3 zones, focus ring, scroll-into-view; typing never navigates). - PR3: native gamepad via gilrs — D-pad/stick/A/B to synthetic Slint keys with hysteresis, repeat and debounce; B suppresses Escape while a text field is focused (closes the Steam OSK). - PR4: Steam OSK via the steam://open/keyboard deeplink on text focus. - PR5: scripts/qbz-add-to-steam (stdlib-only, 19/19 unit tests) with artwork assets + pure-gamepad controller layout. Spec: qbz-nix-docs/steam-deck/STEAM_DECK_GAME_MODE_PLAN.md km
482 lines
7.0 KiB
Plaintext
482 lines
7.0 KiB
Plaintext
// QBZ — Steam Deck (neptune) controller layout, seeded by qbz-add-to-steam.
|
|
//
|
|
// Based on the stock Steam "Gamepad" template (controller_neptune_gamepad_joystick.vdf,
|
|
// Steam client 2026-06) — PURE GAMEPAD: only virtual X360 pad output, NO keyboard
|
|
// or mouse emulation, so QBZ's own gilrs gamepad thread is the single input source
|
|
// (see qbz-nix-docs/steam-deck/STEAM_DECK_GAME_MODE_PLAN.md, PR 3/PR 5).
|
|
//
|
|
// The one deviation from the template: Y is bound to Steam's "Show Keyboard"
|
|
// system action (controller_action SHOW_KEYBOARD — token verified in
|
|
// steamclient.so) as a manual OSK fallback next to the steam://open/keyboard
|
|
// deeplink. Y therefore does NOT emit an XInput button.
|
|
//
|
|
// TODO(verify-on-hardware): this file is authored from the known exported
|
|
// config format, not yet exported/validated by the Deck UI. Do the one-time
|
|
// validation from the plan: load it on a real Deck in Game Mode, confirm the
|
|
// layout applies on first launch (configset_<serial>.vdf path) and that Y
|
|
// opens the OSK, then re-export and replace this file if the format drifted.
|
|
"controller_mappings"
|
|
{
|
|
"version" "3"
|
|
"title" "QBZ Kiosk (gamepad + Y=keyboard)"
|
|
"description" "Pure gamepad layout for the QBZ kiosk: D-pad/stick navigate, A activates, B goes back, Y shows the Steam keyboard. No keyboard/mouse emulation."
|
|
"controller_type" "controller_neptune"
|
|
"major_revision" "0"
|
|
"minor_revision" "0"
|
|
"group"
|
|
{
|
|
"id" "0"
|
|
"mode" "four_buttons"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"button_a"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button A, Activate, , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_b"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button B, Back, , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_x"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button X, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_y"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "controller_action SHOW_KEYBOARD, Show Keyboard, , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "1"
|
|
"mode" "dpad"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"dpad_north"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button dpad_up, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"dpad_south"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button dpad_down, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"dpad_east"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button dpad_right, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"dpad_west"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button dpad_left, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "2"
|
|
"mode" "joystick_move"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"click"
|
|
{
|
|
"activators"
|
|
{
|
|
"Soft_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button JOYSTICK_RIGHT, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "3"
|
|
"mode" "joystick_move"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"click"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button JOYSTICK_LEFT, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"settings"
|
|
{
|
|
"deadzone_inner_radius" "7199"
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "4"
|
|
"mode" "trigger"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
}
|
|
"settings"
|
|
{
|
|
"output_trigger" "1"
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "5"
|
|
"mode" "trigger"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
}
|
|
"settings"
|
|
{
|
|
"output_trigger" "2"
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "7"
|
|
"mode" "switches"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"button_escape"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button start, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_menu"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button select, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"left_bumper"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button shoulder_left, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"right_bumper"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button shoulder_right, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_back_left"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_back_right"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_back_left_upper"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"button_back_right_upper"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "8"
|
|
"mode" "joystick_move"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"click"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button JOYSTICK_RIGHT, , , "
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"group"
|
|
{
|
|
"id" "9"
|
|
"mode" "dpad"
|
|
"name" ""
|
|
"description" ""
|
|
"inputs"
|
|
{
|
|
"dpad_north"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button DPAD_UP, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"dpad_south"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button DPAD_DOWN, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"dpad_east"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button DPAD_RIGHT, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"dpad_west"
|
|
{
|
|
"activators"
|
|
{
|
|
"Full_Press"
|
|
{
|
|
"bindings"
|
|
{
|
|
"binding" "xinput_button DPAD_LEFT, , , "
|
|
}
|
|
"settings"
|
|
{
|
|
"haptic_intensity" "1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"settings"
|
|
{
|
|
"requires_click" "0"
|
|
}
|
|
}
|
|
"preset"
|
|
{
|
|
"id" "0"
|
|
"name" "Default"
|
|
"group_source_bindings"
|
|
{
|
|
"7" "switch active"
|
|
"0" "button_diamond active"
|
|
"1" "left_trackpad active"
|
|
"2" "right_trackpad active"
|
|
"3" "joystick active"
|
|
"4" "left_trigger active"
|
|
"5" "right_trigger active"
|
|
"8" "right_joystick active"
|
|
"9" "dpad active"
|
|
}
|
|
}
|
|
"settings"
|
|
{
|
|
"left_trackpad_mode" "0"
|
|
"right_trackpad_mode" "0"
|
|
}
|
|
}
|