1706f2543Smrg/*
2706f2543Smrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3706f2543Smrg *Copyright (C) Colin Harrison 2005-2008
4706f2543Smrg *
5706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining
6706f2543Smrg * a copy of this software and associated documentation files (the
7706f2543Smrg *"Software"), to deal in the Software without restriction, including
8706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish,
9706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to
10706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to
11706f2543Smrg *the following conditions:
12706f2543Smrg *
13706f2543Smrg *The above copyright notice and this permission notice shall be
14706f2543Smrg *included in all copies or substantial portions of the Software.
15706f2543Smrg *
16706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23706f2543Smrg *
24706f2543Smrg *Except as contained in this notice, the name of the XFree86 Project
25706f2543Smrg *shall not be used in advertising or otherwise to promote the sale, use
26706f2543Smrg *or other dealings in this Software without prior written authorization
27706f2543Smrg *from the XFree86 Project.
28706f2543Smrg *
29706f2543Smrg * Authors:	Kensuke Matsuzaki
30706f2543Smrg *		Earle F. Philhower, III
31706f2543Smrg *		Harold L Hunt II
32706f2543Smrg *              Colin Harrison
33706f2543Smrg */
34706f2543Smrg
35706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
36706f2543Smrg#include <xwin-config.h>
37706f2543Smrg#endif
38706f2543Smrg#include "win.h"
39706f2543Smrg#include "dixevents.h"
40706f2543Smrg#include "winmultiwindowclass.h"
41706f2543Smrg#include "winprefs.h"
42706f2543Smrg#include "winmsg.h"
43706f2543Smrg#include "inputstr.h"
44706f2543Smrg
45706f2543Smrgextern void winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle);
46706f2543Smrg
47706f2543Smrg
48706f2543Smrg/*
49706f2543Smrg * Local globals
50706f2543Smrg */
51706f2543Smrg
52706f2543Smrgstatic UINT_PTR		g_uipMousePollingTimerID = 0;
53706f2543Smrg
54706f2543Smrg
55706f2543Smrg/*
56706f2543Smrg * Constant defines
57706f2543Smrg */
58706f2543Smrg
59706f2543Smrg#define WIN_MULTIWINDOW_SHAPE		YES
60706f2543Smrg
61706f2543Smrg
62706f2543Smrg/*
63706f2543Smrg * ConstrainSize - Taken from TWM sources - Respects hints for sizing
64706f2543Smrg */
65706f2543Smrg#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
66706f2543Smrgstatic void
67706f2543SmrgConstrainSize (WinXSizeHints hints, int *widthp, int *heightp)
68706f2543Smrg{
69706f2543Smrg  int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
70706f2543Smrg  int baseWidth, baseHeight;
71706f2543Smrg  int dwidth = *widthp, dheight = *heightp;
72706f2543Smrg
73706f2543Smrg  if (hints.flags & PMinSize)
74706f2543Smrg    {
75706f2543Smrg      minWidth = hints.min_width;
76706f2543Smrg      minHeight = hints.min_height;
77706f2543Smrg    }
78706f2543Smrg  else if (hints.flags & PBaseSize)
79706f2543Smrg    {
80706f2543Smrg      minWidth = hints.base_width;
81706f2543Smrg      minHeight = hints.base_height;
82706f2543Smrg    }
83706f2543Smrg  else
84706f2543Smrg    minWidth = minHeight = 1;
85706f2543Smrg
86706f2543Smrg  if (hints.flags & PBaseSize)
87706f2543Smrg    {
88706f2543Smrg      baseWidth = hints.base_width;
89706f2543Smrg      baseHeight = hints.base_height;
90706f2543Smrg    }
91706f2543Smrg  else if (hints.flags & PMinSize)
92706f2543Smrg    {
93706f2543Smrg      baseWidth = hints.min_width;
94706f2543Smrg      baseHeight = hints.min_height;
95706f2543Smrg    }
96706f2543Smrg  else
97706f2543Smrg    baseWidth = baseHeight = 0;
98706f2543Smrg
99706f2543Smrg  if (hints.flags & PMaxSize)
100706f2543Smrg    {
101706f2543Smrg      maxWidth = hints.max_width;
102706f2543Smrg      maxHeight = hints.max_height;
103706f2543Smrg    }
104706f2543Smrg  else
105706f2543Smrg    {
106706f2543Smrg      maxWidth = MAXINT;
107706f2543Smrg      maxHeight = MAXINT;
108706f2543Smrg    }
109706f2543Smrg
110706f2543Smrg  if (hints.flags & PResizeInc)
111706f2543Smrg    {
112706f2543Smrg      xinc = hints.width_inc;
113706f2543Smrg      yinc = hints.height_inc;
114706f2543Smrg    }
115706f2543Smrg  else
116706f2543Smrg    xinc = yinc = 1;
117706f2543Smrg
118706f2543Smrg  /*
119706f2543Smrg   * First, clamp to min and max values
120706f2543Smrg   */
121706f2543Smrg  if (dwidth < minWidth)
122706f2543Smrg    dwidth = minWidth;
123706f2543Smrg  if (dheight < minHeight)
124706f2543Smrg    dheight = minHeight;
125706f2543Smrg
126706f2543Smrg  if (dwidth > maxWidth)
127706f2543Smrg    dwidth = maxWidth;
128706f2543Smrg  if (dheight > maxHeight)
129706f2543Smrg    dheight = maxHeight;
130706f2543Smrg
131706f2543Smrg  /*
132706f2543Smrg   * Second, fit to base + N * inc
133706f2543Smrg   */
134706f2543Smrg  dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
135706f2543Smrg  dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
136706f2543Smrg
137706f2543Smrg  /*
138706f2543Smrg   * Third, adjust for aspect ratio
139706f2543Smrg   */
140706f2543Smrg
141706f2543Smrg  /*
142706f2543Smrg   * The math looks like this:
143706f2543Smrg   *
144706f2543Smrg   * minAspectX    dwidth     maxAspectX
145706f2543Smrg   * ---------- <= ------- <= ----------
146706f2543Smrg   * minAspectY    dheight    maxAspectY
147706f2543Smrg   *
148706f2543Smrg   * If that is multiplied out, then the width and height are
149706f2543Smrg   * invalid in the following situations:
150706f2543Smrg   *
151706f2543Smrg   * minAspectX * dheight > minAspectY * dwidth
152706f2543Smrg   * maxAspectX * dheight < maxAspectY * dwidth
153706f2543Smrg   *
154706f2543Smrg   */
155706f2543Smrg
156706f2543Smrg  if (hints.flags & PAspect)
157706f2543Smrg    {
158706f2543Smrg      if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth)
159706f2543Smrg        {
160706f2543Smrg	  delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc);
161706f2543Smrg	  if (dwidth + delta <= maxWidth)
162706f2543Smrg	    dwidth += delta;
163706f2543Smrg	  else
164706f2543Smrg            {
165706f2543Smrg	      delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc);
166706f2543Smrg	      if (dheight - delta >= minHeight)
167706f2543Smrg		dheight -= delta;
168706f2543Smrg            }
169706f2543Smrg        }
170706f2543Smrg
171706f2543Smrg      if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth)
172706f2543Smrg        {
173706f2543Smrg	  delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc);
174706f2543Smrg	  if (dheight + delta <= maxHeight)
175706f2543Smrg	    dheight += delta;
176706f2543Smrg	  else
177706f2543Smrg            {
178706f2543Smrg	      delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc);
179706f2543Smrg	      if (dwidth - delta >= minWidth)
180706f2543Smrg		dwidth -= delta;
181706f2543Smrg            }
182706f2543Smrg        }
183706f2543Smrg    }
184706f2543Smrg
185706f2543Smrg  /* Return computed values */
186706f2543Smrg  *widthp = dwidth;
187706f2543Smrg  *heightp = dheight;
188706f2543Smrg}
189706f2543Smrg#undef makemult
190706f2543Smrg
191706f2543Smrg
192706f2543Smrg
193706f2543Smrg/*
194706f2543Smrg * ValidateSizing - Ensures size request respects hints
195706f2543Smrg */
196706f2543Smrgstatic int
197706f2543SmrgValidateSizing (HWND hwnd, WindowPtr pWin,
198706f2543Smrg		WPARAM wParam, LPARAM lParam)
199706f2543Smrg{
200706f2543Smrg  WinXSizeHints sizeHints;
201706f2543Smrg  RECT *rect;
202706f2543Smrg  int iWidth, iHeight;
203706f2543Smrg  RECT rcClient, rcWindow;
204706f2543Smrg  int iBorderWidthX, iBorderWidthY;
205706f2543Smrg
206706f2543Smrg  /* Invalid input checking */
207706f2543Smrg  if (pWin==NULL || lParam==0)
208706f2543Smrg    return FALSE;
209706f2543Smrg
210706f2543Smrg  /* No size hints, no checking */
211706f2543Smrg  if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints))
212706f2543Smrg    return FALSE;
213706f2543Smrg
214706f2543Smrg  /* Avoid divide-by-zero */
215706f2543Smrg  if (sizeHints.flags & PResizeInc)
216706f2543Smrg    {
217706f2543Smrg      if (sizeHints.width_inc == 0) sizeHints.width_inc = 1;
218706f2543Smrg      if (sizeHints.height_inc == 0) sizeHints.height_inc = 1;
219706f2543Smrg    }
220706f2543Smrg
221706f2543Smrg  rect = (RECT*)lParam;
222706f2543Smrg
223706f2543Smrg  iWidth = rect->right - rect->left;
224706f2543Smrg  iHeight = rect->bottom - rect->top;
225706f2543Smrg
226706f2543Smrg  /* Now remove size of any borders and title bar */
227706f2543Smrg  GetClientRect(hwnd, &rcClient);
228706f2543Smrg  GetWindowRect(hwnd, &rcWindow);
229706f2543Smrg  iBorderWidthX = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
230706f2543Smrg  iBorderWidthY = (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
231706f2543Smrg  iWidth -= iBorderWidthX;
232706f2543Smrg  iHeight -= iBorderWidthY;
233706f2543Smrg
234706f2543Smrg  /* Constrain the size to legal values */
235706f2543Smrg  ConstrainSize (sizeHints, &iWidth, &iHeight);
236706f2543Smrg
237706f2543Smrg  /* Add back the size of borders and title bar */
238706f2543Smrg  iWidth += iBorderWidthX;
239706f2543Smrg  iHeight += iBorderWidthY;
240706f2543Smrg
241706f2543Smrg  /* Adjust size according to where we're dragging from */
242706f2543Smrg  switch(wParam) {
243706f2543Smrg  case WMSZ_TOP:
244706f2543Smrg  case WMSZ_TOPRIGHT:
245706f2543Smrg  case WMSZ_BOTTOM:
246706f2543Smrg  case WMSZ_BOTTOMRIGHT:
247706f2543Smrg  case WMSZ_RIGHT:
248706f2543Smrg    rect->right = rect->left + iWidth;
249706f2543Smrg    break;
250706f2543Smrg  default:
251706f2543Smrg    rect->left = rect->right - iWidth;
252706f2543Smrg    break;
253706f2543Smrg  }
254706f2543Smrg  switch(wParam) {
255706f2543Smrg  case WMSZ_BOTTOM:
256706f2543Smrg  case WMSZ_BOTTOMRIGHT:
257706f2543Smrg  case WMSZ_BOTTOMLEFT:
258706f2543Smrg  case WMSZ_RIGHT:
259706f2543Smrg  case WMSZ_LEFT:
260706f2543Smrg    rect->bottom = rect->top + iHeight;
261706f2543Smrg    break;
262706f2543Smrg  default:
263706f2543Smrg    rect->top = rect->bottom - iHeight;
264706f2543Smrg    break;
265706f2543Smrg  }
266706f2543Smrg  return TRUE;
267706f2543Smrg}
268706f2543Smrg
269706f2543Smrgextern Bool winInDestroyWindowsWindow;
270706f2543Smrgstatic Bool winInRaiseWindow = FALSE;
271706f2543Smrgstatic void winRaiseWindow(WindowPtr pWin)
272706f2543Smrg{
273706f2543Smrg  if (!winInDestroyWindowsWindow && !winInRaiseWindow)
274706f2543Smrg  {
275706f2543Smrg    BOOL oldstate = winInRaiseWindow;
276706f2543Smrg    XID vlist[1] = { 0 };
277706f2543Smrg    winInRaiseWindow = TRUE;
278706f2543Smrg    /* Call configure window directly to make sure it gets processed
279706f2543Smrg     * in time
280706f2543Smrg     */
281706f2543Smrg    ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
282706f2543Smrg    winInRaiseWindow = oldstate;
283706f2543Smrg  }
284706f2543Smrg}
285706f2543Smrg
286706f2543Smrgstatic
287706f2543Smrgvoid winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
288706f2543Smrg{
289706f2543Smrg  /*
290706f2543Smrg   * Timer to poll mouse position.  This is needed to make
291706f2543Smrg   * programs like xeyes follow the mouse properly when the
292706f2543Smrg   * mouse pointer is outside of any X window.
293706f2543Smrg   */
294706f2543Smrg  if (g_uipMousePollingTimerID == 0)
295706f2543Smrg    g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
296706f2543Smrg					 WIN_POLLING_MOUSE_TIMER_ID,
297706f2543Smrg					 MOUSE_POLLING_INTERVAL,
298706f2543Smrg					 NULL);
299706f2543Smrg}
300706f2543Smrg
301706f2543Smrg/*
302706f2543Smrg * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
303706f2543Smrg */
304706f2543Smrg
305706f2543SmrgLRESULT CALLBACK
306706f2543SmrgwinTopLevelWindowProc (HWND hwnd, UINT message,
307706f2543Smrg		       WPARAM wParam, LPARAM lParam)
308706f2543Smrg{
309706f2543Smrg  POINT			ptMouse;
310706f2543Smrg  HDC			hdcUpdate;
311706f2543Smrg  PAINTSTRUCT		ps;
312706f2543Smrg  WindowPtr		pWin = NULL;
313706f2543Smrg  winPrivWinPtr	        pWinPriv = NULL;
314706f2543Smrg  ScreenPtr		s_pScreen = NULL;
315706f2543Smrg  winPrivScreenPtr	s_pScreenPriv = NULL;
316706f2543Smrg  winScreenInfo		*s_pScreenInfo = NULL;
317706f2543Smrg  HWND			hwndScreen = NULL;
318706f2543Smrg  DrawablePtr		pDraw = NULL;
319706f2543Smrg  winWMMessageRec	wmMsg;
320706f2543Smrg  Bool                  fWMMsgInitialized = FALSE;
321706f2543Smrg  static Bool		s_fTracking = FALSE;
322706f2543Smrg  Bool			needRestack = FALSE;
323706f2543Smrg  LRESULT		ret;
324706f2543Smrg
325706f2543Smrg#if CYGDEBUG
326706f2543Smrg  winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam, lParam);
327706f2543Smrg#endif
328706f2543Smrg
329706f2543Smrg  /* Check if the Windows window property for our X window pointer is valid */
330706f2543Smrg  if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
331706f2543Smrg    {
332706f2543Smrg      /* Our X window pointer is valid */
333706f2543Smrg
334706f2543Smrg      /* Get pointers to the drawable and the screen */
335706f2543Smrg      pDraw		= &pWin->drawable;
336706f2543Smrg      s_pScreen		= pWin->drawable.pScreen;
337706f2543Smrg
338706f2543Smrg      /* Get a pointer to our window privates */
339706f2543Smrg      pWinPriv		= winGetWindowPriv(pWin);
340706f2543Smrg
341706f2543Smrg      /* Get pointers to our screen privates and screen info */
342706f2543Smrg      s_pScreenPriv	= pWinPriv->pScreenPriv;
343706f2543Smrg      s_pScreenInfo	= s_pScreenPriv->pScreenInfo;
344706f2543Smrg
345706f2543Smrg      /* Get the handle for our screen-sized window */
346706f2543Smrg      hwndScreen	= s_pScreenPriv->hwndScreen;
347706f2543Smrg
348706f2543Smrg      /* */
349706f2543Smrg      wmMsg.msg		= 0;
350706f2543Smrg      wmMsg.hwndWindow	= hwnd;
351706f2543Smrg      wmMsg.iWindow	= (Window)GetProp (hwnd, WIN_WID_PROP);
352706f2543Smrg
353706f2543Smrg      wmMsg.iX		= pDraw->x;
354706f2543Smrg      wmMsg.iY		= pDraw->y;
355706f2543Smrg      wmMsg.iWidth	= pDraw->width;
356706f2543Smrg      wmMsg.iHeight	= pDraw->height;
357706f2543Smrg
358706f2543Smrg      fWMMsgInitialized = TRUE;
359706f2543Smrg
360706f2543Smrg#if 0
361706f2543Smrg      /*
362706f2543Smrg       * Print some debugging information
363706f2543Smrg       */
364706f2543Smrg
365706f2543Smrg      ErrorF ("hWnd %08X\n", hwnd);
366706f2543Smrg      ErrorF ("pWin %08X\n", pWin);
367706f2543Smrg      ErrorF ("pDraw %08X\n", pDraw);
368706f2543Smrg      ErrorF ("\ttype %08X\n", pWin->drawable.type);
369706f2543Smrg      ErrorF ("\tclass %08X\n", pWin->drawable.class);
370706f2543Smrg      ErrorF ("\tdepth %08X\n", pWin->drawable.depth);
371706f2543Smrg      ErrorF ("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
372706f2543Smrg      ErrorF ("\tid %08X\n", pWin->drawable.id);
373706f2543Smrg      ErrorF ("\tx %08X\n", pWin->drawable.x);
374706f2543Smrg      ErrorF ("\ty %08X\n", pWin->drawable.y);
375706f2543Smrg      ErrorF ("\twidth %08X\n", pWin->drawable.width);
376706f2543Smrg      ErrorF ("\thenght %08X\n", pWin->drawable.height);
377706f2543Smrg      ErrorF ("\tpScreen %08X\n", pWin->drawable.pScreen);
378706f2543Smrg      ErrorF ("\tserialNumber %08X\n", pWin->drawable.serialNumber);
379706f2543Smrg      ErrorF ("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
380706f2543Smrg      ErrorF ("pWinPriv %08X\n", pWinPriv);
381706f2543Smrg      ErrorF ("s_pScreenPriv %08X\n", s_pScreenPriv);
382706f2543Smrg      ErrorF ("s_pScreenInfo %08X\n", s_pScreenInfo);
383706f2543Smrg      ErrorF ("hwndScreen %08X\n", hwndScreen);
384706f2543Smrg#endif
385706f2543Smrg    }
386706f2543Smrg
387706f2543Smrg  /* Branch on message type */
388706f2543Smrg  switch (message)
389706f2543Smrg    {
390706f2543Smrg    case WM_CREATE:
391706f2543Smrg
392706f2543Smrg      /* */
393706f2543Smrg      SetProp (hwnd,
394706f2543Smrg	       WIN_WINDOW_PROP,
395706f2543Smrg	       (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams);
396706f2543Smrg
397706f2543Smrg      /* */
398706f2543Smrg      SetProp (hwnd,
399706f2543Smrg	       WIN_WID_PROP,
400706f2543Smrg	       (HANDLE)winGetWindowID (((LPCREATESTRUCT) lParam)->lpCreateParams));
401706f2543Smrg
402706f2543Smrg      /*
403706f2543Smrg       * Make X windows' Z orders sync with Windows windows because
404706f2543Smrg       * there can be AlwaysOnTop windows overlapped on the window
405706f2543Smrg       * currently being created.
406706f2543Smrg       */
407706f2543Smrg      winReorderWindowsMultiWindow ();
408706f2543Smrg
409706f2543Smrg      /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
410706f2543Smrg      {
411706f2543Smrg        RECT rWindow;
412706f2543Smrg        HRGN hRgnWindow;
413706f2543Smrg        GetWindowRect(hwnd, &rWindow);
414706f2543Smrg        hRgnWindow = CreateRectRgnIndirect(&rWindow);
415706f2543Smrg        SetWindowRgn (hwnd, hRgnWindow, TRUE);
416706f2543Smrg        DeleteObject(hRgnWindow);
417706f2543Smrg      }
418706f2543Smrg
419706f2543Smrg      SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)XMING_SIGNATURE);
420706f2543Smrg
421706f2543Smrg      return 0;
422706f2543Smrg
423706f2543Smrg    case WM_INIT_SYS_MENU:
424706f2543Smrg      /*
425706f2543Smrg       * Add whatever the setup file wants to for this window
426706f2543Smrg       */
427706f2543Smrg      SetupSysMenu ((unsigned long)hwnd);
428706f2543Smrg      return 0;
429706f2543Smrg
430706f2543Smrg    case WM_SYSCOMMAND:
431706f2543Smrg      /*
432706f2543Smrg       * Any window menu items go through here
433706f2543Smrg       */
434706f2543Smrg      if (HandleCustomWM_COMMAND ((unsigned long)hwnd, LOWORD(wParam)))
435706f2543Smrg      {
436706f2543Smrg        /* Don't pass customized menus to DefWindowProc */
437706f2543Smrg        return 0;
438706f2543Smrg      }
439706f2543Smrg      if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE)
440706f2543Smrg      {
441706f2543Smrg        WINDOWPLACEMENT wndpl;
442706f2543Smrg	wndpl.length = sizeof(wndpl);
443706f2543Smrg	if (GetWindowPlacement(hwnd, &wndpl) && wndpl.showCmd == SW_SHOWMINIMIZED)
444706f2543Smrg          needRestack = TRUE;
445706f2543Smrg      }
446706f2543Smrg      break;
447706f2543Smrg
448706f2543Smrg    case WM_INITMENU:
449706f2543Smrg      /* Checks/Unchecks any menu items before they are displayed */
450706f2543Smrg      HandleCustomWM_INITMENU ((unsigned long)hwnd, wParam);
451706f2543Smrg      break;
452706f2543Smrg
453706f2543Smrg    case WM_ERASEBKGND:
454706f2543Smrg      /*
455706f2543Smrg       * Pretend that we did erase the background but we don't care,
456706f2543Smrg       * since we repaint the entire region anyhow
457706f2543Smrg       * This avoids some flickering when resizing.
458706f2543Smrg       */
459706f2543Smrg      return TRUE;
460706f2543Smrg
461706f2543Smrg    case WM_PAINT:
462706f2543Smrg      /* Only paint if our window handle is valid */
463706f2543Smrg      if (hwndScreen == NULL)
464706f2543Smrg	break;
465706f2543Smrg
466706f2543Smrg      /* BeginPaint gives us an hdc that clips to the invalidated region */
467706f2543Smrg      hdcUpdate = BeginPaint (hwnd, &ps);
468706f2543Smrg      /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
469706f2543Smrg      if (ps.rcPaint.right==0 && ps.rcPaint.bottom==0 && ps.rcPaint.left==0 && ps.rcPaint.top==0)
470706f2543Smrg      {
471706f2543Smrg	EndPaint (hwnd, &ps);
472706f2543Smrg	return 0;
473706f2543Smrg      }
474706f2543Smrg
475706f2543Smrg      /* Try to copy from the shadow buffer */
476706f2543Smrg      if (!BitBlt (hdcUpdate,
477706f2543Smrg		   ps.rcPaint.left, ps.rcPaint.top,
478706f2543Smrg		   ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
479706f2543Smrg		   s_pScreenPriv->hdcShadow,
480706f2543Smrg		   ps.rcPaint.left + pWin->drawable.x, ps.rcPaint.top + pWin->drawable.y,
481706f2543Smrg		   SRCCOPY))
482706f2543Smrg	{
483706f2543Smrg	  LPVOID lpMsgBuf;
484706f2543Smrg
485706f2543Smrg	  /* Display a fancy error message */
486706f2543Smrg	  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
487706f2543Smrg			 FORMAT_MESSAGE_FROM_SYSTEM |
488706f2543Smrg			 FORMAT_MESSAGE_IGNORE_INSERTS,
489706f2543Smrg			 NULL,
490706f2543Smrg			 GetLastError (),
491706f2543Smrg			 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
492706f2543Smrg			 (LPTSTR) &lpMsgBuf,
493706f2543Smrg			 0, NULL);
494706f2543Smrg
495706f2543Smrg	  ErrorF ("winTopLevelWindowProc - BitBlt failed: %s\n",
496706f2543Smrg		  (LPSTR)lpMsgBuf);
497706f2543Smrg	  LocalFree (lpMsgBuf);
498706f2543Smrg	}
499706f2543Smrg
500706f2543Smrg      /* EndPaint frees the DC */
501706f2543Smrg      EndPaint (hwnd, &ps);
502706f2543Smrg      return 0;
503706f2543Smrg
504706f2543Smrg    case WM_MOUSEMOVE:
505706f2543Smrg      /* Unpack the client area mouse coordinates */
506706f2543Smrg      ptMouse.x = GET_X_LPARAM(lParam);
507706f2543Smrg      ptMouse.y = GET_Y_LPARAM(lParam);
508706f2543Smrg
509706f2543Smrg      /* Translate the client area mouse coordinates to screen coordinates */
510706f2543Smrg      ClientToScreen (hwnd, &ptMouse);
511706f2543Smrg
512706f2543Smrg      /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
513706f2543Smrg      ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
514706f2543Smrg      ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
515706f2543Smrg
516706f2543Smrg      /* We can't do anything without privates */
517706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
518706f2543Smrg	break;
519706f2543Smrg
520706f2543Smrg      /* Has the mouse pointer crossed screens? */
521706f2543Smrg      if (s_pScreen != miPointerGetScreen(g_pwinPointer))
522706f2543Smrg	miPointerSetScreen (g_pwinPointer, s_pScreenInfo->dwScreen,
523706f2543Smrg			       ptMouse.x - s_pScreenInfo->dwXOffset,
524706f2543Smrg			       ptMouse.y - s_pScreenInfo->dwYOffset);
525706f2543Smrg
526706f2543Smrg      /* Are we tracking yet? */
527706f2543Smrg      if (!s_fTracking)
528706f2543Smrg	{
529706f2543Smrg	  TRACKMOUSEEVENT		tme;
530706f2543Smrg
531706f2543Smrg	  /* Setup data structure */
532706f2543Smrg	  ZeroMemory (&tme, sizeof (tme));
533706f2543Smrg	  tme.cbSize = sizeof (tme);
534706f2543Smrg	  tme.dwFlags = TME_LEAVE;
535706f2543Smrg	  tme.hwndTrack = hwnd;
536706f2543Smrg
537706f2543Smrg	  /* Call the tracking function */
538706f2543Smrg	  if (!(*g_fpTrackMouseEvent) (&tme))
539706f2543Smrg	    ErrorF ("winTopLevelWindowProc - _TrackMouseEvent failed\n");
540706f2543Smrg
541706f2543Smrg	  /* Flag that we are tracking now */
542706f2543Smrg	  s_fTracking = TRUE;
543706f2543Smrg	}
544706f2543Smrg
545706f2543Smrg      /* Hide or show the Windows mouse cursor */
546706f2543Smrg      if (g_fSoftwareCursor && g_fCursor)
547706f2543Smrg	{
548706f2543Smrg	  /* Hide Windows cursor */
549706f2543Smrg	  g_fCursor = FALSE;
550706f2543Smrg	  ShowCursor (FALSE);
551706f2543Smrg	}
552706f2543Smrg
553706f2543Smrg      /* Kill the timer used to poll mouse events */
554706f2543Smrg      if (g_uipMousePollingTimerID != 0)
555706f2543Smrg	{
556706f2543Smrg	  KillTimer (s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
557706f2543Smrg	  g_uipMousePollingTimerID = 0;
558706f2543Smrg	}
559706f2543Smrg
560706f2543Smrg      /* Deliver absolute cursor position to X Server */
561706f2543Smrg      winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
562706f2543Smrg		       ptMouse.y - s_pScreenInfo->dwYOffset);
563706f2543Smrg
564706f2543Smrg      return 0;
565706f2543Smrg
566706f2543Smrg    case WM_NCMOUSEMOVE:
567706f2543Smrg      /*
568706f2543Smrg       * We break instead of returning 0 since we need to call
569706f2543Smrg       * DefWindowProc to get the mouse cursor changes
570706f2543Smrg       * and min/max/close button highlighting in Windows XP.
571706f2543Smrg       * The Platform SDK says that you should return 0 if you
572706f2543Smrg       * process this message, but it fails to mention that you
573706f2543Smrg       * will give up any default functionality if you do return 0.
574706f2543Smrg       */
575706f2543Smrg
576706f2543Smrg      /* We can't do anything without privates */
577706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
578706f2543Smrg	break;
579706f2543Smrg
580706f2543Smrg      /* Non-client mouse movement, show Windows cursor */
581706f2543Smrg      if (g_fSoftwareCursor && !g_fCursor)
582706f2543Smrg	{
583706f2543Smrg	  g_fCursor = TRUE;
584706f2543Smrg	  ShowCursor (TRUE);
585706f2543Smrg	}
586706f2543Smrg
587706f2543Smrg      winStartMousePolling(s_pScreenPriv);
588706f2543Smrg
589706f2543Smrg      break;
590706f2543Smrg
591706f2543Smrg    case WM_MOUSELEAVE:
592706f2543Smrg      /* Mouse has left our client area */
593706f2543Smrg
594706f2543Smrg      /* Flag that we are no longer tracking */
595706f2543Smrg      s_fTracking = FALSE;
596706f2543Smrg
597706f2543Smrg      /* Show the mouse cursor, if necessary */
598706f2543Smrg      if (g_fSoftwareCursor && !g_fCursor)
599706f2543Smrg	{
600706f2543Smrg	  g_fCursor = TRUE;
601706f2543Smrg	  ShowCursor (TRUE);
602706f2543Smrg	}
603706f2543Smrg
604706f2543Smrg      winStartMousePolling(s_pScreenPriv);
605706f2543Smrg
606706f2543Smrg      return 0;
607706f2543Smrg
608706f2543Smrg    case WM_LBUTTONDBLCLK:
609706f2543Smrg    case WM_LBUTTONDOWN:
610706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
611706f2543Smrg	break;
612706f2543Smrg      g_fButton[0] = TRUE;
613706f2543Smrg      SetCapture(hwnd);
614706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
615706f2543Smrg
616706f2543Smrg    case WM_LBUTTONUP:
617706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
618706f2543Smrg	break;
619706f2543Smrg      g_fButton[0] = FALSE;
620706f2543Smrg      ReleaseCapture();
621706f2543Smrg      winStartMousePolling(s_pScreenPriv);
622706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
623706f2543Smrg
624706f2543Smrg    case WM_MBUTTONDBLCLK:
625706f2543Smrg    case WM_MBUTTONDOWN:
626706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
627706f2543Smrg	break;
628706f2543Smrg      g_fButton[1] = TRUE;
629706f2543Smrg      SetCapture(hwnd);
630706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
631706f2543Smrg
632706f2543Smrg    case WM_MBUTTONUP:
633706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
634706f2543Smrg	break;
635706f2543Smrg      g_fButton[1] = FALSE;
636706f2543Smrg      ReleaseCapture();
637706f2543Smrg      winStartMousePolling(s_pScreenPriv);
638706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
639706f2543Smrg
640706f2543Smrg    case WM_RBUTTONDBLCLK:
641706f2543Smrg    case WM_RBUTTONDOWN:
642706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
643706f2543Smrg	break;
644706f2543Smrg      g_fButton[2] = TRUE;
645706f2543Smrg      SetCapture(hwnd);
646706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
647706f2543Smrg
648706f2543Smrg    case WM_RBUTTONUP:
649706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
650706f2543Smrg	break;
651706f2543Smrg      g_fButton[2] = FALSE;
652706f2543Smrg      ReleaseCapture();
653706f2543Smrg      winStartMousePolling(s_pScreenPriv);
654706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
655706f2543Smrg
656706f2543Smrg    case WM_XBUTTONDBLCLK:
657706f2543Smrg    case WM_XBUTTONDOWN:
658706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
659706f2543Smrg	break;
660706f2543Smrg	SetCapture(hwnd);
661706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
662706f2543Smrg
663706f2543Smrg    case WM_XBUTTONUP:
664706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
665706f2543Smrg	break;
666706f2543Smrg      ReleaseCapture();
667706f2543Smrg      winStartMousePolling(s_pScreenPriv);
668706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
669706f2543Smrg
670706f2543Smrg    case WM_MOUSEWHEEL:
671706f2543Smrg      if (SendMessage(hwnd, WM_NCHITTEST, 0, MAKELONG(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) == HTCLIENT)
672706f2543Smrg	{
673706f2543Smrg	  /* Pass the message to the root window */
674706f2543Smrg	  SendMessage (hwndScreen, message, wParam, lParam);
675706f2543Smrg	  return 0;
676706f2543Smrg	}
677706f2543Smrg      else break;
678706f2543Smrg
679706f2543Smrg    case WM_SETFOCUS:
680706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
681706f2543Smrg	break;
682706f2543Smrg
683706f2543Smrg      {
684706f2543Smrg	/* Get the parent window for transient handling */
685706f2543Smrg	HWND hParent = GetParent(hwnd);
686706f2543Smrg	if (hParent && IsIconic(hParent)) ShowWindow (hParent, SW_RESTORE);
687706f2543Smrg      }
688706f2543Smrg
689706f2543Smrg      winRestoreModeKeyStates ();
690706f2543Smrg
691706f2543Smrg      /* Add the keyboard hook if possible */
692706f2543Smrg      if (g_fKeyboardHookLL)
693706f2543Smrg	g_fKeyboardHookLL = winInstallKeyboardHookLL ();
694706f2543Smrg      return 0;
695706f2543Smrg
696706f2543Smrg    case WM_KILLFOCUS:
697706f2543Smrg      /* Pop any pressed keys since we are losing keyboard focus */
698706f2543Smrg      winKeybdReleaseKeys ();
699706f2543Smrg
700706f2543Smrg      /* Remove our keyboard hook if it is installed */
701706f2543Smrg      winRemoveKeyboardHookLL ();
702706f2543Smrg      if (!wParam)
703706f2543Smrg	/* Revert the X focus as well, but only if the Windows focus is going to another window */
704706f2543Smrg	DeleteWindowFromAnyEvents(pWin, FALSE);
705706f2543Smrg      return 0;
706706f2543Smrg
707706f2543Smrg    case WM_SYSDEADCHAR:
708706f2543Smrg    case WM_DEADCHAR:
709706f2543Smrg      /*
710706f2543Smrg       * NOTE: We do nothing with WM_*CHAR messages,
711706f2543Smrg       * nor does the root window, so we can just toss these messages.
712706f2543Smrg       */
713706f2543Smrg      return 0;
714706f2543Smrg
715706f2543Smrg    case WM_SYSKEYDOWN:
716706f2543Smrg    case WM_KEYDOWN:
717706f2543Smrg
718706f2543Smrg      /*
719706f2543Smrg       * Don't pass Alt-F4 key combo to root window,
720706f2543Smrg       * let Windows translate to WM_CLOSE and close this top-level window.
721706f2543Smrg       *
722706f2543Smrg       * NOTE: We purposely don't check the fUseWinKillKey setting because
723706f2543Smrg       * it should only apply to the key handling for the root window,
724706f2543Smrg       * not for top-level window-manager windows.
725706f2543Smrg       *
726706f2543Smrg       * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
727706f2543Smrg       * because that is a key combo that no X app should be expecting to
728706f2543Smrg       * receive, since it has historically been used to shutdown the X server.
729706f2543Smrg       * Passing Ctrl-Alt-Backspace to the root window preserves that
730706f2543Smrg       * behavior, assuming that -unixkill has been passed as a parameter.
731706f2543Smrg       */
732706f2543Smrg      if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000))
733706f2543Smrg	  break;
734706f2543Smrg
735706f2543Smrg#if CYGWINDOWING_DEBUG
736706f2543Smrg      if (wParam == VK_ESCAPE)
737706f2543Smrg	{
738706f2543Smrg	  /* Place for debug: put any tests and dumps here */
739706f2543Smrg	  WINDOWPLACEMENT windPlace;
740706f2543Smrg	  RECT rc;
741706f2543Smrg	  LPRECT pRect;
742706f2543Smrg
743706f2543Smrg	  windPlace.length = sizeof (WINDOWPLACEMENT);
744706f2543Smrg	  GetWindowPlacement (hwnd, &windPlace);
745706f2543Smrg	  pRect = &windPlace.rcNormalPosition;
746706f2543Smrg	  ErrorF ("\nCYGWINDOWING Dump:\n"
747706f2543Smrg		  "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
748706f2543Smrg		  pDraw->y, pDraw->width, pDraw->height);
749706f2543Smrg	  ErrorF ("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left,
750706f2543Smrg		  pRect->top, pRect->right - pRect->left,
751706f2543Smrg		  pRect->bottom - pRect->top);
752706f2543Smrg	  if (GetClientRect (hwnd, &rc))
753706f2543Smrg	    {
754706f2543Smrg	      pRect = &rc;
755706f2543Smrg	      ErrorF ("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
756706f2543Smrg		      pRect->top, pRect->right - pRect->left,
757706f2543Smrg		      pRect->bottom - pRect->top);
758706f2543Smrg	    }
759706f2543Smrg	  if (GetWindowRect (hwnd, &rc))
760706f2543Smrg	    {
761706f2543Smrg	      pRect = &rc;
762706f2543Smrg	      ErrorF ("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
763706f2543Smrg		      pRect->top, pRect->right - pRect->left,
764706f2543Smrg		      pRect->bottom - pRect->top);
765706f2543Smrg	    }
766706f2543Smrg	  ErrorF ("\n");
767706f2543Smrg	}
768706f2543Smrg#endif
769706f2543Smrg
770706f2543Smrg      /* Pass the message to the root window */
771706f2543Smrg      return winWindowProc(hwndScreen, message, wParam, lParam);
772706f2543Smrg
773706f2543Smrg    case WM_SYSKEYUP:
774706f2543Smrg    case WM_KEYUP:
775706f2543Smrg
776706f2543Smrg
777706f2543Smrg      /* Pass the message to the root window */
778706f2543Smrg      return winWindowProc(hwndScreen, message, wParam, lParam);
779706f2543Smrg
780706f2543Smrg    case WM_HOTKEY:
781706f2543Smrg
782706f2543Smrg      /* Pass the message to the root window */
783706f2543Smrg      SendMessage (hwndScreen, message, wParam, lParam);
784706f2543Smrg      return 0;
785706f2543Smrg
786706f2543Smrg    case WM_ACTIVATE:
787706f2543Smrg
788706f2543Smrg      /* Pass the message to the root window */
789706f2543Smrg      SendMessage (hwndScreen, message, wParam, lParam);
790706f2543Smrg
791706f2543Smrg      if (LOWORD(wParam) != WA_INACTIVE)
792706f2543Smrg	{
793706f2543Smrg	  /* Raise the window to the top in Z order */
794706f2543Smrg          /* ago: Activate does not mean putting it to front! */
795706f2543Smrg          /*
796706f2543Smrg	  wmMsg.msg = WM_WM_RAISE;
797706f2543Smrg	  if (fWMMsgInitialized)
798706f2543Smrg	    winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
799706f2543Smrg          */
800706f2543Smrg
801706f2543Smrg	  /* Tell our Window Manager thread to activate the window */
802706f2543Smrg	  wmMsg.msg = WM_WM_ACTIVATE;
803706f2543Smrg	  if (fWMMsgInitialized)
804706f2543Smrg	    if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
805706f2543Smrg	      winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
806706f2543Smrg	}
807706f2543Smrg      /* Prevent the mouse wheel from stalling when another window is minimized */
808706f2543Smrg      if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
809706f2543Smrg	  (HWND)lParam != NULL && (HWND)lParam != (HWND)GetParent(hwnd))
810706f2543Smrg	SetFocus(hwnd);
811706f2543Smrg      return 0;
812706f2543Smrg
813706f2543Smrg    case WM_ACTIVATEAPP:
814706f2543Smrg      /*
815706f2543Smrg       * This message is also sent to the root window
816706f2543Smrg       * so we do nothing for individual multiwindow windows
817706f2543Smrg       */
818706f2543Smrg      break;
819706f2543Smrg
820706f2543Smrg    case WM_CLOSE:
821706f2543Smrg      /* Branch on if the window was killed in X already */
822706f2543Smrg      if (pWinPriv->fXKilled)
823706f2543Smrg        {
824706f2543Smrg	  /* Window was killed, go ahead and destroy the window */
825706f2543Smrg	  DestroyWindow (hwnd);
826706f2543Smrg	}
827706f2543Smrg      else
828706f2543Smrg	{
829706f2543Smrg	  /* Tell our Window Manager thread to kill the window */
830706f2543Smrg	  wmMsg.msg = WM_WM_KILL;
831706f2543Smrg	  if (fWMMsgInitialized)
832706f2543Smrg	    winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
833706f2543Smrg	}
834706f2543Smrg      return 0;
835706f2543Smrg
836706f2543Smrg    case WM_DESTROY:
837706f2543Smrg
838706f2543Smrg      /* Branch on if the window was killed in X already */
839706f2543Smrg      if (pWinPriv && !pWinPriv->fXKilled)
840706f2543Smrg	{
841706f2543Smrg	  ErrorF ("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
842706f2543Smrg
843706f2543Smrg	  /* Tell our Window Manager thread to kill the window */
844706f2543Smrg	  wmMsg.msg = WM_WM_KILL;
845706f2543Smrg	  if (fWMMsgInitialized)
846706f2543Smrg	    winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
847706f2543Smrg	}
848706f2543Smrg
849706f2543Smrg      RemoveProp (hwnd, WIN_WINDOW_PROP);
850706f2543Smrg      RemoveProp (hwnd, WIN_WID_PROP);
851706f2543Smrg      RemoveProp (hwnd, WIN_NEEDMANAGE_PROP);
852706f2543Smrg
853706f2543Smrg      break;
854706f2543Smrg
855706f2543Smrg    case WM_MOVE:
856706f2543Smrg      /* Adjust the X Window to the moved Windows window */
857706f2543Smrg      winAdjustXWindow (pWin, hwnd);
858706f2543Smrg      return 0;
859706f2543Smrg
860706f2543Smrg    case WM_SHOWWINDOW:
861706f2543Smrg      /* Bail out if the window is being hidden */
862706f2543Smrg      if (!wParam)
863706f2543Smrg	return 0;
864706f2543Smrg
865706f2543Smrg      /* */
866706f2543Smrg      if (!pWin->overrideRedirect)
867706f2543Smrg	{
868706f2543Smrg	  /* Flag that this window needs to be made active when clicked */
869706f2543Smrg	  SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
870706f2543Smrg
871706f2543Smrg	  if (!(GetWindowLongPtr (hwnd, GWL_EXSTYLE) & WS_EX_APPWINDOW))
872706f2543Smrg	    {
873706f2543Smrg	      HWND		zstyle = HWND_NOTOPMOST;
874706f2543Smrg
875706f2543Smrg	      /* Set the window extended style flags */
876706f2543Smrg	      SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
877706f2543Smrg
878706f2543Smrg	      /* Set the transient style flags */
879706f2543Smrg	      if (GetParent(hwnd)) SetWindowLongPtr (hwnd, GWL_STYLE,
880706f2543Smrg		   WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
881706f2543Smrg	      /* Set the window standard style flags */
882706f2543Smrg	      else SetWindowLongPtr (hwnd, GWL_STYLE,
883706f2543Smrg		   (WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
884706f2543Smrg		   & ~WS_CAPTION & ~WS_SIZEBOX);
885706f2543Smrg
886706f2543Smrg	      winUpdateWindowPosition (hwnd, FALSE, &zstyle);
887706f2543Smrg	      SetForegroundWindow (hwnd);
888706f2543Smrg	    }
889706f2543Smrg	  wmMsg.msg = WM_WM_MAP3;
890706f2543Smrg	}
891706f2543Smrg      else /* It is an overridden window so make it top of Z stack */
892706f2543Smrg	{
893706f2543Smrg	  HWND forHwnd = GetForegroundWindow();
894706f2543Smrg#if CYGWINDOWING_DEBUG
895706f2543Smrg	  ErrorF ("overridden window is shown\n");
896706f2543Smrg#endif
897706f2543Smrg	  if (forHwnd != NULL)
898706f2543Smrg	  {
899706f2543Smrg	    if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)XMING_SIGNATURE)
900706f2543Smrg	    {
901706f2543Smrg	      if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
902706f2543Smrg		SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
903706f2543Smrg	      else
904706f2543Smrg		SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
905706f2543Smrg	    }
906706f2543Smrg	  }
907706f2543Smrg	  wmMsg.msg = WM_WM_MAP2;
908706f2543Smrg	}
909706f2543Smrg
910706f2543Smrg      /* Tell our Window Manager thread to map the window */
911706f2543Smrg      if (fWMMsgInitialized)
912706f2543Smrg	winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
913706f2543Smrg
914706f2543Smrg      winStartMousePolling(s_pScreenPriv);
915706f2543Smrg
916706f2543Smrg      return 0;
917706f2543Smrg
918706f2543Smrg    case WM_SIZING:
919706f2543Smrg      /* Need to legalize the size according to WM_NORMAL_HINTS */
920706f2543Smrg      /* for applications like xterm */
921706f2543Smrg      return ValidateSizing (hwnd, pWin, wParam, lParam);
922706f2543Smrg
923706f2543Smrg    case WM_WINDOWPOSCHANGED:
924706f2543Smrg      {
925706f2543Smrg	LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
926706f2543Smrg
927706f2543Smrg	if (!(pWinPos->flags & SWP_NOZORDER))
928706f2543Smrg	  {
929706f2543Smrg#if CYGWINDOWING_DEBUG
930706f2543Smrg	    winDebug ("\twindow z order was changed\n");
931706f2543Smrg#endif
932706f2543Smrg	    if (pWinPos->hwndInsertAfter == HWND_TOP
933706f2543Smrg		||pWinPos->hwndInsertAfter == HWND_TOPMOST
934706f2543Smrg		||pWinPos->hwndInsertAfter == HWND_NOTOPMOST)
935706f2543Smrg	      {
936706f2543Smrg#if CYGWINDOWING_DEBUG
937706f2543Smrg		winDebug ("\traise to top\n");
938706f2543Smrg#endif
939706f2543Smrg		/* Raise the window to the top in Z order */
940706f2543Smrg		winRaiseWindow(pWin);
941706f2543Smrg	      }
942706f2543Smrg	    else if (pWinPos->hwndInsertAfter == HWND_BOTTOM)
943706f2543Smrg	      {
944706f2543Smrg	      }
945706f2543Smrg	    else
946706f2543Smrg	      {
947706f2543Smrg		/* Check if this window is top of X windows. */
948706f2543Smrg		HWND hWndAbove = NULL;
949706f2543Smrg		DWORD dwCurrentProcessID = GetCurrentProcessId ();
950706f2543Smrg		DWORD dwWindowProcessID = 0;
951706f2543Smrg
952706f2543Smrg		for (hWndAbove = pWinPos->hwndInsertAfter;
953706f2543Smrg		     hWndAbove != NULL;
954706f2543Smrg		     hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV))
955706f2543Smrg		  {
956706f2543Smrg		    /* Ignore other XWin process's window */
957706f2543Smrg		    GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID);
958706f2543Smrg
959706f2543Smrg		    if ((dwWindowProcessID == dwCurrentProcessID)
960706f2543Smrg			&& GetProp (hWndAbove, WIN_WINDOW_PROP)
961706f2543Smrg			&& !IsWindowVisible (hWndAbove)
962706f2543Smrg			&& !IsIconic (hWndAbove) ) /* ignore minimized windows */
963706f2543Smrg		      break;
964706f2543Smrg		  }
965706f2543Smrg		/* If this is top of X windows in Windows stack,
966706f2543Smrg		   raise it in X stack. */
967706f2543Smrg		if (hWndAbove == NULL)
968706f2543Smrg		  {
969706f2543Smrg#if CYGWINDOWING_DEBUG
970706f2543Smrg		    winDebug ("\traise to top\n");
971706f2543Smrg#endif
972706f2543Smrg		    winRaiseWindow(pWin);
973706f2543Smrg		  }
974706f2543Smrg	      }
975706f2543Smrg	  }
976706f2543Smrg      }
977706f2543Smrg      /*
978706f2543Smrg       * Pass the message to DefWindowProc to let the function
979706f2543Smrg       * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
980706f2543Smrg      */
981706f2543Smrg      break;
982706f2543Smrg
983706f2543Smrg    case WM_SIZE:
984706f2543Smrg      /* see dix/window.c */
985706f2543Smrg#if CYGWINDOWING_DEBUG
986706f2543Smrg      {
987706f2543Smrg	char buf[64];
988706f2543Smrg	switch (wParam)
989706f2543Smrg	  {
990706f2543Smrg	  case SIZE_MINIMIZED:
991706f2543Smrg	    strcpy(buf, "SIZE_MINIMIZED");
992706f2543Smrg	    break;
993706f2543Smrg	  case SIZE_MAXIMIZED:
994706f2543Smrg	    strcpy(buf, "SIZE_MAXIMIZED");
995706f2543Smrg	    break;
996706f2543Smrg	  case SIZE_RESTORED:
997706f2543Smrg	    strcpy(buf, "SIZE_RESTORED");
998706f2543Smrg	    break;
999706f2543Smrg	  default:
1000706f2543Smrg	    strcpy(buf, "UNKNOWN_FLAG");
1001706f2543Smrg	  }
1002706f2543Smrg	ErrorF ("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
1003706f2543Smrg		(int)LOWORD(lParam), (int)HIWORD(lParam), buf,
1004706f2543Smrg		(int)(GetTickCount ()));
1005706f2543Smrg      }
1006706f2543Smrg#endif
1007706f2543Smrg      /* Adjust the X Window to the moved Windows window */
1008706f2543Smrg      winAdjustXWindow (pWin, hwnd);
1009706f2543Smrg      return 0; /* end of WM_SIZE handler */
1010706f2543Smrg
1011706f2543Smrg    case WM_MOUSEACTIVATE:
1012706f2543Smrg
1013706f2543Smrg      /* Check if this window needs to be made active when clicked */
1014706f2543Smrg      if (!GetProp (pWinPriv->hWnd, WIN_NEEDMANAGE_PROP))
1015706f2543Smrg	{
1016706f2543Smrg#if CYGMULTIWINDOW_DEBUG
1017706f2543Smrg	  ErrorF ("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
1018706f2543Smrg		  "MA_NOACTIVATE\n");
1019706f2543Smrg#endif
1020706f2543Smrg
1021706f2543Smrg	  /* */
1022706f2543Smrg	  return MA_NOACTIVATE;
1023706f2543Smrg	}
1024706f2543Smrg      break;
1025706f2543Smrg
1026706f2543Smrg    case WM_SETCURSOR:
1027706f2543Smrg      if (LOWORD(lParam) == HTCLIENT)
1028706f2543Smrg	{
1029706f2543Smrg	  if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle);
1030706f2543Smrg	  return TRUE;
1031706f2543Smrg	}
1032706f2543Smrg      break;
1033706f2543Smrg
1034706f2543Smrg    default:
1035706f2543Smrg      break;
1036706f2543Smrg    }
1037706f2543Smrg
1038706f2543Smrg  ret = DefWindowProc (hwnd, message, wParam, lParam);
1039706f2543Smrg  /*
1040706f2543Smrg   * If the window was minized we get the stack change before the window is restored
1041706f2543Smrg   * and so it gets lost. Ensure there stacking order is correct.
1042706f2543Smrg   */
1043706f2543Smrg  if (needRestack)
1044706f2543Smrg    winReorderWindowsMultiWindow();
1045706f2543Smrg  return ret;
1046706f2543Smrg}
1047