Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 68 additions & 65 deletions modules/graphical-interface/sway/sway-config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,22 @@ in

### Key bindings
#
# --to-code binds the physical key rather than the keysym, so the
# shortcuts stay the same on fr and en keyboards.
#
# Basics:
#
# Start a terminal
bindsym $mod+Return exec $term
bindsym --to-code $mod+Return exec $term

# Kill focused window
bindsym $mod+Shift+q kill
bindsym --to-code $mod+Shift+q kill

# Start your launcher
bindsym $mod+d exec $menu
bindsym --to-code $mod+d exec $menu

# Lock the session
bindsym $mod+Control+l exec --no-startup-id swaylock -c 000000 -e
bindsym --to-code $mod+Control+l exec --no-startup-id swaylock -c 000000 -e

# Drag floating windows by holding down $mod and left mouse button.
# Resize them with right mouse button + $mod.
Expand All @@ -112,100 +115,100 @@ in
floating_modifier $mod normal

# Reload the configuration file
bindsym $mod+Shift+c reload
bindsym --to-code $mod+Shift+c reload

# Exit sway (logs you out of your Wayland session)
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
bindsym --to-code $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
#
# Moving around:
#
# Move your focus around
bindsym $mod+$left focus left
bindsym $mod+$down focus down
bindsym $mod+$up focus up
bindsym $mod+$right focus right
bindsym --to-code $mod+$left focus left
bindsym --to-code $mod+$down focus down
bindsym --to-code $mod+$up focus up
bindsym --to-code $mod+$right focus right
# Or use $mod+[up|down|left|right]
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
bindsym --to-code $mod+Left focus left
bindsym --to-code $mod+Down focus down
bindsym --to-code $mod+Up focus up
bindsym --to-code $mod+Right focus right

# Move the focused window with the same, but add Shift
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
bindsym --to-code $mod+Shift+$left move left
bindsym --to-code $mod+Shift+$down move down
bindsym --to-code $mod+Shift+$up move up
bindsym --to-code $mod+Shift+$right move right
# Ditto, with arrow keys
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
bindsym --to-code $mod+Shift+Left move left
bindsym --to-code $mod+Shift+Down move down
bindsym --to-code $mod+Shift+Up move up
bindsym --to-code $mod+Shift+Right move right
#
# Workspaces:
#
# Switch to workspace
bindsym $mod+ampersand workspace number 1
bindsym $mod+eacute workspace number 2
bindsym $mod+quotedbl workspace number 3
bindsym $mod+apostrophe workspace number 4
bindsym $mod+parenleft workspace number 5
bindsym $mod+minus workspace number 6 # +section on Apple keyboards
bindsym $mod+egrave workspace number 7
bindsym $mod+underscore workspace number 8 # +exclam on Apple keyboards
bindsym $mod+ccedilla workspace number 9
bindsym $mod+agrave workspace number 10
bindsym --to-code $mod+ampersand workspace number 1
bindsym --to-code $mod+eacute workspace number 2
bindsym --to-code $mod+quotedbl workspace number 3
bindsym --to-code $mod+apostrophe workspace number 4
bindsym --to-code $mod+parenleft workspace number 5
bindsym --to-code $mod+minus workspace number 6 # +section on Apple keyboards
bindsym --to-code $mod+egrave workspace number 7
bindsym --to-code $mod+underscore workspace number 8 # +exclam on Apple keyboards
bindsym --to-code $mod+ccedilla workspace number 9
bindsym --to-code $mod+agrave workspace number 10
# Move focused container to workspace
bindsym $mod+Shift+ampersand move container to workspace number 1
bindsym $mod+Shift+eacute move container to workspace number 2
bindsym $mod+Shift+quotedbl move container to workspace number 3
bindsym $mod+Shift+apostrophe move container to workspace number 4
bindsym $mod+Shift+parenleft move container to workspace number 5
bindsym $mod+Shift+minus move container to workspace number 6
bindsym $mod+Shift+egrave move container to workspace number 7
bindsym $mod+Shift+underscore move container to workspace number 8
bindsym $mod+Shift+ccedilla move container to workspace number 9
bindsym $mod+Shift+agrave move container to workspace number 10
bindsym --to-code $mod+Shift+ampersand move container to workspace number 1
bindsym --to-code $mod+Shift+eacute move container to workspace number 2
bindsym --to-code $mod+Shift+quotedbl move container to workspace number 3
bindsym --to-code $mod+Shift+apostrophe move container to workspace number 4
bindsym --to-code $mod+Shift+parenleft move container to workspace number 5
bindsym --to-code $mod+Shift+minus move container to workspace number 6
bindsym --to-code $mod+Shift+egrave move container to workspace number 7
bindsym --to-code $mod+Shift+underscore move container to workspace number 8
bindsym --to-code $mod+Shift+ccedilla move container to workspace number 9
bindsym --to-code $mod+Shift+agrave move container to workspace number 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
# For multi-screens.
bindsym $mod+m move workspace to output left
bindsym --to-code $mod+m move workspace to output left
#
# Layout stuff:
#
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
bindsym $mod+b splith
bindsym $mod+v splitv
bindsym --to-code $mod+b splith
bindsym --to-code $mod+v splitv

# Switch the current container between different layout styles
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
bindsym --to-code $mod+s layout stacking
bindsym --to-code $mod+w layout tabbed
bindsym --to-code $mod+e layout toggle split

# Make the current focus fullscreen
bindsym $mod+f fullscreen
bindsym --to-code $mod+f fullscreen

# Toggle the current focus between tiling and floating mode
bindsym $mod+Shift+space floating toggle
bindsym --to-code $mod+Shift+space floating toggle

