winmultiwindowwndproc.c revision 6747b715
105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
36747b715Smrg *Copyright (C) Colin Harrison 2005-2008
405b261ecSmrg *
505b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
605b261ecSmrg * a copy of this software and associated documentation files (the
705b261ecSmrg *"Software"), to deal in the Software without restriction, including
805b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
905b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
1005b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1105b261ecSmrg *the following conditions:
1205b261ecSmrg *
1305b261ecSmrg *The above copyright notice and this permission notice shall be
1405b261ecSmrg *included in all copies or substantial portions of the Software.
1505b261ecSmrg *
1605b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1705b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1805b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1905b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
2005b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2105b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2205b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2305b261ecSmrg *
2405b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project
2505b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2605b261ecSmrg *or other dealings in this Software without prior written authorization
2705b261ecSmrg *from the XFree86 Project.
2805b261ecSmrg *
2905b261ecSmrg * Authors:	Kensuke Matsuzaki
3005b261ecSmrg *		Earle F. Philhower, III
3105b261ecSmrg *		Harold L Hunt II
326747b715Smrg *              Colin Harrison
3305b261ecSmrg */
3405b261ecSmrg
3505b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3605b261ecSmrg#include <xwin-config.h>
3705b261ecSmrg#endif
3805b261ecSmrg#include "win.h"
3905b261ecSmrg#include "dixevents.h"
4005b261ecSmrg#include "winmultiwindowclass.h"
4105b261ecSmrg#include "winprefs.h"
4205b261ecSmrg#include "winmsg.h"
4305b261ecSmrg#include "inputstr.h"
4405b261ecSmrg
4505b261ecSmrg/*
4605b261ecSmrg * External global variables
4705b261ecSmrg */
4805b261ecSmrg
4905b261ecSmrgextern Bool			g_fCursor;
5005b261ecSmrgextern Bool			g_fKeyboardHookLL;
5105b261ecSmrgextern Bool			g_fSoftwareCursor;
5205b261ecSmrgextern Bool			g_fButton[3];
5305b261ecSmrg
546747b715Smrgextern void winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle);
556747b715Smrg
5605b261ecSmrg
5705b261ecSmrg/*
5805b261ecSmrg * Local globals
5905b261ecSmrg */
6005b261ecSmrg
6105b261ecSmrgstatic UINT_PTR		g_uipMousePollingTimerID = 0;
6205b261ecSmrg
6305b261ecSmrg
6405b261ecSmrg/*
6505b261ecSmrg * Constant defines
6605b261ecSmrg */
6705b261ecSmrg
6805b261ecSmrg#define WIN_MULTIWINDOW_SHAPE		YES
6905b261ecSmrg
7005b261ecSmrg
7105b261ecSmrg/*
7205b261ecSmrg * ConstrainSize - Taken from TWM sources - Respects hints for sizing
7305b261ecSmrg */
7405b261ecSmrg#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
7505b261ecSmrgstatic void
7605b261ecSmrgConstrainSize (WinXSizeHints hints, int *widthp, int *heightp)
7705b261ecSmrg{
7805b261ecSmrg  int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
7905b261ecSmrg  int baseWidth, baseHeight;
8005b261ecSmrg  int dwidth = *widthp, dheight = *heightp;
8105b261ecSmrg
8205b261ecSmrg  if (hints.flags & PMinSize)
8305b261ecSmrg    {
8405b261ecSmrg      minWidth = hints.min_width;
8505b261ecSmrg      minHeight = hints.min_height;
8605b261ecSmrg    }
8705b261ecSmrg  else if (hints.flags & PBaseSize)
8805b261ecSmrg    {
8905b261ecSmrg      minWidth = hints.base_width;
9005b261ecSmrg      minHeight = hints.base_height;
9105b261ecSmrg    }
9205b261ecSmrg  else
9305b261ecSmrg    minWidth = minHeight = 1;
9405b261ecSmrg
9505b261ecSmrg  if (hints.flags & PBaseSize)
9605b261ecSmrg    {
9705b261ecSmrg      baseWidth = hints.base_width;
9805b261ecSmrg      baseHeight = hints.base_height;
9905b261ecSmrg    }
10005b261ecSmrg  else if (hints.flags & PMinSize)
10105b261ecSmrg    {
10205b261ecSmrg      baseWidth = hints.min_width;
10305b261ecSmrg      baseHeight = hints.min_height;
10405b261ecSmrg    }
10505b261ecSmrg  else
10605b261ecSmrg    baseWidth = baseHeight = 0;
10705b261ecSmrg
10805b261ecSmrg  if (hints.flags & PMaxSize)
10905b261ecSmrg    {
11005b261ecSmrg      maxWidth = hints.max_width;
11105b261ecSmrg      maxHeight = hints.max_height;
11205b261ecSmrg    }
11305b261ecSmrg  else
11405b261ecSmrg    {
11505b261ecSmrg      maxWidth = MAXINT;
11605b261ecSmrg      maxHeight = MAXINT;
11705b261ecSmrg    }
11805b261ecSmrg
11905b261ecSmrg  if (hints.flags & PResizeInc)
12005b261ecSmrg    {
12105b261ecSmrg      xinc = hints.width_inc;
12205b261ecSmrg      yinc = hints.height_inc;
12305b261ecSmrg    }
12405b261ecSmrg  else
12505b261ecSmrg    xinc = yinc = 1;
12605b261ecSmrg
12705b261ecSmrg  /*
12805b261ecSmrg   * First, clamp to min and max values
12905b261ecSmrg   */
13005b261ecSmrg  if (dwidth < minWidth)
13105b261ecSmrg    dwidth = minWidth;
13205b261ecSmrg  if (dheight < minHeight)
13305b261ecSmrg    dheight = minHeight;
13405b261ecSmrg
13505b261ecSmrg  if (dwidth > maxWidth)
13605b261ecSmrg    dwidth = maxWidth;
13705b261ecSmrg  if (dheight > maxHeight)
13805b261ecSmrg    dheight = maxHeight;
13905b261ecSmrg
14005b261ecSmrg  /*
14105b261ecSmrg   * Second, fit to base + N * inc
14205b261ecSmrg   */
14305b261ecSmrg  dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
14405b261ecSmrg  dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
14505b261ecSmrg
14605b261ecSmrg  /*
14705b261ecSmrg   * Third, adjust for aspect ratio
14805b261ecSmrg   */
14905b261ecSmrg
15005b261ecSmrg  /*
15105b261ecSmrg   * The math looks like this:
15205b261ecSmrg   *
15305b261ecSmrg   * minAspectX    dwidth     maxAspectX
15405b261ecSmrg   * ---------- <= ------- <= ----------
15505b261ecSmrg   * minAspectY    dheight    maxAspectY
15605b261ecSmrg   *
15705b261ecSmrg   * If that is multiplied out, then the width and height are
15805b261ecSmrg   * invalid in the following situations:
15905b261ecSmrg   *
16005b261ecSmrg   * minAspectX * dheight > minAspectY * dwidth
16105b261ecSmrg   * maxAspectX * dheight < maxAspectY * dwidth
16205b261ecSmrg   *
16305b261ecSmrg   */
16405b261ecSmrg
16505b261ecSmrg  if (hints.flags & PAspect)
16605b261ecSmrg    {
16705b261ecSmrg      if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth)
16805b261ecSmrg        {
16905b261ecSmrg	  delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc);
17005b261ecSmrg	  if (dwidth + delta <= maxWidth)
17105b261ecSmrg	    dwidth += delta;
17205b261ecSmrg	  else
17305b261ecSmrg            {
17405b261ecSmrg	      delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc);
17505b261ecSmrg	      if (dheight - delta >= minHeight)
17605b261ecSmrg		dheight -= delta;
17705b261ecSmrg            }
17805b261ecSmrg        }
17905b261ecSmrg
18005b261ecSmrg      if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth)
18105b261ecSmrg        {
18205b261ecSmrg	  delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc);
18305b261ecSmrg	  if (dheight + delta <= maxHeight)
18405b261ecSmrg	    dheight += delta;
18505b261ecSmrg	  else
18605b261ecSmrg            {
18705b261ecSmrg	      delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc);
18805b261ecSmrg	      if (dwidth - delta >= minWidth)
18905b261ecSmrg		dwidth -= delta;
19005b261ecSmrg            }
19105b261ecSmrg        }
19205b261ecSmrg    }
19305b261ecSmrg
19405b261ecSmrg  /* Return computed values */
19505b261ecSmrg  *widthp = dwidth;
19605b261ecSmrg  *heightp = dheight;
19705b261ecSmrg}
19805b261ecSmrg#undef makemult
19905b261ecSmrg
20005b261ecSmrg
20105b261ecSmrg
20205b261ecSmrg/*
20305b261ecSmrg * ValidateSizing - Ensures size request respects hints
20405b261ecSmrg */
20505b261ecSmrgstatic int
20605b261ecSmrgValidateSizing (HWND hwnd, WindowPtr pWin,
20705b261ecSmrg		WPARAM wParam, LPARAM lParam)
20805b261ecSmrg{
20905b261ecSmrg  WinXSizeHints sizeHints;
21005b261ecSmrg  RECT *rect;
21105b261ecSmrg  int iWidth, iHeight;
2126747b715Smrg  RECT rcClient, rcWindow;
2136747b715Smrg  int iBorderWidthX, iBorderWidthY;
21405b261ecSmrg
21505b261ecSmrg  /* Invalid input checking */
21605b261ecSmrg  if (pWin==NULL || lParam==0)
21705b261ecSmrg    return FALSE;
21805b261ecSmrg
21905b261ecSmrg  /* No size hints, no checking */
22005b261ecSmrg  if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints))
22105b261ecSmrg    return FALSE;
22205b261ecSmrg
22305b261ecSmrg  /* Avoid divide-by-zero */
22405b261ecSmrg  if (sizeHints.flags & PResizeInc)
22505b261ecSmrg    {
22605b261ecSmrg      if (sizeHints.width_inc == 0) sizeHints.width_inc = 1;
22705b261ecSmrg      if (sizeHints.height_inc == 0) sizeHints.height_inc = 1;
22805b261ecSmrg    }
22905b261ecSmrg
23005b261ecSmrg  rect = (RECT*)lParam;
23105b261ecSmrg
23205b261ecSmrg  iWidth = rect->right - rect->left;
23305b261ecSmrg  iHeight = rect->bottom - rect->top;
23405b261ecSmrg
2356747b715Smrg  /* Now remove size of any borders and title bar */
2366747b715Smrg  GetClientRect(hwnd, &rcClient);
2376747b715Smrg  GetWindowRect(hwnd, &rcWindow);
2386747b715Smrg  iBorderWidthX = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
2396747b715Smrg  iBorderWidthY = (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
2406747b715Smrg  iWidth -= iBorderWidthX;
2416747b715Smrg  iHeight -= iBorderWidthY;
24205b261ecSmrg
24305b261ecSmrg  /* Constrain the size to legal values */
24405b261ecSmrg  ConstrainSize (sizeHints, &iWidth, &iHeight);
24505b261ecSmrg
2466747b715Smrg  /* Add back the size of borders and title bar */
2476747b715Smrg  iWidth += iBorderWidthX;
2486747b715Smrg  iHeight += iBorderWidthY;
24905b261ecSmrg
25005b261ecSmrg  /* Adjust size according to where we're dragging from */
25105b261ecSmrg  switch(wParam) {
25205b261ecSmrg  case WMSZ_TOP:
25305b261ecSmrg  case WMSZ_TOPRIGHT:
25405b261ecSmrg  case WMSZ_BOTTOM:
25505b261ecSmrg  case WMSZ_BOTTOMRIGHT:
25605b261ecSmrg  case WMSZ_RIGHT:
25705b261ecSmrg    rect->right = rect->left + iWidth;
25805b261ecSmrg    break;
25905b261ecSmrg  default:
26005b261ecSmrg    rect->left = rect->right - iWidth;
26105b261ecSmrg    break;
26205b261ecSmrg  }
26305b261ecSmrg  switch(wParam) {
26405b261ecSmrg  case WMSZ_BOTTOM:
26505b261ecSmrg  case WMSZ_BOTTOMRIGHT:
26605b261ecSmrg  case WMSZ_BOTTOMLEFT:
26705b261ecSmrg  case WMSZ_RIGHT:
26805b261ecSmrg  case WMSZ_LEFT:
26905b261ecSmrg    rect->bottom = rect->top + iHeight;
27005b261ecSmrg    break;
27105b261ecSmrg  default:
27205b261ecSmrg    rect->top = rect->bottom - iHeight;
27305b261ecSmrg    break;
27405b261ecSmrg  }
27505b261ecSmrg  return TRUE;
27605b261ecSmrg}
27705b261ecSmrg
27805b261ecSmrgextern Bool winInDestroyWindowsWindow;
27905b261ecSmrgstatic Bool winInRaiseWindow = FALSE;
28005b261ecSmrgstatic void winRaiseWindow(WindowPtr pWin)
28105b261ecSmrg{
28205b261ecSmrg  if (!winInDestroyWindowsWindow && !winInRaiseWindow)
28305b261ecSmrg  {
28405b261ecSmrg    BOOL oldstate = winInRaiseWindow;
2856747b715Smrg    XID vlist[1] = { 0 };
28605b261ecSmrg    winInRaiseWindow = TRUE;
28705b261ecSmrg    /* Call configure window directly to make sure it gets processed
28805b261ecSmrg     * in time
28905b261ecSmrg     */
29005b261ecSmrg    ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
29105b261ecSmrg    winInRaiseWindow = oldstate;
29205b261ecSmrg  }
29305b261ecSmrg}
29405b261ecSmrg
2956747b715Smrgstatic
2966747b715Smrgvoid winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
2976747b715Smrg{
2986747b715Smrg  /*
2996747b715Smrg   * Timer to poll mouse position.  This is needed to make
3006747b715Smrg   * programs like xeyes follow the mouse properly when the
3016747b715Smrg   * mouse pointer is outside of any X window.
3026747b715Smrg   */
3036747b715Smrg  if (g_uipMousePollingTimerID == 0)
3046747b715Smrg    g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
3056747b715Smrg					 WIN_POLLING_MOUSE_TIMER_ID,
3066747b715Smrg					 MOUSE_POLLING_INTERVAL,
3076747b715Smrg					 NULL);
3086747b715Smrg}
30905b261ecSmrg
31005b261ecSmrg/*
31105b261ecSmrg * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
31205b261ecSmrg */
31305b261ecSmrg
31405b261ecSmrgLRESULT CALLBACK
31505b261ecSmrgwinTopLevelWindowProc (HWND hwnd, UINT message,
31605b261ecSmrg		       WPARAM wParam, LPARAM lParam)
31705b261ecSmrg{
31805b261ecSmrg  POINT			ptMouse;
31905b261ecSmrg  HDC			hdcUpdate;
32005b261ecSmrg  PAINTSTRUCT		ps;
32105b261ecSmrg  WindowPtr		pWin = NULL;
32205b261ecSmrg  winPrivWinPtr	        pWinPriv = NULL;
32305b261ecSmrg  ScreenPtr		s_pScreen = NULL;
32405b261ecSmrg  winPrivScreenPtr	s_pScreenPriv = NULL;
32505b261ecSmrg  winScreenInfo		*s_pScreenInfo = NULL;
32605b261ecSmrg  HWND			hwndScreen = NULL;
32705b261ecSmrg  DrawablePtr		pDraw = NULL;
32805b261ecSmrg  winWMMessageRec	wmMsg;
32905b261ecSmrg  Bool                  fWMMsgInitialized = FALSE;
33005b261ecSmrg  static Bool		s_fTracking = FALSE;
33105b261ecSmrg  Bool			needRestack = FALSE;
33205b261ecSmrg  LRESULT		ret;
33305b261ecSmrg
33405b261ecSmrg#if CYGDEBUG
33505b261ecSmrg  winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam, lParam);
33605b261ecSmrg#endif
33705b261ecSmrg
33805b261ecSmrg  /* Check if the Windows window property for our X window pointer is valid */
33905b261ecSmrg  if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
34005b261ecSmrg    {
34105b261ecSmrg      /* Our X window pointer is valid */
34205b261ecSmrg
34305b261ecSmrg      /* Get pointers to the drawable and the screen */
34405b261ecSmrg      pDraw		= &pWin->drawable;
34505b261ecSmrg      s_pScreen		= pWin->drawable.pScreen;
34605b261ecSmrg
34705b261ecSmrg      /* Get a pointer to our window privates */
34805b261ecSmrg      pWinPriv		= winGetWindowPriv(pWin);
34905b261ecSmrg
35005b261ecSmrg      /* Get pointers to our screen privates and screen info */
35105b261ecSmrg      s_pScreenPriv	= pWinPriv->pScreenPriv;
35205b261ecSmrg      s_pScreenInfo	= s_pScreenPriv->pScreenInfo;
35305b261ecSmrg
35405b261ecSmrg      /* Get the handle for our screen-sized window */
35505b261ecSmrg      hwndScreen	= s_pScreenPriv->hwndScreen;
35605b261ecSmrg
35705b261ecSmrg      /* */
35805b261ecSmrg      wmMsg.msg		= 0;
35905b261ecSmrg      wmMsg.hwndWindow	= hwnd;
36005b261ecSmrg      wmMsg.iWindow	= (Window)GetProp (hwnd, WIN_WID_PROP);
36105b261ecSmrg
36205b261ecSmrg      wmMsg.iX		= pDraw->x;
36305b261ecSmrg      wmMsg.iY		= pDraw->y;
36405b261ecSmrg      wmMsg.iWidth	= pDraw->width;
36505b261ecSmrg      wmMsg.iHeight	= pDraw->height;
36605b261ecSmrg
36705b261ecSmrg      fWMMsgInitialized = TRUE;
36805b261ecSmrg
36905b261ecSmrg#if 0
37005b261ecSmrg      /*
37105b261ecSmrg       * Print some debugging information
37205b261ecSmrg       */
37305b261ecSmrg
37405b261ecSmrg      ErrorF ("hWnd %08X\n", hwnd);
37505b261ecSmrg      ErrorF ("pWin %08X\n", pWin);
37605b261ecSmrg      ErrorF ("pDraw %08X\n", pDraw);
37705b261ecSmrg      ErrorF ("\ttype %08X\n", pWin->drawable.type);
37805b261ecSmrg      ErrorF ("\tclass %08X\n", pWin->drawable.class);
37905b261ecSmrg      ErrorF ("\tdepth %08X\n", pWin->drawable.depth);
38005b261ecSmrg      ErrorF ("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
38105b261ecSmrg      ErrorF ("\tid %08X\n", pWin->drawable.id);
38205b261ecSmrg      ErrorF ("\tx %08X\n", pWin->drawable.x);
38305b261ecSmrg      ErrorF ("\ty %08X\n", pWin->drawable.y);
38405b261ecSmrg      ErrorF ("\twidth %08X\n", pWin->drawable.width);
38505b261ecSmrg      ErrorF ("\thenght %08X\n", pWin->drawable.height);
38605b261ecSmrg      ErrorF ("\tpScreen %08X\n", pWin->drawable.pScreen);
38705b261ecSmrg      ErrorF ("\tserialNumber %08X\n", pWin->drawable.serialNumber);
3884642e01fSmrg      ErrorF ("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
38905b261ecSmrg      ErrorF ("pWinPriv %08X\n", pWinPriv);
39005b261ecSmrg      ErrorF ("s_pScreenPriv %08X\n", s_pScreenPriv);
39105b261ecSmrg      ErrorF ("s_pScreenInfo %08X\n", s_pScreenInfo);
39205b261ecSmrg      ErrorF ("hwndScreen %08X\n", hwndScreen);
39305b261ecSmrg#endif
39405b261ecSmrg    }
39505b261ecSmrg
39605b261ecSmrg  /* Branch on message type */
39705b261ecSmrg  switch (message)
39805b261ecSmrg    {
39905b261ecSmrg    case WM_CREATE:
40005b261ecSmrg
40105b261ecSmrg      /* */
40205b261ecSmrg      SetProp (hwnd,
40305b261ecSmrg	       WIN_WINDOW_PROP,
40405b261ecSmrg	       (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams);
40505b261ecSmrg
40605b261ecSmrg      /* */
40705b261ecSmrg      SetProp (hwnd,
40805b261ecSmrg	       WIN_WID_PROP,
40905b261ecSmrg	       (HANDLE)winGetWindowID (((LPCREATESTRUCT) lParam)->lpCreateParams));
41005b261ecSmrg
41105b261ecSmrg      /*
41205b261ecSmrg       * Make X windows' Z orders sync with Windows windows because
41305b261ecSmrg       * there can be AlwaysOnTop windows overlapped on the window
41405b261ecSmrg       * currently being created.
41505b261ecSmrg       */
41605b261ecSmrg      winReorderWindowsMultiWindow ();
41705b261ecSmrg
41805b261ecSmrg      /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
4196747b715Smrg      {
4206747b715Smrg        RECT rWindow;
4216747b715Smrg        HRGN hRgnWindow;
4226747b715Smrg        GetWindowRect(hwnd, &rWindow);
4236747b715Smrg        hRgnWindow = CreateRectRgnIndirect(&rWindow);
4246747b715Smrg        SetWindowRgn (hwnd, hRgnWindow, TRUE);
4256747b715Smrg        DeleteObject(hRgnWindow);
4266747b715Smrg      }
4276747b715Smrg
4286747b715Smrg      SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)XMING_SIGNATURE);
42905b261ecSmrg
43005b261ecSmrg      return 0;
43105b261ecSmrg
43205b261ecSmrg    case WM_INIT_SYS_MENU:
43305b261ecSmrg      /*
43405b261ecSmrg       * Add whatever the setup file wants to for this window
43505b261ecSmrg       */
43605b261ecSmrg      SetupSysMenu ((unsigned long)hwnd);
43705b261ecSmrg      return 0;
43805b261ecSmrg
43905b261ecSmrg    case WM_SYSCOMMAND:
44005b261ecSmrg      /*
44105b261ecSmrg       * Any window menu items go through here
44205b261ecSmrg       */
44305b261ecSmrg      if (HandleCustomWM_COMMAND ((unsigned long)hwnd, LOWORD(wParam)))
44405b261ecSmrg      {
44505b261ecSmrg        /* Don't pass customized menus to DefWindowProc */
44605b261ecSmrg        return 0;
44705b261ecSmrg      }
44805b261ecSmrg      if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE)
44905b261ecSmrg      {
45005b261ecSmrg        WINDOWPLACEMENT wndpl;
45105b261ecSmrg	wndpl.length = sizeof(wndpl);
45205b261ecSmrg	if (GetWindowPlacement(hwnd, &wndpl) && wndpl.showCmd == SW_SHOWMINIMIZED)
45305b261ecSmrg          needRestack = TRUE;
45405b261ecSmrg      }
45505b261ecSmrg      break;
45605b261ecSmrg
45705b261ecSmrg    case WM_INITMENU:
45805b261ecSmrg      /* Checks/Unchecks any menu items before they are displayed */
45905b261ecSmrg      HandleCustomWM_INITMENU ((unsigned long)hwnd, wParam);
46005b261ecSmrg      break;
46105b261ecSmrg
4626747b715Smrg    case WM_ERASEBKGND:
4636747b715Smrg      /*
4646747b715Smrg       * Pretend that we did erase the background but we don't care,
4656747b715Smrg       * since we repaint the entire region anyhow
4666747b715Smrg       * This avoids some flickering when resizing.
4676747b715Smrg       */
4686747b715Smrg      return TRUE;
4696747b715Smrg
47005b261ecSmrg    case WM_PAINT:
47105b261ecSmrg      /* Only paint if our window handle is valid */
47205b261ecSmrg      if (hwndScreen == NULL)
47305b261ecSmrg	break;
47405b261ecSmrg
47505b261ecSmrg      /* BeginPaint gives us an hdc that clips to the invalidated region */
47605b261ecSmrg      hdcUpdate = BeginPaint (hwnd, &ps);
47705b261ecSmrg      /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
47805b261ecSmrg      if (ps.rcPaint.right==0 && ps.rcPaint.bottom==0 && ps.rcPaint.left==0 && ps.rcPaint.top==0)
47905b261ecSmrg      {
48005b261ecSmrg	EndPaint (hwnd, &ps);
48105b261ecSmrg	return 0;
48205b261ecSmrg      }
48305b261ecSmrg
48405b261ecSmrg      /* Try to copy from the shadow buffer */
48505b261ecSmrg      if (!BitBlt (hdcUpdate,
48605b261ecSmrg		   ps.rcPaint.left, ps.rcPaint.top,
48705b261ecSmrg		   ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
48805b261ecSmrg		   s_pScreenPriv->hdcShadow,
48905b261ecSmrg		   ps.rcPaint.left + pWin->drawable.x, ps.rcPaint.top + pWin->drawable.y,
49005b261ecSmrg		   SRCCOPY))
49105b261ecSmrg	{
49205b261ecSmrg	  LPVOID lpMsgBuf;
49305b261ecSmrg
49405b261ecSmrg	  /* Display a fancy error message */
49505b261ecSmrg	  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
49605b261ecSmrg			 FORMAT_MESSAGE_FROM_SYSTEM |
49705b261ecSmrg			 FORMAT_MESSAGE_IGNORE_INSERTS,
49805b261ecSmrg			 NULL,
49905b261ecSmrg			 GetLastError (),
50005b261ecSmrg			 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
50105b261ecSmrg			 (LPTSTR) &lpMsgBuf,
50205b261ecSmrg			 0, NULL);
50305b261ecSmrg
50405b261ecSmrg	  ErrorF ("winTopLevelWindowProc - BitBlt failed: %s\n",
50505b261ecSmrg		  (LPSTR)lpMsgBuf);
50605b261ecSmrg	  LocalFree (lpMsgBuf);
50705b261ecSmrg	}
50805b261ecSmrg
50905b261ecSmrg      /* EndPaint frees the DC */
51005b261ecSmrg      EndPaint (hwnd, &ps);
51105b261ecSmrg      return 0;
51205b261ecSmrg
51305b261ecSmrg    case WM_MOUSEMOVE:
51405b261ecSmrg      /* Unpack the client area mouse coordinates */
51505b261ecSmrg      ptMouse.x = GET_X_LPARAM(lParam);
51605b261ecSmrg      ptMouse.y = GET_Y_LPARAM(lParam);
51705b261ecSmrg
51805b261ecSmrg      /* Translate the client area mouse coordinates to screen coordinates */
51905b261ecSmrg      ClientToScreen (hwnd, &ptMouse);
52005b261ecSmrg
52105b261ecSmrg      /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
52205b261ecSmrg      ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
52305b261ecSmrg      ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
52405b261ecSmrg
52505b261ecSmrg      /* We can't do anything without privates */
52605b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
52705b261ecSmrg	break;
52805b261ecSmrg
52905b261ecSmrg      /* Has the mouse pointer crossed screens? */
5306747b715Smrg      if (s_pScreen != miPointerGetScreen(g_pwinPointer))
5316747b715Smrg	miPointerSetScreen (g_pwinPointer, s_pScreenInfo->dwScreen,
53205b261ecSmrg			       ptMouse.x - s_pScreenInfo->dwXOffset,
53305b261ecSmrg			       ptMouse.y - s_pScreenInfo->dwYOffset);
53405b261ecSmrg
53505b261ecSmrg      /* Are we tracking yet? */
53605b261ecSmrg      if (!s_fTracking)
53705b261ecSmrg	{
53805b261ecSmrg	  TRACKMOUSEEVENT		tme;
53905b261ecSmrg
54005b261ecSmrg	  /* Setup data structure */
54105b261ecSmrg	  ZeroMemory (&tme, sizeof (tme));
54205b261ecSmrg	  tme.cbSize = sizeof (tme);
54305b261ecSmrg	  tme.dwFlags = TME_LEAVE;
54405b261ecSmrg	  tme.hwndTrack = hwnd;
54505b261ecSmrg
54605b261ecSmrg	  /* Call the tracking function */
54705b261ecSmrg	  if (!(*g_fpTrackMouseEvent) (&tme))
54805b261ecSmrg	    ErrorF ("winTopLevelWindowProc - _TrackMouseEvent failed\n");
54905b261ecSmrg
55005b261ecSmrg	  /* Flag that we are tracking now */
55105b261ecSmrg	  s_fTracking = TRUE;
55205b261ecSmrg	}
55305b261ecSmrg
55405b261ecSmrg      /* Hide or show the Windows mouse cursor */
55505b261ecSmrg      if (g_fSoftwareCursor && g_fCursor)
55605b261ecSmrg	{
55705b261ecSmrg	  /* Hide Windows cursor */
55805b261ecSmrg	  g_fCursor = FALSE;
55905b261ecSmrg	  ShowCursor (FALSE);
56005b261ecSmrg	}
56105b261ecSmrg
56205b261ecSmrg      /* Kill the timer used to poll mouse events */
56305b261ecSmrg      if (g_uipMousePollingTimerID != 0)
56405b261ecSmrg	{
56505b261ecSmrg	  KillTimer (s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
56605b261ecSmrg	  g_uipMousePollingTimerID = 0;
56705b261ecSmrg	}
56805b261ecSmrg
56905b261ecSmrg      /* Deliver absolute cursor position to X Server */
5706747b715Smrg      winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
5716747b715Smrg		       ptMouse.y - s_pScreenInfo->dwYOffset);
5726747b715Smrg
57305b261ecSmrg      return 0;
57405b261ecSmrg
57505b261ecSmrg    case WM_NCMOUSEMOVE:
57605b261ecSmrg      /*
57705b261ecSmrg       * We break instead of returning 0 since we need to call
57805b261ecSmrg       * DefWindowProc to get the mouse cursor changes
57905b261ecSmrg       * and min/max/close button highlighting in Windows XP.
58005b261ecSmrg       * The Platform SDK says that you should return 0 if you
58105b261ecSmrg       * process this message, but it fails to mention that you
58205b261ecSmrg       * will give up any default functionality if you do return 0.
58305b261ecSmrg       */
58405b261ecSmrg
58505b261ecSmrg      /* We can't do anything without privates */
58605b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
58705b261ecSmrg	break;
58805b261ecSmrg
58905b261ecSmrg      /* Non-client mouse movement, show Windows cursor */
59005b261ecSmrg      if (g_fSoftwareCursor && !g_fCursor)
59105b261ecSmrg	{
59205b261ecSmrg	  g_fCursor = TRUE;
59305b261ecSmrg	  ShowCursor (TRUE);
59405b261ecSmrg	}
59505b261ecSmrg
5966747b715Smrg      winStartMousePolling(s_pScreenPriv);
5976747b715Smrg
59805b261ecSmrg      break;
59905b261ecSmrg
60005b261ecSmrg    case WM_MOUSELEAVE:
60105b261ecSmrg      /* Mouse has left our client area */
60205b261ecSmrg
60305b261ecSmrg      /* Flag that we are no longer tracking */
60405b261ecSmrg      s_fTracking = FALSE;
60505b261ecSmrg
60605b261ecSmrg      /* Show the mouse cursor, if necessary */
60705b261ecSmrg      if (g_fSoftwareCursor && !g_fCursor)
60805b261ecSmrg	{
60905b261ecSmrg	  g_fCursor = TRUE;
61005b261ecSmrg	  ShowCursor (TRUE);
61105b261ecSmrg	}
61205b261ecSmrg
6136747b715Smrg      winStartMousePolling(s_pScreenPriv);
6146747b715Smrg
61505b261ecSmrg      return 0;
61605b261ecSmrg
61705b261ecSmrg    case WM_LBUTTONDBLCLK:
61805b261ecSmrg    case WM_LBUTTONDOWN:
61905b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
62005b261ecSmrg	break;
62105b261ecSmrg      g_fButton[0] = TRUE;
6226747b715Smrg      SetCapture(hwnd);
62305b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
6246747b715Smrg
62505b261ecSmrg    case WM_LBUTTONUP:
62605b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
62705b261ecSmrg	break;
62805b261ecSmrg      g_fButton[0] = FALSE;
6296747b715Smrg      ReleaseCapture();
6306747b715Smrg      winStartMousePolling(s_pScreenPriv);
63105b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
63205b261ecSmrg
63305b261ecSmrg    case WM_MBUTTONDBLCLK:
63405b261ecSmrg    case WM_MBUTTONDOWN:
63505b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
63605b261ecSmrg	break;
63705b261ecSmrg      g_fButton[1] = TRUE;
6386747b715Smrg      SetCapture(hwnd);
63905b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
6406747b715Smrg
64105b261ecSmrg    case WM_MBUTTONUP:
64205b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
64305b261ecSmrg	break;
64405b261ecSmrg      g_fButton[1] = FALSE;
6456747b715Smrg      ReleaseCapture();
6466747b715Smrg      winStartMousePolling(s_pScreenPriv);
64705b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
6486747b715Smrg
64905b261ecSmrg    case WM_RBUTTONDBLCLK:
65005b261ecSmrg    case WM_RBUTTONDOWN:
65105b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
65205b261ecSmrg	break;
65305b261ecSmrg      g_fButton[2] = TRUE;
6546747b715Smrg      SetCapture(hwnd);
65505b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
6566747b715Smrg
65705b261ecSmrg    case WM_RBUTTONUP:
65805b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
65905b261ecSmrg	break;
66005b261ecSmrg      g_fButton[2] = FALSE;
6616747b715Smrg      ReleaseCapture();
6626747b715Smrg      winStartMousePolling(s_pScreenPriv);
66305b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
66405b261ecSmrg
66505b261ecSmrg    case WM_XBUTTONDBLCLK:
66605b261ecSmrg    case WM_XBUTTONDOWN:
66705b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
66805b261ecSmrg	break;
6696747b715Smrg	SetCapture(hwnd);
67005b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
6716747b715Smrg
67205b261ecSmrg    case WM_XBUTTONUP:
67305b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
67405b261ecSmrg	break;
6756747b715Smrg      ReleaseCapture();
6766747b715Smrg      winStartMousePolling(s_pScreenPriv);
67705b261ecSmrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
67805b261ecSmrg
67905b261ecSmrg    case WM_MOUSEWHEEL:
6806747b715Smrg      if (SendMessage(hwnd, WM_NCHITTEST, 0, MAKELONG(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) == HTCLIENT)
6816747b715Smrg	{
6826747b715Smrg	  /* Pass the message to the root window */
6836747b715Smrg	  SendMessage (hwndScreen, message, wParam, lParam);
6846747b715Smrg	  return 0;
6856747b715Smrg	}
6866747b715Smrg      else break;
68705b261ecSmrg
68805b261ecSmrg    case WM_SETFOCUS:
68905b261ecSmrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
69005b261ecSmrg	break;
69105b261ecSmrg
6926747b715Smrg      {
6936747b715Smrg	/* Get the parent window for transient handling */
6946747b715Smrg	HWND hParent = GetParent(hwnd);
6956747b715Smrg	if (hParent && IsIconic(hParent)) ShowWindow (hParent, SW_RESTORE);
6966747b715Smrg      }
6976747b715Smrg
69805b261ecSmrg      winRestoreModeKeyStates ();
69905b261ecSmrg
70005b261ecSmrg      /* Add the keyboard hook if possible */
70105b261ecSmrg      if (g_fKeyboardHookLL)
70205b261ecSmrg	g_fKeyboardHookLL = winInstallKeyboardHookLL ();
70305b261ecSmrg      return 0;
70405b261ecSmrg
70505b261ecSmrg    case WM_KILLFOCUS:
70605b261ecSmrg      /* Pop any pressed keys since we are losing keyboard focus */
70705b261ecSmrg      winKeybdReleaseKeys ();
70805b261ecSmrg
70905b261ecSmrg      /* Remove our keyboard hook if it is installed */
71005b261ecSmrg      winRemoveKeyboardHookLL ();
7116747b715Smrg      if (!wParam)
7126747b715Smrg	/* Revert the X focus as well, but only if the Windows focus is going to another window */
7136747b715Smrg	DeleteWindowFromAnyEvents(pWin, FALSE);
71405b261ecSmrg      return 0;
71505b261ecSmrg
71605b261ecSmrg    case WM_SYSDEADCHAR:
71705b261ecSmrg    case WM_DEADCHAR:
71805b261ecSmrg      /*
71905b261ecSmrg       * NOTE: We do nothing with WM_*CHAR messages,
72005b261ecSmrg       * nor does the root window, so we can just toss these messages.
72105b261ecSmrg       */
72205b261ecSmrg      return 0;
72305b261ecSmrg
72405b261ecSmrg    case WM_SYSKEYDOWN:
72505b261ecSmrg    case WM_KEYDOWN:
72605b261ecSmrg
72705b261ecSmrg      /*
72805b261ecSmrg       * Don't pass Alt-F4 key combo to root window,
72905b261ecSmrg       * let Windows translate to WM_CLOSE and close this top-level window.
73005b261ecSmrg       *
73105b261ecSmrg       * NOTE: We purposely don't check the fUseWinKillKey setting because
73205b261ecSmrg       * it should only apply to the key handling for the root window,
73305b261ecSmrg       * not for top-level window-manager windows.
73405b261ecSmrg       *
73505b261ecSmrg       * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
73605b261ecSmrg       * because that is a key combo that no X app should be expecting to
73705b261ecSmrg       * receive, since it has historically been used to shutdown the X server.
73805b261ecSmrg       * Passing Ctrl-Alt-Backspace to the root window preserves that
73905b261ecSmrg       * behavior, assuming that -unixkill has been passed as a parameter.
74005b261ecSmrg       */
74105b261ecSmrg      if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000))
74205b261ecSmrg	  break;
74305b261ecSmrg
74405b261ecSmrg#if CYGWINDOWING_DEBUG
74505b261ecSmrg      if (wParam == VK_ESCAPE)
74605b261ecSmrg	{
74705b261ecSmrg	  /* Place for debug: put any tests and dumps here */
74805b261ecSmrg	  WINDOWPLACEMENT windPlace;
74905b261ecSmrg	  RECT rc;
75005b261ecSmrg	  LPRECT pRect;
75105b261ecSmrg
75205b261ecSmrg	  windPlace.length = sizeof (WINDOWPLACEMENT);
75305b261ecSmrg	  GetWindowPlacement (hwnd, &windPlace);
75405b261ecSmrg	  pRect = &windPlace.rcNormalPosition;
75505b261ecSmrg	  ErrorF ("\nCYGWINDOWING Dump:\n"
75605b261ecSmrg		  "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
75705b261ecSmrg		  pDraw->y, pDraw->width, pDraw->height);
75805b261ecSmrg	  ErrorF ("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left,
75905b261ecSmrg		  pRect->top, pRect->right - pRect->left,
76005b261ecSmrg		  pRect->bottom - pRect->top);
76105b261ecSmrg	  if (GetClientRect (hwnd, &rc))
76205b261ecSmrg	    {
76305b261ecSmrg	      pRect = &rc;
76405b261ecSmrg	      ErrorF ("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
76505b261ecSmrg		      pRect->top, pRect->right - pRect->left,
76605b261ecSmrg		      pRect->bottom - pRect->top);
76705b261ecSmrg	    }
76805b261ecSmrg	  if (GetWindowRect (hwnd, &rc))
76905b261ecSmrg	    {
77005b261ecSmrg	      pRect = &rc;
77105b261ecSmrg	      ErrorF ("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
77205b261ecSmrg		      pRect->top, pRect->right - pRect->left,
77305b261ecSmrg		      pRect->bottom - pRect->top);
77405b261ecSmrg	    }
77505b261ecSmrg	  ErrorF ("\n");
77605b261ecSmrg	}
77705b261ecSmrg#endif
77805b261ecSmrg
77905b261ecSmrg      /* Pass the message to the root window */
78005b261ecSmrg      return winWindowProc(hwndScreen, message, wParam, lParam);
78105b261ecSmrg
78205b261ecSmrg    case WM_SYSKEYUP:
78305b261ecSmrg    case WM_KEYUP:
78405b261ecSmrg
78505b261ecSmrg
78605b261ecSmrg      /* Pass the message to the root window */
78705b261ecSmrg      return winWindowProc(hwndScreen, message, wParam, lParam);
78805b261ecSmrg
78905b261ecSmrg    case WM_HOTKEY:
79005b261ecSmrg
79105b261ecSmrg      /* Pass the message to the root window */
79205b261ecSmrg      SendMessage (hwndScreen, message, wParam, lParam);
79305b261ecSmrg      return 0;
79405b261ecSmrg
79505b261ecSmrg    case WM_ACTIVATE:
79605b261ecSmrg
79705b261ecSmrg      /* Pass the message to the root window */
79805b261ecSmrg      SendMessage (hwndScreen, message, wParam, lParam);
79905b261ecSmrg
80005b261ecSmrg      if (LOWORD(wParam) != WA_INACTIVE)
80105b261ecSmrg	{
80205b261ecSmrg	  /* Raise the window to the top in Z order */
80305b261ecSmrg          /* ago: Activate does not mean putting it to front! */
80405b261ecSmrg          /*
80505b261ecSmrg	  wmMsg.msg = WM_WM_RAISE;
80605b261ecSmrg	  if (fWMMsgInitialized)
80705b261ecSmrg	    winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
80805b261ecSmrg          */
80905b261ecSmrg
81005b261ecSmrg	  /* Tell our Window Manager thread to activate the window */
81105b261ecSmrg	  wmMsg.msg = WM_WM_ACTIVATE;
81205b261ecSmrg	  if (fWMMsgInitialized)
81305b261ecSmrg	    if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
81405b261ecSmrg	      winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
81505b261ecSmrg	}
8166747b715Smrg      /* Prevent the mouse wheel from stalling when another window is minimized */
8176747b715Smrg      if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
8186747b715Smrg	  (HWND)lParam != NULL && (HWND)lParam != (HWND)GetParent(hwnd))
8196747b715Smrg	SetFocus(hwnd);
82005b261ecSmrg      return 0;
82105b261ecSmrg
82205b261ecSmrg    case WM_ACTIVATEAPP:
82305b261ecSmrg      /*
82405b261ecSmrg       * This message is also sent to the root window
82505b261ecSmrg       * so we do nothing for individual multiwindow windows
82605b261ecSmrg       */
82705b261ecSmrg      break;
82805b261ecSmrg
82905b261ecSmrg    case WM_CLOSE:
83005b261ecSmrg      /* Branch on if the window was killed in X already */
83105b261ecSmrg      if (pWinPriv->fXKilled)
83205b261ecSmrg        {
83305b261ecSmrg	  /* Window was killed, go ahead and destroy the window */
83405b261ecSmrg	  DestroyWindow (hwnd);
83505b261ecSmrg	}
83605b261ecSmrg      else
83705b261ecSmrg	{
83805b261ecSmrg	  /* Tell our Window Manager thread to kill the window */
83905b261ecSmrg	  wmMsg.msg = WM_WM_KILL;
84005b261ecSmrg	  if (fWMMsgInitialized)
84105b261ecSmrg	    winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
84205b261ecSmrg	}
84305b261ecSmrg      return 0;
84405b261ecSmrg
84505b261ecSmrg    case WM_DESTROY:
84605b261ecSmrg
84705b261ecSmrg      /* Branch on if the window was killed in X already */
84805b261ecSmrg      if (pWinPriv && !pWinPriv->fXKilled)
84905b261ecSmrg	{
85005b261ecSmrg	  ErrorF ("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
85105b261ecSmrg
85205b261ecSmrg	  /* Tell our Window Manager thread to kill the window */
85305b261ecSmrg	  wmMsg.msg = WM_WM_KILL;
85405b261ecSmrg	  if (fWMMsgInitialized)
85505b261ecSmrg	    winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
85605b261ecSmrg	}
85705b261ecSmrg
85805b261ecSmrg      RemoveProp (hwnd, WIN_WINDOW_PROP);
85905b261ecSmrg      RemoveProp (hwnd, WIN_WID_PROP);
86005b261ecSmrg      RemoveProp (hwnd, WIN_NEEDMANAGE_PROP);
86105b261ecSmrg
86205b261ecSmrg      break;
86305b261ecSmrg
86405b261ecSmrg    case WM_MOVE:
86505b261ecSmrg      /* Adjust the X Window to the moved Windows window */
86605b261ecSmrg      winAdjustXWindow (pWin, hwnd);
86705b261ecSmrg      return 0;
86805b261ecSmrg
86905b261ecSmrg    case WM_SHOWWINDOW:
87005b261ecSmrg      /* Bail out if the window is being hidden */
87105b261ecSmrg      if (!wParam)
87205b261ecSmrg	return 0;
87305b261ecSmrg
87405b261ecSmrg      /* */
87505b261ecSmrg      if (!pWin->overrideRedirect)
87605b261ecSmrg	{
87705b261ecSmrg	  /* Flag that this window needs to be made active when clicked */
87805b261ecSmrg	  SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
87905b261ecSmrg
8806747b715Smrg	  if (!(GetWindowLongPtr (hwnd, GWL_EXSTYLE) & WS_EX_APPWINDOW))
88105b261ecSmrg	    {
8826747b715Smrg	      HWND		zstyle = HWND_NOTOPMOST;
88305b261ecSmrg
88405b261ecSmrg	      /* Set the window extended style flags */
88505b261ecSmrg	      SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
88605b261ecSmrg
8876747b715Smrg	      /* Set the transient style flags */
8886747b715Smrg	      if (GetParent(hwnd)) SetWindowLongPtr (hwnd, GWL_STYLE,
8896747b715Smrg		   WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
89005b261ecSmrg	      /* Set the window standard style flags */
8916747b715Smrg	      else SetWindowLongPtr (hwnd, GWL_STYLE,
8926747b715Smrg		   (WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
8936747b715Smrg		   & ~WS_CAPTION & ~WS_SIZEBOX);
89405b261ecSmrg
8956747b715Smrg	      winUpdateWindowPosition (hwnd, FALSE, &zstyle);
89605b261ecSmrg	      SetForegroundWindow (hwnd);
89705b261ecSmrg	    }
8986747b715Smrg	  wmMsg.msg = WM_WM_MAP3;
89905b261ecSmrg	}
90005b261ecSmrg      else /* It is an overridden window so make it top of Z stack */
90105b261ecSmrg	{
9026747b715Smrg	  HWND forHwnd = GetForegroundWindow();
90305b261ecSmrg#if CYGWINDOWING_DEBUG
90405b261ecSmrg	  ErrorF ("overridden window is shown\n");
90505b261ecSmrg#endif
9066747b715Smrg	  if (forHwnd != NULL)
9076747b715Smrg	  {
9086747b715Smrg	    if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)XMING_SIGNATURE)
9096747b715Smrg	    {
9106747b715Smrg	      if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
9116747b715Smrg		SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
9126747b715Smrg	      else
9136747b715Smrg		SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
9146747b715Smrg	    }
9156747b715Smrg	  }
9166747b715Smrg	  wmMsg.msg = WM_WM_MAP2;
91705b261ecSmrg	}
91805b261ecSmrg
91905b261ecSmrg      /* Tell our Window Manager thread to map the window */
92005b261ecSmrg      if (fWMMsgInitialized)
92105b261ecSmrg	winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
92205b261ecSmrg
9236747b715Smrg      winStartMousePolling(s_pScreenPriv);
9246747b715Smrg
92505b261ecSmrg      return 0;
92605b261ecSmrg
92705b261ecSmrg    case WM_SIZING:
92805b261ecSmrg      /* Need to legalize the size according to WM_NORMAL_HINTS */
92905b261ecSmrg      /* for applications like xterm */
93005b261ecSmrg      return ValidateSizing (hwnd, pWin, wParam, lParam);
93105b261ecSmrg
93205b261ecSmrg    case WM_WINDOWPOSCHANGED:
93305b261ecSmrg      {
93405b261ecSmrg	LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
93505b261ecSmrg
93605b261ecSmrg	if (!(pWinPos->flags & SWP_NOZORDER))
93705b261ecSmrg	  {
93805b261ecSmrg#if CYGWINDOWING_DEBUG
93905b261ecSmrg	    winDebug ("\twindow z order was changed\n");
94005b261ecSmrg#endif
94105b261ecSmrg	    if (pWinPos->hwndInsertAfter == HWND_TOP
94205b261ecSmrg		||pWinPos->hwndInsertAfter == HWND_TOPMOST
94305b261ecSmrg		||pWinPos->hwndInsertAfter == HWND_NOTOPMOST)
94405b261ecSmrg	      {
94505b261ecSmrg#if CYGWINDOWING_DEBUG
94605b261ecSmrg		winDebug ("\traise to top\n");
94705b261ecSmrg#endif
94805b261ecSmrg		/* Raise the window to the top in Z order */
94905b261ecSmrg		winRaiseWindow(pWin);
95005b261ecSmrg	      }
95105b261ecSmrg	    else if (pWinPos->hwndInsertAfter == HWND_BOTTOM)
95205b261ecSmrg	      {
95305b261ecSmrg	      }
95405b261ecSmrg	    else
95505b261ecSmrg	      {
95605b261ecSmrg		/* Check if this window is top of X windows. */
95705b261ecSmrg		HWND hWndAbove = NULL;
95805b261ecSmrg		DWORD dwCurrentProcessID = GetCurrentProcessId ();
95905b261ecSmrg		DWORD dwWindowProcessID = 0;
96005b261ecSmrg
96105b261ecSmrg		for (hWndAbove = pWinPos->hwndInsertAfter;
96205b261ecSmrg		     hWndAbove != NULL;
96305b261ecSmrg		     hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV))
96405b261ecSmrg		  {
96505b261ecSmrg		    /* Ignore other XWin process's window */
96605b261ecSmrg		    GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID);
96705b261ecSmrg
96805b261ecSmrg		    if ((dwWindowProcessID == dwCurrentProcessID)
96905b261ecSmrg			&& GetProp (hWndAbove, WIN_WINDOW_PROP)
97005b261ecSmrg			&& !IsWindowVisible (hWndAbove)
97105b261ecSmrg			&& !IsIconic (hWndAbove) ) /* ignore minimized windows */
97205b261ecSmrg		      break;
97305b261ecSmrg		  }
97405b261ecSmrg		/* If this is top of X windows in Windows stack,
97505b261ecSmrg		   raise it in X stack. */
97605b261ecSmrg		if (hWndAbove == NULL)
97705b261ecSmrg		  {
97805b261ecSmrg#if CYGWINDOWING_DEBUG
97905b261ecSmrg		    winDebug ("\traise to top\n");
98005b261ecSmrg#endif
98105b261ecSmrg		    winRaiseWindow(pWin);
98205b261ecSmrg		  }
98305b261ecSmrg	      }
98405b261ecSmrg	  }
98505b261ecSmrg      }
98605b261ecSmrg      /*
98705b261ecSmrg       * Pass the message to DefWindowProc to let the function
98805b261ecSmrg       * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
98905b261ecSmrg      */
99005b261ecSmrg      break;
99105b261ecSmrg
99205b261ecSmrg    case WM_SIZE:
99305b261ecSmrg      /* see dix/window.c */
99405b261ecSmrg#if CYGWINDOWING_DEBUG
99505b261ecSmrg      {
99605b261ecSmrg	char buf[64];
99705b261ecSmrg	switch (wParam)
99805b261ecSmrg	  {
99905b261ecSmrg	  case SIZE_MINIMIZED:
100005b261ecSmrg	    strcpy(buf, "SIZE_MINIMIZED");
100105b261ecSmrg	    break;
100205b261ecSmrg	  case SIZE_MAXIMIZED:
100305b261ecSmrg	    strcpy(buf, "SIZE_MAXIMIZED");
100405b261ecSmrg	    break;
100505b261ecSmrg	  case SIZE_RESTORED:
100605b261ecSmrg	    strcpy(buf, "SIZE_RESTORED");
100705b261ecSmrg	    break;
100805b261ecSmrg	  default:
100905b261ecSmrg	    strcpy(buf, "UNKNOWN_FLAG");
101005b261ecSmrg	  }
101105b261ecSmrg	ErrorF ("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
101205b261ecSmrg		(int)LOWORD(lParam), (int)HIWORD(lParam), buf,
101305b261ecSmrg		(int)(GetTickCount ()));
101405b261ecSmrg      }
101505b261ecSmrg#endif
101605b261ecSmrg      /* Adjust the X Window to the moved Windows window */
101705b261ecSmrg      winAdjustXWindow (pWin, hwnd);
101805b261ecSmrg      return 0; /* end of WM_SIZE handler */
101905b261ecSmrg
102005b261ecSmrg    case WM_MOUSEACTIVATE:
102105b261ecSmrg
102205b261ecSmrg      /* Check if this window needs to be made active when clicked */
102305b261ecSmrg      if (!GetProp (pWinPriv->hWnd, WIN_NEEDMANAGE_PROP))
102405b261ecSmrg	{
102505b261ecSmrg#if CYGMULTIWINDOW_DEBUG
102605b261ecSmrg	  ErrorF ("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
102705b261ecSmrg		  "MA_NOACTIVATE\n");
102805b261ecSmrg#endif
102905b261ecSmrg
103005b261ecSmrg	  /* */
103105b261ecSmrg	  return MA_NOACTIVATE;
103205b261ecSmrg	}
103305b261ecSmrg      break;
103405b261ecSmrg
103505b261ecSmrg    case WM_SETCURSOR:
103605b261ecSmrg      if (LOWORD(lParam) == HTCLIENT)
103705b261ecSmrg	{
103805b261ecSmrg	  if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle);
103905b261ecSmrg	  return TRUE;
104005b261ecSmrg	}
104105b261ecSmrg      break;
104205b261ecSmrg
104305b261ecSmrg    default:
104405b261ecSmrg      break;
104505b261ecSmrg    }
104605b261ecSmrg
104705b261ecSmrg  ret = DefWindowProc (hwnd, message, wParam, lParam);
104805b261ecSmrg  /*
104905b261ecSmrg   * If the window was minized we get the stack change before the window is restored
105005b261ecSmrg   * and so it gets lost. Ensure there stacking order is correct.
105105b261ecSmrg   */
105205b261ecSmrg  if (needRestack)
105305b261ecSmrg    winReorderWindowsMultiWindow();
105405b261ecSmrg  return ret;
105505b261ecSmrg}
1056