When computing nonclient area take into consideration that a child
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996, 1999 Alex Korobka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26 #include <string.h>
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winerror.h"
32 #include "ntstatus.h"
33 #include "wine/winuser16.h"
34 #include "wine/server.h"
35 #include "controls.h"
36 #include "user_private.h"
37 #include "win.h"
38 #include "message.h"
39 #include "winpos.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
43
44 #define HAS_DLGFRAME(style,exStyle) \
45     (((exStyle) & WS_EX_DLGMODALFRAME) || \
46      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
47
48 #define HAS_THICKFRAME(style) \
49     (((style) & WS_THICKFRAME) && \
50      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
51
52 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
53
54 #define PLACE_MIN               0x0001
55 #define PLACE_MAX               0x0002
56 #define PLACE_RECT              0x0004
57
58
59 #define DWP_MAGIC  ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
60
61 typedef struct
62 {
63     INT       actualCount;
64     INT       suggestedCount;
65     BOOL      valid;
66     INT       wMagic;
67     HWND      hwndParent;
68     WINDOWPOS winPos[1];
69 } DWP;
70
71 typedef struct
72 {
73     RECT16   rectNormal;
74     POINT16  ptIconPos;
75     POINT16  ptMaxPos;
76     HWND     hwndIconTitle;
77 } INTERNALPOS, *LPINTERNALPOS;
78
79 /* ----- internal variables ----- */
80
81 static LPCSTR atomInternalPos;
82
83
84 /***********************************************************************
85  *           WINPOS_CreateInternalPosAtom
86  */
87 BOOL WINPOS_CreateInternalPosAtom()
88 {
89     LPCSTR str = "SysIP";
90     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
91     return (atomInternalPos) ? TRUE : FALSE;
92 }
93
94 /***********************************************************************
95  *           WINPOS_CheckInternalPos
96  *
97  * Called when a window is destroyed.
98  */
99 void WINPOS_CheckInternalPos( HWND hwnd )
100 {
101     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
102
103     if( lpPos )
104     {
105         if( IsWindow(lpPos->hwndIconTitle) )
106             DestroyWindow( lpPos->hwndIconTitle );
107         HeapFree( GetProcessHeap(), 0, lpPos );
108     }
109 }
110
111 /***********************************************************************
112  *              ArrangeIconicWindows (USER32.@)
113  */
114 UINT WINAPI ArrangeIconicWindows( HWND parent )
115 {
116     RECT rectParent;
117     HWND hwndChild;
118     INT x, y, xspacing, yspacing;
119
120     GetClientRect( parent, &rectParent );
121     x = rectParent.left;
122     y = rectParent.bottom;
123     xspacing = GetSystemMetrics(SM_CXICONSPACING);
124     yspacing = GetSystemMetrics(SM_CYICONSPACING);
125
126     hwndChild = GetWindow( parent, GW_CHILD );
127     while (hwndChild)
128     {
129         if( IsIconic( hwndChild ) )
130         {
131             WINPOS_ShowIconTitle( hwndChild, FALSE );
132
133             SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
134                             y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
135                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
136             if( IsWindow(hwndChild) )
137                 WINPOS_ShowIconTitle(hwndChild , TRUE );
138
139             if (x <= rectParent.right - xspacing) x += xspacing;
140             else
141             {
142                 x = rectParent.left;
143                 y -= yspacing;
144             }
145         }
146         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
147     }
148     return yspacing;
149 }
150
151
152 /***********************************************************************
153  *              SwitchToThisWindow (USER32.@)
154  */
155 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
156 {
157     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
158 }
159
160
161 /***********************************************************************
162  *              GetWindowRect (USER32.@)
163  */
164 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
165 {
166     BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
167     if (ret)
168     {
169         MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
170         TRACE( "hwnd %p (%ld,%ld)-(%ld,%ld)\n",
171                hwnd, rect->left, rect->top, rect->right, rect->bottom);
172     }
173     return ret;
174 }
175
176
177 /***********************************************************************
178  *              GetWindowRgn (USER32.@)
179  */
180 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
181 {
182     int nRet = ERROR;
183     NTSTATUS status;
184     HRGN win_rgn = 0;
185     RGNDATA *data;
186     size_t size = 256;
187
188     do
189     {
190         if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 )))
191         {
192             SetLastError( ERROR_OUTOFMEMORY );
193             return ERROR;
194         }
195         SERVER_START_REQ( get_window_region )
196         {
197             req->window = hwnd;
198             wine_server_set_reply( req, data->Buffer, size );
199             if (!(status = wine_server_call( req )))
200             {
201                 size_t reply_size = wine_server_reply_size( reply );
202                 if (reply_size)
203                 {
204                     data->rdh.dwSize   = sizeof(data->rdh);
205                     data->rdh.iType    = RDH_RECTANGLES;
206                     data->rdh.nCount   = reply_size / sizeof(RECT);
207                     data->rdh.nRgnSize = reply_size;
208                     win_rgn = ExtCreateRegion( NULL, size, data );
209                 }
210             }
211             else size = reply->total_size;
212         }
213         SERVER_END_REQ;
214         HeapFree( GetProcessHeap(), 0, data );
215     } while (status == STATUS_BUFFER_OVERFLOW);
216
217     if (status) SetLastError( RtlNtStatusToDosError(status) );
218     else if (win_rgn)
219     {
220         nRet = CombineRgn( hrgn, win_rgn, 0, RGN_COPY );
221         DeleteObject( win_rgn );
222     }
223     return nRet;
224 }
225
226
227 /***********************************************************************
228  *              SetWindowRgn (USER32.@)
229  */
230 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
231 {
232     static const RECT empty_rect;
233     BOOL ret;
234
235     if (hrgn)
236     {
237         RGNDATA *data;
238         DWORD size;
239
240         if (!(size = GetRegionData( hrgn, 0, NULL ))) return FALSE;
241         if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
242         if (!GetRegionData( hrgn, size, data ))
243         {
244             HeapFree( GetProcessHeap(), 0, data );
245             return FALSE;
246         }
247         SERVER_START_REQ( set_window_region )
248         {
249             req->window = hwnd;
250             if (data->rdh.nCount)
251                 wine_server_add_data( req, data->Buffer, data->rdh.nCount * sizeof(RECT) );
252             else
253                 wine_server_add_data( req, &empty_rect, sizeof(empty_rect) );
254             ret = !wine_server_call_err( req );
255         }
256         SERVER_END_REQ;
257     }
258     else  /* clear existing region */
259     {
260         SERVER_START_REQ( set_window_region )
261         {
262             req->window = hwnd;
263             ret = !wine_server_call_err( req );
264         }
265         SERVER_END_REQ;
266     }
267
268     if (ret && USER_Driver.pSetWindowRgn)
269         ret = USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
270
271     if (ret && bRedraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
272     return ret;
273 }
274
275
276 /***********************************************************************
277  *              GetClientRect (USER32.@)
278  */
279 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
280 {
281     BOOL ret;
282
283     if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
284     {
285         rect->right -= rect->left;
286         rect->bottom -= rect->top;
287         rect->left = rect->top = 0;
288     }
289     return ret;
290 }
291
292
293 /*******************************************************************
294  *              ClientToScreen (USER32.@)
295  */
296 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
297 {
298     MapWindowPoints( hwnd, 0, lppnt, 1 );
299     return TRUE;
300 }
301
302
303 /*******************************************************************
304  *              ScreenToClient (USER32.@)
305  */
306 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
307 {
308     MapWindowPoints( 0, hwnd, lppnt, 1 );
309     return TRUE;
310 }
311
312
313 /***********************************************************************
314  *           list_children_from_point
315  *
316  * Get the list of children that can contain point from the server.
317  * Point is in screen coordinates.
318  * Returned list must be freed by caller.
319  */
320 static HWND *list_children_from_point( HWND hwnd, POINT pt )
321 {
322     HWND *list;
323     int size = 32;
324
325     for (;;)
326     {
327         int count = 0;
328
329         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
330
331         SERVER_START_REQ( get_window_children_from_point )
332         {
333             req->parent = hwnd;
334             req->x = pt.x;
335             req->y = pt.y;
336             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
337             if (!wine_server_call( req )) count = reply->count;
338         }
339         SERVER_END_REQ;
340         if (count && count < size)
341         {
342             list[count] = 0;
343             return list;
344         }
345         HeapFree( GetProcessHeap(), 0, list );
346         if (!count) break;
347         size = count + 1;  /* restart with a large enough buffer */
348     }
349     return NULL;
350 }
351
352
353 /***********************************************************************
354  *           WINPOS_WindowFromPoint
355  *
356  * Find the window and hittest for a given point.
357  */
358 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
359 {
360     int i, res;
361     HWND ret, *list;
362
363     if (!hwndScope) hwndScope = GetDesktopWindow();
364
365     *hittest = HTNOWHERE;
366
367     if (!(list = list_children_from_point( hwndScope, pt ))) return 0;
368
369     /* now determine the hittest */
370
371     for (i = 0; list[i]; i++)
372     {
373         LONG style = GetWindowLongW( list[i], GWL_STYLE );
374
375         /* If window is minimized or disabled, return at once */
376         if (style & WS_MINIMIZE)
377         {
378             *hittest = HTCAPTION;
379             break;
380         }
381         if (style & WS_DISABLED)
382         {
383             *hittest = HTERROR;
384             break;
385         }
386         /* Send WM_NCCHITTEST (if same thread) */
387         if (!WIN_IsCurrentThread( list[i] ))
388         {
389             *hittest = HTCLIENT;
390             break;
391         }
392         res = SendMessageA( list[i], WM_NCHITTEST, 0, MAKELONG(pt.x,pt.y) );
393         if (res != HTTRANSPARENT)
394         {
395             *hittest = res;  /* Found the window */
396             break;
397         }
398         /* continue search with next window in z-order */
399     }
400     ret = list[i];
401     HeapFree( GetProcessHeap(), 0, list );
402     TRACE( "scope %p (%ld,%ld) returning %p\n", hwndScope, pt.x, pt.y, ret );
403     return ret;
404 }
405
406
407 /*******************************************************************
408  *              WindowFromPoint (USER32.@)
409  */
410 HWND WINAPI WindowFromPoint( POINT pt )
411 {
412     INT hittest;
413     return WINPOS_WindowFromPoint( 0, pt, &hittest );
414 }
415
416
417 /*******************************************************************
418  *              ChildWindowFromPoint (USER32.@)
419  */
420 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
421 {
422     return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
423 }
424
425 /*******************************************************************
426  *              ChildWindowFromPointEx (USER32.@)
427  */
428 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
429 {
430     /* pt is in the client coordinates */
431     HWND *list;
432     int i;
433     RECT rect;
434     HWND retvalue;
435
436     GetClientRect( hwndParent, &rect );
437     if (!PtInRect( &rect, pt )) return 0;
438     if (!(list = WIN_ListChildren( hwndParent ))) return hwndParent;
439
440     for (i = 0; list[i]; i++)
441     {
442         if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
443         if (!PtInRect( &rect, pt )) continue;
444         if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
445         {
446             LONG style = GetWindowLongW( list[i], GWL_STYLE );
447             if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
448             if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
449         }
450         if (uFlags & CWP_SKIPTRANSPARENT)
451         {
452             if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
453         }
454         break;
455     }
456     retvalue = list[i];
457     HeapFree( GetProcessHeap(), 0, list );
458     if (!retvalue) retvalue = hwndParent;
459     return retvalue;
460 }
461
462
463 /*******************************************************************
464  *         WINPOS_GetWinOffset
465  *
466  * Calculate the offset between the origin of the two windows. Used
467  * to implement MapWindowPoints.
468  */
469 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
470 {
471     WND * wndPtr;
472
473     offset->x = offset->y = 0;
474
475     /* Translate source window origin to screen coords */
476     if (hwndFrom)
477     {
478         HWND hwnd = hwndFrom;
479
480         while (hwnd)
481         {
482             if (hwnd == hwndTo) return;
483             if (!(wndPtr = WIN_GetPtr( hwnd )))
484             {
485                 ERR( "bad hwndFrom = %p\n", hwnd );
486                 return;
487             }
488             if (wndPtr == WND_DESKTOP) break;
489             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
490             offset->x += wndPtr->rectClient.left;
491             offset->y += wndPtr->rectClient.top;
492             hwnd = wndPtr->parent;
493             WIN_ReleasePtr( wndPtr );
494         }
495     }
496
497     /* Translate origin to destination window coords */
498     if (hwndTo)
499     {
500         HWND hwnd = hwndTo;
501
502         while (hwnd)
503         {
504             if (!(wndPtr = WIN_GetPtr( hwnd )))
505             {
506                 ERR( "bad hwndTo = %p\n", hwnd );
507                 return;
508             }
509             if (wndPtr == WND_DESKTOP) break;
510             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
511             offset->x -= wndPtr->rectClient.left;
512             offset->y -= wndPtr->rectClient.top;
513             hwnd = wndPtr->parent;
514             WIN_ReleasePtr( wndPtr );
515         }
516     }
517     return;
518
519  other_process:  /* one of the parents may belong to another process, do it the hard way */
520     offset->x = offset->y = 0;
521     SERVER_START_REQ( get_windows_offset )
522     {
523         req->from = hwndFrom;
524         req->to   = hwndTo;
525         if (!wine_server_call( req ))
526         {
527             offset->x = reply->x;
528             offset->y = reply->y;
529         }
530     }
531     SERVER_END_REQ;
532 }
533
534
535 /*******************************************************************
536  *              MapWindowPoints (USER.258)
537  */
538 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
539                                LPPOINT16 lppt, UINT16 count )
540 {
541     POINT offset;
542
543     WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
544     while (count--)
545     {
546         lppt->x += offset.x;
547         lppt->y += offset.y;
548         lppt++;
549     }
550 }
551
552
553 /*******************************************************************
554  *              MapWindowPoints (USER32.@)
555  */
556 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
557 {
558     POINT offset;
559
560     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
561     while (count--)
562     {
563         lppt->x += offset.x;
564         lppt->y += offset.y;
565         lppt++;
566     }
567     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
568 }
569
570
571 /***********************************************************************
572  *              IsIconic (USER32.@)
573  */
574 BOOL WINAPI IsIconic(HWND hWnd)
575 {
576     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
577 }
578
579
580 /***********************************************************************
581  *              IsZoomed (USER32.@)
582  */
583 BOOL WINAPI IsZoomed(HWND hWnd)
584 {
585     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
586 }
587
588
589 /*******************************************************************
590  *              AllowSetForegroundWindow (USER32.@)
591  */
592 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
593 {
594     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
595      * implemented, then fix this function. */
596     return TRUE;
597 }
598
599
600 /*******************************************************************
601  *              LockSetForegroundWindow (USER32.@)
602  */
603 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
604 {
605     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
606      * implemented, then fix this function. */
607     return TRUE;
608 }
609
610
611 /***********************************************************************
612  *              BringWindowToTop (USER32.@)
613  */
614 BOOL WINAPI BringWindowToTop( HWND hwnd )
615 {
616     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
617 }
618
619
620 /***********************************************************************
621  *              MoveWindow (USER32.@)
622  */
623 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
624                             BOOL repaint )
625 {
626     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
627     if (!repaint) flags |= SWP_NOREDRAW;
628     TRACE("%p %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
629     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
630 }
631
632 /***********************************************************************
633  *           WINPOS_InitInternalPos
634  */
635 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd )
636 {
637     LPINTERNALPOS lpPos = GetPropA( wnd->hwndSelf, atomInternalPos );
638     if( !lpPos )
639     {
640         /* this happens when the window is minimized/maximized
641          * for the first time (rectWindow is not adjusted yet) */
642
643         lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
644         if( !lpPos ) return NULL;
645
646         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
647         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
648         lpPos->rectNormal.left   = wnd->rectWindow.left;
649         lpPos->rectNormal.top    = wnd->rectWindow.top;
650         lpPos->rectNormal.right  = wnd->rectWindow.right;
651         lpPos->rectNormal.bottom = wnd->rectWindow.bottom;
652         lpPos->ptIconPos.x = lpPos->ptIconPos.y = -1;
653         lpPos->ptMaxPos.x = lpPos->ptMaxPos.y = -1;
654     }
655
656     if( wnd->dwStyle & WS_MINIMIZE )
657     {
658         lpPos->ptIconPos.x = wnd->rectWindow.left;
659         lpPos->ptIconPos.y = wnd->rectWindow.top;
660     }
661     else if( wnd->dwStyle & WS_MAXIMIZE )
662     {
663         lpPos->ptMaxPos.x = wnd->rectWindow.left;
664         lpPos->ptMaxPos.y = wnd->rectWindow.top;
665     }
666     else
667     {
668         lpPos->rectNormal.left   = wnd->rectWindow.left;
669         lpPos->rectNormal.top    = wnd->rectWindow.top;
670         lpPos->rectNormal.right  = wnd->rectWindow.right;
671         lpPos->rectNormal.bottom = wnd->rectWindow.bottom;
672     }
673     return lpPos;
674 }
675
676 /***********************************************************************
677  *           WINPOS_RedrawIconTitle
678  */
679 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
680 {
681     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
682     if( lpPos )
683     {
684         if( lpPos->hwndIconTitle )
685         {
686             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
687             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
688             return TRUE;
689         }
690     }
691     return FALSE;
692 }
693
694 /***********************************************************************
695  *           WINPOS_ShowIconTitle
696  */
697 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
698 {
699     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
700
701     if (lpPos && !GetPropA( hwnd, "__wine_x11_managed" ))
702     {
703         HWND title = lpPos->hwndIconTitle;
704
705         TRACE("%p %i\n", hwnd, (bShow != 0) );
706
707         if( !title )
708             lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
709         if( bShow )
710         {
711             if (!IsWindowVisible(title))
712             {
713                 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
714                 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
715                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
716             }
717         }
718         else ShowWindow( title, SW_HIDE );
719     }
720     return FALSE;
721 }
722
723 /*******************************************************************
724  *           WINPOS_GetMinMaxInfo
725  *
726  * Get the minimized and maximized information for a window.
727  */
728 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
729                            POINT *minTrack, POINT *maxTrack )
730 {
731     LPINTERNALPOS lpPos;
732     MINMAXINFO MinMax;
733     INT xinc, yinc;
734     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
735     LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
736     RECT rc;
737
738     /* Compute default values */
739
740     GetWindowRect(hwnd, &rc);
741     MinMax.ptReserved.x = rc.left;
742     MinMax.ptReserved.y = rc.top;
743
744     if (style & WS_CHILD)
745     {
746         if ((style & WS_CAPTION) == WS_CAPTION)
747             style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
748
749         GetClientRect(GetAncestor(hwnd,GA_PARENT), &rc);
750         AdjustWindowRectEx(&rc, style, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
751
752         /* avoid calculating this twice */
753         style &= ~(WS_DLGFRAME | WS_BORDER | WS_THICKFRAME);
754
755         MinMax.ptMaxSize.x = rc.right - rc.left;
756         MinMax.ptMaxSize.y = rc.bottom - rc.top;
757     }
758     else
759     {
760         MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
761         MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
762     }
763     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
764     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
765     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN) + 2*GetSystemMetrics(SM_CXFRAME);
766     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN) + 2*GetSystemMetrics(SM_CYFRAME);
767
768     if (HAS_DLGFRAME( style, exstyle ))
769     {
770         xinc = GetSystemMetrics(SM_CXDLGFRAME);
771         yinc = GetSystemMetrics(SM_CYDLGFRAME);
772     }
773     else
774     {
775         xinc = yinc = 0;
776         if (HAS_THICKFRAME(style))
777         {
778             xinc += GetSystemMetrics(SM_CXFRAME);
779             yinc += GetSystemMetrics(SM_CYFRAME);
780         }
781         if (style & WS_BORDER)
782         {
783             xinc += GetSystemMetrics(SM_CXBORDER);
784             yinc += GetSystemMetrics(SM_CYBORDER);
785         }
786     }
787     MinMax.ptMaxSize.x += 2 * xinc;
788     MinMax.ptMaxSize.y += 2 * yinc;
789
790     lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
791     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
792     {
793         MinMax.ptMaxPosition.x = lpPos->ptMaxPos.x;
794         MinMax.ptMaxPosition.y = lpPos->ptMaxPos.y;
795     }
796     else
797     {
798         MinMax.ptMaxPosition.x = -xinc;
799         MinMax.ptMaxPosition.y = -yinc;
800     }
801
802     SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
803
804       /* Some sanity checks */
805
806     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
807                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
808                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
809                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
810                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
811     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
812                                    MinMax.ptMinTrackSize.x );
813     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
814                                    MinMax.ptMinTrackSize.y );
815
816     if (maxSize) *maxSize = MinMax.ptMaxSize;
817     if (maxPos) *maxPos = MinMax.ptMaxPosition;
818     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
819     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
820 }
821
822 /***********************************************************************
823  *              ShowWindowAsync (USER32.@)
824  *
825  * doesn't wait; returns immediately.
826  * used by threads to toggle windows in other (possibly hanging) threads
827  */
828 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
829 {
830     HWND full_handle;
831
832     if (is_broadcast(hwnd))
833     {
834         SetLastError( ERROR_INVALID_PARAMETER );
835         return FALSE;
836     }
837
838     if ((full_handle = WIN_IsCurrentThread( hwnd )))
839     {
840         if (USER_Driver.pShowWindow)
841             return USER_Driver.pShowWindow( full_handle, cmd );
842         return FALSE;
843     }
844     return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
845 }
846
847
848 /***********************************************************************
849  *              ShowWindow (USER32.@)
850  */
851 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
852 {
853     HWND full_handle;
854
855     if (is_broadcast(hwnd))
856     {
857         SetLastError( ERROR_INVALID_PARAMETER );
858         return FALSE;
859     }
860     if ((full_handle = WIN_IsCurrentThread( hwnd )))
861     {
862         if (USER_Driver.pShowWindow)
863             return USER_Driver.pShowWindow( full_handle, cmd );
864         return FALSE;
865     }
866     return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
867 }
868
869
870 /***********************************************************************
871  *              GetInternalWindowPos (USER32.@)
872  */
873 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
874                                       LPPOINT ptIcon )
875 {
876     WINDOWPLACEMENT wndpl;
877     if (GetWindowPlacement( hwnd, &wndpl ))
878     {
879         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
880         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
881         return wndpl.showCmd;
882     }
883     return 0;
884 }
885
886
887 /***********************************************************************
888  *              GetWindowPlacement (USER32.@)
889  *
890  * Win95:
891  * Fails if wndpl->length of Win95 (!) apps is invalid.
892  */
893 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
894 {
895     WND *pWnd = WIN_GetPtr( hwnd );
896     LPINTERNALPOS lpPos;
897
898     if (!pWnd || pWnd == WND_DESKTOP) return FALSE;
899     if (pWnd == WND_OTHER_PROCESS)
900     {
901         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
902         return FALSE;
903     }
904
905     lpPos = WINPOS_InitInternalPos( pWnd );
906     wndpl->length  = sizeof(*wndpl);
907     if( pWnd->dwStyle & WS_MINIMIZE )
908         wndpl->showCmd = SW_SHOWMINIMIZED;
909     else
910         wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
911     if( pWnd->flags & WIN_RESTORE_MAX )
912         wndpl->flags = WPF_RESTORETOMAXIMIZED;
913     else
914         wndpl->flags = 0;
915     wndpl->ptMinPosition.x = lpPos->ptIconPos.x;
916     wndpl->ptMinPosition.y = lpPos->ptIconPos.y;
917     wndpl->ptMaxPosition.x = lpPos->ptMaxPos.x;
918     wndpl->ptMaxPosition.y = lpPos->ptMaxPos.y;
919     wndpl->rcNormalPosition.left   = lpPos->rectNormal.left;
920     wndpl->rcNormalPosition.top    = lpPos->rectNormal.top;
921     wndpl->rcNormalPosition.right  = lpPos->rectNormal.right;
922     wndpl->rcNormalPosition.bottom = lpPos->rectNormal.bottom;
923     WIN_ReleasePtr( pWnd );
924     return TRUE;
925 }
926
927
928 /***********************************************************************
929  *           WINPOS_SetPlacement
930  */
931 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
932 {
933     LPINTERNALPOS lpPos;
934     DWORD style;
935     WND *pWnd = WIN_GetPtr( hwnd );
936
937     if (!pWnd || pWnd == WND_OTHER_PROCESS || pWnd == WND_DESKTOP) return FALSE;
938     lpPos = WINPOS_InitInternalPos( pWnd );
939
940     if( flags & PLACE_MIN )
941     {
942         lpPos->ptIconPos.x = wndpl->ptMinPosition.x;
943         lpPos->ptIconPos.y = wndpl->ptMinPosition.y;
944     }
945     if( flags & PLACE_MAX )
946     {
947         lpPos->ptMaxPos.x = wndpl->ptMaxPosition.x;
948         lpPos->ptMaxPos.y = wndpl->ptMaxPosition.y;
949     }
950     if( flags & PLACE_RECT)
951     {
952         lpPos->rectNormal.left   = wndpl->rcNormalPosition.left;
953         lpPos->rectNormal.top    = wndpl->rcNormalPosition.top;
954         lpPos->rectNormal.right  = wndpl->rcNormalPosition.right;
955         lpPos->rectNormal.bottom = wndpl->rcNormalPosition.bottom;
956     }
957
958     style = pWnd->dwStyle;
959     WIN_ReleasePtr( pWnd );
960
961     if( style & WS_MINIMIZE )
962     {
963         WINPOS_ShowIconTitle( hwnd, FALSE );
964         if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
965             SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
966                           0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
967     }
968     else if( style & WS_MAXIMIZE )
969     {
970         if( !EMPTYPOINT(lpPos->ptMaxPos) )
971             SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
972                           0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
973     }
974     else if( flags & PLACE_RECT )
975         SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
976                       lpPos->rectNormal.right - lpPos->rectNormal.left,
977                       lpPos->rectNormal.bottom - lpPos->rectNormal.top,
978                       SWP_NOZORDER | SWP_NOACTIVATE );
979
980     ShowWindow( hwnd, wndpl->showCmd );
981
982     if (IsIconic( hwnd ))
983     {
984         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE) WINPOS_ShowIconTitle( hwnd, TRUE );
985
986         /* SDK: ...valid only the next time... */
987         if( wndpl->flags & WPF_RESTORETOMAXIMIZED )
988         {
989             pWnd = WIN_GetPtr( hwnd );
990             if (pWnd && pWnd != WND_OTHER_PROCESS)
991             {
992                 pWnd->flags |= WIN_RESTORE_MAX;
993                 WIN_ReleasePtr( pWnd );
994             }
995         }
996     }
997     return TRUE;
998 }
999
1000
1001 /***********************************************************************
1002  *              SetWindowPlacement (USER32.@)
1003  *
1004  * Win95:
1005  * Fails if wndpl->length of Win95 (!) apps is invalid.
1006  */
1007 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
1008 {
1009     if (!wpl) return FALSE;
1010     return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1011 }
1012
1013
1014 /***********************************************************************
1015  *              AnimateWindow (USER32.@)
1016  *              Shows/Hides a window with an animation
1017  *              NO ANIMATION YET
1018  */
1019 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1020 {
1021         FIXME("partial stub\n");
1022
1023         /* If trying to show/hide and it's already   *
1024          * shown/hidden or invalid window, fail with *
1025          * invalid parameter                         */
1026         if(!IsWindow(hwnd) ||
1027            (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1028            (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1029         {
1030                 SetLastError(ERROR_INVALID_PARAMETER);
1031                 return FALSE;
1032         }
1033
1034         ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1035
1036         return TRUE;
1037 }
1038
1039 /***********************************************************************
1040  *              SetInternalWindowPos (USER32.@)
1041  */
1042 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1043                                     LPRECT rect, LPPOINT pt )
1044 {
1045     if( IsWindow(hwnd) )
1046     {
1047         WINDOWPLACEMENT wndpl;
1048         UINT flags;
1049
1050         wndpl.length  = sizeof(wndpl);
1051         wndpl.showCmd = showCmd;
1052         wndpl.flags = flags = 0;
1053
1054         if( pt )
1055         {
1056             flags |= PLACE_MIN;
1057             wndpl.flags |= WPF_SETMINPOSITION;
1058             wndpl.ptMinPosition = *pt;
1059         }
1060         if( rect )
1061         {
1062             flags |= PLACE_RECT;
1063             wndpl.rcNormalPosition = *rect;
1064         }
1065         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1066     }
1067 }
1068
1069
1070 /*******************************************************************
1071  *         can_activate_window
1072  *
1073  * Check if we can activate the specified window.
1074  */
1075 static BOOL can_activate_window( HWND hwnd )
1076 {
1077     LONG style;
1078
1079     if (!hwnd) return FALSE;
1080     style = GetWindowLongW( hwnd, GWL_STYLE );
1081     if (!(style & WS_VISIBLE)) return FALSE;
1082     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
1083     return !(style & WS_DISABLED);
1084 }
1085
1086
1087 /*******************************************************************
1088  *         WINPOS_ActivateOtherWindow
1089  *
1090  *  Activates window other than pWnd.
1091  */
1092 void WINPOS_ActivateOtherWindow(HWND hwnd)
1093 {
1094     HWND hwndTo, fg;
1095
1096     if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) && (hwndTo = GetWindow( hwnd, GW_OWNER )))
1097     {
1098         hwndTo = GetAncestor( hwndTo, GA_ROOT );
1099         if (can_activate_window( hwndTo )) goto done;
1100     }
1101
1102     hwndTo = hwnd;
1103     for (;;)
1104     {
1105         if (!(hwndTo = GetWindow( hwndTo, GW_HWNDNEXT ))) break;
1106         if (can_activate_window( hwndTo )) break;
1107     }
1108
1109  done:
1110     fg = GetForegroundWindow();
1111     TRACE("win = %p fg = %p\n", hwndTo, fg);
1112     if (!fg || (hwnd == fg))
1113     {
1114         if (SetForegroundWindow( hwndTo )) return;
1115     }
1116     if (!SetActiveWindow( hwndTo )) SetActiveWindow(0);
1117 }
1118
1119
1120 /***********************************************************************
1121  *           WINPOS_HandleWindowPosChanging
1122  *
1123  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1124  */
1125 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1126 {
1127     POINT minTrack, maxTrack;
1128     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1129
1130     if (winpos->flags & SWP_NOSIZE) return 0;
1131     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1132     {
1133         WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1134         if (winpos->cx > maxTrack.x) winpos->cx = maxTrack.x;
1135         if (winpos->cy > maxTrack.y) winpos->cy = maxTrack.y;
1136         if (!(style & WS_MINIMIZE))
1137         {
1138             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1139             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1140         }
1141     }
1142     return 0;
1143 }
1144
1145
1146 /***********************************************************************
1147  *           dump_winpos_flags
1148  */
1149 static void dump_winpos_flags(UINT flags)
1150 {
1151     TRACE("flags:");
1152     if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE");
1153     if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE");
1154     if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER");
1155     if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW");
1156     if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE");
1157     if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED");
1158     if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW");
1159     if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW");
1160     if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS");
1161     if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER");
1162     if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING");
1163     if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE");
1164     if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS");
1165
1166 #define DUMPED_FLAGS \
1167     (SWP_NOSIZE | \
1168     SWP_NOMOVE | \
1169     SWP_NOZORDER | \
1170     SWP_NOREDRAW | \
1171     SWP_NOACTIVATE | \
1172     SWP_FRAMECHANGED | \
1173     SWP_SHOWWINDOW | \
1174     SWP_HIDEWINDOW | \
1175     SWP_NOCOPYBITS | \
1176     SWP_NOOWNERZORDER | \
1177     SWP_NOSENDCHANGING | \
1178     SWP_DEFERERASE | \
1179     SWP_ASYNCWINDOWPOS)
1180
1181     if(flags & ~DUMPED_FLAGS) TRACE(" %08x", flags & ~DUMPED_FLAGS);
1182     TRACE("\n");
1183 #undef DUMPED_FLAGS
1184 }
1185
1186 /***********************************************************************
1187  *              SetWindowPos (USER32.@)
1188  */
1189 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1190                           INT x, INT y, INT cx, INT cy, UINT flags )
1191 {
1192     WINDOWPOS winpos;
1193
1194     TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1195           hwnd, hwndInsertAfter, x, y, cx, cy, flags);
1196     if(TRACE_ON(win)) dump_winpos_flags(flags);
1197
1198     if (is_broadcast(hwnd))
1199     {
1200         SetLastError( ERROR_INVALID_PARAMETER );
1201         return FALSE;
1202     }
1203
1204     winpos.hwnd = WIN_GetFullHandle(hwnd);
1205     winpos.hwndInsertAfter = WIN_GetFullHandle(hwndInsertAfter);
1206     winpos.x = x;
1207     winpos.y = y;
1208     winpos.cx = cx;
1209     winpos.cy = cy;
1210     winpos.flags = flags;
1211     if (WIN_IsCurrentThread( hwnd ))
1212     {
1213         if (USER_Driver.pSetWindowPos)
1214             return USER_Driver.pSetWindowPos( &winpos );
1215         return FALSE;
1216     }
1217     return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1218 }
1219
1220
1221 /***********************************************************************
1222  *              BeginDeferWindowPos (USER32.@)
1223  */
1224 HDWP WINAPI BeginDeferWindowPos( INT count )
1225 {
1226     HDWP handle;
1227     DWP *pDWP;
1228
1229     TRACE("%d\n", count);
1230
1231     if (count < 0)
1232     {
1233         SetLastError(ERROR_INVALID_PARAMETER);
1234         return 0;
1235     }
1236     /* Windows allows zero count, in which case it allocates context for 8 moves */
1237     if (count == 0) count = 8;
1238
1239     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1240     if (!handle) return 0;
1241     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1242     pDWP->actualCount    = 0;
1243     pDWP->suggestedCount = count;
1244     pDWP->valid          = TRUE;
1245     pDWP->wMagic         = DWP_MAGIC;
1246     pDWP->hwndParent     = 0;
1247
1248     TRACE("returning hdwp %p\n", handle);
1249     return handle;
1250 }
1251
1252
1253 /***********************************************************************
1254  *              DeferWindowPos (USER32.@)
1255  */
1256 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1257                                 INT x, INT y, INT cx, INT cy,
1258                                 UINT flags )
1259 {
1260     DWP *pDWP;
1261     int i;
1262     HDWP newhdwp = hdwp,retvalue;
1263
1264     TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1265           hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
1266
1267     hwnd = WIN_GetFullHandle( hwnd );
1268     if (hwnd == GetDesktopWindow()) return 0;
1269
1270     if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1271
1272     USER_Lock();
1273
1274     for (i = 0; i < pDWP->actualCount; i++)
1275     {
1276         if (pDWP->winPos[i].hwnd == hwnd)
1277         {
1278               /* Merge with the other changes */
1279             if (!(flags & SWP_NOZORDER))
1280             {
1281                 pDWP->winPos[i].hwndInsertAfter = WIN_GetFullHandle(hwndAfter);
1282             }
1283             if (!(flags & SWP_NOMOVE))
1284             {
1285                 pDWP->winPos[i].x = x;
1286                 pDWP->winPos[i].y = y;
1287             }
1288             if (!(flags & SWP_NOSIZE))
1289             {
1290                 pDWP->winPos[i].cx = cx;
1291                 pDWP->winPos[i].cy = cy;
1292             }
1293             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1294                                                SWP_NOZORDER | SWP_NOREDRAW |
1295                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
1296                                                SWP_NOOWNERZORDER);
1297             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1298                                               SWP_FRAMECHANGED);
1299             retvalue = hdwp;
1300             goto END;
1301         }
1302     }
1303     if (pDWP->actualCount >= pDWP->suggestedCount)
1304     {
1305         newhdwp = USER_HEAP_REALLOC( hdwp,
1306                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1307         if (!newhdwp)
1308         {
1309             retvalue = 0;
1310             goto END;
1311         }
1312         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1313         pDWP->suggestedCount++;
1314     }
1315     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1316     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1317     pDWP->winPos[pDWP->actualCount].x = x;
1318     pDWP->winPos[pDWP->actualCount].y = y;
1319     pDWP->winPos[pDWP->actualCount].cx = cx;
1320     pDWP->winPos[pDWP->actualCount].cy = cy;
1321     pDWP->winPos[pDWP->actualCount].flags = flags;
1322     pDWP->actualCount++;
1323     retvalue = newhdwp;
1324 END:
1325     USER_Unlock();
1326     return retvalue;
1327 }
1328
1329
1330 /***********************************************************************
1331  *              EndDeferWindowPos (USER32.@)
1332  */
1333 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1334 {
1335     DWP *pDWP;
1336     WINDOWPOS *winpos;
1337     BOOL res = TRUE;
1338     int i;
1339
1340     TRACE("%p\n", hdwp);
1341
1342     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1343     if (!pDWP) return FALSE;
1344     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1345     {
1346         if (!USER_Driver.pSetWindowPos || !(res = USER_Driver.pSetWindowPos( winpos ))) break;
1347     }
1348     USER_HEAP_FREE( hdwp );
1349     return res;
1350 }
1351
1352
1353 /***********************************************************************
1354  *              TileChildWindows (USER.199)
1355  */
1356 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1357 {
1358     FIXME("(%04x, %d): stub\n", parent, action);
1359 }
1360
1361 /***********************************************************************
1362  *              CascadeChildWindows (USER.198)
1363  */
1364 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1365 {
1366     FIXME("(%04x, %d): stub\n", parent, action);
1367 }