Help with Home Manager, Sway, and Generic Linux

My main Questions

Thank you so much for your time and patience :green_heart:

  1. Should I split these topics into separate help threads?
  2. Am I even taking the right approach? Would it be simpler if I installed all the window manager packages with the host’s apt and only did the configurations with package = null in home-manager?
  3. How do I solve the issues I (presumably) have with DBus?
  4. How can I get theme switching fully working, as gsettings doesn’t affect all (but most) apps?
  5. Am I doing the scaling correctly?
  6. Am I doing the guarding for the services with regards to sway vs. i3 correctly?

What I am doing

I have a machine that (has to) run Debian Trixie with KDE/Plasma/SDDM. I use home-manager in standalone mode to install and configure sway and i3 alongside the host’s Plasma session.

Most of it works, but some things don’t work and other problems were likely not solved “correctly”. I had to brute force a few “solutions” since I didn’t find enough information online.

  • nix --version: nix (Nix) 2.33.1
Some of the flakes and how I set them up

In my dotfiles, these are some of the details of how I set things up. I am sure it contains non-sensical or wrong stuff, since I am not yet confident with nix or home-manager. I am happy about any and all pointers on how I can improve things.

hosts/schenck-debian/default.nix

hosts/schenck-debian/default.nix (excerpt):

{
  config,
  lib,
  ...
}:
{
  targets.genericLinux.enable = true;

  home.file.".config/plasma-workspace/env/10-home-manager-xdg-data-dirs.sh" = {
    executable = true;
    text = ''
      #!/bin/sh
      export XDG_DATA_DIRS="${config.home.sessionVariables.XDG_DATA_DIRS}"
    '';
  };

  home.sessionVariables = {
    XDG_CONFIG_HOME = "$HOME/.config";
    XDG_CACHE_HOME = "$HOME/.cache";
    XDG_DATA_HOME = "$HOME/.local/share";
    XDG_STATE_HOME = "$HOME/.local/state";
  };
  systemd.user.sessionVariables = {
    XDG_CONFIG_HOME = "$HOME/.config";
    XDG_CACHE_HOME = "$HOME/.cache";
    XDG_DATA_HOME = "$HOME/.local/share";
    XDG_STATE_HOME = "$HOME/.local/state";
  };

  systemd.user = {
    services.polkit-kde-agent = {
      # A polkit agent for graphical privilege escalation.
      Unit = {
        Description = "KDE Polkit Authentication Agent";
        After = [
          "graphical-session.target"
          "dbus.service"
        ];
        PartOf = [ "graphical-session.target" ];
        # Only start in sway and i3, not e.g. plasma:
        ExecCondition = "/bin/bash -c '[ $XDG_CURRENT_DESKTOP = sway ] || [ $XDG_CURRENT_DESKTOP = i3 ]'";
      };

      Service = {
        Type = "simple";
        ExecStart = "/usr/lib/x86_64-linux-gnu/libexec/polkit-kde-authentication-agent-1";
        Restart = "on-failure";
        RestartSec = 1;
      };

      Install = {
        WantedBy = [ "graphical-session.target" ];
      };
    };
  };

  wayland.windowManager.sway = {
    config = {
      output = {
        "HDMI-A-1" = {
          scale = "2";
          bg = "${../../assets/images/daniel-leone-v7daTKlZzaw-unsplash.jpg} fill";
        };
      };
    };
  };

  # Uses home-manager standalone module on debian linux:
  imports = [
    ./screencast.nix
    ../../home/linux-desktop.nix
    ../../home/standalone.nix
  ];
}
home/linux-desktop.nix

