or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

3d-models.mdapp-clock.mdaudio-video.mdgraphics-rendering.mdgui.mdimages-textures.mdindex.mdinput-devices.mdmath.mdopengl.mdresource-management.mdsprites-shapes.mdtext-rendering.mdwindowing.md
IMPROVEMENTS.md

windowing.mddocs/

0

# Windowing and Display

1

2

Cross-platform window creation, management, and event handling.

3

4

## Window Class

5

6

```python

7

class pyglet.window.Window:

8

"""Platform-independent application window with OpenGL context"""

9

10

__init__(width=None, height=None, caption=None, resizable=False,

11

style=WINDOW_STYLE_DEFAULT, fullscreen=False, visible=True,

12

vsync=True, display=None, screen=None, config=None, context=None,

13

mode=None, file_drops=False)

14

```

15

16

### Properties

17

18

| Property | Type | Description |

19

|----------|------|-------------|

20

| `caption` | str | Window title |

21

| `width`, `height` | int | Window dimensions (pixels) |

22

| `resizable` | bool | Can be resized by user |

23

| `fullscreen` | bool | Fullscreen mode |

24

| `visible` | bool | Window visibility |

25

| `vsync` | bool | Vertical sync |

26

| `display` | Display | Display device (read-only) |

27

| `context` | Context | OpenGL context (read-only) |

28

| `config` | Config | OpenGL config (read-only) |

29

| `screen` | Screen | Screen for fullscreen (read-only) |

30

| `scale` | float | DPI scale factor (read-only) |

31

| `dpi` | int | DPI value (read-only) |

32

| `size` | tuple | (width, height) (read-only) |

33

| `aspect_ratio` | float | width/height (read-only) |

34

| `projection` | Mat4 | Projection matrix (read-only) |

35

| `view` | Mat4 | View matrix (read-only) |

36

| `viewport` | tuple | (x, y, width, height) (read-only) |

37

| `invalid` | bool | Needs redraw flag |

38

39

### Core Methods

40

41

```python

42

# Window control

43

def close()

44

def switch_to() # Make GL context current

45

def flip() # Swap buffers

46

def clear() # Clear with background

47

def draw(dt) # Full draw cycle (switch_to + on_draw + on_refresh + flip)

48

49

# Configuration

50

def set_caption(caption: str)

51

def set_size(width: int, height: int)

52

def set_location(x: int, y: int)

53

def get_size() -> tuple # (width, height)

54

def get_location() -> tuple # (x, y)

55

def get_framebuffer_size() -> tuple # HiDPI may differ from window size

56

def get_pixel_ratio() -> float # framebuffer/window size ratio

57

def set_minimum_size(width: int, height: int)

58

def set_maximum_size(width: int, height: int)

59

def set_visible(visible: bool = True)

60

def set_fullscreen(fullscreen: bool = True, screen=None, mode=None, width=None, height=None)

61

def minimize()

62

def maximize()

63

def activate() # Bring to foreground

64

65

# Display settings

66

def set_vsync(vsync: bool)

67

def set_icon(*images) # Set window icon

68

69

# Mouse

70

def set_mouse_visible(visible: bool = True)

71

def set_mouse_cursor(cursor=None) # None for default

72

def get_system_mouse_cursor(name: str) -> MouseCursor

73

def set_mouse_platform_visible(platform_visible=None)

74

def set_mouse_passthrough(state: bool) # Click-through window

75

def set_exclusive_mouse(exclusive: bool = True) # Hide and constrain

76

77

# Keyboard

78

def set_exclusive_keyboard(exclusive: bool = True) # Capture shortcuts

79

80

# Clipboard

81

def get_clipboard_text() -> str

82

def set_clipboard_text(text: str)

83

84

# Events

85

def dispatch_events() # For custom event loops (use pyglet.app.run() instead)

86

def push_handlers(*args, **kwargs)

87

def pop_handlers()

88

def remove_handlers(*args, **kwargs)

89

def set_handler(name: str, handler: callable)

90

def set_handlers(*args, **kwargs)

91

def remove_handler(name: str, handler: callable)

92

```

93

94

## Window Events

95

96

Register with `@window.event` decorator or `window.push_handlers()`:

