aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/island/Keyboard.qml
blob: 1cbe9bc074f358f74d563f0fd240ef6f04fa9f90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

pragma Singleton

import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import QtQuick
import "Logic.js" as Logic

// The layout of whichever keyboard Hyprland marks main. Resolved per event,
// never cached: the same keyboard is a different device over USB and over
// its dongle, which is what broke wb-lang's hardcoded device name.
Singleton {
    id: root

    property string keymap: ""
    readonly property string flag: Logic.flagFor(keymap)

    readonly property string mainKeyboard:
        "hyprctl devices -j | jq -r '.keyboards[] | select(.main) | .name'"

    Process {
        id: query
        running: true
        command: ["sh", "-c",
            "hyprctl devices -j | jq -r '.keyboards[] | select(.main) | .active_keymap'"]
        stdout: StdioCollector { onStreamFinished: root.keymap = text.trim() }
    }

    Process { id: switcher }

    function refresh() {
        query.running = false;
        query.running = true;
    }

    // dir is "next" or "prev", from the caller's own literal, never user text.
    function cycle(dir) {
        switcher.command = ["sh", "-c",
            `hyprctl switchxkblayout "$(${root.mainKeyboard})" ${dir}`];
        switcher.running = false;
        switcher.running = true;
    }

    Connections {
        target: Hyprland
        function onRawEvent(event) {
            if (event.name === "activelayout") root.refresh();
        }
    }
}