# Swap focus between the tiling area and the floating area
bindsym $mod+space focus mode_toggle
bindsym --to-code $mod+space focus mode_toggle

# Move focus to the parent container
bindsym $mod+a focus parent
bindsym --to-code $mod+a focus parent
#
# Scratchpad:
#
# Sway has a "scratchpad", which is a bag of holding for windows.
# You can send windows there and get them back later.

# Move the currently focused window to the scratchpad
bindsym $mod+Shift+p move scratchpad
bindsym --to-code $mod+Shift+p move scratchpad

# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+p scratchpad show
bindsym --to-code $mod+p scratchpad show
#
# Resizing containers:
#
Expand All @@ -214,22 +217,22 @@ in
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
bindsym $left resize shrink width 10px
bindsym $down resize grow height 10px
bindsym $up resize shrink height 10px
bindsym $right resize grow width 10px
bindsym --to-code $left resize shrink width 10px
bindsym --to-code $down resize grow height 10px
bindsym --to-code $up resize shrink height 10px
bindsym --to-code $right resize grow width 10px

# Ditto, with arrow keys
bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px
bindsym --to-code Left resize shrink width 10px
bindsym --to-code Down resize grow height 10px
bindsym --to-code Up resize shrink height 10px
bindsym --to-code Right resize grow width 10px

# Return to default mode
bindsym Return mode "default"
bindsym Escape mode "default"
bindsym --to-code Return mode "default"
bindsym --to-code Escape mode "default"
}
bindsym $mod+r mode "resize"
bindsym --to-code $mod+r mode "resize"

#
# Status Bar:
Expand Down
1 change: 1 addition & 0 deletions tests/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
anssi-minimal = import ./anssi-minimal.nix { inherit pkgs libSecurix; };
idempotent-autoinstall = import ./idempotent-autoinstall.nix { inherit pkgs libSecurix; };
portail = import ./portail.nix { inherit pkgs libSecurix; };
sway-keybindings = import ./sway-keybindings.nix { inherit pkgs libSecurix; };
tools = import ./tools.nix { inherit pkgs libSecurix; };
}
100 changes: 100 additions & 0 deletions tests/sway-keybindings.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# SPDX-FileCopyrightText: 2026 Quentin Cazier <cazierquentin@gmail.com>
#
# SPDX-License-Identifier: MIT
#
# Regression test for https://github.com/cloud-gouv/securix/issues/84
#
# Boots the Securix sway configuration and drives it with key events sent
# by QEMU. The shortcuts must keep working on the same physical keys once
# the keyboard is switched from the default fr layout to a us layout.

{ pkgs, libSecurix }:

let
lib = pkgs.lib;
in
pkgs.testers.nixosTest {
name = "sway-keybindings";

nodes.machine = {
imports = [ ../modules/graphical-interface ];

securix.graphical-interface = {
enable = true;
variant = "sway";
};

# Log in on tty1 directly instead of going through tuigreet.
services.greetd.enable = lib.mkForce false;
services.getty.autologinUser = "alice";

users.users.alice = {
isNormalUser = true;
password = "test";
uid = 1000;
};

environment.variables = {
SWAYSOCK = "/tmp/sway-ipc.sock";
WLR_RENDERER = "pixman";
};

programs.bash.loginShellInit = ''
if [ "$(tty)" = "/dev/tty1" ]; then
sway
fi
'';

virtualisation.qemu.options = [ "-vga none -device virtio-gpu-pci" ];
};

testScript = ''
import json
import shlex

def swaymsg(command, msg_type="command"):
shell = "swaymsg -t " + shlex.quote(msg_type) + " -- " + shlex.quote(command)
out = machine.succeed("su - alice -c " + shlex.quote(shell))
return json.loads(out)

def walk(node):
yield node
for group in ("nodes", "floating_nodes"):
for child in node.get(group, []):
yield from walk(child)

def app_ids():
return [node.get("app_id") for node in walk(swaymsg("", "get_tree"))]

def focused_workspace():
return [ws["num"] for ws in swaymsg("", "get_workspaces") if ws["focused"]][0]

def keyboards():
return [i for i in swaymsg("", "get_inputs") if i["type"] == "keyboard"]

# QEMU names keys by their us position, so the fr "q" key is sent as "a".
machine.wait_for_unit("multi-user.target")
machine.wait_for_file("/tmp/sway-ipc.sock")
retry(lambda _: len(keyboards()) > 0, timeout_seconds=120)

with subtest("fr layout: shortcuts work"):
assert keyboards()[0]["xkb_active_layout_name"].startswith("French")
machine.send_key("meta_l-ret")
retry(lambda _: "foot" in app_ids(), timeout_seconds=120)
machine.send_key("meta_l-shift-a")
machine.wait_until_fails("pgrep foot")
machine.send_key("meta_l-2")
retry(lambda _: focused_workspace() == 2, timeout_seconds=120)

with subtest("us layout: same physical keys"):
swaymsg('input type:keyboard xkb_layout "fr,us"')
swaymsg("input type:keyboard xkb_switch_layout 1")
retry(lambda _: keyboards()[0]["xkb_active_layout_name"].startswith("English"), timeout_seconds=120)
machine.send_key("meta_l-3")
retry(lambda _: focused_workspace() == 3, timeout_seconds=120)
machine.send_key("meta_l-ret")
retry(lambda _: "foot" in app_ids(), timeout_seconds=120)
machine.send_key("meta_l-shift-a")
machine.wait_until_fails("pgrep foot")
'';
}
Loading