home/linux-desktop.nix (excerpt):

  # Scaling in xresources:
  xresources = {
    extraConfig = ''
      *dpi: 192
      Xft.dpi: 192
      Xcursor.size: 48
    '';
  };
  home.file.".local/bin/lightmode.sh" = {
    executable = true;
    text = # bash
      ''
        #!/usr/bin/env bash

        printf "light" > ~/.config/current_theme_store

        gsettings set org.gnome.desktop.interface gtk-theme 'Breeze'
        gsettings set org.gnome.desktop.interface icon-theme 'breeze'
        gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'

        tmux source-file ~/.config/tmux/tmux.conf
        pkill -USR1 zsh
      '';
  };
  home.file.".local/bin/darkmode.sh" = {
    executable = true;
    text = # bash
      ''
        #!/usr/bin/env bash

        printf "dark" > ~/.config/current_theme_store

        gsettings set org.gnome.desktop.interface gtk-theme 'Breeze-Dark'
        gsettings set org.gnome.desktop.interface icon-theme 'breeze-dark'
        gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'

        tmux source-file ~/.config/tmux/tmux.conf
        pkill -USR1 zsh
      '';
  };
configs/i3-sway/sway.nix

configs/i3-sway/sway.nix:

{ lib, pkgs, ... }:
{
  home.file.".local/bin/start-sway.sh" = {
    executable = true;
    text = # bash
      ''
        #!/usr/bin/env bash

        # Session
        export XDG_SESSION_TYPE=wayland
        export XDG_SESSION_DESKTOP=sway
        export XDG_CURRENT_DESKTOP=sway

        # Wayland stuff
        export MOZ_ENABLE_WAYLAND=1
        export QT_QPA_PLATFORM=wayland
        export SDL_VIDEODRIVER=wayland
        export _JAVA_AWT_WM_NONREPARENTING=1
        export NIXOS_OZONE_WL=1

        exec ${pkgs.sway}/bin/sway "$@"
      '';
  };

  wayland.windowManager.sway = {
    enable = true;
    # This also starts a systemd sway-session.target:
    systemd.enable = true;

    wrapperFeatures.gtk = true; # Include fixes for GTK apps under Sway

    config =
      let
        commonConfig = import ./common-config.nix {
          inherit lib pkgs;
          commands = {
            powerCommand = "exec ~/.local/bin/powermenu.sh fuzzel";
            settingsCommand = "exec ~/.local/bin/settingsmenu.sh fuzzel";
            notificationDismissCommand = "exec ${pkgs.mako}/bin/makoctl dismiss";
            applicationCommand = "exec ${pkgs.fuzzel}/bin/fuzzel";
            emojiCommand = "exec ${pkgs.bemoji}/bin/bemoji --type";
            audioUpCommand = "exec ${pkgs.avizo}/bin/volumectl -u up";
            audioDownCommand = "exec ${pkgs.avizo}/bin/volumectl -u down";
            audioMuteCommand = "exec ${pkgs.avizo}/bin/volumectl toggle-mute";
            audioMicMuteCommand = "exec ${pkgs.avizo}/bin/volumectl -m toggle-mute";
            brightnessUpCommand = "exec ${pkgs.avizo}/bin/lightctl up";
            brightnessDownCommand = "exec ${pkgs.avizo}/bin/lightctl down";
            searchCommand = "exec ${pkgs.fuzzel}/bin/fuzzel";
          };
        };
      in
      lib.recursiveUpdate commonConfig {
        startup = [
          {
            command = ''
              swayidle -w \
                timeout 300 'swaylock -fF' \
                timeout 600 'swaymsg "output * dpms off"' \
                resume 'swaymsg "output * dpms on"' \
                before-sleep 'swaylock -fF'
            '';
          }

          {
            command = "nm-applet";
          }
        ];

        seat = {
          "*" = {
            hide_cursor = "when-typing enable";
          };
        };

        input = {
          "type:keyboard" = {
            # Map capslock to escape:
            "xkb_options" = "caps:escape";

            "repeat_delay" = "200";
            "repeat_rate" = "50";
          };
        };

        bars = [
          {
            command = "${pkgs.waybar}/bin/waybar";
          }
        ];
      };

    extraConfig = # swayconfig
      ''
        for_window [shell="xwayland"] title_format "[XWayland] %title"

        # Make sure tmux-server, etc. exit when sway exits so that new sessions
        # start with new servers that attach to the correct dbus, etc.
        exec --no-startup-id swaymsg -mt subscribe '[]' || true && ${pkgs.tmux}/bin/tmux kill-server
        exec --no-startup-id swaymsg -mt subscribe '[]' || true && pkill ghostty
        exec --no-startup-id swaymsg -mt subscribe '[]' || true && systemctl --user stop mako.service
      '';
  };
}
configs/i3-sway/i3.nix

