diff --git a/kuro/config.py b/kuro/config.py index dc21c57..f0320fb 100644 --- a/kuro/config.py +++ b/kuro/config.py @@ -22,6 +22,7 @@ class Config(BaseConfig): app_chat = "/usr/bin/rambox" app_irc = "quasselclient" app_mail = "thunderbird" + app_music = "spotify" cmd_brightness_up = "sudo /usr/bin/xbacklight -inc 10" cmd_brightness_down = "sudo /usr/bin/xbacklight -dec 10" lock_command = "bash /home/kevin/bin/lock.sh" @@ -29,6 +30,20 @@ class Config(BaseConfig): cmd_screenshot = "xfce4-screenshooter -r -c -d 1" cmd_alt_screenshot = "xfce4-screenshooter -w -c -d 0" + # Keyboard commands + cmd_media_play = "playerctl -i kdeconnect play-pause" + cmd_media_next = "playerctl -i kdeconnect next" + cmd_media_mute = "pamixer -t" + cmd_media_volume_down = "pamixer -i 2" + cmd_media_volume_up = "pamixer -d 2" + + # Display mode commands + cmd_monitor_mode_3s144 = "bash /home/kevin/.screenlayout/3scrns_144_rrot.sh" + cmd_monitor_mode_3s60 = "bash /home/kevin/.screenlayout/3scrns_60_rrot.sh" + cmd_monitor_mode_day = "bash /home/kevin/bin/monitor_day.sh" + cmd_monitor_mode_night = "bash /home/kevin/bin/monitor_night.sh" + cmd_monitor_mode_alt = "bash /home/kevin/bin/monitor_gamenight.sh" + # Commands wallpaper_config_command = "/home/kevin/bin/wal-nitrogen-noupdate" @@ -121,6 +136,7 @@ class Config(BaseConfig): volume_fontsize = 11 volume_theme_path = "/home/kevin/.config/qtile/kuro/resources/volume" volume_pulse_sink = "alsa_output.pci-0000_00_1f.3.analog-stereo" + volume_pulse_sink2 = "" volume_is_bluetooth_icon = False volume_update_interval = 0.2 @@ -155,6 +171,15 @@ class Config(BaseConfig): # Show thermal widget show_temperature = True + # Show GPU widget + show_gpu_widget = False + + # Show battery widget + show_battery_widget = False + # Audio control applications # apps_audio = ["pavucontrol"] - apps_audio_afterstart = "/home/kevin/bin/start_jack_audio_chain.sh" + apps_audio_afterstart = [] + + # Comma-separated list of ignored players in the media widget + media_ignore_players = "kdeconnect" diff --git a/kuro/theme.py b/kuro/theme.py index 2226c5e..7e15e82 100644 --- a/kuro/theme.py +++ b/kuro/theme.py @@ -83,6 +83,7 @@ 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): @@ -143,6 +144,9 @@ class Kuro(BaseTheme): # Floating toggle Key([self.mod, "shift"], 'f', lazy.window.toggle_floating()), + # Pinned toggle + Key([self.mod, "shift"], 'p', lazy.function(self.toggle_pinned)), + # Toggle between split and unsplit sides of stack. # Split = all windows displayed # Unsplit = 1 window displayed, like Max layout, but still with @@ -171,10 +175,27 @@ class Kuro(BaseTheme): Key([], "XF86MonBrightnessUp", lazy.spawn(Config.get('cmd_brightness_up', 'xbacklight -inc 10'))), Key([], "XF86MonBrightnessDown", lazy.spawn(Config.get('cmd_brightness_down', 'xbacklight -dec 10'))), + # Display modes + Key([self.mod], "Prior", lazy.spawn(Config.get('cmd_monitor_mode_3s144', 'true'))), + Key([self.mod], "Next", lazy.spawn(Config.get('cmd_monitor_mode_3s60', 'true'))), + Key([self.mod], "Home", lazy.spawn(Config.get('cmd_monitor_mode_day', 'true'))), + Key([self.mod], "End", lazy.spawn(Config.get('cmd_monitor_mode_night', 'true'))), + Key([self.mod], "Insert", lazy.spawn(Config.get('cmd_monitor_mode_alt', 'true'))), + + # Media keys + Key([], "XF86AudioPlay", lazy.spawn(Config.get('cmd_media_play', 'true'))), + Key([], "XF86AudioNext", lazy.spawn(Config.get('cmd_media_next', 'true'))), + Key([], "XF86AudioMute", lazy.spawn(Config.get('cmd_media_mute', 'true'))), + Key([], "XF86AudioRaiseVolume", lazy.spawn(Config.get('cmd_media_volume_up', 'true'))), + Key([], "XF86AudioLowerVolume", lazy.spawn(Config.get('cmd_media_volume_down', 'true'))), + + # Sleep key + Key([], "XF86Sleep", lazy.spawn(Config.get('cmd_sleep', 'true'))), + # Screenshot key Key([], "Print", lazy.spawn(Config.get('cmd_screenshot', 'xfce4-screenshooter'))), - # Alt Screenshot + # Alt screenshot Key([self.mod], "Print", lazy.spawn(Config.get('cmd_alt_screenshot', 'xfce4-screenshooter'))), # Toggle between different layouts as defined below @@ -234,7 +255,7 @@ class Kuro(BaseTheme): groups.append(Group("", spawn=Config.get('file_manager', "true"))) groups.append(Group("", spawn=Config.get('app_mail', "true"))) groups.append(Group("")) - groups.append(Group("")) + groups.append(Group("", spawn=Config.get('app_music', "true"))) groups.append(Group("")) groups.append(Group("", spawn=Config.get('apps_audio', "true"))) groups.append(Group("", layout='floating', layouts=[ @@ -321,7 +342,7 @@ class Kuro(BaseTheme): widgets.append(kuro.utils.widgets.AudioVisualizerWidget(margin_x=0, margin_y=0)) widgets.extend([ - kuro.utils.widgets.MediaWidget(), + kuro.utils.widgets.MediaWidget(ignore_players=Config.get('media_ignore_players', '')), kuro.utils.widgets.TextSpacerWidget(fontsize=14), ]) @@ -344,19 +365,36 @@ class Kuro(BaseTheme): kuro.utils.widgets.CPUInfoWidget(fontsize_left=16, fontsize_right=11), kuro.utils.widgets.MemoryInfoWidget(fontsize_left=18, fontsize_right=11), kuro.utils.widgets.DiskIOInfoWidget(fontsize_left=16, fontsize_right=11), - kuro.utils.widgets.BatteryInfoWidget(fontsize_left=16, fontsize_right=11), + ]) + if Config.get('show_battery_widget', False): + widgets.extend([ + kuro.utils.widgets.BatteryInfoWidget(fontsize_left=16, fontsize_right=11), + ]) + widgets.extend([ kuro.utils.widgets.VolumeInfoWidget( pulse_sink=Config.get('volume_pulse_sink', None), fontsize_left=18, fontsize_right=11, + font_left=Config.get('font_groupbox', None), + ), + kuro.utils.widgets.VolumeInfoWidget( + pulse_sink=Config.get('volume_pulse_sink2', None), + fontsize_left=18, + fontsize_right=11, + font_left=Config.get('font_groupbox', None), ), kuro.utils.widgets.TextSpacerWidget(fontsize=14), kuro.utils.widgets.NetworkInfoWidget(fontsize_left=16, fontsize_right=14), - kuro.utils.widgets.GPUStatusWidget( - theme_path=Config.get('gpu_theme_path', '/home/docs/checkouts/readthedocs.org/user_builds/qtile' - '/checkouts/latest/libqtile/resources/battery-icons'), - padding=0, - ), + ]) + if Config.get('show_gpu_widget', False): + widgets.extend([ + kuro.utils.widgets.GPUStatusWidget( + theme_path=Config.get('gpu_theme_path', '/home/docs/checkouts/readthedocs.org/user_builds/qtile' + '/checkouts/latest/libqtile/resources/battery-icons'), + padding=0, + ) + ]) + widgets.extend([ kuro.utils.widgets.TextSpacerWidget(fontsize=14), ]) @@ -466,7 +504,6 @@ class Kuro(BaseTheme): @staticmethod def update_screens(qtile): out = utils.call_process(["xrandr", "--current"]) - #mode_out = utils.call_process(["optimus-manager", "--print-mode"]) video_mode = "nvidia" #if "nvidia" in mode_out: # video_mode = "nvidia" @@ -552,6 +589,12 @@ class Kuro(BaseTheme): window.floating = True + # Pinned toggle function + @staticmethod + def toggle_pinned(qtile): + windows = qtile.cmd_windows() + print(windows) + # QTile base callbacks def callback_startup_once(self, *args, **kwargs): if not hasattr(qtile, 'theme_instance'): @@ -709,11 +752,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 @@ -729,7 +772,7 @@ class Kuro(BaseTheme): wallpapers = [] wallpaper_dir = Config.get("desktop_bg_folder", "") try: - wallpapers = os.listdir(wallpaper_dir) + wallpapers = [x for x in os.listdir(wallpaper_dir) if ".vertical." not in x] except os.error as e: logger.warning("Could not load wallpapers from directory: {}".format(e)) diff --git a/kuro/utils/general.py b/kuro/utils/general.py index 5bc12bc..f63e1ad 100644 --- a/kuro/utils/general.py +++ b/kuro/utils/general.py @@ -105,7 +105,7 @@ def notify(title, content, urgency=URGENCY_NORMAL, timeout=5000, image=None): return notification.show() except notify2.UninittedError: logger.warning("Notify2 was uninitialized, initializing...") - notify2.init("qtile") + notify2.init("qtile") return notification.show() except DBusException as e: logger.warning("Showing notification failed: {}".format(e)) @@ -204,22 +204,24 @@ class KuroTopBar(Bar): self.window.update_name() def draw(self): - if self.queued_draws == 0: - self.qtile.call_soon(self._actual_draw) - self.queued_draws += 1 + if not self.widgets: + return + if not self._draw_queued: + self.future = self.qtile.call_soon(self._actual_draw) + self._draw_queued = True def _actual_draw(self): - self.queued_draws = 0 - self._resize(self.length, self.widgets) + self._draw_queued = False + self._resize(self._length, self.widgets) for i in self.widgets: i.draw() if self.widgets: end = i.offset + i.length - if end < self.length: + if end < self._length: if self.horizontal: - self.drawer.draw(offsetx=end, width=self.length - end) + self.drawer.draw(offsetx=end, width=self._length - end) else: - self.drawer.draw(offsety=end, height=self.length - end) + self.drawer.draw(offsety=end, height=self._length - end) self.theme.update_visualizers() diff --git a/kuro/utils/widgets.py b/kuro/utils/widgets.py index 36e1283..c1b2f32 100644 --- a/kuro/utils/widgets.py +++ b/kuro/utils/widgets.py @@ -139,6 +139,26 @@ class DualPaneTextboxBase(base._Widget): if self.layout_right: self.layout_right.font = value + @property + def font_left(self): + return self._font_left + + @font_left.setter + def font_left(self, value): + self._font_left = value + if self.layout_left: + self.layout_left.font = value + + @property + def font_right(self): + return self._font_right + + @font_right.setter + def font_right(self, value): + self._font_right = value + if self.layout_right: + self.layout_right.font = value + @property def fontshadow(self): return self._fontshadow @@ -262,6 +282,7 @@ class MediaWidget(base.InLoopPollText): ('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.'), + ('ignore_players', '', 'Comma-separated list of players to ignore.') ] player_icons = { @@ -319,13 +340,13 @@ class MediaWidget(base.InLoopPollText): if button == BUTTON_LEFT: player = self._player_to_control() if player is not None: - command = ["playerctl", "-p", player, "play-pause"] + command = ["playerctl", "-i", self.ignore_players, "-p", player, "play-pause"] _ = self.call_process(command) notify("MediaWidget", "Toggled {}".format(player)) if button == BUTTON_RIGHT: player = self._player_to_control() if player is not None: - command = ["playerctl", "-p", player, "next"] + command = ["playerctl", "-i", self.ignore_players, "-p", player, "next"] _ = self.call_process(command) if button == BUTTON_MIDDLE: # Jump to the screen that the player is on @@ -358,7 +379,7 @@ class MediaWidget(base.InLoopPollText): # Playerctl players try: - result = self.call_process(["playerctl", "-l"]) + result = self.call_process(["playerctl", "-i", self.ignore_players, "-l"]) except subprocess.CalledProcessError: result = None @@ -398,17 +419,17 @@ class MediaWidget(base.InLoopPollText): else: # PlayerCtl player - command = ["playerctl", "-p", player, "status"] + command = ["playerctl", "-i", self.ignore_players, "-p", player, "status"] cmd_result = self.call_process(command).strip() text = "Unknown" if cmd_result in ["Playing", "Paused"]: try: - artist = self.call_process(['playerctl', '-p', player, 'metadata', 'artist']).strip() + artist = self.call_process(['playerctl', "-i", self.ignore_players, '-p', player, 'metadata', 'artist']).strip() except subprocess.CalledProcessError: artist = None try: - title = self.call_process(['playerctl', '-p', player, 'metadata', 'title']).strip() + title = self.call_process(['playerctl', "-i", self.ignore_players, '-p', player, 'metadata', 'title']).strip() except subprocess.CalledProcessError: title = None @@ -438,7 +459,7 @@ class MediaWidget(base.InLoopPollText): else: res = "Unknown" res = pangocffi.markup_escape_text(res) - res = unicodedata.normalize("NFKD", res) + res = unicodedata.normalize('NFKD', res) if len(res) > self.max_chars_per_player: res = res[:self.max_chars_per_player] + "..." return res @@ -1196,7 +1217,7 @@ class VolumeInfoWidget(DualPaneTextboxBase): """Displays information about the volume""" orientations = base.ORIENTATION_HORIZONTAL defaults = [ - ('update_interval', 10, 'The update interval in seconds.'), + ('update_interval', 5, 'The update interval in seconds.'), ('text_pattern', "{percentage}%", 'The pattern for the text that is displayed.'), ('charging_color', "#ffffff", "Color when battery is charging"), ('normal_color', "#ffffff", "Color when value is normal"), diff --git a/required_packages.txt b/required_packages.txt index 8b3391e..ff3bd88 100644 --- a/required_packages.txt +++ b/required_packages.txt @@ -8,4 +8,5 @@ python-osc playerctl xfce4-screenshooter -xfce4-clipman-plugin \ No newline at end of file +xfce4-clipman-plugin +wireless_tools