@@ -16,6 +16,9 @@ class Communicate(QObject):
1616
1717
1818class OverlayWindow (OverlayWidget ):
19+ custom_draw_requested = Signal (str , object , object )
20+ custom_clear_requested = Signal (object )
21+
1922 def __init__ (self , hwnd_window : HwndWindow ):
2023 super ().__init__ ()
2124 self ._source_visible = False
@@ -27,6 +30,8 @@ def __init__(self, hwnd_window: HwndWindow):
2730 self ._boxes_until = 0
2831 self ._custom_drawing_active = False
2932 self ._custom_drawing_until = 0
33+ self .custom_painters = {}
34+ self ._custom_painter_until = {}
3035 # Set translucent background
3136 self .setAttribute (Qt .WA_TranslucentBackground )
3237
@@ -39,6 +44,8 @@ def __init__(self, hwnd_window: HwndWindow):
3944 communicate .clear_box .connect (self .clear_drawing )
4045 communicate .blur_overlay .connect (self .update_blur_patches )
4146 communicate .clear_blur_overlay .connect (self .clear_blur_overlay )
47+ self .custom_draw_requested .connect (self ._set_custom_draw , Qt .QueuedConnection )
48+ self .custom_clear_requested .connect (self ._clear_custom_draw , Qt .QueuedConnection )
4249
4350 # self.update_overlay(hwnd_window.visible, hwnd_window.x, hwnd_window.y, hwnd_window.window_width,
4451 # hwnd_window.window_height, hwnd_window.width, hwnd_window.height, hwnd_window.scaling)
@@ -65,6 +72,46 @@ def request_show(self, duration=4.0):
6572 self .update ()
6673 QTimer .singleShot (int (duration * 1000 ) + 10 , self .expire_custom_drawing )
6774
75+ def draw (self , key , callback , duration = None ):
76+ """Schedule arbitrary painting with callback(QPainter, OverlayWindow)."""
77+ if not callable (callback ):
78+ raise TypeError ('callback must be callable' )
79+ self .custom_draw_requested .emit (str (key ), callback , duration )
80+
81+ def clear_draw (self , key = None ):
82+ """Remove one custom painter, or all painters when key is None."""
83+ self .custom_clear_requested .emit (key )
84+
85+ def _set_custom_draw (self , key , callback , duration ):
86+ self .custom_painters [key ] = callback
87+ if duration is None :
88+ self ._custom_painter_until .pop (key , None )
89+ else :
90+ duration = max (0.0 , float (duration ))
91+ self ._custom_painter_until [key ] = time .monotonic () + duration
92+ QTimer .singleShot (int (duration * 1000 ) + 10 , lambda : self ._expire_custom_draw (key ))
93+ self .refresh_visibility ()
94+ self .update ()
95+
96+ def _clear_custom_draw (self , key ):
97+ if key is None :
98+ self .custom_painters .clear ()
99+ self ._custom_painter_until .clear ()
100+ else :
101+ key = str (key )
102+ self .custom_painters .pop (key , None )
103+ self ._custom_painter_until .pop (key , None )
104+ self .refresh_visibility ()
105+ self .update ()
106+
107+ def _expire_custom_draw (self , key ):
108+ until = self ._custom_painter_until .get (key )
109+ if until is not None and time .monotonic () >= until :
110+ self .custom_painters .pop (key , None )
111+ self ._custom_painter_until .pop (key , None )
112+ self .refresh_visibility ()
113+ self .update ()
114+
68115 def on_draw_box (self , key , boxes , color , frame , debug ):
69116 if boxes and self ._boxes_enabled :
70117 self ._boxes_active = True
@@ -100,7 +147,8 @@ def clear_blur_overlay(self):
100147 self .refresh_visibility ()
101148
102149 def refresh_visibility (self ):
103- required = self ._boxes_active or self ._custom_drawing_active or bool (self .blur_images )
150+ required = (self ._boxes_active or self ._custom_drawing_active
151+ or bool (self .blur_images ) or bool (self .custom_painters ))
104152 if self ._source_visible and required and not self .isVisible ():
105153 self .show ()
106154 return
0 commit comments