summaryrefslogtreecommitdiffstats
path: root/developers/internals.txt
blob: dde2ba7588fbaa45de5099d1ecb7029c1c5b950d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
Matchbox Internals Documentation - v0.1 - mallum@o-hand.com 
===========================================================

Introduction
====

This document describes and discusses the internal source structure of
the Matchbox Window Manager, a unique X11 window manager with a
restrictive PDA style of window management.

Matchbox aims to be small, fast, light and flexible with both compile
and run time features so its UI tailored to fit different embedded
type platforms.

Matchbox has been developed over the past 3 years and much has been
learnt from its development.

Here I present a fairly comprehensive overiew of the source codes inner
working in the hope of guideing any potential contributers.


Coding style
====

Matchbox is written in C with the source approximating to GNU style
coding standards. 

All functions prefixed with the source file name they live in, for
example wm_new() lives in wm.c. Each .c file has an associated header
file listing any shared functionality.

'Global' structures, enums and defines are in structs.h. 


Overview
====

The window manager starting point is in main.c . Initially, a new Wm
'object', used throughout to store various environment and global state
data, is created via wm_new(). 

This wm_new() function initially loads any user configuration data (
via wm_load_config() ) from command line parameters and/or
XResources. Various Wm X11 environment parameters are then initialized
( such as display size, window manager event setup ) before
initializing the various 'subsystems' - EWMH, key shortcuts, various
compile time features etc. Finally a new Wm object is returned which
is then used extensably throughout the programs life cycle.

Any pre-existing windows are then processed ( wm_init_existing() ) and
the program then enters its main loop ( wm_event_loop() ).

Like all window managers, Matchbox is event based. Events come mainly
in the form of redirected ones from clients attempting actions that
are to be managed by the window manager. For example an application
attempting to resize will cause a 'configure request' event to get
sent to the window manager, which can then decide how this is honored
or handled.

When a new client window appears, Matchbox receives a map notify event
with the new window ID. Assuming this ID is unknown to matchbox, a new
'Client' object will be created by wm_make_new_client(). This function
will examine various window properties and based on these decide the
'type' of Client object to be initialized. Types include Application,
Dialog and panel windows, with each needing to be managed slightly
differently.

To achieve this a psudeo object orientated C style is used where each
client type has its own class which inherits from a base client
class. Pointers to functions within the Client struct help provide this
functionality.

All created client objects are stored in a circular doublely linked
list, there are various pointers in the top level Wm object that
reference clients in this list.

Once a client is created various core methods are called in sequence
to initialize and finally realize the then docorated framed client;

 - Properties relevant to the window manager are communicated ( set ) on 
   the client. See ewmh_set_allowed_actions() .

 - The clients configure() method is called to calculate suitable
   client geometry.

 - The client window is then re-parented. It becomes a child window of
   a matchbox frame window. It is the frame window that decorations are
   painted on to.

 - The client window and frame are resized and positioned to fit the
   matchbox management style ( from the previously created geometry ).

 - The client show() method is called which will ultimately realize
   the client. Its very likely an initial call of this method with
   render the frame decorations. Rendering will call into theme engine
   code.

 - Finally global root window properties are updated.  

During the lifetime of a client it will generate other events ( such
as resizing ) which will ultimately get mapped into the client objects
methods and managed.

The other source of events is user interaction. This could be from a key
shortcut press or window decoration button press.

Key presses are handled by wm_handle_keypress(), which looks to see if
an action has been defined for the received key press ( defined in
keys.c ). If this is true the action is carried out by calling
relevant 'global' functions in wm.c and client_common.c .

Button presses are more complicated, wm_handle_button_event() will
detect where the press happened and if required call a resulting
client objects button_press() method.

client_common.c contains code to deal with button management. Window
decoration buttons are simple objects created by
client_button_new(). Each client object has a list referencing its
button objects. client_button_do_ops() helps a client manage it
buttons and provide visual states. 

