A ctypes-based wrapper for GLFW3 that provides Python bindings for OpenGL, OpenGL ES, and Vulkan development on desktop platforms.
—
Comprehensive input system supporting keyboard, mouse, joystick, and gamepad input with both polling and callback-based event handling for interactive applications.
Process input events and window system messages.
def poll_events() -> None:
"""
Process all pending events.
This function processes only those events that are already in the
event queue and then returns immediately.
"""
def wait_events() -> None:
"""
Wait until events are queued and processes them.
This function puts the calling thread to sleep until at least
one event is available in the event queue.
"""
def wait_events_timeout(timeout: float) -> None:
"""
Wait with timeout until events are queued and processes them.
Parameters:
timeout: Maximum time to wait, in seconds
"""
def post_empty_event() -> None:
"""
Post an empty event to the event queue.
This function posts an empty event from the current thread
to the event queue, causing wait_events to return.
"""Configure input behavior for windows.
def get_input_mode(window, mode: int) -> int:
"""
Get the value of an input option for the window.
Parameters:
window: Window to query
mode: Input mode to query
Returns:
int: Current mode value
"""
def set_input_mode(window, mode: int, value: int) -> None:
"""
Set an input option for the window.
Parameters:
window: Window to configure
mode: Input mode to set
value: New mode value
"""# Input modes
CURSOR: int = 0x00033001
STICKY_KEYS: int = 0x00033002
STICKY_MOUSE_BUTTONS: int = 0x00033003
LOCK_KEY_MODS: int = 0x00033004
RAW_MOUSE_MOTION: int = 0x00033005
# Cursor mode values
CURSOR_NORMAL: int = 0x00034001
CURSOR_HIDDEN: int = 0x00034002
CURSOR_DISABLED: int = 0x00034003
CURSOR_CAPTURED: int = 0x00034004Handle keyboard input with both polling and callbacks.
def get_key(window, key: int) -> int:
"""
Get the last reported state of a keyboard key.
Parameters:
window: Window to query
key: Keyboard key constant
Returns:
int: PRESS, RELEASE, or REPEAT
"""
def get_key_name(key: int, scancode: int) -> str:
"""
Get the localized name of the specified printable key.
Parameters:
key: Key constant, or KEY_UNKNOWN
scancode: Platform-specific scancode
Returns:
str: Key name, or None if unavailable
"""
def get_key_scancode(key: int) -> int:
"""
Get the platform-specific scancode of the key.
Parameters:
key: Key constant
Returns:
int: Platform-specific scancode
"""
def set_key_callback(window, cbfun) -> callable:
"""
Set the key callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, key: int, scancode: int,
action: int, mods: int)
"""
def set_char_callback(window, cbfun) -> callable:
"""
Set the Unicode character callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, codepoint: int)
"""
def set_char_mods_callback(window, cbfun) -> callable:
"""
Set the Unicode character with modifiers callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, codepoint: int, mods: int)
"""# Key actions
RELEASE: int = 0
PRESS: int = 1
REPEAT: int = 2
# Modifier key bits
MOD_SHIFT: int = 0x0001
MOD_CONTROL: int = 0x0002
MOD_ALT: int = 0x0004
MOD_SUPER: int = 0x0008
MOD_CAPS_LOCK: int = 0x0010
MOD_NUM_LOCK: int = 0x0020
# Key constants (selection - 100+ available)
KEY_UNKNOWN: int = -1
KEY_SPACE: int = 32
KEY_APOSTROPHE: int = 39 # '
KEY_COMMA: int = 44 # ,
KEY_MINUS: int = 45 # -
KEY_PERIOD: int = 46 # .
KEY_SLASH: int = 47 # /
# Number keys
KEY_0: int = 48
KEY_1: int = 49
# ... through KEY_9: int = 57
# Letter keys
KEY_A: int = 65
KEY_B: int = 66
# ... through KEY_Z: int = 90
# Function keys
KEY_F1: int = 290
KEY_F2: int = 291
# ... through KEY_F25: int = 314
# Arrow keys
KEY_RIGHT: int = 262
KEY_LEFT: int = 263
KEY_DOWN: int = 264
KEY_UP: int = 265
# Common special keys
KEY_ESCAPE: int = 256
KEY_ENTER: int = 257
KEY_TAB: int = 258
KEY_BACKSPACE: int = 259
KEY_INSERT: int = 260
KEY_DELETE: int = 261
KEY_HOME: int = 268
KEY_END: int = 269
# Modifier keys
KEY_LEFT_SHIFT: int = 340
KEY_LEFT_CONTROL: int = 341
KEY_LEFT_ALT: int = 342
KEY_LEFT_SUPER: int = 343
KEY_RIGHT_SHIFT: int = 344
KEY_RIGHT_CONTROL: int = 345
KEY_RIGHT_ALT: int = 346
KEY_RIGHT_SUPER: int = 347Handle mouse button and cursor input.
def get_mouse_button(window, button: int) -> int:
"""
Get the last reported state of a mouse button.
Parameters:
window: Window to query
button: Mouse button constant
Returns:
int: PRESS or RELEASE
"""
def get_cursor_pos(window) -> tuple[float, float]:
"""
Get the cursor position relative to the window's client area.
Parameters:
window: Window to query
Returns:
tuple: (x, y) cursor position
"""
def set_cursor_pos(window, xpos: float, ypos: float) -> None:
"""
Set the cursor position relative to the window's client area.
Parameters:
window: Window to modify
xpos: New x-coordinate
ypos: New y-coordinate
"""
def raw_mouse_motion_supported() -> bool:
"""
Check whether raw mouse motion is supported.
Returns:
bool: True if raw mouse motion is supported
"""# Mouse buttons
MOUSE_BUTTON_1: int = 0
MOUSE_BUTTON_2: int = 1
MOUSE_BUTTON_3: int = 2
MOUSE_BUTTON_4: int = 3
MOUSE_BUTTON_5: int = 4
MOUSE_BUTTON_6: int = 5
MOUSE_BUTTON_7: int = 6
MOUSE_BUTTON_8: int = 7
MOUSE_BUTTON_LAST: int = MOUSE_BUTTON_8
# Mouse button aliases
MOUSE_BUTTON_LEFT: int = MOUSE_BUTTON_1
MOUSE_BUTTON_RIGHT: int = MOUSE_BUTTON_2
MOUSE_BUTTON_MIDDLE: int = MOUSE_BUTTON_3Register callbacks for mouse events.
def set_mouse_button_callback(window, cbfun) -> callable:
"""
Set the mouse button callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, button: int, action: int, mods: int)
"""
def set_cursor_pos_callback(window, cbfun) -> callable:
"""
Set the cursor position callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, xpos: float, ypos: float)
"""
def set_cursor_enter_callback(window, cbfun) -> callable:
"""
Set the cursor enter/exit callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, entered: int)
"""
def set_scroll_callback(window, cbfun) -> callable:
"""
Set the scroll callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, xoffset: float, yoffset: float)
"""Create and manage custom cursors.
def create_cursor(image, xhot: int, yhot: int):
"""
Create a custom cursor from an image.
Parameters:
image: Image data or PIL Image object
xhot: X-coordinate of cursor hotspot
yhot: Y-coordinate of cursor hotspot
Returns:
GLFWcursor: Cursor handle
"""
def create_standard_cursor(shape: int):
"""
Create a cursor with a standard shape.
Parameters:
shape: Standard cursor shape constant
Returns:
GLFWcursor: Cursor handle
"""
def destroy_cursor(cursor) -> None:
"""
Destroy a cursor.
Parameters:
cursor: Cursor to destroy
"""
def set_cursor(window, cursor) -> None:
"""
Set the cursor for the window.
Parameters:
window: Window to modify
cursor: Cursor to set, or None for default
"""# Standard cursor shapes
ARROW_CURSOR: int = 0x00036001
IBEAM_CURSOR: int = 0x00036002
CROSSHAIR_CURSOR: int = 0x00036003
HAND_CURSOR: int = 0x00036004
POINTING_HAND_CURSOR: int = 0x00036004
HRESIZE_CURSOR: int = 0x00036005
RESIZE_EW_CURSOR: int = 0x00036005
VRESIZE_CURSOR: int = 0x00036006
RESIZE_NS_CURSOR: int = 0x00036006
RESIZE_NWSE_CURSOR: int = 0x00036007
RESIZE_NESW_CURSOR: int = 0x00036008
RESIZE_ALL_CURSOR: int = 0x00036009
NOT_ALLOWED_CURSOR: int = 0x0003600AQuery and handle joystick/controller input.
def joystick_present(joy: int) -> int:
"""
Check whether the specified joystick is present.
Parameters:
joy: Joystick ID (JOYSTICK_1 through JOYSTICK_16)
Returns:
int: 1 if present, 0 if not present
"""
def get_joystick_axes(joy: int) -> tuple:
"""
Get the values of all axes of the specified joystick.
Parameters:
joy: Joystick ID
Returns:
tuple: (axes_array, count) - axes values and count
"""
def get_joystick_buttons(joy: int) -> tuple:
"""
Get the state of all buttons of the specified joystick.
Parameters:
joy: Joystick ID
Returns:
tuple: (buttons_array, count) - button states and count
"""
def get_joystick_hats(joystick_id: int) -> tuple:
"""
Get the state of all hats of the specified joystick.
Parameters:
joystick_id: Joystick ID
Returns:
tuple: (hats_array, count) - hat states and count
"""
def get_joystick_name(joy: int) -> bytes:
"""
Get the name of the specified joystick.
Parameters:
joy: Joystick ID
Returns:
bytes: Joystick name
"""
def get_joystick_guid(joystick_id: int) -> bytes:
"""
Get the SDL compatible GUID of the specified joystick.
Parameters:
joystick_id: Joystick ID
Returns:
bytes: Joystick GUID
"""
def set_joystick_user_pointer(joystick_id: int, pointer) -> None:
"""Set user data for the joystick."""
def get_joystick_user_pointer(joystick_id: int):
"""Get user data for the joystick."""
def set_joystick_callback(cbfun) -> callable:
"""
Set the joystick configuration callback.
Parameters:
cbfun: Callback function or None
Signature: callback(joy: int, event: int)
"""# Joystick IDs
JOYSTICK_1: int = 0
JOYSTICK_2: int = 1
# ... through JOYSTICK_16: int = 15
JOYSTICK_LAST: int = JOYSTICK_16
# Joystick events
CONNECTED: int = 0x00040001
DISCONNECTED: int = 0x00040002
# Hat states
HAT_CENTERED: int = 0
HAT_UP: int = 1
HAT_RIGHT: int = 2
HAT_DOWN: int = 4
HAT_LEFT: int = 8
HAT_RIGHT_UP: int = HAT_RIGHT | HAT_UP
HAT_RIGHT_DOWN: int = HAT_RIGHT | HAT_DOWN
HAT_LEFT_UP: int = HAT_LEFT | HAT_UP
HAT_LEFT_DOWN: int = HAT_LEFT | HAT_DOWNHigh-level gamepad interface with standardized button mapping.
def joystick_is_gamepad(joystick_id: int) -> bool:
"""
Check whether the specified joystick has a gamepad mapping.
Parameters:
joystick_id: Joystick ID
Returns:
bool: True if joystick has gamepad mapping
"""
def get_gamepad_state(joystick_id: int):
"""
Get the state of the specified joystick remapped as a gamepad.
Parameters:
joystick_id: Joystick ID
Returns:
GLFWgamepadstate: Gamepad state, or None if not available
"""
def get_gamepad_name(joystick_id: int) -> str:
"""
Get the human-readable gamepad name for the specified joystick.
Parameters:
joystick_id: Joystick ID
Returns:
str: Gamepad name, or None if not available
"""
def update_gamepad_mappings(string: str) -> int:
"""
Add the specified SDL_GameControllerDB gamepad mappings.
Parameters:
string: Gamepad mappings string
Returns:
int: 1 if successful, 0 if failed
"""# Gamepad buttons
GAMEPAD_BUTTON_A: int = 0
GAMEPAD_BUTTON_B: int = 1
GAMEPAD_BUTTON_X: int = 2
GAMEPAD_BUTTON_Y: int = 3
GAMEPAD_BUTTON_LEFT_BUMPER: int = 4
GAMEPAD_BUTTON_RIGHT_BUMPER: int = 5
GAMEPAD_BUTTON_BACK: int = 6
GAMEPAD_BUTTON_START: int = 7
GAMEPAD_BUTTON_GUIDE: int = 8
GAMEPAD_BUTTON_LEFT_THUMB: int = 9
GAMEPAD_BUTTON_RIGHT_THUMB: int = 10
GAMEPAD_BUTTON_DPAD_UP: int = 11
GAMEPAD_BUTTON_DPAD_RIGHT: int = 12
GAMEPAD_BUTTON_DPAD_DOWN: int = 13
GAMEPAD_BUTTON_DPAD_LEFT: int = 14
GAMEPAD_BUTTON_LAST: int = GAMEPAD_BUTTON_DPAD_LEFT
# PlayStation-style aliases
GAMEPAD_BUTTON_CROSS: int = GAMEPAD_BUTTON_A
GAMEPAD_BUTTON_CIRCLE: int = GAMEPAD_BUTTON_B
GAMEPAD_BUTTON_SQUARE: int = GAMEPAD_BUTTON_X
GAMEPAD_BUTTON_TRIANGLE: int = GAMEPAD_BUTTON_Y
# Gamepad axes
GAMEPAD_AXIS_LEFT_X: int = 0
GAMEPAD_AXIS_LEFT_Y: int = 1
GAMEPAD_AXIS_RIGHT_X: int = 2
GAMEPAD_AXIS_RIGHT_Y: int = 3
GAMEPAD_AXIS_LEFT_TRIGGER: int = 4
GAMEPAD_AXIS_RIGHT_TRIGGER: int = 5
GAMEPAD_AXIS_LAST: int = GAMEPAD_AXIS_RIGHT_TRIGGERAccess system clipboard for text data.
def set_clipboard_string(window, string: str) -> None:
"""
Set the clipboard to the specified string.
Parameters:
window: Window (deprecated, can be None)
string: String to set in clipboard
"""
def get_clipboard_string(window) -> bytes:
"""
Get the contents of the clipboard as a string.
Parameters:
window: Window (deprecated, can be None)
Returns:
bytes: Clipboard contents
"""Handle file drag and drop operations.
def set_drop_callback(window, cbfun) -> callable:
"""
Set the file drop callback.
Parameters:
cbfun: Callback function or None
Signature: callback(window, paths: list[str])
"""import glfw
glfw.init()
window = glfw.create_window(640, 480, "Input Example", None, None)
glfw.make_context_current(window)
while not glfw.window_should_close(window):
glfw.poll_events()
# Check for escape key
if glfw.get_key(window, glfw.KEY_ESCAPE) == glfw.PRESS:
glfw.set_window_should_close(window, True)
# Check mouse button
if glfw.get_mouse_button(window, glfw.MOUSE_BUTTON_LEFT) == glfw.PRESS:
x, y = glfw.get_cursor_pos(window)
print(f"Mouse clicked at {x}, {y}")
glfw.swap_buffers(window)
glfw.terminate()import glfw
def key_callback(window, key, scancode, action, mods):
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.set_window_should_close(window, True)
elif action == glfw.PRESS:
print(f"Key {key} pressed")
def mouse_button_callback(window, button, action, mods):
if button == glfw.MOUSE_BUTTON_LEFT and action == glfw.PRESS:
x, y = glfw.get_cursor_pos(window)
print(f"Left mouse button pressed at {x}, {y}")
glfw.init()
window = glfw.create_window(640, 480, "Callbacks", None, None)
# Set callbacks
glfw.set_key_callback(window, key_callback)
glfw.set_mouse_button_callback(window, mouse_button_callback)
# Main loop...import glfw
glfw.init()
window = glfw.create_window(640, 480, "Gamepad", None, None)
while not glfw.window_should_close(window):
glfw.poll_events()
# Check for connected gamepads
for joy in range(glfw.JOYSTICK_1, glfw.JOYSTICK_LAST + 1):
if glfw.joystick_present(joy) and glfw.joystick_is_gamepad(joy):
state = glfw.get_gamepad_state(joy)
if state:
# Check A button
if state.buttons[glfw.GAMEPAD_BUTTON_A]:
print("A button pressed")
# Check left stick
left_x = state.axes[glfw.GAMEPAD_AXIS_LEFT_X]
left_y = state.axes[glfw.GAMEPAD_AXIS_LEFT_Y]
if abs(left_x) > 0.1 or abs(left_y) > 0.1:
print(f"Left stick: {left_x}, {left_y}")
glfw.swap_buffers(window)
glfw.terminate()Install with Tessl CLI
npx tessl i tessl/pypi-glfw