Hyprland: Hyprland crashes when used with kanshi on NixOS

Hello, I’m relatively new to NixOS and hyprland. I’m trying to setup kanshi with hyprland so that when I connect my laptop to my monitors, the internal screen is disabled. But this seems to crash hyprland. Attaching the logs here:

@fufexan tagging you since its NixOS related.

Unfortunately I can’t make my NixOS config open but this is the kanshi flake

{ config, lib, pkgs, ... }:

{
  services = {
    kanshi = {
      enable = true;
      systemdTarget = "xdg-desktop-portal-hyprland.service";
      profiles = {
        laptop = {
          outputs = [
            {
              criteria = "eDP-1";
            }
          ];
        };
        home = {
          outputs = [
            {
              criteria = "Dell Inc. DELL S2722QC FL7WLD3";
              mode = "3840x2160@59.997002";
              position = "0,0";
              scale = 2.0;
            }
            {
              criteria = "Dell Inc. DELL S2722QC C77WLD3";
              mode = "3840x2160@60.000000";
              position = "1920,0";
              scale = 2.0;
            }
            {
              criteria = "eDP-1";
              status = "disable";
            }
          ];
        };
      };
    };
  };
}

My hyprland nix config

{ config, lib, pkgs, ... }:

let
  hyprlandConf = ''
    exec-once=${pkgs.swaybg}/bin/swaybg -m stretch -i $HOME/.config/wall
    exec-once=dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
    exec-once=systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
    exec-once=${pkgs.networkmanagerapplet}/bin/nm-applet --indicator
    exec-once=${pkgs.waybar}/bin/waybar
    exec-once=${pkgs.blueman}/bin/blueman-applet

    monitor=eDP-1, highres, 0x0, 1.0

    input {
        kb_layout = us
        kb_options = ctrl:nocaps
        follow_mouse = 1

        touchpad {
            natural_scroll = no
        }

        sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
    }

    bind=SUPER SHIFT, P, exec,${pkgs.grim}/bin/grim -g "$(${pkgs.slurp}/bin/slurp)" - | ${pkgs.swappy}/bin/swappy -f - -o ~/Pictures/$(date +%Hh_%Mm_%Ss_%d_%B_%Y).png && notify-send "Saved to ~/Pictures/$(date +%Hh_%Mm_%Ss_%d_%B_%Y).png"
    bind=,XF86AudioLowerVolume,exec,${pkgs.pamixer}/bin/pamixer -d 10
    bind=,XF86AudioRaiseVolume,exec,${pkgs.pamixer}/bin/pamixer -i 10
    bind=,XF86AudioMute,exec,${pkgs.pamixer}/bin/pamixer -t
    bind=,XF86AudioMicMute,exec,${pkgs.pamixer}/bin/pamixer --default-source -t
    bind=,XF86MonBrightnessDown,exec,${pkgs.light}/bin/light -U 10
    bind=,XF86MonBrightnessUP,exec,${pkgs.light}/bin/light -A 10

    general {
        gaps_in = 5
        gaps_out = 5

        border_size=1
        no_border_on_floating = true
        col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
        col.inactive_border = rgba(595959aa)

        layout = dwindle
    }

    decoration {
      rounding = 8
      multisample_edges = true

      active_opacity = 1.0
      inactive_opacity = 1.0

      blur = true
      blur_size = 3
      blur_passes = 3
      blur_new_optimizations = true

      drop_shadow = false
      # drop_shadow = true
      # shadow_ignore_window = true
      # shadow_offset = 2 2
      # shadow_range = 4
      # shadow_render_power = 2
      # col.shadow = 0x66000000

      blurls = gtk-layer-shell
      # blurls = waybar
      blurls = lockscreen
    }

    animations {
      enabled = true
      # enabled = true
      # bezier = overshot, 0.05, 0.9, 0.1, 1.05
      # bezier = smoothOut, 0.36, 0, 0.66, -0.56
      # bezier = smoothIn, 0.25, 1, 0.5, 1

      # animation = windows, 1, 5, overshot, slide
      # animation = windowsOut, 1, 4, smoothOut, slide
      # animation = windowsMove, 1, 4, default
      # animation = border, 1, 10, default
      # animation = fade, 1, 10, smoothIn
      # animation = fadeDim, 1, 10, smoothIn
      # animation = workspaces, 1, 6, default
    }

    dwindle {
      no_gaps_when_only = false
      pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
      preserve_split = true # you probably want this
    }

    windowrule = float, file_progress
    windowrule = float, confirm
    windowrule = float, dialog
    windowrule = float, download
    windowrule = float, notification
    windowrule = float, error
    windowrule = float, splash
    windowrule = float, confirmreset
    windowrule = float, title:Open File
    windowrule = float, title:branchdialog
    windowrule = float, Lxappearance
    windowrule = float, Rofi
    windowrule = animation none,Rofi
    windowrule = float, viewnior
    windowrule = float, Viewnior
    windowrule = float, feh
    windowrule = float, pavucontrol-qt
    windowrule = float, pavucontrol
    windowrule = float, file-roller
    windowrule = fullscreen, wlogout
    windowrule = float, title:wlogout
    windowrule = fullscreen, title:wlogout
    windowrule = idleinhibit focus, mpv
    windowrule = idleinhibit fullscreen, firefox
    windowrule = float, title:^(Media viewer)$
    windowrule = float, title:^(Volume Control)$
    windowrule = float, title:^(Picture-in-Picture)$
    windowrule = size 800 600, title:^(Volume Control)$
    windowrule = move 75 44%, title:^(Volume Control)$

    bind = SUPER SHIFT, O, exec, ${pkgs.swaylock}/bin/swaylock
    bind = SUPER, Return, exec, ${pkgs.alacritty}/bin/alacritty
    bind = SUPER, E, exec, thunar
    bind = SUPER, D, exec, ${pkgs.rofi}/bin/rofi -show drun -theme ~/.config/rofi/global/rofi.rasi
    #bind = SUPER, D, exec, "killall rofi; and ${pkgs.rofi}/bin/rofi -show drun"
    bind = SUPER, escape, exec, wlogout --protocol layer-shell -b 5 -T 400 -B 400
    bind = SUPER, Slash, exec, dunstctl close
    bind = SUPER, Period, exec, dunstctl action
    bind = SUPER, Grave, exec, dunstctl history-pop
    bind = SUPER, Q, killactive,
    #bind = SUPER, E, exec, ${pkgs.pcmanfm}/bin/pcmanfm
    bind = SUPER, T, exec, ${pkgs.emacs}/bin/emacsclient -c

    bind = SUPER SHIFT, E, exit
    bind = SUPER SHIFT, Q, killactive
    bind = SUPER, F, fullscreen,
    bind = SUPER, Space, togglefloating,
    bind = SUPER, P, pseudo, # dwindle
    bind = SUPER, S, togglesplit, # dwindle
    bind = SUPER, TAB, workspace, previous
    bind = SUPER SHIFT, Comma, movecurrentworkspacetomonitor, -1
    bind = SUPER SHIFT, Period, movecurrentworkspacetomonitor, +1

    bind = SUPER, left, movefocus, l
    bind = SUPER, right, movefocus, r
    bind = SUPER, up, movefocus, u
    bind = SUPER, down, movefocus, d

    bind = SUPER, J, movefocus, l
    bind = SUPER, semicolon, movefocus, r
    bind = SUPER, L, movefocus, u
    bind = SUPER, K, movefocus, d

    bind = SUPER SHIFT, left, movewindow, l
    bind = SUPER SHIFT, right, movewindow, r
    bind = SUPER SHIFT, up, movewindow, u
    bind = SUPER SHIFT, down, movewindow, d

    bind = SUPER SHIFT, H, movewindow, l
    bind = SUPER SHIFT, L, movewindow, r
    bind = SUPER SHIFT, K, movewindow, u
    bind = SUPER SHIFT, J, movewindow, d

    bind = SUPER CTRL, left, resizeactive, -20 0
    bind = SUPER CTRL, right, resizeactive, 20 0
    bind = SUPER CTRL, up, resizeactive, 0 -20
    bind = SUPER CTRL, down, resizeactive, 0 20

    bind= SUPER, w, togglegroup
    bind= SUPER, z, changegroupactive

    bind = SUPER, c, togglespecialworkspace
    bind = SUPERSHIFT, c, movetoworkspace, special

    bind = SUPER, 1, workspace, 1
    bind = SUPER, 2, workspace, 2
    bind = SUPER, 3, workspace, 3
    bind = SUPER, 4, workspace, 4
    bind = SUPER, 5, workspace, 5
    bind = SUPER, 6, workspace, 6
    bind = SUPER, 7, workspace, 7
    bind = SUPER, 8, workspace, 8
    bind = SUPER, 9, workspace, 9
    bind = SUPER, 0, workspace, 10
    bind = SUPER ALT, up, workspace, e+1
    bind = SUPER ALT, down, workspace, e-1

    bind = SUPER SHIFT, 1, movetoworkspace, 1
    bind = SUPER SHIFT, 2, movetoworkspace, 2
    bind = SUPER SHIFT, 3, movetoworkspace, 3
    bind = SUPER SHIFT, 4, movetoworkspace, 4
    bind = SUPER SHIFT, 5, movetoworkspace, 5
    bind = SUPER SHIFT, 6, movetoworkspace, 6
    bind = SUPER SHIFT, 7, movetoworkspace, 7
    bind = SUPER SHIFT, 8, movetoworkspace, 8
    bind = SUPER SHIFT, 9, movetoworkspace, 9
    bind = SUPER SHIFT, 0, movetoworkspace, 10

    bindm = SUPER, mouse:272, movewindow
    bindm = SUPER, mouse:273, resizewindow
    bind = SUPER, mouse_down, workspace, e+1
    bind = SUPER, mouse_up, workspace, e-1
  '';
