or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdaudio-system.mdcore-system.mdcursor-management.mddisplay-graphics.mdevent-handling.mdindex.mdinput-systems.mdmath-operations.mdmidi-support.mdsprites-game-objects.mdtyping-support.md

cursor-management.mddocs/

0

# Cursor Management

1

2

Comprehensive mouse cursor control including system cursors, custom bitmap cursors, and color cursors. Provides both high-level cursor management and low-level cursor compilation utilities.

3

4

## Capabilities

5

6

### Cursor Object

7

8

The Cursor class provides unified interface for all cursor types.

9

10

```python { .api }

11

class Cursor:

12

def __init__(self, *args):

13

"""

14

Create cursor from various sources.

15

16

Parameters:

17

*args: Variable arguments depending on cursor type:

18

- (constant,) for system cursors

19

- (size, hotspot, xormasks, andmasks) for bitmap cursors

20

- (hotspot, surface) for color cursors

21

"""

22

23

type: str # "system", "bitmap", or "color"

24

data: tuple # Cursor-specific data

25

26

def copy(self) -> Cursor:

27

"""

28

Create copy of cursor.

29

30

Returns:

31

Cursor: New cursor object with same data

32

"""

33

```

34

35

### System Cursor Management

36

37

Functions for setting and querying the current system cursor.

38

39

```python { .api }

40

def set_cursor(*args) -> None:

41

"""

42

Set the current mouse cursor.

43

44

Parameters:

45

*args: Cursor data in various formats:

46

- (cursor_object,) - Set from Cursor object

47

- (constant,) - Set system cursor by constant

48

- (size, hotspot, xormasks, andmasks) - Set bitmap cursor

49

- (hotspot, surface) - Set color cursor from surface

50

"""

51

52

def get_cursor() -> Cursor:

53

"""

54

Get the current cursor.

55

56

Returns:

57

Cursor: Current cursor object

58

"""

59

```

60

61

### Bitmap Cursor Compilation

62

63

Utilities for creating bitmap cursors from string representations.

64

65

```python { .api }

66

def compile(

67

strings: tuple[str, ...],

68

black: str = "X",

69

white: str = ".",

70

xor: str = "o"

71

) -> tuple[tuple[int, ...], tuple[int, ...]]:

72

"""

73

Compile cursor from string representation.

74

75

Parameters:

76

strings: Tuple of strings representing cursor bitmap

77

black: Character representing black pixels

78

white: Character representing white pixels

79

xor: Character representing XOR pixels

80

81

Returns:

82

tuple[tuple[int, ...], tuple[int, ...]]: (xormasks, andmasks) bitmap data

83

"""

84

85

def load_xbm(cursor_file, mask_file) -> tuple:

86

"""

87

Load cursor from XBM format files.

88

89

Parameters:

90

cursor_file: Path to cursor XBM file

91

mask_file: Path to mask XBM file

92

93

Returns:

94

tuple: Cursor data suitable for Cursor creation

95

"""

96

```

97

98

### Pre-defined System Cursors

99

100

Built-in cursor constants for common system cursors.

101

102

```python { .api }

103

# System cursor constants

104

SYSTEM_CURSOR_ARROW: int # Standard arrow cursor

105

SYSTEM_CURSOR_IBEAM: int # Text input cursor

106

SYSTEM_CURSOR_WAIT: int # Wait/busy cursor

107

SYSTEM_CURSOR_CROSSHAIR: int # Crosshair cursor

108

SYSTEM_CURSOR_WAITARROW: int # Arrow with wait symbol

109

SYSTEM_CURSOR_SIZENWSE: int # Resize NW-SE cursor

110

SYSTEM_CURSOR_SIZENESW: int # Resize NE-SW cursor

111

SYSTEM_CURSOR_SIZEWE: int # Resize W-E cursor

112

SYSTEM_CURSOR_SIZENS: int # Resize N-S cursor

113

SYSTEM_CURSOR_SIZEALL: int # Move/resize all directions

114

SYSTEM_CURSOR_NO: int # Not allowed cursor

115

SYSTEM_CURSOR_HAND: int # Hand/pointer cursor

116

```

117

118

