Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
with open(os.path.join(ROOT_DIR, "docs", "reference_wgpu.rst"), "rb") as f:
wgpu_api_docs_text = f.read().decode()
for cls_name in wgpu.base.__all__:
expected_line = f".. autoclass:: wgpu.{cls_name}\n"
expected_line = f".. autoclass:: wgpu.{cls_name}"
assert expected_line in wgpu_api_docs_text, f"Missing docs for {cls_name}"

# Make flags and enum appear better in docs
Expand Down
59 changes: 58 additions & 1 deletion wgpu/gui/glfw.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
or ``sudo apt install libglfw3-wayland`` when using Wayland.
"""

from collections import defaultdict
import os
import sys
import time
Expand Down Expand Up @@ -138,6 +139,7 @@ def __init__(self, *, size=None, title=None, **kwargs):
self._need_draw = False
self._request_draw_timer_running = False
self._changing_pixel_ratio = False
self._event_handlers = defaultdict(set)

# Register ourselves
all_glfw_canvases.add(self)
Expand Down Expand Up @@ -308,7 +310,62 @@ def handle_event(self, event):
is a dict with at least the key event_type. For details, see
https://jupyter-rfb.readthedocs.io/en/latest/events.html
"""
pass
event_type = event.get("event_type")
for callback in self._event_handlers[event_type]:
callback(event)

def add_event_handler(self, *args):
"""Register an event handler.

Arguments:
callback (callable): The event handler. Must accept a
single event argument.
*types (list of strings): A list of event types.

For the available events, see
https://jupyter-rfb.readthedocs.io/en/latest/events.html

Can also be used as a decorator.

Example:

.. code-block:: py

def my_handler(event):
print(event)

canvas.add_event_handler(my_handler, "pointer_up", "pointer_down")

Decorator usage example:

.. code-block:: py

@canvas.add_event_handler("pointer_up", "pointer_down")
def my_handler(event):
print(event)
"""
decorating = not callable(args[0])
callback = None if decorating else args[0]
types = args if decorating else args[1:]

def decorator(_callback):
for type in types:
self._event_handlers[type].add(_callback)
return _callback

if decorating:
return decorator
return decorator(callback)

def remove_event_handler(self, callback, *types):
"""Unregister an event handler.

Arguments:
callback (callable): The event handler.
*types (list of strings): A list of event types.
"""
for type in types:
self._event_handlers[type].remove(callback)

# User events

Expand Down
60 changes: 59 additions & 1 deletion wgpu/gui/jupyter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
can be used as cell output, or embedded in a ipywidgets gui.
"""

from collections import defaultdict
import weakref
import asyncio

Expand All @@ -27,6 +28,7 @@ def __init__(self, *, size=None, title=None, **kwargs):
self._logical_size = 0, 0
self._is_closed = False
self._request_draw_timer_running = False
self._event_handlers = defaultdict(set)

# Register so this can be display'ed when run() is called
pending_jupyter_canvases.append(weakref.ref(self))
Expand All @@ -38,13 +40,69 @@ def __init__(self, *, size=None, title=None, **kwargs):
# Implementation needed for RemoteFrameBuffer

def handle_event(self, event):
event_type = event.get("event_type", "")
event_type = event.get("event_type")
if event_type == "close":
self._is_closed = True
elif event_type == "resize":
self._pixel_ratio = event["pixel_ratio"]
self._logical_size = event["width"], event["height"]

for callback in self._event_handlers[event_type]:
callback(event)

def add_event_handler(self, *args):
"""Register an event handler.

Arguments:
callback (callable): The event handler. Must accept a
single event argument.
*types (list of strings): A list of event types.

For the available events, see
https://jupyter-rfb.readthedocs.io/en/latest/events.html

Can also be used as a decorator.

Example:

.. code-block:: py

def my_handler(event):
print(event)

canvas.add_event_handler(my_handler, "pointer_up", "pointer_down")

Decorator usage example:

.. code-block:: py

@canvas.add_event_handler("pointer_up", "pointer_down")
def my_handler(event):
print(event)
"""
decorating = not callable(args[0])
callback = None if decorating else args[0]
types = args if decorating else args[1:]

def decorator(_callback):
for type in types:
self._event_handlers[type].add(_callback)
return _callback

if decorating:
return decorator
return decorator(callback)

def remove_event_handler(self, callback, *types):
"""Unregister an event handler.

Arguments:
callback (callable): The event handler.
*types (list of strings): A list of event types.
"""
for type in types:
self._event_handlers[type].remove(callback)

def get_frame(self):
self._request_draw_timer_running = False
# The _draw_frame_and_present() does the drawing and then calls
Expand Down