From 6a265ea3b617aa9dc9be34aa302862b1130732fb Mon Sep 17 00:00:00 2001 From: Kevin Alberts Date: Mon, 22 Nov 2021 19:42:03 +0100 Subject: [PATCH] Compatibility with latest qtile, fixes to widgets, etc... --- config.py | 3 --- kuro/config.py | 16 +++++------ kuro/theme.py | 63 ++++++++++++++++++++++++++----------------- kuro/utils/general.py | 2 +- kuro/utils/widgets.py | 41 ++++++++++++++++++++-------- kuro/utils/windows.py | 3 +-- 6 files changed, 78 insertions(+), 50 deletions(-) diff --git a/config.py b/config.py index c3abfcd..7d5f49f 100644 --- a/config.py +++ b/config.py @@ -121,8 +121,5 @@ def main(qtile): else: qtile.cmd_warning() - # Save qtile instance in theme - Theme.qtile = qtile - # Save theme instance in qtile qtile.theme_instance = Theme diff --git a/kuro/config.py b/kuro/config.py index b986e53..480de2c 100644 --- a/kuro/config.py +++ b/kuro/config.py @@ -16,12 +16,10 @@ class Config(BaseConfig): # Default Applications app_terminal = "terminator" - #app_launcher = "/home/kevin/bin/dmenu_wal.sh" - app_launcher = "dmenu_run -i -p '»' -nb '" + background + "' -fn 'Noto Sans-11' -nf '" + inactive_light + \ - "' -sb '" + highlight + "' -sf '" + foreground + "'" + app_launcher = "/home/kevin/bin/dmenu_wal.sh" web_browser = "firefox-developer-edition" file_manager = "thunar" - app_chat = "/home/kevin/bin/ramboxpro" + app_chat = "/usr/bin/ramboxpro" app_irc = "quasselclient" app_mail = "thunderbird" cmd_brightness_up = "sudo /usr/bin/xbacklight -inc 10" @@ -94,8 +92,8 @@ class Config(BaseConfig): # Thermal indicator variables thermal_threshold = 75 - thermal_sensor = "Package id 0" - thermal_chip = "coretemp-isa-0000" + thermal_sensor = "Tdie" + thermal_chip = "zenpower-pci-00c3" # CPU graph variables cpu_graph_colour = '#ff0000' @@ -122,8 +120,8 @@ class Config(BaseConfig): volume_font = "Noto Sans" volume_fontsize = 11 volume_theme_path = "/home/kevin/.config/qtile/kuro/resources/volume" - volume_pulse_sink = "alsa_output.pci-0000_04_00.0.pro-output-0" - volume_pulse_sink2 = "alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.pro-output-0" + volume_pulse_sink = "alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo" + volume_pulse_sink2 = "alsa_output.pci-0000_0e_00.4.analog-stereo" volume_is_bluetooth_icon = False volume_update_interval = 0.2 @@ -152,7 +150,7 @@ class Config(BaseConfig): do_keyboard_updates = False # Show audio visualizer - show_audio_visualizer = False + show_audio_visualizer = True kill_unnecessary_glava_processes = True # Show thermal widget diff --git a/kuro/theme.py b/kuro/theme.py index 27012d6..aebeb85 100644 --- a/kuro/theme.py +++ b/kuro/theme.py @@ -9,7 +9,7 @@ logger.error("Importing qtile theme requirements...") from libqtile.config import Key, Screen, Group, Drag, Click, Match from libqtile.command import lazy -from libqtile import layout, bar, widget +from libqtile import layout, bar, widget, qtile logger.error("Importing theme util functions...") @@ -83,13 +83,14 @@ class Kuro(BaseTheme): Match(wm_class='ssh-askpass'), # ssh-askpass Match(title='branchdialog'), # gitk Match(title='pinentry'), # GPG key password entry + Match(title='origin.exe', wm_class='Wine'), # Wine Origin game launcher ]) def set_debug_text(self, text): for field in self.debug_textfields: field.text = text for bar in self.debug_bars: - if self.qtile is not None: + if qtile is not None: bar.draw() def log_debug(self, text): @@ -144,7 +145,7 @@ class Kuro(BaseTheme): Key([self.mod, "shift"], 'f', lazy.window.toggle_floating()), # Pinned toggle - Key([self.mod], 'p', lazy.function(self.toggle_pinned)), + Key([self.mod, "shift"], 'p', lazy.function(self.toggle_pinned)), # Toggle between split and unsplit sides of stack. # Split = all windows displayed @@ -513,22 +514,22 @@ class Kuro(BaseTheme): else: utils.execute("arandr") - def reinitialize_visualizers(self, qtile=None): + def reinitialize_visualizers(self): if Config.get("show_audio_visualizer", False): logger.warning("Reinitializing visualizers...") - for screen in self.qtile.screens: + for screen in qtile.screens: for widget in screen.top.widgets: if isinstance(widget, kuro.utils.widgets.AudioVisualizerWidget): if widget.client is not None: widget.client.kill() widget.client = None widget.screen = None - self.update_visualizers(qtile=qtile) + self.update_visualizers() - def update_visualizers(self, qtile=None): + def update_visualizers(self): if Config.get("show_audio_visualizer", False): logger.warning("Updating visualizers..") - for screen in self.qtile.screens: + for screen in qtile.screens: for widget in screen.top.widgets: if isinstance(widget, kuro.utils.widgets.AudioVisualizerWidget): if widget.client is None: @@ -577,13 +578,20 @@ class Kuro(BaseTheme): # QTile base callbacks def callback_startup_once(self, *args, **kwargs): - self.update_wallpaper(self.qtile) + if not hasattr(qtile, 'theme_instance'): + # Save theme instance in qtile + qtile.theme_instance = self + self.update_wallpaper(qtile) # Setup audio # p = utils.execute_once(["qjackctl"]) # p.wait() def callback_startup(self): + if not hasattr(qtile, 'theme_instance'): + # Save theme instance in qtile + qtile.theme_instance = self + if self.current_wallpaper: p = utils.execute_once(["wal", "-n", "-i", "{}".format(self.current_wallpaper)]) p.wait() @@ -596,7 +604,7 @@ class Kuro(BaseTheme): except KeyError: wallpaper = None if wallpaper: - Kuro.set_wallpaper(self.qtile, wallpaper) + Kuro.set_wallpaper(qtile, wallpaper) else: p = utils.execute_once("nitrogen --restore") p.wait() @@ -610,6 +618,9 @@ class Kuro(BaseTheme): self.log_info("Starting notification daemon...") utils.execute_once("dunst") + self.log_info("Starting xiccd color profile manager...") + utils.execute_once("xiccd") + # Update color scheme self.initialize_colorscheme() @@ -635,9 +646,13 @@ class Kuro(BaseTheme): initial_windows = [] def callback_startup_complete(self, *args, **kwargs): + if not hasattr(qtile, 'theme_instance'): + # Save theme instance in qtile + qtile.theme_instance = self + # Only run on first startup - if not self.qtile.no_spawn: - dg = self.qtile.dgroups + if not qtile.no_spawn: + dg = qtile.dgroups for r in dg.rules: pid = -1 # noinspection PyProtectedMember @@ -651,12 +666,12 @@ class Kuro(BaseTheme): self.callback_client_new() # After first startup is complete, start the audio apps that can only be started after boot is complete - if not self.qtile.no_spawn: + if not qtile.no_spawn: for app in Config.get("apps_audio_afterstart", []): utils.execute_once(app) # Update color scheme - Kuro.update_colorscheme(self.qtile) + Kuro.update_colorscheme(qtile) def callback_client_new(self, *args, **kwargs): client = args[0] if len(args) > 0 else None @@ -664,27 +679,27 @@ class Kuro(BaseTheme): if len(self.initial_windows) > 0: init = self.initial_windows.copy() for pid, gname in init: - for group in self.qtile.groups: + for group in qtile.groups: if len(group.windows) > 0: for window in group.windows: w_pid = window.window.get_net_wm_pid() self.log_info("Comparing pid {} with window PID {}, window {}".format(pid, w_pid, window.name)) if pid == w_pid: - c = self.qtile.dgroups.rules_map.copy() + c = qtile.dgroups.rules_map.copy() for rid, r in c.items(): if r.matches(window): - self.qtile.dgroups.remove_rule(rid) + qtile.dgroups.remove_rule(rid) self.initial_windows.remove((pid, gname)) self.log_info("Removed group rule for PID {}, window {}".format(pid, window.name)) - self.log_info(str(self.qtile.dgroups.rules_map)) + self.log_info(str(qtile.dgroups.rules_map)) # Check if it is a visualizer if Config.get("show_audio_visualizer", False): if client is not None and client.window.get_name() == "GLava": placed = False - for screen in self.qtile.screens: + for screen in qtile.screens: for widget in screen.top.widgets: if not placed and isinstance(widget, kuro.utils.widgets.AudioVisualizerWidget): if widget.client is None: @@ -693,10 +708,10 @@ class Kuro(BaseTheme): pos_y = 0 + widget.margin_y width = viz_info['width'] - (2 * widget.margin_x) height = viz_info['height'] - (2 * widget.margin_y) - screen_index = self.qtile.screens.index(screen) + screen_index = qtile.screens.index(screen) logger.warning("Attaching {} {} to {} on screen {}".format(client, client.window.wid, type(widget).__name__, screen_index)) c = KuroStatic.create(client, screen, x=pos_x, y=pos_y, width=width, height=height) - c.set_opacity(Config.get("bar_opacity", 1.0)) + c.opacity = Config.get("bar_opacity", 1.0) widget.set_client(c, screen) placed = True if not placed: @@ -722,11 +737,11 @@ class Kuro(BaseTheme): # Detach visualizer from widget if it was a visualizer window if isinstance(client, KuroStatic): - for screen in self.qtile.screens: + for screen in qtile.screens: for widget in screen.top.widgets: if isinstance(widget, kuro.utils.widgets.AudioVisualizerWidget): if widget.client == client: - screen_index = self.qtile.screens.index(screen) + screen_index = qtile.screens.index(screen) logger.warning("Detaching {} {} from widget {} on screen {}".format(client, client.window.wid, type(widget).__name__, screen_index)) widget.client = None widget.screen = None @@ -876,7 +891,7 @@ class Kuro(BaseTheme): # Update colors in visualizers and restart visualizers with open(Config.get("glava_color_file_path", "~/.config/glava/kurobars_color.glsl"), 'w') as f: - f.write("#define COLOR {}\n#request setbg {}".format(colors['color15'], colors['color1'][1:])) + f.write("#define COLOR {}\n#request setbg {}00".format(colors['color15'], colors['color1'][1:])) qtile.theme_instance.reinitialize_visualizers() utils.notify( diff --git a/kuro/utils/general.py b/kuro/utils/general.py index bfa32fc..92551f7 100644 --- a/kuro/utils/general.py +++ b/kuro/utils/general.py @@ -7,7 +7,7 @@ import notify2 import six from dbus import DBusException from libqtile import widget -from libqtile.window import Internal +from libqtile.backend.x11.window import Internal from libqtile.bar import Bar from notify2 import Notification, URGENCY_NORMAL from libqtile.log_utils import logger diff --git a/kuro/utils/widgets.py b/kuro/utils/widgets.py index a122a50..7620d1a 100644 --- a/kuro/utils/widgets.py +++ b/kuro/utils/widgets.py @@ -18,7 +18,7 @@ from libqtile.widget.currentlayout import CurrentLayoutIcon from libqtile.widget.graph import _Graph from libqtile.widget.tasklist import TaskList from libqtile.widget.wlan import get_status -from libqtile.window import Window +from libqtile.backend.x11.window import Window from kuro.utils.general import notify, BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT, BUTTON_DOWN, BUTTON_UP, BUTTON_MUTE, \ call_process @@ -260,6 +260,7 @@ class MediaWidget(base.InLoopPollText): ('on_text_pause', ' {}', 'The pattern for the text if music is paused.'), ('on_text_stop', ' {}', 'The pattern for the text if music is stopped.'), ('update_interval', 1, 'The update interval.'), + ('max_chars_per_player', 50, 'Maximum characters of text per player.'), ] player_icons = { @@ -333,7 +334,7 @@ class MediaWidget(base.InLoopPollText): def cmd_update_custom_player(self, player_name, data): # Update firefox player - if player_name == "firefox": + if player_name.startswith("firefox"): if data['playing'] and data['muted']: self.custom_player_data['firefox']['showing'] = True self.custom_player_data['firefox']['state'] = MediaWidget.Status.PAUSED @@ -355,8 +356,11 @@ class MediaWidget(base.InLoopPollText): players = [] # Playerctl players - command = ["playerctl", "-l"] - result = self.call_process(command) + try: + result = self.call_process(["playerctl", "-l"]) + except subprocess.CalledProcessError: + result = None + if result: players.extend([x for x in result.split("\n") if x]) @@ -398,8 +402,14 @@ class MediaWidget(base.InLoopPollText): text = "Unknown" if cmd_result in ["Playing", "Paused"]: - artist = self.call_process(['playerctl', '-p', player, 'metadata', 'artist']).strip() - title = self.call_process(['playerctl', '-p', player, 'metadata', 'title']).strip() + try: + artist = self.call_process(['playerctl', '-p', player, 'metadata', 'artist']).strip() + except subprocess.CalledProcessError: + artist = None + try: + title = self.call_process(['playerctl', '-p', player, 'metadata', 'title']).strip() + except subprocess.CalledProcessError: + title = None if artist and title: text = "{} - {}".format(artist, title) @@ -419,13 +429,17 @@ class MediaWidget(base.InLoopPollText): def _get_formatted_text(self, status): if status[0] == MediaWidget.Status.PLAYING: - return self.on_text_play.format(status[1]) + res = self.on_text_play.format(status[1]) elif status[0] == MediaWidget.Status.PAUSED: - return self.on_text_pause.format(status[1]) + res = self.on_text_pause.format(status[1]) elif status[0] == MediaWidget.Status.STOPPED: - return self.on_text_stop.format(status[1]) + res = self.on_text_stop.format(status[1]) else: - return "Unknown" + res = "Unknown" + res = pangocffi.markup_escape_text(res) + if len(res) > self.max_chars_per_player: + res = res[:self.max_chars_per_player] + "..." + return res def draw(self): super(MediaWidget, self).draw() @@ -437,7 +451,12 @@ class MediaWidget(base.InLoopPollText): return self.off_text else: for player in status.keys(): - icon = self.player_icons.get(player, player) + # Shorten firefox.instance[0-9]+ to just firefox for icon finding + if player.startswith("firefox"): + player_icon = "firefox" + else: + player_icon = player + icon = self.player_icons.get(player_icon, player_icon) text.append("{} {}".format(icon, self._get_formatted_text(status[player]))) return " | ".join(text) if text else self.off_text diff --git a/kuro/utils/windows.py b/kuro/utils/windows.py index edaf7ac..6bfd997 100644 --- a/kuro/utils/windows.py +++ b/kuro/utils/windows.py @@ -1,7 +1,6 @@ from cairocffi.test_xcb import xcffib from libqtile import hook -from libqtile.window import Window, Static - +from libqtile.backend.x11.window import Window, Static class KuroStatic(Static):