97

98

| Event | Signature | Description |

99

|-------|-----------|-------------|

100

| `on_activate` | `()` | Window gained focus |

101

| `on_close` | `()` | Close requested (return False to prevent) |

102

| `on_context_lost` | `()` | OpenGL context lost |

103

| `on_context_state_lost` | `()` | OpenGL state lost |

104

| `on_deactivate` | `()` | Window lost focus |

105

| `on_draw` | `()` | Window needs redraw |

106

| `on_expose` | `()` | Window uncovered |

107

| `on_hide` | `()` | Window hidden |

108

| `on_show` | `()` | Window shown |

109

| `on_move` | `(x: int, y: int)` | Window moved |

110

| `on_resize` | `(width: int, height: int)` | Window resized |

111

| `on_refresh` | `(dt: float)` | Window refreshed (after on_draw) |

112

| `on_scale` | `(scale: float, dpi: int)` | DPI changed |

113

| `on_key_press` | `(symbol: int, modifiers: int)` | Key pressed |

114

| `on_key_release` | `(symbol: int, modifiers: int)` | Key released |

115

| `on_text` | `(text: str)` | Unicode text entered |

116

| `on_text_motion` | `(motion: int)` | Text cursor motion |

117

| `on_text_motion_select` | `(motion: int)` | Text cursor motion with selection |

118

| `on_mouse_enter` | `(x: int, y: int)` | Mouse entered window |

119

| `on_mouse_leave` | `(x: int, y: int)` | Mouse left window |

120

| `on_mouse_motion` | `(x: int, y: int, dx: int, dy: int)` | Mouse moved |

121

| `on_mouse_drag` | `(x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int)` | Mouse dragged |

122

| `on_mouse_press` | `(x: int, y: int, button: int, modifiers: int)` | Mouse button pressed |

123

| `on_mouse_release` | `(x: int, y: int, button: int, modifiers: int)` | Mouse button released |

124

| `on_mouse_scroll` | `(x: int, y: int, scroll_x: float, scroll_y: float)` | Mouse wheel scrolled |

125

| `on_file_drop` | `(x: int, y: int, paths: list)` | Files dropped (requires file_drops=True) |

126

127

## Display & Screen

128

129

```python

130

# Get display

131

display = pyglet.display.get_display(name=None) # None for default

132

screens = display.get_screens() # list of Screen

133

default_screen = display.get_default_screen()

134

windows = display.get_windows() # list of Window

135

136

# Screen properties

137

screen.x, screen.y # Position

138

screen.width, screen.height # Dimensions

139

screen.xdpi, screen.ydpi # DPI

140

141

# Screen methods

142

modes = screen.get_modes() # Available ScreenMode objects

143

mode = screen.get_mode() # Current mode

144

screen.set_mode(mode)

145

screen.restore_mode()

146

dpi = screen.get_dpi()

147

scale = screen.get_scale() # 1.0 standard, 2.0 for 2x scaling

148

display_id = screen.get_display_id()

149

name = screen.get_monitor_name()

150

151

# ScreenMode properties

152

mode.width, mode.height # Resolution

153

mode.depth # Color depth (bits)

154

mode.rate # Refresh rate (Hz)

155

```

156

157

## Input State Tracking

158

159

```python

160

from pyglet.window import key, mouse

161

162

# Keyboard state

163

keys = key.KeyStateHandler()

164

window.push_handlers(keys)

165

if keys[key.LEFT]: # Check if key is pressed

166

# Move left

167

168

# Mouse state

169

buttons = mouse.MouseStateHandler()

170

window.push_handlers(buttons)

171

if buttons[mouse.LEFT]: # Check if button is pressed

172

# Handle mouse button

173

```

174

175

## FPS Display

176

177

```python

178

class pyglet.window.FPSDisplay:

179

"""Frame rate counter display"""

180

181

__init__(window, color=(127,127,127,127), samples=240)

182

183

update_period: float = 0.25 # Update frequency

184

label: pyglet.text.Label # Display label

185

186

def update() # Update FPS (called automatically)

187

def draw() # Draw counter

188

189

# Usage

190

fps_display = pyglet.window.FPSDisplay(window)

191

192

@window.event

193

def on_draw():

194

window.clear()

195

# ... draw game

196

fps_display.draw()

197

```

