Meconopsis changes for Wayland and general refactoring/optimizations

This commit is contained in:
Kevin Alberts 2024-02-08 18:59:30 +01:00
parent 1e65025045
commit 2860100089
9 changed files with 697 additions and 1185 deletions

View file

@ -2,20 +2,14 @@ import re
import subprocess
import traceback
from time import sleep
from typing import List
import notify2
import six
from dbus import DBusException
from libqtile import widget
from libqtile.backend.x11.window import Internal
from libqtile.bar import Bar
from notify2 import Notification, URGENCY_NORMAL
from libqtile.log_utils import logger
try:
notify2.init("QTileWM")
except DBusException as e:
logger.error("Could not initialize notify2: {}".format(e))
from libqtile import qtile
BUTTON_LEFT = 1
BUTTON_MIDDLE = 2
@ -38,40 +32,68 @@ def is_running(process):
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):
try:
if isinstance(process, list):
return subprocess.Popen(process)
elif isinstance(process, str):
return subprocess.Popen(process.split())
else:
pass
logger.info(f"Failed to execute_once")
except FileNotFoundError as e:
logger.error(f"Could not execute {process}, FileNotFoundError - {e}")
def execute_once(process):
logger.info(f"Attempting to execute_once: {process}")
if not is_running(process):
return execute(process)
logger.info(f"Process was already running: {process}")
def start_in_group(theme, qtile, group: str, command: List[str], floating: bool = False,
intrusive: bool = False, dont_break: bool = False):
try:
proc = subprocess.Popen(command)
match_args = {"net_wm_pid": proc.pid}
rule_args = {
"float": floating,
"intrusive": intrusive,
"group": group,
"break_on_match": not dont_break,
}
rule_id = qtile.add_rule(match_args, rule_args)
theme.autostart_app_rules[proc.pid] = rule_id
return proc
except FileNotFoundError as e:
logger.error(f"Could not execute {process}, FileNotFoundError - {e}")
def start_in_group_once(theme, qtile, group: str, command: List[str], floating: bool = False,
intrusive: bool = False, dont_break: bool = False):
logger.info(f"Attempting to start_in_group_once: {command}")
if not is_running(command):
return start_in_group(theme=theme, qtile=qtile, group=group, command=command,
floating=floating, intrusive=intrusive, dont_break=dont_break)
logger.info(f"Process was already running: {command}")
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.
Run the given command and return the string from stdout.
"""
output = subprocess.check_output(command, **kwargs)
if six.PY3:
output = output.decode()
return output
return subprocess.check_output(command, **kwargs).decode()
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]
if qtile.core.name == "x11":
logger.info("Using xrandr to detect screen count")
output = subprocess.check_output("xrandr -q".split()).decode('utf-8')
output = [x for x in output.split("\n") if " connected" in x]
else:
logger.info("Using lsmon (wallutils) to detect screen count")
output = subprocess.check_output(["lsmon"]).decode('utf-8')
output = output.split("\n")
except subprocess.CalledProcessError:
return 1
@ -87,8 +109,21 @@ def bar_separator(config):
padding=config.get('padding_spacer', 4),
)
def init_notify(qtile):
if qtile and qtile.theme_instance and qtile.theme_instance.startup_completed:
try:
if not notify2.is_initted():
logger.warning("Initializing Notify2")
notify2.init("QTileWM")
except DBusException:
logger.error(f"Failed to initialize Notify2 (DBus error), retrying later.")
except Exception:
logger.error(f"Failed to initialize Notify2 (Generic error), retrying later.")
else:
logger.warning(f"Not initializing Notify2 yet, QTile startup not completed.")
def notify(title, content, urgency=URGENCY_NORMAL, timeout=5000, image=None):
def notify(qtile, title, content, urgency=URGENCY_NORMAL, timeout=5000, image=None):
if image is not None:
notification = Notification(
summary=title, message=content,
@ -101,13 +136,14 @@ def notify(title, content, urgency=URGENCY_NORMAL, timeout=5000, image=None):
notification.set_timeout(timeout)
notification.set_urgency(urgency)
init_notify(qtile)
try:
return notification.show()
except notify2.UninittedError:
logger.warning("Notify2 was uninitialized, initializing...")
notify2.init("qtile")
return notification.show()
except DBusException as e:
try:
return notification.show()
except notify2.UninittedError:
logger.warning("Notify2 is not initialized")
except Exception as e:
logger.warning("Showing notification failed: {}".format(e))
logger.warning(traceback.format_exc())
@ -125,6 +161,10 @@ def spawn_popup(qtile, x, y, text):
:return: The popup instance
:rtype: Internal
"""
if qtile.core.name == "x11":
from libqtile.backend.x11.window import Internal
else:
from libqtile.backend.wayland.window import Internal
popup = Internal.create(
qtile, x, y, 100, 100, opacity=1
)
@ -158,11 +198,11 @@ def display_wm_class(qtile):
window = qtile.currentWindow if qtile else None
if window:
wm_class = window.window.get_wm_class() or None
wm_class = window.get_wm_class() or None
name = window.name
if wm_class:
notify(title="WM_Class of {}".format(name),
notify(qtile=qtile, title="WM_Class of {}".format(name),
content="{}".format(wm_class),
urgency=notify2.URGENCY_CRITICAL)
@ -189,76 +229,3 @@ def bluetooth_audio_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, *args, **kwargs):
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 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._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 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()