Skip to content

Commit 4a265ff

Browse files
committed
refactor: get kwin script output using dbus
refs: #337
1 parent 7242129 commit 4a265ff

2 files changed

Lines changed: 63 additions & 42 deletions

File tree

src/kde_material_you_colors/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
KWIN_DESKTOP_ID_JSCRIPT = (
6161
f"{TEMPDIR}/kde-material-you-colors-desktop-win-id-{USERNAME}.js"
6262
)
63+
DBUS_NAME = "luisbocanegra.kdematerialyou.colors"
6364
KONSOLE_ACTIVE_PROFILE_NAME = (
6465
f"{TEMPDIR}/kde-material-you-colors-konsole-profile-{USERNAME}"
6566
)

src/kde_material_you_colors/utils/kwin_utils.py

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,60 @@
11
import logging
22
import subprocess
3-
import time
43
import re
4+
import threading
5+
import queue
56
import dbus
67
import dbus.lowlevel
8+
import dbus.service
9+
from dbus.mainloop.glib import DBusGMainLoop
10+
from gi.repository import GLib
711
from kde_material_you_colors import settings
812

13+
DBusGMainLoop(set_as_default=True)
14+
15+
16+
class WindowIdReceiver(dbus.service.Object):
17+
def __init__(self, bus, loop, result_queue):
18+
self.loop = loop
19+
self.bus = bus
20+
self.result_queue = result_queue
21+
self._quit = False
22+
self.bus.request_name(settings.DBUS_NAME, dbus.bus.NAME_FLAG_REPLACE_EXISTING)
23+
super().__init__(self.bus, "/")
24+
25+
@dbus.service.method(settings.DBUS_NAME)
26+
def result(self, text):
27+
self.result_queue.put(text)
28+
self.cleanup()
29+
30+
def cleanup(self):
31+
if self._quit:
32+
return
33+
self.remove_from_connection()
34+
35+
try:
36+
dbus_daemon = self.bus.get_object(
37+
"org.freedesktop.DBus", "/org/freedesktop/DBus"
38+
)
39+
dbus_interface = dbus.Interface(dbus_daemon, "org.freedesktop.DBus")
40+
dbus_interface.ReleaseName(settings.DBUS_NAME)
41+
except dbus.exceptions.DBusException as e:
42+
logging.exception(f"Error releasing name: {e.get_dbus_message()}")
43+
44+
self.loop.quit()
45+
self._quit = True
46+
47+
48+
def run_dbus_service(result_queue):
49+
loop = GLib.MainLoop()
50+
bus = dbus.SessionBus()
51+
52+
service = WindowIdReceiver(bus, loop, result_queue)
53+
GLib.timeout_add(2000, service.cleanup)
54+
55+
logging.debug("D-Bus service waiting for window id")
56+
loop.run()
57+
958

1059
def reload():
1160
if not settings.DESKTOP_IS_KDE:
@@ -100,7 +149,7 @@ def load_desktop_window_id_script():
100149
# keep only the id
101150
script_id = re.sub(r"\D", "", result.stdout.strip())
102151

103-
# logging.debug(f"Script loaded id: {command}")
152+
logging.debug(f"Script loaded id: {script_id}")
104153

105154
if script_id.isdigit():
106155
return script_id
@@ -149,8 +198,7 @@ def get_desktop_window_id(screen: int = 0) -> str | None:
149198
// it seems the list of windows is sorted by the screens positions(?)
150199
// and (at least on my machine) this works for any arrangement
151200
//desktopWindows.sort((b,a) => (a.pos.x - b.pos.x))
152-
// FIXME: Use callDBus + dbus service instead
153-
console.error("KMYC-desktop-window-id:", desktopWindows[{screen}].id)
201+
callDBus("{settings.DBUS_NAME}", "/", "{settings.DBUS_NAME}", "result", desktopWindows[{screen}].id.toString());
154202
"""
155203
with open(settings.KWIN_DESKTOP_ID_JSCRIPT, "w", encoding="utf-8") as js:
156204
js.write(script_str)
@@ -163,56 +211,28 @@ def get_desktop_window_id(screen: int = 0) -> str | None:
163211
raise
164212

165213
try:
214+
result_queue: queue.Queue = queue.Queue()
215+
t = threading.Thread(target=run_dbus_service, args=(result_queue,))
216+
t.start()
217+
166218
# run the script
167219
bus = dbus.SessionBus()
168220
kwin = bus.get_object("org.kde.KWin", "/Scripting/Script" + script_id)
169221
script = dbus.Interface(kwin, "org.kde.kwin.Script")
170-
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
171222
script.run()
172-
time.sleep(0.1)
173223
try:
174-
command = [
175-
"journalctl",
176-
"--since",
177-
timestamp,
178-
"--user",
179-
"-u",
180-
"plasma-kwin_wayland.service",
181-
"-u",
182-
"plasma-kwin_x11.service",
183-
"--output",
184-
"cat",
185-
"-g",
186-
"KMYC-desktop-window-id",
187-
]
188-
189-
# Execute the command using subprocess.run
190-
result = subprocess.run(
191-
command,
192-
stdout=subprocess.PIPE,
193-
stderr=subprocess.STDOUT,
194-
text=True,
195-
check=True,
196-
)
224+
win_id = result_queue.get(block=True, timeout=2)
225+
except queue.Empty:
226+
win_id = None
197227

198-
# The output is now stored in result.stdout
199-
output = result.stdout.strip()
200-
win_id = output.split(" ").pop()
201-
except subprocess.CalledProcessError as e:
202-
error = f"Script id {script_id} didn't return a desktop id for screen {screen}: {e}"
203-
# Replace time to make notify show the error only one time
204-
cmd = str(e).replace(timestamp, "TIME_NOW")
205-
logging.exception(error)
206-
script.stop()
207-
raise subprocess.CalledProcessError(e.returncode, cmd, e.output, e.stderr)
228+
t.join()
229+
script.stop()
208230
except dbus.exceptions.DBusException as e:
209231
msg = f"Error running script with id {script_id}: {e.get_dbus_message()}"
210232
logging.exception(msg)
211233
raise
212-
else:
213-
script.stop()
214234

215-
# logging.debug(f"HANDLE: {win_id}")
235+
logging.debug(f"Desktop window id: {win_id}")
216236
return win_id
217237

218238

0 commit comments

Comments
 (0)