1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
27 *
28 * Authors:	Kensuke Matsuzaki
29 *		Earle F. Philhower, III
30 *		Harold L Hunt II
31 */
32
33#ifdef HAVE_XWIN_CONFIG_H
34#include <xwin-config.h>
35#endif
36#include "win.h"
37#include "winprefs.h"
38
39#if 0
40/*
41 * winMWExtWMReorderWindows
42 */
43
44void
45winMWExtWMReorderWindows (ScreenPtr pScreen)
46{
47  winScreenPriv(pScreen);
48  HWND hwnd = NULL;
49  win32RootlessWindowPtr pRLWin = NULL;
50  win32RootlessWindowPtr pRLWinSib = NULL;
51  DWORD dwCurrentProcessID = GetCurrentProcessId ();
52  DWORD dwWindowProcessID = 0;
53  XID vlist[2];
54
55#if CYGMULTIWINDOW_DEBUG && FALSE
56  winDebug ("winMWExtWMReorderWindows\n");
57#endif
58
59  pScreenPriv->fRestacking = TRUE;
60
61  if (pScreenPriv->fWindowOrderChanged)
62    {
63#if CYGMULTIWINDOW_DEBUG
64      winDebug ("winMWExtWMReorderWindows - Need to restack\n");
65#endif
66      hwnd = GetTopWindow (NULL);
67
68      while (hwnd)
69	{
70	  GetWindowThreadProcessId (hwnd, &dwWindowProcessID);
71
72	  if ((dwWindowProcessID == dwCurrentProcessID)
73	      && GetProp (hwnd, WIN_WINDOW_PROP))
74	    {
75	      pRLWinSib = pRLWin;
76	      pRLWin = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP);
77
78	      if (pRLWinSib)
79		{
80		  vlist[0] = pRLWinSib->pFrame->win->drawable.id;
81		  vlist[1] = Below;
82
83		  ConfigureWindow (pRLWin->pFrame->win, CWSibling | CWStackMode,
84				   vlist, wClient(pRLWin->pFrame->win));
85		}
86	      else
87		{
88		  /* 1st window - raise to the top */
89		  vlist[0] = Above;
90
91		  ConfigureWindow (pRLWin->pFrame->win, CWStackMode,
92				   vlist, wClient(pRLWin->pFrame->win));
93		}
94	    }
95	  hwnd = GetNextWindow (hwnd, GW_HWNDNEXT);
96	}
97    }
98
99  pScreenPriv->fRestacking = FALSE;
100  pScreenPriv->fWindowOrderChanged = FALSE;
101}
102#endif
103
104
105/*
106 * winMWExtWMMoveXWindow
107 */
108
109void
110winMWExtWMMoveXWindow (WindowPtr pWin, int x, int y)
111{
112  CARD32 *vlist = malloc(sizeof(CARD32)*2);
113
114  vlist[0] = x;
115  vlist[1] = y;
116  ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin));
117  free(vlist);
118}
119
120
121/*
122 * winMWExtWMResizeXWindow
123 */
124
125void
126winMWExtWMResizeXWindow (WindowPtr pWin, int w, int h)
127{
128  CARD32 *vlist = malloc(sizeof(CARD32)*2);
129
130  vlist[0] = w;
131  vlist[1] = h;
132  ConfigureWindow (pWin, CWWidth | CWHeight, vlist, wClient(pWin));
133  free(vlist);
134}
135
136
137/*
138 * winMWExtWMMoveResizeXWindow
139 */
140
141void
142winMWExtWMMoveResizeXWindow (WindowPtr pWin, int x, int y, int w, int h)
143{
144  CARD32 *vlist = malloc(sizeof(long)*4);
145
146  vlist[0] = x;
147  vlist[1] = y;
148  vlist[2] = w;
149  vlist[3] = h;
150
151  ConfigureWindow (pWin, CWX | CWY | CWWidth | CWHeight, vlist, wClient(pWin));
152  free(vlist);
153}
154
155
156/*
157 * winMWExtWMUpdateIcon
158 * Change the Windows window icon
159 */
160
161void
162winMWExtWMUpdateIcon (Window id)
163{
164  WindowPtr		pWin;
165  HICON			hIcon, hiconOld;
166
167  dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess);
168  hIcon = winOverrideIcon ((unsigned long)pWin);
169
170  if (!hIcon)
171    hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXICON));
172
173  if (hIcon)
174    {
175      win32RootlessWindowPtr pRLWinPriv
176	= (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
177
178      if (pRLWinPriv->hWnd)
179	{
180
181          hiconOld = (HICON) SendMessage (pRLWinPriv->hWnd,
182                     WM_SETICON, ICON_BIG, (LPARAM) hIcon);
183          winDestroyIcon(hiconOld);
184	}
185      hIcon=NULL;
186    }
187}
188
189
190/*
191 * winMWExtWMDecorateWindow - Update window style. Called by EnumWindows.
192 */
193
194wBOOL CALLBACK
195winMWExtWMDecorateWindow (HWND hwnd, LPARAM lParam)
196{
197  win32RootlessWindowPtr pRLWinPriv = NULL;
198  ScreenPtr		pScreen = NULL;
199  winPrivScreenPtr	pScreenPriv = NULL;
200  winScreenInfo		*pScreenInfo = NULL;
201
202  /* Check if the Windows window property for our X window pointer is valid */
203  if ((pRLWinPriv = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
204    {
205      pScreen				= pRLWinPriv->pFrame->win->drawable.pScreen;
206      if (pScreen) pScreenPriv		= winGetScreenPriv(pScreen);
207      if (pScreenPriv) pScreenInfo	= pScreenPriv->pScreenInfo;
208      if (pRLWinPriv && pScreenInfo) winMWExtWMUpdateWindowDecoration (pRLWinPriv, pScreenInfo);
209    }
210  return TRUE;
211}
212
213
214/*
215 * winMWExtWMUpdateWindowDecoration - Update window style.
216 */
217
218void
219winMWExtWMUpdateWindowDecoration (win32RootlessWindowPtr pRLWinPriv,
220				  winScreenInfoPtr pScreenInfo)
221{
222  Bool		fDecorate = FALSE;
223  DWORD		dwExStyle = 0;
224  DWORD		dwStyle = 0;
225  WINDOWPLACEMENT wndPlace;
226  UINT		showCmd = 0;
227
228  wndPlace.length = sizeof (WINDOWPLACEMENT);
229
230  /* Get current window placement */
231  GetWindowPlacement (pRLWinPriv->hWnd, &wndPlace);
232
233  if (winIsInternalWMRunning(pScreenInfo))
234    {
235      if (!pRLWinPriv->pFrame->win->overrideRedirect)
236	fDecorate = TRUE;
237    }
238#if 0
239  if (wndPlace.showCmd == SW_HIDE)
240    return;//showCmd = SWP_HIDEWINDOW;
241  else
242    showCmd = SWP_SHOWWINDOW;
243#else
244  if (wndPlace.showCmd == SW_HIDE)
245    return;
246
247  if (IsWindowVisible (pRLWinPriv->hWnd))
248    showCmd = SWP_SHOWWINDOW;
249#endif
250
251  showCmd |= SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER;
252
253  winDebug ("winMWExtWMUpdateWindowDecoration %08x %s\n",
254	    (int)pRLWinPriv, fDecorate?"Decorate":"Bare");
255
256  /* Get the standard and extended window style information */
257  dwExStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE);
258  dwStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE);
259
260  if (fDecorate)
261    {
262      RECT		rcNew;
263      int		iDx, iDy;
264      winWMMessageRec	wmMsg;
265      winScreenPriv(pScreenInfo->pScreen);
266
267      /* */
268      if (!(dwExStyle & WS_EX_APPWINDOW))
269	{
270	  winDebug ("\tBare=>Decorate\n");
271	  /* Setup a rectangle with the X window position and size */
272	  SetRect (&rcNew,
273		   pRLWinPriv->pFrame->x,
274		   pRLWinPriv->pFrame->y,
275		   pRLWinPriv->pFrame->x + pRLWinPriv->pFrame->width,
276		   pRLWinPriv->pFrame->y + pRLWinPriv->pFrame->height);
277
278#ifdef CYGMULTIWINDOW_DEBUG
279          winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n",
280              rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
281              rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
282#endif
283	  /* */
284	  AdjustWindowRectEx (&rcNew,
285			      WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW,
286			      FALSE,
287			      WS_EX_APPWINDOW);
288
289#ifdef CYGMULTIWINDOW_DEBUG
290          winDebug("\tAdjusted {%d, %d, %d, %d}, {%d, %d}\n",
291              rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
292              rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
293#endif
294	  /* Calculate position deltas */
295	  iDx = pRLWinPriv->pFrame->x - rcNew.left;
296	  iDy = pRLWinPriv->pFrame->y - rcNew.top;
297
298	  /* Calculate new rectangle */
299	  rcNew.left += iDx;
300	  rcNew.right += iDx;
301	  rcNew.top += iDy;
302	  rcNew.bottom += iDy;
303
304	  /* Set the window extended style flags */
305	  SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
306
307	  /* Set the window standard style flags */
308	  SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE,
309			    WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW);
310
311#ifdef CYGMULTIWINDOW_DEBUG
312          winDebug("\tWindowStyle: %08x %08x\n",
313              WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW,
314              WS_EX_APPWINDOW);
315#endif
316	  /* Position the Windows window */
317#ifdef CYGMULTIWINDOW_DEBUG
318          winDebug("\tMoved {%d, %d, %d, %d}, {%d, %d}\n",
319              rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
320              rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
321#endif
322	  SetWindowPos (pRLWinPriv->hWnd, NULL,
323			rcNew.left, rcNew.top,
324			rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
325			showCmd);
326
327
328	  wmMsg.hwndWindow = pRLWinPriv->hWnd;
329	  wmMsg.iWindow	= (Window)pRLWinPriv->pFrame->win->drawable.id;
330	  wmMsg.msg = WM_WM_NAME_EVENT;
331	  winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
332
333	  winMWExtWMReshapeFrame ((RootlessFrameID)pRLWinPriv ,
334				  wBoundingShape(pRLWinPriv->pFrame->win));
335	}
336    }
337  else
338    {
339      RECT		rcNew;
340
341      /* */
342      if (dwExStyle & WS_EX_APPWINDOW)
343	{
344	  winDebug ("\tDecorate=>Bare\n");
345	  /* Setup a rectangle with the X window position and size */
346	  SetRect (&rcNew,
347		   pRLWinPriv->pFrame->x,
348		   pRLWinPriv->pFrame->y,
349		   pRLWinPriv->pFrame->x + pRLWinPriv->pFrame->width,
350		   pRLWinPriv->pFrame->y + pRLWinPriv->pFrame->height);
351#if 0
352	  /* */
353	  AdjustWindowRectEx (&rcNew,
354			      WS_POPUP | WS_CLIPCHILDREN,
355			      FALSE,
356			      WS_EX_TOOLWINDOW);
357
358	  /* Calculate position deltas */
359	  iDx = pRLWinPriv->pFrame->x - rcNew.left;
360	  iDy = pRLWinPriv->pFrame->y - rcNew.top;
361
362	  /* Calculate new rectangle */
363	  rcNew.left += iDx;
364	  rcNew.right += iDx;
365	  rcNew.top += iDy;
366	  rcNew.bottom += iDy;
367#endif
368
369	  /* Hide window temporary to remove from taskbar. */
370	  ShowWindow( pRLWinPriv->hWnd, SW_HIDE );
371
372	  /* Set the window extended style flags */
373	  SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
374
375	  /* Set the window standard style flags */
376	  SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE,
377			    WS_POPUP | WS_CLIPCHILDREN);
378
379	  /* Position the Windows window */
380	  SetWindowPos (pRLWinPriv->hWnd, NULL,
381			rcNew.left, rcNew.top,
382			rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
383			showCmd);
384
385	  winMWExtWMReshapeFrame ((RootlessFrameID)pRLWinPriv ,
386				  wBoundingShape(pRLWinPriv->pFrame->win));
387	}
388    }
389}
390
391
392/*
393 * winIsInternalWMRunning (winScreenInfoPtr pScreenInfo)
394 */
395Bool
396winIsInternalWMRunning (winScreenInfoPtr pScreenInfo)
397{
398  return pScreenInfo->fInternalWM && !pScreenInfo->fAnotherWMRunning;
399}
400
401
402/*
403 * winMWExtWMRestackWindows
404 */
405
406void
407winMWExtWMRestackWindows (ScreenPtr pScreen)
408{
409  winScreenPriv(pScreen);
410  WindowPtr pRoot = pScreen->root;
411  WindowPtr pWin = NULL;
412  WindowPtr pWinPrev = NULL;
413  win32RootlessWindowPtr pRLWin = NULL;
414  win32RootlessWindowPtr pRLWinPrev = NULL;
415  int  nWindow = 0;
416  HDWP hWinPosInfo = NULL;
417
418#if CYGMULTIWINDOW_DEBUG
419  winDebug ("winMWExtWMRestackWindows\n");
420#endif
421
422  pScreenPriv->fRestacking = TRUE;
423
424  if (pRoot != NULL)
425    {
426      for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib)
427	nWindow ++;
428
429      hWinPosInfo = BeginDeferWindowPos(nWindow);
430
431      for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib)
432	{
433	  if (pWin->realized)
434	    {
435	      UINT uFlags;
436
437	      pRLWin = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
438	      if (pRLWin == NULL) continue;
439
440	      if (pWinPrev)
441		pRLWinPrev = (win32RootlessWindowPtr) RootlessFrameForWindow (pWinPrev, FALSE);
442
443	      uFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW;
444	      if (pRLWinPrev != NULL) uFlags |= SWP_NOACTIVATE;
445
446#if CYGMULTIWINDOW_DEBUG
447	      winDebug ("winMWExtWMRestackWindows - DeferWindowPos (%08x, %08x)\n",
448			pRLWin->hWnd,
449			pRLWinPrev ? pRLWinPrev->hWnd : HWND_TOP);
450#endif
451	      hWinPosInfo = DeferWindowPos (hWinPosInfo, pRLWin->hWnd,
452					    pRLWinPrev ? pRLWinPrev->hWnd : HWND_TOP,
453					    0, 0, 0, 0,
454					    uFlags);
455	      if (hWinPosInfo == NULL)
456		{
457		  ErrorF ("winMWExtWMRestackWindows - DeferWindowPos () failed: %d\n",
458			  (int) GetLastError ());
459		  return;
460		}
461	      pWinPrev = pWin;
462	    }
463	}
464      if (!EndDeferWindowPos (hWinPosInfo))
465	{
466	  ErrorF ("winMWExtWMRestackWindows - EndDeferWindowPos () failed: %d\n",
467		  (int) GetLastError ());
468	  return;
469	}
470    }
471
472#if CYGMULTIWINDOW_DEBUG
473  winDebug ("winMWExtWMRestackWindows - done\n");
474#endif
475  pScreenPriv->fRestacking = FALSE;
476}
477