in
{
  xdg.configFile."hypr/hyprland.conf".text = hyprlandConf;

  programs.swaylock.settings = {
    ignore-empty-password = true;
	  show-failed-attempts  = true;
	  indicator-caps-lock  = true;
	  image = "$HOME/.config/wall";
	  scaling = "fill";
	  font = "Iosevka Nerd Font";
	  font-size = 45;
	  indicator-radius = 170;
	  indicator-thicknes = 15;
	  bs-hl-color  = "94E2D5";
	  key-hl-color  = "94E2D5";
	  caps-lock-bs-hl-color  = "94E2D5";
	  caps-lock-key-hl-color  = "94E2D5";
	  inside-color = "1E1E2E";
	  inside-clear-color = "1E1E2E";
	  inside-caps-lock-color = "1E1E2E";
	  inside-ver-color = "1E1E2E";
	  inside-wrong-color = "1E1E2E";
	  line-color = "00000000";
	  line-clear-color = "00000000";
	  line-caps-lock-color = "00000000";
	  line-ver-color = "00000000";
	  line-wrong-color = "00000000";
	  ring-color = "FAB387";
	  ring-clear-color = "F9E2AF";
	  ring-caps-lock-color = "FAB387";
	  ring-ver-color = "A6E3A1";
	  ring-wrong-color = "F38BA8";
	  separator-color = "00000000";
	  text-color  = "94E2D5";
	  text-clear-color  = "94E2D5";
	  text-ver-color  = "94E2D5";
	  text-wrong-color  = "94E2D5";
	  text-caps-lock-color = "94E2D5";
  };

  services.swayidle = {
    enable = true;
    events = [
      { event = "before-sleep"; command = "${pkgs.swaylock}/bin/swaylock -f"; }
      { event = "lock"; command = "lock"; }
    ];
    timeouts = [
      { timeout = 300; command = "${pkgs.swaylock}/bin/swaylock -f";}
      { timeout = 480; command = "systemctl suspend"; }
    ];
    systemdTarget = "xdg-desktop-portal-hyprland.service";
  };
}

