11import logging
22import subprocess
3- import time
43import re
4+ import threading
5+ import queue
56import dbus
67import dbus .lowlevel
8+ import dbus .service
9+ from dbus .mainloop .glib import DBusGMainLoop
10+ from gi .repository import GLib
711from 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
1059def 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