or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-ewmh

Python implementation of Extended Window Manager Hints for querying and controlling EWMH-compliant window managers

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/ewmh@0.1.x

To install, run

npx @tessl/cli install tessl/pypi-ewmh@0.1.0

0

# EWMH

1

2

A Python implementation of Extended Window Manager Hints (EWMH) specification for querying and controlling EWMH-compliant window managers on Linux/Unix systems. Built on top of python-xlib, it enables programmatic interaction with modern window managers to retrieve window information, manipulate window properties, manage desktops and workspaces, and perform window management operations.

3

4

## Package Information

5

6

- **Package Name**: ewmh

7

- **Package Type**: pypi

8

- **Language**: Python

9

- **Installation**: `pip install ewmh`

10

- **Dependencies**: python-xlib

11

12

## Core Imports

13

14

```python

15

from ewmh import EWMH

16

```

17

18

Alternative import pattern:

19

```python

20

import ewmh

21

ewmh_instance = ewmh.EWMH()

22

```

23

24

## Basic Usage

25

26

```python

27

from ewmh import EWMH

28

29

# Initialize EWMH connection (uses default display and root window)

30

ewmh = EWMH()

31

32

# Get current active window

33

active_window = ewmh.getActiveWindow()

34

if active_window:

35

print(f"Active window: {ewmh.getWmName(active_window)}")

36

37

# Get list of all managed windows

38

windows = ewmh.getClientList()

39

print(f"Total windows: {len(windows)}")

40

41

# Get desktop information

42

num_desktops = ewmh.getNumberOfDesktops()

43

current_desktop = ewmh.getCurrentDesktop()

44

print(f"Desktop {current_desktop + 1} of {num_desktops}")

45

46

# Set a window as active

47

if windows:

48

ewmh.setActiveWindow(windows[0])

49

ewmh.display.flush() # Important: flush to send the request

50

51

# Clean up

52

ewmh.display.close()

53

```

54

55

## Architecture

56

57

EWMH provides a comprehensive interface to the Extended Window Manager Hints specification through a single EWMH class. The architecture is organized around five main capability areas:

58

59

- **Desktop/Workspace Management**: Query and control virtual desktops, geometry, viewports, and workspace properties

60

- **Window Discovery**: Enumerate managed windows, get stacking order, and find active windows

61

- **Window Properties**: Access window metadata like names, types, states, process IDs, and allowed actions

62

- **Window Control**: Perform window operations including activation, movement, resizing, state changes, and closure

63

- **Generic Access**: Use string-based property names for dynamic access to any EWMH property

64

65

The implementation builds on python-xlib for low-level X11 communication and provides both specific methods (e.g., `getActiveWindow()`) and generic property access (e.g., `getProperty('_NET_ACTIVE_WINDOW')`) for maximum flexibility. All operations require explicit display flushing to ensure commands are sent to the window manager.

66

67

## Capabilities

68

69

### EWMH Class

70

71

Main class providing access to all EWMH window manager functionality through getter and setter methods.

72

73

```python { .api }

74

class EWMH:

75

"""

76

Implementation of Extended Window Manager Hints specification.

77

78

Args:

79

_display: X11 display connection (optional, defaults to Xlib.display.Display())

80

root: Root window object (optional, defaults to display.screen().root)

81

"""

82

def __init__(self, _display=None, root=None): ...

83

```

84

85

### Desktop and Workspace Information

86

87

Methods for querying and controlling desktop/workspace properties.

88

89

```python { .api }

90

def getClientList(self):

91

"""

92

Get list of windows maintained by the window manager.

93

94

Returns:

95

list: List of Window objects

96

"""

97

98

def getClientListStacking(self):

99

"""

100

Get list of windows in bottom-to-top stacking order.

101

102

Returns:

103

list: List of Window objects in stacking order

104

"""

105

106

def getNumberOfDesktops(self):

107

"""

108

Get number of virtual desktops.

109

110

Returns:

111

int: Number of desktops

112

"""

113

114

def getDesktopGeometry(self):

115

"""

116

Get desktop geometry as width and height.

117

118

Returns:

119

list: [width, height] in pixels

120

"""

121

122

def getDesktopViewPort(self):

123

"""

124

Get viewport positions for each desktop.

125

126

Returns:

127

list: List of [x, y] coordinates for each desktop viewport

128

"""

129

130

def getCurrentDesktop(self):

131

"""

132

Get current desktop number (0-indexed).

133

134

Returns:

135

int: Current desktop index

136

"""

137

138

def getActiveWindow(self):

139

"""

140

Get currently active window.

141

142

Returns:

143

Window or None: Active window object or None if no active window

144

"""

145

146

def getWorkArea(self):

147

"""

148

Get work area geometry for each desktop.

149

150

Returns:

151

list: List of [x, y, width, height] for each desktop work area

152

"""

153

154

def getShowingDesktop(self):

155

"""

156

Get desktop showing mode status.

157

158

Returns:

159

int: 1 if showing desktop mode active, 0 otherwise

160

"""

161

```