Hyprland crash logo

--------------------------------------------
   Hyprland Crash Report
--------------------------------------------
I don't feel so good...

Hyprland received signal 6 (Aborted)

System info:
	System name: Linux
	Node name: personal
	Release: 6.2.6
	Version: #1-NixOS SMP PREEMPT_DYNAMIC Mon Mar 13 09:26:43 UTC 2023

GPU:
	04:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Lucienne [1002:164c] (rev c1) (prog-if 00 [VGA controller])


os-release:
	BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues"
	BUILD_ID="23.05.20230315.ac718d0"
	DOCUMENTATION_URL="https://nixos.org/learn.html"
	HOME_URL="https://nixos.org/"
	ID=nixos
	LOGO="nix-snowflake"
	NAME=NixOS
	PRETTY_NAME="NixOS 23.05 (Stoat)"
	SUPPORT_URL="https://nixos.org/community.html"
	VERSION="23.05 (Stoat)"
	VERSION_CODENAME=stoat
	VERSION_ID="23.05"
	


Backtrace:
	#0 | Hyprland() [0x49a69d]
			#1 | Hyprland() [0x515e6f]
			#2 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(+0x3dbf0) [0x7f561903dbf0]
			#3 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(+0x8abc7) [0x7f561908abc7]
			#4 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(raise+0x16) [0x7f561903db46]
			#5 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(abort+0xd7) [0x7f56190284b5]
			#6 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(+0x283d9) [0x7f56190283d9]
			#7 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(+0x367b6) [0x7f56190367b6]
			#8 | /nix/store/wflz2jwax6pirbr0gf25i4cwmcm9z4j7-wlroots-hyprland-hidpi-2023-03-02_5ae17de/lib/libwlroots.so.12(+0x6b2f3) [0x7f5619c9d2f3]
			#9 | /nix/store/wflz2jwax6pirbr0gf25i4cwmcm9z4j7-wlroots-hyprland-hidpi-2023-03-02_5ae17de/lib/libwlroots.so.12(wlr_output_damage_attach_render+0x3d) [0x7f5619cbdbad]
			#10 | Hyprland() [0x514391]
			#11 | Hyprland() [0x4b7c7b]
			#12 | /nix/store/q1h62pjh94fanmw6l3vi2daysny2mwr0-wayland-1.21.0/lib/libwayland-server.so.0(wl_signal_emit_mutable+0x7c) [0x7f5619d508fc]
			#13 | /nix/store/q1h62pjh94fanmw6l3vi2daysny2mwr0-wayland-1.21.0/lib/libwayland-server.so.0(wl_event_loop_dispatch_idle+0x1b) [0x7f5619d526fb]
			#14 | /nix/store/q1h62pjh94fanmw6l3vi2daysny2mwr0-wayland-1.21.0/lib/libwayland-server.so.0(wl_event_loop_dispatch+0xfa) [0x7f5619d5281a]
			#15 | /nix/store/q1h62pjh94fanmw6l3vi2daysny2mwr0-wayland-1.21.0/lib/libwayland-server.so.0(wl_display_run+0x25) [0x7f5619d50335]
			#16 | Hyprland() [0x42e26c]
			#17 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(+0x2924e) [0x7f561902924e]
			#18 | /nix/store/8bmp6r3a0xfha3wj36phlc47clh9w81l-glibc-2.35-224/lib/libc.so.6(__libc_start_main+0x89) [0x7f5619029309]
			#19 | Hyprland() [0x444375]
		

