4 * Copyright 1998,1999 Patrik Stridvall
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.
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.
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
27 #include "wine/wingdi16.h"
28 #include "wine/server.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(ttydrv
);
33 #define SWP_AGG_NOGEOMETRYCHANGE \
34 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
35 #define SWP_AGG_NOPOSCHANGE \
36 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
37 #define SWP_AGG_STATUSFLAGS \
38 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
40 /***********************************************************************
41 * set_window_rectangles
43 * Set the window and client rectangles.
45 static void set_window_rectangles( HWND hwnd
, const RECT
*rectWindow
, const RECT
*rectClient
)
47 WND
*win
= WIN_GetPtr( hwnd
);
51 if (win
== WND_OTHER_PROCESS
)
53 if (IsWindow( hwnd
)) ERR( "cannot set rectangles of other process window %p\n", hwnd
);
56 SERVER_START_REQ( set_window_rectangles
)
59 req
->window
.left
= rectWindow
->left
;
60 req
->window
.top
= rectWindow
->top
;
61 req
->window
.right
= rectWindow
->right
;
62 req
->window
.bottom
= rectWindow
->bottom
;
63 req
->client
.left
= rectClient
->left
;
64 req
->client
.top
= rectClient
->top
;
65 req
->client
.right
= rectClient
->right
;
66 req
->client
.bottom
= rectClient
->bottom
;
67 ret
= !wine_server_call( req
);
72 win
->rectWindow
= *rectWindow
;
73 win
->rectClient
= *rectClient
;
75 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd
,
76 rectWindow
->left
, rectWindow
->top
, rectWindow
->right
, rectWindow
->bottom
,
77 rectClient
->left
, rectClient
->top
, rectClient
->right
, rectClient
->bottom
);
79 WIN_ReleasePtr( win
);
83 /**********************************************************************
84 * CreateWindow (TTYDRV.@)
86 BOOL
TTYDRV_CreateWindow( HWND hwnd
, CREATESTRUCTA
*cs
, BOOL unicode
)
92 WND
*wndPtr
= WIN_GetPtr( hwnd
);
94 TRACE("(%p)\n", hwnd
);
96 /* initialize the dimensions before sending WM_GETMINMAXINFO */
97 SetRect( &rect
, cs
->x
, cs
->y
, cs
->x
+ cs
->cx
, cs
->y
+ cs
->cy
);
98 set_window_rectangles( hwnd
, &rect
, &rect
);
100 if (!wndPtr
->parent
) /* desktop window */
102 wndPtr
->pDriverData
= root_window
;
103 WIN_ReleasePtr( wndPtr
);
108 /* Only create top-level windows */
109 if (!(wndPtr
->dwStyle
& WS_CHILD
))
112 const INT cellWidth
=8, cellHeight
=8; /* FIXME: Hardcoded */
114 int x
= wndPtr
->rectWindow
.left
;
115 int y
= wndPtr
->rectWindow
.top
;
116 int cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
117 int cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
119 window
= subwin( root_window
, cy
/cellHeight
, cx
/cellWidth
,
120 y
/cellHeight
, x
/cellWidth
);
123 wndPtr
->pDriverData
= window
;
125 #else /* defined(WINE_CURSES) */
126 FIXME("(%p): stub\n", hwnd
);
127 #endif /* defined(WINE_CURSES) */
128 WIN_ReleasePtr( wndPtr
);
130 /* Call the WH_CBT hook */
132 hwndLinkAfter
= ((cs
->style
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
) ? HWND_BOTTOM
: HWND_TOP
;
135 cbtc
.hwndInsertAfter
= hwndLinkAfter
;
136 if (HOOK_CallHooks( WH_CBT
, HCBT_CREATEWND
, (WPARAM
)hwnd
, (LPARAM
)&cbtc
, unicode
))
138 TRACE("CBT-hook returned !0\n");
144 ret
= SendMessageW( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
145 if (ret
) ret
= (SendMessageW( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
) != -1);
149 ret
= SendMessageA( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
150 if (ret
) ret
= (SendMessageA( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
) != -1);
155 /***********************************************************************
156 * DestroyWindow (TTYDRV.@)
158 BOOL
TTYDRV_DestroyWindow( HWND hwnd
)
161 WND
*wndPtr
= WIN_GetPtr( hwnd
);
162 WINDOW
*window
= wndPtr
->pDriverData
;
164 TRACE("(%p)\n", hwnd
);
166 if (window
&& window
!= root_window
) delwin(window
);
167 wndPtr
->pDriverData
= NULL
;
168 WIN_ReleasePtr( wndPtr
);
169 #else /* defined(WINE_CURSES) */
170 FIXME("(%p): stub\n", hwnd
);
171 #endif /* defined(WINE_CURSES) */
176 /***********************************************************************
179 * Calculate the visible rectangle of a window (i.e. the client or
180 * window area clipped by the client area of all ancestors) in the
181 * corresponding coordinates. Return FALSE if the visible region is empty.
183 static BOOL
DCE_GetVisRect( WND
*wndPtr
, BOOL clientArea
, RECT
*lprect
)
185 *lprect
= clientArea
? wndPtr
->rectClient
: wndPtr
->rectWindow
;
187 if (wndPtr
->dwStyle
& WS_VISIBLE
)
189 INT xoffset
= lprect
->left
;
190 INT yoffset
= lprect
->top
;
192 while ((wndPtr
= WIN_FindWndPtr( GetAncestor(wndPtr
->hwndSelf
,GA_PARENT
) )))
194 if ( (wndPtr
->dwStyle
& (WS_ICONIC
| WS_VISIBLE
)) != WS_VISIBLE
)
196 WIN_ReleaseWndPtr(wndPtr
);
200 xoffset
+= wndPtr
->rectClient
.left
;
201 yoffset
+= wndPtr
->rectClient
.top
;
202 OffsetRect( lprect
, wndPtr
->rectClient
.left
,
203 wndPtr
->rectClient
.top
);
205 if( (wndPtr
->rectClient
.left
>= wndPtr
->rectClient
.right
) ||
206 (wndPtr
->rectClient
.top
>= wndPtr
->rectClient
.bottom
) ||
207 (lprect
->left
>= wndPtr
->rectClient
.right
) ||
208 (lprect
->right
<= wndPtr
->rectClient
.left
) ||
209 (lprect
->top
>= wndPtr
->rectClient
.bottom
) ||
210 (lprect
->bottom
<= wndPtr
->rectClient
.top
) )
212 WIN_ReleaseWndPtr(wndPtr
);
216 lprect
->left
= max( lprect
->left
, wndPtr
->rectClient
.left
);
217 lprect
->right
= min( lprect
->right
, wndPtr
->rectClient
.right
);
218 lprect
->top
= max( lprect
->top
, wndPtr
->rectClient
.top
);
219 lprect
->bottom
= min( lprect
->bottom
, wndPtr
->rectClient
.bottom
);
221 WIN_ReleaseWndPtr(wndPtr
);
223 OffsetRect( lprect
, -xoffset
, -yoffset
);
228 SetRectEmpty( lprect
);
233 /***********************************************************************
236 * Go through the linked list of windows from pWndStart to pWndEnd,
237 * adding to the clip region the intersection of the target rectangle
238 * with an offset window rectangle.
240 static void DCE_AddClipRects( HWND parent
, HWND end
, HRGN hrgnClip
, LPRECT lpRect
, int x
, int y
)
245 HWND
*list
= WIN_ListChildren( parent
);
249 for (i
= 0; list
[i
]; i
++)
251 if (list
[i
] == end
) break;
252 if (!(pWnd
= WIN_FindWndPtr( list
[i
] ))) continue;
253 if (pWnd
->dwStyle
& WS_VISIBLE
)
255 rect
.left
= pWnd
->rectWindow
.left
+ x
;
256 rect
.top
= pWnd
->rectWindow
.top
+ y
;
257 rect
.right
= pWnd
->rectWindow
.right
+ x
;
258 rect
.bottom
= pWnd
->rectWindow
.bottom
+ y
;
259 if( IntersectRect( &rect
, &rect
, lpRect
))
261 if (!hrgn
) hrgn
= CreateRectRgnIndirect( &rect
);
262 else SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
263 CombineRgn( hrgnClip
, hrgnClip
, hrgn
, RGN_OR
);
266 WIN_ReleaseWndPtr( pWnd
);
268 if (hrgn
) DeleteObject( hrgn
);
269 HeapFree( GetProcessHeap(), 0, list
);
273 /***********************************************************************
276 * Return the visible region of a window, i.e. the client or window area
277 * clipped by the client area of all ancestors, and then optionally
278 * by siblings and children.
280 static HRGN
DCE_GetVisRgn( HWND hwnd
, WORD flags
, HWND hwndChild
, WORD cflags
)
284 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
285 WND
*childWnd
= WIN_FindWndPtr( hwndChild
);
287 /* Get visible rectangle and create a region with it. */
289 if (wndPtr
&& DCE_GetVisRect(wndPtr
, !(flags
& DCX_WINDOW
), &rect
))
291 if((hrgnVis
= CreateRectRgnIndirect( &rect
)))
293 HRGN hrgnClip
= CreateRectRgn( 0, 0, 0, 0 );
294 INT xoffset
, yoffset
;
298 /* Compute obscured region for the visible rectangle by
299 * clipping children, siblings, and ancestors. Note that
300 * DCE_GetVisRect() returns a rectangle either in client
301 * or in window coordinates (for DCX_WINDOW request). */
303 if (flags
& DCX_CLIPCHILDREN
)
305 if( flags
& DCX_WINDOW
)
307 /* adjust offsets since child window rectangles are
308 * in client coordinates */
310 xoffset
= wndPtr
->rectClient
.left
- wndPtr
->rectWindow
.left
;
311 yoffset
= wndPtr
->rectClient
.top
- wndPtr
->rectWindow
.top
;
314 xoffset
= yoffset
= 0;
316 DCE_AddClipRects( wndPtr
->hwndSelf
, 0, hrgnClip
, &rect
, xoffset
, yoffset
);
319 /* We may need to clip children of child window, if a window with PARENTDC
320 * class style and CLIPCHILDREN window style (like in Free Agent 16
321 * preference dialogs) gets here, we take the region for the parent window
322 * but apparently still need to clip the children of the child window... */
324 if( (cflags
& DCX_CLIPCHILDREN
) && childWnd
)
326 if( flags
& DCX_WINDOW
)
328 /* adjust offsets since child window rectangles are
329 * in client coordinates */
331 xoffset
= wndPtr
->rectClient
.left
- wndPtr
->rectWindow
.left
;
332 yoffset
= wndPtr
->rectClient
.top
- wndPtr
->rectWindow
.top
;
335 xoffset
= yoffset
= 0;
337 /* client coordinates of child window */
338 xoffset
+= childWnd
->rectClient
.left
;
339 yoffset
+= childWnd
->rectClient
.top
;
341 DCE_AddClipRects( childWnd
->hwndSelf
, 0, hrgnClip
,
342 &rect
, xoffset
, yoffset
);
345 /* sibling window rectangles are in client
346 * coordinates of the parent window */
348 if (flags
& DCX_WINDOW
)
350 xoffset
= -wndPtr
->rectWindow
.left
;
351 yoffset
= -wndPtr
->rectWindow
.top
;
355 xoffset
= -wndPtr
->rectClient
.left
;
356 yoffset
= -wndPtr
->rectClient
.top
;
359 if (flags
& DCX_CLIPSIBLINGS
&& wndPtr
->parent
)
360 DCE_AddClipRects( wndPtr
->parent
, wndPtr
->hwndSelf
,
361 hrgnClip
, &rect
, xoffset
, yoffset
);
363 /* Clip siblings of all ancestors that have the
364 * WS_CLIPSIBLINGS style
367 while (wndPtr
->parent
)
369 WND
*ptr
= WIN_FindWndPtr( wndPtr
->parent
);
370 WIN_ReleaseWndPtr( wndPtr
);
372 xoffset
-= wndPtr
->rectClient
.left
;
373 yoffset
-= wndPtr
->rectClient
.top
;
374 if(wndPtr
->dwStyle
& WS_CLIPSIBLINGS
&& wndPtr
->parent
)
376 DCE_AddClipRects( wndPtr
->parent
, wndPtr
->hwndSelf
,
377 hrgnClip
, &rect
, xoffset
, yoffset
);
381 /* Now once we've got a jumbo clip region we have
382 * to substract it from the visible rectangle.
384 CombineRgn( hrgnVis
, hrgnVis
, hrgnClip
, RGN_DIFF
);
385 DeleteObject( hrgnClip
);
389 DeleteObject( hrgnVis
);
395 hrgnVis
= CreateRectRgn(0, 0, 0, 0); /* empty */
396 WIN_ReleaseWndPtr(wndPtr
);
397 WIN_ReleaseWndPtr(childWnd
);
402 /***********************************************************************
405 * Set the drawable, origin and dimensions for the DC associated to
408 BOOL
TTYDRV_GetDC( HWND hwnd
, HDC hdc
, HRGN hrgn
, DWORD flags
)
410 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
411 HRGN hrgnVisible
= 0;
414 if (!wndPtr
) return FALSE
;
416 if(flags
& DCX_WINDOW
)
418 org
.x
= wndPtr
->rectWindow
.left
;
419 org
.y
= wndPtr
->rectWindow
.top
;
423 org
.x
= wndPtr
->rectClient
.left
;
424 org
.y
= wndPtr
->rectClient
.top
;
427 SetDCOrg16( HDC_16(hdc
), org
.x
, org
.y
);
429 if (SetHookFlags16( HDC_16(hdc
), DCHF_VALIDATEVISRGN
) || /* DC was dirty */
430 ( flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
) ))
432 if (flags
& DCX_PARENTCLIP
)
434 WND
*parentPtr
= WIN_FindWndPtr( wndPtr
->parent
);
436 if( wndPtr
->dwStyle
& WS_VISIBLE
&& !(parentPtr
->dwStyle
& WS_MINIMIZE
) )
440 if( parentPtr
->dwStyle
& WS_CLIPSIBLINGS
)
441 dcxFlags
= DCX_CLIPSIBLINGS
| (flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
443 dcxFlags
= flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
445 hrgnVisible
= DCE_GetVisRgn( parentPtr
->hwndSelf
, dcxFlags
,
446 wndPtr
->hwndSelf
, flags
);
447 if( flags
& DCX_WINDOW
)
448 OffsetRgn( hrgnVisible
, -wndPtr
->rectWindow
.left
,
449 -wndPtr
->rectWindow
.top
);
451 OffsetRgn( hrgnVisible
, -wndPtr
->rectClient
.left
,
452 -wndPtr
->rectClient
.top
);
455 hrgnVisible
= CreateRectRgn( 0, 0, 0, 0 );
456 WIN_ReleaseWndPtr(parentPtr
);
460 hrgnVisible
= DCE_GetVisRgn( hwnd
, flags
, 0, 0 );
461 OffsetRgn( hrgnVisible
, org
.x
, org
.y
);
464 /* apply additional region operation (if any) */
465 if( flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
) )
466 CombineRgn( hrgnVisible
, hrgnVisible
, hrgn
,
467 (flags
& DCX_INTERSECTRGN
) ? RGN_AND
: RGN_DIFF
);
469 SelectVisRgn16( HDC_16(hdc
), HRGN_16(hrgnVisible
) );
472 if (hrgnVisible
) DeleteObject( hrgnVisible
);
474 WIN_ReleaseWndPtr( wndPtr
);
479 /***********************************************************************
480 * SetWindowPos (TTYDRV.@)
482 BOOL
TTYDRV_SetWindowPos( WINDOWPOS
*winpos
)
485 RECT newWindowRect
, newClientRect
;
487 HWND hwndActive
= GetForegroundWindow();
489 TRACE( "hwnd %p, swp (%i,%i)-(%i,%i) flags %08x\n",
490 winpos
->hwnd
, winpos
->x
, winpos
->y
,
491 winpos
->x
+ winpos
->cx
, winpos
->y
+ winpos
->cy
, winpos
->flags
);
493 /* ------------------------------------------------------------------------ CHECKS */
495 /* Check window handle */
497 if (winpos
->hwnd
== GetDesktopWindow()) return FALSE
;
498 if (!(wndPtr
= WIN_FindWndPtr( winpos
->hwnd
))) return FALSE
;
500 TRACE("\tcurrent (%ld,%ld)-(%ld,%ld), style %08x\n",
501 wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
502 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
504 /* Fix redundant flags */
506 if(wndPtr
->dwStyle
& WS_VISIBLE
)
507 winpos
->flags
&= ~SWP_SHOWWINDOW
;
510 if (!(winpos
->flags
& SWP_SHOWWINDOW
)) winpos
->flags
|= SWP_NOREDRAW
;
511 winpos
->flags
&= ~SWP_HIDEWINDOW
;
514 if ( winpos
->cx
< 0 ) winpos
->cx
= 0;
515 if ( winpos
->cy
< 0 ) winpos
->cy
= 0;
517 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== winpos
->cx
) &&
518 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== winpos
->cy
))
519 winpos
->flags
|= SWP_NOSIZE
; /* Already the right size */
521 if ((wndPtr
->rectWindow
.left
== winpos
->x
) && (wndPtr
->rectWindow
.top
== winpos
->y
))
522 winpos
->flags
|= SWP_NOMOVE
; /* Already the right position */
524 if (winpos
->hwnd
== hwndActive
)
525 winpos
->flags
|= SWP_NOACTIVATE
; /* Already active */
526 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
528 if(!(winpos
->flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
530 winpos
->flags
&= ~SWP_NOZORDER
;
531 winpos
->hwndInsertAfter
= HWND_TOP
;
536 /* Check hwndInsertAfter */
538 /* FIXME: TOPMOST not supported yet */
539 if ((winpos
->hwndInsertAfter
== HWND_TOPMOST
) ||
540 (winpos
->hwndInsertAfter
== HWND_NOTOPMOST
)) winpos
->hwndInsertAfter
= HWND_TOP
;
542 /* hwndInsertAfter must be a sibling of the window */
543 if ((winpos
->hwndInsertAfter
!= HWND_TOP
) && (winpos
->hwndInsertAfter
!= HWND_BOTTOM
))
545 WND
* wnd
= WIN_FindWndPtr(winpos
->hwndInsertAfter
);
548 if( wnd
->parent
!= wndPtr
->parent
)
551 WIN_ReleaseWndPtr(wnd
);
554 /* don't need to change the Zorder of hwnd if it's already inserted
555 * after hwndInsertAfter or when inserting hwnd after itself.
557 if ((winpos
->hwnd
== winpos
->hwndInsertAfter
) ||
558 (winpos
->hwnd
== GetWindow( winpos
->hwndInsertAfter
, GW_HWNDNEXT
)))
559 winpos
->flags
|= SWP_NOZORDER
;
561 WIN_ReleaseWndPtr(wnd
);
564 Pos
: /* ------------------------------------------------------------------------ MAIN part */
566 /* Send WM_WINDOWPOSCHANGING message */
568 if (!(winpos
->flags
& SWP_NOSENDCHANGING
))
569 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)winpos
);
571 /* Calculate new position and size */
573 newWindowRect
= wndPtr
->rectWindow
;
574 newClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
575 : wndPtr
->rectClient
;
577 if (!(winpos
->flags
& SWP_NOSIZE
))
579 newWindowRect
.right
= newWindowRect
.left
+ winpos
->cx
;
580 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
->cy
;
582 if (!(winpos
->flags
& SWP_NOMOVE
))
584 newWindowRect
.left
= winpos
->x
;
585 newWindowRect
.top
= winpos
->y
;
586 newWindowRect
.right
+= winpos
->x
- wndPtr
->rectWindow
.left
;
587 newWindowRect
.bottom
+= winpos
->y
- wndPtr
->rectWindow
.top
;
589 OffsetRect( &newClientRect
, winpos
->x
- wndPtr
->rectWindow
.left
,
590 winpos
->y
- wndPtr
->rectWindow
.top
);
593 if( winpos
->hwndInsertAfter
== HWND_TOP
)
595 if (GetWindow( wndPtr
->hwndSelf
, GW_HWNDFIRST
) == wndPtr
->hwndSelf
)
596 winpos
->flags
|= SWP_NOZORDER
;
599 if( winpos
->hwndInsertAfter
== HWND_BOTTOM
)
601 if (!GetWindow( wndPtr
->hwndSelf
, GW_HWNDNEXT
))
602 winpos
->flags
|= SWP_NOZORDER
;
605 if( !(winpos
->flags
& SWP_NOZORDER
) )
606 if( GetWindow(winpos
->hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
607 winpos
->flags
|= SWP_NOZORDER
;
609 /* Common operations */
611 /* Send WM_NCCALCSIZE message to get new client area */
612 if( (winpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
614 NCCALCSIZE_PARAMS params
;
615 WINDOWPOS winposCopy
;
617 params
.rgrc
[0] = newWindowRect
;
618 params
.rgrc
[1] = wndPtr
->rectWindow
;
619 params
.rgrc
[2] = wndPtr
->rectClient
;
620 params
.lppos
= &winposCopy
;
621 winposCopy
= *winpos
;
623 SendMessageW( winpos
->hwnd
, WM_NCCALCSIZE
, TRUE
, (LPARAM
)¶ms
);
625 TRACE( "%ld,%ld-%ld,%ld\n", params
.rgrc
[0].left
, params
.rgrc
[0].top
,
626 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
628 /* If the application send back garbage, ignore it */
629 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
630 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
631 newClientRect
= params
.rgrc
[0];
633 /* FIXME: WVR_ALIGNxxx */
635 if( newClientRect
.left
!= wndPtr
->rectClient
.left
||
636 newClientRect
.top
!= wndPtr
->rectClient
.top
)
637 winpos
->flags
&= ~SWP_NOCLIENTMOVE
;
639 if( (newClientRect
.right
- newClientRect
.left
!=
640 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
641 (newClientRect
.bottom
- newClientRect
.top
!=
642 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
643 winpos
->flags
&= ~SWP_NOCLIENTSIZE
;
646 if(!(winpos
->flags
& SWP_NOZORDER
) && winpos
->hwnd
!= winpos
->hwndInsertAfter
)
648 HWND parent
= GetAncestor( winpos
->hwnd
, GA_PARENT
);
649 if (parent
) WIN_LinkWindow( winpos
->hwnd
, parent
, winpos
->hwndInsertAfter
);
652 /* FIXME: actually do something with WVR_VALIDRECTS */
654 set_window_rectangles( winpos
->hwnd
, &newWindowRect
, &newClientRect
);
656 if( winpos
->flags
& SWP_SHOWWINDOW
)
657 WIN_SetStyle( winpos
->hwnd
, wndPtr
->dwStyle
| WS_VISIBLE
);
658 else if( winpos
->flags
& SWP_HIDEWINDOW
)
659 WIN_SetStyle( winpos
->hwnd
, wndPtr
->dwStyle
& ~WS_VISIBLE
);
661 /* ------------------------------------------------------------------------ FINAL */
663 /* repaint invalidated region (if any)
665 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
666 * and force update after ChangeActiveWindow() to avoid painting frames twice.
669 if( !(winpos
->flags
& SWP_NOREDRAW
) )
671 RedrawWindow( wndPtr
->parent
, NULL
, 0,
672 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
673 if (wndPtr
->parent
== GetDesktopWindow())
674 RedrawWindow( wndPtr
->parent
, NULL
, 0,
675 RDW_ERASENOW
| RDW_NOCHILDREN
);
678 if (!(winpos
->flags
& SWP_NOACTIVATE
)) SetActiveWindow( winpos
->hwnd
);
680 /* And last, send the WM_WINDOWPOSCHANGED message */
682 TRACE("\tstatus flags = %04x\n", winpos
->flags
& SWP_AGG_STATUSFLAGS
);
684 if ((((winpos
->flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
685 !(winpos
->flags
& SWP_NOSENDCHANGING
)) )
686 SendMessageA( winpos
->hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)winpos
);
690 WIN_ReleaseWndPtr(wndPtr
);
695 /***********************************************************************
696 * WINPOS_MinMaximize (internal)
698 *Lifted from x11 driver
700 static UINT
WINPOS_MinMaximize( HWND hwnd
, UINT cmd
, LPRECT rect
)
705 TRACE("%p %u\n", hwnd
, cmd
);
706 FIXME("(%p): stub\n", hwnd
);
708 wpl
.length
= sizeof(wpl
);
709 GetWindowPlacement( hwnd
, &wpl
);
711 /* If I glark this right, yields an immutable window*/
712 swpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
714 /*cmd handling goes here. see dlls/x1drv/winpos.c*/
719 /***********************************************************************
720 * ShowWindow (TTYDRV.@)
722 *Lifted from x11 driver
723 *Sets the specified windows' show state.
725 BOOL
TTYDRV_ShowWindow( HWND hwnd
, INT cmd
)
727 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
728 BOOL wasVisible
, showFlag
;
729 RECT newPos
= {0, 0, 0, 0};
732 if (!wndPtr
) return FALSE
;
733 hwnd
= wndPtr
->hwndSelf
; /* make it a full handle */
735 TRACE("hwnd=%p, cmd=%d\n", hwnd
, cmd
);
737 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
742 if (!wasVisible
) goto END
;
743 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
744 SWP_NOACTIVATE
| SWP_NOZORDER
;
747 case SW_SHOWMINNOACTIVE
:
748 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
750 case SW_SHOWMINIMIZED
:
751 swp
|= SWP_SHOWWINDOW
;
754 swp
|= SWP_FRAMECHANGED
;
755 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
756 swp
|= WINPOS_MinMaximize( hwnd
, SW_MINIMIZE
, &newPos
);
757 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
760 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
761 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
762 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
763 swp
|= WINPOS_MinMaximize( hwnd
, SW_MAXIMIZE
, &newPos
);
764 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
768 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
771 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
774 * ShowWindow has a little peculiar behavior that if the
775 * window is already the topmost window, it will not
778 if (GetTopWindow(NULL
)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
779 swp
|= SWP_NOACTIVATE
;
783 case SW_SHOWNOACTIVATE
:
785 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
787 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
788 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
790 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
792 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
793 swp
|= WINPOS_MinMaximize( hwnd
, SW_RESTORE
, &newPos
);
794 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
798 showFlag
= (cmd
!= SW_HIDE
);
799 if (showFlag
!= wasVisible
)
801 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
802 if (!IsWindow( hwnd
)) goto END
;
805 /* We can't activate a child window */
806 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
807 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
808 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
810 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
811 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
814 /* FIXME: This will cause the window to be activated irrespective
815 * of whether it is owned by the same thread. Has to be done
819 if (hwnd
== GetActiveWindow())
820 WINPOS_ActivateOtherWindow(hwnd
);
822 /* Revert focus to parent */
823 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
824 SetFocus( GetParent(hwnd
) );
826 if (!IsWindow( hwnd
)) goto END
;
827 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( hwnd
, TRUE
);
829 if (wndPtr
->flags
& WIN_NEED_SIZE
)
831 /* should happen only in CreateWindowEx() */
832 int wParam
= SIZE_RESTORED
;
834 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
835 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
836 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
837 SendMessageA( hwnd
, WM_SIZE
, wParam
,
838 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
839 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
840 SendMessageA( hwnd
, WM_MOVE
, 0,
841 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
845 WIN_ReleaseWndPtr(wndPtr
);