198

199

## Window Styles

200

201

```python

202

pyglet.window.WINDOW_STYLE_DEFAULT # Standard with title bar

203

pyglet.window.WINDOW_STYLE_DIALOG # Dialog style

204

pyglet.window.WINDOW_STYLE_TOOL # Tool window

205

pyglet.window.WINDOW_STYLE_BORDERLESS # No borders

206

pyglet.window.WINDOW_STYLE_TRANSPARENT # Transparent, interactable

207

pyglet.window.WINDOW_STYLE_OVERLAY # Transparent, topmost, click-through

208

```

209

210

## Mouse Cursors

211

212

```python

213

# System cursors

214

cursor = window.get_system_mouse_cursor(name)

215

window.set_mouse_cursor(cursor)

216

217

# Cursor constants

218

CURSOR_DEFAULT, CURSOR_CROSSHAIR, CURSOR_HAND, CURSOR_HELP, CURSOR_NO,

219

CURSOR_SIZE, CURSOR_SIZE_UP, CURSOR_SIZE_UP_RIGHT, CURSOR_SIZE_RIGHT,

220

CURSOR_SIZE_DOWN_RIGHT, CURSOR_SIZE_DOWN, CURSOR_SIZE_DOWN_LEFT,

221

CURSOR_SIZE_LEFT, CURSOR_SIZE_UP_LEFT, CURSOR_SIZE_UP_DOWN,

222

CURSOR_SIZE_LEFT_RIGHT, CURSOR_TEXT, CURSOR_WAIT, CURSOR_WAIT_ARROW

223

224

# Custom cursor

225

from pyglet.window import ImageMouseCursor

226

image = pyglet.image.load('cursor.png')

227

cursor = ImageMouseCursor(image, hot_x=0, hot_y=0)

228

window.set_mouse_cursor(cursor)

229

```

230

231

## Keyboard Constants

232

233

```python

234

from pyglet.window import key

235

236

# Letters: key.A through key.Z

237

# Numbers: key._0 through key._9 (top row)

238

# Numpad: key.NUM_0 through key.NUM_9

239

# Function: key.F1 through key.F24

240

241

# Special keys

242

key.ENTER, key.ESCAPE, key.SPACE, key.TAB, key.BACKSPACE, key.DELETE,

243

key.INSERT, key.HOME, key.END, key.PAGEUP, key.PAGEDOWN

244

245

# Arrows

246

key.LEFT, key.RIGHT, key.UP, key.DOWN

247

248

# Modifiers (bitwise flags for checking)

249

key.MOD_SHIFT, key.MOD_CTRL, key.MOD_ALT, key.MOD_CAPSLOCK,

250

key.MOD_NUMLOCK, key.MOD_SCROLLLOCK, key.MOD_COMMAND, key.MOD_OPTION,

251

key.MOD_WINDOWS, key.MOD_FUNCTION

252

key.MOD_ACCEL # Ctrl on Windows/Linux, Command on macOS

253

254

# Text motion constants (for on_text_motion events)

255

key.MOTION_UP, key.MOTION_DOWN, key.MOTION_LEFT, key.MOTION_RIGHT,

256

key.MOTION_NEXT_WORD, key.MOTION_PREVIOUS_WORD,

257

key.MOTION_BEGINNING_OF_LINE, key.MOTION_END_OF_LINE,

258

key.MOTION_NEXT_PAGE, key.MOTION_PREVIOUS_PAGE,

259

key.MOTION_BEGINNING_OF_FILE, key.MOTION_END_OF_FILE,

260

key.MOTION_BACKSPACE, key.MOTION_DELETE,

261

key.MOTION_COPY, key.MOTION_PASTE

262

263

# Utility functions

264

key.symbol_string(symbol) -> str # Get key name

265

key.modifiers_string(modifiers) -> str # Get modifier names

266

key.motion_string(motion) -> str # Get motion name

267

key.user_key(scancode) -> int # Platform-specific key mapping

268

```

269

270

## Mouse Constants

271

272