### Pre-compiled Cursors

119

120

Ready-to-use cursor objects for common cursor types.

121

122

```python { .api }

123

# Pre-compiled cursor objects

124

arrow: Cursor # Standard arrow cursor

125

diamond: Cursor # Diamond-shaped cursor

126

ball: Cursor # Ball/circle cursor

127

broken_x: Cursor # Broken X cursor

128

tri_left: Cursor # Left-pointing triangle

129

tri_right: Cursor # Right-pointing triangle

130

```

131

132

### Cursor String Templates

133

134

String templates for creating custom cursors with compile().

135

136

```python { .api }

137

# String templates for cursor compilation

138

thickarrow_strings: tuple[str, ...] # Thick arrow cursor

139

sizer_x_strings: tuple[str, ...] # Horizontal resize cursor

140

sizer_y_strings: tuple[str, ...] # Vertical resize cursor

141

sizer_xy_strings: tuple[str, ...] # Diagonal resize cursor

142

textmarker_strings: tuple[str, ...] # Text marker cursor

143

```

144

145

## Usage Examples

146

147

### Basic Cursor Management

148

149

```python

150

import pygame

151

import pygame.cursors

152

153

pygame.init()

154

screen = pygame.display.set_mode((800, 600))

155

156

# Set different system cursors

157

print("Changing to different system cursors...")

158

159

# Standard arrow (default)

160

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)

161

pygame.time.wait(1000)

162

163

# Hand cursor for clickable elements

164

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_HAND)

165

pygame.time.wait(1000)

166

167

# Text input cursor

168

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_IBEAM)

169

pygame.time.wait(1000)

170

171

# Wait cursor

172

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_WAIT)

173

pygame.time.wait(1000)

174

175

# Crosshair cursor

176

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_CROSSHAIR)

177

pygame.time.wait(1000)

178

179

# Get current cursor

180

current_cursor = pygame.cursors.get_cursor()

181

print(f"Current cursor type: {current_cursor.type}")

182

183

pygame.quit()

184

```

185

186

### Pre-compiled Cursors

187

188

```python

189

import pygame

190

import pygame.cursors

191

192

pygame.init()

193

screen = pygame.display.set_mode((800, 600))

194

195

# Use pre-compiled cursors

196

cursors_to_try = [

197

("Arrow", pygame.cursors.arrow),

198

("Diamond", pygame.cursors.diamond),

199

("Ball", pygame.cursors.ball),

200

("Broken X", pygame.cursors.broken_x),

201

("Triangle Left", pygame.cursors.tri_left),

202

("Triangle Right", pygame.cursors.tri_right),

203

]

204

205

for name, cursor in cursors_to_try:

206

print(f"Setting cursor: {name}")

207

pygame.cursors.set_cursor(cursor)

208

pygame.time.wait(1500)

209

210

pygame.quit()

211

```

212

213

### Custom Bitmap Cursor

214

215

```python

216

import pygame

217

import pygame.cursors

218

219

pygame.init()

220

screen = pygame.display.set_mode((800, 600))

221

222

# Create custom cursor from string

223

custom_cursor_strings = (

224

" XX ",

225

" X..X ",

226

" X....X ",

227

" X......X ",

228

" X........X ",

229

"X..........X",

230

" X........X ",

231

" X......X ",

232

" X....X ",

233

" X..X ",

234

" XX ",

235

)

236

237

# Compile the cursor

238

cursor_data = pygame.cursors.compile(

239

custom_cursor_strings,

240

black='X', # Character for black pixels

241

white='.', # Character for white pixels

242

xor='o' # Character for XOR pixels (unused here)

243

)

244

245

# Create cursor object

246

size = (12, 11) # Width x Height

247

hotspot = (6, 5) # Center point

248

custom_cursor = pygame.cursors.Cursor(size, hotspot, cursor_data[0], cursor_data[1])

249

250

# Set the custom cursor

251

pygame.cursors.set_cursor(custom_cursor)

252

253

print("Custom cursor set! Move mouse to see it.")

254

pygame.time.wait(3000)

255

256

pygame.quit()

257

```

258

259

### Color Cursor from Surface

260

261

```python

262

import pygame

263

import pygame.cursors

264

265

pygame.init()

266

screen = pygame.display.set_mode((800, 600))

267

268

# Create a colorful cursor surface

269

cursor_size = (32, 32)

270

cursor_surface = pygame.Surface(cursor_size, pygame.SRCALPHA)

271

272

# Draw a colorful cursor

273

center = (cursor_size[0] // 2, cursor_size[1] // 2)

274

275

# Draw concentric circles

276

pygame.draw.circle(cursor_surface, (255, 0, 0, 200), center, 15)

277

pygame.draw.circle(cursor_surface, (0, 255, 0, 200), center, 10)

278

pygame.draw.circle(cursor_surface, (0, 0, 255, 200), center, 5)

279

280

# Add crosshair

281

pygame.draw.line(cursor_surface, (255, 255, 255), (center[0], 0), (center[0], cursor_size[1]), 2)

282

pygame.draw.line(cursor_surface, (255, 255, 255), (0, center[1]), (cursor_size[0], center[1]), 2)

283

284

# Create color cursor

285

hotspot = center # Click point at center

286

color_cursor = pygame.cursors.Cursor(hotspot, cursor_surface)

287

288

# Set the color cursor

289

pygame.cursors.set_cursor(color_cursor)

290

291

print("Color cursor set! Move mouse to see the colorful cursor.")

292

pygame.time.wait(5000)

293

294

pygame.quit()

295

```

296

297

### Context-Sensitive Cursors

298

299

```python

300

import pygame

301

import pygame.cursors

302

303

pygame.init()

304

screen = pygame.display.set_mode((800, 600))

305

pygame.display.set_caption("Context-Sensitive Cursors")

306

307

# Define areas with different cursors

308

button_rect = pygame.Rect(100, 100, 200, 100)

309

text_rect = pygame.Rect(400, 200, 300, 50)

310

resize_rect = pygame.Rect(650, 450, 100, 100)

311

312

# Cursor for different contexts

313

default_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)

314

button_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_HAND)

315

text_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_IBEAM)

316

resize_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_SIZENWSE)

317

318

current_cursor = None

319

clock = pygame.time.Clock()

320

running = True

321

322

while running:

323

for event in pygame.event.get():

324

if event.type == pygame.QUIT:

325

running = False

326

327

# Get mouse position

328

mouse_pos = pygame.mouse.get_pos()

329

330

# Determine appropriate cursor based on mouse position

331

new_cursor = default_cursor

332

333

if button_rect.collidepoint(mouse_pos):

334

new_cursor = button_cursor

335

elif text_rect.collidepoint(mouse_pos):

336

new_cursor = text_cursor

337

elif resize_rect.collidepoint(mouse_pos):

338

new_cursor = resize_cursor

339

340

# Only change cursor if different

341

if new_cursor != current_cursor:

342

pygame.cursors.set_cursor(new_cursor)

343

current_cursor = new_cursor

344

345

# Draw interface elements

346

screen.fill((240, 240, 240))

347

348

# Draw button

349

pygame.draw.rect(screen, (100, 150, 255), button_rect)

350

pygame.draw.rect(screen, (0, 0, 0), button_rect, 2)

351

font = pygame.font.Font(None, 36)

352

text = font.render("Button", True, (255, 255, 255))

353

text_pos = (button_rect.centerx - text.get_width()//2,

354

button_rect.centery - text.get_height()//2)

355

screen.blit(text, text_pos)

356

357

# Draw text area

358

pygame.draw.rect(screen, (255, 255, 255), text_rect)

359

pygame.draw.rect(screen, (0, 0, 0), text_rect, 2)

360

text_label = font.render("Text Input Area", True, (0, 0, 0))

361

screen.blit(text_label, (text_rect.x + 5, text_rect.y + 10))

362

363

# Draw resize area

364

pygame.draw.rect(screen, (255, 200, 100), resize_rect)

365

pygame.draw.rect(screen, (0, 0, 0), resize_rect, 2)

366

resize_text = font.render("Resize", True, (0, 0, 0))

367

resize_pos = (resize_rect.centerx - resize_text.get_width()//2,

368

resize_rect.centery - resize_text.get_height()//2)

369

screen.blit(resize_text, resize_pos)

370

371

# Draw instructions

372

instructions = [

373

"Move mouse over different areas:",

374

"• Button area - Hand cursor",

375

"• Text area - I-beam cursor",

376

"• Resize area - Resize cursor",

377

"• Other areas - Default arrow"

378

]

379

380

small_font = pygame.font.Font(None, 24)

381

y = 20

382

for instruction in instructions:

383

text_surface = small_font.render(instruction, True, (0, 0, 0))

384

screen.blit(text_surface, (20, y))

385

y += 25

386

387

pygame.display.flip()

388

clock.tick(60)

389

390

pygame.quit()

391

```