Log tail:
[LOG] Framebuffer created, status 36053
[LOG] LayerSurface 3290d60 destroyed
[LOG] Callback 328cc78 -> 328cc70, layerSurface removed.
[LOG] Callback 328cb40 -> 328cb38, layerSurface removed.
[LOG] Callback 328cba8 -> 328cba0, layerSurface removed.
[LOG] Callback 328cc10 -> 328cc08, layerSurface removed.
[LOG] Callback 328cce0 -> 328ccd8, layerSurface removed.
[LOG] LayerSurface 32b3c40 arranged: x: 0 y: 0 w: 1920 h: 41 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] Monitor eDP-1 layers arranged: reserved: 0.000000 41.000000 0.000000 0.000000
[LOG] LayerSurface 3047be0 unmapped
[LOG] Framebuffer created, status 36053
[LOG] LayerSurface 3047be0 destroyed
[LOG] Callback 32b3e38 -> 32b3e30, layerSurface removed.
[LOG] Callback 32b3d00 -> 32b3cf8, layerSurface removed.
[LOG] Callback 32b3d68 -> 32b3d60, layerSurface removed.
[LOG] Callback 32b3dd0 -> 32b3dc8, layerSurface removed.
[LOG] Callback 32b3ea0 -> 32b3e98, layerSurface removed.
[LOG] Monitor eDP-1 layers arranged: reserved: 0.000000 0.000000 0.000000 0.000000
[LOG] Removed monitor eDP-1!
[LOG]  [hookSystem] New hook event registered: monitorRemoved
[LOG] moveWorkspaceToMonitor: Moving 1 to monitor 1
[LOG] moveWorkspaceToMonitor: Plugging gap with new 4
[LOG] moveWorkspaceToMonitor: Plugging gap with existing 4
[LOG] Changed to workspace 1
[LOG]  [hookSystem] New hook event registered: workspace
[LOG] Changed to workspace 4
[LOG] moveWorkspaceToMonitor: SWITCHINGISACTIVE, active 2 -> 1
[LOG]  [hookSystem] New hook event registered: moveWorkspace
[LOG] Destroying workspace ID 4
[LOG]  [hookSystem] New hook event registered: destroyWorkspace
[LOG] Applying monitor rule for HDMI-A-1
[LOG] Monitor HDMI-A-1: requested 3840x2160@60.000000, found available mode: 3840x2160@60000mHz, applying.
[LOG] Monitor HDMI-A-1 -> destroyed all render data
[LOG] LayerSurface 32ae180 arranged: x: 1920 y: 0 w: 1920 h: 41 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] LayerSurface 32890e0 arranged: x: 1920 y: 0 w: 1920 h: 1080 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] Monitor HDMI-A-1 layers arranged: reserved: 0.000000 41.000000 0.000000 0.000000
[LOG] Monitor HDMI-A-1 data dump: res 3840x2160@60.00Hz, scale 2.00, transform 0, pos 1920x0, 10b 0
[LOG] LayerSurface 32ae180 arranged: x: 1920 y: 0 w: 1920 h: 41 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] LayerSurface 32890e0 arranged: x: 1920 y: 0 w: 1920 h: 1080 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] Monitor HDMI-A-1 layers arranged: reserved: 0.000000 41.000000 0.000000 0.000000
[LOG] Applying monitor rule for DP-1
[LOG] Monitor DP-1: requested 3840x2160@59.997002, found available mode: 3840x2160@59997mHz, applying.
[LOG] Monitor DP-1 -> destroyed all render data
[LOG] LayerSurface 2d895b0 arranged: x: 0 y: 0 w: 1920 h: 41 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] LayerSurface 328e570 arranged: x: 0 y: 0 w: 1920 h: 1080 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] Monitor DP-1 layers arranged: reserved: 0.000000 41.000000 0.000000 0.000000
[LOG] Monitor DP-1 data dump: res 3840x2160@60.00Hz, scale 2.00, transform 0, pos 0x0, 10b 0
[LOG] LayerSurface 2d895b0 arranged: x: 0 y: 0 w: 1920 h: 41 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] LayerSurface 328e570 arranged: x: 0 y: 0 w: 1920 h: 1080 with margins: t: 0 l: 0 r: 0 b: 0
[LOG] Monitor DP-1 layers arranged: reserved: 0.000000 41.000000 0.000000 0.000000

