Skip to content

keyboard, hyprland/ipc: keyboard layout handling - #923

Open
brainrom wants to merge 3 commits into
quickshell-mirror:masterfrom
brainrom:feat-keyboard-layout
Open

keyboard, hyprland/ipc: keyboard layout handling#923
brainrom wants to merge 3 commits into
quickshell-mirror:masterfrom
brainrom:feat-keyboard-layout

Conversation

@brainrom

@brainrom brainrom commented Jul 24, 2026

Copy link
Copy Markdown

Adds keyboard layout support to the Hyprland backend, inspired by the equivalent Waybar module.

Problem

QuickShell had no way to query or switch keyboard layouts under Hyprland or any other environment. Users who wanted a layout indicator or switcher had to resort to external tools.

Solution

Two new components:

Quickshell.Keyboard (src/keyboard/) — A compositor-agnostic KeyboardLayout data class that resolves xkb layout names via libxkbregistry. Can be reused by future compositor backends (Sway, etc.) since the layout model is the same regardless of the compositor.

HyprlandKeyboard (Quickshell.Hyprland._Ipc) — Hyprland-specific keyboard device representation. Maintains an ObjectModel<KeyboardLayout> of available layouts, tracks the active one, and exposes cycleLayout() / switchToLayout(index) for switching.

Commits

The change is split into three commits, each independently reviewable:

Commit Scope
keyboard: new module for keyboard layouts (data class) New Quickshell.Keyboard module with the shared KeyboardLayout class and xkbregistry resolution logic.
hyprland/ipc: make dispatch prefix in dispatch() optional Enables sending raw Hyprland commands (like switchxkblayout) without the dispatch prefix, mirroring hyprctl behavior, since switchxkblayout isn't available through Hyprland's Lua/legacy dispatcher.
hyprland/ipc: keyboard layout handling HyprlandKeyboard device tracking, j/devices parsing, activelayout event handling, and layout switching via switchxkblayout.

QML API additions

import Quickshell.Hyprland

Hyprland.keyboards              // model of HyprlandKeyboard
Hyprland.activeKeyboard         // last device that sent activelayout
Hyprland.activeKeyboardChanged  // signal

// HyprlandKeyboard
keyboard.name                   // device name
keyboard.activeLayout           // KeyboardLayout*
keyboard.activeLayoutIndex      // int
keyboard.availableLayouts       // model of KeyboardLayout
keyboard.cycleLayout()
keyboard.switchToLayout(index)

// KeyboardLayout (Quickshell.Keyboard)
layout.shortName                // "us" | "de" | "fr" | "ru" | "ua"
layout.variant                  // "intl", ""
layout.shortDescription         // "English" | "German" | "French" | "Russian" | "Ukrainian"
layout.fullName                 // "English (US, intl., with dead keys)", etc.

Checklist

  • clang-format passes on all new/modified files
  • Builds with default options
  • module.md for new module added, new files added to corresponding module.md, docs tested

@brainrom
brainrom force-pushed the feat-keyboard-layout branch from c2468c1 to 2dfe82d Compare July 24, 2026 17:55
brainrom added 2 commits July 24, 2026 21:11
Some dispatchers doesn't have Lua equivalents, so the don't get
through Hyprland Lua/legacy dispatcher. This allows to mimick
hyprctl behvaior.
@brainrom
brainrom force-pushed the feat-keyboard-layout branch from 2dfe82d to 63f7623 Compare July 24, 2026 18:13
@brainrom
brainrom force-pushed the feat-keyboard-layout branch from 63f7623 to d122fb2 Compare July 24, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant