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