Skip to content

Commit 8f66e31

Browse files
authored
Prevent UI events from propagating beyond imgui (#569)
* event propagation * update * fix remove event handler
1 parent c62e65b commit 8f66e31

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

wgpu/gui/base.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def __init__(self, *args, **kwargs):
197197
super().__init__(*args, **kwargs)
198198
self._last_event_time = 0
199199
self._pending_events = {}
200-
self._event_handlers = defaultdict(set)
200+
self._event_handlers = defaultdict(list)
201201

202202
def _get_event_wait_time(self):
203203
"""Calculate the time to wait for the next event dispatching.
@@ -274,18 +274,21 @@ def handle_event(self, event):
274274
"""
275275
# Collect callbacks
276276
event_type = event.get("event_type")
277-
callbacks = self._event_handlers[event_type] | self._event_handlers["*"]
277+
callbacks = self._event_handlers[event_type] + self._event_handlers["*"]
278278
# Dispatch
279-
for callback in callbacks:
279+
for _, callback in callbacks:
280280
with log_exception(f"Error during handling {event['event_type']} event"):
281+
if event.get("stop_propagation", False):
282+
break
281283
callback(event)
282284

283-
def add_event_handler(self, *args):
285+
def add_event_handler(self, *args, order=0):
284286
"""Register an event handler to receive events.
285287
286288
Arguments:
287289
callback (callable): The event handler. Must accept a single event argument.
288290
*types (list of strings): A list of event types.
291+
order (int): The order in which the handler is called. Lower numbers are called first. Default is 0.
289292
290293
For the available events, see
291294
https://jupyter-rfb.readthedocs.io/en/stable/events.html.
@@ -331,7 +334,8 @@ def my_handler(event):
331334

332335
def decorator(_callback):
333336
for type in types:
334-
self._event_handlers[type].add(_callback)
337+
self._event_handlers[type].append((order, _callback))
338+
self._event_handlers[type].sort(key=lambda x: x[0])
335339
return _callback
336340

337341
if decorating:
@@ -346,4 +350,6 @@ def remove_event_handler(self, callback, *types):
346350
*types (list of strings): A list of event types.
347351
"""
348352
for type in types:
349-
self._event_handlers[type].remove(callback)
353+
self._event_handlers[type] = [
354+
(o, cb) for o, cb in self._event_handlers[type] if cb is not callback
355+
]

wgpu/utils/imgui/imgui_renderer.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,13 @@ def __init__(
7878
self._backend.io.display_framebuffer_scale = (scale, scale)
7979

8080
canvas.add_event_handler(self._on_resize, "resize")
81-
canvas.add_event_handler(self._on_mouse_move, "pointer_move")
82-
canvas.add_event_handler(self._on_mouse, "pointer_up", "pointer_down")
83-
canvas.add_event_handler(self._on_key, "key_up", "key_down")
84-
canvas.add_event_handler(self._on_wheel, "wheel")
85-
canvas.add_event_handler(self._on_char_input, "char")
81+
canvas.add_event_handler(self._on_mouse_move, "pointer_move", order=-99)
82+
canvas.add_event_handler(
83+
self._on_mouse, "pointer_up", "pointer_down", order=-99
84+
)
85+
canvas.add_event_handler(self._on_key, "key_up", "key_down", order=-99)
86+
canvas.add_event_handler(self._on_wheel, "wheel", order=-99)
87+
canvas.add_event_handler(self._on_char_input, "char", order=-99)
8688

8789
self._update_gui_function = None
8890

@@ -152,11 +154,17 @@ def _on_resize(self, event):
152154
def _on_mouse_move(self, event):
153155
self._backend.io.add_mouse_pos_event(event["x"], event["y"])
154156

157+
if self._backend.io.want_capture_mouse:
158+
event["stop_propagation"] = True
159+
155160
def _on_mouse(self, event):
156161
event_type = event["event_type"]
157162
down = event_type == "pointer_down"
158163
self._backend.io.add_mouse_button_event(event["button"] - 1, down)
159164

165+
if self._backend.io.want_capture_mouse:
166+
event["stop_propagation"] = True
167+
160168
def _on_key(self, event):
161169
event_type = event["event_type"]
162170
down = event_type == "key_down"
@@ -182,8 +190,17 @@ def _on_key(self, event):
182190
key = self.KEY_MAP_MOD[key_name]
183191
self._backend.io.add_key_event(key, down)
184192

193+
if self._backend.io.want_capture_keyboard:
194+
event["stop_propagation"] = True
195+
185196
def _on_wheel(self, event):
186197
self._backend.io.add_mouse_wheel_event(event["dx"] / 100, event["dy"] / 100)
187198

199+
if self._backend.io.want_capture_mouse:
200+
event["stop_propagation"] = True
201+
188202
def _on_char_input(self, event):
189203
self._backend.io.add_input_characters_utf8(event["char_str"])
204+
205+
if self._backend.io.want_text_input:
206+
event["stop_propagation"] = True

0 commit comments

Comments
 (0)