392

393

### Advanced Cursor Animation

394

395

```python

396

import pygame

397

import pygame.cursors

398

import math

399

400

pygame.init()

401

screen = pygame.display.set_mode((800, 600))

402

pygame.display.set_caption("Animated Cursor")

403

404

class AnimatedCursor:

405

def __init__(self, frames, frame_duration=100):

406

self.frames = frames

407

self.frame_duration = frame_duration

408

self.current_frame = 0

409

self.last_update = pygame.time.get_ticks()

410

411

def update(self):

412

now = pygame.time.get_ticks()

413

if now - self.last_update > self.frame_duration:

414

self.current_frame = (self.current_frame + 1) % len(self.frames)

415

pygame.cursors.set_cursor(self.frames[self.current_frame])

416

self.last_update = now

417

418

# Create spinning cursor frames

419

def create_spinning_cursor_frames(num_frames=8):

420

frames = []

421

cursor_size = (32, 32)

422

center = (cursor_size[0] // 2, cursor_size[1] // 2)

423

424

for i in range(num_frames):

425

surface = pygame.Surface(cursor_size, pygame.SRCALPHA)

426

angle = (360 / num_frames) * i

427

428

# Draw rotating arrow

429

length = 12

430

angle_rad = math.radians(angle)

431

end_x = center[0] + length * math.cos(angle_rad)

432

end_y = center[1] + length * math.sin(angle_rad)

433

434

# Arrow shaft

435

pygame.draw.line(surface, (255, 255, 255), center, (end_x, end_y), 3)

436

437

# Arrow head

438

head_angle1 = angle_rad + math.radians(150)

439

head_angle2 = angle_rad - math.radians(150)

440

head_length = 8

441

442

head1_x = end_x + head_length * math.cos(head_angle1)

443

head1_y = end_y + head_length * math.sin(head_angle1)

444

head2_x = end_x + head_length * math.cos(head_angle2)

445

head2_y = end_y + head_length * math.sin(head_angle2)

446

447

pygame.draw.line(surface, (255, 255, 255), (end_x, end_y), (head1_x, head1_y), 2)

448

pygame.draw.line(surface, (255, 255, 255), (end_x, end_y), (head2_x, head2_y), 2)

449

450

# Create cursor

451

cursor = pygame.cursors.Cursor(center, surface)

452

frames.append(cursor)

453

454

return frames

455

456

# Create animated cursor

457

spinner_frames = create_spinning_cursor_frames(12)

458

animated_cursor = AnimatedCursor(spinner_frames, frame_duration=100)

459

460

clock = pygame.time.Clock()

461

running = True

462

463

while running:

464

for event in pygame.event.get():

465

if event.type == pygame.QUIT:

466

running = False

467

elif event.type == pygame.KEYDOWN:

468

if event.key == pygame.K_SPACE:

469

# Toggle between animated and normal cursor

470

if hasattr(animated_cursor, 'active'):

471

animated_cursor.active = not animated_cursor.active

472

if not animated_cursor.active:

473

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)

474

else:

475

animated_cursor.active = True

476

477

# Update animated cursor

478

if hasattr(animated_cursor, 'active') and animated_cursor.active:

479

animated_cursor.update()

480

481

# Draw instructions

482

screen.fill((50, 50, 50))

483

font = pygame.font.Font(None, 48)

484

text1 = font.render("Animated Cursor Demo", True, (255, 255, 255))

485

text2 = font.render("Press SPACE to toggle animation", True, (200, 200, 200))

486

487

screen.blit(text1, (screen.get_width()//2 - text1.get_width()//2, 200))

488

screen.blit(text2, (screen.get_width()//2 - text2.get_width()//2, 300))

489

490

pygame.display.flip()

491

clock.tick(60)

492

493

pygame.quit()

494

```