Kanshi config

profile home {
  output eDP-1 enable mode 1920x1200 position 0,0 scale 1
}

profile home {
	output "Dell Inc. DELL S2722QC FL7WLD3" mode 3840x2160@59.997002 position 0,0 scale 2
	output "Dell Inc. DELL S2722QC C77WLD3" mode 3840x2160@60.000000position 1920,0 scale 2
	output eDP-1 disable
}

hyprctl monitors output

~> hyprctl monitors
Monitor eDP-1 (ID 0):
	1920x1080@60.020000 at 0x0
	description: LG Display 0x0683 (eDP-1)
	make: LG Display
	model: 0x0683
	serial:
	active workspace: 3 (3)
	reserved: 0 41 0 0
	scale: 1.00
	transform: 0
	focused: no
	dpmsStatus: 1
	vrr: 0

Monitor HDMI-A-1 (ID 1):
	3840x2160@60.000000 at 1920x0
	description: Dell Inc. DELL S2722QC C77WLD3 (HDMI-A-1)
	make: Dell Inc.
	model: DELL S2722QC
	serial: C77WLD3
	active workspace: 2 (2)
	reserved: 0 41 0 0
	scale: 1.50
	transform: 0
	focused: yes
	dpmsStatus: 1
	vrr: 0

Monitor DP-1 (ID 2):
	3840x2160@59.997002 at 5760x0
	description: Dell Inc. DELL S2722QC FL7WLD3 (DP-1)
	make: Dell Inc.
	model: DELL S2722QC
	serial: FL7WLD3
	active workspace: 4 (4)
	reserved: 0 41 0 0
	scale: 1.50
	transform: 0
	focused: no
	dpmsStatus: 1
	vrr: 0

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 2
  • Comments: 29 (8 by maintainers)

