2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
8 #include "sysmetrics.h"
15 #include "stackframe.h"
17 #include "nonclient.h"
19 /* #define DEBUG_WIN */
22 /* ----- external functions ----- */
24 void FOCUS_SwitchFocus( HWND
, HWND
);
26 /* ----- internal variables ----- */
28 static HWND hwndActive
= 0; /* Currently active window */
29 static HWND hwndPrevActive
= 0; /* Previously active window */
31 extern HANDLE hActiveQ_G
; /* from message.c */
34 /***********************************************************************
37 * Find a suitable place for an iconic window.
38 * The new position is stored into wndPtr->ptIconPos.
40 void WINPOS_FindIconPos( HWND hwnd
)
43 short x
, y
, xspacing
, yspacing
;
44 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
47 GetClientRect( wndPtr
->hwndParent
, &rectParent
);
48 if ((wndPtr
->ptIconPos
.x
>= rectParent
.left
) &&
49 (wndPtr
->ptIconPos
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
50 (wndPtr
->ptIconPos
.y
>= rectParent
.top
) &&
51 (wndPtr
->ptIconPos
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
52 return; /* The icon already has a suitable position */
54 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
55 y
= rectParent
.bottom
;
58 for (x
= rectParent
.left
; x
<=rectParent
.right
-xspacing
; x
+= xspacing
)
60 /* Check if another icon already occupies this spot */
61 HWND hwndChild
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
64 WND
*childPtr
= WIN_FindWndPtr( hwndChild
);
65 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (hwndChild
!= hwnd
))
67 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
68 (childPtr
->rectWindow
.right
>= x
) &&
69 (childPtr
->rectWindow
.top
<= y
) &&
70 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
71 break; /* There's a window in there */
74 hwndChild
= childPtr
->hwndNext
;
78 /* No window was found, so it's OK for us */
79 wndPtr
->ptIconPos
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
80 wndPtr
->ptIconPos
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
89 /***********************************************************************
90 * ArrangeIconicWindows (USER.170)
92 WORD
ArrangeIconicWindows( HWND parent
)
96 short x
, y
, xspacing
, yspacing
;
98 GetClientRect( parent
, &rectParent
);
100 y
= rectParent
.bottom
;
101 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
102 hwndChild
= GetWindow( parent
, GW_CHILD
);
105 if (IsIconic( hwndChild
))
107 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
108 y
- (yspacing
+ SYSMETRICS_CYICON
) / 2, 0, 0,
109 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
110 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
117 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
123 /***********************************************************************
124 * GetWindowRect (USER.32)
126 void GetWindowRect( HWND hwnd
, LPRECT rect
)
128 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
131 *rect
= wndPtr
->rectWindow
;
132 if (wndPtr
->dwStyle
& WS_CHILD
)
133 MapWindowPoints( wndPtr
->hwndParent
, 0, (POINT
*)rect
, 2 );
137 /***********************************************************************
138 * GetClientRect (USER.33)
140 void GetClientRect( HWND hwnd
, LPRECT rect
)
142 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
144 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
147 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
148 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
153 /*******************************************************************
154 * ClientToScreen (USER.28)
156 void ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
158 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
162 /*******************************************************************
163 * ScreenToClient (USER.29)
165 void ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
167 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
171 /*******************************************************************
172 * WindowFromPoint (USER.30)
174 HWND
WindowFromPoint( POINT pt
)
177 HWND hwnd
= GetDesktopWindow();
181 /* If point is in window, and window is visible, */
182 /* not disabled and not transparent, then explore */
183 /* its children. Otherwise, go to the next window. */
185 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
186 if ((pt
.x
>= wndPtr
->rectWindow
.left
) &&
187 (pt
.x
< wndPtr
->rectWindow
.right
) &&
188 (pt
.y
>= wndPtr
->rectWindow
.top
) &&
189 (pt
.y
< wndPtr
->rectWindow
.bottom
) &&
190 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
191 (wndPtr
->dwStyle
& WS_VISIBLE
) &&
192 !(wndPtr
->dwExStyle
& WS_EX_TRANSPARENT
))
195 /* If window is minimized, ignore its children */
196 if (wndPtr
->dwStyle
& WS_MINIMIZE
) break;
197 pt
.x
-= wndPtr
->rectClient
.left
;
198 pt
.y
-= wndPtr
->rectClient
.top
;
199 hwnd
= wndPtr
->hwndChild
;
201 else hwnd
= wndPtr
->hwndNext
;
207 /*******************************************************************
208 * ChildWindowFromPoint (USER.191)
210 HWND
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
215 GetWindowRect( hwndParent
, &rect
);
216 if (!PtInRect( &rect
, pt
)) return 0;
217 hwnd
= GetTopWindow( hwndParent
);
220 GetWindowRect( hwnd
, &rect
);
221 if (PtInRect( &rect
, pt
)) return hwnd
;
222 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
228 /*******************************************************************
229 * MapWindowPoints (USER.258)
231 void MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, WORD count
)
235 POINT origin
= { 0, 0 };
238 /* Translate source window origin to screen coords */
241 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
243 fprintf( stderr
, "MapWindowPoints: bad hwndFrom = "NPFMT
"\n",
247 origin
.x
+= wndPtr
->rectClient
.left
;
248 origin
.y
+= wndPtr
->rectClient
.top
;
249 hwndFrom
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
252 /* Translate origin to destination window coords */
255 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
257 fprintf(stderr
,"MapWindowPoints: bad hwndTo = "NPFMT
"\n", hwndTo
);
260 origin
.x
-= wndPtr
->rectClient
.left
;
261 origin
.y
-= wndPtr
->rectClient
.top
;
262 hwndTo
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
265 /* Translate points */
266 for (i
= 0, curpt
= lppt
; i
< count
; i
++, curpt
++)
268 curpt
->x
+= origin
.x
;
269 curpt
->y
+= origin
.y
;
274 /***********************************************************************
277 BOOL
IsIconic(HWND hWnd
)
279 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
280 if (wndPtr
== NULL
) return FALSE
;
281 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
285 /***********************************************************************
286 * IsZoomed (USER.272)
288 BOOL
IsZoomed(HWND hWnd
)
290 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
291 if (wndPtr
== NULL
) return FALSE
;
292 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
296 /*******************************************************************
297 * GetActiveWindow (USER.60)
299 HWND
GetActiveWindow()
305 /*******************************************************************
306 * SetActiveWindow (USER.59)
308 HWND
SetActiveWindow( HWND hwnd
)
310 HWND prev
= hwndActive
;
311 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
313 if (!wndPtr
|| (wndPtr
->dwStyle
& WS_DISABLED
) ||
314 !(wndPtr
->dwStyle
& WS_VISIBLE
)) return 0;
316 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
321 /***********************************************************************
322 * BringWindowToTop (USER.45)
324 BOOL
BringWindowToTop( HWND hwnd
)
326 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
330 /***********************************************************************
331 * MoveWindow (USER.56)
333 BOOL
MoveWindow( HWND hwnd
, short x
, short y
, short cx
, short cy
, BOOL repaint
)
335 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
336 if (!repaint
) flags
|= SWP_NOREDRAW
;
337 dprintf_win(stddeb
, "MoveWindow: "NPFMT
" %d,%d %dx%d %d\n",
338 hwnd
, x
, y
, cx
, cy
, repaint
);
339 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
343 /***********************************************************************
344 * ShowWindow (USER.42)
346 BOOL
ShowWindow( HWND hwnd
, int cmd
)
348 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
352 short x
= 0, y
= 0, cx
= 0, cy
= 0;
354 if (!wndPtr
) return FALSE
;
356 dprintf_win(stddeb
,"ShowWindow: hwnd="NPFMT
", cmd=%d\n", hwnd
, cmd
);
358 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
363 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
364 SWP_NOACTIVATE
| SWP_NOZORDER
;
367 case SW_SHOWMINNOACTIVE
:
368 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
370 case SW_SHOWMINIMIZED
:
371 swpflags
|= SWP_SHOWWINDOW
;
374 swpflags
|= SWP_FRAMECHANGED
;
375 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
377 if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
379 wndPtr
->flags
|= WIN_RESTORE_MAX
;
380 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
384 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
385 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
387 wndPtr
->dwStyle
|= WS_MINIMIZE
;
388 WINPOS_FindIconPos( hwnd
);
389 x
= wndPtr
->ptIconPos
.x
;
390 y
= wndPtr
->ptIconPos
.y
;
391 cx
= SYSMETRICS_CXICON
;
392 cy
= SYSMETRICS_CYICON
;
394 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
397 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE: */
398 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
399 if (!(wndPtr
->dwStyle
& WS_MAXIMIZE
))
401 /* Store the current position and find the maximized size */
402 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
403 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
405 NC_GetMinMaxInfo( hwnd
, &maxSize
,
406 &wndPtr
->ptMaxPos
, NULL
, NULL
);
407 x
= wndPtr
->ptMaxPos
.x
;
408 y
= wndPtr
->ptMaxPos
.y
;
410 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
411 if( !SendMessage( hwnd
, WM_QUERYOPEN
, 0, 0L ) )
413 swpflags
|= SWP_NOSIZE
;
419 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
420 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
422 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
426 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
429 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
432 case SW_SHOWNOACTIVATE
:
433 swpflags
|= SWP_NOZORDER
;
434 if (GetActiveWindow()) swpflags
|= SWP_NOACTIVATE
;
436 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
438 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
440 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
442 if( !SendMessage( hwnd
, WM_QUERYOPEN
, 0, 0L) )
444 swpflags
|= SWP_NOSIZE
;
447 wndPtr
->ptIconPos
.x
= wndPtr
->rectWindow
.left
;
448 wndPtr
->ptIconPos
.y
= wndPtr
->rectWindow
.top
;
449 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
450 if (wndPtr
->flags
& WIN_RESTORE_MAX
)
452 /* Restore to maximized position */
453 NC_GetMinMaxInfo( hwnd
, &maxSize
, &wndPtr
->ptMaxPos
,
455 x
= wndPtr
->ptMaxPos
.x
;
456 y
= wndPtr
->ptMaxPos
.y
;
459 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
461 else /* Restore to normal position */
463 x
= wndPtr
->rectNormal
.left
;
464 y
= wndPtr
->rectNormal
.top
;
465 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
466 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
469 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
471 wndPtr
->ptMaxPos
.x
= wndPtr
->rectWindow
.left
;
472 wndPtr
->ptMaxPos
.y
= wndPtr
->rectWindow
.top
;
473 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
474 x
= wndPtr
->rectNormal
.left
;
475 y
= wndPtr
->rectNormal
.top
;
476 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
477 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
479 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
483 SendMessage( hwnd
, WM_SHOWWINDOW
, (cmd
!= SW_HIDE
), 0 );
484 SetWindowPos( hwnd
, HWND_TOP
, x
, y
, cx
, cy
, swpflags
);
486 /* Send WM_SIZE and WM_MOVE messages if not already done */
487 if (!(wndPtr
->flags
& WIN_GOT_SIZEMSG
))
489 int wParam
= SIZE_RESTORED
;
490 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
491 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
492 wndPtr
->flags
|= WIN_GOT_SIZEMSG
;
493 SendMessage( hwnd
, WM_SIZE
, wParam
,
494 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
495 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
496 SendMessage( hwnd
, WM_MOVE
, 0,
497 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
504 /***********************************************************************
505 * GetInternalWindowPos (USER.460)
507 WORD
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
, LPPOINT ptIcon
)
509 WINDOWPLACEMENT wndpl
;
510 if (!GetWindowPlacement( hwnd
, &wndpl
)) return 0;
511 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
512 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
513 return wndpl
.showCmd
;
517 /***********************************************************************
518 * SetInternalWindowPos (USER.461)
520 void SetInternalWindowPos( HWND hwnd
, WORD showCmd
, LPRECT rect
, LPPOINT pt
)
522 WINDOWPLACEMENT wndpl
;
523 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
525 wndpl
.length
= sizeof(wndpl
);
526 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
527 wndpl
.showCmd
= showCmd
;
528 if (pt
) wndpl
.ptMinPosition
= *pt
;
529 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
530 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
531 SetWindowPlacement( hwnd
, &wndpl
);
535 /***********************************************************************
536 * GetWindowPlacement (USER.370)
538 BOOL
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
540 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
541 if (!wndPtr
) return FALSE
;
543 wndpl
->length
= sizeof(*wndpl
);
545 wndpl
->showCmd
= IsZoomed(hwnd
) ? SW_SHOWMAXIMIZED
:
546 (IsIconic(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
547 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
548 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
549 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
554 /***********************************************************************
555 * SetWindowPlacement (USER.371)
557 BOOL
SetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
559 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
560 if (!wndPtr
) return FALSE
;
562 if (wndpl
->flags
& WPF_SETMINPOSITION
)
563 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
564 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
565 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
566 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
567 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
568 ShowWindow( hwnd
, wndpl
->showCmd
);
572 /*******************************************************************
573 * ACTIVATEAPP_callback
575 BOOL
ACTIVATEAPP_callback(HWND hWnd
, LPARAM lParam
)
577 ACTIVATESTRUCT
*lpActStruct
= (ACTIVATESTRUCT
*)lParam
;
578 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
580 if( !wndPtr
|| hWnd
== GetDesktopWindow()) return 1;
582 if( MSG_GetQueueTask(wndPtr
->hmemTaskQ
) != lpActStruct
->hTaskSendTo
)
585 SendMessage( hWnd
, WM_ACTIVATEAPP
, lpActStruct
->wFlag
,
586 (LPARAM
)(lpActStruct
->hWindowTask
)?lpActStruct
->hWindowTask
:0);
591 /*******************************************************************
592 * WINPOS_SetActiveWindow
594 * back-end to SetActiveWindow
596 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
598 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
599 WND
*wndTemp
= WIN_FindWndPtr(hwndActive
);
600 CBTACTIVATESTRUCT cbtStruct
= { fMouse
, hwndActive
};
601 FARPROC enumCallback
= (FARPROC
)GetWndProcEntry16("ActivateAppProc");
602 ACTIVATESTRUCT actStruct
;
603 WORD wIconized
=0,wRet
= 0;
605 /* paranoid checks */
606 if( !hWnd
|| hWnd
== GetDesktopWindow() || hWnd
== hwndActive
)
609 if( GetTaskQueue(0) != wndPtr
->hmemTaskQ
)
613 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
615 dprintf_win(stddeb
,"WINPOS_ActivateWindow: no current active window.\n");
617 /* call CBT hook chain */
618 wRet
= HOOK_CallHooks(WH_CBT
, HCBT_ACTIVATE
, hWnd
,
619 (LPARAM
)MAKE_SEGPTR(&cbtStruct
));
621 if( wRet
) return wRet
;
623 /* set prev active wnd to current active wnd and send notification */
624 if( (hwndPrevActive
= hwndActive
) )
626 if( !SendMessage(hwndPrevActive
, WM_NCACTIVATE
, 0, MAKELONG(hWnd
,wIconized
)) )
628 if (GetSysModalWindow() != hWnd
) return 0;
629 /* disregard refusal if hWnd is sysmodal */
633 SendMessage( hwndActive
, WM_ACTIVATE
,
634 MAKEWPARAM( WA_INACTIVE
, wIconized
),
637 SendMessage(hwndPrevActive
, WM_ACTIVATE
, WA_INACTIVE
,
638 MAKELONG(hWnd
,wIconized
));
641 /* check if something happened during message processing */
642 if( hwndPrevActive
!= hwndActive
) return 0;
648 /* send palette messages */
649 if( SendMessage( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L) )
650 SendMessage((HWND
)-1, WM_PALETTEISCHANGING
, hWnd
, 0L );
652 /* if prev wnd is minimized redraw icon title
655 wndTemp = WIN_FindWndPtr( WIN_GetTopParent( hwndPrevActive ) );
657 if(wndTemp->dwStyle & WS_MINIMIZE)
658 RedrawIconTitle(hwndPrevActive);
661 if (!(wndPtr
->dwStyle
& WS_CHILD
) )
663 /* check Z-order and bring hWnd to the top */
664 wndTemp
= WIN_FindWndPtr( GetDesktopWindow() );
666 for( ; wndTemp
; wndTemp
= WIN_FindWndPtr( wndTemp
->hwndNext
))
667 if( wndTemp
->dwStyle
& WS_VISIBLE
)
670 if( wndTemp
!= wndPtr
)
671 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
672 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
675 if( !IsWindow(hWnd
) ) return 0;
677 /* send WM_ACTIVATEAPP if necessary */
678 if( hActiveQ_G
!= wndPtr
->hmemTaskQ
)
680 HTASK hT
= MSG_GetQueueTask( hActiveQ_G
);
682 actStruct
.wFlag
= 0; /* deactivate */
683 actStruct
.hWindowTask
= MSG_GetQueueTask(wndPtr
->hmemTaskQ
);
684 actStruct
.hTaskSendTo
= hT
;
686 /* send WM_ACTIVATEAPP to top-level windows
687 * that belong to the actStruct.hTaskSendTo task
689 EnumWindows( enumCallback
, (LPARAM
)&actStruct
);
691 /* change active queue */
692 hActiveQ_G
= wndPtr
->hmemTaskQ
;
694 actStruct
.wFlag
= 1; /* activate */
695 actStruct
.hWindowTask
= hT
;
696 actStruct
.hTaskSendTo
= MSG_GetQueueTask( hActiveQ_G
);
698 EnumWindows( enumCallback
, (LPARAM
)&actStruct
);
700 if( !IsWindow(hWnd
) ) return 0;
703 /* walk up to the first unowned window */
706 while(wndTemp
->hwndOwner
)
708 wndTemp
= WIN_FindWndPtr(wndTemp
->hwndOwner
);
711 /* there must be an unowned window in hierarchy */
712 dprintf_win(stddeb
,"WINPOS_ActivateWindow: broken owner list\n");
717 /* and set last active owned popup */
718 wndTemp
->hwndLastActive
= hWnd
;
720 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
721 SendMessage( hWnd
, WM_NCACTIVATE
, 1,
722 MAKELONG(hwndPrevActive
,wIconized
));
724 SendMessage( hWnd
, WM_ACTIVATE
,
725 MAKEWPARAM( (fMouse
)?WA_CLICKACTIVE
:WA_ACTIVE
, wIconized
),
726 (LPARAM
)hwndPrevActive
);
728 SendMessage( hWnd
, WM_ACTIVATE
, (fMouse
)? WA_CLICKACTIVE
: WA_ACTIVE
,
729 MAKELONG(hwndPrevActive
,wIconized
));
732 if( !IsWindow(hWnd
) ) return 0;
734 /* change focus if possible */
735 if( fChangeFocus
&& GetFocus() )
736 if( WIN_GetTopParent(GetFocus()) != hwndActive
)
737 FOCUS_SwitchFocus( GetFocus(),
738 (wndPtr
->dwStyle
& WS_MINIMIZE
)? 0: hwndActive
);
740 /* if active wnd is minimized redraw icon title
743 wndPtr = WIN_FindWndPtr(hwndActive);
744 if(wndPtr->dwStyle & WS_MINIMIZE)
745 RedrawIconTitle(hwndActive);
748 return (hWnd
== hwndActive
);
752 /*******************************************************************
753 * WINPOS_ChangeActiveWindow
756 HWND
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
758 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
760 if( !wndPtr
) return 0;
762 /* minors are not allowed */
763 if( (wndPtr
->dwStyle
& WS_CHILD
) && !( wndPtr
->dwStyle
& WS_POPUP
))
764 return SendMessage(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
766 if( hWnd
== hwndActive
) return 0;
768 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
771 /* switch desktop queue to current active here */
772 if( wndPtr
->hwndParent
== GetDesktopWindow())
779 /***********************************************************************
780 * WINPOS_SendNCCalcSize
782 * Send a WM_NCCALCSIZE message to a window.
783 * All parameters are read-only except newClientRect.
784 * oldWindowRect, oldClientRect and winpos must be non-NULL only
785 * when calcValidRect is TRUE.
787 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
, RECT
*newWindowRect
,
788 RECT
*oldWindowRect
, RECT
*oldClientRect
,
789 WINDOWPOS
*winpos
, RECT
*newClientRect
)
791 NCCALCSIZE_PARAMS params
;
794 params
.rgrc
[0] = *newWindowRect
;
797 params
.rgrc
[1] = *oldWindowRect
;
798 params
.rgrc
[2] = *oldClientRect
;
799 params
.lppos
= winpos
;
801 result
= SendMessage( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
802 MAKE_SEGPTR( ¶ms
) );
803 dprintf_win(stddeb
, "WINPOS_SendNCCalcSize: %d %d %d %d\n",
804 params
.rgrc
[0].top
, params
.rgrc
[0].left
,
805 params
.rgrc
[0].bottom
, params
.rgrc
[0].right
);
806 *newClientRect
= params
.rgrc
[0];
811 /***********************************************************************
812 * WINPOS_HandleWindowPosChanging
814 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
816 LONG
WINPOS_HandleWindowPosChanging( WINDOWPOS
*winpos
)
819 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
820 if (!wndPtr
|| (winpos
->flags
& SWP_NOSIZE
)) return 0;
821 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
822 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
824 NC_GetMinMaxInfo( winpos
->hwnd
, &maxSize
, NULL
, NULL
, NULL
);
825 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
826 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
832 /***********************************************************************
833 * WINPOS_MoveWindowZOrder
835 * Move a window in Z order, invalidating everything that needs it.
836 * Only necessary for windows without associated X window.
838 static void WINPOS_MoveWindowZOrder( HWND hwnd
, HWND hwndAfter
)
842 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
844 /* We have two possible cases:
845 * - The window is moving up: we have to invalidate all areas
846 * of the window that were covered by other windows
847 * - The window is moving down: we have to invalidate areas
848 * of other windows covered by this one.
851 if (hwndAfter
== HWND_TOP
)
855 else if (hwndAfter
== HWND_BOTTOM
)
857 if (!wndPtr
->hwndNext
) return; /* Already at the bottom */
862 if (wndPtr
->hwndNext
== hwndAfter
) return; /* Already placed right */
864 /* Determine which window we encounter first in Z-order */
865 hwndCur
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
866 while ((hwndCur
!= hwnd
) && (hwndCur
!= hwndAfter
))
867 hwndCur
= GetWindow( hwndCur
, GW_HWNDNEXT
);
868 movingUp
= (hwndCur
== hwndAfter
);
873 HWND hwndPrevAfter
= wndPtr
->hwndNext
;
874 WIN_UnlinkWindow( hwnd
);
875 WIN_LinkWindow( hwnd
, hwndAfter
);
876 hwndCur
= wndPtr
->hwndNext
;
877 while (hwndCur
!= hwndPrevAfter
)
879 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
880 RECT rect
= curPtr
->rectWindow
;
881 OffsetRect( &rect
, -wndPtr
->rectClient
.left
,
882 -wndPtr
->rectClient
.top
);
883 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
884 RDW_FRAME
| RDW_ERASE
);
885 hwndCur
= curPtr
->hwndNext
;
888 else /* Moving down */
890 hwndCur
= wndPtr
->hwndNext
;
891 WIN_UnlinkWindow( hwnd
);
892 WIN_LinkWindow( hwnd
, hwndAfter
);
893 while (hwndCur
!= hwnd
)
895 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
896 RECT rect
= wndPtr
->rectWindow
;
897 OffsetRect( &rect
, -curPtr
->rectClient
.left
,
898 -curPtr
->rectClient
.top
);
899 RedrawWindow( hwndCur
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
900 RDW_FRAME
| RDW_ERASE
);
901 hwndCur
= curPtr
->hwndNext
;
907 /***********************************************************************
908 * WINPOS_SetXWindowPos
910 * SetWindowPos() for an X window. Used by the real SetWindowPos().
912 static void WINPOS_SetXWindowPos( WINDOWPOS
*winpos
)
914 XWindowChanges winChanges
;
916 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
918 if (!(winpos
->flags
& SWP_NOSIZE
))
920 winChanges
.width
= winpos
->cx
;
921 winChanges
.height
= winpos
->cy
;
922 changeMask
|= CWWidth
| CWHeight
;
924 if (!(winpos
->flags
& SWP_NOMOVE
))
926 winChanges
.x
= winpos
->x
;
927 winChanges
.y
= winpos
->y
;
928 changeMask
|= CWX
| CWY
;
930 if (!(winpos
->flags
& SWP_NOZORDER
))
932 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
933 else winChanges
.stack_mode
= Below
;
934 if ((winpos
->hwndInsertAfter
!= HWND_TOP
) &&
935 (winpos
->hwndInsertAfter
!= HWND_BOTTOM
))
937 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
938 winChanges
.sibling
= insertPtr
->window
;
939 changeMask
|= CWSibling
;
941 changeMask
|= CWStackMode
;
944 XConfigureWindow( display
, wndPtr
->window
, changeMask
, &winChanges
);
948 /***********************************************************************
949 * SetWindowPos (USER.232)
951 BOOL
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
, INT x
, INT y
,
952 INT cx
, INT cy
, WORD flags
)
956 RECT newWindowRect
, newClientRect
;
959 /* Check window handle */
961 if (hwnd
== GetDesktopWindow()) return FALSE
;
962 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
964 /* Check dimensions */
971 if (hwnd
== hwndActive
) flags
|= SWP_NOACTIVATE
; /* Already active */
972 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
973 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
974 flags
|= SWP_NOSIZE
; /* Already the right size */
975 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
976 flags
|= SWP_NOMOVE
; /* Already the right position */
978 /* Check hwndInsertAfter */
980 if (!(flags
& (SWP_NOZORDER
| SWP_NOACTIVATE
)))
982 /* Ignore TOPMOST flags when activating a window */
983 /* _and_ moving it in Z order. */
984 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
985 (hwndInsertAfter
== HWND_NOTOPMOST
))
986 hwndInsertAfter
= HWND_TOP
;
988 /* TOPMOST not supported yet */
989 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
990 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
991 /* hwndInsertAfter must be a sibling of the window */
992 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
) &&
993 (wndPtr
->hwndParent
!= WIN_FindWndPtr(hwndInsertAfter
)->hwndParent
))
996 /* Fill the WINDOWPOS structure */
999 winpos
.hwndInsertAfter
= hwndInsertAfter
;
1004 winpos
.flags
= flags
;
1006 /* Send WM_WINDOWPOSCHANGING message */
1008 if (!(flags
& SWP_NOSENDCHANGING
))
1009 SendMessage( hwnd
, WM_WINDOWPOSCHANGING
, 0, MAKE_SEGPTR(&winpos
) );
1011 /* Calculate new position and size */
1013 newWindowRect
= wndPtr
->rectWindow
;
1014 newClientRect
= wndPtr
->rectClient
;
1016 if (!(winpos
.flags
& SWP_NOSIZE
))
1018 newWindowRect
.right
= newWindowRect
.left
+ winpos
.cx
;
1019 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
.cy
;
1021 if (!(winpos
.flags
& SWP_NOMOVE
))
1023 newWindowRect
.left
= winpos
.x
;
1024 newWindowRect
.top
= winpos
.y
;
1025 newWindowRect
.right
+= winpos
.x
- wndPtr
->rectWindow
.left
;
1026 newWindowRect
.bottom
+= winpos
.y
- wndPtr
->rectWindow
.top
;
1029 /* Reposition window in Z order */
1031 if (!(winpos
.flags
& SWP_NOZORDER
))
1035 WIN_UnlinkWindow( winpos
.hwnd
);
1036 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
1038 else WINPOS_MoveWindowZOrder( winpos
.hwnd
, hwndInsertAfter
);
1041 /* Send WM_NCCALCSIZE message to get new client area */
1043 result
= WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
1044 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
1045 &winpos
, &newClientRect
);
1046 /* .... Should handle result here */
1048 /* Perform the moving and resizing */
1052 WINPOS_SetXWindowPos( &winpos
);
1053 wndPtr
->rectWindow
= newWindowRect
;
1054 wndPtr
->rectClient
= newClientRect
;
1058 RECT oldWindowRect
= wndPtr
->rectWindow
;
1060 wndPtr
->rectWindow
= newWindowRect
;
1061 wndPtr
->rectClient
= newClientRect
;
1063 if (!(flags
& SWP_NOREDRAW
) &&
1064 (!(flags
& SWP_NOSIZE
) || !(flags
& SWP_NOMOVE
) ||
1065 (!(flags
& SWP_NOZORDER
) && (hwndInsertAfter
!= HWND_TOP
))))
1067 HRGN hrgn1
= CreateRectRgnIndirect( &oldWindowRect
);
1068 HRGN hrgn2
= CreateRectRgnIndirect( &wndPtr
->rectWindow
);
1069 HRGN hrgn3
= CreateRectRgn( 0, 0, 0, 0 );
1070 CombineRgn( hrgn3
, hrgn1
, hrgn2
, RGN_DIFF
);
1071 RedrawWindow( wndPtr
->hwndParent
, NULL
, hrgn3
,
1072 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
);
1074 /* DCE_GetVisRgn should be called for old coordinates
1075 * and for new, then OffsetRgn and CombineRgn -
1076 * voila, a nice update region to use here - AK.
1078 if ((oldWindowRect
.left
!= wndPtr
->rectWindow
.left
) ||
1079 (oldWindowRect
.top
!= wndPtr
->rectWindow
.top
))
1081 RedrawWindow( winpos
.hwnd
, NULL
, 0, RDW_INVALIDATE
|
1082 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
);
1085 if( CombineRgn( hrgn3
, hrgn2
, hrgn1
, RGN_DIFF
) != NULLREGION
)
1086 RedrawWindow( winpos
.hwnd
, NULL
, hrgn3
, RDW_INVALIDATE
|
1087 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
);
1089 DeleteObject( hrgn1
);
1090 DeleteObject( hrgn2
);
1091 DeleteObject( hrgn3
);
1095 if (flags
& SWP_SHOWWINDOW
)
1097 wndPtr
->dwStyle
|= WS_VISIBLE
;
1100 XMapWindow( display
, wndPtr
->window
);
1104 if (!(flags
& SWP_NOREDRAW
))
1105 RedrawWindow( winpos
.hwnd
, NULL
, 0,
1106 RDW_INVALIDATE
| RDW_ALLCHILDREN
|
1107 RDW_FRAME
| RDW_ERASE
);
1110 else if (flags
& SWP_HIDEWINDOW
)
1112 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1115 XUnmapWindow( display
, wndPtr
->window
);
1119 if (!(flags
& SWP_NOREDRAW
))
1120 RedrawWindow( wndPtr
->hwndParent
, &wndPtr
->rectWindow
, 0,
1121 RDW_INVALIDATE
| RDW_FRAME
|
1122 RDW_ALLCHILDREN
| RDW_ERASE
);
1125 if ((winpos
.hwnd
== GetFocus()) || IsChild(winpos
.hwnd
, GetFocus()))
1126 SetFocus( GetParent(winpos
.hwnd
) ); /* Revert focus to parent */
1128 if (winpos
.hwnd
== hwndActive
)
1130 /* Activate previously active window if possible */
1131 HWND newActive
= hwndPrevActive
;
1132 if (!IsWindow(newActive
) || (newActive
== winpos
.hwnd
))
1134 newActive
= GetTopWindow( GetDesktopWindow() );
1135 if (newActive
== winpos
.hwnd
) newActive
= wndPtr
->hwndNext
;
1137 WINPOS_ChangeActiveWindow( newActive
, FALSE
);
1141 /* Activate the window */
1143 if (!(flags
& SWP_NOACTIVATE
))
1144 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
1146 /* Repaint the window */
1148 if (wndPtr
->window
) MSG_Synchronize(); /* Wait for all expose events */
1150 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
1152 if ((flags
& SWP_FRAMECHANGED
) && !(flags
& SWP_NOREDRAW
))
1153 RedrawWindow( winpos
.hwnd
, NULL
, 0,
1154 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
1155 if (!(flags
& SWP_DEFERERASE
))
1156 RedrawWindow( wndPtr
->hwndParent
, NULL
, 0,
1157 RDW_ALLCHILDREN
| RDW_ERASENOW
);
1159 /* And last, send the WM_WINDOWPOSCHANGED message */
1161 winpos
.flags
|= SWP_NOMOVE
; /* prevent looping.. window is already moved ??? (FIXME)*/
1163 if (!(winpos
.flags
& SWP_NOSENDCHANGING
))
1164 SendMessage( winpos
.hwnd
, WM_WINDOWPOSCHANGED
,
1165 0, MAKE_SEGPTR(&winpos
) );
1171 /***********************************************************************
1172 * BeginDeferWindowPos (USER.259)
1174 HDWP
BeginDeferWindowPos( INT count
)
1179 if (count
<= 0) return 0;
1180 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
1181 if (!handle
) return 0;
1182 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
1183 pDWP
->actualCount
= 0;
1184 pDWP
->suggestedCount
= count
;
1186 pDWP
->wMagic
= DWP_MAGIC
;
1187 pDWP
->hwndParent
= 0;
1192 /***********************************************************************
1193 * DeferWindowPos (USER.260)
1195 HDWP
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
, INT x
, INT y
,
1196 INT cx
, INT cy
, WORD flags
)
1200 HDWP newhdwp
= hdwp
;
1203 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
1204 if (!pDWP
) return 0;
1206 /* All the windows of a DeferWindowPos() must have the same parent */
1208 parent
= WIN_FindWndPtr( hwnd
)->hwndParent
;
1209 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
1210 else if (parent
!= pDWP
->hwndParent
)
1212 USER_HEAP_FREE( hdwp
);
1216 for (i
= 0; i
< pDWP
->actualCount
; i
++)
1218 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
1220 /* Merge with the other changes */
1221 if (!(flags
& SWP_NOZORDER
))
1223 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
1225 if (!(flags
& SWP_NOMOVE
))
1227 pDWP
->winPos
[i
].x
= x
;
1228 pDWP
->winPos
[i
].y
= y
;
1230 if (!(flags
& SWP_NOSIZE
))
1232 pDWP
->winPos
[i
].cx
= cx
;
1233 pDWP
->winPos
[i
].cy
= cy
;
1235 pDWP
->winPos
[i
].flags
&= flags
& (SWP_NOSIZE
| SWP_NOMOVE
|
1236 SWP_NOZORDER
| SWP_NOREDRAW
|
1237 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1239 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1244 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
1246 newhdwp
= USER_HEAP_REALLOC( hdwp
,
1247 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
1248 if (!newhdwp
) return 0;
1249 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
1250 pDWP
->suggestedCount
++;
1252 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
1253 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
1254 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
1255 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
1256 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
1257 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
1258 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
1259 pDWP
->actualCount
++;
1264 /***********************************************************************
1265 * EndDeferWindowPos (USER.261)
1267 BOOL
EndDeferWindowPos( HDWP hdwp
)
1274 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
1275 if (!pDWP
) return FALSE
;
1276 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
1278 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
1279 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
1280 winpos
->flags
))) break;
1282 USER_HEAP_FREE( hdwp
);
1287 /***********************************************************************
1288 * TileChildWindows (USER.199)
1290 void TileChildWindows( HWND parent
, WORD action
)
1292 printf("STUB TileChildWindows("NPFMT
", %d)\n", parent
, action
);
1295 /***********************************************************************
1296 * CascageChildWindows (USER.198)
1298 void CascadeChildWindows( HWND parent
, WORD action
)
1300 printf("STUB CascadeChildWindows("NPFMT
", %d)\n", parent
, action
);