Release 960616
[wine/multimedia.git] / documentation / user_module
blob6b6bfd74c2605a58ad74cd67a4a65b5552e48ad4
1 USER MODULE
2 ===========
4 USER implements windowing and messaging subsystems. It also 
5 contains code for common controls and for other miscellaneous 
6 stuff (rectangles, clipboard, WNet, etc). Wine USER code is 
7 located in windows/, controls/, and misc/ directories.
9 1. Windowing subsystem
11    Windows are arranged into parent/child hierarchy with one
12    common ancestor for all windows (desktop window). Each window
13    structure contains a pointer to the immediate ancestor (parent 
14    window if WS_CHILD style bit is set), a pointer to the sibling 
15    (returned by GetWindow(..., GW_NEXT)), a pointer to the owner 
16    window (set only for popup window if it was created with valid 
17    hwndParent parameter), and a pointer to the first child
18    window (GetWindow(.., GW_CHILD)). All popup and non-child windows
19    are therefore placed in the first level of this hierarchy and their
20    ancestor link (wnd->parent) points to the desktop window.
22    Desktop window                       - root window
23     |     \      '-.
24     |      \        '-.
25    popup -> wnd1  ->  wnd2              - top level windows    
26     |       \   '-.      '-.
27     |        \     '-.      '-.
28    child1  child2 -> child3  child4     - child windows
29   
30    Horizontal arrows denote sibling relationship, vertical lines
31    - ancestor/child. To summarize, all windows with the same immediate 
32    ancestor are sibling windows, all windows which do not have desktop 
33    as their immediate ancestor are child windows. Popup windows behave
34    as topmost top-level windows unless they are owned. In this case the
35    only requirement is that they must precede their owners in the top-level 
36    sibling list (they are not topmost). Child windows are confined to the
37    client area of their parent windows (client area is where window gets
38    to do its own drawing, non-client area consists of caption, menu, borders,
39    intrinsic scrollbars, and minimize/maximize/close buttons). 
40   
41    Another fairly important concept is "z-order". It is derived from
42    the ancestor/child hierarchy and is used to determine "above/below"
43    relationship. For instance, in the example above, z-order is
44    child1->popup->child2->child3->wnd1->child4->wnd2->desktop. Current 
45    active window ("foreground window" in Win32) is moved to the front
46    of z-order unless its top-level ancestor owns popup windows.
48    All these issues are dealt with (or supposed to be) in 
49    windows/winpos.c
51    Wine specifics: in default and managed mode each top-level window
52    gets its own X counterpart with desktop window being basically a 
53    fake stub. In desktop mode, however, only desktop window has X
54    window associated with it.
56 2. Messaging subsystem
58    Each Windows task/thread has its own message queue - this is where
59    it gets messages from. Messages can be generated on the fly
60    (WM_PAINT, WM_NCPAINT, WM_TIMER), they can be created by the system
61    (hardware messages), they can be posted by other tasks/threads
62    (PostMessage), or they can be sent by other tasks/threads (SendMessage).
63    
64    Message priority:
66    First the system looks for sent messages, then for posted messages,
67    then for hardware messages, then it checks if the queue has the
68    "dirty window" bit set, and, finally, it checks for expired
69    timers. See windows/message.c.
71    From all these different types of messages, only posted messages go
72    directly into the private message queue. System messages (even in
73    Win95) are first collected in the system message queue and then
74    they either sit there until Get/PeekMessage gets to process them
75    or, as in Win95, if system queue is getting clobbered, a special
76    thread ("raw input thread") assigns them to the private
77    queues. Sent messages are queued separately and the sender sleeps
78    until it gets a reply. Special messages are generated on the fly
79    depending on the window/queue state. If the window update region is
80    not empty, the system sets the QS_PAINT bit in the owning queue and
81    eventually this window receives a WM_PAINT message (WM_NCPAINT too
82    if the update region intersects with the non-client area). A timer
83    event is raised when one of the queue timers expire. Depending on
84    the timer parameters DispatchMessage either calls the callback
85    function or the window procedure. If there are no messages pending
86    the task/thread sleeps until messages appear.
88    There are several tricky moments (open for discussion) - 
90     a) System message order has to be honored and messages should be
91        processed within correct task/thread context. Therefore when
92        Get/PeekMessage encounters unassigned system message and this
93        message appears not to be for the current task/thread it should
94        either skip it (or get rid of it by moving it into the private
95        message queue of the target task/thread - Win95, AFAIK) and
96        look further or roll back and then yield until this message
97        gets processed when system switches to the correct context
98        (Win16). In the first case we lose correct message ordering, in
99        the second case we have the infamous synchronous system message
100        queue. Here is a post to one of the OS/2 newsgroup I found to
101        be relevant:
103         " Here's the problem in a nutshell, and there is no good solution.
104         Every possible solution creates a different problem.
106         With a windowing system, events can go to many different windows.
107         Most are sent by applications or by the OS when things relating to
108         that window happen (like repainting, timers, etc.)
110         Mouse input events go to the window you click on (unless some window
111         captures the mouse).
113         So far, no problem.  Whenever an event happens, you put a message on
114         the target window's message queue.  Every process has a message
115         queue.  If the process queue fills up, the messages back up onto the
116         system queue.
118         This is the first cause of apps hanging the GUI.  If an app doesn't
119         handle messages and they back up into the system queue, other apps
120         can't get any more messages.  The reason is that the next message in
121         line can't go anywhere, and the system won't skip over it.
122         
123         This can be fixed by making apps have bigger private message queues.
124         The SIQ fix does this.  PMQSIZE does this for systems without the SIQ
125         fix.  Applications can also request large queues on their own.
127         Another source of the problem, however, happens when you include
128         keyboard events.  When you press a key, there's no easy way to know
129         what window the keystroke message should be delivered to.
131         Most windowing systems use a concept known as "focus".  The window
132         with focus gets all incoming keyboard messages.  Focus can be changed
133         from window to window by apps or by users clicking on winodws.
135         This is the second source of the problem.  Suppose window A has focus.
136         You click on window B and start typing before the window gets focus.
137         Where should the keystrokes go?  On the one hand, they should go to A
138         until the focus actually changes to B.  On the other hand, you
139         probably want the keystrokes to go to B, since you clicked there
140         first.
142         OS/2's solution is that when a focus-changing event happens (like
143         clicking on a window), OS/2 holds all messages in the system queue
144         until the focus change actually happens.  This way, subsequent
145         keystrokes go to the window you clicked on, even if it takes a while
146         for that window to get focus.
148         The downside is that if the window takes a real long time to get focus
149         (maybe it's not handling events, or maybe the window losing focus
150         isn't handling events), everything backs up in the system queue and
151         the system appears hung.
153         There are a few solutions to this problem.
155         One is to make focus policy asynchronous.  That is, focus changing has
156         absolutely nothing to do with the keyboard.  If you click on a window
157         and start typing before the focus actually changes, the keystrokes go
158         to the first window until focus changes, then they go to the second.
159         This is what X-windows does.
161         Another is what NT does.  When focus changes, keyboard events are held
162         in the system message queue, but other events are allowed through.
163         This is "asynchronous" because the messages in the system queue are
164         delivered to the application queues in a different order from that
165         with which they were posted.  If a bad app won't handle the "lose
166         focus" message, it's of no consequence - the app receiving focus will
167         get its "gain focus" message, and the keystrokes will go to it.
169         The NT solution also takes care of the application queue filling up
170         problem.  Since the system delivers messages asynchronously, messages
171         waiting in the system queue will just sit there and the rest of the
172         messages will be delivered to their apps.
174         The OS/2 SIQ solution is this:  When a focus-changing event happens,
175         in addition to blocking further messages from the application queues,
176         a timer is started.  When the timer goes off, if the focus change has
177         not yet happened, the bad app has its focus taken away and all
178         messages targetted at that window are skipped.  When the bad app
179         finally handles the focus change message, OS/2 will detect this and
180         stop skipping its messages.
183         As for the pros and cons:
185         The X-windows solution is probably the easiest.  The problem is that
186         users generally don't like having to wait for the focus to change
187         before they start typing.  On many occasions, you can type and the
188         characters end up in the wrong window because something (usually heavy
189         system load) is preventing the focus change from happening in a timely
190         manner.
191         
192         The NT solution seems pretty nice, but making the system message queue
193         asynchronous can cause similar problems to the X-windows problem.
194         Since messages can be delivered out of order, programs must not assume
195         that two messages posted in a particular order will be delivered in
196         that same order.  This can break legacy apps, but since Win32 always
197         had an asynchronous queue, it is fair to simply tell app designers
198         "don't do that".  It's harder to tell app designers something like
199         that on OS/2 - they'll complain "you changed the rules and our apps
200         are breaking."
201         
202         The OS/2 solution's problem is that nothing happens until you try to
203         change window focus, and then wait for the timeout.  Until then, the
204         bad app is not detected and nothing is done." (by David Charlap)
205         
207     b) Intertask/interthread SendMessage. The system has to inform the
208        target queue about the forthcoming message, then it has to
209        carry out the context switch and wait until the result is
210        available.  In Win16 it is done by putting necessary parameters
211        into the queue structure and do a DirectedYield() call.
212        However, in Win32 there could be several messages pending sent
213        by preemptively executing threads, and in this case SendMessage
214        has to build some sort of message queue for sent
215        messages. Another issue is what to do with messages sent to the
216        sender when it is blocked inside its own SendMessage. At this
217        point Wine does not address any of these problems.