Most upvoted comments

When disconnecting the external monitor, the internal monitor doesn’t turn on again and after interacting with hyprland (switching workspaces) hyprland crashes.

Can confirm. There is a log of kanshi, probably can clarify smth

Jul 25 19:27:42 thinkpad-x1-gen9 systemd[4311]: Started Dynamic output configuration.

-------- INITIAL CONFIGURATION, NOTHING CONNECTED TO LAPTOP ----------
Jul 25 19:27:42 thinkpad-x1-gen9 kanshi[4501]: applying profile 'laptopOnly'
Jul 25 19:27:42 thinkpad-x1-gen9 kanshi[4501]: applying profile output 'eDP-1' on connected head 'eDP-1'
Jul 25 19:27:42 thinkpad-x1-gen9 kanshi[4501]: configuration for profile 'laptopOnly' applied

-------- PLUG IN EXTERNAL MONITOR ----------
Jul 25 19:29:23 thinkpad-x1-gen9 kanshi[4501]: applying profile 'withDellDisplay'
Jul 25 19:29:23 thinkpad-x1-gen9 kanshi[4501]: applying profile output 'Dell Inc. DELL U2723QE JSJ91P3' on connected head 'DP-3'
Jul 25 19:29:23 thinkpad-x1-gen9 kanshi[4501]: applying profile output 'eDP-1' on connected head 'eDP-1'
Jul 25 19:29:24 thinkpad-x1-gen9 kanshi[4501]: configuration for profile 'withDellDisplay' cancelled, retrying
Jul 25 19:29:24 thinkpad-x1-gen9 kanshi[4501]: applying profile 'withDellDisplay'
Jul 25 19:29:24 thinkpad-x1-gen9 kanshi[4501]: applying profile output 'Dell Inc. DELL U2723QE JSJ91P3' on connected head 'DP-3'
Jul 25 19:29:24 thinkpad-x1-gen9 kanshi[4501]: applying profile output 'eDP-1' on connected head 'eDP-1'
Jul 25 19:29:24 thinkpad-x1-gen9 kanshi[4501]: configuration for profile 'withDellDisplay' applied
Jul 25 19:29:24 thinkpad-x1-gen9 kanshi[4501]: no profile matched

