Meconopsis changes for Wayland and general refactoring/optimizations
This commit is contained in:
parent
1e65025045
commit
2860100089
9 changed files with 697 additions and 1185 deletions
|
@ -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()
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue