Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - aydiler/kb-layout-daemon: Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux) · GitHub
Skip to content

Repository files navigation

kb-layout-daemon

A lightweight daemon that automatically switches keyboard layout based on which physical keyboard you're typing on.

Perfect for users with multiple keyboards who want different layouts for each (e.g., English on one keyboard, German on another).

Features

  • Monitors multiple keyboards simultaneously
  • Two modes:
    • Grab mode: Correct layout on first keystroke (~1ms latency)
    • Passive mode: Zero latency (first key after switch may use old layout)
  • Toggle between modes via D-Bus or KDE Plasma widget
  • Native D-Bus integration with KDE Plasma
  • Minimal resource usage (~2MB RAM, <1% CPU)
  • Single static binary, no runtime dependencies
  • Configurable via TOML file
  • Systemd user service included
  • KDE Plasma widget to toggle modes (KDE Store)

Requirements

  • Linux with evdev support
  • KDE Plasma (Wayland or X11)
  • User must be in the input group

Installation

From source

git clone https://github.com/aydiler/kb-layout-daemon
cd kb-layout-daemon
cargo build --release
sudo cp target/release/kb-layout-daemon /usr/local/bin/

Arch Linux (AUR)

yay -S kb-layout-daemon-git

From crates.io

cargo install kb-layout-daemon

Setup

  1. Add yourself to the input group:

    sudo usermod -aG input $USER

    Then log out and back in.

  2. Create config file at ~/.config/kb-layout-daemon/config.toml:

    # Mode: "grab" (correct first key) or "passive" (zero latency)mode = "grab"
    [[keyboards]]
    name = "Lofree"layout_index = 1layout_name = "English (US)"
    [[keyboards]]
    name = "CHERRY"layout_index = 0layout_name = "German"

    The layout_index corresponds to the order in KDE's keyboard layout settings (0-based).

  3. Install the systemd service:

    mkdir -p ~/.config/systemd/user
    cp kb-layout-daemon.service ~/.config/systemd/user/
    systemctl --user enable --now kb-layout-daemon

KDE Plasma Widget

A panel widget is included to toggle between Grab and Passive modes.

Install from KDE Store

KB Layout Mode Toggle on KDE Store

Or install manually:

cp -r widget ~/.local/share/plasma/plasmoids/org.kblayout.toggle

Then right-click your panel → "Add Widgets" → search for "KB Layout Mode" → drag to panel.

  • Green "KB": Grab mode (correct first key, ~1ms latency)
  • Red "GM": Passive/Game mode (zero latency)

Click to toggle between modes.

D-Bus Interface

Control the daemon via D-Bus at org.kblayout.Daemon:

# Get current mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.GetMode
# Set mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"# Toggle mode
dbus-send --session --print-reply --dest=org.kblayout.Daemon \
/org/kblayout/Daemon org.kblayout.Daemon.ToggleMode

Configuration

The config file uses TOML format:

FieldDescription
modeInitial mode: "grab" or "passive" (default: "grab")

Each [[keyboards]] section defines a keyboard to monitor:

FieldDescription
nameSubstring to match in the device name (case-insensitive)
layout_indexKDE layout index (0-based, matches order in System Settings)
layout_nameHuman-readable name for logging

To find your keyboard names:

cat /proc/bus/input/devices | grep -A 4 "Name="

How It Works

  1. On startup, scans /dev/input/event* for keyboards matching configured names
  2. Monitors all keyboards using evdev
  3. On keypress, checks if layout switch is needed
  4. Switches layout via D-Bus call to org.kde.keyboard

Grab mode: Grabs exclusive access to keyboards, intercepts all input, switches layout, then forwards events through a virtual keyboard. This ensures the first keystroke uses the correct layout.

Passive mode: Monitors keyboards without grabbing. Layout switches after detecting a keypress, so the first key may use the old layout. Zero added latency.

Troubleshooting

"No keyboards found"

  • Ensure you're in the input group: groups | grep input
  • Log out and back in after adding yourself to the group

Layout not switching

  • Check KDE has multiple layouts configured
  • Verify layout_index matches your KDE layout order
  • Check logs: journalctl --user -u kb-layout-daemon -f

Keys not working in Grab mode

  • Try switching to Passive mode: dbus-send --session --print-reply --dest=org.kblayout.Daemon /org/kblayout/Daemon org.kblayout.Daemon.SetMode string:"passive"
  • Report the issue with your keyboard model

License

MIT

About

Auto-switch keyboard layout based on which physical keyboard is used (KDE/Linux)

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages