nixosTests.{qtile,qtile-extras}: Use startup hook to determine when wm is ready
This commit is contained in:
		
							parent
							
								
									9200c874c5
								
							
						
					
					
						commit
						344f2b103d
					
				@ -1250,7 +1250,7 @@ in
 | 
			
		||||
  qgis = handleTest ./qgis.nix { package = pkgs.qgis; };
 | 
			
		||||
  qgis-ltr = handleTest ./qgis.nix { package = pkgs.qgis-ltr; };
 | 
			
		||||
  qownnotes = runTest ./qownnotes.nix;
 | 
			
		||||
  qtile = runTestOn [ "x86_64-linux" "aarch64-linux" ] ./qtile.nix;
 | 
			
		||||
  qtile = runTestOn [ "x86_64-linux" "aarch64-linux" ] ./qtile/default.nix;
 | 
			
		||||
  qtile-extras = runTestOn [ "x86_64-linux" "aarch64-linux" ] ./qtile-extras/default.nix;
 | 
			
		||||
  quake3 = runTest ./quake3.nix;
 | 
			
		||||
  quicktun = runTest ./quicktun.nix;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								nixos/tests/qtile-extras/add-startup-hook.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								nixos/tests/qtile-extras/add-startup-hook.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
--- a/config.py	2025-08-03 00:37:13.058374602 +0200
 | 
			
		||||
+++ b/config.py	2025-08-03 00:45:51.869382363 +0200
 | 
			
		||||
@@ -24,10 +24,18 @@
 | 
			
		||||
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
 # SOFTWARE.
 | 
			
		||||
 
 | 
			
		||||
-from libqtile import bar, layout, qtile, widget
 | 
			
		||||
+from libqtile import bar, layout, qtile, widget, hook
 | 
			
		||||
 from libqtile.config import Click, Drag, Group, Key, Match, Screen
 | 
			
		||||
 from libqtile.lazy import lazy
 | 
			
		||||
 from libqtile.utils import guess_terminal
 | 
			
		||||
+from libqtile.log_utils import logger
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+@hook.subscribe.startup
 | 
			
		||||
+def print_ready():
 | 
			
		||||
+    logger.warning("ready!") # warning to make it always visible
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
 mod = "mod4"
 | 
			
		||||
 terminal = guess_terminal()
 | 
			
		||||
