From c5b6c7a8091e4dfae1f1a979e11ba0423d2b5111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?m=C3=BCde?= Date: Sun, 30 Aug 2026 20:38:31 +0200 Subject: [PATCH] add on screen keyboard to lpt2 --- homeConfigurations/muede/niri.nix | 840 ++++++++++++++++-------------- 1 file changed, 439 insertions(+), 401 deletions(-) diff --git a/homeConfigurations/muede/niri.nix b/homeConfigurations/muede/niri.nix index 9fe1c66..a1385c8 100644 --- a/homeConfigurations/muede/niri.nix +++ b/homeConfigurations/muede/niri.nix @@ -2,436 +2,474 @@ pkgs, config, lib, + device, ... }: { - config = { - home.sessionVariables.NIXOS_OZONE_WL = "1"; - home.packages = with pkgs; [ - xwayland-satellite - ]; - - # Qt theming (QT_STYLE_OVERRIDE) is deliberately disabled, here and in - # nixosModules/stylix.nix. Qt >= 6.5 resolves QT_STYLE_OVERRIDE as a - # Qt Quick Controls style and crashes any QML app when no such QML module - # exists: with QT_STYLE_OVERRIDE=adwaita-dark, polkit-kde-agent segfaulted - # on every auth request, breaking polkit under niri. adwaita-qt only ships - # a Qt5 widget style (archived upstream), so Qt6 apps never got themed - # anyway. If a specific Qt5 app needs the style back, set it per app: - # QT_STYLE_OVERRIDE=adwaita-dark - # or for a systemd unit: Environment=QT_STYLE_OVERRIDE=adwaita-dark. - # A future alternative is stylix's qtct/kvantum platform, once - # https://github.com/nix-community/home-manager/issues/6565 is resolved. - stylix.targets.qt.enable = false; - - services.wpaperd.enable = true; - - programs.niri.settings = { - outputs = { - "BOE 0x0A3B Unknown" = { - scale = 1.0; - variable-refresh-rate = true; - }; - "Dell Inc. DELL P2719H 39VHKS2" = { - scale = 1.0; - }; - "LG Electronics LG ULTRAGEAR 106NTYT27386" = { - scale = 1.0; - variable-refresh-rate = true; - }; - }; - - layout = - let - colors = config.lib.stylix.colors.withHashtag; - pink_light = colors.base0A; - pink_dark = colors.base0C; - blue_light = colors.base0B; - blue_dark = colors.base09; - gradient-common = { - angle = 90; - in' = "oklab"; - }; - gradient-active = gradient-common // { - from = pink_light; - to = blue_light; - }; - gradient-inactive = gradient-common // { - from = pink_dark; - to = blue_dark; - }; - gradient-urgent = gradient-common // { - from = pink_dark; - to = pink_light; - }; - gap-size = 6; - in - { - background-color = "transparent"; - gaps = gap-size; - border = { - enable = true; - width = gap-size / 2; - active.gradient = gradient-active; - inactive.gradient = gradient-inactive; - urgent.gradient = gradient-urgent; - }; - focus-ring = { - enable = false; - active.gradient = gradient-active; - inactive.gradient = gradient-inactive; - urgent.gradient = gradient-urgent; - }; - shadow = { - enable = false; - color = "white"; - inactive-color = pink_dark; - draw-behind-window = true; - spread = 5; - softness = 10; - offset = { - x = 0; - y = 0; - }; - }; - insert-hint = { - enable = true; - display.color = pink_dark; - }; - struts = - let - strut-inset = 4; - in - { - left = strut-inset; - right = strut-inset; - top = strut-inset; - bottom = strut-inset; - }; - tab-indicator = { - place-within-column = true; - active.gradient = gradient-inactive; - inactive.gradient = gradient-inactive; - urgent.gradient = gradient-inactive; - }; - }; - - cursor.theme = "Adwaita"; - - input = { - touchpad.tap = true; - keyboard = { - xkb = { - layout = "de"; - options = "compose:caps"; - }; - numlock = true; - }; - }; - - #prefer-no-csd = true; - hotkey-overlay.skip-at-startup = true; - - window-rules = [ - { - clip-to-geometry = true; - geometry-corner-radius = - let - radius = 15.; - in - { - top-left = radius; - bottom-left = radius; - top-right = radius; - bottom-right = radius; - }; - } - { - matches = [ - { - app-id = "steam"; - title = "^notificationtoasts_\\d+_desktop$"; - } - ]; - default-floating-position = { - x = 10; - y = 10; - relative-to = "bottom-right"; - }; - } + config = lib.mkMerge [ + { + home.sessionVariables.NIXOS_OZONE_WL = "1"; + home.packages = with pkgs; [ + xwayland-satellite ]; - # defaults taken from https://github.com/sodiboo/niri-flake/issues/483 - binds = { - # Keys consist of modifiers separated by + signs, followed by an XKB key name - # in the end. To find an XKB name for a particular key, you may use a program - # like wev. - # - # "Mod" is a special modifier equal to Super when running on a TTY, and to Alt - # when running as a winit window. - # - # Most actions that you can bind here can also be invoked programmatically with - # `niri msg action do-something`. + # Qt theming (QT_STYLE_OVERRIDE) is deliberately disabled, here and in + # nixosModules/stylix.nix. Qt >= 6.5 resolves QT_STYLE_OVERRIDE as a + # Qt Quick Controls style and crashes any QML app when no such QML module + # exists: with QT_STYLE_OVERRIDE=adwaita-dark, polkit-kde-agent segfaulted + # on every auth request, breaking polkit under niri. adwaita-qt only ships + # a Qt5 widget style (archived upstream), so Qt6 apps never got themed + # anyway. If a specific Qt5 app needs the style back, set it per app: + # QT_STYLE_OVERRIDE=adwaita-dark + # or for a systemd unit: Environment=QT_STYLE_OVERRIDE=adwaita-dark. + # A future alternative is stylix's qtct/kvantum platform, once + # https://github.com/nix-community/home-manager/issues/6565 is resolved. + stylix.targets.qt.enable = false; - # Mod-Shift-/, which is usually the same as Mod-?, - # shows a list of important hotkeys. - "Mod+Shift+Numbersign".action.show-hotkey-overlay = { }; + services.wpaperd.enable = true; - # Suggested binds for running programs: terminal, app launcher, screen locker. - "Mod+T".action.spawn = "${lib.getBin pkgs.gnome-console}/bin/kgx"; - "Mod+D".action.spawn = "${lib.getBin config.programs.fuzzel.package}/bin/fuzzel"; - - # You can also use a shell. Do this if you need pipes, multiple commands, etc. - # Note: the entire command goes as a single argument in the end. - # Mod+T { spawn "bash" "-c" "notify-send hello && exec alacritty"; } - - # Example volume keys mappings for PipeWire & WirePlumber. - # The allow-when-locked=true property makes them work even when the session is locked. - "XF86AudioRaiseVolume" = { - allow-when-locked = true; - action.spawn = [ - "wpctl" - "set-volume" - "@DEFAULT_AUDIO_SINK@" - "0.1+" - ]; - }; - "XF86AudioLowerVolume" = { - allow-when-locked = true; - action.spawn = [ - "wpctl" - "set-volume" - "@DEFAULT_AUDIO_SINK@" - "0.1-" - ]; - }; - "XF86AudioMute" = { - allow-when-locked = true; - action.spawn = [ - "wpctl" - "set-mute" - "@DEFAULT_AUDIO_SINK@" - "toggle" - ]; - }; - "XF86AudioMicMute" = { - allow-when-locked = true; - action.spawn = [ - "wpctl" - "set-mute" - "@DEFAULT_AUDIO_SOURCE@" - "toggle" - ]; - }; - "XF86MonBrightnessUp" = { - allow-when-locked = true; - action.spawn = [ - "brightnessctl" - "set" - "5%+" - ]; - }; - "XF86MonBrightnessDown" = { - allow-when-locked = true; - action.spawn = [ - "brightnessctl" - "set" - "5%-" - ]; + programs.niri.settings = { + outputs = { + "BOE 0x0A3B Unknown" = { + scale = 1.0; + variable-refresh-rate = true; + }; + "Dell Inc. DELL P2719H 39VHKS2" = { + scale = 1.0; + }; + "LG Electronics LG ULTRAGEAR 106NTYT27386" = { + scale = 1.0; + variable-refresh-rate = true; + }; }; - "Mod+Q".action.close-window = { }; + layout = + let + colors = config.lib.stylix.colors.withHashtag; + pink_light = colors.base0A; + pink_dark = colors.base0C; + blue_light = colors.base0B; + blue_dark = colors.base09; + gradient-common = { + angle = 90; + in' = "oklab"; + }; + gradient-active = gradient-common // { + from = pink_light; + to = blue_light; + }; + gradient-inactive = gradient-common // { + from = pink_dark; + to = blue_dark; + }; + gradient-urgent = gradient-common // { + from = pink_dark; + to = pink_light; + }; + gap-size = 6; + in + { + background-color = "transparent"; + gaps = gap-size; + border = { + enable = true; + width = gap-size / 2; + active.gradient = gradient-active; + inactive.gradient = gradient-inactive; + urgent.gradient = gradient-urgent; + }; + focus-ring = { + enable = false; + active.gradient = gradient-active; + inactive.gradient = gradient-inactive; + urgent.gradient = gradient-urgent; + }; + shadow = { + enable = false; + color = "white"; + inactive-color = pink_dark; + draw-behind-window = true; + spread = 5; + softness = 10; + offset = { + x = 0; + y = 0; + }; + }; + insert-hint = { + enable = true; + display.color = pink_dark; + }; + struts = + let + strut-inset = 4; + in + { + left = strut-inset; + right = strut-inset; + top = strut-inset; + bottom = strut-inset; + }; + tab-indicator = { + place-within-column = true; + active.gradient = gradient-inactive; + inactive.gradient = gradient-inactive; + urgent.gradient = gradient-inactive; + }; + }; - "Mod+Left".action.focus-column-left = { }; - "Mod+Down".action.focus-window-down = { }; - "Mod+Up".action.focus-window-up = { }; - "Mod+Right".action.focus-column-right = { }; + cursor.theme = "Adwaita"; - "Mod+Ctrl+Left".action.move-column-left = { }; - "Mod+Ctrl+Down".action.move-window-down = { }; - "Mod+Ctrl+Up".action.move-window-up = { }; - "Mod+Ctrl+Right".action.move-column-right = { }; - - # Alternative commands that move across workspaces when reaching - # the first or last window in a column. - # Mod+J { focus-window-or-workspace-down; } - # Mod+K { focus-window-or-workspace-up; } - # Mod+Ctrl+J { move-window-down-or-to-workspace-down; } - # Mod+Ctrl+K { move-window-up-or-to-workspace-up; } - - "Mod+Home".action.focus-column-first = { }; - "Mod+End".action.focus-column-last = { }; - "Mod+Ctrl+Home".action.move-column-to-first = { }; - "Mod+Ctrl+End".action.move-column-to-last = { }; - - "Mod+Shift+Left".action.focus-monitor-left = { }; - "Mod+Shift+Down".action.focus-monitor-down = { }; - "Mod+Shift+Up".action.focus-monitor-up = { }; - "Mod+Shift+Right".action.focus-monitor-right = { }; - - "Mod+Shift+Ctrl+Left".action.move-column-to-monitor-left = { }; - "Mod+Shift+Ctrl+Down".action.move-column-to-monitor-down = { }; - "Mod+Shift+Ctrl+Up".action.move-column-to-monitor-up = { }; - "Mod+Shift+Ctrl+Right".action.move-column-to-monitor-right = { }; - - # Alternatively, there are commands to move just a single window: - # Mod+Shift+Ctrl+Left { move-window-to-monitor-left; } - # ... - - # And you can also move a whole workspace to another monitor: - # Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; } - # ... - - "Mod+Page_Down".action.focus-workspace-down = { }; - "Mod+Page_Up".action.focus-workspace-up = { }; - "Mod+U".action.focus-workspace-down = { }; - "Mod+I".action.focus-workspace-up = { }; - "Mod+Ctrl+Page_Down".action.move-column-to-workspace-down = { }; - "Mod+Ctrl+Page_Up".action.move-column-to-workspace-up = { }; - "Mod+Ctrl+U".action.move-column-to-workspace-down = { }; - "Mod+Ctrl+I".action.move-column-to-workspace-up = { }; - - # Alternatively, there are commands to move just a single window: - # Mod+Ctrl+Page_Down { move-window-to-workspace-down; } - # ... - - "Mod+Shift+Page_Down".action.move-workspace-down = { }; - "Mod+Shift+Page_Up".action.move-workspace-up = { }; - "Mod+Shift+U".action.move-workspace-down = { }; - "Mod+Shift+I".action.move-workspace-up = { }; - - # You can bind mouse wheel scroll ticks using the following syntax. - # These binds will change direction based on the natural-scroll setting. - # - # To avoid scrolling through workspaces really fast, you can use - # the cooldown-ms property. The bind will be rate-limited to this value. - # You can set a cooldown on any bind, but it's most useful for the wheel. - "Mod+WheelScrollDown" = { - cooldown-ms = 150; - action.focus-workspace-down = { }; - }; - "Mod+WheelScrollUp" = { - cooldown-ms = 150; - action.focus-workspace-up = { }; - }; - "Mod+Ctrl+WheelScrollDown" = { - cooldown-ms = 150; - action.move-column-to-workspace-down = { }; - }; - "Mod+Ctrl+WheelScrollUp" = { - cooldown-ms = 150; - action.move-column-to-workspace-up = { }; + input = { + touchpad.tap = true; + keyboard = { + xkb = { + layout = "de"; + options = "compose:caps"; + }; + numlock = true; + }; }; - "Mod+WheelScrollRight".action.focus-column-right = { }; - "Mod+WheelScrollLeft".action.focus-column-left = { }; - "Mod+Ctrl+WheelScrollRight".action.move-column-right = { }; - "Mod+Ctrl+WheelScrollLeft".action.move-column-left = { }; + #prefer-no-csd = true; + hotkey-overlay.skip-at-startup = true; - # Usually scrolling up and down with Shift in applications results in - # horizontal scrolling; these binds replicate that. - "Mod+Shift+WheelScrollDown".action.focus-column-right = { }; - "Mod+Shift+WheelScrollUp".action.focus-column-left = { }; - "Mod+Ctrl+Shift+WheelScrollDown".action.move-column-right = { }; - "Mod+Ctrl+Shift+WheelScrollUp".action.move-column-left = { }; + window-rules = [ + { + clip-to-geometry = true; + geometry-corner-radius = + let + radius = 15.; + in + { + top-left = radius; + bottom-left = radius; + top-right = radius; + bottom-right = radius; + }; + } + { + matches = [ + { + app-id = "steam"; + title = "^notificationtoasts_\\d+_desktop$"; + } + ]; + default-floating-position = { + x = 10; + y = 10; + relative-to = "bottom-right"; + }; + } + ]; - # Similarly, you can bind touchpad scroll "ticks". - # Touchpad scrolling is continuous, so for these binds it is split into - # discrete intervals. - # These binds are also affected by touchpad's natural-scroll, so these - # example binds are "inverted", since we have natural-scroll enabled for - # touchpads by default. - # Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; } - # Mod+TouchpadScrollUp { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; } + # defaults taken from https://github.com/sodiboo/niri-flake/issues/483 + binds = { + # Keys consist of modifiers separated by + signs, followed by an XKB key name + # in the end. To find an XKB name for a particular key, you may use a program + # like wev. + # + # "Mod" is a special modifier equal to Super when running on a TTY, and to Alt + # when running as a winit window. + # + # Most actions that you can bind here can also be invoked programmatically with + # `niri msg action do-something`. - # You can refer to workspaces by index. However, keep in mind that - # niri is a dynamic workspace system, so these commands are kind of - # "best effort". Trying to refer to a workspace index bigger than - # the current workspace count will instead refer to the bottommost - # (empty) workspace. - # - # For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on - # will all refer to the 3rd workspace. - "Mod+1".action.focus-workspace = 1; - "Mod+2".action.focus-workspace = 2; - "Mod+3".action.focus-workspace = 3; - "Mod+4".action.focus-workspace = 4; - "Mod+5".action.focus-workspace = 5; - "Mod+6".action.focus-workspace = 6; - "Mod+7".action.focus-workspace = 7; - "Mod+8".action.focus-workspace = 8; - "Mod+9".action.focus-workspace = 9; - "Mod+Ctrl+1".action.move-column-to-workspace = 1; - "Mod+Ctrl+2".action.move-column-to-workspace = 2; - "Mod+Ctrl+3".action.move-column-to-workspace = 3; - "Mod+Ctrl+4".action.move-column-to-workspace = 4; - "Mod+Ctrl+5".action.move-column-to-workspace = 5; - "Mod+Ctrl+6".action.move-column-to-workspace = 6; - "Mod+Ctrl+7".action.move-column-to-workspace = 7; - "Mod+Ctrl+8".action.move-column-to-workspace = 8; - "Mod+Ctrl+9".action.move-column-to-workspace = 9; + # Mod-Shift-/, which is usually the same as Mod-?, + # shows a list of important hotkeys. + "Mod+Shift+Numbersign".action.show-hotkey-overlay = { }; - # Alternatively, there are commands to move just a single window: - # Mod+Ctrl+1 { move-window-to-workspace 1; } + # Suggested binds for running programs: terminal, app launcher, screen locker. + "Mod+T".action.spawn = "${lib.getBin pkgs.gnome-console}/bin/kgx"; + "Mod+D".action.spawn = "${lib.getBin config.programs.fuzzel.package}/bin/fuzzel"; - # Switches focus between the current and the previous workspace. - # Mod+Tab { focus-workspace-previous; } + # You can also use a shell. Do this if you need pipes, multiple commands, etc. + # Note: the entire command goes as a single argument in the end. + # Mod+T { spawn "bash" "-c" "notify-send hello && exec alacritty"; } - "Mod+Comma".action.consume-window-into-column = { }; - "Mod+Period".action.expel-window-from-column = { }; + # Example volume keys mappings for PipeWire & WirePlumber. + # The allow-when-locked=true property makes them work even when the session is locked. + "XF86AudioRaiseVolume" = { + allow-when-locked = true; + action.spawn = [ + "wpctl" + "set-volume" + "@DEFAULT_AUDIO_SINK@" + "0.1+" + ]; + }; + "XF86AudioLowerVolume" = { + allow-when-locked = true; + action.spawn = [ + "wpctl" + "set-volume" + "@DEFAULT_AUDIO_SINK@" + "0.1-" + ]; + }; + "XF86AudioMute" = { + allow-when-locked = true; + action.spawn = [ + "wpctl" + "set-mute" + "@DEFAULT_AUDIO_SINK@" + "toggle" + ]; + }; + "XF86AudioMicMute" = { + allow-when-locked = true; + action.spawn = [ + "wpctl" + "set-mute" + "@DEFAULT_AUDIO_SOURCE@" + "toggle" + ]; + }; + "XF86MonBrightnessUp" = { + allow-when-locked = true; + action.spawn = [ + "brightnessctl" + "set" + "5%+" + ]; + }; + "XF86MonBrightnessDown" = { + allow-when-locked = true; + action.spawn = [ + "brightnessctl" + "set" + "5%-" + ]; + }; - # There are also commands that consume or expel a single window to the side. - # Mod+BracketLeft { consume-or-expel-window-left; } - # Mod+BracketRight { consume-or-expel-window-right; } + "Mod+Q".action.close-window = { }; - "Mod+R".action.switch-preset-column-width = { }; - "Mod+Shift+R".action.reset-window-height = { }; - "Mod+F".action.maximize-column = { }; - "Mod+Shift+F".action.fullscreen-window = { }; - "Mod+C".action.center-column = { }; + "Mod+Left".action.focus-column-left = { }; + "Mod+Down".action.focus-window-down = { }; + "Mod+Up".action.focus-window-up = { }; + "Mod+Right".action.focus-column-right = { }; - # Finer width adjustments. - # This command can also: - # * set width in pixels: "1000" - # * adjust width in pixels: "-5" or "+5" - # * set width as a percentage of screen width: "25%" - # * adjust width as a percentage of screen width: "-10%" or "+10%" - # Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0, - # set-column-width "100" will make the column occupy 200 physical screen pixels. - "Mod+Minus".action.set-column-width = "-10%"; - "Mod+Equal".action.set-column-width = "+10%"; + "Mod+Ctrl+Left".action.move-column-left = { }; + "Mod+Ctrl+Down".action.move-window-down = { }; + "Mod+Ctrl+Up".action.move-window-up = { }; + "Mod+Ctrl+Right".action.move-column-right = { }; - # Finer height adjustments when in column with other windows. - "Mod+Shift+Minus".action.set-window-height = "-10%"; - "Mod+Shift+Equal".action.set-window-height = "+10%"; + # Alternative commands that move across workspaces when reaching + # the first or last window in a column. + # Mod+J { focus-window-or-workspace-down; } + # Mod+K { focus-window-or-workspace-up; } + # Mod+Ctrl+J { move-window-down-or-to-workspace-down; } + # Mod+Ctrl+K { move-window-up-or-to-workspace-up; } - # Actions to switch layouts. - # Note: if you uncomment these, make sure you do NOT have - # a matching layout switch hotkey configured in xkb options above. - # Having both at once on the same hotkey will break the switching, - # since it will switch twice upon pressing the hotkey (once by xkb, once by niri). - # Mod+Space { switch-layout "next"; } - # Mod+Shift+Space { switch-layout "prev"; } + "Mod+Home".action.focus-column-first = { }; + "Mod+End".action.focus-column-last = { }; + "Mod+Ctrl+Home".action.move-column-to-first = { }; + "Mod+Ctrl+End".action.move-column-to-last = { }; - "Print".action.screenshot = { }; - "Ctrl+Print".action.screenshot-screen = { }; - "Alt+Print".action.screenshot-window = { }; + "Mod+Shift+Left".action.focus-monitor-left = { }; + "Mod+Shift+Down".action.focus-monitor-down = { }; + "Mod+Shift+Up".action.focus-monitor-up = { }; + "Mod+Shift+Right".action.focus-monitor-right = { }; - # The quit action will show a confirmation dialog to avoid accidental exits. - "Mod+Shift+E".action.quit = { }; + "Mod+Shift+Ctrl+Left".action.move-column-to-monitor-left = { }; + "Mod+Shift+Ctrl+Down".action.move-column-to-monitor-down = { }; + "Mod+Shift+Ctrl+Up".action.move-column-to-monitor-up = { }; + "Mod+Shift+Ctrl+Right".action.move-column-to-monitor-right = { }; - # Powers off the monitors. To turn them back on, do any input like - # moving the mouse or pressing any other key. - "Mod+Shift+P".action.power-off-monitors = { }; + # Alternatively, there are commands to move just a single window: + # Mod+Shift+Ctrl+Left { move-window-to-monitor-left; } + # ... - "Mod+W".action.toggle-column-tabbed-display = { }; - "Mod+O".action.toggle-overview = { }; + # And you can also move a whole workspace to another monitor: + # Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; } + # ... - "Super+Alt+L" = { - action.spawn = "${pkgs.systemd}/bin/loginctl lock-session"; - allow-when-locked = true; + "Mod+Page_Down".action.focus-workspace-down = { }; + "Mod+Page_Up".action.focus-workspace-up = { }; + "Mod+U".action.focus-workspace-down = { }; + "Mod+I".action.focus-workspace-up = { }; + "Mod+Ctrl+Page_Down".action.move-column-to-workspace-down = { }; + "Mod+Ctrl+Page_Up".action.move-column-to-workspace-up = { }; + "Mod+Ctrl+U".action.move-column-to-workspace-down = { }; + "Mod+Ctrl+I".action.move-column-to-workspace-up = { }; + + # Alternatively, there are commands to move just a single window: + # Mod+Ctrl+Page_Down { move-window-to-workspace-down; } + # ... + + "Mod+Shift+Page_Down".action.move-workspace-down = { }; + "Mod+Shift+Page_Up".action.move-workspace-up = { }; + "Mod+Shift+U".action.move-workspace-down = { }; + "Mod+Shift+I".action.move-workspace-up = { }; + + # You can bind mouse wheel scroll ticks using the following syntax. + # These binds will change direction based on the natural-scroll setting. + # + # To avoid scrolling through workspaces really fast, you can use + # the cooldown-ms property. The bind will be rate-limited to this value. + # You can set a cooldown on any bind, but it's most useful for the wheel. + "Mod+WheelScrollDown" = { + cooldown-ms = 150; + action.focus-workspace-down = { }; + }; + "Mod+WheelScrollUp" = { + cooldown-ms = 150; + action.focus-workspace-up = { }; + }; + "Mod+Ctrl+WheelScrollDown" = { + cooldown-ms = 150; + action.move-column-to-workspace-down = { }; + }; + "Mod+Ctrl+WheelScrollUp" = { + cooldown-ms = 150; + action.move-column-to-workspace-up = { }; + }; + + "Mod+WheelScrollRight".action.focus-column-right = { }; + "Mod+WheelScrollLeft".action.focus-column-left = { }; + "Mod+Ctrl+WheelScrollRight".action.move-column-right = { }; + "Mod+Ctrl+WheelScrollLeft".action.move-column-left = { }; + + # Usually scrolling up and down with Shift in applications results in + # horizontal scrolling; these binds replicate that. + "Mod+Shift+WheelScrollDown".action.focus-column-right = { }; + "Mod+Shift+WheelScrollUp".action.focus-column-left = { }; + "Mod+Ctrl+Shift+WheelScrollDown".action.move-column-right = { }; + "Mod+Ctrl+Shift+WheelScrollUp".action.move-column-left = { }; + + # Similarly, you can bind touchpad scroll "ticks". + # Touchpad scrolling is continuous, so for these binds it is split into + # discrete intervals. + # These binds are also affected by touchpad's natural-scroll, so these + # example binds are "inverted", since we have natural-scroll enabled for + # touchpads by default. + # Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; } + # Mod+TouchpadScrollUp { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; } + + # You can refer to workspaces by index. However, keep in mind that + # niri is a dynamic workspace system, so these commands are kind of + # "best effort". Trying to refer to a workspace index bigger than + # the current workspace count will instead refer to the bottommost + # (empty) workspace. + # + # For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on + # will all refer to the 3rd workspace. + "Mod+1".action.focus-workspace = 1; + "Mod+2".action.focus-workspace = 2; + "Mod+3".action.focus-workspace = 3; + "Mod+4".action.focus-workspace = 4; + "Mod+5".action.focus-workspace = 5; + "Mod+6".action.focus-workspace = 6; + "Mod+7".action.focus-workspace = 7; + "Mod+8".action.focus-workspace = 8; + "Mod+9".action.focus-workspace = 9; + "Mod+Ctrl+1".action.move-column-to-workspace = 1; + "Mod+Ctrl+2".action.move-column-to-workspace = 2; + "Mod+Ctrl+3".action.move-column-to-workspace = 3; + "Mod+Ctrl+4".action.move-column-to-workspace = 4; + "Mod+Ctrl+5".action.move-column-to-workspace = 5; + "Mod+Ctrl+6".action.move-column-to-workspace = 6; + "Mod+Ctrl+7".action.move-column-to-workspace = 7; + "Mod+Ctrl+8".action.move-column-to-workspace = 8; + "Mod+Ctrl+9".action.move-column-to-workspace = 9; + + # Alternatively, there are commands to move just a single window: + # Mod+Ctrl+1 { move-window-to-workspace 1; } + + # Switches focus between the current and the previous workspace. + # Mod+Tab { focus-workspace-previous; } + + "Mod+Comma".action.consume-window-into-column = { }; + "Mod+Period".action.expel-window-from-column = { }; + + # There are also commands that consume or expel a single window to the side. + # Mod+BracketLeft { consume-or-expel-window-left; } + # Mod+BracketRight { consume-or-expel-window-right; } + + "Mod+R".action.switch-preset-column-width = { }; + "Mod+Shift+R".action.reset-window-height = { }; + "Mod+F".action.maximize-column = { }; + "Mod+Shift+F".action.fullscreen-window = { }; + "Mod+C".action.center-column = { }; + + # Finer width adjustments. + # This command can also: + # * set width in pixels: "1000" + # * adjust width in pixels: "-5" or "+5" + # * set width as a percentage of screen width: "25%" + # * adjust width as a percentage of screen width: "-10%" or "+10%" + # Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0, + # set-column-width "100" will make the column occupy 200 physical screen pixels. + "Mod+Minus".action.set-column-width = "-10%"; + "Mod+Equal".action.set-column-width = "+10%"; + + # Finer height adjustments when in column with other windows. + "Mod+Shift+Minus".action.set-window-height = "-10%"; + "Mod+Shift+Equal".action.set-window-height = "+10%"; + + # Actions to switch layouts. + # Note: if you uncomment these, make sure you do NOT have + # a matching layout switch hotkey configured in xkb options above. + # Having both at once on the same hotkey will break the switching, + # since it will switch twice upon pressing the hotkey (once by xkb, once by niri). + # Mod+Space { switch-layout "next"; } + # Mod+Shift+Space { switch-layout "prev"; } + + "Print".action.screenshot = { }; + "Ctrl+Print".action.screenshot-screen = { }; + "Alt+Print".action.screenshot-window = { }; + + # The quit action will show a confirmation dialog to avoid accidental exits. + "Mod+Shift+E".action.quit = { }; + + # Powers off the monitors. To turn them back on, do any input like + # moving the mouse or pressing any other key. + "Mod+Shift+P".action.power-off-monitors = { }; + + "Mod+W".action.toggle-column-tabbed-display = { }; + "Mod+O".action.toggle-overview = { }; + + "Super+Alt+L" = { + action.spawn = "${pkgs.systemd}/bin/loginctl lock-session"; + allow-when-locked = true; + }; }; }; - }; - }; + } + + # lpt2's keyboard is flaky, so give it an on-screen keyboard. + # squeekboard auto-shows on focused text fields via the input-method + # protocol, but that doesn't catch every app, so Mod+K force-toggles it + # over D-Bus (sm.puri.OSK0), which is squeekboard's own control interface. + ( + let + squeekboard-toggle = pkgs.writeShellApplication { + name = "squeekboard-toggle"; + runtimeInputs = [ pkgs.systemd ]; + text = '' + dest=sm.puri.OSK0 + path=/sm/puri/OSK0 + iface=sm.puri.OSK0 + current=$(busctl --user get-property "$dest" "$path" "$iface" Visible | cut -d' ' -f2) + if [ "$current" = "true" ]; then + busctl --user call "$dest" "$path" "$iface" SetVisible b false + else + busctl --user call "$dest" "$path" "$iface" SetVisible b true + fi + ''; + }; + in + lib.mkIf (device == "muede-lpt2") { + home.packages = [ pkgs.squeekboard ]; + + programs.niri.settings = { + spawn-at-startup = [ + { command = [ (lib.getExe' pkgs.squeekboard "squeekboard") ]; } + ]; + + binds."Mod+K".action.spawn = lib.getExe squeekboard-toggle; + }; + } + ) + ]; }