495

496

### XBM Cursor Loading

497

498

```python

499

import pygame

500

import pygame.cursors

501

import tempfile

502

import os

503

504

pygame.init()

505

screen = pygame.display.set_mode((800, 600))

506

507

# Create sample XBM files for demonstration

508

cursor_xbm_data = """#define cursor_width 16

509

#define cursor_height 16

510

static unsigned char cursor_bits[] = {

511

0x00, 0x00, 0x40, 0x02, 0x60, 0x06, 0x70, 0x0e, 0x78, 0x1e, 0x7c, 0x3e,

512

0x7e, 0x7e, 0x7f, 0xfe, 0x7f, 0xfe, 0x7e, 0x7e, 0x6c, 0x36, 0x46, 0x62,

513

0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00 };"""

514

515

mask_xbm_data = """#define mask_width 16

516

#define mask_height 16

517

static unsigned char mask_bits[] = {

518

0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f,

519

0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xef, 0xf7,

520

0xcf, 0xf3, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0xc0 };"""

521

522

# Write temporary XBM files

523

with tempfile.NamedTemporaryFile(mode='w', suffix='.xbm', delete=False) as cursor_file:

524

cursor_file.write(cursor_xbm_data)

525

cursor_filename = cursor_file.name

526

527

with tempfile.NamedTemporaryFile(mode='w', suffix='.xbm', delete=False) as mask_file:

528

mask_file.write(mask_xbm_data)

529

mask_filename = mask_file.name

530

531

try:

532

# Load cursor from XBM files

533

xbm_cursor_data = pygame.cursors.load_xbm(cursor_filename, mask_filename)

534

535

# Create cursor object

536

size = (16, 16)

537

hotspot = (0, 0)

538

xbm_cursor = pygame.cursors.Cursor(size, hotspot, xbm_cursor_data[0], xbm_cursor_data[1])

539

540

# Set the XBM cursor

541

pygame.cursors.set_cursor(xbm_cursor)

542

543

print("XBM cursor loaded and set!")

544

pygame.time.wait(3000)

545

546

except Exception as e:

547

print(f"Error loading XBM cursor: {e}")

548

549

finally:

550

# Clean up temporary files

551

try:

552

os.unlink(cursor_filename)

553

os.unlink(mask_filename)

554

except:

555

pass

556

557

# Restore default cursor

558

pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)

559

560

pygame.quit()

561

```

562

563

## Constants

564

565

System cursor constants and cursor compilation characters:

566

567

```python { .api }

568

# System cursor types

569

SYSTEM_CURSOR_ARROW: int = 0 # Standard arrow

570

SYSTEM_CURSOR_IBEAM: int = 1 # Text selection

571

SYSTEM_CURSOR_WAIT: int = 2 # Wait/loading

572

SYSTEM_CURSOR_CROSSHAIR: int = 3 # Crosshair/precision

573

SYSTEM_CURSOR_WAITARROW: int = 4 # Arrow with hourglass

574

SYSTEM_CURSOR_SIZENWSE: int = 5 # Resize northwest-southeast

575

SYSTEM_CURSOR_SIZENESW: int = 6 # Resize northeast-southwest

576

SYSTEM_CURSOR_SIZEWE: int = 7 # Resize west-east

577

SYSTEM_CURSOR_SIZENS: int = 8 # Resize north-south

578

SYSTEM_CURSOR_SIZEALL: int = 9 # Move/resize all directions

579

SYSTEM_CURSOR_NO: int = 10 # Not allowed/prohibited

580

SYSTEM_CURSOR_HAND: int = 11 # Hand/pointing

581

582

# Default compilation characters

583

DEFAULT_BLACK: str = "X" # Black pixel character

584

DEFAULT_WHITE: str = "." # White pixel character

585

DEFAULT_XOR: str = "o" # XOR pixel character

586

```