@ -15,7 +15,10 @@ stdenvNoCC.mkDerivation {
 | 
			
		||||
    cp $src config.py
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  patches = [ ./add-widget.patch ];
 | 
			
		||||
  patches = [
 | 
			
		||||
    ./add-widget.patch
 | 
			
		||||
    ./add-startup-hook.patch
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  dontUnpack = true;
 | 
			
		||||
  dontBuild = true;
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,8 @@
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  testScript = ''
 | 
			
		||||
    from pathlib import Path
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure x starts"):
 | 
			
		||||
        machine.wait_for_x()
 | 
			
		||||
        machine.wait_for_file("/home/alice/.Xauthority")
 | 
			
		||||
@ -48,6 +50,13 @@
 | 
			
		||||
    with subtest("ensure client is available"):
 | 
			
		||||
        machine.succeed("qtile --version")
 | 
			
		||||
 | 
			
		||||
    with subtest("Qtile signals that it is ready"):
 | 
			
		||||
        qtile_logfile = Path("/home/alice/.local/share/qtile/qtile.log")
 | 
			
		||||
 | 
			
		||||
        machine.succeed(f"mkdir -p {qtile_logfile.parent}")
 | 
			
		||||
        machine.succeed(f"touch {qtile_logfile}")
 | 
			
		||||
        machine.succeed(f"sh -c 'tail -f {qtile_logfile} | grep --line-buffered \'ready\' -m 1'")
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure we can open a new terminal"):
 | 
			
		||||
        machine.send_key("meta_l-ret")
 | 
			
		||||
        machine.wait_for_window(r"alice.*?machine")
 | 
			
		||||
 | 
			
		||||
@ -1,46 +0,0 @@
 | 
			
		||||
{ lib, ... }:
 | 
			
		||||
{
 | 
			
		||||
  name = "qtile";
 | 
			
		||||
 | 
			
		||||
  meta = {
 | 
			
		||||
    maintainers = with lib.maintainers; [
 | 
			
		||||
      sigmanificient
 | 
			
		||||
      gurjaka
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  nodes.machine =
 | 
			
		||||
    {
 | 
			
		||||
      pkgs,
 | 
			
		||||
      lib,
 | 
			
		||||
      ...
 | 
			
		||||
    }:
 | 
			
		||||
    {
 | 
			
		||||
      imports = [
 | 
			
		||||
        ./common/x11.nix
 | 
			
		||||
        ./common/user-account.nix
 | 
			
		||||
      ];
 | 
			
		||||
      test-support.displayManager.auto.user = "alice";
 | 
			
		||||
 | 
			
		||||
      services.xserver.windowManager.qtile.enable = true;
 | 
			
		||||
 | 
			
		||||
      services.displayManager.defaultSession = lib.mkForce "qtile";
 | 
			
		||||
 | 
			
		||||
      environment.systemPackages = [ pkgs.kitty ];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  testScript = ''
 | 
			
		||||
    with subtest("ensure x starts"):
 | 
			
		||||
        machine.wait_for_x()
 | 
			
		||||
        machine.wait_for_file("/home/alice/.Xauthority")
 | 
			
		||||
        machine.succeed("xauth merge ~alice/.Xauthority")
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure client is available"):
 | 
			
		||||
        machine.succeed("qtile --version")
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure we can open a new terminal"):
 | 
			
		||||
        machine.send_key("meta_l-ret")
 | 
			
		||||
        machine.wait_for_window(r"alice.*?machine")
 | 
			
		||||
        machine.screenshot("terminal")
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								nixos/tests/qtile/add-startup-hook.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								nixos/tests/qtile/add-startup-hook.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
--- a/config.py	2025-08-03 00:37:13.058374602 +0200
 | 
			
		||||
+++ b/config.py	2025-08-03 00:45:51.869382363 +0200
 | 
			
		||||
@@ -24,10 +24,18 @@
 | 
			
		||||
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
 # SOFTWARE.
 | 
			
		||||
 
 | 
			
		||||
-from libqtile import bar, layout, qtile, widget
 | 
			
		||||
+from libqtile import bar, layout, qtile, widget, hook
 | 
			
		||||
 from libqtile.config import Click, Drag, Group, Key, Match, Screen
 | 
			
		||||
 from libqtile.lazy import lazy
 | 
			
		||||
 from libqtile.utils import guess_terminal
 | 
			
		||||
+from libqtile.log_utils import logger
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+@hook.subscribe.startup
 | 
			
		||||
+def print_ready():
 | 
			
		||||
+    logger.warning("ready!") # warning to make it always visible
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
 mod = "mod4"
 | 
			
		||||
 terminal = guess_terminal()
 | 
			
		||||
							
								
								
									
										27
									
								
								nixos/tests/qtile/config.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								nixos/tests/qtile/config.nix
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
{
 | 
			
		||||
  stdenvNoCC,
 | 
			
		||||
  fetchurl,
 | 
			
		||||
}:
 | 
			
		||||
stdenvNoCC.mkDerivation {
 | 
			
		||||
  name = "qtile-extras-config";
 | 
			
		||||
  version = "0.0.1";
 | 
			
		||||
 | 
			
		||||
  src = fetchurl {
 | 
			
		||||
    url = "https://raw.githubusercontent.com/qtile/qtile/v0.28.1/libqtile/resources/default_config.py";
 | 
			
		||||
    hash = "sha256-Y5W277CWVNSi4BdgEW/f7Px/MMjnN9W9TDqdOncVwPc=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  prePatch = ''
 | 
			
		||||
    cp $src config.py
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  patches = [ ./add-startup-hook.patch ];
 | 
			
		||||
 | 
			
		||||
  dontUnpack = true;
 | 
			
		||||
  dontBuild = true;
 | 
			
		||||
 | 
			
		||||
  installPhase = ''
 | 
			
		||||
    mkdir -p $out
 | 
			
		||||
    cp config.py $out/config.py
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								nixos/tests/qtile/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								nixos/tests/qtile/default.nix
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
			
		||||
{ lib, ... }:
 | 
			
		||||
{
 | 
			
		||||
  name = "qtile";
 | 
			
		||||
 | 
			
		||||
  meta = {
 | 
			
		||||
    maintainers = with lib.maintainers; [
 | 
			
		||||
      sigmanificient
 | 
			
		||||
      gurjaka
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  nodes.machine =
 | 
			
		||||
    {
 | 
			
		||||
      pkgs,
 | 
			
		||||
      lib,
 | 
			
		||||
      ...
 | 
			
		||||
    }:
 | 
			
		||||
    let
 | 
			
		||||
      # We create a custom Qtile configuration file that adds a
 | 
			
		||||
      # startup hook to qtile. This ensure we can reproducibly check
 | 
			
		||||
      # when Qtile is truly ready to receive our inputs
 | 
			
		||||
      config-deriv = pkgs.callPackage ./config.nix { };
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
      imports = [
 | 
			
		||||
        ../common/x11.nix
 | 
			
		||||
        ../common/user-account.nix
 | 
			
		||||
      ];
 | 
			
		||||
      test-support.displayManager.auto.user = "alice";
 | 
			
		||||
 | 
			
		||||
      services.xserver.windowManager.qtile = {
 | 
			
		||||
        enable = true;
 | 
			
		||||
        configFile = "${config-deriv}/config.py";
 | 
			
		||||
        extraPackages = ps: [ ps.qtile-extras ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      services.displayManager.defaultSession = lib.mkForce "qtile";
 | 
			
		||||
 | 
			
		||||
      environment.systemPackages = [
 | 
			
		||||
        pkgs.kitty
 | 
			
		||||
        pkgs.xorg.xwininfo
 | 
			
		||||
      ];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  testScript = ''
 | 
			
		||||
    from pathlib import Path
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure x starts"):
 | 
			
		||||
        machine.wait_for_x()
 | 
			
		||||
        machine.wait_for_file("/home/alice/.Xauthority")
 | 
			
		||||
        machine.succeed("xauth merge ~alice/.Xauthority")
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure client is available"):
 | 
			
		||||
        machine.succeed("qtile --version")
 | 
			
		||||
 | 
			
		||||
    with subtest("Qtile signals that it is ready"):
 | 
			
		||||
        qtile_logfile = Path("/home/alice/.local/share/qtile/qtile.log")
 | 
			
		||||
 | 
			
		||||
        machine.succeed(f"mkdir -p {qtile_logfile.parent}")
 | 
			
		||||
        machine.succeed(f"touch {qtile_logfile}")
 | 
			
		||||
        machine.succeed(f"sh -c 'tail -f {qtile_logfile} | grep --line-buffered \'ready\' -m 1'")
 | 
			
		||||
 | 
			
		||||
    with subtest("ensure we can open a new terminal"):
 | 
			
		||||
        machine.send_key("meta_l-ret")
 | 
			
		||||
        machine.wait_for_window(r"alice.*?machine")
 | 
			
		||||
        machine.screenshot("terminal")
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user