diff --git a/README-Wayland.org b/README-Wayland.org
new file mode 100644
index 0000000..202f032
--- /dev/null
+++ b/README-Wayland.org
@@ -0,0 +1,92 @@
+#+title: Wayland
+
+Install [[https://wiki.archlinux.org/title/wayland][wayland]]: ~wayland~, ~xorg-xwayland~
+
+* Login Manager
+
+The login manager is not managed by this configuration but mentioned here since
+it interacts with the desktop environment. For ~hyprland~, ~sddm~ is
+recommended.
+
+- ~sddm~: Enable ~sddm.service~
+
+ A note about themes: The themes must be placed in ~/usr/share/sddm/themes~.
+ Then in ~/etc/sddm.conf~, enable the relevant theme. By default the breeze
+ theme comes with ~plasma-workspace~ which is very bloated to install, so
+ consider some of the alternative themes.
+
+* Fonts
+
+- ~otf-font-awesome~: Needed for ~waybar~ to render icons
+- Noto Sans/Serif: System font
+
+* Status Bar and Tray
+
+- ~waybar~: Status bar, use ~waybar-hyprland-git~ AUR repo to enable clicking!
+- ~eww-wayland~: Another status bar, requires ~socat~ to listen for hyprland events.
+
+* Sway
+
+This is one choice of a compositor.
+
+- ~swayfx~: Window manager
+- ~python-i3ipc~: Enables inactive window opacity scripts
+
+** Wallpaper
+Use ~multibg-sway~, which assigns a different wallpaper to each workspace and
+does not crash. The wallpapers directory ~~/.config/sway/wallpapers~ needs to be setup in this way:
+#+begin_src
+wallpapers
+ ├─ eDP-1
+ │ ├─ _default.jpg
+ │ ├─ 1.jpg
+ │ ├─ 2.png
+ │ └─ browser.jpg
+ └─ HDMI-A-1
+ ├─ 1.jpg
+ └─ 3.png
+#+end_src
+where the output information can be obtained from ~swaymsg -t get_outputs~.
+
+Supposedly does not work with ~hypr~.
+
+* Hyprland
+
+This is another choice of a compositor.
+
+Note: Setup does not work with NVIDIA GPU without some tweaks.
+
+- [[https://wiki.archlinux.org/title/Hyprland][hyprland]]: window manager
+ Until [[https://github.com/elkowar/eww/issues/111][tray support]] has been added to ~eww~ in a stable manner, tray will be handled with waybar.
+- ~hyprpaper~: Wallpaper engine
+
+ The command to set a wallpaper:
+ ~hyprctl hyprpaper wallpaper "$DISPLAY,$FILE"~
+The command for changing keyboard layouts is handled by ~fcitx5~.
+
+* Utilities
+
+- [[https://github.com/Horus645/swww][swww]]: Alternate wallpaper engine
+
+ Note that ~~/.config/hypr/wallpapers~ must have jpeg files ~{1..8}.jpg~. A
+ handy command can be used crop and resize images:
+ #+begin_src bash
+convert $IN \
+ -resize 3840x2160^ \
+ -gravity center \
+ -extent 3840x2160 \
+ $OUT
+ #+end_src
+- ~swaync~: Notification server
+- ~wofi~: finding programs, drop in replacement for ~rofi~
+- ~grimblast~: Screenshot engine
+- ~dolphin~: File explorer
+- ~swaylock-effects~: A simple lockscreen
+- ~wl-clipboard~: Provides copying
+- ~blueman~: Bluetooth connector
+
+** Configuration
+
+- ~lxappearance~: Used to configure GTK3 themes
+- ~nwg-look~: Configures cursor
+- ~wev~: Wayland event interceptor useful for determining keybinds
diff --git a/README.org b/README.org
index 8a5da2d..9334224 100644
--- a/README.org
+++ b/README.org
@@ -50,70 +50,6 @@ systemctl start --user mpd
- ~neofetch~: Screenfetch
- ~macchina~ (aur): Another screenfetch
-* Hyprland Desktop Environment
-
-** Login Manager
-
-The login manager is not managed by this configuration but mentioned here since
-it interacts with the desktop environment. For ~hyprland~, ~sddm~ is
-recommended.
-
-- ~sddm~: Enable ~sddm.service~
-
- A note about themes: The themes must be placed in ~/usr/share/sddm/themes~.
- Then in ~/etc/sddm.conf~, enable the relevant theme. By default the breeze
- theme comes with ~plasma-workspace~ which is very bloated to install, so
- consider some of the alternative themes.
-
-** Fonts
-
-- ~otf-font-awesome~: Needed for ~waybar~ to render icons
-- Noto Sans/Serif: System font
-
-** Hyprland
-
-Note: Setup does not work with NVIDIA GPU without some tweaks.
-
-- [[https://wiki.archlinux.org/title/wayland][wayland]]: display manager: ~wayland~, ~xorg-xwayland~
-- [[https://wiki.archlinux.org/title/Hyprland][hyprland]]: window manager
-- ~waybar~: Status bar, use ~waybar-hyprland-git~ AUR repo to enable clicking!
-- ~eww-wayland~: Another status bar, requires ~socat~ to listen for hyprland events.
-
- Until [[https://github.com/elkowar/eww/issues/111][tray support]] has been added to ~eww~ in a stable manner, tray will be handled with waybar.
-- ~hyprpaper~: Wallpaper engine
-
- The command to set a wallpaper:
- ~hyprctl hyprpaper wallpaper "$DISPLAY,$FILE"~
-- [[https://github.com/Horus645/swww][swww]]: Alternate wallpaper engine
-
- Note that ~~/.config/hypr/wallpapers~ must have jpeg files ~{1..8}.jpg~. A
- handy command can be used crop and resize images:
- #+begin_src bash
-convert $IN \
- -resize 3840x2160^ \
- -gravity center \
- -extent 3840x2160 \
- $OUT
- #+end_src
-- ~swaync~: Notification server
-
-The command for changing keyboard layouts is handled by ~fcitx5~.
-
-** Utilities
-
-- ~wofi~: finding programs, drop in replacement for ~rofi~
-- ~grimblast~: Screenshot engine
-- ~dolphin~: File explorer
-- ~swaylock-effects~: A simple lockscreen
-- ~wl-clipboard~: Provides copying
-- ~blueman~: Bluetooth connector
-
-*** Configuration
-
-- ~lxappearance~: Used to configure GTK3 themes
-- ~nwg-look~: Configures cursor
-- ~wev~: Wayland event interceptor useful for determining keybinds
-
* Dot Files
All the configurations which must appear as dot files are not included:
diff --git a/eww/bar/eww.yuck b/eww/bar/eww.yuck
index cb76b6d..2604de7 100644
--- a/eww/bar/eww.yuck
+++ b/eww/bar/eww.yuck
@@ -25,47 +25,6 @@
;(widget_status)
))
-(defwidget widget_weather [orientation]
- (box
- :class "weather"
- :orientation orientation
- :space-evenly false
- :valign "start"
- :halign "center"
- :spacing 10
- ;(box :class "moon" :orientation "v" moon) ; Not very stable
- (box :class "temperature" :orientation orientation
- (box :class "icon" "")
- "${weather.current_condition[0].temp_C}"
- (box :class "feelsLike" "${weather.current_condition[0].FeelsLikeC}")
- )
- (box :class "uvIndex" :orientation orientation
- (box :class "icon" "")
- "${weather.current_condition[0].uvIndex}")
- (box :class "humidity" :orientation orientation
- (box :class "icon" "")
- "${weather.current_condition[0].humidity}"
- )
- (box :class "precip" :orientation orientation
- (box :class "icon" "")
- "${weather.current_condition[0].precipMM}"
- )
- (box :class "wind" :orientation orientation
- (box :class "icon" "")
- "${weather.current_condition[0].windspeedKmph}"
- "${weather.current_condition[0].winddir16Point}"
- )
- (box :class "cloud" :orientation orientation
- (box :class "icon" "")
- "${weather.current_condition[0].cloudcover}"
- )
- ))
-
-(defpoll moon :initial "" :interval "180s"
- "curl wttr.in/?format=%m")
-(defpoll weather :initial "{\"current_condition\": [{\"cloudcover\": \"\"}]}" :interval "180s"
- "curl wttr.in/?format=j1")
-
(defwidget widget_workspaces []
(box
:class "workspaces"
@@ -83,6 +42,37 @@
"scripts/get-workspaces")
+; Weather
+
+(defwidget widget_weather [orientation]
+ (box
+ :class "weather"
+ :orientation orientation
+ :space-evenly false
+ :valign "start"
+ :halign "center"
+ :spacing 10
+ (button :onclick "scripts/popup weather" "W")
+ ))
+
+(defpoll weather_text :initial "" :interval "180s"
+ "curl --max-time 2 wttr.in")
+
+(defwindow weather
+ :geometry (geometry :x "70px"
+ :y "50%"
+ :width "270px"
+ :height "60px")
+ (box weather_text))
+
+
+(defwindow calendar
+ :geometry (geometry :x "70px"
+ :y "65%"
+ :width "270px"
+ :height "60px")
+ (cal))
+
(defwidget widget_clock []
(box
:class "clock"
diff --git a/eww/bar/scripts/get-workspaces b/eww/bar/scripts/get-workspaces
index c5b2d3c..4c2070d 100755
--- a/eww/bar/scripts/get-workspaces
+++ b/eww/bar/scripts/get-workspaces
@@ -6,81 +6,121 @@ Utility to generate the workspace buttons for eww bar widget.
Currently it fetches information from monitor 0. If all monitors have
synchronised workspaces this should not be a problem.
"""
-import os, sys, socket, json
+import os, sys, socket, json, subprocess
+from typing import Optional
WORKSPACE_ICONS = [
- (1, '☱'),
- (2, '☲'),
- (3, '☳'),
- (4, '☴'),
- (5, '☵'),
- (6, '☶'),
- (7, '☷'),
- (8, '☰'),
+ (1, "☱"),
+ (2, "☲"),
+ (3, "☳"),
+ (4, "☴"),
+ (5, "☵"),
+ (6, "☶"),
+ (7, "☷"),
+ (8, "☰"),
]
EXTRA_WORKSPACE_ICONS = [
- (0, '⚌'),
- (1, '⚍'),
- (2, '⚎'),
- (3, '⚏'),
+ (0, "⚌"),
+ (1, "⚍"),
+ (2, "⚎"),
+ (3, "⚏"),
]
-def get_workspace_info():
+Workspaces = dict[int, bool]
- workspaces = json.loads(os.popen('hyprctl workspaces -j').read())
- monitors = json.loads(os.popen('hyprctl monitors -j').read())
- if not monitors:
- print("No monitor found!", file=sys.stderr)
- return []
-
- monitor, active = [(m['name'], m['activeWorkspace']['id'])
- for m in monitors if m['id'] == 0][0]
- workspaces = [(w['id'], w['id'] == active)
- for w in workspaces
- if w['monitor'] == monitor]
- return workspaces
-
-
-def get_widgets():
- # get all workspace keys
- workspaces = {k: v for k, v in get_workspace_info()}
+def get_widgets(workspaces: Workspaces) -> str:
+ """
+ Create widget sexp from workspace information
+ """
def get_class(k):
key = workspaces.get(k, None)
if key is None:
- return 'inactive'
+ return "inactive"
elif key:
- return 'focused'
+ return "focused"
else:
- return 'active'
+ return "active"
buttons = [
f'"id": "{k}", "text": "{icon}", "class": "{get_class(k)}"'
for k, icon in WORKSPACE_ICONS
]
- buttons = ', '.join(['{' + b + '}' for b in buttons])
- return '[' + buttons + ']'
+ buttons = ", ".join(["{" + b + "}" for b in buttons])
+ return "[" + buttons + "]"
-def listen():
+# Compositor specific information
+
+def hypr_get_workspace_info() -> Workspaces:
+ workspaces = json.loads(os.popen("hyprctl workspaces -j").read())
+ monitors = json.loads(os.popen("hyprctl monitors -j").read())
+ if not monitors:
+ print("No monitor found!", file=sys.stderr)
+ return []
+
+ monitor, active = [
+ (m["name"], m["activeWorkspace"]["id"]) for m in monitors if m["id"] == 0
+ ][0]
+ workspaces = {
+ w["id"]: w["id"] == active
+ for w in workspaces if w["monitor"] == monitor
+ }
+ return workspaces
+
+
+def hypr_listen(socket_addr: str):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- KEY = 'HYPRLAND_INSTANCE_SIGNATURE'
- signature = os.environ.get(KEY, None)
- if signature is None:
- print("Hyprland variable uninitialised.", file=sys.stderr)
- return
- server_address = f"/tmp/hypr/{signature}/.socket2.sock"
try:
- sock.connect(server_address)
+ sock.connect(socket_addr)
except:
- print(f"Could not connect to {server_address}", file=sys.stderr)
+ print(f"Could not connect to {socket_addr}", file=sys.stderr)
raise
# The flush here is very important since python by default buffers!
- print(get_widgets(), flush=True)
+ workspace_info = hypr_get_workspace_info()
+ print(get_widgets(workspace_info), flush=True)
while sock:
data = sock.recv(1024)
- if b'workspace' in data:
- print(get_widgets(), flush=True)
+ if b"workspace" in data:
+ workspace_info = hypr_get_workspace_info()
+ print(get_widgets(workspace_info), flush=True)
-listen()
+def sway_get_workspace_info() -> Workspaces:
+ workspaces = json.loads(os.popen("swaymsg --raw -t get_workspaces").read())
+ # REVIEW: This has not been tested on a multi-monitor setup.
+ workspaces = {
+ int(w["num"]): w["focused"]
+ for w in workspaces
+ }
+ return workspaces
+
+def sway_listen():
+ proc = subprocess.Popen(
+ ["swaymsg", "-t", "subscribe", "-m", '["workspace"]'], stdout=subprocess.PIPE
+ )
+ workspace_info = sway_get_workspace_info()
+ print(get_widgets(workspace_info), flush=True)
+ while line := proc.stdout.readline():
+ # Not needed
+ info = json.loads(line)
+ workspace_info = sway_get_workspace_info()
+ print(get_widgets(workspace_info), flush=True)
+
+
+def detect():
+ """
+ Main entry point, detects the type of compositor used
+ """
+ if signature := os.environ.get("HYPRLAND_INSTANCE_SIGNATURE", None):
+ socket_addr = f"/tmp/hypr/{signature}/.socket2.sock"
+ return hypr_listen(socket_addr)
+ if signature := os.environ.get("SWAYSOCK", None):
+ return sway_listen()
+
+ print("No compositor found.", file=sys.stderr)
+ return None
+
+
+if __name__ == "__main__":
+ detect()
diff --git a/eww/bar/scripts/popup b/eww/bar/scripts/popup
new file mode 100755
index 0000000..faef20e
--- /dev/null
+++ b/eww/bar/scripts/popup
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+toggle_popup() {
+ LOCK="/tmp/eww-$1.lock"
+ if [[ ! -f "$LOCK" ]]; then
+ touch "$LOCK"
+ eww --config ~/.config/eww/bar open $1
+ else
+ eww --config ~/.config/eww/bar close $1
+ rm "$LOCK"
+ fi
+}
+
+if [ "$1" = weather ]; then
+ toggle_popup weather
+fi
diff --git a/sway/config b/sway/config
new file mode 100644
index 0000000..b10891d
--- /dev/null
+++ b/sway/config
@@ -0,0 +1,44 @@
+# Terminal
+set $term alacritty
+# Launcher
+set $menu wofi --show drun -I -G
+set $lock swaylock
+set $screenshot_full /usr/share/swayfx/scripts/grimshot copy screen
+set $screenshot_area /usr/share/swayfx/scripts/grimshot copy area
+
+xwayland enable
+
+scratchpad_minimize disable
+
+# Visual Effects
+corner_radius 20
+smart_corner_radius enable
+blur on
+blur_xray off
+blur_passes 2
+blur_radius 5
+shadows on
+shadows_on_csd off
+shadow_blur_radius 20
+shadow_color #0000007F
+default_dim_inactive 0.0
+dim_inactive_colors.unfocused #000000FF
+dim_inactive_colors.urgent #900000FF
+
+set $border 2
+default_border pixel $border
+default_floating_border pixel $border
+
+for_window [app_id=".*"] gaps inner all set 5
+for_window [app_id=".*"] gaps outer all set 15
+for_window [app_id=".*"] opacity 0.85
+for_window [app_id=__focused__] opacity 0.95
+
+# Include keys
+include ~/.config/sway/keys.conf
+
+# Launching programs
+include ~/.config/sway/launch.conf
+
+# Include systemd fix
+include /etc/sway/config.d/*
diff --git a/sway/keys.conf b/sway/keys.conf
new file mode 100644
index 0000000..8199647
--- /dev/null
+++ b/sway/keys.conf
@@ -0,0 +1,63 @@
+set $mod Mod4
+set $left h
+set $down j
+set $up k
+set $right l
+
+bindsym $mod+t exec $term
+bindsym $mod+q kill
+bindsym $mod+space exec $menu
+bindsym $mod+semicolon exec $lock
+bindsym $mod+Shift+c reload
+bindsym Print exec $screenshot_area
+bindsym Shift+Print exec $screenshot_full
+
+# Drag floating windows by holding down $mod and left mouse button.
+# Resize them with right mouse button + $mod.
+# Despite the name, also works for non-floating windows.
+# Change normal to inverse to use left mouse button for resizing and right
+# mouse button for dragging.
+floating_modifier $mod normal
+
+bindsym $mod+f fullscreen
+bindsym $mod+v floating toggle
+
+# Move focus
+bindsym $mod+$left focus left
+bindsym $mod+$down focus down
+bindsym $mod+$up focus up
+bindsym $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
+
+# 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
+# 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 $mod+1 workspace number 1
+bindsym $mod+2 workspace number 2
+bindsym $mod+3 workspace number 3
+bindsym $mod+4 workspace number 4
+bindsym $mod+5 workspace number 5
+bindsym $mod+6 workspace number 6
+bindsym $mod+7 workspace number 7
+bindsym $mod+8 workspace number 8
+# Move focused container to workspace
+bindsym $mod+Shift+1 move container to workspace number 1; workspace number 1
+bindsym $mod+Shift+2 move container to workspace number 2; workspace number 2
+bindsym $mod+Shift+3 move container to workspace number 3; workspace number 3
+bindsym $mod+Shift+4 move container to workspace number 4; workspace number 4
+bindsym $mod+Shift+5 move container to workspace number 5; workspace number 5
+bindsym $mod+Shift+6 move container to workspace number 6; workspace number 6
+bindsym $mod+Shift+7 move container to workspace number 7; workspace number 7
+bindsym $mod+Shift+8 move container to workspace number 8; workspace number 8
diff --git a/sway/launch.conf b/sway/launch.conf
new file mode 100644
index 0000000..ddd1921
--- /dev/null
+++ b/sway/launch.conf
@@ -0,0 +1,9 @@
+exec /usr/share/swayfx/scripts/inactive-windows-transparency --opacity 0.8
+exec_always eww --config ~/.config/eww/bar open bar
+bar {
+ position top
+ swaybar_command waybar
+}
+exec_always multibg-sway ~/.config/sway/wallpapers
+exec swaync
+exec fcitx5
diff --git a/waybar/config b/waybar/config
index 25999b1..bc36509 100644
--- a/waybar/config
+++ b/waybar/config
@@ -6,7 +6,9 @@
"margin": "0 15 0 5",
"modules-left": [
//"wlr/workspaces",
- "hyprland/window"],
+ "hyprland/window",
+ "sway/window"
+ ],
"modules-center": ["mpd"],
"modules-right": [
"tray",
@@ -35,7 +37,9 @@
},
"hyprland/window": {
"format": " {}",
- "separate-outputs": true
+ },
+ "sway/window": {
+ "format": " {}",
},
"keyboard-state": {
"numlock": true,
@@ -47,14 +51,6 @@
//"unlocked": ""
}
},
- "hyprland/language": {
- "format": "{}",
- "format-en": "🇺🇸",
- "format-fr": "🇨🇦",
- "format-ja": "🇯🇵",
- "tooltip-format": "{}",
- "tooltip": true
- },
"mpd": {
"format": "『{artist} - {album} - {title} 』{stateIcon} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}",
"format-disconnected": "Disconnected",