feat: add pystray for hyprland

This commit is contained in:
Kat Inskip 2024-02-17 14:28:02 -08:00
parent 7bc4a2c918
commit 51fe663a47
Signed by: kat
GPG key ID: 465E64DECEA8CF0F
3 changed files with 40 additions and 12 deletions

View file

@ -1,5 +1,6 @@
import subprocess import subprocess
import dbus import dbus
import time
from konawall.module_loader import add_environment from konawall.module_loader import add_environment
@add_environment("hyprland_setter") @add_environment("hyprland_setter")

View file

@ -19,9 +19,9 @@ class Konawall(wx.adv.TaskBarIcon):
def __init__(self, version, file_logger): def __init__(self, version, file_logger):
super().__init__() super().__init__()
# Prevents it from closing before it has done any work on macOS # Prevents it from closing before it has done any work on macOS
#if wx.Platform == "__WXMAC__" or wx.Platform == "__WXGTK__": if wx.Platform == "__WXMAC__" or wx.Platform == "__WXGTK__":
self.hidden_frame = wx.Frame(None) self.hidden_frame = wx.Frame(None)
self.hidden_frame.Hide() self.hidden_frame.Hide()
self.wallpaper_rotation_counter = 0 self.wallpaper_rotation_counter = 0
self.file_logger = file_logger self.file_logger = file_logger
@ -61,6 +61,15 @@ class Konawall(wx.adv.TaskBarIcon):
# Set up the taskbar icon, menu, bindings, ... # Set up the taskbar icon, menu, bindings, ...
icon = self.generate_icon() icon = self.generate_icon()
self.SetIcon(icon, self.title_string) self.SetIcon(icon, self.title_string)
if self.environment == "hyprland":
import pystray
def setup(self):
self.visible = True
self.external_icon = pystray.Icon("Konawall - {version}", icon=self.generate_icon_bitmap(), menu=pystray.Menu(
pystray.MenuItem("Rotate", self.rotate_wallpapers),
pystray.MenuItem("Toggle Rotation", self.toggle_timed_wallpaper_rotation, checked=lambda item: self.rotate)
))
self.external_icon.run(setup)
self.hidden_frame.SetIcon(icon) self.hidden_frame.SetIcon(icon)
self.create_menu() self.create_menu()
self.create_bindings() self.create_bindings()
@ -69,7 +78,7 @@ class Konawall(wx.adv.TaskBarIcon):
self.rotate_wallpapers(None) self.rotate_wallpapers(None)
# wxPython requires a wx.Bitmap, so we generate one from a PIL.Image # wxPython requires a wx.Bitmap, so we generate one from a PIL.Image
def generate_icon(self): def generate_icon_bitmap(self):
width = 128 width = 128
height = 128 height = 128
@ -79,7 +88,10 @@ class Konawall(wx.adv.TaskBarIcon):
image = image.resize((16, 16)) image = image.resize((16, 16))
elif "wxGTK" in wx.PlatformInfo: elif "wxGTK" in wx.PlatformInfo:
image = image.resize((22, 22)) image = image.resize((22, 22))
return image
def generate_icon(self):
image = self.generate_icon_bitmap()
# Write image to temporary file # Write image to temporary file
temp = tempfile.NamedTemporaryFile(suffix=".png", delete=False) temp = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
image.save(temp.name) image.save(temp.name)
@ -263,7 +275,8 @@ class Konawall(wx.adv.TaskBarIcon):
# Update the menu item of the current interval display to read correctly # Update the menu item of the current interval display to read correctly
def respect_current_interval_status(self): def respect_current_interval_status(self):
self.current_interval_menu_item.SetItemLabel(f"Rotation interval: {format_timespan(self.interval)}") if self.IsAvailable:
self.current_interval_menu_item.SetItemLabel(f"Rotation interval: {format_timespan(self.interval)}")
# Set whether to rotate wallpapers automatically or not # Set whether to rotate wallpapers automatically or not
def toggle_timed_wallpaper_rotation(self, event): def toggle_timed_wallpaper_rotation(self, event):
@ -277,14 +290,17 @@ class Konawall(wx.adv.TaskBarIcon):
elif not self.rotate and self.wallpaper_rotation_timer.IsRunning(): elif not self.rotate and self.wallpaper_rotation_timer.IsRunning():
self.wallpaper_rotation_timer.Stop() self.wallpaper_rotation_timer.Stop()
# Set the time left counter to show that it is disabled # Set the time left counter to show that it is disabled
self.timed_wallpaper_rotation_status_menu_item.SetItemLabel(f"Automatic wallpaper rotation disabled") if self.IsAvailable:
self.current_interval_menu_item.SetItemLabel(f"Automatic wallpaper rotation disabled")
# Update the menu item for the toggle # Update the menu item for the toggle
self.toggle_wallpaper_rotation_menu_item.SetItemLabel(self.toggle_timed_wallpaper_rotation_status()) if self.IsAvailable:
self.toggle_wallpaper_rotation_menu_item.SetItemLabel(self.toggle_timed_wallpaper_rotation_status())
# Update wallpaper rotation time left counter # Update wallpaper rotation time left counter
def respect_timed_wallpaper_rotation_status(self): def respect_timed_wallpaper_rotation_status(self):
self.timed_wallpaper_rotation_status_menu_item.SetItemLabel(f"Next rotation: {format_timespan(self.interval - self.wallpaper_rotation_counter)} remaining") if self.IsAvailable:
self.timed_wallpaper_rotation_status_menu_item.SetItemLabel(f"Next rotation: {format_timespan(self.interval - self.wallpaper_rotation_counter)} remaining")
# Perform the purpose of the application; get new wallpaper media and set 'em. # Perform the purpose of the application; get new wallpaper media and set 'em.
def rotate_wallpapers(self, event): def rotate_wallpapers(self, event):

View file

@ -2,7 +2,11 @@
lib, lib,
buildPythonPackage, buildPythonPackage,
python311Packages, python311Packages,
psmisc psmisc,
gobject-introspection,
gtk3,
dbus-python,
wrapGAppsHook,
}: let }: let
pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml);
poetryBlock = pyproject.tool.poetry; poetryBlock = pyproject.tool.poetry;
@ -18,12 +22,19 @@ in
doCheck = false; doCheck = false;
nativeBuildInputs = [
wrapGAppsHook
gobject-introspection
];
propagatedBuildInputs = let propagatedBuildInputs = let
dependencyNames = (lib.attrNames poetryBlock.dependencies) ++ ["dbus-python"]; dependencyNames = (lib.attrNames poetryBlock.dependencies) ++ ["setuptools" "pygobject3" "pystray" "dbus-python"];
dependencies = map (name: python311Packages.${name} or dependencyReplacements.${name}) dependencyNames; dependencies = map (name: python311Packages.${name} or dependencyReplacements.${name}) dependencyNames;
in in
dependencies ++ [ dependencies ++ [
psmisc psmisc
gtk3
dbus-python
]; ];
meta = with lib; { meta = with lib; {