A final source of events is X messages, for example a request to show
the desktop from an external application will send a X message to the
root window. These are handled by wm_handle_client_message() which
handles matchbox specific messages before calling
ewmh_handle_root_message() which handles standard EWMH ones.

Wm.c also has various functions for 'global' operations on clients
such as resizing/repositioning all clients. Numerous points throughout
the codebase will use this.

Note a diagram reprenting visually what has been discussed in this
overview is available via;

http://matchbox.handhelds.org/documentation/developers/internals/internals.png

File Structure
====

structs.h

All global structures ( aka objects ), defines, enums are defined here. 


wm.c

The window manager 'core'. Contains the event loop and event handlers
and various functions for dealing with global state, such as
re-stacking and resizing all clients.


base_client.c     

base client 'class', all other clients source files ( or types ) are
derived from this optionally overriding various methods.

    
dockbar_client.c  

Derived 'class' for handling panel window types. 


main_client.c     

Derived 'class' for handling application windows     


select_client.c   

Handles the application drop down selection menu


toolbar_client.c  

Derived 'class' for handling toolbar windows ( eg xkbd, input windows ).


desktop_client.c  

Derived 'class' for handling desktop windows.


dialog_client.c   

Derived 'class' for handling dialog windows


client_common.c   

Various client utility and misc funcs common to all client types. This
includes various basic window communication handling, decoration
caching and button management.
 

ewmh.c   

Provides functions for freedesktop.org extended window manager hint protocols.


composite-engine.c 

composite engine , can be compiled out. See below for a further
explanation of its workings.


keys.c             

Provides key shortcut handling ( can be compiled out )


xml.c              

Simple xml parser used by mbtheme.c ( can be compiled out for
stand-alone or expat used instead )


list.c             

Simple list api, used by mbtheme for storing and referencing the
various theme resources.


misc.c             

misc stuff - include strsep implementation for building on systems
that lack it ( eg solaris ), error trappping / reporting funcs, signal
handling.


mbtheme.c            

Provides the complex libmatchbox pixbuf based theme engine.  See below
for a further explanation.


mbtheme-standalone.c 

Provides a alternative smaller and simpler X primitives based 
theme engine. This is used by stand-alone builds.

     
main.c               

Program main entry, init and startup. 


'Objects'
====

structs.h 

Client Object methods

Client* 
XX_client_new (Wm *w, Window win);

Creates a client object. Will set up structure function pointers. 

void 
XX_client_configure (Client *c);

Calculates client size and position variables. 

void 
XX_client_reparent (Client *c);

Is responsable for re-parenting the client window to the decoration
frame window.


void 
XX_client_redraw (Client *c, Bool use_cache);

Renders the window decorations


void 
XX_client_button_press (Client *c, XButtonEvent *e);

Handles any reported button events. 


void 
XX_client_move_resize (Client *c);

Safely moves and resizes a client ( to positions set by
client_configure ) or other.


void 
XX_client_get_coverage (Client *c, int *x, int *y, int *w, int *h);

returns the display area covered by the client and its decoration frame.


void 
XX_client_hide (Client *c);

Hides ( unmaps ) a client. 


void 
XX_client_show (Client *c);

Shows ( maps ) a client.


void 
XX_client_destroy (Client *c);

Removes a client from the circular list cleanly, freeing up any resources.


Themeing
====

'Themeing' is the name used to describe the painting of window frame
decorations. Matchbox provides two themeing implementations or
'engines'; a basic small implementation which uses X drawing
primitives and no configuration files ( mbtheme-standalone.c ) and an
advanced implementation which uses libMatchbox pixbufs for painting
and advanced xml based configuration files. Both engines export a very
similar api which can be used by the core of the window manager to
render defined window decorations. I shall explain the operation of the
advanced engine, but the actual structure also applys to the basic (
standalone ) implementation.

