Remove Get/SetBeepActive from USER driver and manage it locally inside
[wine] / dlls / ttydrv / wnd.c
1 /*
2  * TTY window driver
3  *
4  * Copyright 1998,1999 Patrik Stridvall
5  */
6
7 #include "config.h"
8
9 #include "gdi.h"
10 #include "ttydrv.h"
11 #include "region.h"
12 #include "win.h"
13 #include "winpos.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(ttydrv);
17
18 WND_DRIVER TTYDRV_WND_Driver =
19 {
20   TTYDRV_WND_ForceWindowRaise,
21   TTYDRV_WND_PreSizeMove,
22   TTYDRV_WND_PostSizeMove,
23   TTYDRV_WND_ScrollWindow,
24   TTYDRV_WND_SetHostAttr
25 };
26
27 #define SWP_AGG_NOGEOMETRYCHANGE \
28     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
29 #define SWP_AGG_NOPOSCHANGE \
30     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
31 #define SWP_AGG_STATUSFLAGS \
32     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
33
34 /**********************************************************************
35  *              CreateWindow   (TTYDRV.@)
36  */
37 BOOL TTYDRV_CreateWindow( HWND hwnd )
38 {
39 #ifdef WINE_CURSES
40     WND *wndPtr = WIN_FindWndPtr( hwnd );
41     WINDOW *window;
42     INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
43
44     TRACE("(%x)\n", hwnd);
45
46     /* Only create top-level windows */
47     if (wndPtr->dwStyle & WS_CHILD)
48     {
49         WIN_ReleaseWndPtr( wndPtr );
50         return TRUE;
51     }
52
53     if (!wndPtr->parent)  /* desktop */
54         window = root_window;
55     else
56     {
57         int x = wndPtr->rectWindow.left;
58         int y = wndPtr->rectWindow.top;
59         int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
60         int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
61
62         window = subwin( root_window, cy/cellHeight, cx/cellWidth,
63                          y/cellHeight, x/cellWidth);
64         werase(window);
65         wrefresh(window);
66     }
67     wndPtr->pDriverData = window;
68     WIN_ReleaseWndPtr( wndPtr );
69 #else /* defined(WINE_CURSES) */
70     FIXME("(%x): stub\n", hwnd);
71 #endif /* defined(WINE_CURSES) */
72     return TRUE;
73 }
74
75 /***********************************************************************
76  *              DestroyWindow   (TTYDRV.@)
77  */
78 BOOL TTYDRV_DestroyWindow( HWND hwnd )
79 {
80 #ifdef WINE_CURSES
81     WND *wndPtr = WIN_FindWndPtr( hwnd );
82     WINDOW *window = wndPtr->pDriverData;
83
84     TRACE("(%x)\n", hwnd);
85
86     if (window && window != root_window) delwin(window);
87     wndPtr->pDriverData = NULL;
88     WIN_ReleaseWndPtr( wndPtr );
89 #else /* defined(WINE_CURSES) */
90     FIXME("(%x): stub\n", hwnd);
91 #endif /* defined(WINE_CURSES) */
92     return TRUE;
93 }
94
95 /***********************************************************************
96  *              TTYDRV_WND_ForceWindowRaise
97  */
98 void TTYDRV_WND_ForceWindowRaise(WND *wndPtr)
99 {
100   FIXME("(%p): stub\n", wndPtr);
101 }
102
103 /*****************************************************************
104  *              TTYDRV_WND_PreSizeMove
105  */
106 void TTYDRV_WND_PreSizeMove(WND *wndPtr)
107 {
108   FIXME("(%p): stub\n", wndPtr);
109 }
110
111 /*****************************************************************
112  *               TTYDRV_WND_PostSizeMove
113  */
114 void TTYDRV_WND_PostSizeMove(WND *wndPtr)
115 {
116   FIXME("(%p): stub\n", wndPtr);
117 }
118
119 /*****************************************************************
120  *               TTYDRV_WND_ScrollWindow
121  */
122 void TTYDRV_WND_ScrollWindow( WND *wndPtr, HDC hdc, INT dx, INT dy, 
123                               const RECT *clipRect, BOOL bUpdate)
124 {
125   FIXME("(%p, %x, %d, %d, %p, %d): stub\n", 
126         wndPtr, hdc, dx, dy, clipRect, bUpdate);
127 }
128
129 /***********************************************************************
130  *              TTYDRV_WND_SetHostAttr
131  */
132 BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
133 {
134   FIXME("(%p): stub\n", wndPtr);
135
136   return TRUE;
137 }
138
139
140 /***********************************************************************
141  *           DCE_OffsetVisRgn
142  *
143  * Change region from DC-origin relative coordinates to screen coords.
144  */
145
146 static void DCE_OffsetVisRgn( HDC hDC, HRGN hVisRgn )
147 {
148     DC *dc;
149     if (!(dc = DC_GetDCPtr( hDC ))) return;
150
151     OffsetRgn( hVisRgn, dc->DCOrgX, dc->DCOrgY );
152
153     GDI_ReleaseObj( hDC );
154 }
155
156
157 /***********************************************************************
158  *           DCE_GetVisRect
159  *
160  * Calculate the visible rectangle of a window (i.e. the client or
161  * window area clipped by the client area of all ancestors) in the
162  * corresponding coordinates. Return FALSE if the visible region is empty.
163  */
164 static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
165 {
166     *lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
167
168     if (wndPtr->dwStyle & WS_VISIBLE)
169     {
170         INT xoffset = lprect->left;
171         INT yoffset = lprect->top;
172
173         while ((wndPtr = WIN_LockWndPtr(wndPtr->parent)))
174         {
175             if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
176             {
177                 WIN_ReleaseWndPtr(wndPtr);
178                 goto fail;
179             }
180
181             xoffset += wndPtr->rectClient.left;
182             yoffset += wndPtr->rectClient.top;
183             OffsetRect( lprect, wndPtr->rectClient.left,
184                         wndPtr->rectClient.top );
185
186             if( (wndPtr->rectClient.left >= wndPtr->rectClient.right) ||
187                 (wndPtr->rectClient.top >= wndPtr->rectClient.bottom) ||
188                 (lprect->left >= wndPtr->rectClient.right) ||
189                 (lprect->right <= wndPtr->rectClient.left) ||
190                 (lprect->top >= wndPtr->rectClient.bottom) ||
191                 (lprect->bottom <= wndPtr->rectClient.top) )
192             {
193                 WIN_ReleaseWndPtr(wndPtr);
194                 goto fail;
195             }
196
197             lprect->left = max( lprect->left, wndPtr->rectClient.left );
198             lprect->right = min( lprect->right, wndPtr->rectClient.right );
199             lprect->top = max( lprect->top, wndPtr->rectClient.top );
200             lprect->bottom = min( lprect->bottom, wndPtr->rectClient.bottom );
201
202             WIN_ReleaseWndPtr(wndPtr);
203         }
204         OffsetRect( lprect, -xoffset, -yoffset );
205         return TRUE;
206     }
207
208 fail:
209     SetRectEmpty( lprect );
210     return FALSE;
211 }
212
213
214 /***********************************************************************
215  *           DCE_AddClipRects
216  *
217  * Go through the linked list of windows from pWndStart to pWndEnd,
218  * adding to the clip region the intersection of the target rectangle
219  * with an offset window rectangle.
220  */
221 static BOOL DCE_AddClipRects( WND *pWndStart, WND *pWndEnd,
222                               HRGN hrgnClip, LPRECT lpRect, int x, int y )
223 {
224     RECT rect;
225
226     for (WIN_LockWndPtr(pWndStart); (pWndStart && (pWndStart != pWndEnd)); WIN_UpdateWndPtr(&pWndStart,pWndStart->next))
227     {
228         if( !(pWndStart->dwStyle & WS_VISIBLE) ) continue;
229
230         rect.left = pWndStart->rectWindow.left + x;
231         rect.top = pWndStart->rectWindow.top + y;
232         rect.right = pWndStart->rectWindow.right + x;
233         rect.bottom = pWndStart->rectWindow.bottom + y;
234
235         if( IntersectRect( &rect, &rect, lpRect ))
236         {
237             if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break;
238         }
239     }
240     WIN_ReleaseWndPtr(pWndStart);
241     return (pWndStart == pWndEnd);
242 }
243
244
245 /***********************************************************************
246  *           DCE_GetVisRgn
247  *
248  * Return the visible region of a window, i.e. the client or window area
249  * clipped by the client area of all ancestors, and then optionally
250  * by siblings and children.
251  */
252 static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
253 {
254     HRGN hrgnVis = 0;
255     RECT rect;
256     WND *wndPtr = WIN_FindWndPtr( hwnd );
257     WND *childWnd = WIN_FindWndPtr( hwndChild );
258
259     /* Get visible rectangle and create a region with it. */
260
261     if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
262     {
263         if((hrgnVis = CreateRectRgnIndirect( &rect )))
264         {
265             HRGN hrgnClip = CreateRectRgn( 0, 0, 0, 0 );
266             INT xoffset, yoffset;
267
268             if( hrgnClip )
269             {
270                 /* Compute obscured region for the visible rectangle by 
271                  * clipping children, siblings, and ancestors. Note that
272                  * DCE_GetVisRect() returns a rectangle either in client
273                  * or in window coordinates (for DCX_WINDOW request). */
274
275                 if( (flags & DCX_CLIPCHILDREN) && wndPtr->child )
276                 {
277                     if( flags & DCX_WINDOW )
278                     {
279                         /* adjust offsets since child window rectangles are 
280                          * in client coordinates */
281
282                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
283                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
284                     }
285                     else
286                         xoffset = yoffset = 0;
287
288                     DCE_AddClipRects( wndPtr->child, NULL, hrgnClip, &rect, xoffset, yoffset );
289                 }
290
291                 /* We may need to clip children of child window, if a window with PARENTDC
292                  * class style and CLIPCHILDREN window style (like in Free Agent 16
293                  * preference dialogs) gets here, we take the region for the parent window
294                  * but apparently still need to clip the children of the child window... */
295
296                 if( (cflags & DCX_CLIPCHILDREN) && childWnd && childWnd->child )
297                 {
298                     if( flags & DCX_WINDOW )
299                     {
300                         /* adjust offsets since child window rectangles are 
301                          * in client coordinates */
302
303                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
304                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
305                     }
306                     else
307                         xoffset = yoffset = 0;
308
309                     /* client coordinates of child window */
310                     xoffset += childWnd->rectClient.left;
311                     yoffset += childWnd->rectClient.top;
312
313                     DCE_AddClipRects( childWnd->child, NULL, hrgnClip,
314                                       &rect, xoffset, yoffset );
315                 }
316
317                 /* sibling window rectangles are in client 
318                  * coordinates of the parent window */
319
320                 if (flags & DCX_WINDOW)
321                 {
322                     xoffset = -wndPtr->rectWindow.left;
323                     yoffset = -wndPtr->rectWindow.top;
324                 }
325                 else
326                 {
327                     xoffset = -wndPtr->rectClient.left;
328                     yoffset = -wndPtr->rectClient.top;
329                 }
330
331                 if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
332                     DCE_AddClipRects( wndPtr->parent->child,
333                                       wndPtr, hrgnClip, &rect, xoffset, yoffset );
334
335                 /* Clip siblings of all ancestors that have the
336                  * WS_CLIPSIBLINGS style
337                  */
338
339                 while (wndPtr->parent)
340                 {
341                     WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
342                     xoffset -= wndPtr->rectClient.left;
343                     yoffset -= wndPtr->rectClient.top;
344                     if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
345                     {
346                         DCE_AddClipRects( wndPtr->parent->child, wndPtr,
347                                           hrgnClip, &rect, xoffset, yoffset );
348                     }
349                 }
350
351                 /* Now once we've got a jumbo clip region we have
352                  * to substract it from the visible rectangle.
353                  */
354                 CombineRgn( hrgnVis, hrgnVis, hrgnClip, RGN_DIFF );
355                 DeleteObject( hrgnClip );
356             }
357             else
358             {
359                 DeleteObject( hrgnVis );
360                 hrgnVis = 0;
361             }
362         }
363     }
364     else
365         hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
366     WIN_ReleaseWndPtr(wndPtr);
367     WIN_ReleaseWndPtr(childWnd);
368     return hrgnVis;
369 }
370
371
372 /***********************************************************************
373  *              GetDC   (TTYDRV.@)
374  *
375  * Set the drawable, origin and dimensions for the DC associated to
376  * a given window.
377  */
378 BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
379 {
380     WND *wndPtr = WIN_FindWndPtr(hwnd);
381     DC *dc;
382     BOOL updateVisRgn;
383     HRGN hrgnVisible = 0;
384
385     if (!wndPtr) return FALSE;
386
387     if (!(dc = DC_GetDCPtr( hdc )))
388     {
389         WIN_ReleaseWndPtr( wndPtr );
390         return FALSE;
391     }
392
393     if(flags & DCX_WINDOW)
394     {
395         dc->DCOrgX = wndPtr->rectWindow.left;
396         dc->DCOrgY = wndPtr->rectWindow.top;
397     }
398     else
399     {
400         dc->DCOrgX = wndPtr->rectClient.left;
401         dc->DCOrgY = wndPtr->rectClient.top;
402     }
403     updateVisRgn = (dc->flags & DC_DIRTY) != 0;
404     GDI_ReleaseObj( hdc );
405
406     if (updateVisRgn)
407     {
408         if (flags & DCX_PARENTCLIP)
409         {
410             WND *parentPtr = WIN_LockWndPtr(wndPtr->parent);
411
412             if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
413             {
414                 DWORD dcxFlags;
415
416                 if( parentPtr->dwStyle & WS_CLIPSIBLINGS )
417                     dcxFlags = DCX_CLIPSIBLINGS | (flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
418                 else
419                     dcxFlags = flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
420
421                 hrgnVisible = DCE_GetVisRgn( parentPtr->hwndSelf, dcxFlags,
422                                              wndPtr->hwndSelf, flags );
423                 if( flags & DCX_WINDOW )
424                     OffsetRgn( hrgnVisible, -wndPtr->rectWindow.left,
425                                -wndPtr->rectWindow.top );
426                 else
427                     OffsetRgn( hrgnVisible, -wndPtr->rectClient.left,
428                                -wndPtr->rectClient.top );
429                 DCE_OffsetVisRgn( hdc, hrgnVisible );
430             }
431             else
432                 hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
433             WIN_ReleaseWndPtr(parentPtr);
434         }
435         else
436         {
437             hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
438             DCE_OffsetVisRgn( hdc, hrgnVisible );
439         }
440         SelectVisRgn16( hdc, hrgnVisible );
441     }
442
443     /* apply additional region operation (if any) */
444
445     if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
446     {
447         if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
448
449         TRACE("\tsaved VisRgn, clipRgn = %04x\n", hrgn);
450
451         SaveVisRgn16( hdc );
452         CombineRgn( hrgnVisible, hrgn, 0, RGN_COPY );
453         DCE_OffsetVisRgn( hdc, hrgnVisible );
454         CombineRgn( hrgnVisible, InquireVisRgn16( hdc ), hrgnVisible,
455                       (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
456         SelectVisRgn16( hdc, hrgnVisible );
457     }
458
459     if (hrgnVisible) DeleteObject( hrgnVisible );
460
461     WIN_ReleaseWndPtr( wndPtr );
462     return TRUE;
463 }
464
465
466 /***********************************************************************
467  *              SetWindowPos   (TTYDRV.@)
468  */
469 BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
470 {
471     WND *wndPtr;
472     RECT newWindowRect, newClientRect;
473     BOOL retvalue;
474     HWND hwndActive = GetForegroundWindow();
475
476     TRACE( "hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
477            winpos->hwnd, winpos->x, winpos->y,
478            winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
479
480     /* ------------------------------------------------------------------------ CHECKS */
481
482       /* Check window handle */
483
484     if (winpos->hwnd == GetDesktopWindow()) return FALSE;
485     if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
486
487     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n",
488           wndPtr->rectWindow.left, wndPtr->rectWindow.top,
489           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
490
491     /* Fix redundant flags */
492
493     if(wndPtr->dwStyle & WS_VISIBLE)
494         winpos->flags &= ~SWP_SHOWWINDOW;
495     else
496     {
497         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
498         winpos->flags &= ~SWP_HIDEWINDOW;
499     }
500
501     if ( winpos->cx < 0 ) winpos->cx = 0;
502     if ( winpos->cy < 0 ) winpos->cy = 0;
503
504     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
505         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
506         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
507
508     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
509         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
510
511     if (winpos->hwnd == hwndActive)
512         winpos->flags |= SWP_NOACTIVATE;   /* Already active */
513     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
514     {
515         if(!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
516         {
517             winpos->flags &= ~SWP_NOZORDER;
518             winpos->hwndInsertAfter = HWND_TOP;
519             goto Pos;
520         }
521     }
522
523     /* Check hwndInsertAfter */
524
525       /* FIXME: TOPMOST not supported yet */
526     if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
527         (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
528
529     /* hwndInsertAfter must be a sibling of the window */
530     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
531     {
532         WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
533
534         if( wnd ) {
535             if( wnd->parent != wndPtr->parent )
536             {
537                 retvalue = FALSE;
538                 WIN_ReleaseWndPtr(wnd);
539                 goto END;
540             }
541             /* don't need to change the Zorder of hwnd if it's already inserted
542              * after hwndInsertAfter or when inserting hwnd after itself.
543              */
544             if(( wnd->next == wndPtr ) || (winpos->hwnd == winpos->hwndInsertAfter))
545                 winpos->flags |= SWP_NOZORDER;
546         }
547         WIN_ReleaseWndPtr(wnd);
548     }
549
550  Pos:  /* ------------------------------------------------------------------------ MAIN part */
551
552       /* Send WM_WINDOWPOSCHANGING message */
553
554     if (!(winpos->flags & SWP_NOSENDCHANGING))
555         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)winpos );
556
557       /* Calculate new position and size */
558
559     newWindowRect = wndPtr->rectWindow;
560     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
561                                                     : wndPtr->rectClient;
562
563     if (!(winpos->flags & SWP_NOSIZE))
564     {
565         newWindowRect.right  = newWindowRect.left + winpos->cx;
566         newWindowRect.bottom = newWindowRect.top + winpos->cy;
567     }
568     if (!(winpos->flags & SWP_NOMOVE))
569     {
570         newWindowRect.left    = winpos->x;
571         newWindowRect.top     = winpos->y;
572         newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
573         newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
574
575         OffsetRect( &newClientRect, winpos->x - wndPtr->rectWindow.left,
576                     winpos->y - wndPtr->rectWindow.top );
577     }
578
579     if( winpos->hwndInsertAfter == HWND_TOP )
580         winpos->flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
581     else
582         if( winpos->hwndInsertAfter == HWND_BOTTOM )
583             winpos->flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
584         else
585             if( !(winpos->flags & SWP_NOZORDER) )
586                 if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
587                     winpos->flags |= SWP_NOZORDER;
588
589     /* Common operations */
590
591       /* Send WM_NCCALCSIZE message to get new client area */
592     if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
593     {
594          WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
595                                 &wndPtr->rectWindow, &wndPtr->rectClient,
596                                 winpos, &newClientRect );
597     }
598
599     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
600     {
601         if ( WIN_UnlinkWindow( winpos->hwnd ) )
602             WIN_LinkWindow( winpos->hwnd, winpos->hwndInsertAfter );
603     }
604
605     /* FIXME: actually do something with WVR_VALIDRECTS */
606
607     wndPtr->rectWindow = newWindowRect;
608     wndPtr->rectClient = newClientRect;
609
610     if( winpos->flags & SWP_SHOWWINDOW )
611     {
612         wndPtr->dwStyle |= WS_VISIBLE;
613     }
614     else if( winpos->flags & SWP_HIDEWINDOW )
615     {
616         wndPtr->dwStyle &= ~WS_VISIBLE;
617     }
618
619     /* ------------------------------------------------------------------------ FINAL */
620
621     /* repaint invalidated region (if any)
622      *
623      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
624      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
625      */
626
627     if( !(winpos->flags & SWP_NOREDRAW) )
628     {
629         RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
630                       RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN );
631         if (wndPtr->parent->hwndSelf == GetDesktopWindow() ||
632             wndPtr->parent->parent->hwndSelf == GetDesktopWindow())
633         {
634             RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
635                           RDW_ERASENOW | RDW_NOCHILDREN );
636         }
637     }
638
639     if (!(winpos->flags & SWP_NOACTIVATE))
640         WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
641
642       /* And last, send the WM_WINDOWPOSCHANGED message */
643
644     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
645
646     if ((((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
647           !(winpos->flags & SWP_NOSENDCHANGING)) )
648         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
649
650     retvalue = TRUE;
651  END:
652     WIN_ReleaseWndPtr(wndPtr);
653     return retvalue;
654 }