1706f2543Smrg/*
2706f2543Smrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3706f2543Smrg *
4706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining
5706f2543Smrg * a copy of this software and associated documentation files (the
6706f2543Smrg *"Software"), to deal in the Software without restriction, including
7706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish,
8706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to
9706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to
10706f2543Smrg *the following conditions:
11706f2543Smrg *
12706f2543Smrg *The above copyright notice and this permission notice shall be
13706f2543Smrg *included in all copies or substantial portions of the Software.
14706f2543Smrg *
15706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22706f2543Smrg *
23706f2543Smrg *Except as contained in this notice, the name of the XFree86 Project
24706f2543Smrg *shall not be used in advertising or otherwise to promote the sale, use
25706f2543Smrg *or other dealings in this Software without prior written authorization
26706f2543Smrg *from the XFree86 Project.
27706f2543Smrg *
28706f2543Smrg * Authors:	Dakshinamurthy Karra
29706f2543Smrg *		Suhaib M Siddiqi
30706f2543Smrg *		Peter Busch
31706f2543Smrg *		Harold L Hunt II
32706f2543Smrg *		MATSUZAKI Kensuke
33706f2543Smrg */
34706f2543Smrg
35706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
36706f2543Smrg#include <xwin-config.h>
37706f2543Smrg#endif
38706f2543Smrg#include "win.h"
39706f2543Smrg#include <commctrl.h>
40706f2543Smrg#include "winprefs.h"
41706f2543Smrg#include "winconfig.h"
42706f2543Smrg#include "winmsg.h"
43706f2543Smrg#include "winmonitors.h"
44706f2543Smrg#include "inputstr.h"
45706f2543Smrg
46706f2543Smrg/*
47706f2543Smrg * Global variables
48706f2543Smrg */
49706f2543Smrg
50706f2543SmrgBool				g_fCursor = TRUE;
51706f2543SmrgBool				g_fButton[3] = { FALSE, FALSE, FALSE };
52706f2543Smrg
53706f2543Smrg
54706f2543Smrg/*
55706f2543Smrg * Called by winWakeupHandler
56706f2543Smrg * Processes current Windows message
57706f2543Smrg */
58706f2543Smrg
59706f2543SmrgLRESULT CALLBACK
60706f2543SmrgwinWindowProc (HWND hwnd, UINT message,
61706f2543Smrg	       WPARAM wParam, LPARAM lParam)
62706f2543Smrg{
63706f2543Smrg  static winPrivScreenPtr	s_pScreenPriv = NULL;
64706f2543Smrg  static winScreenInfo		*s_pScreenInfo = NULL;
65706f2543Smrg  static ScreenPtr		s_pScreen = NULL;
66706f2543Smrg  static HWND			s_hwndLastPrivates = NULL;
67706f2543Smrg  static HINSTANCE		s_hInstance;
68706f2543Smrg  static Bool			s_fTracking = FALSE;
69706f2543Smrg  static unsigned long		s_ulServerGeneration = 0;
70706f2543Smrg  static UINT			s_uTaskbarRestart = 0;
71706f2543Smrg  int				iScanCode;
72706f2543Smrg  int				i;
73706f2543Smrg
74706f2543Smrg#if CYGDEBUG
75706f2543Smrg  winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam);
76706f2543Smrg#endif
77706f2543Smrg
78706f2543Smrg  /* Watch for server regeneration */
79706f2543Smrg  if (g_ulServerGeneration != s_ulServerGeneration)
80706f2543Smrg    {
81706f2543Smrg      /* Store new server generation */
82706f2543Smrg      s_ulServerGeneration = g_ulServerGeneration;
83706f2543Smrg    }
84706f2543Smrg
85706f2543Smrg  /* Only retrieve new privates pointers if window handle is null or changed */
86706f2543Smrg  if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates)
87706f2543Smrg      && (s_pScreenPriv = GetProp (hwnd, WIN_SCR_PROP)) != NULL)
88706f2543Smrg    {
89706f2543Smrg#if CYGDEBUG
90706f2543Smrg      winDebug ("winWindowProc - Setting privates handle\n");
91706f2543Smrg#endif
92706f2543Smrg      s_pScreenInfo = s_pScreenPriv->pScreenInfo;
93706f2543Smrg      s_pScreen = s_pScreenInfo->pScreen;
94706f2543Smrg      s_hwndLastPrivates = hwnd;
95706f2543Smrg    }
96706f2543Smrg  else if (s_pScreenPriv == NULL)
97706f2543Smrg    {
98706f2543Smrg      /* For safety, handle case that should never happen */
99706f2543Smrg      s_pScreenInfo = NULL;
100706f2543Smrg      s_pScreen = NULL;
101706f2543Smrg      s_hwndLastPrivates = NULL;
102706f2543Smrg    }
103706f2543Smrg
104706f2543Smrg  /* Branch on message type */
105706f2543Smrg  switch (message)
106706f2543Smrg    {
107706f2543Smrg    case WM_TRAYICON:
108706f2543Smrg      return winHandleIconMessage (hwnd, message, wParam, lParam,
109706f2543Smrg				   s_pScreenPriv);
110706f2543Smrg
111706f2543Smrg    case WM_CREATE:
112706f2543Smrg#if CYGDEBUG
113706f2543Smrg      winDebug ("winWindowProc - WM_CREATE\n");
114706f2543Smrg#endif
115706f2543Smrg
116706f2543Smrg      /*
117706f2543Smrg       * Add a property to our display window that references
118706f2543Smrg       * this screens' privates.
119706f2543Smrg       *
120706f2543Smrg       * This allows the window procedure to refer to the
121706f2543Smrg       * appropriate window DC and shadow DC for the window that
122706f2543Smrg       * it is processing.  We use this to repaint exposed
123706f2543Smrg       * areas of our display window.
124706f2543Smrg       */
125706f2543Smrg      s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams;
126706f2543Smrg      s_hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
127706f2543Smrg      s_pScreenInfo = s_pScreenPriv->pScreenInfo;
128706f2543Smrg      s_pScreen = s_pScreenInfo->pScreen;
129706f2543Smrg      s_hwndLastPrivates = hwnd;
130706f2543Smrg      s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
131706f2543Smrg      SetProp (hwnd, WIN_SCR_PROP, s_pScreenPriv);
132706f2543Smrg
133706f2543Smrg      /* Setup tray icon */
134706f2543Smrg      if (!s_pScreenInfo->fNoTrayIcon)
135706f2543Smrg	{
136706f2543Smrg	  /*
137706f2543Smrg	   * NOTE: The WM_CREATE message is processed before CreateWindowEx
138706f2543Smrg	   * returns, so s_pScreenPriv->hwndScreen is invalid at this point.
139706f2543Smrg	   * We go ahead and copy our hwnd parameter over top of the screen
140706f2543Smrg	   * privates hwndScreen so that we have a valid value for
141706f2543Smrg	   * that member.  Otherwise, the tray icon will disappear
142706f2543Smrg	   * the first time you move the mouse over top of it.
143706f2543Smrg	   */
144706f2543Smrg
145706f2543Smrg	  s_pScreenPriv->hwndScreen = hwnd;
146706f2543Smrg
147706f2543Smrg	  winInitNotifyIcon (s_pScreenPriv);
148706f2543Smrg	}
149706f2543Smrg      return 0;
150706f2543Smrg
151706f2543Smrg    case WM_DISPLAYCHANGE:
152706f2543Smrg      /*
153706f2543Smrg        WM_DISPLAYCHANGE seems to be sent when the monitor layout or
154706f2543Smrg        any monitor's resolution or depth changes, but it's lParam and
155706f2543Smrg        wParam always indicate the resolution and bpp for the primary
156706f2543Smrg        monitor (so ignore that as we could be on any monitor...)
157706f2543Smrg       */
158706f2543Smrg
159706f2543Smrg      /* We cannot handle a display mode change during initialization */
160706f2543Smrg      if (s_pScreenInfo == NULL)
161706f2543Smrg	FatalError ("winWindowProc - WM_DISPLAYCHANGE - The display "
162706f2543Smrg		    "mode changed while we were intializing.  This is "
163706f2543Smrg		    "very bad and unexpected.  Exiting.\n");
164706f2543Smrg
165706f2543Smrg      /*
166706f2543Smrg       * We do not care about display changes with
167706f2543Smrg       * fullscreen DirectDraw engines, because those engines set
168706f2543Smrg       * their own mode when they become active.
169706f2543Smrg       */
170706f2543Smrg      if (s_pScreenInfo->fFullScreen
171706f2543Smrg	  && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
172706f2543Smrg	      || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
173706f2543Smrg#ifdef XWIN_PRIMARYFB
174706f2543Smrg	      || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD
175706f2543Smrg#endif
176706f2543Smrg	      ))
177706f2543Smrg	{
178706f2543Smrg	  break;
179706f2543Smrg	}
180706f2543Smrg
181706f2543Smrg      ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
182706f2543Smrg	      "new height: %d new bpp: %d\n",
183706f2543Smrg	      LOWORD (lParam), HIWORD (lParam), wParam);
184706f2543Smrg
185706f2543Smrg      /*
186706f2543Smrg       * Check for a disruptive change in depth.
187706f2543Smrg       * We can only display a message for a disruptive depth change,
188706f2543Smrg       * we cannot do anything to correct the situation.
189706f2543Smrg       */
190706f2543Smrg      /*
191706f2543Smrg        XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT)
192706f2543Smrg        has changed as well...
193706f2543Smrg      */
194706f2543Smrg      if (s_pScreenInfo->dwBPP != GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL))
195706f2543Smrg        {
196706f2543Smrg          if ((s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
197706f2543Smrg               || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
198706f2543Smrg#ifdef XWIN_PRIMARYFB
199706f2543Smrg               || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD
200706f2543Smrg#endif
201706f2543Smrg               ))
202706f2543Smrg            {
203706f2543Smrg              /* Cannot display the visual until the depth is restored */
204706f2543Smrg              ErrorF ("winWindowProc - Disruptive change in depth\n");
205706f2543Smrg
206706f2543Smrg              /* Display depth change dialog */
207706f2543Smrg              winDisplayDepthChangeDialog (s_pScreenPriv);
208706f2543Smrg
209706f2543Smrg              /* Flag that we have an invalid screen depth */
210706f2543Smrg              s_pScreenPriv->fBadDepth = TRUE;
211706f2543Smrg
212706f2543Smrg              /* Minimize the display window */
213706f2543Smrg              ShowWindow (hwnd, SW_MINIMIZE);
214706f2543Smrg            }
215706f2543Smrg          else
216706f2543Smrg            {
217706f2543Smrg              /* For GDI, performance may suffer until original depth is restored */
218706f2543Smrg              ErrorF ("winWindowProc - Performance may be non-optimal after change in depth\n");
219706f2543Smrg            }
220706f2543Smrg        }
221706f2543Smrg      else
222706f2543Smrg        {
223706f2543Smrg          /* Flag that we have a valid screen depth */
224706f2543Smrg          s_pScreenPriv->fBadDepth = FALSE;
225706f2543Smrg        }
226706f2543Smrg
227706f2543Smrg      /*
228706f2543Smrg        If we could cheaply check if this WM_DISPLAYCHANGE change
229706f2543Smrg        affects the monitor(s) which this X screen is displayed on
230706f2543Smrg        then we should do so here.  For the moment, assume it does.
231706f2543Smrg        (this is probably usually the case so that might be an
232706f2543Smrg        overoptimization)
233706f2543Smrg      */
234706f2543Smrg	{
235706f2543Smrg	  /*
236706f2543Smrg             In rootless modes which are monitor or virtual desktop size
237706f2543Smrg             use RandR to resize the X screen
238706f2543Smrg          */
239706f2543Smrg          if ((!s_pScreenInfo->fUserGaveHeightAndWidth) &&
240706f2543Smrg              (s_pScreenInfo->iResizeMode == resizeWithRandr) &&
241706f2543Smrg              (FALSE
242706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
243706f2543Smrg               || s_pScreenInfo->fMWExtWM
244706f2543Smrg#endif
245706f2543Smrg               || s_pScreenInfo->fRootless
246706f2543Smrg#ifdef XWIN_MULTIWINDOW
247706f2543Smrg               || s_pScreenInfo->fMultiWindow
248706f2543Smrg#endif
249706f2543Smrg               ))
250706f2543Smrg	    {
251706f2543Smrg              DWORD dwWidth, dwHeight;
252706f2543Smrg
253706f2543Smrg              if (s_pScreenInfo->fMultipleMonitors)
254706f2543Smrg                {
255706f2543Smrg                  /* resize to new virtual desktop size */
256706f2543Smrg                  dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
257706f2543Smrg                  dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
258706f2543Smrg                }
259706f2543Smrg              else
260706f2543Smrg                {
261706f2543Smrg                  /* resize to new size of specified monitor */
262706f2543Smrg                  struct GetMonitorInfoData data;
263706f2543Smrg                  if (QueryMonitor(s_pScreenInfo->iMonitor, &data))
264706f2543Smrg                    {
265706f2543Smrg                      if (data.bMonitorSpecifiedExists == TRUE)
266706f2543Smrg                        {
267706f2543Smrg                          dwWidth = data.monitorWidth;
268706f2543Smrg                          dwHeight = data.monitorHeight;
269706f2543Smrg                          /*
270706f2543Smrg                             XXX: monitor may have changed position,
271706f2543Smrg                             so we might need to update xinerama data
272706f2543Smrg                          */
273706f2543Smrg                        }
274706f2543Smrg                      else
275706f2543Smrg                        {
276706f2543Smrg                          ErrorF ("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor);
277706f2543Smrg                        }
278706f2543Smrg                    }
279706f2543Smrg                }
280706f2543Smrg
281706f2543Smrg              /*
282706f2543Smrg                XXX: probably a small bug here: we don't compute the work area
283706f2543Smrg                and allow for task bar
284706f2543Smrg
285706f2543Smrg                XXX: generally, we don't allow for the task bar being moved after
286706f2543Smrg                the server is started
287706f2543Smrg               */
288706f2543Smrg
289706f2543Smrg              /* Set screen size to match new size, if it is different to current */
290706f2543Smrg              if ((s_pScreenInfo->dwWidth != dwWidth) ||
291706f2543Smrg                  (s_pScreenInfo->dwHeight != dwHeight))
292706f2543Smrg                {
293706f2543Smrg                  winDoRandRScreenSetSize(s_pScreen,
294706f2543Smrg                                          dwWidth,
295706f2543Smrg                                          dwHeight,
296706f2543Smrg                                          (dwWidth * 25.4) / monitorResolution,
297706f2543Smrg                                          (dwHeight * 25.4) / monitorResolution);
298706f2543Smrg                }
299706f2543Smrg	    }
300706f2543Smrg          else
301706f2543Smrg            {
302706f2543Smrg              /*
303706f2543Smrg               * We can simply recreate the same-sized primary surface when
304706f2543Smrg               * the display dimensions change.
305706f2543Smrg               */
306706f2543Smrg
307706f2543Smrg              /*
308706f2543Smrg               * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface
309706f2543Smrg               * and CreatePrimarySurface function pointers to point
310706f2543Smrg               * to the no operation function, NoopDDA.  This allows us
311706f2543Smrg               * to blindly call these functions, even if they are not
312706f2543Smrg               * relevant to the current engine (e.g., Shadow GDI).
313706f2543Smrg               */
314706f2543Smrg
315706f2543Smrg              winDebug ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
316706f2543Smrg
317706f2543Smrg              /* Release the old primary surface */
318706f2543Smrg              (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
319706f2543Smrg
320706f2543Smrg              /* Create the new primary surface */
321706f2543Smrg              (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
322706f2543Smrg            }
323706f2543Smrg	}
324706f2543Smrg
325706f2543Smrg      break;
326706f2543Smrg
327706f2543Smrg    case WM_SIZE:
328706f2543Smrg      {
329706f2543Smrg	SCROLLINFO		si;
330706f2543Smrg	RECT			rcWindow;
331706f2543Smrg	int			iWidth, iHeight;
332706f2543Smrg
333706f2543Smrg#if CYGDEBUG
334706f2543Smrg	winDebug ("winWindowProc - WM_SIZE\n");
335706f2543Smrg#endif
336706f2543Smrg
337706f2543Smrg	/* Break if we do not allow resizing */
338706f2543Smrg	if ((s_pScreenInfo->iResizeMode == notAllowed)
339706f2543Smrg	    || !s_pScreenInfo->fDecoration
340706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
341706f2543Smrg	    || s_pScreenInfo->fMWExtWM
342706f2543Smrg#endif
343706f2543Smrg	    || s_pScreenInfo->fRootless
344706f2543Smrg#ifdef XWIN_MULTIWINDOW
345706f2543Smrg	    || s_pScreenInfo->fMultiWindow
346706f2543Smrg#endif
347706f2543Smrg	    || s_pScreenInfo->fFullScreen)
348706f2543Smrg	  break;
349706f2543Smrg
350706f2543Smrg	/* No need to resize if we get minimized */
351706f2543Smrg	if (wParam == SIZE_MINIMIZED)
352706f2543Smrg	  return 0;
353706f2543Smrg
354706f2543Smrg        ErrorF ("winWindowProc - WM_SIZE - new client area w: %d h: %d\n",
355706f2543Smrg                LOWORD (lParam), HIWORD (lParam));
356706f2543Smrg
357706f2543Smrg        if (s_pScreenInfo->iResizeMode == resizeWithRandr)
358706f2543Smrg          {
359706f2543Smrg            /* Actual resizing is done on WM_EXITSIZEMOVE */
360706f2543Smrg            return 0;
361706f2543Smrg          }
362706f2543Smrg
363706f2543Smrg        /* Otherwise iResizeMode == resizeWithScrollbars */
364706f2543Smrg
365706f2543Smrg	/*
366706f2543Smrg	 * Get the size of the whole window, including client area,
367706f2543Smrg	 * scrollbars, and non-client area decorations (caption, borders).
368706f2543Smrg	 * We do this because we need to check if the client area
369706f2543Smrg	 * without scrollbars is large enough to display the whole visual.
370706f2543Smrg	 * The new client area size passed by lParam already subtracts
371706f2543Smrg	 * the size of the scrollbars if they are currently displayed.
372706f2543Smrg	 * So checking is LOWORD(lParam) == visual_width and
373706f2543Smrg	 * HIWORD(lParam) == visual_height will never tell us to hide
374706f2543Smrg	 * the scrollbars because the client area would always be too small.
375706f2543Smrg	 * GetClientRect returns the same sizes given by lParam, so we
376706f2543Smrg	 * cannot use GetClientRect either.
377706f2543Smrg	 */
378706f2543Smrg	GetWindowRect (hwnd, &rcWindow);
379706f2543Smrg	iWidth = rcWindow.right - rcWindow.left;
380706f2543Smrg	iHeight = rcWindow.bottom - rcWindow.top;
381706f2543Smrg
382706f2543Smrg	/* Subtract the frame size from the window size. */
383706f2543Smrg	iWidth -= 2 * GetSystemMetrics (SM_CXSIZEFRAME);
384706f2543Smrg	iHeight -= (2 * GetSystemMetrics (SM_CYSIZEFRAME)
385706f2543Smrg		    + GetSystemMetrics (SM_CYCAPTION));
386706f2543Smrg
387706f2543Smrg	/*
388706f2543Smrg	 * Update scrollbar page sizes.
389706f2543Smrg	 * NOTE: If page size == range, then the scrollbar is
390706f2543Smrg	 * automatically hidden.
391706f2543Smrg	 */
392706f2543Smrg
393706f2543Smrg	/* Is the naked client area large enough to show the whole visual? */
394706f2543Smrg	if (iWidth < s_pScreenInfo->dwWidth
395706f2543Smrg	    || iHeight < s_pScreenInfo->dwHeight)
396706f2543Smrg	  {
397706f2543Smrg	    /* Client area too small to display visual, use scrollbars */
398706f2543Smrg	    iWidth -= GetSystemMetrics (SM_CXVSCROLL);
399706f2543Smrg	    iHeight -= GetSystemMetrics (SM_CYHSCROLL);
400706f2543Smrg	  }
401706f2543Smrg
402706f2543Smrg	/* Set the horizontal scrollbar page size */
403706f2543Smrg	si.cbSize = sizeof (si);
404706f2543Smrg	si.fMask = SIF_PAGE | SIF_RANGE;
405706f2543Smrg	si.nMin = 0;
406706f2543Smrg	si.nMax = s_pScreenInfo->dwWidth - 1;
407706f2543Smrg	si.nPage = iWidth;
408706f2543Smrg	SetScrollInfo (hwnd, SB_HORZ, &si, TRUE);
409706f2543Smrg
410706f2543Smrg	/* Set the vertical scrollbar page size */
411706f2543Smrg	si.cbSize = sizeof (si);
412706f2543Smrg	si.fMask = SIF_PAGE | SIF_RANGE;
413706f2543Smrg	si.nMin = 0;
414706f2543Smrg	si.nMax = s_pScreenInfo->dwHeight - 1;
415706f2543Smrg	si.nPage = iHeight;
416706f2543Smrg	SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
417706f2543Smrg
418706f2543Smrg	/*
419706f2543Smrg	 * NOTE: Scrollbars may have moved if they were at the
420706f2543Smrg	 * far right/bottom, so we query their current position.
421706f2543Smrg	 */
422706f2543Smrg
423706f2543Smrg	/* Get the horizontal scrollbar position and set the offset */
424706f2543Smrg	si.cbSize = sizeof (si);
425706f2543Smrg	si.fMask = SIF_POS;
426706f2543Smrg	GetScrollInfo (hwnd, SB_HORZ, &si);
427706f2543Smrg	s_pScreenInfo->dwXOffset = -si.nPos;
428706f2543Smrg
429706f2543Smrg	/* Get the vertical scrollbar position and set the offset */
430706f2543Smrg	si.cbSize = sizeof (si);
431706f2543Smrg	si.fMask = SIF_POS;
432706f2543Smrg	GetScrollInfo (hwnd, SB_VERT, &si);
433706f2543Smrg	s_pScreenInfo->dwYOffset = -si.nPos;
434706f2543Smrg      }
435706f2543Smrg      return 0;
436706f2543Smrg
437706f2543Smrg    case WM_ENTERSIZEMOVE:
438706f2543Smrg      ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n");
439706f2543Smrg      break;
440706f2543Smrg
441706f2543Smrg    case WM_EXITSIZEMOVE:
442706f2543Smrg      ErrorF("winWindowProc - WM_EXITSIZEMOVE\n");
443706f2543Smrg
444706f2543Smrg      if (s_pScreenInfo->iResizeMode == resizeWithRandr)
445706f2543Smrg        {
446706f2543Smrg          /* Set screen size to match new client area, if it is different to current */
447706f2543Smrg          RECT rcClient;
448706f2543Smrg          DWORD dwWidth, dwHeight;
449706f2543Smrg
450706f2543Smrg          GetClientRect (hwnd, &rcClient);
451706f2543Smrg          dwWidth = rcClient.right - rcClient.left;
452706f2543Smrg          dwHeight = rcClient.bottom - rcClient.top;
453706f2543Smrg
454706f2543Smrg          if ((s_pScreenInfo->dwWidth != dwWidth) ||
455706f2543Smrg              (s_pScreenInfo->dwHeight != dwHeight))
456706f2543Smrg            {
457706f2543Smrg              /* mm = dots * (25.4 mm / inch) / (dots / inch) */
458706f2543Smrg              winDoRandRScreenSetSize(s_pScreen,
459706f2543Smrg                                      dwWidth,
460706f2543Smrg                                      dwHeight,
461706f2543Smrg                                      (dwWidth * 25.4) / monitorResolution,
462706f2543Smrg                                      (dwHeight * 25.4) / monitorResolution);
463706f2543Smrg            }
464706f2543Smrg        }
465706f2543Smrg
466706f2543Smrg      break;
467706f2543Smrg
468706f2543Smrg    case WM_VSCROLL:
469706f2543Smrg      {
470706f2543Smrg	SCROLLINFO		si;
471706f2543Smrg	int			iVertPos;
472706f2543Smrg
473706f2543Smrg#if CYGDEBUG
474706f2543Smrg	winDebug ("winWindowProc - WM_VSCROLL\n");
475706f2543Smrg#endif
476706f2543Smrg
477706f2543Smrg	/* Get vertical scroll bar info */
478706f2543Smrg	si.cbSize = sizeof (si);
479706f2543Smrg	si.fMask = SIF_ALL;
480706f2543Smrg	GetScrollInfo (hwnd, SB_VERT, &si);
481706f2543Smrg
482706f2543Smrg	/* Save the vertical position for comparison later */
483706f2543Smrg	iVertPos = si.nPos;
484706f2543Smrg
485706f2543Smrg	/*
486706f2543Smrg	 * Don't forget:
487706f2543Smrg	 * moving the scrollbar to the DOWN, scroll the content UP
488706f2543Smrg	 */
489706f2543Smrg	switch (LOWORD(wParam))
490706f2543Smrg	  {
491706f2543Smrg	  case SB_TOP:
492706f2543Smrg	    si.nPos = si.nMin;
493706f2543Smrg	    break;
494706f2543Smrg
495706f2543Smrg	  case SB_BOTTOM:
496706f2543Smrg	    si.nPos = si.nMax - si.nPage + 1;
497706f2543Smrg	    break;
498706f2543Smrg
499706f2543Smrg	  case SB_LINEUP:
500706f2543Smrg	    si.nPos -= 1;
501706f2543Smrg	    break;
502706f2543Smrg
503706f2543Smrg	  case SB_LINEDOWN:
504706f2543Smrg	    si.nPos += 1;
505706f2543Smrg	    break;
506706f2543Smrg
507706f2543Smrg	  case SB_PAGEUP:
508706f2543Smrg	    si.nPos -= si.nPage;
509706f2543Smrg	    break;
510706f2543Smrg
511706f2543Smrg	  case SB_PAGEDOWN:
512706f2543Smrg	    si.nPos += si.nPage;
513706f2543Smrg	    break;
514706f2543Smrg
515706f2543Smrg	  case SB_THUMBTRACK:
516706f2543Smrg	    si.nPos = si.nTrackPos;
517706f2543Smrg	    break;
518706f2543Smrg
519706f2543Smrg	  default:
520706f2543Smrg	    break;
521706f2543Smrg	  }
522706f2543Smrg
523706f2543Smrg	/*
524706f2543Smrg	 * We retrieve the position after setting it,
525706f2543Smrg	 * because Windows may adjust it.
526706f2543Smrg	 */
527706f2543Smrg	si.fMask = SIF_POS;
528706f2543Smrg	SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
529706f2543Smrg	GetScrollInfo (hwnd, SB_VERT, &si);
530706f2543Smrg
531706f2543Smrg	/* Scroll the window if the position has changed */
532706f2543Smrg	if (si.nPos != iVertPos)
533706f2543Smrg	  {
534706f2543Smrg	    /* Save the new offset for bit block transfers, etc. */
535706f2543Smrg	    s_pScreenInfo->dwYOffset = -si.nPos;
536706f2543Smrg
537706f2543Smrg	    /* Change displayed region in the window */
538706f2543Smrg	    ScrollWindowEx (hwnd,
539706f2543Smrg			    0,
540706f2543Smrg			    iVertPos - si.nPos,
541706f2543Smrg			    NULL,
542706f2543Smrg			    NULL,
543706f2543Smrg			    NULL,
544706f2543Smrg			    NULL,
545706f2543Smrg			    SW_INVALIDATE);
546706f2543Smrg
547706f2543Smrg	    /* Redraw the window contents */
548706f2543Smrg	    UpdateWindow (hwnd);
549706f2543Smrg	  }
550706f2543Smrg      }
551706f2543Smrg      return 0;
552706f2543Smrg
553706f2543Smrg    case WM_HSCROLL:
554706f2543Smrg      {
555706f2543Smrg	SCROLLINFO		si;
556706f2543Smrg	int			iHorzPos;
557706f2543Smrg
558706f2543Smrg#if CYGDEBUG
559706f2543Smrg	winDebug ("winWindowProc - WM_HSCROLL\n");
560706f2543Smrg#endif
561706f2543Smrg
562706f2543Smrg	/* Get horizontal scroll bar info */
563706f2543Smrg	si.cbSize = sizeof (si);
564706f2543Smrg	si.fMask = SIF_ALL;
565706f2543Smrg	GetScrollInfo (hwnd, SB_HORZ, &si);
566706f2543Smrg
567706f2543Smrg	/* Save the horizontal position for comparison later */
568706f2543Smrg	iHorzPos = si.nPos;
569706f2543Smrg
570706f2543Smrg	/*
571706f2543Smrg	 * Don't forget:
572706f2543Smrg	 * moving the scrollbar to the RIGHT, scroll the content LEFT
573706f2543Smrg	 */
574706f2543Smrg	switch (LOWORD(wParam))
575706f2543Smrg	  {
576706f2543Smrg	  case SB_LEFT:
577706f2543Smrg	    si.nPos = si.nMin;
578706f2543Smrg	    break;
579706f2543Smrg
580706f2543Smrg	  case SB_RIGHT:
581706f2543Smrg	    si.nPos = si.nMax - si.nPage + 1;
582706f2543Smrg	    break;
583706f2543Smrg
584706f2543Smrg	  case SB_LINELEFT:
585706f2543Smrg	    si.nPos -= 1;
586706f2543Smrg	    break;
587706f2543Smrg
588706f2543Smrg	  case SB_LINERIGHT:
589706f2543Smrg	    si.nPos += 1;
590706f2543Smrg	    break;
591706f2543Smrg
592706f2543Smrg	  case SB_PAGELEFT:
593706f2543Smrg	    si.nPos -= si.nPage;
594706f2543Smrg	    break;
595706f2543Smrg
596706f2543Smrg	  case SB_PAGERIGHT:
597706f2543Smrg	    si.nPos += si.nPage;
598706f2543Smrg	    break;
599706f2543Smrg
600706f2543Smrg	  case SB_THUMBTRACK:
601706f2543Smrg	    si.nPos = si.nTrackPos;
602706f2543Smrg	    break;
603706f2543Smrg
604706f2543Smrg	  default:
605706f2543Smrg	    break;
606706f2543Smrg	  }
607706f2543Smrg
608706f2543Smrg	/*
609706f2543Smrg	 * We retrieve the position after setting it,
610706f2543Smrg	 * because Windows may adjust it.
611706f2543Smrg	 */
612706f2543Smrg	si.fMask = SIF_POS;
613706f2543Smrg	SetScrollInfo (hwnd, SB_HORZ, &si, TRUE);
614706f2543Smrg	GetScrollInfo (hwnd, SB_HORZ, &si);
615706f2543Smrg
616706f2543Smrg	/* Scroll the window if the position has changed */
617706f2543Smrg	if (si.nPos != iHorzPos)
618706f2543Smrg	  {
619706f2543Smrg	    /* Save the new offset for bit block transfers, etc. */
620706f2543Smrg	    s_pScreenInfo->dwXOffset = -si.nPos;
621706f2543Smrg
622706f2543Smrg	    /* Change displayed region in the window */
623706f2543Smrg	    ScrollWindowEx (hwnd,
624706f2543Smrg			    iHorzPos - si.nPos,
625706f2543Smrg			    0,
626706f2543Smrg			    NULL,
627706f2543Smrg			    NULL,
628706f2543Smrg			    NULL,
629706f2543Smrg			    NULL,
630706f2543Smrg			    SW_INVALIDATE);
631706f2543Smrg
632706f2543Smrg	    /* Redraw the window contents */
633706f2543Smrg	    UpdateWindow (hwnd);
634706f2543Smrg	  }
635706f2543Smrg      }
636706f2543Smrg      return 0;
637706f2543Smrg
638706f2543Smrg    case WM_GETMINMAXINFO:
639706f2543Smrg      {
640706f2543Smrg	MINMAXINFO		*pMinMaxInfo = (MINMAXINFO *) lParam;
641706f2543Smrg	int			iCaptionHeight;
642706f2543Smrg	int			iBorderHeight, iBorderWidth;
643706f2543Smrg
644706f2543Smrg#if CYGDEBUG
645706f2543Smrg	winDebug ("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n",
646706f2543Smrg		s_pScreenInfo);
647706f2543Smrg#endif
648706f2543Smrg
649706f2543Smrg	/* Can't do anything without screen info */
650706f2543Smrg	if (s_pScreenInfo == NULL
651706f2543Smrg	    || (s_pScreenInfo->iResizeMode != resizeWithScrollbars)
652706f2543Smrg	    || s_pScreenInfo->fFullScreen
653706f2543Smrg	    || !s_pScreenInfo->fDecoration
654706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
655706f2543Smrg	    || s_pScreenInfo->fMWExtWM
656706f2543Smrg#endif
657706f2543Smrg	    || s_pScreenInfo->fRootless
658706f2543Smrg#ifdef XWIN_MULTIWINDOW
659706f2543Smrg	    || s_pScreenInfo->fMultiWindow
660706f2543Smrg#endif
661706f2543Smrg	    )
662706f2543Smrg	  break;
663706f2543Smrg
664706f2543Smrg	/*
665706f2543Smrg	 * Here we can override the maximum tracking size, which
666706f2543Smrg	 * is the largest size that can be assigned to our window
667706f2543Smrg	 * via the sizing border.
668706f2543Smrg	 */
669706f2543Smrg
670706f2543Smrg	/*
671706f2543Smrg	 * FIXME: Do we only need to do this once, since our visual size
672706f2543Smrg	 * does not change?  Does Windows store this value statically
673706f2543Smrg	 * once we have set it once?
674706f2543Smrg	 */
675706f2543Smrg
676706f2543Smrg	/* Get the border and caption sizes */
677706f2543Smrg	iCaptionHeight = GetSystemMetrics (SM_CYCAPTION);
678706f2543Smrg	iBorderWidth = 2 * GetSystemMetrics (SM_CXSIZEFRAME);
679706f2543Smrg	iBorderHeight = 2 * GetSystemMetrics (SM_CYSIZEFRAME);
680706f2543Smrg
681706f2543Smrg	/* Allow the full visual to be displayed */
682706f2543Smrg	pMinMaxInfo->ptMaxTrackSize.x
683706f2543Smrg	  = s_pScreenInfo->dwWidth + iBorderWidth;
684706f2543Smrg	pMinMaxInfo->ptMaxTrackSize.y
685706f2543Smrg	  = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight;
686706f2543Smrg      }
687706f2543Smrg      return 0;
688706f2543Smrg
689706f2543Smrg    case WM_ERASEBKGND:
690706f2543Smrg#if CYGDEBUG
691706f2543Smrg      winDebug ("winWindowProc - WM_ERASEBKGND\n");
692706f2543Smrg#endif
693706f2543Smrg      /*
694706f2543Smrg       * Pretend that we did erase the background but we don't care,
695706f2543Smrg       * the application uses the full window estate. This avoids some
696706f2543Smrg       * flickering when resizing.
697706f2543Smrg       */
698706f2543Smrg      return TRUE;
699706f2543Smrg
700706f2543Smrg    case WM_PAINT:
701706f2543Smrg#if CYGDEBUG
702706f2543Smrg      winDebug ("winWindowProc - WM_PAINT\n");
703706f2543Smrg#endif
704706f2543Smrg      /* Only paint if we have privates and the server is enabled */
705706f2543Smrg      if (s_pScreenPriv == NULL
706706f2543Smrg	  || !s_pScreenPriv->fEnabled
707706f2543Smrg	  || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive)
708706f2543Smrg	  || s_pScreenPriv->fBadDepth)
709706f2543Smrg	{
710706f2543Smrg	  /* We don't want to paint */
711706f2543Smrg	  break;
712706f2543Smrg	}
713706f2543Smrg
714706f2543Smrg      /* Break out here if we don't have a valid paint routine */
715706f2543Smrg      if (s_pScreenPriv->pwinBltExposedRegions == NULL)
716706f2543Smrg	break;
717706f2543Smrg
718706f2543Smrg      /* Call the engine dependent repainter */
719706f2543Smrg      (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen);
720706f2543Smrg      return 0;
721706f2543Smrg
722706f2543Smrg    case WM_PALETTECHANGED:
723706f2543Smrg      {
724706f2543Smrg#if CYGDEBUG
725706f2543Smrg	winDebug ("winWindowProc - WM_PALETTECHANGED\n");
726706f2543Smrg#endif
727706f2543Smrg	/*
728706f2543Smrg	 * Don't process if we don't have privates or a colormap,
729706f2543Smrg	 * or if we have an invalid depth.
730706f2543Smrg	 */
731706f2543Smrg	if (s_pScreenPriv == NULL
732706f2543Smrg	    || s_pScreenPriv->pcmapInstalled == NULL
733706f2543Smrg	    || s_pScreenPriv->fBadDepth)
734706f2543Smrg	  break;
735706f2543Smrg
736706f2543Smrg	/* Return if we caused the palette to change */
737706f2543Smrg	if ((HWND) wParam == hwnd)
738706f2543Smrg	  {
739706f2543Smrg	    /* Redraw the screen */
740706f2543Smrg	    (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
741706f2543Smrg	    return 0;
742706f2543Smrg	  }
743706f2543Smrg
744706f2543Smrg	/* Reinstall the windows palette */
745706f2543Smrg	(*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen);
746706f2543Smrg
747706f2543Smrg	/* Redraw the screen */
748706f2543Smrg	(*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
749706f2543Smrg	return 0;
750706f2543Smrg      }
751706f2543Smrg
752706f2543Smrg    case WM_MOUSEMOVE:
753706f2543Smrg      /* We can't do anything without privates */
754706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
755706f2543Smrg	break;
756706f2543Smrg
757706f2543Smrg      /* We can't do anything without g_pwinPointer */
758706f2543Smrg      if (g_pwinPointer == NULL)
759706f2543Smrg        break;
760706f2543Smrg
761706f2543Smrg      /* Has the mouse pointer crossed screens? */
762706f2543Smrg      if (s_pScreen != miPointerGetScreen(g_pwinPointer))
763706f2543Smrg	miPointerSetScreen (g_pwinPointer, s_pScreenInfo->dwScreen,
764706f2543Smrg			       GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset,
765706f2543Smrg			       GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset);
766706f2543Smrg
767706f2543Smrg      /* Are we tracking yet? */
768706f2543Smrg      if (!s_fTracking)
769706f2543Smrg	{
770706f2543Smrg	  TRACKMOUSEEVENT		tme;
771706f2543Smrg
772706f2543Smrg	  /* Setup data structure */
773706f2543Smrg	  ZeroMemory (&tme, sizeof (tme));
774706f2543Smrg	  tme.cbSize = sizeof (tme);
775706f2543Smrg	  tme.dwFlags = TME_LEAVE;
776706f2543Smrg	  tme.hwndTrack = hwnd;
777706f2543Smrg
778706f2543Smrg	  /* Call the tracking function */
779706f2543Smrg	  if (!(*g_fpTrackMouseEvent) (&tme))
780706f2543Smrg	    ErrorF ("winWindowProc - _TrackMouseEvent failed\n");
781706f2543Smrg
782706f2543Smrg	  /* Flag that we are tracking now */
783706f2543Smrg	  s_fTracking = TRUE;
784706f2543Smrg	}
785706f2543Smrg
786706f2543Smrg      /* Hide or show the Windows mouse cursor */
787706f2543Smrg      if (g_fSoftwareCursor && g_fCursor && (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer))
788706f2543Smrg	{
789706f2543Smrg	  /* Hide Windows cursor */
790706f2543Smrg	  g_fCursor = FALSE;
791706f2543Smrg	  ShowCursor (FALSE);
792706f2543Smrg	}
793706f2543Smrg      else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive
794706f2543Smrg	       && !s_pScreenInfo->fLessPointer)
795706f2543Smrg	{
796706f2543Smrg	  /* Show Windows cursor */
797706f2543Smrg	  g_fCursor = TRUE;
798706f2543Smrg	  ShowCursor (TRUE);
799706f2543Smrg	}
800706f2543Smrg
801706f2543Smrg      /* Deliver absolute cursor position to X Server */
802706f2543Smrg      winEnqueueMotion(GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset,
803706f2543Smrg		       GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset);
804706f2543Smrg      return 0;
805706f2543Smrg
806706f2543Smrg    case WM_NCMOUSEMOVE:
807706f2543Smrg      /*
808706f2543Smrg       * We break instead of returning 0 since we need to call
809706f2543Smrg       * DefWindowProc to get the mouse cursor changes
810706f2543Smrg       * and min/max/close button highlighting in Windows XP.
811706f2543Smrg       * The Platform SDK says that you should return 0 if you
812706f2543Smrg       * process this message, but it fails to mention that you
813706f2543Smrg       * will give up any default functionality if you do return 0.
814706f2543Smrg       */
815706f2543Smrg
816706f2543Smrg      /* We can't do anything without privates */
817706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
818706f2543Smrg	break;
819706f2543Smrg
820706f2543Smrg      /* Non-client mouse movement, show Windows cursor */
821706f2543Smrg      if (g_fSoftwareCursor && !g_fCursor)
822706f2543Smrg	{
823706f2543Smrg	  g_fCursor = TRUE;
824706f2543Smrg	  ShowCursor (TRUE);
825706f2543Smrg	}
826706f2543Smrg      break;
827706f2543Smrg
828706f2543Smrg    case WM_MOUSELEAVE:
829706f2543Smrg      /* Mouse has left our client area */
830706f2543Smrg
831706f2543Smrg      /* Flag that we are no longer tracking */
832706f2543Smrg      s_fTracking = FALSE;
833706f2543Smrg
834706f2543Smrg      /* Show the mouse cursor, if necessary */
835706f2543Smrg      if (g_fSoftwareCursor && !g_fCursor)
836706f2543Smrg	{
837706f2543Smrg	  g_fCursor = TRUE;
838706f2543Smrg	  ShowCursor (TRUE);
839706f2543Smrg	}
840706f2543Smrg      return 0;
841706f2543Smrg
842706f2543Smrg    case WM_LBUTTONDBLCLK:
843706f2543Smrg    case WM_LBUTTONDOWN:
844706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
845706f2543Smrg	break;
846706f2543Smrg      if (s_pScreenInfo->fRootless
847706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
848706f2543Smrg	  || s_pScreenInfo->fMWExtWM
849706f2543Smrg#endif
850706f2543Smrg	  )
851706f2543Smrg	SetCapture (hwnd);
852706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
853706f2543Smrg
854706f2543Smrg    case WM_LBUTTONUP:
855706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
856706f2543Smrg	break;
857706f2543Smrg      if (s_pScreenInfo->fRootless
858706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
859706f2543Smrg	  || s_pScreenInfo->fMWExtWM
860706f2543Smrg#endif
861706f2543Smrg	  )
862706f2543Smrg	ReleaseCapture ();
863706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
864706f2543Smrg
865706f2543Smrg    case WM_MBUTTONDBLCLK:
866706f2543Smrg    case WM_MBUTTONDOWN:
867706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
868706f2543Smrg	break;
869706f2543Smrg      if (s_pScreenInfo->fRootless
870706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
871706f2543Smrg	  || s_pScreenInfo->fMWExtWM
872706f2543Smrg#endif
873706f2543Smrg	  )
874706f2543Smrg	SetCapture (hwnd);
875706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
876706f2543Smrg
877706f2543Smrg    case WM_MBUTTONUP:
878706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
879706f2543Smrg	break;
880706f2543Smrg      if (s_pScreenInfo->fRootless
881706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
882706f2543Smrg	  || s_pScreenInfo->fMWExtWM
883706f2543Smrg#endif
884706f2543Smrg	  )
885706f2543Smrg	ReleaseCapture ();
886706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
887706f2543Smrg
888706f2543Smrg    case WM_RBUTTONDBLCLK:
889706f2543Smrg    case WM_RBUTTONDOWN:
890706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
891706f2543Smrg	break;
892706f2543Smrg      if (s_pScreenInfo->fRootless
893706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
894706f2543Smrg	  || s_pScreenInfo->fMWExtWM
895706f2543Smrg#endif
896706f2543Smrg	  )
897706f2543Smrg	SetCapture (hwnd);
898706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
899706f2543Smrg
900706f2543Smrg    case WM_RBUTTONUP:
901706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
902706f2543Smrg	break;
903706f2543Smrg      if (s_pScreenInfo->fRootless
904706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
905706f2543Smrg	  || s_pScreenInfo->fMWExtWM
906706f2543Smrg#endif
907706f2543Smrg	  )
908706f2543Smrg	ReleaseCapture ();
909706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
910706f2543Smrg
911706f2543Smrg    case WM_XBUTTONDBLCLK:
912706f2543Smrg    case WM_XBUTTONDOWN:
913706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
914706f2543Smrg	break;
915706f2543Smrg      if (s_pScreenInfo->fRootless
916706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
917706f2543Smrg	  || s_pScreenInfo->fMWExtWM
918706f2543Smrg#endif
919706f2543Smrg	  )
920706f2543Smrg	SetCapture (hwnd);
921706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
922706f2543Smrg    case WM_XBUTTONUP:
923706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
924706f2543Smrg	break;
925706f2543Smrg      if (s_pScreenInfo->fRootless
926706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
927706f2543Smrg	  || s_pScreenInfo->fMWExtWM
928706f2543Smrg#endif
929706f2543Smrg	  )
930706f2543Smrg	ReleaseCapture ();
931706f2543Smrg      return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
932706f2543Smrg
933706f2543Smrg    case WM_TIMER:
934706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
935706f2543Smrg	break;
936706f2543Smrg
937706f2543Smrg      /* Branch on the timer id */
938706f2543Smrg      switch (wParam)
939706f2543Smrg	{
940706f2543Smrg	case WIN_E3B_TIMER_ID:
941706f2543Smrg	  /* Send delayed button press */
942706f2543Smrg	  winMouseButtonsSendEvent (ButtonPress,
943706f2543Smrg				    s_pScreenPriv->iE3BCachedPress);
944706f2543Smrg
945706f2543Smrg	  /* Kill this timer */
946706f2543Smrg	  KillTimer (s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
947706f2543Smrg
948706f2543Smrg	  /* Clear screen privates flags */
949706f2543Smrg	  s_pScreenPriv->iE3BCachedPress = 0;
950706f2543Smrg	  break;
951706f2543Smrg
952706f2543Smrg	case WIN_POLLING_MOUSE_TIMER_ID:
953706f2543Smrg	  {
954706f2543Smrg	    POINT		point;
955706f2543Smrg	    WPARAM		wL, wM, wR, wShift, wCtrl;
956706f2543Smrg	    LPARAM		lPos;
957706f2543Smrg
958706f2543Smrg	    /* Get the current position of the mouse cursor */
959706f2543Smrg	    GetCursorPos (&point);
960706f2543Smrg
961706f2543Smrg	    /* Map from screen (-X, -Y) to root (0, 0) */
962706f2543Smrg	    point.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
963706f2543Smrg	    point.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
964706f2543Smrg
965706f2543Smrg	    /* Deliver absolute cursor position to X Server */
966706f2543Smrg	    winEnqueueMotion(point.x , point.y);
967706f2543Smrg
968706f2543Smrg	    /* Check if a button was released but we didn't see it */
969706f2543Smrg	    GetCursorPos (&point);
970706f2543Smrg	    wL = (GetKeyState (VK_LBUTTON) & 0x8000)?MK_LBUTTON:0;
971706f2543Smrg	    wM = (GetKeyState (VK_MBUTTON) & 0x8000)?MK_MBUTTON:0;
972706f2543Smrg	    wR = (GetKeyState (VK_RBUTTON) & 0x8000)?MK_RBUTTON:0;
973706f2543Smrg	    wShift = (GetKeyState (VK_SHIFT) & 0x8000)?MK_SHIFT:0;
974706f2543Smrg	    wCtrl = (GetKeyState (VK_CONTROL) & 0x8000)?MK_CONTROL:0;
975706f2543Smrg	    lPos = MAKELPARAM(point.x, point.y);
976706f2543Smrg	    if (g_fButton[0] & !wL)
977706f2543Smrg	    PostMessage (hwnd, WM_LBUTTONUP, wCtrl|wM|wR|wShift, lPos);
978706f2543Smrg	    if (g_fButton[1] & !wM)
979706f2543Smrg	      PostMessage (hwnd, WM_MBUTTONUP, wCtrl|wL|wR|wShift, lPos);
980706f2543Smrg	    if (g_fButton[2] & !wR)
981706f2543Smrg	      PostMessage (hwnd, WM_RBUTTONUP, wCtrl|wL|wM|wShift, lPos);
982706f2543Smrg	  }
983706f2543Smrg	}
984706f2543Smrg      return 0;
985706f2543Smrg
986706f2543Smrg    case WM_CTLCOLORSCROLLBAR:
987706f2543Smrg      FatalError ("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not "
988706f2543Smrg		  "supposed to get this message.  Exiting.\n");
989706f2543Smrg      return 0;
990706f2543Smrg
991706f2543Smrg    case WM_MOUSEWHEEL:
992706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
993706f2543Smrg	break;
994706f2543Smrg#if CYGDEBUG
995706f2543Smrg      winDebug ("winWindowProc - WM_MOUSEWHEEL\n");
996706f2543Smrg#endif
997706f2543Smrg      winMouseWheel (s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam));
998706f2543Smrg      break;
999706f2543Smrg
1000706f2543Smrg    case WM_SETFOCUS:
1001706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1002706f2543Smrg	break;
1003706f2543Smrg
1004706f2543Smrg      /* Restore the state of all mode keys */
1005706f2543Smrg      winRestoreModeKeyStates ();
1006706f2543Smrg
1007706f2543Smrg      /* Add the keyboard hook if possible */
1008706f2543Smrg      if (g_fKeyboardHookLL)
1009706f2543Smrg	g_fKeyboardHookLL = winInstallKeyboardHookLL ();
1010706f2543Smrg      return 0;
1011706f2543Smrg
1012706f2543Smrg    case WM_KILLFOCUS:
1013706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1014706f2543Smrg	break;
1015706f2543Smrg
1016706f2543Smrg      /* Release any pressed keys */
1017706f2543Smrg      winKeybdReleaseKeys ();
1018706f2543Smrg
1019706f2543Smrg      /* Remove our keyboard hook if it is installed */
1020706f2543Smrg      winRemoveKeyboardHookLL ();
1021706f2543Smrg      return 0;
1022706f2543Smrg
1023706f2543Smrg    case WM_SYSKEYDOWN:
1024706f2543Smrg    case WM_KEYDOWN:
1025706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1026706f2543Smrg	break;
1027706f2543Smrg
1028706f2543Smrg      /*
1029706f2543Smrg       * FIXME: Catching Alt-F4 like this is really terrible.  This should
1030706f2543Smrg       * be generalized to handle other Windows keyboard signals.  Actually,
1031706f2543Smrg       * the list keys to catch and the actions to perform when caught should
1032706f2543Smrg       * be configurable; that way user's can customize the keys that they
1033706f2543Smrg       * need to have passed through to their window manager or apps, or they
1034706f2543Smrg       * can remap certain actions to new key codes that do not conflict
1035706f2543Smrg       * with the X apps that they are using.  Yeah, that'll take awhile.
1036706f2543Smrg       */
1037706f2543Smrg      if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4
1038706f2543Smrg	   && (GetKeyState (VK_MENU) & 0x8000))
1039706f2543Smrg	  || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK
1040706f2543Smrg	      && (GetKeyState (VK_MENU) & 0x8000)
1041706f2543Smrg	      && (GetKeyState (VK_CONTROL) & 0x8000)))
1042706f2543Smrg	{
1043706f2543Smrg	  /*
1044706f2543Smrg	   * Better leave this message here, just in case some unsuspecting
1045706f2543Smrg	   * user enters Alt + F4 and is surprised when the application
1046706f2543Smrg	   * quits.
1047706f2543Smrg	   */
1048706f2543Smrg	  ErrorF ("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n");
1049706f2543Smrg
1050706f2543Smrg	  /* Display Exit dialog */
1051706f2543Smrg	  winDisplayExitDialog (s_pScreenPriv);
1052706f2543Smrg	  return 0;
1053706f2543Smrg	}
1054706f2543Smrg
1055706f2543Smrg      /*
1056706f2543Smrg       * Don't do anything for the Windows keys, as focus will soon
1057706f2543Smrg       * be returned to Windows.  We may be able to trap the Windows keys,
1058706f2543Smrg       * but we should determine if that is desirable before doing so.
1059706f2543Smrg       */
1060706f2543Smrg      if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
1061706f2543Smrg	break;
1062706f2543Smrg
1063706f2543Smrg      /*
1064706f2543Smrg       * Discard presses generated from Windows auto-repeat
1065706f2543Smrg       */
1066706f2543Smrg      if (lParam & (1<<30))
1067706f2543Smrg      {
1068706f2543Smrg        switch (wParam)
1069706f2543Smrg        {
1070706f2543Smrg          /* ago: Pressing LControl while RControl is pressed is
1071706f2543Smrg           * Indicated as repeat. Fix this!
1072706f2543Smrg           */
1073706f2543Smrg          case VK_CONTROL:
1074706f2543Smrg          case VK_SHIFT:
1075706f2543Smrg            if (winCheckKeyPressed(wParam, lParam))
1076706f2543Smrg              return 0;
1077706f2543Smrg            break;
1078706f2543Smrg          default:
1079706f2543Smrg            return 0;
1080706f2543Smrg        }
1081706f2543Smrg      }
1082706f2543Smrg
1083706f2543Smrg      /* Discard fake Ctrl_L presses that precede AltGR on non-US keyboards */
1084706f2543Smrg      if (winIsFakeCtrl_L (message, wParam, lParam))
1085706f2543Smrg	return 0;
1086706f2543Smrg
1087706f2543Smrg      /* Translate Windows key code to X scan code */
1088706f2543Smrg      winTranslateKey (wParam, lParam, &iScanCode);
1089706f2543Smrg
1090706f2543Smrg      /* Ignore repeats for CapsLock */
1091706f2543Smrg      if (wParam == VK_CAPITAL)
1092706f2543Smrg	lParam = 1;
1093706f2543Smrg
1094706f2543Smrg      /* Send the key event(s) */
1095706f2543Smrg      for (i = 0; i < LOWORD(lParam); ++i)
1096706f2543Smrg	winSendKeyEvent (iScanCode, TRUE);
1097706f2543Smrg      return 0;
1098706f2543Smrg
1099706f2543Smrg    case WM_SYSKEYUP:
1100706f2543Smrg    case WM_KEYUP:
1101706f2543Smrg      if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1102706f2543Smrg	break;
1103706f2543Smrg
1104706f2543Smrg      /*
1105706f2543Smrg       * Don't do anything for the Windows keys, as focus will soon
1106706f2543Smrg       * be returned to Windows.  We may be able to trap the Windows keys,
1107706f2543Smrg       * but we should determine if that is desirable before doing so.
1108706f2543Smrg       */
1109706f2543Smrg      if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
1110706f2543Smrg	break;
1111706f2543Smrg
1112706f2543Smrg      /* Ignore the fake Ctrl_L that follows an AltGr release */
1113706f2543Smrg      if (winIsFakeCtrl_L (message, wParam, lParam))
1114706f2543Smrg	return 0;
1115706f2543Smrg
1116706f2543Smrg      /* Enqueue a keyup event */
1117706f2543Smrg      winTranslateKey (wParam, lParam, &iScanCode);
1118706f2543Smrg      winSendKeyEvent (iScanCode, FALSE);
1119706f2543Smrg
1120706f2543Smrg      /* Release all pressed shift keys */
1121706f2543Smrg      if (wParam == VK_SHIFT)
1122706f2543Smrg        winFixShiftKeys (iScanCode);
1123706f2543Smrg      return 0;
1124706f2543Smrg
1125706f2543Smrg    case WM_HOTKEY:
1126706f2543Smrg      if (s_pScreenPriv == NULL)
1127706f2543Smrg	break;
1128706f2543Smrg
1129706f2543Smrg      /* Call the engine-specific hot key handler */
1130706f2543Smrg      (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen);
1131706f2543Smrg      return 0;
1132706f2543Smrg
1133706f2543Smrg    case WM_ACTIVATE:
1134706f2543Smrg      if (s_pScreenPriv == NULL
1135706f2543Smrg	  || s_pScreenInfo->fIgnoreInput)
1136706f2543Smrg	break;
1137706f2543Smrg
1138706f2543Smrg      /* TODO: Override display of window when we have a bad depth */
1139706f2543Smrg      if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth)
1140706f2543Smrg	{
1141706f2543Smrg	  ErrorF ("winWindowProc - WM_ACTIVATE - Bad depth, trying "
1142706f2543Smrg		  "to override window activation\n");
1143706f2543Smrg
1144706f2543Smrg	  /* Minimize the window */
1145706f2543Smrg	  ShowWindow (hwnd, SW_MINIMIZE);
1146706f2543Smrg
1147706f2543Smrg	  /* Display dialog box */
1148706f2543Smrg	  if (g_hDlgDepthChange != NULL)
1149706f2543Smrg	    {
1150706f2543Smrg	      /* Make the existing dialog box active */
1151706f2543Smrg	      SetActiveWindow (g_hDlgDepthChange);
1152706f2543Smrg	    }
1153706f2543Smrg	  else
1154706f2543Smrg	    {
1155706f2543Smrg	      /* TODO: Recreate the dialog box and bring to the top */
1156706f2543Smrg	      ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT);
1157706f2543Smrg	    }
1158706f2543Smrg
1159706f2543Smrg	  /* Don't do any other processing of this message */
1160706f2543Smrg	  return 0;
1161706f2543Smrg	}
1162706f2543Smrg
1163706f2543Smrg#if CYGDEBUG
1164706f2543Smrg      winDebug ("winWindowProc - WM_ACTIVATE\n");
1165706f2543Smrg#endif
1166706f2543Smrg
1167706f2543Smrg      /*
1168706f2543Smrg       * Focus is being changed to another window.
1169706f2543Smrg       * The other window may or may not belong to
1170706f2543Smrg       * our process.
1171706f2543Smrg       */
1172706f2543Smrg
1173706f2543Smrg      /* Clear any lingering wheel delta */
1174706f2543Smrg      s_pScreenPriv->iDeltaZ = 0;
1175706f2543Smrg
1176706f2543Smrg      /* Reshow the Windows mouse cursor if we are being deactivated */
1177706f2543Smrg      if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE
1178706f2543Smrg	  && !g_fCursor)
1179706f2543Smrg	{
1180706f2543Smrg	  /* Show Windows cursor */
1181706f2543Smrg	  g_fCursor = TRUE;
1182706f2543Smrg	  ShowCursor (TRUE);
1183706f2543Smrg	}
1184706f2543Smrg      return 0;
1185706f2543Smrg
1186706f2543Smrg    case WM_ACTIVATEAPP:
1187706f2543Smrg      if (s_pScreenPriv == NULL
1188706f2543Smrg	  || s_pScreenInfo->fIgnoreInput)
1189706f2543Smrg	break;
1190706f2543Smrg
1191706f2543Smrg#if CYGDEBUG || TRUE
1192706f2543Smrg      winDebug ("winWindowProc - WM_ACTIVATEAPP\n");
1193706f2543Smrg#endif
1194706f2543Smrg
1195706f2543Smrg      /* Activate or deactivate */
1196706f2543Smrg      s_pScreenPriv->fActive = wParam;
1197706f2543Smrg
1198706f2543Smrg      /* Reshow the Windows mouse cursor if we are being deactivated */
1199706f2543Smrg      if (g_fSoftwareCursor && !s_pScreenPriv->fActive
1200706f2543Smrg	  && !g_fCursor)
1201706f2543Smrg	{
1202706f2543Smrg	  /* Show Windows cursor */
1203706f2543Smrg	  g_fCursor = TRUE;
1204706f2543Smrg	  ShowCursor (TRUE);
1205706f2543Smrg	}
1206706f2543Smrg
1207706f2543Smrg#ifdef XWIN_CLIPBOARD
1208706f2543Smrg      /* Make sure the clipboard chain is ok. */
1209706f2543Smrg      winFixClipboardChain ();
1210706f2543Smrg#endif
1211706f2543Smrg
1212706f2543Smrg      /* Call engine specific screen activation/deactivation function */
1213706f2543Smrg      (*s_pScreenPriv->pwinActivateApp) (s_pScreen);
1214706f2543Smrg
1215706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
1216706f2543Smrg      if (s_pScreenPriv->fActive)
1217706f2543Smrg	{
1218706f2543Smrg	  /* Restack all window unless using built-in wm. */
1219706f2543Smrg	  if (s_pScreenInfo->fInternalWM && s_pScreenInfo->fAnotherWMRunning)
1220706f2543Smrg	    winMWExtWMRestackWindows (s_pScreen);
1221706f2543Smrg	}
1222706f2543Smrg#endif
1223706f2543Smrg
1224706f2543Smrg      return 0;
1225706f2543Smrg
1226706f2543Smrg    case WM_COMMAND:
1227706f2543Smrg      switch (LOWORD (wParam))
1228706f2543Smrg	{
1229706f2543Smrg	case ID_APP_EXIT:
1230706f2543Smrg	  /* Display Exit dialog */
1231706f2543Smrg	  winDisplayExitDialog (s_pScreenPriv);
1232706f2543Smrg	  return 0;
1233706f2543Smrg
1234706f2543Smrg#ifdef XWIN_MULTIWINDOW
1235706f2543Smrg	case ID_APP_HIDE_ROOT:
1236706f2543Smrg	  if (s_pScreenPriv->fRootWindowShown)
1237706f2543Smrg	    ShowWindow (s_pScreenPriv->hwndScreen, SW_HIDE);
1238706f2543Smrg	  else
1239706f2543Smrg	    ShowWindow (s_pScreenPriv->hwndScreen, SW_SHOW);
1240706f2543Smrg	  s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown;
1241706f2543Smrg	  return 0;
1242706f2543Smrg#endif
1243706f2543Smrg
1244706f2543Smrg	case ID_APP_ABOUT:
1245706f2543Smrg	  /* Display the About box */
1246706f2543Smrg	  winDisplayAboutDialog (s_pScreenPriv);
1247706f2543Smrg	  return 0;
1248706f2543Smrg
1249706f2543Smrg	default:
1250706f2543Smrg	  /* It's probably one of the custom menus... */
1251706f2543Smrg	  if (HandleCustomWM_COMMAND (0, LOWORD (wParam)))
1252706f2543Smrg	    return 0;
1253706f2543Smrg	}
1254706f2543Smrg      break;
1255706f2543Smrg
1256706f2543Smrg    case WM_ENDSESSION:
1257706f2543Smrg    case WM_GIVEUP:
1258706f2543Smrg      /* Tell X that we are giving up */
1259706f2543Smrg#ifdef XWIN_MULTIWINDOW
1260706f2543Smrg      if (s_pScreenInfo->fMultiWindow)
1261706f2543Smrg	winDeinitMultiWindowWM ();
1262706f2543Smrg#endif
1263706f2543Smrg      GiveUp (0);
1264706f2543Smrg      return 0;
1265706f2543Smrg
1266706f2543Smrg    case WM_CLOSE:
1267706f2543Smrg      /* Display Exit dialog */
1268706f2543Smrg      winDisplayExitDialog (s_pScreenPriv);
1269706f2543Smrg      return 0;
1270706f2543Smrg
1271706f2543Smrg    case WM_SETCURSOR:
1272706f2543Smrg      if (LOWORD(lParam) == HTCLIENT)
1273706f2543Smrg	{
1274706f2543Smrg	  if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle);
1275706f2543Smrg	  return TRUE;
1276706f2543Smrg	}
1277706f2543Smrg      break;
1278706f2543Smrg
1279706f2543Smrg#ifdef XWIN_MULTIWINDOWEXTWM
1280706f2543Smrg    case WM_MANAGE:
1281706f2543Smrg      ErrorF ("winWindowProc - WM_MANAGE\n");
1282706f2543Smrg      s_pScreenInfo->fAnotherWMRunning = FALSE;
1283706f2543Smrg
1284706f2543Smrg      if (s_pScreenInfo->fInternalWM)
1285706f2543Smrg	{
1286706f2543Smrg	  EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
1287706f2543Smrg	  //RootlessRepositionWindows (s_pScreen);
1288706f2543Smrg	}
1289706f2543Smrg      break;
1290706f2543Smrg
1291706f2543Smrg    case WM_UNMANAGE:
1292706f2543Smrg      ErrorF ("winWindowProc - WM_UNMANAGE\n");
1293706f2543Smrg      s_pScreenInfo->fAnotherWMRunning = TRUE;
1294706f2543Smrg
1295706f2543Smrg      if (s_pScreenInfo->fInternalWM)
1296706f2543Smrg	{
1297706f2543Smrg	  EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
1298706f2543Smrg	  winMWExtWMRestackWindows (s_pScreen);
1299706f2543Smrg	}
1300706f2543Smrg      break;
1301706f2543Smrg#endif
1302706f2543Smrg
1303706f2543Smrg    default:
1304706f2543Smrg      if(message == s_uTaskbarRestart)
1305706f2543Smrg	{
1306706f2543Smrg	  winInitNotifyIcon (s_pScreenPriv);
1307706f2543Smrg	}
1308706f2543Smrg      break;
1309706f2543Smrg    }
1310706f2543Smrg
1311706f2543Smrg  return DefWindowProc (hwnd, message, wParam, lParam);
1312706f2543Smrg}
1313