The theme engine is initially created with mbtheme_init(), this will
create and initialize an engine specific theme structure. A suitable
theme.xml file will then be located and parsed. The parsing ( see
parse_*_tag ) populates more of the mbtheme structure with lists of
theme resources ( such as fonts, or loaded image data ) and layout
data for each window type decoration.

A window that needs its decorations painting will call
theme_frame_paint(), specifying the frame type to be painted and its
dimensions relative to the decoration window frame. The frame type is
basically the window type extended with an actual edge ( eg
FRAME_MAIN_NORTH for the title area, FRAME_MAIN_EAST for the right
edge ). The function the builds up the required decoration from the
lists of layout and resource data before rendering to the clients
backing pixmap. The function will also create any masks needed for
window shaping.

Separate function is provided for the painting of buttons (
theme_frame_button_paint() ) and the window select menu (
theme_frame_menu_paint() ). Both these and theme_frame_paint() share
various utility calls for painting ( _theme_paint_core(),
_theme_paint_gradient() etc )

The theme engine also provides various calls for client to code to get
specified decoration dimensions ( theme_frame_menu_get_dimentions(),
theme_frame_defined_width_get(), theme_frame_defined_height_get() )

When the theme is changed, mbtheme_switch() will be called. This
function will free all current defined theme resources and in effect
re theme_init() itself with the new theme before repainting window
decorations.


Compositing
====

Matchbox window manager optionally provides compile time support for
the new X Composite extension ( with associated Damage and Fixes
extensions ). With this active matchbox manages not just window
positions etc but also how the window contents are rendered to the
display - this allows for effects like shadowing and translucency.

The compositing api is at the time of writing considered quite
experimental and therefor unstable. Because of this the composite code
is kept quite un-intrusively self contained in composite-engine.c.
The composite functions to a degree map onto client object methods. 

The composite engine initiates itself via comp_engine_init(). This
function checks for available extensions, sets up the server for
composite style rendering ( via XCompositeRedirectSubwindows() ) and
initializes composite related Wm resources.

Back buffers of all window type contents ( this includes override
redirect windows, of which matchbox now has to track, see
wm_handle_map_notify() ) are now stored in client structures via 32bit
render pictures for visible clients ( see comp_engine_client_show(),
comp_engine_client_hide(), comp_engine_client_init() ). Accumulated
Damage events provide information on what areas of the display needs to
be updated. This information is used with the client back buffers and
Xfixes regions to efficiently update the display ( see
comp_engine_render() ). It also adds effects such as shadowing and
basic translucency.


Optimizations
====

Some optimizations matchbox uses;

 - The theme engine caches a 'base' matchbox pixbuf representation of
   main application window type declarations. This means a new main
   window needs just text painting rather than its entire decoration
   layers being built up. This cache will be cleared if the
   application window size changes or the theme changes.

   The cache is also used to enable button window pixbuf compositing. 

 - Decoration painting is done via XSetWindowBackground with a theme
   engine created pixmap, that is immediately free after the paint.
   Painting to the window background lets the server handle exposes
   and results in simpler smaller code with a 'smoother' appearance.

 - Compositing only back buffers visible windows - ie the top of the 
   stack to save memory. Pictures not visible are freed. 
   Composite Gaussian shadows are pregenerated and cut into tiles on
   start up. The shadows are then built up from the tiles
 
 - Matchbox's small binary size comes from careful coding and the fact
   that due to its style of restrictive window management it avoids much 
   of the code needed by a desktop window manager.


Further reading
====

Matchbox WM source
http://cvs.handhelds.org/cgi-bin/viewcvs.cgi/apps/matchbox/matchbox-window-manager/src/

Matchbox Developer documentation.
http://matchbox.handhelds.org/developer.shtml

Matchbox X Communication specifics ( ie freedesktop.org standards support )
http://matchbox.handhelds.org/documentation/developers/matchbox-key.txt

libMatchbox API documentation. 
http://matchbox.handhelds.org/documentation/developers/api/