{ pkgs, ... }: let audio = pkgs.writeShellScript "audio" '' export PATH=${ with pkgs; lib.makeBinPath [ pulseaudio findutils gnugrep ] }:$PATH export MUTEFILE=''${TEMPDIR:-/tmp}/.qtilemute case $1 in mute) newstate=$(( $(cat $MUTEFILE || echo 0 ) ^ 1 )) echo -n $newstate > $MUTEFILE pactl list short sinks | awk '{ print $1 }' | xargs -L1 -I {} pactl set-sink-mute {} $newstate ;; lower) pactl list short sinks | awk '{ print $1 }' | xargs -L1 -I {} pactl set-sink-volume {} -10% ;; raise) pactl list short sinks | awk '{ print $1 }' | xargs -L1 -I {} pactl set-sink-volume {} +10% ;; *) echo Unknown command: $1 exit 1 ;; esac ''; terminalCommand = "${pkgs.alacritty}/bin/alacritty"; dpmsScript = pkgs.writeShellScript "dpmsScript" '' export PATH=${with pkgs; lib.makeBinPath [ xorg.xset ]}:$PATH set -xe case $1 in default) xset dpms 0 0 0 xset s off xset s noblank xset s 0 0 xset -dpms ;; standby) xset dpms 5 5 5 ;; *) echo Unknown command: $1 exit 1 ;; esac ''; screenLockCommand = pkgs.writeShellScript "screenLock" '' export PATH=${with pkgs; lib.makeBinPath [ i3lock ]}:$PATH revert() { ${dpmsScript} default } trap revert HUP INT TERM ${dpmsScript} standby i3lock -n -c 000000 -e -f revert ''; initScreen = pkgs.writeShellScript "initScreen" '' # ${pkgs.xorg.xinput}/bin/xinput set-prop "ZSA Moonlander Mark I Mouse" "libinput Natural Scrolling Enabled" 1 ${pkgs.autorandr}/bin/autorandr -c ${pkgs.feh}/bin/feh --bg-scale ${pkgs.nixos-artwork.wallpapers.simple-blue}/share/artwork/gnome/nix-wallpaper-simple-blue.png ${dpmsScript} default ''; qtileConfig = pkgs.writeScript "qtile_config.py" '' from libqtile.config import Key, Screen, Group, Drag, Click from libqtile.command import lazy from libqtile import layout, bar, widget from libqtile import hook import logging, os logger = logging.getLogger() logger.setLevel(logging.WARN) handler = logging.handlers.RotatingFileHandler( os.path.join(os.getenv('TEMPDIR', default="/tmp"), '.qtilelog'), maxBytes=10240000, backupCount=7 ) handler.setLevel(logging.WARN) logger.addHandler(handler) key_super = "mod4" key_alt = "mod1" key_control = "control" keys = [ # https://github.com/qtile/qtile/blob/master/libqtile/backend/x11/xkeysyms.py Key([key_super], "Return", lazy.spawn("${terminalCommand}")), Key([key_super], "r", lazy.spawncmd()), Key([key_super], "w", lazy.window.kill()), Key([key_alt, key_super], "l", lazy.spawn('${pkgs.bash}/bin/sh -c "loginctl lock-session $XDG_SESSION_ID"')), Key([key_alt, key_super], "s", lazy.spawn("${pkgs.systemd}/bin/systemctl suspend")), Key([key_super, key_control], "r", lazy.spawn("${initScreen}")), Key([key_super, key_control], "q", lazy.shutdown()), # Toggle between different layouts as defined below Key([key_super], "Tab", lazy.next_layout()), # this is usefull when floating windows get buried Key([key_super], "Escape", lazy.window.bring_to_front()), # common to all layouts Key([key_control, key_alt], "h", lazy.layout.grow_left()), Key([key_control, key_alt], "j", lazy.layout.grow_down()), Key([key_control, key_alt], "k", lazy.layout.grow_up()), Key([key_control, key_alt], "l", lazy.layout.grow_right()), Key([key_super], "n", lazy.layout.normalize()), Key([key_super], "o", lazy.layout.maximize()), # MonadTall keybindings Key([key_super], "h", lazy.layout.left().when(layout="monad")), Key([key_super], "l", lazy.layout.right().when(layout="monad")), Key([key_super], "j", lazy.layout.down().when(layout="monad")), Key([key_super], "k", lazy.layout.up().when(layout="monad")), Key([key_super, key_control], "h", lazy.layout.shuffle_left().when(layout="monad")), Key([key_super, key_control], "l", lazy.layout.shuffle_right().when(layout="monad")), Key([key_super, key_control], "j", lazy.layout.shuffle_down().when(layout="monad")), Key([key_super, key_control], "k", lazy.layout.shuffle_up().when(layout="monad")), Key([key_super, key_control], "space", lazy.layout.toggle_split().when(layout="monad")), # Stack Key([key_super], "h", lazy.layout.previous().when(layout='stack')), Key([key_super], "l", lazy.layout.next().when(layout='stack')), Key([key_super], "j", lazy.layout.up().when(layout='stack')), Key([key_super], "k", lazy.layout.down().when(layout='stack')), Key([key_super, key_control], "j", lazy.layout.shuffle_up().when(layout='stack')), Key([key_super, key_control], "k", lazy.layout.shuffle_down().when(layout='stack')), Key([key_super, key_control], "h", lazy.layout.client_to_previous().when(layout='stack')), Key([key_super, key_control], "l", lazy.layout.client_to_next().when(layout='stack')), # Columns Key([key_super], "h", lazy.layout.left().when(layout="columns")), Key([key_super], "l", lazy.layout.right().when(layout="columns")), Key([key_super], "j", lazy.layout.next().when(layout="columns")), Key([key_super], "k", lazy.layout.previous().when(layout="columns")), Key([key_super, key_control], "j", lazy.layout.shuffle_down().when(layout="columns")), Key([key_super, key_control], "k", lazy.layout.shuffle_up().when(layout="columns")), Key([key_super, key_control], "h", lazy.layout.shuffle_left().when(layout="columns")), Key([key_super, key_control], "l", lazy.layout.shuffle_right().when(layout="columns")), Key([key_super, key_control], "space", lazy.layout.toggle_split().when(layout="columns")), # Max Key([key_super], "j", lazy.layout.down().when(layout="max")), Key([key_super], "k", lazy.layout.up().when(layout="max")), # TODO: these are required to make the 'columns' layout work, but why? Key([key_super], "j", lazy.layout.next()), Key([key_super], "k", lazy.layout.previous()), # Multimedia Keys Key([], "XF86AudioPlay", lazy.spawn("${pkgs.playerctl}/bin/playerctl play-pause")), Key([], "XF86AudioPrev", lazy.spawn("${pkgs.playerctl}/bin/playerctl previous")), Key([], "XF86AudioNext", lazy.spawn("${pkgs.playerctl}/bin/playerctl next")), # TODO: the next two don't work yet Key([], "XF86AudioRewind", lazy.spawn("${pkgs.playerctl}/bin/playerctl offset 10-")), Key([], "XF86BackForward", lazy.spawn("${pkgs.playerctl}/bin/playerctl offset 10+")), Key([], "XF86AudioMute", lazy.spawn("${audio} mute")), Key([], "XF86AudioLowerVolume", lazy.spawn("${audio} lower")), Key([], "XF86AudioRaiseVolume", lazy.spawn("${audio} raise")), Key([], "Print", lazy.spawn("${pkgs.flameshot}/bin/flameshot gui")), ] groups = [Group(i) for i in "1234567890"] for i in groups: # super + letter of group = switch to group keys.append( Key([key_super], i.name, lazy.group[i.name].toscreen()) ) # super + shift + letter of group = switch to & move focused window to group keys.append( Key([key_super, key_control], i.name, lazy.window.togroup(i.name)) ) layouts = [ layout.Columns(num_columns=3, border_focus='#00ff00', border_width=2), layout.Max(), # layout.Stack(num_stacks=3, border_focus='#00ff00', border_width=2, autosplit=True, previous_on_rm=True), # layout.Wmii(border_focus='#00ff00'), # layout.MonadTall(ratio=0.6, border_focus='#00ff00'), ] widget_defaults = dict( font='Arial', fontsize=16, padding=3, ) screens_count = 4 screens = [] for i in range(0, screens_count+1): j = i+1 widgets = [ widget.TextBox("Screen %i" % j, name="Screen %i" % j), widget.GroupBox(), widget.WindowName(), widget.Prompt(), widget.CPUGraph(), widget.ThermalSensor(tag_sensor = "CPU"), widget.Memory(), # widget.Net(interface='eth0'), widget.Net(interface='wlan0'), widget.Clock(format='%Y-%m-%d %a %I:%M %p'), ] if i is 0: widgets.insert(-1, widget.Systray()) screens.append(Screen(bottom=bar.Bar(widgets, 30))) keys.append(Key([key_super, "shift"], "%i" % (i+1), lazy.to_screen(i))) dgroups_key_binder = None dgroups_app_rules = [] follow_mouse_focus = False bring_front_click = False cursor_warp = False auto_fullscreen = True auto_minimize = False # focus_on_window_activation = "urgent" # Drag floating layouts. mouse = [ # Drag([key_super,key_control], "Button1", lazy.window.set_position_floating(), start=lazy.window.get_position()), # Drag([key_super,key_control], "Button2", lazy.window.set_size_floating(), start=lazy.window.get_size()), Click([key_super,key_control], "Button3", lazy.window.disable_floating()) ] # disable any floating @hook.subscribe.client_new def disable_floating_for_all_new_windows(window): window.floating = False @hook.subscribe.client_new def print_new_window(window): print("new window: ", window) ''; in { services = { gnome-keyring.enable = true; blueman-applet.enable = true; screen-locker = { enable = true; inactiveInterval = 7; lockCmd = "${screenLockCommand}"; }; network-manager-applet.enable = true; flameshot.enable = true; pasystray.enable = true; cbatticon.enable = true; }; home.pointerCursor = { name = "Vanilla-DMZ"; package = pkgs.vanilla-dmz; size = 32; x11.enable = true; gtk.enable = true; }; xsession = { enable = false; windowManager.command = "${pkgs.qtile}/bin/qtile start -c ${qtileConfig}"; initExtra = "${initScreen}"; }; home.packages = with pkgs; [ # X Tools/Libraries lightdm networkmanagerapplet gnome-icon-theme gnome.gnome-themes-extra gnome.adwaita-icon-theme lxappearance xorg.xcursorthemes pavucontrol lm_sensors ]; }