162

163

### Desktop and Workspace Control

164

165

Methods for controlling desktop/workspace properties and state.

166

167

```python { .api }

168

def setNumberOfDesktops(self, nb):

169

"""

170

Set number of virtual desktops.

171

172

Args:

173

nb (int): Desired number of desktops

174

"""

175

176

def setDesktopGeometry(self, w, h):

177

"""

178

Set desktop geometry.

179

180

Args:

181

w (int): Desktop width in pixels

182

h (int): Desktop height in pixels

183

"""

184

185

def setDesktopViewport(self, w, h):

186

"""

187

Set desktop viewport size.

188

189

Args:

190

w (int): Viewport width in pixels

191

h (int): Viewport height in pixels

192

"""

193

194

def setCurrentDesktop(self, i):

195

"""

196

Switch to specified desktop.

197

198

Args:

199

i (int): Desktop index (0-indexed)

200

"""

201

202

def setActiveWindow(self, win):

203

"""

204

Set specified window as active.

205

206

Args:

207

win (Window): Window object to activate

208

"""

209

210

def setShowingDesktop(self, show):

211

"""

212

Enable or disable desktop showing mode.

213

214

Args:

215

show (int): 1 to show desktop, 0 to hide

216

"""

217

```

218

219

### Window Information

220

221

Methods for querying individual window properties.

222

223

```python { .api }

224

def getWmName(self, win):

225

"""

226

Get window name/title.

227

228

Args:

229

win (Window): Window object

230

231

Returns:

232

str: Window name

233

"""

234

235

def getWmVisibleName(self, win):

236

"""

237

Get window visible name (may differ from WM_NAME).

238

239

Args:

240

win (Window): Window object

241

242

Returns:

243

str: Window visible name

244

"""

245

246

def getWmDesktop(self, win):

247

"""

248

Get desktop number that window belongs to.

249

250

Args:

251

win (Window): Window object

252

253

Returns:

254

int: Desktop index (0-indexed)

255

"""

256

257

def getWmWindowType(self, win, str=False):

258

"""

259

Get window type(s).

260

261

Args:

262

win (Window): Window object

263

str (bool): If True, return string names instead of atom IDs

264

265

Returns:

266

list: List of window type atoms (int) or names (str)

267

"""

268

269

def getWmState(self, win, str=False):

270

"""

271

Get window state(s).

272

273

Args:

274

win (Window): Window object

275

str (bool): If True, return string names instead of atom IDs

276

277

Returns:

278

list: List of window state atoms (int) or names (str)

279

"""

280

281

def getWmAllowedActions(self, win, str=False):

282

"""

283

Get allowed actions for window.

284

285

Args:

286

win (Window): Window object

287

str (bool): If True, return string names instead of atom IDs

288

289

Returns:

290

list: List of allowed action atoms (int) or names (str)

291

"""

292

293

def getWmPid(self, win):

294

"""

295

Get process ID of window's application.

296

297

Args:

298

win (Window): Window object

299

300

Returns:

301

int: Process ID

302

"""

303

```

304

305

### Window Control

306

307

Methods for controlling individual window properties and actions.

308

309

```python { .api }

310

def setCloseWindow(self, win):

311

"""

312

Request window closure.

313

314

Args:

315

win (Window): Window object to close

316

"""

317

318

def setWmName(self, win, name):

319

"""

320

Set window name/title.

321

322

Args:

323

win (Window): Window object

324

name (str): New window name

325

"""

326

327

def setWmVisibleName(self, win, name):

328

"""

329

Set window visible name.

330

331

Args:

332

win (Window): Window object

333

name (str): New visible name

334

"""

335

336

def setWmDesktop(self, win, i):

337

"""

338

Move window to specified desktop.

339

340

Args:

341

win (Window): Window object

342

i (int): Target desktop index (0-indexed)

343

"""

344

345

def setMoveResizeWindow(self, win, gravity=0, x=None, y=None, w=None, h=None):

346

"""

347

Move and/or resize window.

348

349

Args:

350

win (Window): Window object

351

gravity (int): Gravity hint (Xlib.X.*Gravity constant or 0)

352

x (int, optional): New X coordinate

353

y (int, optional): New Y coordinate

354

w (int, optional): New width

355

h (int, optional): New height

356

"""

357

358

def setWmState(self, win, action, state, state2=0):

359

"""

360

Set or unset window state(s).

361

362

Args:

363

win (Window): Window object

364

action (int): 0=remove, 1=add, 2=toggle

365

state (int or str): Window state atom ID or name

366

state2 (int or str, optional): Second state atom ID or name

367

"""

368

```

369

370

### Generic Property Access

371

372

Methods for accessing EWMH properties by name using generic interfaces.

373

374

