Moved command-line option handling out of the X11 driver.
[wine] / documentation / internals
1 KERNEL MODULE
2 =============
3
4 ...
5
6 GDI MODULE
7 ==========
8
9 1. X Windows System interface
10 -----------------------------
11
12 The X libraries used to implement X clients (such as Wine) do not work
13 properly if multiple threads access the same display concurrently. It is
14 possible to compile the X libraries to perform their own synchronization
15 (initiated by calling XInitThreads()). However, Wine does not use this
16 approach. Instead Wine performs its own synchronization py putting a
17 wrapper around every X call that is used. This wrapper protects library
18 access with a critical section, and also arranges things so that X
19 libraries compiled without -D_REENTRANT (eg. with global errno variable)
20 will work with Wine.
21
22 To make this scheme work, all calls to X must use the proper wrapper
23 functions (or do their own synchronization that is compatible with the
24 wrappers). The wrapper for a function X...() is calles TSX...() (for
25 "Thread Safe X ..."). So for example, instead of calling XOpenDisplay()
26 in the code, TSXOpenDisplay() must be used. Likewise, X include files
27 that contain function prototypes are wrapped, so that eg. "ts_xutil.h"
28 must be included rather than <X11/Xutil.h>. It is important that this
29 scheme is used everywhere to avoid the introduction of nondeterministic
30 and hard-to-find errors in Wine.
31
32 The code for the thread safe X wrappers is contained in the tsx11/
33 directory and in include/ts*.h. To use a new (ie. not previously used) X
34 function in Wine, a new wrapper must be created. The wrappers are
35 generated (semi-)automatically from the X11R6 includes using the
36 tools/make_X11wrappers perl script. In simple cases it should be enough
37 to add the name of the new function to the list in tsx11/X11_calls; if
38 this does not work the wrapper must be added manually to the
39 make_X11wrappers script. See comments in tsx11/X11_calls and
40 tools/make_X11wrappers for further details.
41
42
43 USER MODULE
44 ===========
45
46 USER implements windowing and messaging subsystems. It also 
47 contains code for common controls and for other miscellaneous 
48 stuff (rectangles, clipboard, WNet, etc). Wine USER code is 
49 located in windows/, controls/, and misc/ directories.
50
51 1. Windowing subsystem
52 ----------------------
53
54    windows/win.c
55    windows/winpos.c
56
57    Windows are arranged into parent/child hierarchy with one
58    common ancestor for all windows (desktop window). Each window
59    structure contains a pointer to the immediate ancestor (parent 
60    window if WS_CHILD style bit is set), a pointer to the sibling 
61    (returned by GetWindow(..., GW_NEXT)), a pointer to the owner 
62    window (set only for popup window if it was created with valid 
63    hwndParent parameter), and a pointer to the first child
64    window (GetWindow(.., GW_CHILD)). All popup and non-child windows
65    are therefore placed in the first level of this hierarchy and their
66    ancestor link (wnd->parent) points to the desktop window.
67
68    Desktop window                       - root window
69     |     \      `-.
70     |      \        `-.
71    popup -> wnd1  ->  wnd2              - top level windows    
72     |       \   `-.      `-.
73     |        \     `-.      `-.
74    child1  child2 -> child3  child4     - child windows
75   
76    Horizontal arrows denote sibling relationship, vertical lines
77    - ancestor/child. To summarize, all windows with the same immediate 
78    ancestor are sibling windows, all windows which do not have desktop 
79    as their immediate ancestor are child windows. Popup windows behave
80    as topmost top-level windows unless they are owned. In this case the
81    only requirement is that they must precede their owners in the top-level 
82    sibling list (they are not topmost). Child windows are confined to the
83    client area of their parent windows (client area is where window gets
84    to do its own drawing, non-client area consists of caption, menu, borders,
85    intrinsic scrollbars, and minimize/maximize/close/help buttons). 
86   
87    Another fairly important concept is "z-order". It is derived from
88    the ancestor/child hierarchy and is used to determine "above/below"
89    relationship. For instance, in the example above, z-order is
90    child1->popup->child2->child3->wnd1->child4->wnd2->desktop. Current 
91    active window ("foreground window" in Win32) is moved to the front
92    of z-order unless its top-level ancestor owns popup windows.
93
94    All these issues are dealt with (or supposed to be) in windows/winpos.c 
95    with SetWindowPos() being the primary interface to the window manager.
96
97    Wine specifics: in default and managed mode each top-level window
98    gets its own X counterpart with desktop window being basically a 
99    fake stub. In desktop mode, however, only desktop window has an X
100    window associated with it. Also, SetWindowPos() should eventually be
101    implemented via Begin/End/DeferWindowPos() calls and not the other way
102    around.
103
104    1.1 Visible region, clipping region and update region
105
106    windows/dce.c
107    windows/winpos.c
108    windows/painting.c
109
110     ________________________
111    |_________               |  A and B are child windows of C
112    |    A    |______        | 
113    |         |      |       |
114    |---------'      |       |
115    |   |      B     |       |
116    |   |            |       |
117    |   `------------'       |
118    |                   C    |
119    `------------------------'
120
121    Visible region determines which part of the window is not obscured
122    by other windows. If a window has the WS_CLIPCHILDREN style then all
123    areas below its children are considered invisible. Similarily, if
124    the WS_CLIPSIBLINGS bit is in effect then all areas obscured by its
125    siblings are invisible. Child windows are always clipped by the 
126    boundaries of their parent windows.
127
128    B has a WS_CLIPSIBLINGS style:
129    .          ______ 
130    :         |      |
131    |   ,-----'      |
132    |   |      B     | - visible region of B
133    |   |            |
134    :   `------------'
135     
136    When the program requests a display context (DC) for a window it 
137    can specify an optional clipping region that further restricts the 
138    area where the graphics output can appear. This area is calculated 
139    as an intersection of the visible region and a clipping region. 
140
141    Program asked for a DC with a clipping region:
142           ______
143       ,--|--.   |     .    ,--. 
144    ,--+--'  |   |     :   _:  |
145    |  |   B |   |  => |  |    | - DC region where the painting will
146    |  |     |   |     |  |    |   be visible
147    `--|-----|---'     :  `----'
148       `-----'
149
150    When the window manager detects that some part of the window 
151    became visible it adds this area to the update region of this
152    window and then generates WM_ERASEBKGND and WM_PAINT messages. 
153    In addition, WM_NCPAINT message is sent when the uncovered area 
154    intersects a nonclient part of the window. Application must reply 
155    to the WM_PAINT message by calling BeginPaint()/EndPaint() pair of
156    functions. BeginPaint() returns a DC that uses accumulated update 
157    region as a clipping region. This operation cleans up invalidated
158    area and the window will not receive another WM_PAINT until the
159    window manager creates a new update region.
160
161    A was moved to the left:
162     ________________________       ...          / C update region
163    |______                  |     :      .___ /
164    | A    |_________        |  => |   ...|___|..
165    |      |         |       |     |   :  |   |
166    |------'         |       |     |   :  '---' 
167    |   |      B     |       |     |   :      \
168    |   |            |       |     :            \
169    |   `------------'       |                    B update region
170    |                   C    |
171    `------------------------'
172
173
174    Windows maintains a display context cache consisting of entries that 
175    include DC itself, window to which it belongs, and an optional clipping 
176    region (visible region is stored in the DC itself). When an API call 
177    changes the state of the window tree, window manager has to go through 
178    the DC cache to recalculate visible regions for entries whose windows 
179    were involved in the operation. DC entries (DCE) can be either private
180    to the window, or private to the window class, or shared between all 
181    windows (Windows 3.1 limits the number of shared DCEs to 5).
182
183    1.2
184
185 2. Messaging subsystem
186 ----------------------
187
188    windows/queue.c
189    windows/message.c
190
191    Each Windows task/thread has its own message queue - this is where
192    it gets messages from. Messages can be generated on the fly
193    (WM_PAINT, WM_NCPAINT, WM_TIMER), they can be created by the system
194    (hardware messages), they can be posted by other tasks/threads
195    (PostMessage), or they can be sent by other tasks/threads (SendMessage).
196    
197    Message priority:
198
199    First the system looks for sent messages, then for posted messages,
200    then for hardware messages, then it checks if the queue has the
201    "dirty window" bit set, and, finally, it checks for expired
202    timers. See windows/message.c.
203
204    From all these different types of messages, only posted messages go
205    directly into the private message queue. System messages (even in
206    Win95) are first collected in the system message queue and then
207    they either sit there until Get/PeekMessage gets to process them
208    or, as in Win95, if system queue is getting clobbered, a special
209    thread ("raw input thread") assigns them to the private
210    queues. Sent messages are queued separately and the sender sleeps
211    until it gets a reply. Special messages are generated on the fly
212    depending on the window/queue state. If the window update region is
213    not empty, the system sets the QS_PAINT bit in the owning queue and
214    eventually this window receives a WM_PAINT message (WM_NCPAINT too
215    if the update region intersects with the non-client area). A timer
216    event is raised when one of the queue timers expire. Depending on
217    the timer parameters DispatchMessage either calls the callback
218    function or the window procedure. If there are no messages pending
219    the task/thread sleeps until messages appear.
220
221    There are several tricky moments (open for discussion) - 
222
223     a) System message order has to be honored and messages should be
224        processed within correct task/thread context. Therefore when
225        Get/PeekMessage encounters unassigned system message and this
226        message appears not to be for the current task/thread it should
227        either skip it (or get rid of it by moving it into the private
228        message queue of the target task/thread - Win95, AFAIK) and
229        look further or roll back and then yield until this message
230        gets processed when system switches to the correct context
231        (Win16). In the first case we lose correct message ordering, in
232        the second case we have the infamous synchronous system message
233        queue. Here is a post to one of the OS/2 newsgroup I found to
234        be relevant:
235
236         " Here's the problem in a nutshell, and there is no good solution.
237         Every possible solution creates a different problem.
238
239         With a windowing system, events can go to many different windows.
240         Most are sent by applications or by the OS when things relating to
241         that window happen (like repainting, timers, etc.)
242
243         Mouse input events go to the window you click on (unless some window
244         captures the mouse).
245
246         So far, no problem.  Whenever an event happens, you put a message on
247         the target window's message queue.  Every process has a message
248         queue.  If the process queue fills up, the messages back up onto the
249         system queue.
250
251         This is the first cause of apps hanging the GUI.  If an app doesn't
252         handle messages and they back up into the system queue, other apps
253         can't get any more messages.  The reason is that the next message in
254         line can't go anywhere, and the system won't skip over it.
255         
256         This can be fixed by making apps have bigger private message queues.
257         The SIQ fix does this.  PMQSIZE does this for systems without the SIQ
258         fix.  Applications can also request large queues on their own.
259
260         Another source of the problem, however, happens when you include
261         keyboard events.  When you press a key, there's no easy way to know
262         what window the keystroke message should be delivered to.
263
264         Most windowing systems use a concept known as "focus".  The window
265         with focus gets all incoming keyboard messages.  Focus can be changed
266         from window to window by apps or by users clicking on winodws.
267
268         This is the second source of the problem.  Suppose window A has focus.
269         You click on window B and start typing before the window gets focus.
270         Where should the keystrokes go?  On the one hand, they should go to A
271         until the focus actually changes to B.  On the other hand, you
272         probably want the keystrokes to go to B, since you clicked there
273         first.
274
275         OS/2's solution is that when a focus-changing event happens (like
276         clicking on a window), OS/2 holds all messages in the system queue
277         until the focus change actually happens.  This way, subsequent
278         keystrokes go to the window you clicked on, even if it takes a while
279         for that window to get focus.
280
281         The downside is that if the window takes a real long time to get focus
282         (maybe it's not handling events, or maybe the window losing focus
283         isn't handling events), everything backs up in the system queue and
284         the system appears hung.
285
286         There are a few solutions to this problem.
287
288         One is to make focus policy asynchronous.  That is, focus changing has
289         absolutely nothing to do with the keyboard.  If you click on a window
290         and start typing before the focus actually changes, the keystrokes go
291         to the first window until focus changes, then they go to the second.
292         This is what X-windows does.
293
294         Another is what NT does.  When focus changes, keyboard events are held
295         in the system message queue, but other events are allowed through.
296         This is "asynchronous" because the messages in the system queue are
297         delivered to the application queues in a different order from that
298         with which they were posted.  If a bad app won't handle the "lose
299         focus" message, it's of no consequence - the app receiving focus will
300         get its "gain focus" message, and the keystrokes will go to it.
301
302         The NT solution also takes care of the application queue filling up
303         problem.  Since the system delivers messages asynchronously, messages
304         waiting in the system queue will just sit there and the rest of the
305         messages will be delivered to their apps.
306
307         The OS/2 SIQ solution is this:  When a focus-changing event happens,
308         in addition to blocking further messages from the application queues,
309         a timer is started.  When the timer goes off, if the focus change has
310         not yet happened, the bad app has its focus taken away and all
311         messages targetted at that window are skipped.  When the bad app
312         finally handles the focus change message, OS/2 will detect this and
313         stop skipping its messages.
314
315
316         As for the pros and cons:
317
318         The X-windows solution is probably the easiest.  The problem is that
319         users generally don't like having to wait for the focus to change
320         before they start typing.  On many occasions, you can type and the
321         characters end up in the wrong window because something (usually heavy
322         system load) is preventing the focus change from happening in a timely
323         manner.
324         
325         The NT solution seems pretty nice, but making the system message queue
326         asynchronous can cause similar problems to the X-windows problem.
327         Since messages can be delivered out of order, programs must not assume
328         that two messages posted in a particular order will be delivered in
329         that same order.  This can break legacy apps, but since Win32 always
330         had an asynchronous queue, it is fair to simply tell app designers
331         "don't do that".  It's harder to tell app designers something like
332         that on OS/2 - they'll complain "you changed the rules and our apps
333         are breaking."
334         
335         The OS/2 solution's problem is that nothing happens until you try to
336         change window focus, and then wait for the timeout.  Until then, the
337         bad app is not detected and nothing is done." (by David Charlap)
338         
339
340     b) Intertask/interthread SendMessage. The system has to inform the
341        target queue about the forthcoming message, then it has to carry 
342        out the context switch and wait until the result is available.  
343        Win16 stores necessary parameters in the queue structure and then 
344        calls DirectedYield() function.  However, in Win32 there could be 
345        several messages pending sent by preemptively executing threads, 
346        and in this case SendMessage has to build some sort of message 
347        queue for sent messages. Another issue is what to do with messages 
348        sent to the sender when it is blocked inside its own SendMessage. 
349
350