← All solutions
Caelestia Shell · Input Devices

Locking laptop keyboard inputs for cleaning
without powering down

Notebook cleaning usually requires shutting down the machine or locking the screen, which still results in accidental keystrokes spamming the password field. I built a native Caelestia Shell utility to disable physical keyboards temporarily while keeping the system running.

Arch Linux Hyprland IPC Quickshell / QML
The Challenge

Cleaning my laptop keyboard has always been a minor annoyance. I either had to turn the entire machine off (slow and disruptive), or lock the session and clean it anyway. The latter meant that keys pressed during cleaning would wake the monitor, spam random characters into the lock screen password prompt, and sometimes trigger security lockouts or run system macros if function keys were hit.

I wanted a way to press a single button, have the desktop remain completely visible, disable all physical keyboard hardware inputs temporarily, and enable them back using my mouse or touchpad once the keyboard was clean.

How It Works

Hyprland allows modifying input configuration dynamically via its IPC socket using the device keyword. I can disable or enable specific devices on-the-fly using commands like:

bash
hyprctl keyword "device[at-translated-set-2-keyboard]:enabled" false

By querying all connected keyboards programmatically and generating this rule for each of them, I could block all physical keyboard typing without affecting my mouse, touchpad, or overall UI rendering.

Implementation Steps

Here is how I wired the solution inside my Caelestia Shell configuration:

Create the KeyboardLock Singleton Service

I created a new Singleton service in Quickshell that queries the keyboard list via hyprctl devices -j and toggles the enabled state of each physical keyboard device.

KeyboardLock.qml
pragma Singleton

import QtQuick
import Quickshell

Singleton {
    id: root
    property bool enabled: false

    onEnabledChanged: {
        if (enabled) {
            Quickshell.execDetached([
                "bash", "-c", 
                "hyprctl devices -j | jq -r '.keyboards[].name' | " +
                "while read -r kb; do hyprctl keyword \"device[$kb]:enabled\" false; done"
            ]);
            Toaster.toast(qsTr("Keyboard Locked"), qsTr("All keyboard inputs are disabled."), "keyboard");
        } else {
            Quickshell.execDetached([
                "bash", "-c", 
                "hyprctl devices -j | jq -r '.keyboards[].name' | " +
                "while read -r kb; do hyprctl keyword \"device[$kb]:enabled\" true; done"
            ]);
            Toaster.toast(qsTr("Keyboard Unlocked"), qsTr("Keyboard inputs enabled."), "keyboard");
        }
    }
}

Add the Toggle button to Quick Settings

I added a toggle card in Toggles.qml linking to this service, rendering a keyboard icon. Since mouse inputs are untouched, clicking the toggle again with the mouse or touchpad seamlessly restores physical keyboard inputs.

Solve the Lockscreen Deadlock

During testing, I found a dangerous deadlock: if I left the keyboard locked for too long, my system's idle monitor daemon would think I'm inactive and trigger the desktop lock screen automatically. With the lock screen active and the physical keyboard disabled, I could no longer type my password to unlock the session!

To solve this, I modified the idle monitor wrapper in my shell config to temporarily suspend screen locking actions while the keyboard lock is active.

IdleMonitors.qml
// Inhibit automatic screen locking while KeyboardLock is enabled
readonly property bool enabled: (!GlobalConfig.general.idle.inhibitWhenAudio || !Players.list.some(p => p.isPlaying)) && !KeyboardLock.enabled
Because hyprctl devices -j lists all devices categorized under keyboards, virtual keyboard drivers (such as Bluetooth headsets registers) and peripheral mouse buttons may also be toggled. Ensure your pointing device (touchpad/mouse) is active to toggle the mode off.