Moving monitor checks to common.py

This commit is contained in:
Roman 2024-06-04 02:49:05 -04:00
parent e8d9e56327
commit feeaf9a769
4 changed files with 65 additions and 45 deletions

View File

@ -1,6 +1,6 @@
# Waypaper
GUI wallpaper setter for Wayland and Xorg window managers. It works as a frontend for popular wallpaper backends like `swaybg`, `swww`, `wallutils` and `feh`. You can check a [demo on reddit](https://www.reddit.com/r/unixporn/comments/15lbhuc/hyprland_waypaper_gui_wallpaper_setter_for_wayland/). See details in [the documentation](https://anufrievroman.gitbook.io/waypaper).
GUI wallpaper setter for Wayland and Xorg window managers. It works as a frontend for popular wallpaper backends like `swaybg`, `swww`, `wallutils`, `hyprpaper` and `feh`. See details in [the documentation](https://anufrievroman.gitbook.io/waypaper).
![screenshot](screenshot.jpg)
@ -9,7 +9,8 @@ GUI wallpaper setter for Wayland and Xorg window managers. It works as a fronten
- Vim keys
- Support for GIF animations (with `swww`)
- Support for multiple monitors (with `swww`)
- Works on both Wayland (with `swww` or `swaybg` or `wallutils`) and Xorg (with `feh` or `wallutils`)
- Works on Wayland (with `swww` or `swaybg` or `hyprpaper` or `wallutils`)
- Works on Xorg (with `feh` or `wallutils`)
- Restores wallpaper at launch of your WM
- Caching for fast loading
@ -19,7 +20,7 @@ You need to install at least one of the backends and Waypaper, which works as a
### 1. Install a backend
Install a preferred backend from your package manager: [swww](https://github.com/Horus645/swww) or [swaybg](https://github.com/swaywm/swaybg) on Wayland or [feh](https://github.com/derf/feh) on Xorg or [wallutils](https://github.com/xyproto/wallutils) on both.
Install a preferred backend from your package manager: [swww](https://github.com/Horus645/swww) or [swaybg](https://github.com/swaywm/swaybg) or [swaybg](https://github.com/hyprwm/hyprpaper) on Wayland or [feh](https://github.com/derf/feh) on Xorg or [wallutils](https://github.com/xyproto/wallutils) on both.
### 2. Install Waypaper
@ -33,9 +34,9 @@ If `pipx` is not found, you first need to install `pipx` from your package manag
#### On Arch-based distributions
`yay -S waypaper-git`
`yay -S waypaper` or `yay -S waypaper-git`
The [waypaper-git](https://aur.archlinux.org/packages/waypaper-git) package is available in AUR, thanks to *metak*. Please upvote to support the project.
The [waypaper](https://aur.archlinux.org/packages/waypaper) and [waypaper-git](https://aur.archlinux.org/packages/waypaper-git) packages are available in AUR, thanks to *metak*. Please upvote to support the project.
#### On NixOS
@ -47,7 +48,7 @@ Users of OpenSUSE [reported issue with installation](https://github.com/anufriev
### Dependencies
- `swww` or `swaybg` or `feh` or `wallutils`
- `swww` or `swaybg` or `feh` or `wallutils` or `hyprpaper`
- gobject python library (it might be called `python-gobject` or `python3-gi` or `python3-gobject` in your package manager.)
- `python-importlib_metadata`
- `python-platformdirs`

View File

@ -1,18 +1,16 @@
"""Module that runs GUI app"""
import subprocess
import threading
import os
import gi
import shutil
from pathlib import Path
from PIL import Image
import re
from waypaper.aboutdata import AboutData
from waypaper.changer import change_wallpaper
from waypaper.config import Config
from waypaper.common import get_image_paths, get_random_file
from waypaper.common import get_image_paths, get_random_file, get_monitor_names_hyprctl, get_monitor_names_swww
from waypaper.options import FILL_OPTIONS, SORT_OPTIONS, SORT_DISPLAYS
from waypaper.translations import Chinese, English, French, German, Polish, Russian
@ -228,35 +226,11 @@ class App(Gtk.Window):
# Check available monitors:
monitor_names = ["All"]
if self.cf.backend == "swww":
try:
# Check if swww-deamon is already running. If not, launch it:
try:
subprocess.check_output(["pgrep", "swww-daemon"], encoding='utf-8')
except subprocess.CalledProcessError:
subprocess.Popen(["swww-daemon"])
print("The swww-daemon launched.")
# Check available monitors (using swww):
query_output = str(subprocess.check_output(["swww", "query"], encoding='utf-8'))
monitors = query_output.split("\n")
for monitor in monitors[:-1]:
monitor_names.append(monitor.split(':')[0])
except Exception as e:
print(f"{self.txt.err_disp} {e}")
connected_monitors = get_monitor_names_swww()
monitor_names.extend(connected_monitors)
elif self.cf.backend == "hyprpaper":
try:
# Check available motitors (using hyprpaper):
query_output = str(subprocess.check_output(["hyprctl", "monitors"], encoding='utf-8'))
query_output = query_output.split('\n')
# Use a regular expression to get the lines that contain the monitor names:
query_output = list(filter(lambda line: re.match(r"Monitor [a-zA-Z-0-9]+ \(ID \d+\):", line),query_output))
for line in query_output:
monitor_names.append(line.split(' ')[1])
except Exception as e:
print(f"{self.txt.err_disp} {e}")
connected_monitors = get_monitor_names_hyprctl()
monitor_names.extend(connected_monitors)
else:
return

View File

@ -3,6 +3,7 @@
import subprocess
import time
from waypaper.config import Config
from waypaper.common import get_monitor_names_hyprctl
from waypaper.translations import Chinese, English, French, German, Polish, Russian
import re
@ -108,28 +109,29 @@ def change_wallpaper(image_path: str, cf: Config, monitor: str, txt: Chinese|Eng
# hyprpaper backend:
elif cf.backend == "hyprpaper":
# Check if hyprpaper is already running, otherwise start it, and preload the wallpaper:
try:
str(subprocess.check_output(["pgrep", "hyprpaper"], encoding='utf-8'))
except Exception:
subprocess.Popen(["hyprpaper"])
time.sleep(1)
preload_command = ["hyprctl", "hyprpaper", "preload", image_path]
# Decide which monitors are affected:
if monitor == "All":
monitors: list = []
# Check available motitors (using hyprpaper):
query_output = str(subprocess.check_output(["hyprctl", "monitors"], encoding='utf-8'))
query_output = query_output.split('\n')
# Use a regular expression to get the lines that contain the monitor names:
query_output = list(filter(lambda line: re.match(r"Monitor [a-zA-Z-0-9]+ \(ID \d+\):", line),query_output))
for line in query_output:
monitors.append(line.split(' ')[1])
monitors = get_monitor_names_hyprctl()
else:
monitors: list = [monitor]
# Change the wallpaper one by one for each affected monitor:
for m in monitors:
wallpaper_command = ["hyprctl", "hyprpaper", "wallpaper", f"{m},{image_path}"]
unload_command = ["hyprctl", "hyprpaper", "unload", "all"]
result: str = ""
retry_counter: int = 0
# Since sometimes hyprpaper fails to change the wallpaper, we try until success:
while result != "ok" and retry_counter < 10:
try:
subprocess.check_output(unload_command, encoding="utf-8").strip()

View File

@ -1,8 +1,10 @@
"""Module with some of the common functions, like file operations"""
import os
import re
import random
import shutil
import subprocess
from waypaper.options import IMAGE_EXTENSIONS, BACKEND_OPTIONS
from typing import List
@ -84,3 +86,44 @@ def check_installed_backends() -> List[str]:
if is_installed:
installed_backends.append(backend)
return installed_backends
def get_monitor_names_swww() -> List[str]:
"""Obtain the list of plugged monitors using swww daemon"""
connected_monitors: List[str] = []
try:
# Check if swww-deamon is already running. If not, launch it:
try:
subprocess.check_output(["pgrep", "swww-daemon"], encoding='utf-8')
except subprocess.CalledProcessError:
subprocess.Popen(["swww-daemon"])
print("The swww-daemon launched.")
# Check available monitors:
query_output = str(subprocess.check_output(["swww", "query"], encoding='utf-8'))
monitors = query_output.split("\n")
for monitor in monitors[:-1]:
connected_monitors.append(monitor.split(':')[0])
except Exception as e:
print(f"{self.txt.err_disp} {e}")
return connected_monitors
def get_monitor_names_hyprctl() -> List[str]:
"""Obtain the list of plugged monitors using hyprctl"""
connected_monitors: List[str] = []
try:
# Check available motitors:
query_output = str(subprocess.check_output(["hyprctl", "monitors"], encoding='utf-8'))
query_output = query_output.split('\n')
# Use a regular expression to get the lines that contain the monitor names:
query_output = list(filter(lambda line: re.match(r"Monitor [a-zA-Z-0-9]+ \(ID \d+\):", line), query_output))
for line in query_output:
connected_monitors.append(line.split(' ')[1])
except Exception as e:
print(f"{self.txt.err_disp} {e}")
return connected_monitors