import re import subprocess from time import sleep import notify2 import six from libqtile import widget from libqtile.window import Internal from libqtile.bar import Bar from notify2 import Notification, URGENCY_NORMAL notify2.init("QTileWM") BUTTON_LEFT = 1 BUTTON_MIDDLE = 2 BUTTON_RIGHT = 3 BUTTON_SCROLL_UP = 4 BUTTON_SCROLL_DOWN = 5 def is_running(process): s = subprocess.Popen(["ps", "axuw"], stdout=subprocess.PIPE) if isinstance(process, list): process = "".join(process) for x in s.stdout: if re.search(process, x.decode('utf-8')): return True return False def execute(process): if isinstance(process, list): return subprocess.Popen(process) elif isinstance(process, str): return subprocess.Popen(process.split()) else: pass def execute_once(process): if not is_running(process): if isinstance(process, list): return subprocess.Popen(process) elif isinstance(process, str): return subprocess.Popen(process.split()) else: pass def call_process(command, **kwargs): """ This method uses `subprocess.check_output` to run the given command and return the string from stdout, which is decoded when using Python 3. """ output = subprocess.check_output(command, **kwargs) if six.PY3: output = output.decode() return output def get_screen_count(): try: output = subprocess.check_output("xrandr -q".split()).decode('utf-8') output = [x for x in output.split("\n") if " connected" in x] except subprocess.CalledProcessError: return 1 if output: return len(output) else: return 1 def bar_separator(config): return widget.Sep(foreground=config.get('colour_spacer_background', '#777777'), linewidth=config.get('width_spacer', 1), padding=config.get('padding_spacer', 4), ) def notify(title, content, urgency=URGENCY_NORMAL, timeout=5000, image=None): if image is not None: notification = Notification( summary=title, message=content, icon=image ) else: notification = Notification( summary=title, message=content ) notification.set_timeout(timeout) notification.set_urgency(urgency) return notification.show() def spawn_popup(qtile, x, y, text): """ :param qtile: The main qtile instance :type qtile: Qtile :param x: x-coordinate :type x: int :param y: y-coordinate :type y: int :param text: String to display :type text: str :return: The popup instance :rtype: Internal """ popup = Internal.create( qtile, x, y, 100, 100, opacity=1 ) # Create textwidget for in window popup.bordercolor = "#000000" popup.borderwidth = 1 popup.focus(False) #popup. return popup def despawn_popup(popup): """ :type popup: Internal :param popup: The popup to despawn """ popup.kill() def test_popups(qtile): popup = spawn_popup(qtile, 10, 10, "Hello World!") sleep(3) despawn_popup(popup) def display_wm_class(qtile): window = qtile.currentWindow if qtile else None if window: wm_class = window.window.get_wm_class() or None name = window.name if wm_class: notify(title="WM_Class of {}".format(name), content="{}".format(wm_class), urgency=notify2.URGENCY_CRITICAL) def bluetooth_audio_sink(): try: output = subprocess.check_output("pamixer --list-sinks".split()).decode("utf-8") output = [x for x in output.split('\n') if "blue" in x.lower()] except (subprocess.CalledProcessError, FileNotFoundError): return -1 sink = -1 try: sink = int(output[0].split()[0]) except IndexError: pass except AttributeError: pass except ValueError: pass return sink def bluetooth_audio_connected(): return bluetooth_audio_sink() != -1 class KuroTopBar(Bar): def __init__(self, theme, widgets, size, **config): self.theme = theme super(KuroTopBar, self).__init__(widgets, size, **config) def _configure(self, qtile, screen): super(KuroTopBar, self)._configure(qtile, screen) self.window.handle_EnterNotify = self.handle_enter_notify self.window.handle_LeaveNotify = self.handle_leave_notify self.window.window.set_property("_NET_WM_NAME", "KuroTopBar") self.window.update_name() def draw(self): if self.queued_draws == 0: self.qtile.call_soon(self._actual_draw) self.queued_draws += 1 def _actual_draw(self): self.queued_draws = 0 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 self.horizontal: self.drawer.draw(offsetx=end, width=self.length - end) else: self.drawer.draw(offsety=end, height=self.length - end) self.theme.update_visualizers() def handle_enter_notify(self, e): # self.theme.log_debug("Bar HandleEnterNotify") # # self.window.opacity = Config.get('bar_hover_opacity', 1.0) # print("Bar Hover Enter") # # try: # hovered_widget = [x for x in self.widgets if (x.offsetx + x.width) >= e.event_x][0] # except IndexError: # hovered_widget = None # # self.theme.log_debug("Hovered over {}".format(hovered_widget)) # # if hasattr(hovered_widget, "handle_hover_enter"): # hovered_widget.handle_hover_enter(e) self.draw() def handle_leave_notify(self, e): # self.theme.log_debug("Bar HandleLeaveNotify") # # self.window.opacity = Config.get('bar_opacity', 1.0) # print("Bar Hover Leave") # # try: # hovered_widget = [x for x in self.widgets if (x.offsetx + x.width) >= e.event_x][0] # except IndexError: # hovered_widget = None # # self.theme.log_debug("Hovered over {}".format(hovered_widget)) # # if hasattr(hovered_widget, "handle_hover_leave"): # hovered_widget.handle_hover_leave(e) self.draw()