code: def handle_event(self, ev):
      type = ev["event_type"]
      if type == "resize":
          # Note that jupyter_rfb already throttles this event
          w, h, r = ev["width"], ev["height"], ev["pixel_ratio"]
          self._logical_size = w, h
          self._physical_size = int(w * r), int(h * r)
          self._helper.set_physical_size(*self._physical_size)
          self._loop.call_soon(self._emit_resize_event)
          self._vispy_update()  # make sure to schedule a new draw
      elif type == "pointer_down":
          self._vispy_mouse_press(
              native=ev,
              pos=(ev["x"], ev["y"]),
              button=ev["button"],
              modifiers=self._modifiers(ev),
          )
      elif type == "pointer_up":
          self._vispy_mouse_release(
              native=ev,
              pos=(ev["x"], ev["y"]),
              button=ev["button"],
              modifiers=self._modifiers(ev),
          )
      elif type == "pointer_move":
          self._vispy_mouse_move(
              native=ev,
              pos=(ev["x"], ev["y"]),
              button=ev["button"],
              modifiers=self._modifiers(ev),
          )
      elif type == "double_click":
          self._vispy_mouse_double_click(
              native=ev,
              pos=(ev["x"], ev["y"]),
              button=ev["button"],
              modifiers=self._modifiers(ev),
          )
      elif type == "wheel":
          self._vispy_canvas.events.mouse_wheel(
              native=ev,
              pos=(ev["x"], ev["y"]),
              delta=(ev["dx"] / 100, -ev["dy"] / 100),
              modifiers=self._modifiers(ev),
          )
      elif type == "key_down":
          # The special key names are all (most?) the same
          # But the key is actually more like tex, e.g. shift + 3 becomes "#"
          self._vispy_canvas.events.key_press(
              native=ev,
              key=keys.Key(ev["key"]),
              modifiers=self._modifiers(ev),
              text=ev["key"],
          )
      elif type == "key_up":
          self._vispy_canvas.events.key_release(
              native=ev,
              key=keys.Key(ev["key"]),
              modifiers=self._modifiers(ev),
              text=ev["key"],
          )
      elif type == "close":
          self._lifecycle = 2
          self._context.close()
          _stop_timers(self._vispy_canvas)
      else:
          pass
  
imports: import asyncio
  from ..base import BaseApplicationBackend, BaseCanvasBackend, BaseTimerBackend
  from ...app import Timer
  from ...util import keys
  from ._offscreen_util import OffscreenContext, FrameBufferHelper
label_desc: Use image node_id 2 for calling the CanvasBackend obj's underlying member method code with example usage: obj.handle_event(ev) without return types