code: def _test_callbacks(canvas):
      """Tests input capabilities, triaging based on backend"""
      backend_name = canvas._app.backend_name
      backend = canvas._backend
      if backend_name.lower() == "pyglet":
          # Test Pyglet callbacks can take reasonable args
          backend.on_resize(100, 100)
          backend.our_draw_func()
          backend.on_mouse_press(10, 10, 1)
          backend.on_mouse_release(10, 11, 1)
          backend.on_mouse_motion(10, 12, 0, 1)
          backend.on_mouse_drag(10, 13, 0, 1, 1, 0)
          backend.on_mouse_scroll(10, 13, 1, 1)
          backend.on_key_press(10, 0)
          backend.on_key_release(10, 0)
          backend.on_text("foo")
      elif backend_name.lower() == "glfw":
          # Test GLFW callbacks can take reasonable args
          _id = backend._id
          backend._on_draw(_id)
          backend._on_resize(_id, 100, 100)
  
          backend._on_key_press(_id, 340, 340, 1, 0)  # Shift.
          backend._on_key_press(_id, 50, 50, 1, 0)  # 2
          backend._on_key_char(_id, 50)
          backend._on_key_press(_id, 50, 50, 0, 0)
          backend._on_key_press(_id, 340, 340, 0, 0)
  
          backend._on_key_press(_id, 65, 65, 1, 0)  # Plain A
          backend._on_key_char(_id, 197)  # Unicode A.
          backend._on_key_char(_id, 197)  # Repeat A.
          backend._on_key_press(_id, 65, 65, 0, 0)
  
          backend._on_mouse_button(_id, 1, 1, 0)
          backend._on_mouse_scroll(_id, 1, 0)
          backend._on_mouse_motion(_id, 10, 10)
          backend._on_close(_id)
      elif any(x in backend_name.lower() for x in ("qt", "pyside")):
          # constructing fake Qt events is too hard :(
          pass
      elif "sdl2" in backend_name.lower():
          event = namedtuple(
              "event",
              ["type", "window", "motion", "button", "wheel", "key"],
          )
          event.type = 512  # WINDOWEVENT
          event.window = namedtuple(
              "window", ["event", "data1", "data2"]
          )
          event.motion = namedtuple("motion", ["x", "y"])
          event.button = namedtuple("button", ["x", "y", "button"])
          event.wheel = namedtuple("wheel", ["x", "y"])
          event.key = namedtuple("key", ["keysym"])
          event.key.keysym = namedtuple("keysym", ["mod", "sym"])
  
          event.window.event = 5  # WINDOWEVENT_RESIZED
          event.window.data1 = 10
          event.window.data2 = 20
          backend._on_event(event)
  
          event.type = 1024  # SDL_MOUSEMOTION
          event.motion.x, event.motion.y = 1, 1
          backend._on_event(event)
  
          event.type = 1025  # MOUSEBUTTONDOWN
          event.button.x, event.button.y, event.button.button = 1, 1, 1
          backend._on_event(event)
          event.type = 1026  # MOUSEBUTTONUP
          backend._on_event(event)
  
          event.type = 1027  # sdl2.SDL_MOUSEWHEEL
          event.wheel.x, event.wheel.y = 0, 1
          backend._on_event(event)
  
          event.type = 768  # SDL_KEYDOWN
          event.key.keysym.mod = 1073742049  # SLDK_LSHIFT
          event.key.keysym.sym = 1073741906  # SDLK_UP
          backend._on_event(event)
          event.type = 769  # SDL_KEYUP
          backend._on_event(event)
      elif "wx" in backend_name.lower():
          # Constructing fake wx events is too hard
          pass
      elif "osmesa" in backend_name.lower():
          # No events for osmesa backend
          pass
      elif "tk" in backend_name.lower():
          event = namedtuple(
              "event",
              [
                  "serial",
                  "time",
                  "type",
                  "widget",
                  "width",
                  "height",
                  "char",
                  "keycode",
                  "keysym",
                  "keysym_num",
                  "state",
                  "x",
                  "y",
                  "x_root",
                  "y_root",
                  "num",
                  "delta",
              ],
          )
  
          event.width, event.height = 10, 20
          backend._on_configure(event)  # RESIZE
  
          event.x, event.y, event.state = 1, 1, 0x0
          backend._on_mouse_enter(event)
          backend._on_mouse_move(event)
  
          event.x, event.y, event.num = 1, 1, 1
          backend._on_mouse_button_press(event)
          backend._on_mouse_button_release(event)
          backend._on_mouse_double_button_press(event)
  
          event.delta = 120
          backend._on_mouse_wheel(event)
  
          event.keysym_num, event.keycode, event.state = (
              65362,
              0,
              0x0001,
          )  # SHIFT+UP
          backend._on_key_down(event)
          backend._on_key_up(event)
      else:
          raise ValueError
  
imports: import sys
  from collections import namedtuple
  from io import StringIO
  from time import sleep
  import gc
  import numpy
  from numpy.testing import assert_array_equal
  import pytest
  from vispy.app import use_app, Canvas, Timer, MouseEvent, KeyEvent
  from vispy.app.base import BaseApplicationBackend
  from vispy.testing import requires_application, SkipTest, assert_is, assert_in, run_tests_if_main, assert_equal, assert_true, assert_raises, IS_TRAVIS_CI
  from vispy.util import keys, use_log_level
  from vispy.gloo.program import Program, VertexBuffer, IndexBuffer
  from vispy.gloo.util import _screenshot
  from vispy.gloo import gl
label_desc: Use image node_id 4 for calling a global function with example usage: _test_callbacks(canvas) without return types