```python { .api }

375

def getReadableProperties(self):

376

"""

377

Get list of all readable EWMH property names.

378

379

Returns:

380

list: Property names that can be used with getProperty()

381

"""

382

383

def getProperty(self, prop, *args, **kwargs):

384

"""

385

Get EWMH property value by name.

386

387

Args:

388

prop (str): Property name (e.g., '_NET_ACTIVE_WINDOW')

389

*args: Arguments passed to specific getter method

390

**kwargs: Keyword arguments passed to specific getter method

391

392

Returns:

393

Property value (type depends on property)

394

395

Raises:

396

KeyError: If property name is not recognized

397

"""

398

399

def getWritableProperties(self):

400

"""

401

Get list of all writable EWMH property names.

402

403

Returns:

404

list: Property names that can be used with setProperty()

405

"""

406

407

def setProperty(self, prop, *args, **kwargs):

408

"""

409

Set EWMH property value by name.

410

411

Args:

412

prop (str): Property name (e.g., '_NET_ACTIVE_WINDOW')

413

*args: Arguments passed to specific setter method

414

**kwargs: Keyword arguments passed to specific setter method

415

416

Raises:

417

KeyError: If property name is not recognized

418

"""

419

```

420

421

## Constants

422

423

### Window Types

424

425

```python { .api }

426

NET_WM_WINDOW_TYPES = (

427

'_NET_WM_WINDOW_TYPE_DESKTOP',

428

'_NET_WM_WINDOW_TYPE_DOCK',

429

'_NET_WM_WINDOW_TYPE_TOOLBAR',

430

'_NET_WM_WINDOW_TYPE_MENU',

431

'_NET_WM_WINDOW_TYPE_UTILITY',

432

'_NET_WM_WINDOW_TYPE_SPLASH',

433

'_NET_WM_WINDOW_TYPE_DIALOG',

434

'_NET_WM_WINDOW_TYPE_DROPDOWN_MENU',

435

'_NET_WM_WINDOW_TYPE_POPUP_MENU',

436

'_NET_WM_WINDOW_TYPE_NOTIFICATION',

437

'_NET_WM_WINDOW_TYPE_COMBO',

438

'_NET_WM_WINDOW_TYPE_DND',

439

'_NET_WM_WINDOW_TYPE_NORMAL'

440

)

441

```

442

443

### Window Actions

444

445

```python { .api }

446

NET_WM_ACTIONS = (

447

'_NET_WM_ACTION_MOVE',

448

'_NET_WM_ACTION_RESIZE',

449

'_NET_WM_ACTION_MINIMIZE',

450

'_NET_WM_ACTION_SHADE',

451

'_NET_WM_ACTION_STICK',

452

'_NET_WM_ACTION_MAXIMIZE_HORZ',

453

'_NET_WM_ACTION_MAXIMIZE_VERT',

454

'_NET_WM_ACTION_FULLSCREEN',

455

'_NET_WM_ACTION_CHANGE_DESKTOP',

456

'_NET_WM_ACTION_CLOSE',

457

'_NET_WM_ACTION_ABOVE',

458

'_NET_WM_ACTION_BELOW'

459

)

460

```

461

462

### Window States

463

464

```python { .api }

465

NET_WM_STATES = (

466

'_NET_WM_STATE_MODAL',

467

'_NET_WM_STATE_STICKY',

468

'_NET_WM_STATE_MAXIMIZED_VERT',

469

'_NET_WM_STATE_MAXIMIZED_HORZ',

470

'_NET_WM_STATE_SHADED',

471

'_NET_WM_STATE_SKIP_TASKBAR',

472

'_NET_WM_STATE_SKIP_PAGER',

473

'_NET_WM_STATE_HIDDEN',

474

'_NET_WM_STATE_FULLSCREEN',

475

'_NET_WM_STATE_ABOVE',

476

'_NET_WM_STATE_BELOW',

477

'_NET_WM_STATE_DEMANDS_ATTENTION'

478

)

479

```

480

481

## Types

482

483

```python { .api }

484

# Xlib types used by EWMH methods

485

from Xlib.display import Display

486

from Xlib import Window

487

488

Window = Window # X11 window object from python-xlib

489

Display = Display # X11 display connection object from python-xlib

490

```

491

492

## Usage Notes

493

494

### Flushing Changes

495

496

After calling setter methods, you must flush the display connection to ensure changes are sent to the window manager:

497

498

```python

499

ewmh = EWMH()

500

ewmh.setActiveWindow(some_window)

501

ewmh.display.flush() # Required to send the request

502

```

503

504

### Error Handling

505

506

Methods may raise exceptions from the underlying Xlib operations. Common patterns:

507

508

- Window objects may become invalid if windows are closed

509

- Property access may return None for non-existent properties

510

- Generic property methods raise KeyError for unknown property names

511

512

### Display Management

513

514

Remember to close the display connection when done:

515

516

```python

517

ewmh = EWMH()

518

# ... use ewmh methods ...

519

ewmh.display.close()

520

```

521

522

Or use context management patterns for automatic cleanup.