1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
27 *
28 * Authors:	Kensuke Matsuzaki
29 *		Earle F. Philhower, III
30 *		Harold L Hunt II
31 */
32#ifdef HAVE_XWIN_CONFIG_H
33#include <xwin-config.h>
34#endif
35#include "win.h"
36#include <winuser.h>
37#define _WINDOWSWM_SERVER_
38#include <X11/extensions/windowswmstr.h>
39#include "dixevents.h"
40#include "propertyst.h"
41#include <X11/Xatom.h>
42#include "winmultiwindowclass.h"
43#include "winmsg.h"
44#include "inputstr.h"
45
46
47/*
48 * Constant defines
49 */
50
51#define MOUSE_ACTIVATE_DEFAULT		TRUE
52#define RAISE_ON_CLICK_DEFAULT		FALSE
53
54
55/*
56 * Local globals
57 */
58
59static UINT_PTR		g_uipMousePollingTimerID = 0;
60
61
62/*
63 * Local function
64 */
65
66DEFINE_ATOM_HELPER(AtmWindowsWmRaiseOnClick, WINDOWSWM_RAISE_ON_CLICK)
67DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE)
68/* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */
69
70/*
71 * ConstrainSize - Taken from TWM sources - Respects hints for sizing
72 */
73#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
74static void
75ConstrainSize (WinXSizeHints hints, int *widthp, int *heightp)
76{
77  int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
78  int baseWidth, baseHeight;
79  int dwidth = *widthp, dheight = *heightp;
80
81  if (hints.flags & PMinSize)
82    {
83      minWidth = hints.min_width;
84      minHeight = hints.min_height;
85    }
86  else if (hints.flags & PBaseSize)
87    {
88      minWidth = hints.base_width;
89      minHeight = hints.base_height;
90    }
91  else
92    minWidth = minHeight = 1;
93
94  if (hints.flags & PBaseSize)
95    {
96      baseWidth = hints.base_width;
97      baseHeight = hints.base_height;
98    }
99  else if (hints.flags & PMinSize)
100    {
101      baseWidth = hints.min_width;
102      baseHeight = hints.min_height;
103    }
104  else
105    baseWidth = baseHeight = 0;
106
107  if (hints.flags & PMaxSize)
108    {
109      maxWidth = hints.max_width;
110      maxHeight = hints.max_height;
111    }
112  else
113    {
114      maxWidth = MAXINT;
115      maxHeight = MAXINT;
116    }
117
118  if (hints.flags & PResizeInc)
119    {
120      xinc = hints.width_inc;
121      yinc = hints.height_inc;
122    }
123  else
124    xinc = yinc = 1;
125
126  /*
127   * First, clamp to min and max values
128   */
129  if (dwidth < minWidth)
130    dwidth = minWidth;
131  if (dheight < minHeight)
132    dheight = minHeight;
133
134  if (dwidth > maxWidth)
135    dwidth = maxWidth;
136  if (dheight > maxHeight)
137    dheight = maxHeight;
138
139  /*
140   * Second, fit to base + N * inc
141   */
142  dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
143  dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
144
145  /*
146   * Third, adjust for aspect ratio
147   */
148
149  /*
150   * The math looks like this:
151   *
152   * minAspectX    dwidth     maxAspectX
153   * ---------- <= ------- <= ----------
154   * minAspectY    dheight    maxAspectY
155   *
156   * If that is multiplied out, then the width and height are
157   * invalid in the following situations:
158   *
159   * minAspectX * dheight > minAspectY * dwidth
160   * maxAspectX * dheight < maxAspectY * dwidth
161   *
162   */
163
164  if (hints.flags & PAspect)
165    {
166      if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth)
167        {
168	  delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc);
169	  if (dwidth + delta <= maxWidth)
170	    dwidth += delta;
171	  else
172            {
173	      delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc);
174	      if (dheight - delta >= minHeight)
175		dheight -= delta;
176            }
177        }
178
179      if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth)
180        {
181	  delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc);
182	  if (dheight + delta <= maxHeight)
183	    dheight += delta;
184	  else
185            {
186	      delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc);
187	      if (dwidth - delta >= minWidth)
188		dwidth -= delta;
189            }
190        }
191    }
192
193  /* Return computed values */
194  *widthp = dwidth;
195  *heightp = dheight;
196}
197#undef makemult
198
199
200
201/*
202 * ValidateSizing - Ensures size request respects hints
203 */
204static int
205ValidateSizing (HWND hwnd, WindowPtr pWin,
206		WPARAM wParam, LPARAM lParam)
207{
208  WinXSizeHints sizeHints;
209  RECT *rect;
210  int iWidth, iHeight, iTopBorder;
211  POINT pt;
212
213  /* Invalid input checking */
214  if (pWin==NULL || lParam==0)
215    {
216      ErrorF ("Invalid input checking\n");
217      return FALSE;
218    }
219
220  /* No size hints, no checking */
221  if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints))
222    {
223      ErrorF ("No size hints, no checking\n");
224      return FALSE;
225    }
226
227  /* Avoid divide-by-zero */
228  if (sizeHints.flags & PResizeInc)
229    {
230      if (sizeHints.width_inc == 0) sizeHints.width_inc = 1;
231      if (sizeHints.height_inc == 0) sizeHints.height_inc = 1;
232    }
233
234  rect = (RECT*)lParam;
235
236  iWidth = rect->right - rect->left;
237  iHeight = rect->bottom - rect->top;
238
239  /* Get title bar height, there must be an easier way?! */
240  pt.x = pt.y = 0;
241  ClientToScreen(hwnd, &pt);
242  iTopBorder = pt.y - rect->top;
243
244  /* Now remove size of any borders */
245  iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
246  iHeight -= GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
247
248  /* Constrain the size to legal values */
249  ConstrainSize (sizeHints, &iWidth, &iHeight);
250
251  /* Add back the borders */
252  iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME);
253  iHeight += GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
254
255  /* Adjust size according to where we're dragging from */
256  switch(wParam) {
257  case WMSZ_TOP:
258  case WMSZ_TOPRIGHT:
259  case WMSZ_BOTTOM:
260  case WMSZ_BOTTOMRIGHT:
261  case WMSZ_RIGHT:
262    rect->right = rect->left + iWidth;
263    break;
264  default:
265    rect->left = rect->right - iWidth;
266    break;
267  }
268  switch(wParam) {
269  case WMSZ_BOTTOM:
270  case WMSZ_BOTTOMRIGHT:
271  case WMSZ_BOTTOMLEFT:
272  case WMSZ_RIGHT:
273  case WMSZ_LEFT:
274    rect->bottom = rect->top + iHeight;
275    break;
276  default:
277    rect->top = rect->bottom - iHeight;
278    break;
279  }
280  return TRUE;
281}
282
283
284/*
285 * IsRaiseOnClick
286 */
287
288static Bool
289IsRaiseOnClick (WindowPtr pWin)
290{
291
292  struct _Window	*pwin;
293  struct _Property	*prop;
294  /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
295   * Which pointer's current window do we want? */
296  WindowPtr		pRoot = GetCurrentRootWindow (inputInfo.pointer);
297
298  if (!pWin)
299    {
300      ErrorF ("IsRaiseOnClick - no prop use default value:%d\n",
301	      RAISE_ON_CLICK_DEFAULT);
302      return RAISE_ON_CLICK_DEFAULT;
303    }
304
305  pwin = (struct _Window*) pWin;
306
307  if (pwin->optional)
308    prop = (struct _Property *) pwin->optional->userProps;
309  else
310    prop = NULL;
311
312  while (prop)
313    {
314      if (prop->propertyName == AtmWindowsWmRaiseOnClick ()
315	  && prop->type == XA_INTEGER
316	  && prop->format == 32)
317	{
318	  return *(int*)prop->data;
319	}
320      else
321	prop = prop->next;
322    }
323
324  if (pWin != pRoot)
325    {
326      return IsRaiseOnClick (pRoot);
327    }
328  else
329    {
330#if CYGMULTIWINDOW_DEBUG
331      winDebug ("IsRaiseOnClick - no prop use default value:%d\n",
332		RAISE_ON_CLICK_DEFAULT);
333#endif
334      return RAISE_ON_CLICK_DEFAULT;
335    }
336}
337
338
339/*
340 * IsMouseActive
341 */
342
343static Bool
344IsMouseActive (WindowPtr pWin)
345{
346
347  struct _Window	*pwin;
348  struct _Property	*prop;
349  /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
350   * Which pointer's current window do we want? */
351  WindowPtr		pRoot = GetCurrentRootWindow (inputInfo.pointer);
352
353  if (!pWin)
354    {
355      ErrorF ("IsMouseActive - pWin was NULL use default value:%d\n",
356	      MOUSE_ACTIVATE_DEFAULT);
357      return MOUSE_ACTIVATE_DEFAULT;
358    }
359
360  pwin = (struct _Window*) pWin;
361
362  if (pwin->optional)
363    prop = (struct _Property *) pwin->optional->userProps;
364  else
365    prop = NULL;
366
367  while (prop)
368    {
369      if (prop->propertyName == AtmWindowsWMMouseActivate ()
370	  && prop->type == XA_INTEGER
371	  && prop->format == 32)
372	{
373	  return *(int*)prop->data;
374	}
375      else
376	prop = prop->next;
377    }
378
379  if (pWin != pRoot)
380    {
381      return IsMouseActive (pRoot);
382    }
383  else
384    {
385#if CYGMULTIWINDOW_DEBUG
386      winDebug ("IsMouseActive - no prop use default value:%d\n",
387		MOUSE_ACTIVATE_DEFAULT);
388#endif
389      return MOUSE_ACTIVATE_DEFAULT;
390    }
391}
392
393
394/*
395 * winMWExtWMWindowProc - Window procedure
396 */
397
398LRESULT CALLBACK
399winMWExtWMWindowProc (HWND hwnd, UINT message,
400			    WPARAM wParam, LPARAM lParam)
401{
402  WindowPtr		pWin = NULL;
403  win32RootlessWindowPtr pRLWinPriv = NULL;
404  ScreenPtr		pScreen = NULL;
405  winPrivScreenPtr	pScreenPriv = NULL;
406  winScreenInfo		*pScreenInfo = NULL;
407  HWND			hwndScreen = NULL;
408  POINT			ptMouse;
409  static Bool		s_fTracking = FALSE;
410  HDC			hdcUpdate;
411  PAINTSTRUCT		ps;
412  LPWINDOWPOS		pWinPos = NULL;
413  RECT			rcClient;
414  winWMMessageRec	wmMsg;
415  Bool			fWMMsgInitialized = FALSE;
416
417  /* Check if the Windows window property for our X window pointer is valid */
418  if ((pRLWinPriv = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
419    {
420      pWin = pRLWinPriv->pFrame->win;
421      pScreen				= pWin->drawable.pScreen;
422      if (pScreen) pScreenPriv		= winGetScreenPriv(pScreen);
423      if (pScreenPriv) pScreenInfo	= pScreenPriv->pScreenInfo;
424      if (pScreenPriv) hwndScreen	= pScreenPriv->hwndScreen;
425
426      wmMsg.msg		= 0;
427      wmMsg.hwndWindow	= hwnd;
428      wmMsg.iWindow	= (Window)pWin->drawable.id;
429
430      wmMsg.iX		= pRLWinPriv->pFrame->x;
431      wmMsg.iY		= pRLWinPriv->pFrame->y;
432      wmMsg.iWidth	= pRLWinPriv->pFrame->width;
433      wmMsg.iHeight	= pRLWinPriv->pFrame->height;
434
435      fWMMsgInitialized = TRUE;
436#if CYGDEBUG
437      winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam, lParam);
438
439      winDebug ("\thWnd %08X\n", hwnd);
440      winDebug ("\tpScreenPriv %08X\n", pScreenPriv);
441      winDebug ("\tpScreenInfo %08X\n", pScreenInfo);
442      winDebug ("\thwndScreen %08X\n", hwndScreen);
443      winDebug ("winMWExtWMWindowProc (%08x) %08x %08x %08x\n",
444	      pRLWinPriv, message, wParam, lParam);
445#endif
446    }
447  /* Branch on message type */
448  switch (message)
449    {
450    case WM_CREATE:
451#if CYGMULTIWINDOW_DEBUG
452      winDebug ("winMWExtWMWindowProc - WM_CREATE\n");
453#endif
454      /* */
455      SetProp (hwnd,
456	       WIN_WINDOW_PROP,
457	       (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams);
458      return 0;
459
460    case WM_CLOSE:
461#if CYGMULTIWINDOW_DEBUG
462      winDebug ("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose);
463#endif
464      /* Tell window-manager to close window */
465      if (pRLWinPriv->fClose)
466	{
467	  DestroyWindow (hwnd);
468	}
469      else
470	{
471	  if (winIsInternalWMRunning(pScreenInfo))
472	    {
473	      /* Tell our Window Manager thread to kill the window */
474	      wmMsg.msg = WM_WM_KILL;
475	      if (fWMMsgInitialized)
476		winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
477	    }
478	  winWindowsWMSendEvent(WindowsWMControllerNotify,
479				WindowsWMControllerNotifyMask,
480				1,
481				WindowsWMCloseWindow,
482				pWin->drawable.id,
483				0, 0, 0, 0);
484	}
485      return 0;
486
487    case WM_DESTROY:
488#if CYGMULTIWINDOW_DEBUG
489      winDebug ("winMWExtWMWindowProc - WM_DESTROY\n");
490#endif
491      /* Free the shaodw DC; which allows the bitmap to be freed */
492      DeleteDC (pRLWinPriv->hdcShadow);
493      pRLWinPriv->hdcShadow = NULL;
494
495      /* Free the shadow bitmap */
496      DeleteObject (pRLWinPriv->hbmpShadow);
497      pRLWinPriv->hbmpShadow = NULL;
498
499      /* Free the screen DC */
500      ReleaseDC (pRLWinPriv->hWnd, pRLWinPriv->hdcScreen);
501      pRLWinPriv->hdcScreen = NULL;
502
503      /* Free shadow buffer info header */
504      free (pRLWinPriv->pbmihShadow);
505      pRLWinPriv->pbmihShadow = NULL;
506
507      pRLWinPriv->fResized = FALSE;
508      pRLWinPriv->pfb = NULL;
509      free (pRLWinPriv);
510      RemoveProp (hwnd, WIN_WINDOW_PROP);
511      break;
512
513    case WM_MOUSEMOVE:
514#if CYGMULTIWINDOW_DEBUG && 0
515      winDebug ("winMWExtWMWindowProc - WM_MOUSEMOVE\n");
516#endif
517      /* Unpack the client area mouse coordinates */
518      ptMouse.x = GET_X_LPARAM(lParam);
519      ptMouse.y = GET_Y_LPARAM(lParam);
520
521      /* Translate the client area mouse coordinates to screen coordinates */
522      ClientToScreen (hwnd, &ptMouse);
523
524      /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
525      ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
526      ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
527
528      /* We can't do anything without privates */
529      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
530	break;
531
532      /* Has the mouse pointer crossed screens? */
533      if (pScreen != miPointerGetScreen(inputInfo.pointer))
534	miPointerSetScreen (inputInfo.pointer, pScreenInfo->dwScreen,
535			       ptMouse.x - pScreenInfo->dwXOffset,
536			       ptMouse.y - pScreenInfo->dwYOffset);
537
538      /* Are we tracking yet? */
539      if (!s_fTracking)
540	{
541	  TRACKMOUSEEVENT		tme;
542
543	  /* Setup data structure */
544	  ZeroMemory (&tme, sizeof (tme));
545	  tme.cbSize = sizeof (tme);
546	  tme.dwFlags = TME_LEAVE;
547	  tme.hwndTrack = hwnd;
548
549	  /* Call the tracking function */
550	  if (!(*g_fpTrackMouseEvent) (&tme))
551	    ErrorF ("winMWExtWMWindowProc - _TrackMouseEvent failed\n");
552
553	  /* Flag that we are tracking now */
554	  s_fTracking = TRUE;
555	}
556
557      /* Kill the timer used to poll mouse events */
558      if (g_uipMousePollingTimerID != 0)
559	{
560	  KillTimer (pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
561	  g_uipMousePollingTimerID = 0;
562	}
563
564      /* Deliver absolute cursor position to X Server */
565      winEnqueueMotion(ptMouse.x - pScreenInfo->dwXOffset,
566		       ptMouse.y - pScreenInfo->dwYOffset);
567
568      return 0;
569
570    case WM_NCMOUSEMOVE:
571#if CYGMULTIWINDOW_DEBUG && 0
572      winDebug ("winMWExtWMWindowProc - WM_NCMOUSEMOVE\n");
573#endif
574      /*
575       * We break instead of returning 0 since we need to call
576       * DefWindowProc to get the mouse cursor changes
577       * and min/max/close button highlighting in Windows XP.
578       * The Platform SDK says that you should return 0 if you
579       * process this message, but it fails to mention that you
580       * will give up any default functionality if you do return 0.
581       */
582
583      /* We can't do anything without privates */
584      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
585	break;
586
587      /*
588       * Timer to poll mouse events.  This is needed to make
589       * programs like xeyes follow the mouse properly.
590       */
591      if (g_uipMousePollingTimerID == 0)
592	g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen,
593					     WIN_POLLING_MOUSE_TIMER_ID,
594					     MOUSE_POLLING_INTERVAL,
595					     NULL);
596      break;
597
598    case WM_MOUSELEAVE:
599#if CYGMULTIWINDOW_DEBUG
600      winDebug ("winMWExtWMWindowProc - WM_MOUSELEAVE\n");
601#endif
602      /* Mouse has left our client area */
603
604      /* Flag that we are no longer tracking */
605      s_fTracking = FALSE;
606
607      /*
608       * Timer to poll mouse events.  This is needed to make
609       * programs like xeyes follow the mouse properly.
610       */
611      if (g_uipMousePollingTimerID == 0)
612	g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen,
613					     WIN_POLLING_MOUSE_TIMER_ID,
614					     MOUSE_POLLING_INTERVAL,
615					     NULL);
616      return 0;
617
618    case WM_LBUTTONDBLCLK:
619    case WM_LBUTTONDOWN:
620#if CYGMULTIWINDOW_DEBUG
621      winDebug ("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n");
622#endif
623      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
624	break;
625      SetCapture (hwnd);
626      return winMouseButtonsHandle (pScreen, ButtonPress, Button1, wParam);
627
628    case WM_LBUTTONUP:
629#if CYGMULTIWINDOW_DEBUG
630      winDebug ("winMWExtWMWindowProc - WM_LBUTTONUP\n");
631#endif
632      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
633	break;
634      ReleaseCapture ();
635      return winMouseButtonsHandle (pScreen, ButtonRelease, Button1, wParam);
636
637    case WM_MBUTTONDBLCLK:
638    case WM_MBUTTONDOWN:
639#if CYGMULTIWINDOW_DEBUG
640      winDebug ("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n");
641#endif
642      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
643	break;
644      SetCapture (hwnd);
645      return winMouseButtonsHandle (pScreen, ButtonPress, Button2, wParam);
646
647    case WM_MBUTTONUP:
648#if CYGMULTIWINDOW_DEBUG
649      winDebug ("winMWExtWMWindowProc - WM_MBUTTONUP\n");
650#endif
651      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
652	break;
653      ReleaseCapture ();
654      return winMouseButtonsHandle (pScreen, ButtonRelease, Button2, wParam);
655
656    case WM_RBUTTONDBLCLK:
657    case WM_RBUTTONDOWN:
658#if CYGMULTIWINDOW_DEBUG
659      winDebug ("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n");
660#endif
661      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
662	break;
663      SetCapture (hwnd);
664      return winMouseButtonsHandle (pScreen, ButtonPress, Button3, wParam);
665
666    case WM_RBUTTONUP:
667#if CYGMULTIWINDOW_DEBUG
668      winDebug ("winMWExtWMWindowProc - WM_RBUTTONUP\n");
669#endif
670      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
671	break;
672      ReleaseCapture ();
673      return winMouseButtonsHandle (pScreen, ButtonRelease, Button3, wParam);
674
675    case WM_XBUTTONDBLCLK:
676    case WM_XBUTTONDOWN:
677      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
678	break;
679      SetCapture (hwnd);
680      return winMouseButtonsHandle (pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
681    case WM_XBUTTONUP:
682      if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
683	break;
684      ReleaseCapture ();
685      return winMouseButtonsHandle (pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
686
687    case WM_MOUSEWHEEL:
688#if CYGMULTIWINDOW_DEBUG
689      winDebug ("winMWExtWMWindowProc - WM_MOUSEWHEEL\n");
690#endif
691
692      /* Pass the message to the root window */
693      SendMessage (hwndScreen, message, wParam, lParam);
694      return 0;
695
696    case WM_MOUSEACTIVATE:
697#if CYGMULTIWINDOW_DEBUG
698      winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n");
699#endif
700#if 1
701      /* Check if this window needs to be made active when clicked */
702      if (winIsInternalWMRunning(pScreenInfo) && pWin->overrideRedirect)
703	{
704#if CYGMULTIWINDOW_DEBUG
705	  winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE - "
706		    "MA_NOACTIVATE\n");
707#endif
708
709	  /* */
710	  return MA_NOACTIVATE;
711	}
712#endif
713      if (!winIsInternalWMRunning(pScreenInfo) && !IsMouseActive (pWin))
714	return MA_NOACTIVATE;
715
716      break;
717
718    case WM_KILLFOCUS:
719      /* Pop any pressed keys since we are losing keyboard focus */
720      winKeybdReleaseKeys ();
721      return 0;
722
723    case WM_SYSDEADCHAR:
724    case WM_DEADCHAR:
725      /*
726       * NOTE: We do nothing with WM_*CHAR messages,
727       * nor does the root window, so we can just toss these messages.
728       */
729      return 0;
730
731    case WM_SYSKEYDOWN:
732    case WM_KEYDOWN:
733#if CYGMULTIWINDOW_DEBUG
734      winDebug ("winMWExtWMWindowProc - WM_*KEYDOWN\n");
735#endif
736
737      /*
738       * Don't pass Alt-F4 key combo to root window,
739       * let Windows translate to WM_CLOSE and close this top-level window.
740       *
741       * NOTE: We purposely don't check the fUseWinKillKey setting because
742       * it should only apply to the key handling for the root window,
743       * not for top-level window-manager windows.
744       *
745       * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
746       * because that is a key combo that no X app should be expecting to
747       * receive, since it has historically been used to shutdown the X server.
748       * Passing Ctrl-Alt-Backspace to the root window preserves that
749       * behavior, assuming that -unixkill has been passed as a parameter.
750       */
751      if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000))
752	  break;
753
754      /* Pass the message to the root window */
755      SendMessage (hwndScreen, message, wParam, lParam);
756      return 0;
757
758    case WM_SYSKEYUP:
759    case WM_KEYUP:
760
761#if CYGMULTIWINDOW_DEBUG
762      winDebug ("winMWExtWMWindowProc - WM_*KEYUP\n");
763#endif
764
765      /* Pass the message to the root window */
766      SendMessage (hwndScreen, message, wParam, lParam);
767      return 0;
768
769    case WM_HOTKEY:
770#if CYGMULTIWINDOW_DEBUG
771      winDebug ("winMWExtWMWindowProc - WM_HOTKEY\n");
772#endif
773
774      /* Pass the message to the root window */
775      SendMessage (hwndScreen, message, wParam, lParam);
776      return 0;
777
778    case WM_ERASEBKGND:
779#if CYGDEBUG
780      winDebug ("winMWExtWMWindowProc - WM_ERASEBKGND\n");
781#endif
782      /*
783       * Pretend that we did erase the background but we don't care,
784       * since we repaint the entire region anyhow
785       * This avoids some flickering when resizing.
786       */
787      return TRUE;
788
789    case WM_PAINT:
790
791      /* BeginPaint gives us an hdc that clips to the invalidated region */
792      hdcUpdate = BeginPaint (hwnd, &ps);
793
794      /* Try to copy from the shadow buffer */
795      if (!BitBlt (hdcUpdate,
796		   ps.rcPaint.left, ps.rcPaint.top,
797		   ps.rcPaint.right - ps.rcPaint.left,
798		   ps.rcPaint.bottom - ps.rcPaint.top,
799		   pRLWinPriv->hdcShadow,
800		   ps.rcPaint.left, ps.rcPaint.top,
801		   SRCCOPY))
802	{
803	  LPVOID lpMsgBuf;
804
805	  /* Display a fancy error message */
806	  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
807			 FORMAT_MESSAGE_FROM_SYSTEM |
808			 FORMAT_MESSAGE_IGNORE_INSERTS,
809			 NULL,
810			 GetLastError (),
811			 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
812			 (LPTSTR) &lpMsgBuf,
813			 0, NULL);
814
815	  ErrorF ("winMWExtWMWindowProc - BitBlt failed: %s\n",
816		  (LPSTR)lpMsgBuf);
817	  LocalFree (lpMsgBuf);
818	}
819
820      /* EndPaint frees the DC */
821      EndPaint (hwnd, &ps);
822      break;
823
824    case WM_ACTIVATE:
825#if CYGMULTIWINDOW_DEBUG
826      winDebug ("winMWExtWMWindowProc - WM_ACTIVATE\n");
827#endif
828      if (LOWORD(wParam) != WA_INACTIVE)
829	{
830	  if (winIsInternalWMRunning(pScreenInfo))
831	    {
832#if 0
833	      /* Raise the window to the top in Z order */
834	      wmMsg.msg = WM_WM_RAISE;
835	      if (fWMMsgInitialized)
836		winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
837#endif
838	      /* Tell our Window Manager thread to activate the window */
839	      wmMsg.msg = WM_WM_ACTIVATE;
840	      if (fWMMsgInitialized)
841		if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
842		  winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
843	    }
844	  winWindowsWMSendEvent(WindowsWMControllerNotify,
845				WindowsWMControllerNotifyMask,
846				1,
847				WindowsWMActivateWindow,
848				pWin->drawable.id,
849				0, 0,
850				0, 0);
851	}
852      return 0;
853
854#if 1
855    case WM_WINDOWPOSCHANGING:
856      pWinPos = (LPWINDOWPOS)lParam;
857      if (!(pWinPos->flags & SWP_NOZORDER))
858	{
859	  if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking)
860	    {
861#if CYGMULTIWINDOW_DEBUG
862	      winDebug ("Win %08x is now restacking.\n", (unsigned int)pRLWinPriv);
863#endif
864	      break;
865	    }
866
867	  if (winIsInternalWMRunning(pScreenInfo) || IsRaiseOnClick (pWin))
868	    {
869#if CYGMULTIWINDOW_DEBUG
870	      winDebug ("Win %08x has WINDOWSWM_RAISE_ON_CLICK.\n", (unsigned int)pRLWinPriv);
871#endif
872	      break;
873	    }
874
875#if CYGMULTIWINDOW_DEBUG
876	  winDebug ("Win %08x forbid to change z order (%08x).\n",
877		    (unsigned int)pRLWinPriv, (unsigned int)pWinPos->hwndInsertAfter);
878#endif
879	  pWinPos->flags |= SWP_NOZORDER;
880	}
881      break;
882#endif
883
884    case WM_MOVE:
885#if CYGMULTIWINDOW_DEBUG
886      winDebug ("winMWExtWMWindowProc - WM_MOVE - %d ms\n",
887		(unsigned int)GetTickCount ());
888#endif
889      if (g_fNoConfigureWindow) break;
890#if 0
891      /* Bail if Windows window is not actually moving */
892      if (pRLWinPriv->dwX == (short) LOWORD(lParam)
893	  && pRLWinPriv->dwY == (short) HIWORD(lParam))
894	break;
895
896      /* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */
897      {
898	WINDOWPLACEMENT windPlace;
899	windPlace.length = sizeof (WINDOWPLACEMENT);
900
901	/* Get current window placement */
902	GetWindowPlacement (hwnd, &windPlace);
903
904	/* Bail if maximizing */
905	if (windPlace.showCmd == SW_MAXIMIZE
906	    || windPlace.showCmd == SW_SHOWMAXIMIZED)
907	  break;
908      }
909#endif
910
911#if CYGMULTIWINDOW_DEBUG
912      winDebug ("\t(%d, %d)\n", (short) LOWORD(lParam), (short) HIWORD(lParam));
913#endif
914      if (!pRLWinPriv->fMovingOrSizing)
915	{
916	  if (winIsInternalWMRunning(pScreenInfo))
917	    winAdjustXWindow (pWin, hwnd);
918
919	  winMWExtWMMoveXWindow (pWin,
920				 (LOWORD(lParam) - wBorderWidth (pWin)
921				  - GetSystemMetrics (SM_XVIRTUALSCREEN)),
922				 (HIWORD(lParam) - wBorderWidth (pWin)
923				  - GetSystemMetrics (SM_YVIRTUALSCREEN)));
924	}
925      return 0;
926
927    case WM_SHOWWINDOW:
928#if CYGMULTIWINDOW_DEBUG || TRUE
929      winDebug ("winMWExtWMWindowProc - WM_SHOWWINDOW - %d ms\n",
930		(unsigned int)GetTickCount ());
931#endif
932      /* Bail out if the window is being hidden */
933      if (!wParam)
934	return 0;
935
936      if (!pScreenInfo->fInternalWM)//XXXX
937	return 0;
938
939      winMWExtWMUpdateWindowDecoration (pRLWinPriv, pScreenInfo);
940
941      if (winIsInternalWMRunning(pScreenInfo))
942	{
943#if CYGMULTIWINDOW_DEBUG || TRUE
944	  winDebug ("\tMapWindow\n");
945#endif
946	  /* Tell X to map the window */
947	   MapWindow (pWin, wClient(pWin));
948
949	  if (!pRLWinPriv->pFrame->win->overrideRedirect)
950	    /* Bring the Windows window to the foreground */
951	    SetForegroundWindow (hwnd);
952
953	  /* Setup the Window Manager message */
954	  wmMsg.msg = WM_WM_MAP;
955	  wmMsg.iWidth = pRLWinPriv->pFrame->width;
956	  wmMsg.iHeight = pRLWinPriv->pFrame->height;
957
958	  /* Tell our Window Manager thread to map the window */
959	  if (fWMMsgInitialized)
960	    winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
961	}
962      break;
963
964    case WM_SIZING:
965      /* Need to legalize the size according to WM_NORMAL_HINTS */
966      /* for applications like xterm */
967      return ValidateSizing (hwnd, pWin, wParam, lParam);
968
969    case WM_WINDOWPOSCHANGED:
970      {
971	pWinPos = (LPWINDOWPOS) lParam;
972#if CYGMULTIWINDOW_DEBUG
973        winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n");
974	winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
975	(pWinPos->flags & SWP_DRAWFRAME)?"SWP_DRAWFRAME ":"",
976	(pWinPos->flags & SWP_FRAMECHANGED)?"SWP_FRAMECHANGED ":"",
977	(pWinPos->flags & SWP_HIDEWINDOW)?"SWP_HIDEWINDOW ":"",
978	(pWinPos->flags & SWP_NOACTIVATE)?"SWP_NOACTIVATE ":"",
979	(pWinPos->flags & SWP_NOCOPYBITS)?"SWP_NOCOPYBITS ":"",
980	(pWinPos->flags & SWP_NOMOVE)?"SWP_NOMOVE ":"",
981	(pWinPos->flags & SWP_NOOWNERZORDER)?"SWP_NOOWNERZORDER ":"",
982	(pWinPos->flags & SWP_NOSIZE)?"SWP_NOSIZE ":"",
983	(pWinPos->flags & SWP_NOREDRAW)?"SWP_NOREDRAW ":"",
984	(pWinPos->flags & SWP_NOSENDCHANGING)?"SWP_NOSENDCHANGING ":"",
985	(pWinPos->flags & SWP_NOZORDER)?"SWP_NOZORDER ":"",
986	(pWinPos->flags & SWP_SHOWWINDOW)?"SWP_SHOWWINDOW ":"");
987	winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow?"Yes":"No"));
988	winDebug("\textend: (%d, %d, %d, %d)\n",
989            pWinPos->x, pWinPos->y, pWinPos->cx, pWinPos->cy);
990
991#endif
992	if (pWinPos->flags & SWP_HIDEWINDOW) break;
993
994	/* Reorder if window z order was changed */
995	if ((pScreenPriv != NULL)
996	    && !(pWinPos->flags & SWP_NOZORDER)
997	    && !(pWinPos->flags & SWP_SHOWWINDOW)
998	    && winIsInternalWMRunning(pScreenInfo))
999	  {
1000#if CYGMULTIWINDOW_DEBUG
1001	    winDebug ("\twindow z order was changed\n");
1002#endif
1003	    if (pWinPos->hwndInsertAfter == HWND_TOP
1004		||pWinPos->hwndInsertAfter == HWND_TOPMOST
1005		||pWinPos->hwndInsertAfter == HWND_NOTOPMOST)
1006	      {
1007#if CYGMULTIWINDOW_DEBUG
1008		winDebug ("\traise to top\n");
1009#endif
1010		/* Raise the window to the top in Z order */
1011		wmMsg.msg = WM_WM_RAISE;
1012		if (fWMMsgInitialized)
1013		  winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1014	      }
1015#if 1
1016	    else if (pWinPos->hwndInsertAfter == HWND_BOTTOM)
1017	      {
1018	      }
1019	    else
1020	      {
1021		/* Check if this window is top of X windows. */
1022		HWND hWndAbove = NULL;
1023		DWORD dwCurrentProcessID = GetCurrentProcessId ();
1024		DWORD dwWindowProcessID = 0;
1025
1026		for (hWndAbove = pWinPos->hwndInsertAfter;
1027		     hWndAbove != NULL;
1028		     hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV))
1029		  {
1030		    /* Ignore other XWin process's window */
1031		    GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID);
1032
1033		    if ((dwWindowProcessID == dwCurrentProcessID)
1034			&& GetProp (hWndAbove, WIN_WINDOW_PROP)
1035			&& !IsWindowVisible (hWndAbove)
1036			&& !IsIconic (hWndAbove) ) /* ignore minimized windows */
1037		      break;
1038		  }
1039		/* If this is top of X windows in Windows stack,
1040		   raise it in X stack. */
1041		if (hWndAbove == NULL)
1042		  {
1043#if CYGMULTIWINDOW_DEBUG
1044		    winDebug ("\traise to top\n");
1045#endif
1046		    /* Raise the window to the top in Z order */
1047		    wmMsg.msg = WM_WM_RAISE;
1048		    if (fWMMsgInitialized)
1049		      winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1050		  }
1051	      }
1052#endif
1053	  }
1054
1055	if (!(pWinPos->flags & SWP_NOSIZE)) {
1056	  if (IsIconic(hwnd)){
1057#if CYGMULTIWINDOW_DEBUG
1058	    winDebug ("\tIconic -> MINIMIZED\n");
1059#endif
1060	    if (winIsInternalWMRunning(pScreenInfo))
1061	      {
1062	      /* Raise the window to the top in Z order */
1063		wmMsg.msg = WM_WM_LOWER;
1064		if (fWMMsgInitialized)
1065		  winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1066	      }
1067	    winWindowsWMSendEvent(WindowsWMControllerNotify,
1068				  WindowsWMControllerNotifyMask,
1069				  1,
1070				  WindowsWMMinimizeWindow,
1071				  pWin->drawable.id,
1072				  0, 0, 0, 0);
1073	  } else if (IsZoomed(hwnd)){
1074#if CYGMULTIWINDOW_DEBUG
1075	    winDebug ("\tZoomed -> MAXIMIZED\n");
1076#endif
1077	    winWindowsWMSendEvent(WindowsWMControllerNotify,
1078				  WindowsWMControllerNotifyMask,
1079				  1,
1080				  WindowsWMMaximizeWindow,
1081				  pWin->drawable.id,
1082				  0, 0, 0, 0);
1083	  } else {
1084#if CYGMULTIWINDOW_DEBUG
1085	    winDebug ("\tnone -> RESTORED\n");
1086#endif
1087	    winWindowsWMSendEvent(WindowsWMControllerNotify,
1088				  WindowsWMControllerNotifyMask,
1089				  1,
1090				  WindowsWMRestoreWindow,
1091				  pWin->drawable.id,
1092				  0, 0, 0, 0);
1093	  }
1094	}
1095	if (!g_fNoConfigureWindow ) {
1096
1097	  if (!pRLWinPriv->fMovingOrSizing
1098	      /*&& (pWinPos->flags & SWP_SHOWWINDOW)*/) {
1099	    GetClientRect (hwnd, &rcClient);
1100	    MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2);
1101
1102	    if (!(pWinPos->flags & SWP_NOMOVE)
1103		&&!(pWinPos->flags & SWP_NOSIZE)) {
1104#if CYGMULTIWINDOW_DEBUG
1105	      winDebug ("\tmove & resize\n");
1106#endif
1107	      if (winIsInternalWMRunning(pScreenInfo))
1108                winAdjustXWindow (pWin, hwnd);
1109
1110	      winMWExtWMMoveResizeXWindow (pWin,
1111					   rcClient.left - wBorderWidth (pWin)
1112					   - GetSystemMetrics (SM_XVIRTUALSCREEN),
1113					   rcClient.top - wBorderWidth (pWin)
1114					   - GetSystemMetrics (SM_YVIRTUALSCREEN),
1115					   rcClient.right - rcClient.left
1116					   - wBorderWidth (pWin)*2,
1117					   rcClient.bottom - rcClient.top
1118					   - wBorderWidth (pWin)*2);
1119	    } else if (!(pWinPos->flags & SWP_NOMOVE)) {
1120#if CYGMULTIWINDOW_DEBUG
1121	      winDebug ("\tmove\n");
1122#endif
1123	      if (winIsInternalWMRunning(pScreenInfo))
1124                winAdjustXWindow (pWin, hwnd);
1125
1126	      winMWExtWMMoveResizeXWindow (pWin,
1127					   rcClient.left - wBorderWidth (pWin)
1128					   - GetSystemMetrics (SM_XVIRTUALSCREEN),
1129					   rcClient.top - wBorderWidth (pWin)
1130					   - GetSystemMetrics (SM_YVIRTUALSCREEN),
1131					   rcClient.right - rcClient.left
1132					   - wBorderWidth (pWin)*2,
1133					   rcClient.bottom - rcClient.top
1134					   - wBorderWidth (pWin)*2);
1135	    } else if (!(pWinPos->flags & SWP_NOMOVE)) {
1136#if CYGMULTIWINDOW_DEBUG
1137	      winDebug ("\tmove\n");
1138#endif
1139	      if (winIsInternalWMRunning(pScreenInfo))
1140                winAdjustXWindow (pWin, hwnd);
1141
1142	      winMWExtWMMoveXWindow (pWin,
1143				     rcClient.left - wBorderWidth (pWin)
1144				     - GetSystemMetrics (SM_XVIRTUALSCREEN),
1145				     rcClient.top - wBorderWidth (pWin)
1146				     - GetSystemMetrics (SM_YVIRTUALSCREEN));
1147	    } else if (!(pWinPos->flags & SWP_NOSIZE)) {
1148#if CYGMULTIWINDOW_DEBUG
1149	      winDebug ("\tresize\n");
1150#endif
1151	      if (winIsInternalWMRunning(pScreenInfo))
1152                winAdjustXWindow (pWin, hwnd);
1153
1154	      winMWExtWMResizeXWindow (pWin,
1155				       rcClient.right - rcClient.left
1156				       - wBorderWidth (pWin)*2,
1157				       rcClient.bottom - rcClient.top
1158				       - wBorderWidth (pWin)*2);
1159	    }
1160	  }
1161	}
1162      }
1163#if CYGMULTIWINDOW_DEBUG
1164      winDebug ("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n");
1165#endif
1166      return 0;
1167
1168    case WM_SIZE:
1169      /* see dix/window.c */
1170      /* FIXME: Maximize/Restore? */
1171#if CYGMULTIWINDOW_DEBUG
1172      winDebug ("winMWExtWMWindowProc - WM_SIZE - %d ms\n",
1173		(unsigned int)GetTickCount ());
1174#endif
1175#if CYGMULTIWINDOW_DEBUG
1176      winDebug ("\t(%d, %d) %d\n", (short) LOWORD(lParam), (short) HIWORD(lParam), g_fNoConfigureWindow);
1177#endif
1178      if (g_fNoConfigureWindow) break;
1179
1180      /* Branch on type of resizing occurring */
1181      switch (wParam)
1182	{
1183	case SIZE_MINIMIZED:
1184#if CYGMULTIWINDOW_DEBUG
1185	  winDebug ("\tSIZE_MINIMIZED\n");
1186#endif
1187	  if (winIsInternalWMRunning(pScreenInfo))
1188	    {
1189	      /* Raise the window to the top in Z order */
1190	      wmMsg.msg = WM_WM_LOWER;
1191	      if (fWMMsgInitialized)
1192		winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1193	    }
1194	  winWindowsWMSendEvent(WindowsWMControllerNotify,
1195				WindowsWMControllerNotifyMask,
1196				1,
1197				WindowsWMMinimizeWindow,
1198				pWin->drawable.id,
1199				0, 0,
1200				LOWORD(lParam), HIWORD(lParam));
1201	  break;
1202
1203	case SIZE_RESTORED:
1204#if CYGMULTIWINDOW_DEBUG
1205	  winDebug ("\tSIZE_RESTORED\n");
1206#endif
1207	  winWindowsWMSendEvent(WindowsWMControllerNotify,
1208				WindowsWMControllerNotifyMask,
1209				1,
1210				WindowsWMRestoreWindow,
1211				pWin->drawable.id,
1212				0, 0,
1213				LOWORD(lParam), HIWORD(lParam));
1214	  break;
1215
1216	case SIZE_MAXIMIZED:
1217#if CYGMULTIWINDOW_DEBUG
1218	  winDebug ("\tSIZE_MAXIMIZED\n");
1219#endif
1220	  winWindowsWMSendEvent(WindowsWMControllerNotify,
1221				WindowsWMControllerNotifyMask,
1222				1,
1223				WindowsWMMaximizeWindow,
1224				pWin->drawable.id,
1225				0, 0,
1226				LOWORD(lParam), HIWORD(lParam));
1227	  break;
1228	}
1229
1230      /* Perform the resize and notify the X client */
1231      if (!pRLWinPriv->fMovingOrSizing)
1232	{
1233	  if (winIsInternalWMRunning(pScreenInfo))
1234            winAdjustXWindow (pWin, hwnd);
1235
1236	  winMWExtWMResizeXWindow (pWin,
1237				   (short) LOWORD(lParam)
1238				   - wBorderWidth (pWin)*2,
1239				   (short) HIWORD(lParam)
1240				   - wBorderWidth (pWin)*2);
1241	}
1242      break;
1243
1244    case WM_ACTIVATEAPP:
1245#if CYGMULTIWINDOW_DEBUG
1246      winDebug ("winMWExtWMWindowProc - WM_ACTIVATEAPP - %d ms\n",
1247		(unsigned int)GetTickCount ());
1248#endif
1249      if (wParam)
1250	{
1251	  if (winIsInternalWMRunning(pScreenInfo))
1252	    {
1253	    }
1254	  else
1255	    {
1256	    }
1257	  winWindowsWMSendEvent(WindowsWMActivationNotify,
1258				WindowsWMActivationNotifyMask,
1259				1,
1260				WindowsWMIsActive,
1261				pWin->drawable.id,
1262				0, 0,
1263				0, 0);
1264	}
1265      else
1266	{
1267	  winWindowsWMSendEvent(WindowsWMActivationNotify,
1268				WindowsWMActivationNotifyMask,
1269				1,
1270				WindowsWMIsInactive,
1271				pWin->drawable.id,
1272				0, 0,
1273				0, 0);
1274	}
1275      break;
1276
1277    case WM_SETCURSOR:
1278      if (LOWORD(lParam) == HTCLIENT)
1279	{
1280	  if (!g_fSoftwareCursor) SetCursor (pScreenPriv->cursor.handle);
1281	  return TRUE;
1282	}
1283      break;
1284
1285    case WM_ENTERSIZEMOVE:
1286#if CYGMULTIWINDOW_DEBUG
1287      winDebug ("winMWExtWMWindowProc - WM_ENTERSIZEMOVE - %d ms\n",
1288		(unsigned int)GetTickCount ());
1289#endif
1290      pRLWinPriv->fMovingOrSizing = TRUE;
1291      break;
1292
1293    case WM_EXITSIZEMOVE:
1294#if CYGMULTIWINDOW_DEBUG
1295      winDebug ("winMWExtWMWindowProc - WM_EXITSIZEMOVE - %d ms\n",
1296		(unsigned int)GetTickCount ());
1297#endif
1298      pRLWinPriv->fMovingOrSizing = FALSE;
1299
1300      GetClientRect (hwnd, &rcClient);
1301
1302      MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2);
1303
1304      if (winIsInternalWMRunning(pScreenInfo))
1305        winAdjustXWindow (pWin, hwnd);
1306
1307      winMWExtWMMoveResizeXWindow (pWin,
1308				   rcClient.left - wBorderWidth (pWin)
1309				   - GetSystemMetrics (SM_XVIRTUALSCREEN),
1310				   rcClient.top - wBorderWidth (pWin)
1311				   - GetSystemMetrics (SM_YVIRTUALSCREEN),
1312				   rcClient.right - rcClient.left
1313				   - wBorderWidth (pWin)*2,
1314				   rcClient.bottom - rcClient.top
1315				   - wBorderWidth (pWin)*2);
1316      break;
1317
1318    case WM_MANAGE:
1319      ErrorF ("winMWExtWMWindowProc - WM_MANAGE\n");
1320      break;
1321
1322    case WM_UNMANAGE:
1323      ErrorF ("winMWExtWMWindowProc - WM_UNMANAGE\n");
1324      break;
1325
1326    default:
1327      break;
1328    }
1329
1330  return DefWindowProc (hwnd, message, wParam, lParam);
1331}
1332