configs/i3-sway/i3.nix:

{ lib, pkgs, ... }:
{
  home.file.".local/bin/start-i3.sh" = {
    executable = true;
    text = # bash
      ''
        #!/usr/bin/env bash

        unset MOZ_ENABLE_WAYLAND
        unset QT_QPA_PLATFORM
        unset SDL_VIDEODRIVER
        unset _JAVA_AWT_WM_NONREPARENTING
        unset NIXOS_OZONE_WL

        unset WAYLAND_DISPLAY
        unset XDG_SESSION_TYPE
        unset XDG_SESSION_DESKTOP
        unset XDG_CURRENT_DESKTOP

        export XDG_SESSION_TYPE=x11
        export XDG_SESSION_DESKTOP=i3
        export XDG_CURRENT_DESKTOP=i3

        exec ${pkgs.i3}/bin/i3 "$@"
      '';
  };

  xsession.windowManager.i3 = {
    enable = true;

    config =
      let
        commonConfig = import ./common-config.nix {
          inherit lib pkgs;
          commands = {
            powerCommand = "exec ~/.local/bin/powermenu.sh rofi";
            settingsCommand = "exec ~/.local/bin/settingsmenu.sh rofi";
            # dunst manages its shortcut itself:
            notificationDismissCommand = null;
            applicationCommand = "exec ${pkgs.rofi}/bin/rofi -show drun";
            emojiCommand = null;
            audioUpCommand = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-sink-volume 0 +5%";
            audioDownCommand = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-sink-volume 0 -5%";
            audioMuteCommand = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-sink-mute 0 toggle";
            audioMicMuteCommand = null;
            brightnessUpCommand = "exec --no-startup-id ${pkgs.xbacklight}/bin/xbacklight -inc 20";
            brightnessDownCommand = "exec --no-startup-id ${pkgs.xbacklight}/bin/xbacklight -dec 20";
            searchCommand = "exec ${pkgs.rofi}/bin/rofi -show drun";
          };
        };
      in
      lib.recursiveUpdate commonConfig {
        startup = [
          {
            command = "${pkgs.xautolock}/bin/xautolock -time 5 -locker \"i3lock -n -c 191724\"";
            notification = false;
          }
          {
            # Turn off screen, pc:
            command = "xset dpms 600 900 1200";
            notification = false;
          }

          {
            command = "${pkgs.feh}/bin/feh --no-fehbg --bg-fill ${../../assets/images/daniel-leone-v7daTKlZzaw-unsplash.jpg}";
            always = true;
            notification = false;
          }

          {
            # Keyboard repeat rate:
            command = "${pkgs.xset}/bin/xset r rate 200 50";
            notification = false;
          }
          {
            # Map CapsLock to Escape:
            command = "${pkgs.setxkbmap}/bin/setxkbmap -option caps:escape";
            notification = false;
          }

          {
            command = "systemctl --user restart polybar.service";
            always = true;
            notification = false;
          }

          {
            command = "nm-applet";
            notification = false;
          }
          {
            command = "blueman-applet";
            notification = false;
          }
        ];

        # Polybar is started by start command above using systemctl.
        bars = [ ];
      };

    extraConfig = # i3config
      ''
        # Ensure borders for _all_ windows. Without this, ghostty and vivaldi
        # wouldn't have borders, for example.
        for_window [class="^.*"] border pixel 1

        # Update environment same as in sway module of home-manager:
        exec --no-startup-id ${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE XDG_SESSION_DESKTOP XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed

        # Make sure tmux-server, etc. exit when i3 exits so that new sessions
        # start with new servers that attach to the correct dbus, etc.
        exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && ${pkgs.tmux}/bin/tmux kill-server
        exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && pkill ghostty
        exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && systemctl --user stop polybar.service; systemctl --user stop dunst.service
      '';
  };
}
configs/i3-sway/common-config.nix (likely uninteresting)

configs/i3-sway/i3.nix:

{
  lib,
  pkgs,
  commands,
}:
let
  terminal = "${pkgs.ghostty}/bin/ghostty";
in
{
  focus = {
    followMouse = false;
  };

  fonts = {
    names = [
      "Monaspace Neon"
      "OpenMoji Color"
      "Symbols Nerd Font Mono"
    ];
    size = 13.0;
  };

  # For any defaults left from the sway/i3 modules in home manager:
  modifier = "Mod4"; # Use the Super/Windows key as the Mod key
  terminal = terminal;

  gaps = {
    outer = 6;
    inner = 6;
  };

  window = {
    titlebar = false;
    border = 1;
  };

  defaultWorkspace = "workspace number 1";

  colors = {
    background = "#191724";
    focused = {
      border = "#A19DD4";
      background = "#191724";
      text = "#A2A2A9";
      indicator = "#C394C2";
      childBorder = "#A19DD4";
    };
    focusedInactive = {
      border = "#84848C";
      background = "#0B0A0F";
      text = "#878794";
      indicator = "#37363E";
      childBorder = "#37363E";
    };
    unfocused = {
      border = "#0B0A0F";
      background = "#0B0A0F";
      text = "#878794";
      indicator = "#37363E";
      childBorder = "#37363E";
    };
    placeholder = {
      background = "#191724";
      text = "#A2A2A9";

      # unused
      border = "#000000";
      indicator = "#000000";
      childBorder = "#000000";
    };
  };

  keybindings = lib.mkOptionDefault {
    "Mod4+Shift+a" = "focus child";

    "Mod4+n" = lib.mkIf (
      commands.notificationDismissCommand != null
    ) commands.notificationDismissCommand;

    "Mod4+Shift+e" = lib.mkIf (commands.powerCommand != null) commands.powerCommand;
    "Mod4+Shift+s" = lib.mkIf (commands.settingsCommand != null) commands.settingsCommand;

    "Mod4+d" = lib.mkIf (commands.applicationCommand != null) commands.applicationCommand;
    "Mod4+Shift+d" = lib.mkIf (commands.emojiCommand != null) commands.emojiCommand;

    # Commands provided by avizo.service
    "XF86AudioRaiseVolume" = commands.audioUpCommand;
    "XF86AudioLowerVolume" = commands.audioDownCommand;
    "XF86AudioMute" = commands.audioMuteCommand;
    "XF86AudioMicMute" = lib.mkIf (commands.audioMicMuteCommand != null) commands.audioMicMuteCommand;
    "XF86MonBrightnessUp" = commands.brightnessUpCommand;
    "XF86MonBrightnessDown" = commands.brightnessDownCommand;

    "XF86AudioPlay" = "exec playerctl play-pause";
    "XF86AudioPause" = "exec playerctl play-pause";
    "XF86AudioNext" = "exec playerctl next";
    "XF86AudioPrev" = "exec playerctl previous";
    "XF86AudioStop" = "exec playerctl stop";

    "XF86Search" = lib.mkIf (commands.searchCommand != null) commands.searchCommand;

    # More or less default:
    "Mod4+1" = "workspace number 1";
    "Mod4+0" = "workspace number 10";
    "Mod4+2" = "workspace number 2";
    "Mod4+3" = "workspace number 3";
    "Mod4+4" = "workspace number 4";
    "Mod4+5" = "workspace number 5";
    "Mod4+6" = "workspace number 6";
    "Mod4+7" = "workspace number 7";
    "Mod4+8" = "workspace number 8";
    "Mod4+9" = "workspace number 9";
    "Mod4+Down" = "focus down";
    "Mod4+Left" = "focus left";
    "Mod4+Return" = "exec ${terminal}";
    "Mod4+Right" = "focus right";
    "Mod4+Shift+0" = "move container to workspace number 10";
    "Mod4+Shift+1" = "move container to workspace number 1";
    "Mod4+Shift+2" = "move container to workspace number 2";
    "Mod4+Shift+3" = "move container to workspace number 3";
    "Mod4+Shift+4" = "move container to workspace number 4";
    "Mod4+Shift+5" = "move container to workspace number 5";
    "Mod4+Shift+6" = "move container to workspace number 6";
    "Mod4+Shift+7" = "move container to workspace number 7";
    "Mod4+Shift+8" = "move container to workspace number 8";
    "Mod4+Shift+9" = "move container to workspace number 9";
    "Mod4+Shift+Down" = "move down";
    "Mod4+Shift+Left" = "move left";
    "Mod4+Shift+Right" = "move right";
    "Mod4+Shift+Up" = "move up";
    "Mod4+Shift+c" = "reload";
    "Mod4+Shift+h" = "move left";
    "Mod4+Shift+j" = "move down";
    "Mod4+Shift+k" = "move up";
    "Mod4+Shift+l" = "move right";
    "Mod4+Shift+minus" = "move scratchpad";
    "Mod4+Shift+q" = "kill";
    "Mod4+Shift+space" = "floating toggle";
    "Mod4+Up" = "focus up";
    "Mod4+a" = "focus parent";
    "Mod4+b" = "splith";
    "Mod4+e" = "layout toggle split";
    "Mod4+f" = "fullscreen toggle";
    "Mod4+h" = "focus left";
    "Mod4+j" = "focus down";
    "Mod4+k" = "focus up";
    "Mod4+l" = "focus right";
    "Mod4+minus" = "scratchpad show";
    "Mod4+r" = "mode resize";
    "Mod4+s" = "layout stacking";
    "Mod4+space" = "focus mode_toggle";
    "Mod4+v" = "splitv";
    "Mod4+w" = "layout tabbed";
  };
}
Window Manager Issues

Window Manager Issues

I have found out that I cannot use home-manager’s swaylock or i3lock, as they would always say the password was typed incorrectly. Instead, those two packages I have to install with apt install and then I configured swaylock with package = null;.

I would prefer to set up everything consistently, ideally with everything being in home-manager.

  • How can I get swaylock and i3lock working, if I want to use the home-manager packages?

I got screensharing to work, but full-screen only.

  • Is it possible to only share an app’s window under wayland and sway? Do I have to wait for sway 1.12?
DBus Issues

DBus Issues

I would expect logging out of and back into a session shouldn’t be a problem. E.g. boot SDDM → log into i3 → exit to SDDM → log into i3

Sometimes (not always), when exiting sway or i3 and afterwards logging into sway or i3 (same or different one), I have problems like the following which I assume are caused by DBus:

  • No waybar
    • Some error that the tray cannot register on the bus
  • Ghostty only starts after a huge delay (Konsole as well)

I think maybe the issue appeared more frequently when I ran home-manager switch in the session, but I am not sure about this and it could also be coincidental since the sample size is rather small.

What I tried (and failed):

  • Starting i3 (or sway) with dbus-start-session -- ${pkgs.i3}/bin/i3
    • When doing that, Home Manager would give me a warning when switching. It uses the bus unix:path=/run/user/1000/bus, but ${DBUS_SESSION_BUS_ADDRESS} is set to another bus (with a random, unique ID).
  • Enabling xsession in home-manager:
  • Adding the update of the bus’ ENV variables to i3 (the same way it is done in sway by home manager after enabling wayland.windowManager.sway.systemd.enable = true;), by doing:
    • extraConfig = # i3config
        ''
          # Update environment same as in sway module of home-manager:
          exec --no-startup-id ${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE XDG_SESSION_DESKTOP XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed
        '';
      
  • Tearing stuff down on exit:
    • extraConfig = # i3config
        ''
          # Make sure tmux-server, etc. exit when i3 exits so that new sessions
          # start with new servers that attach to the correct dbus, etc.
          exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && ${pkgs.tmux}/bin/tmux kill-server
          exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && pkill ghostty
          exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && systemctl --user stop polybar.service; systemctl --user stop dunst.service
        '';
      

Do these things even make sense or am I doing nonsensical stuff?

I assume the DBus is causing this issue, but I have no idea how to go about it.

Scaling

Scaling

I am on a HiDPI screen where I want everything to scale 2x. In sway/wayland that’s easily achievable with:

  wayland.windowManager.sway = {
    config = {
      output = {
        "HDMI-A-1" = {
          scale = "2";
        };
      };
    };
  };

However, sometime the mouse cursor gets tiny when it is over specific apps. Especially in todoist-electron. What’s special about todoist-electron? How can I make sure the cursor is the same size there?

To achieve the same in X11/i3, I do:

  • xresources = {
      extraConfig = ''
        *dpi: 192
        Xft.dpi: 192
        Xcursor.size: 48
      '';
    };
    

Do I even need *dpi?

I used to also do:

  • xsession = {
      enable = true;
    
      profileExtra = ''
        # Scaling
        export QT_ENABLE_HIGHDPI_SCALING=1
        export QT_SCALE_FACTOR=2
        export GDK_SCALE=2
      '';
    };
    

But that would also lead to all kinds of DBus/Session problems with i3. I removed the whole block and it doesn’t seem to affect QT or GDK scaling, as everything is still scaled correctly in sway and i3.

Themeing ('solved')

Themeing

:information_source: This works “good enough” now. After playing around in KDE’s system settings, all apps except Vivaldi now follow what I set with gsettings.

I want to be able to switch between light and dark mode. For that, I created scripts like this one for light mode (see `home-linux.nix above for more context):

#!/usr/bin/env bash

gsettings set org.gnome.desktop.interface gtk-theme 'Breeze'
gsettings set org.gnome.desktop.interface icon-theme 'breeze'
gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'

# The rest works as expected

# Sourced by command line tools via aliases (works):
printf "light" > ~/.config/current_theme_store
# Updates the running tmux session (works):
tmux source-file ~/.config/tmux/tmux.conf
# Updates ZSH theme (works):
pkill -USR1 zsh

I would expect all apps to update their theme, but they aren’t. Some apps fully switch over, for example Firefox, Dolphin (file explorer), or ghostty. Vivaldi switches the pages it shows to light mode (e.g. this discourse), but the interface itself doesn’t (even though I set different themes for “OS dark and light”). pavucontrol for example doesn’t switch at all. It stays in dark mode.

I installed the following packages with home-manager: kdePackages.breeze, kdePackages.breeze-gtk, kdePackages.breeze-icons

  • Does this have to do with the underlying Plasma? Am I doing it wrong? What am I missing?
Fonts in Todoist

Fonts in todoist-electron

For some reason, the app displays most of the time but not always the wrong fonts (some ugly serif font). It appears it can neither pick up the bundled fonts, nor the system fonts.

How can I make sure Todoist uses the system fonts (or the bundled ones)? Does this have to do with the fact that it is based on an AppImage or is that unrelated?

Systemd Units' Guards

Systemd Units’ Guards

Since I configure some services with home-manager, home-manager also manages the unit file. Two examples are mako and dunst. I only want to run dunst when in i3 and I only want to run mako when in sway. What I did works, but I wonder if it is even the right way to do this. Having the line at the end of the wm’s config that waits for the exit and then stops the service feels hacky in a way.

Mako

In sway.nix:

wayland.windowManager.sway.systemd.enable = true;

In mako.nix:

  systemd.user.services.mako = {
    Unit = {
      Description = "Lightweight Wayland notification daemon";
      Documentation = "man:mako(1)";
      PartOf = lib.mkForce [ "sway-session.target" ];
      After = lib.mkForce [ "sway-session.target" ];
    };
    Service = {
      Type = "dbus";
      BusName = "org.freedesktop.Notifications";
      ExecCondition = "/bin/sh -c '[ -n \"$WAYLAND_DISPLAY\" ]'";
      ExecStart = "${pkgs.mako}/bin/mako";
      ExecReload = "${pkgs.mako}/bin/makoctl reload";
    };
    Install = {
      WantedBy = lib.mkForce [ "sway-session.target" ];
    };
  };

End of sway config:

exec --no-startup-id swaymsg -mt subscribe '[]' || true && systemctl --user stop mako.service

Dunst

In my dunst.nix file I added:

systemd.user.services.dunst.Service.ExecCondition =
  "/bin/bash -c '[ \"$XDG_CURRENT_DESKTOP\" = \"i3\" ]'";

$XDG_CURRENT_DESKTOP is set by the wrapper script that starts i3:

#!/usr/bin/env bash

unset MOZ_ENABLE_WAYLAND
unset QT_QPA_PLATFORM
unset SDL_VIDEODRIVER
unset _JAVA_AWT_WM_NONREPARENTING
unset NIXOS_OZONE_WL

unset WAYLAND_DISPLAY
unset XDG_SESSION_TYPE
unset XDG_SESSION_DESKTOP
unset XDG_CURRENT_DESKTOP

export XDG_SESSION_TYPE=x11
export XDG_SESSION_DESKTOP=i3
export XDG_CURRENT_DESKTOP=i3

exec ${pkgs.i3}/bin/i3 "$@"

End of i3 config:

exec --no-startup-id ${pkgs.i3}/bin/i3-msg -mt subscribe '[]' || true && systemctl --user stop polybar.service; systemctl --user stop dunst.service

I would recommend this, yeah. They seem largely unrelated, and you’re not going to get a complete answer to everything from any individual, so half of this will get buried.

Sounds more like systemd unit dependency shenanigans. Consider using uwsm.

I don’t think it’s reasonably possible to do this for i3. If you’re already using sway I don’t see the point of having an i3 session, tbh.

Since it’s electron, and electron is forever outdated and misused by applications, it’s rendered with X11, which doesn’t understand hidpi.

To get scaling anyway you need to use the toolkits’ native scaling mechanisms, i.e.:

I’d guess because you’re setting it in xsession. That’ll get in the way of whatever normally happens for i3.

Again, I’d suggest just not using i3 altogether, but if you want to use i3 you should probably come up with a clever set of init scripts that actually clean up correctly, and not just use the home-manager/distro defaults.

For wayland applications, which will be most of them at this point. Xwayland won’t work, on i3 it presumably works because of your Xcursor.size setting, but this doesn’t carry over to Xwayland.

3 Likes

Thanks. I will follow your advice and longer try to make i3 a first class citizen. It’s is only a fallback system and only sway needs all the bells and whistles.

Todoist runs under Wayland, not XWayland, by using NIXOS_OZONE_WL. When I set the scaling variables, other apps are twice the intended size. Overall, it’s a minor annoyance and I think I can get used to it.

Theme switching with gsettings now works for all apps under Wayland, except for Vivaldi. :person_shrugging: And I will no longer try to make it work under i3.

And I will take a look at uwsm, thank you.

All in all, these are all things I can live with. I was just hoping that I don’t have to :sweat_smile: Linux on the desktop has come such a long way :heart:

Thank you so much! :folded_hands:t2:

I don’t think you do; I have none of these issues. There likely is a fix, I just don’t see it off the top of my head, and don’t have the patience to go buy a hidpi monitor and test your configuration to help fix it :wink:

Someone else might know, and you don’t have to give up - there are lots of minor annoyances I only managed to fix years down the line.

Yeah, it really has. Hopefully ubuntu deprecating X11 gets us most of the rest of the way there, so the straggling applications adopt it and the teething issues go away.

After that all we need is, like, adobe providing first-class support for their products, and we may finally witness the year of the Linux desktop :wink:

1 Like

In case someone finds this: I had home-manager‘s gtk module enabled, which hindered theme switching. I removed that config and switching works now for everything except chromium.

Too bad. There’s probably some „correct“ way to do this with the gtk module :sweat_smile:

1 Like