```python

273

from pyglet.window import mouse

274

275

# Buttons

276

mouse.LEFT, mouse.MIDDLE, mouse.RIGHT, mouse.MOUSE4, mouse.MOUSE5

277

278

# Utility

279

mouse.buttons_string(buttons) -> str # Get button names

280

```

281

282

## Event Logger (Debugging)

283

284

```python

285

from pyglet.window.event import WindowEventLogger

286

287

window = pyglet.window.Window()

288

logger = WindowEventLogger() # Logs to stdout by default

289

window.push_handlers(logger)

290

291

# Or log to file

292

with open('events.log', 'w') as f:

293

logger = WindowEventLogger(f)

294

window.push_handlers(logger)

295

```

296

297

## Common Patterns

298

299

### Basic Window

300

```python

301

window = pyglet.window.Window(800, 600, 'My App')

302

303

@window.event

304

def on_draw():

305

window.clear()

306

307

pyglet.app.run()

308

```

309

310

### Fullscreen Toggle

311

```python

312

@window.event

313

def on_key_press(symbol, modifiers):

314

if symbol == key.F and modifiers & key.MOD_CTRL:

315

window.set_fullscreen(not window.fullscreen)

316

elif symbol == key.ESCAPE:

317

if window.fullscreen:

318

window.set_fullscreen(False)

319

else:

320

pyglet.app.exit()

321

```

322

323

### Multi-Monitor

324

```python

325

display = pyglet.display.get_display()

326

screens = display.get_screens()

327

print(f"Found {len(screens)} screens")

328

for i, screen in enumerate(screens):

329

print(f"Screen {i}: {screen.width}x{screen.height} @ ({screen.x},{screen.y})")

330

331

# Create window on specific screen

332

window = pyglet.window.Window(screen=screens[1])

333

```

334

335

### Resizable Window with Aspect Ratio

336

```python

337

window = pyglet.window.Window(800, 600, resizable=True)

338

339

@window.event

340

def on_resize(width, height):

341

# Maintain 4:3 aspect ratio

342

target_aspect = 4/3

343

current_aspect = width/height

344

if current_aspect > target_aspect:

345

# Too wide

346

new_width = int(height * target_aspect)

347

window.set_size(new_width, height)

348

elif current_aspect < target_aspect:

349

# Too tall

350

new_height = int(width / target_aspect)

351

window.set_size(width, new_height)

352

```

353

354

### Custom Cursor

355

```python

356

# Hide system cursor and draw custom

357

window.set_mouse_visible(False)

358

cursor_sprite = pyglet.sprite.Sprite(cursor_img)

359

360

@window.event

361

def on_mouse_motion(x, y, dx, dy):

362

cursor_sprite.position = (x, y)

363

364

@window.event

365

def on_draw():

366

window.clear()

367

# ... draw game

368

cursor_sprite.draw()

369

```

370

371

### Exclusive Mouse (FPS-style)

372

```python

373

window.set_exclusive_mouse(True)

374

375

@window.event

376

def on_mouse_motion(x, y, dx, dy):

377

# dx/dy are relative motion

378

camera.rotate(dx * sensitivity, dy * sensitivity)

379

380

@window.event

381

def on_key_press(symbol, modifiers):

382

if symbol == key.ESCAPE:

383

window.set_exclusive_mouse(False)

384

```

385

386

## Exceptions

387

388

```python

389

class pyglet.window.WindowException(Exception):

390

"""Base window exception"""

391

392

class pyglet.window.NoSuchDisplayException(WindowException):

393

"""Display not found"""

394

395

class pyglet.window.NoSuchConfigException(WindowException):

396

"""OpenGL config not found"""

397

398

class pyglet.window.NoSuchScreenModeException(WindowException):

399

"""Screen mode cannot be set"""

400

401

class pyglet.window.MouseCursorException(WindowException):

402

"""Mouse cursor error"""

403

```

404

405

## Performance Notes

406

407

- Use `vsync=True` to limit frame rate to monitor refresh (default)

408

- `window.invalid` flag controls when window needs redraw (batch operations)

409

- Minimize window resizing operations (expensive)

410

- Use `on_refresh` event for post-draw effects (dt parameter available)

411

- HiDPI: Use `get_framebuffer_size()` for actual pixel count

412