Fixed a race condition on RPC worker thread creation, and a typo.
[wine] / dlls / ttydrv / wnd.c
1 /*
2  * TTY window driver
3  *
4  * Copyright 1998,1999 Patrik Stridvall
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "gdi.h"
24 #include "ttydrv.h"
25 #include "win.h"
26 #include "winpos.h"
27 #include "wownt32.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(ttydrv);
31
32 #define SWP_AGG_NOGEOMETRYCHANGE \
33     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
34 #define SWP_AGG_NOPOSCHANGE \
35     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
36 #define SWP_AGG_STATUSFLAGS \
37     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
38
39 /**********************************************************************
40  *              CreateWindow   (TTYDRV.@)
41  */
42 BOOL TTYDRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
43 {
44     BOOL ret;
45     HWND hwndLinkAfter;
46     CBT_CREATEWNDA cbtc;
47
48 #ifdef WINE_CURSES
49     WND *wndPtr = WIN_GetPtr( hwnd );
50     WINDOW *window;
51     INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
52
53     TRACE("(%p)\n", hwnd);
54
55     /* Only create top-level windows */
56     if (!(wndPtr->dwStyle & WS_CHILD))
57     {
58         if (!wndPtr->parent)  /* desktop */
59             window = root_window;
60         else
61         {
62             int x = wndPtr->rectWindow.left;
63             int y = wndPtr->rectWindow.top;
64             int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
65             int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
66
67             window = subwin( root_window, cy/cellHeight, cx/cellWidth,
68                              y/cellHeight, x/cellWidth);
69             werase(window);
70             wrefresh(window);
71         }
72         wndPtr->pDriverData = window;
73     }
74     WIN_ReleasePtr( wndPtr );
75 #else /* defined(WINE_CURSES) */
76     FIXME("(%x): stub\n", hwnd);
77 #endif /* defined(WINE_CURSES) */
78
79     /* Call the WH_CBT hook */
80
81     hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
82  ? HWND_BOTTOM : HWND_TOP;
83
84     cbtc.lpcs = cs;
85     cbtc.hwndInsertAfter = hwndLinkAfter;
86     if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ))
87     {
88         TRACE("CBT-hook returned !0\n");
89         return FALSE;
90     }
91
92     if (unicode)
93     {
94         ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
95         if (ret) ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
96     }
97     else
98     {
99         ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
100         if (ret) ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
101     }
102     return ret;
103 }
104
105 /***********************************************************************
106  *              DestroyWindow   (TTYDRV.@)
107  */
108 BOOL TTYDRV_DestroyWindow( HWND hwnd )
109 {
110 #ifdef WINE_CURSES
111     WND *wndPtr = WIN_GetPtr( hwnd );
112     WINDOW *window = wndPtr->pDriverData;
113
114     TRACE("(%p)\n", hwnd);
115
116     if (window && window != root_window) delwin(window);
117     wndPtr->pDriverData = NULL;
118     WIN_ReleasePtr( wndPtr );
119 #else /* defined(WINE_CURSES) */
120     FIXME("(%x): stub\n", hwnd);
121 #endif /* defined(WINE_CURSES) */
122     return TRUE;
123 }
124
125
126 /***********************************************************************
127  *           DCE_GetVisRect
128  *
129  * Calculate the visible rectangle of a window (i.e. the client or
130  * window area clipped by the client area of all ancestors) in the
131  * corresponding coordinates. Return FALSE if the visible region is empty.
132  */
133 static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
134 {
135     *lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
136
137     if (wndPtr->dwStyle & WS_VISIBLE)
138     {
139         INT xoffset = lprect->left;
140         INT yoffset = lprect->top;
141
142         while ((wndPtr = WIN_FindWndPtr( GetAncestor(wndPtr->hwndSelf,GA_PARENT) )))
143         {
144             if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
145             {
146                 WIN_ReleaseWndPtr(wndPtr);
147                 goto fail;
148             }
149
150             xoffset += wndPtr->rectClient.left;
151             yoffset += wndPtr->rectClient.top;
152             OffsetRect( lprect, wndPtr->rectClient.left,
153                         wndPtr->rectClient.top );
154
155             if( (wndPtr->rectClient.left >= wndPtr->rectClient.right) ||
156                 (wndPtr->rectClient.top >= wndPtr->rectClient.bottom) ||
157                 (lprect->left >= wndPtr->rectClient.right) ||
158                 (lprect->right <= wndPtr->rectClient.left) ||
159                 (lprect->top >= wndPtr->rectClient.bottom) ||
160                 (lprect->bottom <= wndPtr->rectClient.top) )
161             {
162                 WIN_ReleaseWndPtr(wndPtr);
163                 goto fail;
164             }
165
166             lprect->left = max( lprect->left, wndPtr->rectClient.left );
167             lprect->right = min( lprect->right, wndPtr->rectClient.right );
168             lprect->top = max( lprect->top, wndPtr->rectClient.top );
169             lprect->bottom = min( lprect->bottom, wndPtr->rectClient.bottom );
170
171             WIN_ReleaseWndPtr(wndPtr);
172         }
173         OffsetRect( lprect, -xoffset, -yoffset );
174         return TRUE;
175     }
176
177 fail:
178     SetRectEmpty( lprect );
179     return FALSE;
180 }
181
182
183 /***********************************************************************
184  *           DCE_AddClipRects
185  *
186  * Go through the linked list of windows from pWndStart to pWndEnd,
187  * adding to the clip region the intersection of the target rectangle
188  * with an offset window rectangle.
189  */
190 static void DCE_AddClipRects( HWND parent, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y )
191 {
192     RECT rect;
193     WND *pWnd;
194     int i;
195     HWND *list = WIN_ListChildren( parent );
196     HRGN hrgn = 0;
197
198     if (!list) return;
199     for (i = 0; list[i]; i++)
200     {
201         if (list[i] == end) break;
202         if (!(pWnd = WIN_FindWndPtr( list[i] ))) continue;
203         if (pWnd->dwStyle & WS_VISIBLE)
204         {
205             rect.left = pWnd->rectWindow.left + x;
206             rect.top = pWnd->rectWindow.top + y;
207             rect.right = pWnd->rectWindow.right + x;
208             rect.bottom = pWnd->rectWindow.bottom + y;
209             if( IntersectRect( &rect, &rect, lpRect ))
210             {
211                 if (!hrgn) hrgn = CreateRectRgnIndirect( &rect );
212                 else SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
213                 CombineRgn( hrgnClip, hrgnClip, hrgn, RGN_OR );
214             }
215         }
216         WIN_ReleaseWndPtr( pWnd );
217     }
218     if (hrgn) DeleteObject( hrgn );
219     HeapFree( GetProcessHeap(), 0, list );
220 }
221
222
223 /***********************************************************************
224  *           DCE_GetVisRgn
225  *
226  * Return the visible region of a window, i.e. the client or window area
227  * clipped by the client area of all ancestors, and then optionally
228  * by siblings and children.
229  */
230 static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
231 {
232     HRGN hrgnVis = 0;
233     RECT rect;
234     WND *wndPtr = WIN_FindWndPtr( hwnd );
235     WND *childWnd = WIN_FindWndPtr( hwndChild );
236
237     /* Get visible rectangle and create a region with it. */
238
239     if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
240     {
241         if((hrgnVis = CreateRectRgnIndirect( &rect )))
242         {
243             HRGN hrgnClip = CreateRectRgn( 0, 0, 0, 0 );
244             INT xoffset, yoffset;
245
246             if( hrgnClip )
247             {
248                 /* Compute obscured region for the visible rectangle by
249                  * clipping children, siblings, and ancestors. Note that
250                  * DCE_GetVisRect() returns a rectangle either in client
251                  * or in window coordinates (for DCX_WINDOW request). */
252
253                 if (flags & DCX_CLIPCHILDREN)
254                 {
255                     if( flags & DCX_WINDOW )
256                     {
257                         /* adjust offsets since child window rectangles are
258                          * in client coordinates */
259
260                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
261                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
262                     }
263                     else
264                         xoffset = yoffset = 0;
265
266                     DCE_AddClipRects( wndPtr->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset );
267                 }
268
269                 /* We may need to clip children of child window, if a window with PARENTDC
270                  * class style and CLIPCHILDREN window style (like in Free Agent 16
271                  * preference dialogs) gets here, we take the region for the parent window
272                  * but apparently still need to clip the children of the child window... */
273
274                 if( (cflags & DCX_CLIPCHILDREN) && childWnd)
275                 {
276                     if( flags & DCX_WINDOW )
277                     {
278                         /* adjust offsets since child window rectangles are
279                          * in client coordinates */
280
281                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
282                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
283                     }
284                     else
285                         xoffset = yoffset = 0;
286
287                     /* client coordinates of child window */
288                     xoffset += childWnd->rectClient.left;
289                     yoffset += childWnd->rectClient.top;
290
291                     DCE_AddClipRects( childWnd->hwndSelf, 0, hrgnClip,
292                                       &rect, xoffset, yoffset );
293                 }
294
295                 /* sibling window rectangles are in client
296                  * coordinates of the parent window */
297
298                 if (flags & DCX_WINDOW)
299                 {
300                     xoffset = -wndPtr->rectWindow.left;
301                     yoffset = -wndPtr->rectWindow.top;
302                 }
303                 else
304                 {
305                     xoffset = -wndPtr->rectClient.left;
306                     yoffset = -wndPtr->rectClient.top;
307                 }
308
309                 if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
310                     DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
311                                       hrgnClip, &rect, xoffset, yoffset );
312
313                 /* Clip siblings of all ancestors that have the
314                  * WS_CLIPSIBLINGS style
315                  */
316
317                 while (wndPtr->parent)
318                 {
319                     WND *ptr = WIN_FindWndPtr( wndPtr->parent );
320                     WIN_ReleaseWndPtr( wndPtr );
321                     wndPtr = ptr;
322                     xoffset -= wndPtr->rectClient.left;
323                     yoffset -= wndPtr->rectClient.top;
324                     if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
325                     {
326                         DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
327                                           hrgnClip, &rect, xoffset, yoffset );
328                     }
329                 }
330
331                 /* Now once we've got a jumbo clip region we have
332                  * to substract it from the visible rectangle.
333                  */
334                 CombineRgn( hrgnVis, hrgnVis, hrgnClip, RGN_DIFF );
335                 DeleteObject( hrgnClip );
336             }
337             else
338             {
339                 DeleteObject( hrgnVis );
340                 hrgnVis = 0;
341             }
342         }
343     }
344     else
345         hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
346     WIN_ReleaseWndPtr(wndPtr);
347     WIN_ReleaseWndPtr(childWnd);
348     return hrgnVis;
349 }
350
351
352 /***********************************************************************
353  *              GetDC   (TTYDRV.@)
354  *
355  * Set the drawable, origin and dimensions for the DC associated to
356  * a given window.
357  */
358 BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
359 {
360     WND *wndPtr = WIN_FindWndPtr(hwnd);
361     HRGN hrgnVisible = 0;
362     POINT org;
363
364     if (!wndPtr) return FALSE;
365
366     if(flags & DCX_WINDOW)
367     {
368         org.x = wndPtr->rectWindow.left;
369         org.y = wndPtr->rectWindow.top;
370     }
371     else
372     {
373         org.x = wndPtr->rectClient.left;
374         org.y = wndPtr->rectClient.top;
375     }
376
377     SetDCOrg16( HDC_16(hdc), org.x, org.y );
378
379     if (SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN ))  /* DC was dirty */
380     {
381         if (flags & DCX_PARENTCLIP)
382         {
383             WND *parentPtr = WIN_FindWndPtr( wndPtr->parent );
384
385             if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
386             {
387                 DWORD dcxFlags;
388
389                 if( parentPtr->dwStyle & WS_CLIPSIBLINGS )
390                     dcxFlags = DCX_CLIPSIBLINGS | (flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
391                 else
392                     dcxFlags = flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
393
394                 hrgnVisible = DCE_GetVisRgn( parentPtr->hwndSelf, dcxFlags,
395                                              wndPtr->hwndSelf, flags );
396                 if( flags & DCX_WINDOW )
397                     OffsetRgn( hrgnVisible, -wndPtr->rectWindow.left,
398                                -wndPtr->rectWindow.top );
399                 else
400                     OffsetRgn( hrgnVisible, -wndPtr->rectClient.left,
401                                -wndPtr->rectClient.top );
402             }
403             else
404                 hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
405             WIN_ReleaseWndPtr(parentPtr);
406         }
407         else
408         {
409             hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
410             OffsetRgn( hrgnVisible, org.x, org.y );
411         }
412         SelectVisRgn16( HDC_16(hdc), HRGN_16(hrgnVisible) );
413     }
414
415     /* apply additional region operation (if any) */
416
417     if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
418     {
419         if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
420
421         TRACE("\tsaved VisRgn, clipRgn = %p\n", hrgn);
422
423         SaveVisRgn16( HDC_16(hdc) );
424         CombineRgn( hrgnVisible, hrgn, 0, RGN_COPY );
425         OffsetRgn( hrgnVisible, org.x, org.y );
426         CombineRgn( hrgnVisible, HRGN_32(InquireVisRgn16(HDC_16(hdc))), hrgnVisible,
427                       (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
428         SelectVisRgn16(HDC_16(hdc), HRGN_16(hrgnVisible));
429     }
430
431     if (hrgnVisible) DeleteObject( hrgnVisible );
432
433     WIN_ReleaseWndPtr( wndPtr );
434     return TRUE;
435 }
436
437
438 /***********************************************************************
439  *              SetWindowPos   (TTYDRV.@)
440  */
441 BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
442 {
443     WND *wndPtr;
444     RECT newWindowRect, newClientRect;
445     BOOL retvalue;
446     HWND hwndActive = GetForegroundWindow();
447
448     TRACE( "hwnd %p, swp (%i,%i)-(%i,%i) flags %08x\n",
449            winpos->hwnd, winpos->x, winpos->y,
450            winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
451
452     /* ------------------------------------------------------------------------ CHECKS */
453
454       /* Check window handle */
455
456     if (winpos->hwnd == GetDesktopWindow()) return FALSE;
457     if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
458
459     TRACE("\tcurrent (%ld,%ld)-(%ld,%ld), style %08x\n",
460           wndPtr->rectWindow.left, wndPtr->rectWindow.top,
461           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
462
463     /* Fix redundant flags */
464
465     if(wndPtr->dwStyle & WS_VISIBLE)
466         winpos->flags &= ~SWP_SHOWWINDOW;
467     else
468     {
469         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
470         winpos->flags &= ~SWP_HIDEWINDOW;
471     }
472
473     if ( winpos->cx < 0 ) winpos->cx = 0;
474     if ( winpos->cy < 0 ) winpos->cy = 0;
475
476     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
477         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
478         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
479
480     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
481         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
482
483     if (winpos->hwnd == hwndActive)
484         winpos->flags |= SWP_NOACTIVATE;   /* Already active */
485     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
486     {
487         if(!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
488         {
489             winpos->flags &= ~SWP_NOZORDER;
490             winpos->hwndInsertAfter = HWND_TOP;
491             goto Pos;
492         }
493     }
494
495     /* Check hwndInsertAfter */
496
497       /* FIXME: TOPMOST not supported yet */
498     if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
499         (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
500
501     /* hwndInsertAfter must be a sibling of the window */
502     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
503     {
504         WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
505
506         if( wnd ) {
507             if( wnd->parent != wndPtr->parent )
508             {
509                 retvalue = FALSE;
510                 WIN_ReleaseWndPtr(wnd);
511                 goto END;
512             }
513             /* don't need to change the Zorder of hwnd if it's already inserted
514              * after hwndInsertAfter or when inserting hwnd after itself.
515              */
516             if ((winpos->hwnd == winpos->hwndInsertAfter) ||
517                 (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
518                 winpos->flags |= SWP_NOZORDER;
519         }
520         WIN_ReleaseWndPtr(wnd);
521     }
522
523  Pos:  /* ------------------------------------------------------------------------ MAIN part */
524
525       /* Send WM_WINDOWPOSCHANGING message */
526
527     if (!(winpos->flags & SWP_NOSENDCHANGING))
528         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)winpos );
529
530       /* Calculate new position and size */
531
532     newWindowRect = wndPtr->rectWindow;
533     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
534                                                     : wndPtr->rectClient;
535
536     if (!(winpos->flags & SWP_NOSIZE))
537     {
538         newWindowRect.right  = newWindowRect.left + winpos->cx;
539         newWindowRect.bottom = newWindowRect.top + winpos->cy;
540     }
541     if (!(winpos->flags & SWP_NOMOVE))
542     {
543         newWindowRect.left    = winpos->x;
544         newWindowRect.top     = winpos->y;
545         newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
546         newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
547
548         OffsetRect( &newClientRect, winpos->x - wndPtr->rectWindow.left,
549                     winpos->y - wndPtr->rectWindow.top );
550     }
551
552     if( winpos->hwndInsertAfter == HWND_TOP )
553     {
554         if (GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ) == wndPtr->hwndSelf)
555             winpos->flags |= SWP_NOZORDER;
556     }
557     else
558         if( winpos->hwndInsertAfter == HWND_BOTTOM )
559         {
560             if (!GetWindow( wndPtr->hwndSelf, GW_HWNDNEXT ))
561                 winpos->flags |= SWP_NOZORDER;
562         }
563         else
564             if( !(winpos->flags & SWP_NOZORDER) )
565                 if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
566                     winpos->flags |= SWP_NOZORDER;
567
568     /* Common operations */
569
570       /* Send WM_NCCALCSIZE message to get new client area */
571     if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
572     {
573         NCCALCSIZE_PARAMS params;
574         WINDOWPOS winposCopy;
575
576         params.rgrc[0] = newWindowRect;
577         params.rgrc[1] = wndPtr->rectWindow;
578         params.rgrc[2] = wndPtr->rectClient;
579         params.lppos = &winposCopy;
580         winposCopy = *winpos;
581
582         SendMessageW( winpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
583
584         TRACE( "%ld,%ld-%ld,%ld\n", params.rgrc[0].left, params.rgrc[0].top,
585                params.rgrc[0].right, params.rgrc[0].bottom );
586
587         /* If the application send back garbage, ignore it */
588         if (params.rgrc[0].left <= params.rgrc[0].right &&
589             params.rgrc[0].top <= params.rgrc[0].bottom)
590             newClientRect = params.rgrc[0];
591
592          /* FIXME: WVR_ALIGNxxx */
593
594         if( newClientRect.left != wndPtr->rectClient.left ||
595             newClientRect.top != wndPtr->rectClient.top )
596             winpos->flags &= ~SWP_NOCLIENTMOVE;
597
598         if( (newClientRect.right - newClientRect.left !=
599              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
600             (newClientRect.bottom - newClientRect.top !=
601              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
602             winpos->flags &= ~SWP_NOCLIENTSIZE;
603     }
604
605     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
606     {
607         HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
608         if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter );
609     }
610
611     /* FIXME: actually do something with WVR_VALIDRECTS */
612
613     WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
614
615     if( winpos->flags & SWP_SHOWWINDOW )
616         WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE );
617     else if( winpos->flags & SWP_HIDEWINDOW )
618         WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
619
620     /* ------------------------------------------------------------------------ FINAL */
621
622     /* repaint invalidated region (if any)
623      *
624      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
625      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
626      */
627
628     if( !(winpos->flags & SWP_NOREDRAW) )
629     {
630         RedrawWindow( wndPtr->parent, NULL, 0,
631                       RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN );
632         if (wndPtr->parent == GetDesktopWindow())
633             RedrawWindow( wndPtr->parent, NULL, 0,
634                           RDW_ERASENOW | RDW_NOCHILDREN );
635     }
636
637     if (!(winpos->flags & SWP_NOACTIVATE)) SetActiveWindow( winpos->hwnd );
638
639       /* And last, send the WM_WINDOWPOSCHANGED message */
640
641     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
642
643     if ((((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
644           !(winpos->flags & SWP_NOSENDCHANGING)) )
645         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
646
647     retvalue = TRUE;
648  END:
649     WIN_ReleaseWndPtr(wndPtr);
650     return retvalue;
651 }
652
653
654 /***********************************************************************
655  *              WINPOS_MinMaximize   (internal)
656  *
657  *Lifted from x11 driver
658  */
659 static UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
660 {
661     UINT swpFlags = 0;
662     WINDOWPLACEMENT wpl;
663
664     TRACE("%p %u\n", hwnd, cmd );
665     FIXME("(%p): stub\n", hwnd);
666
667     wpl.length = sizeof(wpl);
668     GetWindowPlacement( hwnd, &wpl );
669
670     /* If I glark this right, yields an immutable window*/
671     swpFlags = SWP_NOSIZE | SWP_NOMOVE;
672
673     /*cmd handling goes here.  see dlls/x1drv/winpos.c*/
674
675     return swpFlags;
676 }
677
678 /***********************************************************************
679  *              ShowWindow   (TTYDRV.@)
680  *
681  *Lifted from x11 driver
682  *Sets the specified windows' show state.
683  */
684 BOOL TTYDRV_ShowWindow( HWND hwnd, INT cmd )
685 {
686     WND*        wndPtr = WIN_FindWndPtr( hwnd );
687     BOOL        wasVisible, showFlag;
688     RECT        newPos = {0, 0, 0, 0};
689     UINT        swp = 0;
690
691     if (!wndPtr) return FALSE;
692     hwnd = wndPtr->hwndSelf;  /* make it a full handle */
693
694     TRACE("hwnd=%p, cmd=%d\n", hwnd, cmd);
695
696     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
697
698     switch(cmd)
699     {
700         case SW_HIDE:
701             if (!wasVisible) goto END;
702             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
703                         SWP_NOACTIVATE | SWP_NOZORDER;
704             break;
705
706         case SW_SHOWMINNOACTIVE:
707             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
708             /* fall through */
709         case SW_SHOWMINIMIZED:
710             swp |= SWP_SHOWWINDOW;
711             /* fall through */
712         case SW_MINIMIZE:
713             swp |= SWP_FRAMECHANGED;
714             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
715                  swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
716             else swp |= SWP_NOSIZE | SWP_NOMOVE;
717             break;
718
719         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
720             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
721             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
722                  swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
723             else swp |= SWP_NOSIZE | SWP_NOMOVE;
724             break;
725
726         case SW_SHOWNA:
727             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
728             /* fall through */
729         case SW_SHOW:
730             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
731
732             /*
733              * ShowWindow has a little peculiar behavior that if the
734              * window is already the topmost window, it will not
735              * activate it.
736              */
737             if (GetTopWindow(NULL)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
738               swp |= SWP_NOACTIVATE;
739
740             break;
741
742         case SW_SHOWNOACTIVATE:
743             swp |= SWP_NOZORDER;
744             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
745             /* fall through */
746         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
747         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
748         case SW_RESTORE:
749             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
750
751             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
752                  swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
753             else swp |= SWP_NOSIZE | SWP_NOMOVE;
754             break;
755     }
756
757     showFlag = (cmd != SW_HIDE);
758     if (showFlag != wasVisible)
759     {
760         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
761         if (!IsWindow( hwnd )) goto END;
762     }
763
764     /* We can't activate a child window */
765     if ((wndPtr->dwStyle & WS_CHILD) &&
766         !(wndPtr->dwExStyle & WS_EX_MDICHILD))
767         swp |= SWP_NOACTIVATE | SWP_NOZORDER;
768
769     SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
770                   newPos.right, newPos.bottom, LOWORD(swp) );
771     if (cmd == SW_HIDE)
772     {
773         /* FIXME: This will cause the window to be activated irrespective
774          * of whether it is owned by the same thread. Has to be done
775          * asynchronously.
776          */
777
778         if (hwnd == GetActiveWindow())
779             WINPOS_ActivateOtherWindow(hwnd);
780
781         /* Revert focus to parent */
782         if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
783             SetFocus( GetParent(hwnd) );
784     }
785     if (!IsWindow( hwnd )) goto END;
786     else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE );
787
788     if (wndPtr->flags & WIN_NEED_SIZE)
789     {
790         /* should happen only in CreateWindowEx() */
791         int wParam = SIZE_RESTORED;
792
793         wndPtr->flags &= ~WIN_NEED_SIZE;
794         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
795         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
796         SendMessageA( hwnd, WM_SIZE, wParam,
797                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
798                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
799         SendMessageA( hwnd, WM_MOVE, 0,
800                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
801     }
802
803 END:
804     WIN_ReleaseWndPtr(wndPtr);
805     return wasVisible;
806 }