-------- DISCONNECT MONITOR ----------
Jul 25 21:09:49 thinkpad-x1-gen9 kanshi[4501]: no profile matched
Jul 25 21:09:58 thinkpad-x1-gen9 kanshi[4501]: no profile matched

Moreover, when I run kanshi after e-DP is turned off it prints: no profile matched seems like hyprland not report that output if it already disabled. I guess hyprland not reports turned off outputs and therefore kanshi can’t detect e-DP output after external monitor disconnect

❯ hyprctl monitors
Monitor DP-3 (ID 1):
	3840x2160@59.997002 at 0x0
	description: Dell Inc. DELL U2723QE JSJ91P3 (DP-3)
	make: Dell Inc.
	model: DELL U2723QE
	serial: JSJ91P3
	active workspace: 3 (3)
	special workspace: 0 ()
	reserved: 0 34 0 0
	scale: 1.00
	transform: 0
	focused: yes
	dpmsStatus: 1
	vrr: 0
	```

@LU15W1R7H

I’m inclined to disagree that this is how hyprland should behave. It should still be possible to re-enable the monitor and bring it back.

This comment posted in another issue might be relevant to this: https://github.com/hyprwm/Hyprland/issues/1274#issuecomment-1573388218

Seems like “out of spec” behaviour

I think the problem could easily be solved by Hyprland. It would only have to enable any remaining monitor when all the others are gone. Should only crash when there are no displays left (not disabled).

@alexandru0-dev Thank you! I can confirm that the issue is not present when building from the latest commit on the master branch.

@AlexNabokikh if u are using nixos (I seen your config in your repos) use the hyprland flake, it’s highly recommended (u can follow the wiki)

This will also allow you to build from master or a pinned tag/commit

@AlexNabokikh try building hyprland from the last master as at some point it was introduced a regression which broke this again and then got it fixed recently

U can check: https://github.com/hyprwm/Hyprland/issues/4725 https://github.com/hyprwm/Hyprland/issues/4728

Good point. Didn’t realize how DPMS behaves.

I didn’t mean to infer how Hyprland should work, I was merely suggesting that the current behavior is expected given Hyprland “specs”.

I did a naive test and it seems that kanshi can actually enable a monitor that has been previously disabled but not under all circumstances. My tests (eDP-1 and DP-1 are connected at the beginning, I’m using kanshi as a user systemd service):

This brings a disabled monitor back up as long as proper profile exists in kanshi, works for both monitors (not at the same time):

hyprctl keyword monitor 'DP-1,disable'
systemctl --user restart kanshi

But this doesn’t:

hyprctl keyword monitor 'DP-1,disable'
<disconnect DP-1 physically (USB-C dock in my case)>
<connect it back>

The monitor doesn’t come back up, even if kanshi is restarted, until hyprctl reload is executed. That is suboptimal but at least consistently reproducible. According to kanshi logs, the disable command doesn’t register with kanshi and after DP-1 is disabled, the physical disconnect doesn’t register with kanshi either. It is only when I reconnect the dock again when kanshi pick it up but even then, it doesn’t see DP-1 and just applies the eDP-1-only profile. After hyprctl reload is executed, kanshi picks up the correct config on its own.

If the disabled monitor in the latter case is eDP-1, Hyprland crashes*)

I have no solid knowledge how any of kanshi, Hyprland and wlr protocols work so I’m not going to draw any conclusions here, just offering an observation.

This is definitely a bug, Hyprland shouldn’t crash. It should, at least, shut down gracefully but somehow I feel that if the discrepancy between the two above described cases is understood, the fix could possibly be inferred, though it could be in kanshi and not Hyprland. Or both.

edit: *) eDP-1 screen is just off after disconnect but nothing happens until I actually reconnect DP-1 back. It is only then when Hyprland crashes. Same if I use similar kanshi profile as OP (that is, eDP-1 off when other screens exist).