xref: /OK3568_Linux_fs/external/xserver/hw/xwin/winwndproc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *Permission is hereby granted, free of charge, to any person obtaining
5*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
6*4882a593Smuzhiyun  *"Software"), to deal in the Software without restriction, including
7*4882a593Smuzhiyun  *without limitation the rights to use, copy, modify, merge, publish,
8*4882a593Smuzhiyun  *distribute, sublicense, and/or sell copies of the Software, and to
9*4882a593Smuzhiyun  *permit persons to whom the Software is furnished to do so, subject to
10*4882a593Smuzhiyun  *the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *The above copyright notice and this permission notice shall be
13*4882a593Smuzhiyun  *included in all copies or substantial portions of the Software.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*4882a593Smuzhiyun  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*4882a593Smuzhiyun  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*4882a593Smuzhiyun  *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19*4882a593Smuzhiyun  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20*4882a593Smuzhiyun  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21*4882a593Smuzhiyun  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  *Except as contained in this notice, the name of the XFree86 Project
24*4882a593Smuzhiyun  *shall not be used in advertising or otherwise to promote the sale, use
25*4882a593Smuzhiyun  *or other dealings in this Software without prior written authorization
26*4882a593Smuzhiyun  *from the XFree86 Project.
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * Authors:	Dakshinamurthy Karra
29*4882a593Smuzhiyun  *		Suhaib M Siddiqi
30*4882a593Smuzhiyun  *		Peter Busch
31*4882a593Smuzhiyun  *		Harold L Hunt II
32*4882a593Smuzhiyun  *		MATSUZAKI Kensuke
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #ifdef HAVE_XWIN_CONFIG_H
36*4882a593Smuzhiyun #include <xwin-config.h>
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun #include "win.h"
39*4882a593Smuzhiyun #include <commctrl.h>
40*4882a593Smuzhiyun #include "winprefs.h"
41*4882a593Smuzhiyun #include "winconfig.h"
42*4882a593Smuzhiyun #include "winmsg.h"
43*4882a593Smuzhiyun #include "winmonitors.h"
44*4882a593Smuzhiyun #include "inputstr.h"
45*4882a593Smuzhiyun #include "winclipboard/winclipboard.h"
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun  * Global variables
49*4882a593Smuzhiyun  */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun Bool g_fCursor = TRUE;
52*4882a593Smuzhiyun Bool g_fButton[3] = { FALSE, FALSE, FALSE };
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /*
55*4882a593Smuzhiyun  * Called by winWakeupHandler
56*4882a593Smuzhiyun  * Processes current Windows message
57*4882a593Smuzhiyun  */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun LRESULT CALLBACK
winWindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)60*4882a593Smuzhiyun winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun     static winPrivScreenPtr s_pScreenPriv = NULL;
63*4882a593Smuzhiyun     static winScreenInfo *s_pScreenInfo = NULL;
64*4882a593Smuzhiyun     static ScreenPtr s_pScreen = NULL;
65*4882a593Smuzhiyun     static HWND s_hwndLastPrivates = NULL;
66*4882a593Smuzhiyun     static Bool s_fTracking = FALSE;
67*4882a593Smuzhiyun     static unsigned long s_ulServerGeneration = 0;
68*4882a593Smuzhiyun     static UINT s_uTaskbarRestart = 0;
69*4882a593Smuzhiyun     int iScanCode;
70*4882a593Smuzhiyun     int i;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #if CYGDEBUG
73*4882a593Smuzhiyun     winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam);
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun     /* Watch for server regeneration */
77*4882a593Smuzhiyun     if (g_ulServerGeneration != s_ulServerGeneration) {
78*4882a593Smuzhiyun         /* Store new server generation */
79*4882a593Smuzhiyun         s_ulServerGeneration = g_ulServerGeneration;
80*4882a593Smuzhiyun     }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun     /* Only retrieve new privates pointers if window handle is null or changed */
83*4882a593Smuzhiyun     if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates)
84*4882a593Smuzhiyun         && (s_pScreenPriv = GetProp(hwnd, WIN_SCR_PROP)) != NULL) {
85*4882a593Smuzhiyun #if CYGDEBUG
86*4882a593Smuzhiyun         winDebug("winWindowProc - Setting privates handle\n");
87*4882a593Smuzhiyun #endif
88*4882a593Smuzhiyun         s_pScreenInfo = s_pScreenPriv->pScreenInfo;
89*4882a593Smuzhiyun         s_pScreen = s_pScreenInfo->pScreen;
90*4882a593Smuzhiyun         s_hwndLastPrivates = hwnd;
91*4882a593Smuzhiyun     }
92*4882a593Smuzhiyun     else if (s_pScreenPriv == NULL) {
93*4882a593Smuzhiyun         /* For safety, handle case that should never happen */
94*4882a593Smuzhiyun         s_pScreenInfo = NULL;
95*4882a593Smuzhiyun         s_pScreen = NULL;
96*4882a593Smuzhiyun         s_hwndLastPrivates = NULL;
97*4882a593Smuzhiyun     }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun     /* Branch on message type */
100*4882a593Smuzhiyun     switch (message) {
101*4882a593Smuzhiyun     case WM_TRAYICON:
102*4882a593Smuzhiyun         return winHandleIconMessage(hwnd, message, wParam, lParam,
103*4882a593Smuzhiyun                                     s_pScreenPriv);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     case WM_CREATE:
106*4882a593Smuzhiyun #if CYGDEBUG
107*4882a593Smuzhiyun         winDebug("winWindowProc - WM_CREATE\n");
108*4882a593Smuzhiyun #endif
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun         /*
111*4882a593Smuzhiyun          * Add a property to our display window that references
112*4882a593Smuzhiyun          * this screens' privates.
113*4882a593Smuzhiyun          *
114*4882a593Smuzhiyun          * This allows the window procedure to refer to the
115*4882a593Smuzhiyun          * appropriate window DC and shadow DC for the window that
116*4882a593Smuzhiyun          * it is processing.  We use this to repaint exposed
117*4882a593Smuzhiyun          * areas of our display window.
118*4882a593Smuzhiyun          */
119*4882a593Smuzhiyun         s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams;
120*4882a593Smuzhiyun         s_pScreenInfo = s_pScreenPriv->pScreenInfo;
121*4882a593Smuzhiyun         s_pScreen = s_pScreenInfo->pScreen;
122*4882a593Smuzhiyun         s_hwndLastPrivates = hwnd;
123*4882a593Smuzhiyun         s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
124*4882a593Smuzhiyun         SetProp(hwnd, WIN_SCR_PROP, s_pScreenPriv);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun         /* Setup tray icon */
127*4882a593Smuzhiyun         if (!s_pScreenInfo->fNoTrayIcon) {
128*4882a593Smuzhiyun             /*
129*4882a593Smuzhiyun              * NOTE: The WM_CREATE message is processed before CreateWindowEx
130*4882a593Smuzhiyun              * returns, so s_pScreenPriv->hwndScreen is invalid at this point.
131*4882a593Smuzhiyun              * We go ahead and copy our hwnd parameter over top of the screen
132*4882a593Smuzhiyun              * privates hwndScreen so that we have a valid value for
133*4882a593Smuzhiyun              * that member.  Otherwise, the tray icon will disappear
134*4882a593Smuzhiyun              * the first time you move the mouse over top of it.
135*4882a593Smuzhiyun              */
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun             s_pScreenPriv->hwndScreen = hwnd;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun             winInitNotifyIcon(s_pScreenPriv);
140*4882a593Smuzhiyun         }
141*4882a593Smuzhiyun         return 0;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     case WM_DISPLAYCHANGE:
144*4882a593Smuzhiyun         /*
145*4882a593Smuzhiyun            WM_DISPLAYCHANGE seems to be sent when the monitor layout or
146*4882a593Smuzhiyun            any monitor's resolution or depth changes, but it's lParam and
147*4882a593Smuzhiyun            wParam always indicate the resolution and bpp for the primary
148*4882a593Smuzhiyun            monitor (so ignore that as we could be on any monitor...)
149*4882a593Smuzhiyun          */
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun         /* We cannot handle a display mode change during initialization */
152*4882a593Smuzhiyun         if (s_pScreenInfo == NULL)
153*4882a593Smuzhiyun             FatalError("winWindowProc - WM_DISPLAYCHANGE - The display "
154*4882a593Smuzhiyun                        "mode changed while we were intializing.  This is "
155*4882a593Smuzhiyun                        "very bad and unexpected.  Exiting.\n");
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun         /*
158*4882a593Smuzhiyun          * We do not care about display changes with
159*4882a593Smuzhiyun          * fullscreen DirectDraw engines, because those engines set
160*4882a593Smuzhiyun          * their own mode when they become active.
161*4882a593Smuzhiyun          */
162*4882a593Smuzhiyun         if (s_pScreenInfo->fFullScreen
163*4882a593Smuzhiyun             && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)) {
164*4882a593Smuzhiyun             break;
165*4882a593Smuzhiyun         }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun         ErrorF("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
168*4882a593Smuzhiyun                "new height: %d new bpp: %d\n",
169*4882a593Smuzhiyun                LOWORD(lParam), HIWORD(lParam), (int)wParam);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun         /* 0 bpp has no defined meaning, ignore this message */
172*4882a593Smuzhiyun         if (wParam == 0)
173*4882a593Smuzhiyun             break;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun         /*
176*4882a593Smuzhiyun          * Check for a disruptive change in depth.
177*4882a593Smuzhiyun          * We can only display a message for a disruptive depth change,
178*4882a593Smuzhiyun          * we cannot do anything to correct the situation.
179*4882a593Smuzhiyun          */
180*4882a593Smuzhiyun         /*
181*4882a593Smuzhiyun            XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT)
182*4882a593Smuzhiyun            has changed as well...
183*4882a593Smuzhiyun          */
184*4882a593Smuzhiyun         if (s_pScreenInfo->dwBPP !=
185*4882a593Smuzhiyun             GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL)) {
186*4882a593Smuzhiyun             if (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL) {
187*4882a593Smuzhiyun                 /* Cannot display the visual until the depth is restored */
188*4882a593Smuzhiyun                 ErrorF("winWindowProc - Disruptive change in depth\n");
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun                 /* Display depth change dialog */
191*4882a593Smuzhiyun                 winDisplayDepthChangeDialog(s_pScreenPriv);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun                 /* Flag that we have an invalid screen depth */
194*4882a593Smuzhiyun                 s_pScreenPriv->fBadDepth = TRUE;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun                 /* Minimize the display window */
197*4882a593Smuzhiyun                 ShowWindow(hwnd, SW_MINIMIZE);
198*4882a593Smuzhiyun             }
199*4882a593Smuzhiyun             else {
200*4882a593Smuzhiyun                 /* For GDI, performance may suffer until original depth is restored */
201*4882a593Smuzhiyun                 ErrorF
202*4882a593Smuzhiyun                     ("winWindowProc - Performance may be non-optimal after change in depth\n");
203*4882a593Smuzhiyun             }
204*4882a593Smuzhiyun         }
205*4882a593Smuzhiyun         else {
206*4882a593Smuzhiyun             /* Flag that we have a valid screen depth */
207*4882a593Smuzhiyun             s_pScreenPriv->fBadDepth = FALSE;
208*4882a593Smuzhiyun         }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun         /*
211*4882a593Smuzhiyun            If we could cheaply check if this WM_DISPLAYCHANGE change
212*4882a593Smuzhiyun            affects the monitor(s) which this X screen is displayed on
213*4882a593Smuzhiyun            then we should do so here.  For the moment, assume it does.
214*4882a593Smuzhiyun            (this is probably usually the case so that might be an
215*4882a593Smuzhiyun            overoptimization)
216*4882a593Smuzhiyun          */
217*4882a593Smuzhiyun         {
218*4882a593Smuzhiyun             /*
219*4882a593Smuzhiyun                In rootless modes which are monitor or virtual desktop size
220*4882a593Smuzhiyun                use RandR to resize the X screen
221*4882a593Smuzhiyun              */
222*4882a593Smuzhiyun             if ((!s_pScreenInfo->fUserGaveHeightAndWidth) &&
223*4882a593Smuzhiyun                 (s_pScreenInfo->iResizeMode == resizeWithRandr) && (FALSE
224*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
225*4882a593Smuzhiyun                                                                     ||
226*4882a593Smuzhiyun                                                                     s_pScreenInfo->
227*4882a593Smuzhiyun                                                                     fMWExtWM
228*4882a593Smuzhiyun #endif
229*4882a593Smuzhiyun                                                                     ||
230*4882a593Smuzhiyun                                                                     s_pScreenInfo->
231*4882a593Smuzhiyun                                                                     fRootless
232*4882a593Smuzhiyun                                                                     ||
233*4882a593Smuzhiyun                                                                     s_pScreenInfo->
234*4882a593Smuzhiyun                                                                     fMultiWindow
235*4882a593Smuzhiyun                 )) {
236*4882a593Smuzhiyun                 DWORD dwWidth = 0, dwHeight = 0;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun                 if (s_pScreenInfo->fMultipleMonitors) {
239*4882a593Smuzhiyun                     /* resize to new virtual desktop size */
240*4882a593Smuzhiyun                     dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
241*4882a593Smuzhiyun                     dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
242*4882a593Smuzhiyun                 }
243*4882a593Smuzhiyun                 else {
244*4882a593Smuzhiyun                     /* resize to new size of specified monitor */
245*4882a593Smuzhiyun                     struct GetMonitorInfoData data;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun                     if (QueryMonitor(s_pScreenInfo->iMonitor, &data)) {
248*4882a593Smuzhiyun                         if (data.bMonitorSpecifiedExists == TRUE) {
249*4882a593Smuzhiyun                             dwWidth = data.monitorWidth;
250*4882a593Smuzhiyun                             dwHeight = data.monitorHeight;
251*4882a593Smuzhiyun                             /*
252*4882a593Smuzhiyun                                XXX: monitor may have changed position,
253*4882a593Smuzhiyun                                so we might need to update xinerama data
254*4882a593Smuzhiyun                              */
255*4882a593Smuzhiyun                         }
256*4882a593Smuzhiyun                         else {
257*4882a593Smuzhiyun                             ErrorF("Monitor number %d no longer exists!\n",
258*4882a593Smuzhiyun                                    s_pScreenInfo->iMonitor);
259*4882a593Smuzhiyun                         }
260*4882a593Smuzhiyun                     }
261*4882a593Smuzhiyun                 }
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun                 /*
264*4882a593Smuzhiyun                    XXX: probably a small bug here: we don't compute the work area
265*4882a593Smuzhiyun                    and allow for task bar
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun                    XXX: generally, we don't allow for the task bar being moved after
268*4882a593Smuzhiyun                    the server is started
269*4882a593Smuzhiyun                  */
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun                 /* Set screen size to match new size, if it is different to current */
272*4882a593Smuzhiyun                 if (((dwWidth != 0) && (dwHeight != 0)) &&
273*4882a593Smuzhiyun                     ((s_pScreenInfo->dwWidth != dwWidth) ||
274*4882a593Smuzhiyun                      (s_pScreenInfo->dwHeight != dwHeight))) {
275*4882a593Smuzhiyun                     winDoRandRScreenSetSize(s_pScreen,
276*4882a593Smuzhiyun                                             dwWidth,
277*4882a593Smuzhiyun                                             dwHeight,
278*4882a593Smuzhiyun                                             (dwWidth * 25.4) /
279*4882a593Smuzhiyun                                             monitorResolution,
280*4882a593Smuzhiyun                                             (dwHeight * 25.4) /
281*4882a593Smuzhiyun                                             monitorResolution);
282*4882a593Smuzhiyun                 }
283*4882a593Smuzhiyun             }
284*4882a593Smuzhiyun             else {
285*4882a593Smuzhiyun                 /*
286*4882a593Smuzhiyun                  * We can simply recreate the same-sized primary surface when
287*4882a593Smuzhiyun                  * the display dimensions change.
288*4882a593Smuzhiyun                  */
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun                 winDebug
291*4882a593Smuzhiyun                     ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun                 /* Release the old primary surface */
294*4882a593Smuzhiyun                 if (*s_pScreenPriv->pwinReleasePrimarySurface)
295*4882a593Smuzhiyun                     (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun                 /* Create the new primary surface */
298*4882a593Smuzhiyun                 if (*s_pScreenPriv->pwinCreatePrimarySurface)
299*4882a593Smuzhiyun                     (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
300*4882a593Smuzhiyun             }
301*4882a593Smuzhiyun         }
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun         break;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     case WM_SIZE:
306*4882a593Smuzhiyun     {
307*4882a593Smuzhiyun         SCROLLINFO si;
308*4882a593Smuzhiyun         RECT rcWindow;
309*4882a593Smuzhiyun         int iWidth, iHeight;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun #if CYGDEBUG
312*4882a593Smuzhiyun         winDebug("winWindowProc - WM_SIZE\n");
313*4882a593Smuzhiyun #endif
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun         /* Break if we do not allow resizing */
316*4882a593Smuzhiyun         if ((s_pScreenInfo->iResizeMode == resizeNotAllowed)
317*4882a593Smuzhiyun             || !s_pScreenInfo->fDecoration
318*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
319*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
320*4882a593Smuzhiyun #endif
321*4882a593Smuzhiyun             || s_pScreenInfo->fRootless
322*4882a593Smuzhiyun             || s_pScreenInfo->fMultiWindow
323*4882a593Smuzhiyun             || s_pScreenInfo->fFullScreen)
324*4882a593Smuzhiyun             break;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun         /* No need to resize if we get minimized */
327*4882a593Smuzhiyun         if (wParam == SIZE_MINIMIZED)
328*4882a593Smuzhiyun             return 0;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun         ErrorF("winWindowProc - WM_SIZE - new client area w: %d h: %d\n",
331*4882a593Smuzhiyun                LOWORD(lParam), HIWORD(lParam));
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun         if (s_pScreenInfo->iResizeMode == resizeWithRandr) {
334*4882a593Smuzhiyun             /* Actual resizing is done on WM_EXITSIZEMOVE */
335*4882a593Smuzhiyun             return 0;
336*4882a593Smuzhiyun         }
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun         /* Otherwise iResizeMode == resizeWithScrollbars */
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun         /*
341*4882a593Smuzhiyun          * Get the size of the whole window, including client area,
342*4882a593Smuzhiyun          * scrollbars, and non-client area decorations (caption, borders).
343*4882a593Smuzhiyun          * We do this because we need to check if the client area
344*4882a593Smuzhiyun          * without scrollbars is large enough to display the whole visual.
345*4882a593Smuzhiyun          * The new client area size passed by lParam already subtracts
346*4882a593Smuzhiyun          * the size of the scrollbars if they are currently displayed.
347*4882a593Smuzhiyun          * So checking is LOWORD(lParam) == visual_width and
348*4882a593Smuzhiyun          * HIWORD(lParam) == visual_height will never tell us to hide
349*4882a593Smuzhiyun          * the scrollbars because the client area would always be too small.
350*4882a593Smuzhiyun          * GetClientRect returns the same sizes given by lParam, so we
351*4882a593Smuzhiyun          * cannot use GetClientRect either.
352*4882a593Smuzhiyun          */
353*4882a593Smuzhiyun         GetWindowRect(hwnd, &rcWindow);
354*4882a593Smuzhiyun         iWidth = rcWindow.right - rcWindow.left;
355*4882a593Smuzhiyun         iHeight = rcWindow.bottom - rcWindow.top;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun         /* Subtract the frame size from the window size. */
358*4882a593Smuzhiyun         iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
359*4882a593Smuzhiyun         iHeight -= (2 * GetSystemMetrics(SM_CYSIZEFRAME)
360*4882a593Smuzhiyun                     + GetSystemMetrics(SM_CYCAPTION));
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun         /*
363*4882a593Smuzhiyun          * Update scrollbar page sizes.
364*4882a593Smuzhiyun          * NOTE: If page size == range, then the scrollbar is
365*4882a593Smuzhiyun          * automatically hidden.
366*4882a593Smuzhiyun          */
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun         /* Is the naked client area large enough to show the whole visual? */
369*4882a593Smuzhiyun         if (iWidth < s_pScreenInfo->dwWidth
370*4882a593Smuzhiyun             || iHeight < s_pScreenInfo->dwHeight) {
371*4882a593Smuzhiyun             /* Client area too small to display visual, use scrollbars */
372*4882a593Smuzhiyun             iWidth -= GetSystemMetrics(SM_CXVSCROLL);
373*4882a593Smuzhiyun             iHeight -= GetSystemMetrics(SM_CYHSCROLL);
374*4882a593Smuzhiyun         }
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun         /* Set the horizontal scrollbar page size */
377*4882a593Smuzhiyun         si.cbSize = sizeof(si);
378*4882a593Smuzhiyun         si.fMask = SIF_PAGE | SIF_RANGE;
379*4882a593Smuzhiyun         si.nMin = 0;
380*4882a593Smuzhiyun         si.nMax = s_pScreenInfo->dwWidth - 1;
381*4882a593Smuzhiyun         si.nPage = iWidth;
382*4882a593Smuzhiyun         SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun         /* Set the vertical scrollbar page size */
385*4882a593Smuzhiyun         si.cbSize = sizeof(si);
386*4882a593Smuzhiyun         si.fMask = SIF_PAGE | SIF_RANGE;
387*4882a593Smuzhiyun         si.nMin = 0;
388*4882a593Smuzhiyun         si.nMax = s_pScreenInfo->dwHeight - 1;
389*4882a593Smuzhiyun         si.nPage = iHeight;
390*4882a593Smuzhiyun         SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun         /*
393*4882a593Smuzhiyun          * NOTE: Scrollbars may have moved if they were at the
394*4882a593Smuzhiyun          * far right/bottom, so we query their current position.
395*4882a593Smuzhiyun          */
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun         /* Get the horizontal scrollbar position and set the offset */
398*4882a593Smuzhiyun         si.cbSize = sizeof(si);
399*4882a593Smuzhiyun         si.fMask = SIF_POS;
400*4882a593Smuzhiyun         GetScrollInfo(hwnd, SB_HORZ, &si);
401*4882a593Smuzhiyun         s_pScreenInfo->dwXOffset = -si.nPos;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun         /* Get the vertical scrollbar position and set the offset */
404*4882a593Smuzhiyun         si.cbSize = sizeof(si);
405*4882a593Smuzhiyun         si.fMask = SIF_POS;
406*4882a593Smuzhiyun         GetScrollInfo(hwnd, SB_VERT, &si);
407*4882a593Smuzhiyun         s_pScreenInfo->dwYOffset = -si.nPos;
408*4882a593Smuzhiyun     }
409*4882a593Smuzhiyun         return 0;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun     case WM_SYSCOMMAND:
412*4882a593Smuzhiyun         if (s_pScreenInfo->iResizeMode == resizeWithRandr &&
413*4882a593Smuzhiyun             ((wParam & 0xfff0) == SC_MAXIMIZE ||
414*4882a593Smuzhiyun              (wParam & 0xfff0) == SC_RESTORE))
415*4882a593Smuzhiyun             PostMessage(hwnd, WM_EXITSIZEMOVE, 0, 0);
416*4882a593Smuzhiyun         break;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun     case WM_ENTERSIZEMOVE:
419*4882a593Smuzhiyun         ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n");
420*4882a593Smuzhiyun         break;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun     case WM_EXITSIZEMOVE:
423*4882a593Smuzhiyun         ErrorF("winWindowProc - WM_EXITSIZEMOVE\n");
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun         if (s_pScreenInfo->iResizeMode == resizeWithRandr) {
426*4882a593Smuzhiyun             /* Set screen size to match new client area, if it is different to current */
427*4882a593Smuzhiyun             RECT rcClient;
428*4882a593Smuzhiyun             DWORD dwWidth, dwHeight;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun             GetClientRect(hwnd, &rcClient);
431*4882a593Smuzhiyun             dwWidth = rcClient.right - rcClient.left;
432*4882a593Smuzhiyun             dwHeight = rcClient.bottom - rcClient.top;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun             if ((s_pScreenInfo->dwWidth != dwWidth) ||
435*4882a593Smuzhiyun                 (s_pScreenInfo->dwHeight != dwHeight)) {
436*4882a593Smuzhiyun                 /* mm = dots * (25.4 mm / inch) / (dots / inch) */
437*4882a593Smuzhiyun                 winDoRandRScreenSetSize(s_pScreen,
438*4882a593Smuzhiyun                                         dwWidth,
439*4882a593Smuzhiyun                                         dwHeight,
440*4882a593Smuzhiyun                                         (dwWidth * 25.4) / monitorResolution,
441*4882a593Smuzhiyun                                         (dwHeight * 25.4) / monitorResolution);
442*4882a593Smuzhiyun             }
443*4882a593Smuzhiyun         }
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun         break;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun     case WM_VSCROLL:
448*4882a593Smuzhiyun     {
449*4882a593Smuzhiyun         SCROLLINFO si;
450*4882a593Smuzhiyun         int iVertPos;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun #if CYGDEBUG
453*4882a593Smuzhiyun         winDebug("winWindowProc - WM_VSCROLL\n");
454*4882a593Smuzhiyun #endif
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun         /* Get vertical scroll bar info */
457*4882a593Smuzhiyun         si.cbSize = sizeof(si);
458*4882a593Smuzhiyun         si.fMask = SIF_ALL;
459*4882a593Smuzhiyun         GetScrollInfo(hwnd, SB_VERT, &si);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun         /* Save the vertical position for comparison later */
462*4882a593Smuzhiyun         iVertPos = si.nPos;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun         /*
465*4882a593Smuzhiyun          * Don't forget:
466*4882a593Smuzhiyun          * moving the scrollbar to the DOWN, scroll the content UP
467*4882a593Smuzhiyun          */
468*4882a593Smuzhiyun         switch (LOWORD(wParam)) {
469*4882a593Smuzhiyun         case SB_TOP:
470*4882a593Smuzhiyun             si.nPos = si.nMin;
471*4882a593Smuzhiyun             break;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun         case SB_BOTTOM:
474*4882a593Smuzhiyun             si.nPos = si.nMax - si.nPage + 1;
475*4882a593Smuzhiyun             break;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun         case SB_LINEUP:
478*4882a593Smuzhiyun             si.nPos -= 1;
479*4882a593Smuzhiyun             break;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun         case SB_LINEDOWN:
482*4882a593Smuzhiyun             si.nPos += 1;
483*4882a593Smuzhiyun             break;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun         case SB_PAGEUP:
486*4882a593Smuzhiyun             si.nPos -= si.nPage;
487*4882a593Smuzhiyun             break;
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun         case SB_PAGEDOWN:
490*4882a593Smuzhiyun             si.nPos += si.nPage;
491*4882a593Smuzhiyun             break;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun         case SB_THUMBTRACK:
494*4882a593Smuzhiyun             si.nPos = si.nTrackPos;
495*4882a593Smuzhiyun             break;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun         default:
498*4882a593Smuzhiyun             break;
499*4882a593Smuzhiyun         }
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun         /*
502*4882a593Smuzhiyun          * We retrieve the position after setting it,
503*4882a593Smuzhiyun          * because Windows may adjust it.
504*4882a593Smuzhiyun          */
505*4882a593Smuzhiyun         si.fMask = SIF_POS;
506*4882a593Smuzhiyun         SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
507*4882a593Smuzhiyun         GetScrollInfo(hwnd, SB_VERT, &si);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun         /* Scroll the window if the position has changed */
510*4882a593Smuzhiyun         if (si.nPos != iVertPos) {
511*4882a593Smuzhiyun             /* Save the new offset for bit block transfers, etc. */
512*4882a593Smuzhiyun             s_pScreenInfo->dwYOffset = -si.nPos;
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun             /* Change displayed region in the window */
515*4882a593Smuzhiyun             ScrollWindowEx(hwnd,
516*4882a593Smuzhiyun                            0,
517*4882a593Smuzhiyun                            iVertPos - si.nPos,
518*4882a593Smuzhiyun                            NULL, NULL, NULL, NULL, SW_INVALIDATE);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun             /* Redraw the window contents */
521*4882a593Smuzhiyun             UpdateWindow(hwnd);
522*4882a593Smuzhiyun         }
523*4882a593Smuzhiyun     }
524*4882a593Smuzhiyun         return 0;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun     case WM_HSCROLL:
527*4882a593Smuzhiyun     {
528*4882a593Smuzhiyun         SCROLLINFO si;
529*4882a593Smuzhiyun         int iHorzPos;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun #if CYGDEBUG
532*4882a593Smuzhiyun         winDebug("winWindowProc - WM_HSCROLL\n");
533*4882a593Smuzhiyun #endif
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun         /* Get horizontal scroll bar info */
536*4882a593Smuzhiyun         si.cbSize = sizeof(si);
537*4882a593Smuzhiyun         si.fMask = SIF_ALL;
538*4882a593Smuzhiyun         GetScrollInfo(hwnd, SB_HORZ, &si);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun         /* Save the horizontal position for comparison later */
541*4882a593Smuzhiyun         iHorzPos = si.nPos;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun         /*
544*4882a593Smuzhiyun          * Don't forget:
545*4882a593Smuzhiyun          * moving the scrollbar to the RIGHT, scroll the content LEFT
546*4882a593Smuzhiyun          */
547*4882a593Smuzhiyun         switch (LOWORD(wParam)) {
548*4882a593Smuzhiyun         case SB_LEFT:
549*4882a593Smuzhiyun             si.nPos = si.nMin;
550*4882a593Smuzhiyun             break;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun         case SB_RIGHT:
553*4882a593Smuzhiyun             si.nPos = si.nMax - si.nPage + 1;
554*4882a593Smuzhiyun             break;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun         case SB_LINELEFT:
557*4882a593Smuzhiyun             si.nPos -= 1;
558*4882a593Smuzhiyun             break;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun         case SB_LINERIGHT:
561*4882a593Smuzhiyun             si.nPos += 1;
562*4882a593Smuzhiyun             break;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun         case SB_PAGELEFT:
565*4882a593Smuzhiyun             si.nPos -= si.nPage;
566*4882a593Smuzhiyun             break;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun         case SB_PAGERIGHT:
569*4882a593Smuzhiyun             si.nPos += si.nPage;
570*4882a593Smuzhiyun             break;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun         case SB_THUMBTRACK:
573*4882a593Smuzhiyun             si.nPos = si.nTrackPos;
574*4882a593Smuzhiyun             break;
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun         default:
577*4882a593Smuzhiyun             break;
578*4882a593Smuzhiyun         }
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun         /*
581*4882a593Smuzhiyun          * We retrieve the position after setting it,
582*4882a593Smuzhiyun          * because Windows may adjust it.
583*4882a593Smuzhiyun          */
584*4882a593Smuzhiyun         si.fMask = SIF_POS;
585*4882a593Smuzhiyun         SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
586*4882a593Smuzhiyun         GetScrollInfo(hwnd, SB_HORZ, &si);
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun         /* Scroll the window if the position has changed */
589*4882a593Smuzhiyun         if (si.nPos != iHorzPos) {
590*4882a593Smuzhiyun             /* Save the new offset for bit block transfers, etc. */
591*4882a593Smuzhiyun             s_pScreenInfo->dwXOffset = -si.nPos;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun             /* Change displayed region in the window */
594*4882a593Smuzhiyun             ScrollWindowEx(hwnd,
595*4882a593Smuzhiyun                            iHorzPos - si.nPos,
596*4882a593Smuzhiyun                            0, NULL, NULL, NULL, NULL, SW_INVALIDATE);
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun             /* Redraw the window contents */
599*4882a593Smuzhiyun             UpdateWindow(hwnd);
600*4882a593Smuzhiyun         }
601*4882a593Smuzhiyun     }
602*4882a593Smuzhiyun         return 0;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun     case WM_GETMINMAXINFO:
605*4882a593Smuzhiyun     {
606*4882a593Smuzhiyun         MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam;
607*4882a593Smuzhiyun         int iCaptionHeight;
608*4882a593Smuzhiyun         int iBorderHeight, iBorderWidth;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun #if CYGDEBUG
611*4882a593Smuzhiyun         winDebug("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %p\n",
612*4882a593Smuzhiyun                  s_pScreenInfo);
613*4882a593Smuzhiyun #endif
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun         /* Can't do anything without screen info */
616*4882a593Smuzhiyun         if (s_pScreenInfo == NULL
617*4882a593Smuzhiyun             || (s_pScreenInfo->iResizeMode != resizeWithScrollbars)
618*4882a593Smuzhiyun             || s_pScreenInfo->fFullScreen || !s_pScreenInfo->fDecoration
619*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
620*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
621*4882a593Smuzhiyun #endif
622*4882a593Smuzhiyun             || s_pScreenInfo->fRootless
623*4882a593Smuzhiyun             || s_pScreenInfo->fMultiWindow
624*4882a593Smuzhiyun             )
625*4882a593Smuzhiyun             break;
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun         /*
628*4882a593Smuzhiyun          * Here we can override the maximum tracking size, which
629*4882a593Smuzhiyun          * is the largest size that can be assigned to our window
630*4882a593Smuzhiyun          * via the sizing border.
631*4882a593Smuzhiyun          */
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun         /*
634*4882a593Smuzhiyun          * FIXME: Do we only need to do this once, since our visual size
635*4882a593Smuzhiyun          * does not change?  Does Windows store this value statically
636*4882a593Smuzhiyun          * once we have set it once?
637*4882a593Smuzhiyun          */
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun         /* Get the border and caption sizes */
640*4882a593Smuzhiyun         iCaptionHeight = GetSystemMetrics(SM_CYCAPTION);
641*4882a593Smuzhiyun         iBorderWidth = 2 * GetSystemMetrics(SM_CXSIZEFRAME);
642*4882a593Smuzhiyun         iBorderHeight = 2 * GetSystemMetrics(SM_CYSIZEFRAME);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun         /* Allow the full visual to be displayed */
645*4882a593Smuzhiyun         pMinMaxInfo->ptMaxTrackSize.x = s_pScreenInfo->dwWidth + iBorderWidth;
646*4882a593Smuzhiyun         pMinMaxInfo->ptMaxTrackSize.y
647*4882a593Smuzhiyun             = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight;
648*4882a593Smuzhiyun     }
649*4882a593Smuzhiyun         return 0;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun     case WM_ERASEBKGND:
652*4882a593Smuzhiyun #if CYGDEBUG
653*4882a593Smuzhiyun         winDebug("winWindowProc - WM_ERASEBKGND\n");
654*4882a593Smuzhiyun #endif
655*4882a593Smuzhiyun         /*
656*4882a593Smuzhiyun          * Pretend that we did erase the background but we don't care,
657*4882a593Smuzhiyun          * the application uses the full window estate. This avoids some
658*4882a593Smuzhiyun          * flickering when resizing.
659*4882a593Smuzhiyun          */
660*4882a593Smuzhiyun         return TRUE;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun     case WM_PAINT:
663*4882a593Smuzhiyun #if CYGDEBUG
664*4882a593Smuzhiyun         winDebug("winWindowProc - WM_PAINT\n");
665*4882a593Smuzhiyun #endif
666*4882a593Smuzhiyun         /* Only paint if we have privates and the server is enabled */
667*4882a593Smuzhiyun         if (s_pScreenPriv == NULL
668*4882a593Smuzhiyun             || !s_pScreenPriv->fEnabled
669*4882a593Smuzhiyun             || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive)
670*4882a593Smuzhiyun             || s_pScreenPriv->fBadDepth) {
671*4882a593Smuzhiyun             /* We don't want to paint */
672*4882a593Smuzhiyun             break;
673*4882a593Smuzhiyun         }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun         /* Break out here if we don't have a valid paint routine */
676*4882a593Smuzhiyun         if (s_pScreenPriv->pwinBltExposedRegions == NULL)
677*4882a593Smuzhiyun             break;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun         /* Call the engine dependent repainter */
680*4882a593Smuzhiyun         (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen);
681*4882a593Smuzhiyun         return 0;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun     case WM_PALETTECHANGED:
684*4882a593Smuzhiyun     {
685*4882a593Smuzhiyun #if CYGDEBUG
686*4882a593Smuzhiyun         winDebug("winWindowProc - WM_PALETTECHANGED\n");
687*4882a593Smuzhiyun #endif
688*4882a593Smuzhiyun         /*
689*4882a593Smuzhiyun          * Don't process if we don't have privates or a colormap,
690*4882a593Smuzhiyun          * or if we have an invalid depth.
691*4882a593Smuzhiyun          */
692*4882a593Smuzhiyun         if (s_pScreenPriv == NULL
693*4882a593Smuzhiyun             || s_pScreenPriv->pcmapInstalled == NULL
694*4882a593Smuzhiyun             || s_pScreenPriv->fBadDepth)
695*4882a593Smuzhiyun             break;
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun         /* Return if we caused the palette to change */
698*4882a593Smuzhiyun         if ((HWND) wParam == hwnd) {
699*4882a593Smuzhiyun             /* Redraw the screen */
700*4882a593Smuzhiyun             (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
701*4882a593Smuzhiyun             return 0;
702*4882a593Smuzhiyun         }
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun         /* Reinstall the windows palette */
705*4882a593Smuzhiyun         (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen);
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun         /* Redraw the screen */
708*4882a593Smuzhiyun         (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
709*4882a593Smuzhiyun         return 0;
710*4882a593Smuzhiyun     }
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun     case WM_MOUSEMOVE:
713*4882a593Smuzhiyun         /* We can't do anything without privates */
714*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
715*4882a593Smuzhiyun             break;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun         /* We can't do anything without g_pwinPointer */
718*4882a593Smuzhiyun         if (g_pwinPointer == NULL)
719*4882a593Smuzhiyun             break;
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun         /* Has the mouse pointer crossed screens? */
722*4882a593Smuzhiyun         if (s_pScreen != miPointerGetScreen(g_pwinPointer))
723*4882a593Smuzhiyun             miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
724*4882a593Smuzhiyun                                GET_X_LPARAM(lParam) - s_pScreenInfo->dwXOffset,
725*4882a593Smuzhiyun                                GET_Y_LPARAM(lParam) - s_pScreenInfo->dwYOffset);
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun         /* Are we tracking yet? */
728*4882a593Smuzhiyun         if (!s_fTracking) {
729*4882a593Smuzhiyun             TRACKMOUSEEVENT tme;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun             /* Setup data structure */
732*4882a593Smuzhiyun             ZeroMemory(&tme, sizeof(tme));
733*4882a593Smuzhiyun             tme.cbSize = sizeof(tme);
734*4882a593Smuzhiyun             tme.dwFlags = TME_LEAVE;
735*4882a593Smuzhiyun             tme.hwndTrack = hwnd;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun             /* Call the tracking function */
738*4882a593Smuzhiyun             if (!TrackMouseEvent(&tme))
739*4882a593Smuzhiyun                 ErrorF("winWindowProc - TrackMouseEvent failed\n");
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun             /* Flag that we are tracking now */
742*4882a593Smuzhiyun             s_fTracking = TRUE;
743*4882a593Smuzhiyun         }
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun         /* Hide or show the Windows mouse cursor */
746*4882a593Smuzhiyun         if (g_fSoftwareCursor && g_fCursor &&
747*4882a593Smuzhiyun             (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer)) {
748*4882a593Smuzhiyun             /* Hide Windows cursor */
749*4882a593Smuzhiyun             g_fCursor = FALSE;
750*4882a593Smuzhiyun             ShowCursor(FALSE);
751*4882a593Smuzhiyun         }
752*4882a593Smuzhiyun         else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive
753*4882a593Smuzhiyun                  && !s_pScreenInfo->fLessPointer) {
754*4882a593Smuzhiyun             /* Show Windows cursor */
755*4882a593Smuzhiyun             g_fCursor = TRUE;
756*4882a593Smuzhiyun             ShowCursor(TRUE);
757*4882a593Smuzhiyun         }
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun         /* Deliver absolute cursor position to X Server */
760*4882a593Smuzhiyun         winEnqueueMotion(GET_X_LPARAM(lParam) - s_pScreenInfo->dwXOffset,
761*4882a593Smuzhiyun                          GET_Y_LPARAM(lParam) - s_pScreenInfo->dwYOffset);
762*4882a593Smuzhiyun         return 0;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun     case WM_NCMOUSEMOVE:
765*4882a593Smuzhiyun         /*
766*4882a593Smuzhiyun          * We break instead of returning 0 since we need to call
767*4882a593Smuzhiyun          * DefWindowProc to get the mouse cursor changes
768*4882a593Smuzhiyun          * and min/max/close button highlighting in Windows XP.
769*4882a593Smuzhiyun          * The Platform SDK says that you should return 0 if you
770*4882a593Smuzhiyun          * process this message, but it fails to mention that you
771*4882a593Smuzhiyun          * will give up any default functionality if you do return 0.
772*4882a593Smuzhiyun          */
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun         /* We can't do anything without privates */
775*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
776*4882a593Smuzhiyun             break;
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun         /* Non-client mouse movement, show Windows cursor */
779*4882a593Smuzhiyun         if (g_fSoftwareCursor && !g_fCursor) {
780*4882a593Smuzhiyun             g_fCursor = TRUE;
781*4882a593Smuzhiyun             ShowCursor(TRUE);
782*4882a593Smuzhiyun         }
783*4882a593Smuzhiyun         break;
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun     case WM_MOUSELEAVE:
786*4882a593Smuzhiyun         /* Mouse has left our client area */
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun         /* Flag that we are no longer tracking */
789*4882a593Smuzhiyun         s_fTracking = FALSE;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun         /* Show the mouse cursor, if necessary */
792*4882a593Smuzhiyun         if (g_fSoftwareCursor && !g_fCursor) {
793*4882a593Smuzhiyun             g_fCursor = TRUE;
794*4882a593Smuzhiyun             ShowCursor(TRUE);
795*4882a593Smuzhiyun         }
796*4882a593Smuzhiyun         return 0;
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun     case WM_LBUTTONDBLCLK:
799*4882a593Smuzhiyun     case WM_LBUTTONDOWN:
800*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
801*4882a593Smuzhiyun             break;
802*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
803*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
804*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
805*4882a593Smuzhiyun #endif
806*4882a593Smuzhiyun             )
807*4882a593Smuzhiyun             SetCapture(hwnd);
808*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun     case WM_LBUTTONUP:
811*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
812*4882a593Smuzhiyun             break;
813*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
814*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
815*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
816*4882a593Smuzhiyun #endif
817*4882a593Smuzhiyun             )
818*4882a593Smuzhiyun             ReleaseCapture();
819*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun     case WM_MBUTTONDBLCLK:
822*4882a593Smuzhiyun     case WM_MBUTTONDOWN:
823*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
824*4882a593Smuzhiyun             break;
825*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
826*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
827*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
828*4882a593Smuzhiyun #endif
829*4882a593Smuzhiyun             )
830*4882a593Smuzhiyun             SetCapture(hwnd);
831*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun     case WM_MBUTTONUP:
834*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
835*4882a593Smuzhiyun             break;
836*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
837*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
838*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
839*4882a593Smuzhiyun #endif
840*4882a593Smuzhiyun             )
841*4882a593Smuzhiyun             ReleaseCapture();
842*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun     case WM_RBUTTONDBLCLK:
845*4882a593Smuzhiyun     case WM_RBUTTONDOWN:
846*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
847*4882a593Smuzhiyun             break;
848*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
849*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
850*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
851*4882a593Smuzhiyun #endif
852*4882a593Smuzhiyun             )
853*4882a593Smuzhiyun             SetCapture(hwnd);
854*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun     case WM_RBUTTONUP:
857*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
858*4882a593Smuzhiyun             break;
859*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
860*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
861*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
862*4882a593Smuzhiyun #endif
863*4882a593Smuzhiyun             )
864*4882a593Smuzhiyun             ReleaseCapture();
865*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun     case WM_XBUTTONDBLCLK:
868*4882a593Smuzhiyun     case WM_XBUTTONDOWN:
869*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
870*4882a593Smuzhiyun             break;
871*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
872*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
873*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
874*4882a593Smuzhiyun #endif
875*4882a593Smuzhiyun             )
876*4882a593Smuzhiyun             SetCapture(hwnd);
877*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
878*4882a593Smuzhiyun                                      wParam);
879*4882a593Smuzhiyun     case WM_XBUTTONUP:
880*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
881*4882a593Smuzhiyun             break;
882*4882a593Smuzhiyun         if (s_pScreenInfo->fRootless
883*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
884*4882a593Smuzhiyun             || s_pScreenInfo->fMWExtWM
885*4882a593Smuzhiyun #endif
886*4882a593Smuzhiyun             )
887*4882a593Smuzhiyun             ReleaseCapture();
888*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease,
889*4882a593Smuzhiyun                                      HIWORD(wParam) + 7, wParam);
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun     case WM_TIMER:
892*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
893*4882a593Smuzhiyun             break;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun         /* Branch on the timer id */
896*4882a593Smuzhiyun         switch (wParam) {
897*4882a593Smuzhiyun         case WIN_E3B_TIMER_ID:
898*4882a593Smuzhiyun             /* Send delayed button press */
899*4882a593Smuzhiyun             winMouseButtonsSendEvent(ButtonPress,
900*4882a593Smuzhiyun                                      s_pScreenPriv->iE3BCachedPress);
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun             /* Kill this timer */
903*4882a593Smuzhiyun             KillTimer(s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun             /* Clear screen privates flags */
906*4882a593Smuzhiyun             s_pScreenPriv->iE3BCachedPress = 0;
907*4882a593Smuzhiyun             break;
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun         case WIN_POLLING_MOUSE_TIMER_ID:
910*4882a593Smuzhiyun         {
911*4882a593Smuzhiyun             static POINT last_point;
912*4882a593Smuzhiyun             POINT point;
913*4882a593Smuzhiyun             WPARAM wL, wM, wR, wShift, wCtrl;
914*4882a593Smuzhiyun             LPARAM lPos;
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun             /* Get the current position of the mouse cursor */
917*4882a593Smuzhiyun             GetCursorPos(&point);
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun             /* Map from screen (-X, -Y) to root (0, 0) */
920*4882a593Smuzhiyun             point.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
921*4882a593Smuzhiyun             point.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun             /* If the mouse pointer has moved, deliver absolute cursor position to X Server */
924*4882a593Smuzhiyun             if (last_point.x != point.x || last_point.y != point.y) {
925*4882a593Smuzhiyun                 winEnqueueMotion(point.x, point.y);
926*4882a593Smuzhiyun                 last_point.x = point.x;
927*4882a593Smuzhiyun                 last_point.y = point.y;
928*4882a593Smuzhiyun             }
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun             /* Check if a button was released but we didn't see it */
931*4882a593Smuzhiyun             GetCursorPos(&point);
932*4882a593Smuzhiyun             wL = (GetKeyState(VK_LBUTTON) & 0x8000) ? MK_LBUTTON : 0;
933*4882a593Smuzhiyun             wM = (GetKeyState(VK_MBUTTON) & 0x8000) ? MK_MBUTTON : 0;
934*4882a593Smuzhiyun             wR = (GetKeyState(VK_RBUTTON) & 0x8000) ? MK_RBUTTON : 0;
935*4882a593Smuzhiyun             wShift = (GetKeyState(VK_SHIFT) & 0x8000) ? MK_SHIFT : 0;
936*4882a593Smuzhiyun             wCtrl = (GetKeyState(VK_CONTROL) & 0x8000) ? MK_CONTROL : 0;
937*4882a593Smuzhiyun             lPos = MAKELPARAM(point.x, point.y);
938*4882a593Smuzhiyun             if (g_fButton[0] && !wL)
939*4882a593Smuzhiyun                 PostMessage(hwnd, WM_LBUTTONUP, wCtrl | wM | wR | wShift, lPos);
940*4882a593Smuzhiyun             if (g_fButton[1] && !wM)
941*4882a593Smuzhiyun                 PostMessage(hwnd, WM_MBUTTONUP, wCtrl | wL | wR | wShift, lPos);
942*4882a593Smuzhiyun             if (g_fButton[2] && !wR)
943*4882a593Smuzhiyun                 PostMessage(hwnd, WM_RBUTTONUP, wCtrl | wL | wM | wShift, lPos);
944*4882a593Smuzhiyun         }
945*4882a593Smuzhiyun         }
946*4882a593Smuzhiyun         return 0;
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun     case WM_CTLCOLORSCROLLBAR:
949*4882a593Smuzhiyun         FatalError("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not "
950*4882a593Smuzhiyun                    "supposed to get this message.  Exiting.\n");
951*4882a593Smuzhiyun         return 0;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun     case WM_MOUSEWHEEL:
954*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
955*4882a593Smuzhiyun             break;
956*4882a593Smuzhiyun #if CYGDEBUG
957*4882a593Smuzhiyun         winDebug("winWindowProc - WM_MOUSEWHEEL\n");
958*4882a593Smuzhiyun #endif
959*4882a593Smuzhiyun         /* Button4 = WheelUp */
960*4882a593Smuzhiyun         /* Button5 = WheelDown */
961*4882a593Smuzhiyun         winMouseWheel(&(s_pScreenPriv->iDeltaZ), GET_WHEEL_DELTA_WPARAM(wParam), Button4, Button5);
962*4882a593Smuzhiyun         break;
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun     case WM_MOUSEHWHEEL:
965*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
966*4882a593Smuzhiyun             break;
967*4882a593Smuzhiyun #if CYGDEBUG
968*4882a593Smuzhiyun         winDebug("winWindowProc - WM_MOUSEHWHEEL\n");
969*4882a593Smuzhiyun #endif
970*4882a593Smuzhiyun         /* Button7 = TiltRight */
971*4882a593Smuzhiyun         /* Button6 = TiltLeft */
972*4882a593Smuzhiyun         winMouseWheel(&(s_pScreenPriv->iDeltaV), GET_WHEEL_DELTA_WPARAM(wParam), 7, 6);
973*4882a593Smuzhiyun         break;
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun     case WM_SETFOCUS:
976*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
977*4882a593Smuzhiyun             break;
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun         /* Restore the state of all mode keys */
980*4882a593Smuzhiyun         winRestoreModeKeyStates();
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun         /* Add the keyboard hook if possible */
983*4882a593Smuzhiyun         if (g_fKeyboardHookLL)
984*4882a593Smuzhiyun             g_fKeyboardHookLL = winInstallKeyboardHookLL();
985*4882a593Smuzhiyun         return 0;
986*4882a593Smuzhiyun 
987*4882a593Smuzhiyun     case WM_KILLFOCUS:
988*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
989*4882a593Smuzhiyun             break;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun         /* Release any pressed keys */
992*4882a593Smuzhiyun         winKeybdReleaseKeys();
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun         /* Remove our keyboard hook if it is installed */
995*4882a593Smuzhiyun         winRemoveKeyboardHookLL();
996*4882a593Smuzhiyun         return 0;
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun     case WM_SYSKEYDOWN:
999*4882a593Smuzhiyun     case WM_KEYDOWN:
1000*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1001*4882a593Smuzhiyun             break;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun         /*
1004*4882a593Smuzhiyun          * FIXME: Catching Alt-F4 like this is really terrible.  This should
1005*4882a593Smuzhiyun          * be generalized to handle other Windows keyboard signals.  Actually,
1006*4882a593Smuzhiyun          * the list keys to catch and the actions to perform when caught should
1007*4882a593Smuzhiyun          * be configurable; that way user's can customize the keys that they
1008*4882a593Smuzhiyun          * need to have passed through to their window manager or apps, or they
1009*4882a593Smuzhiyun          * can remap certain actions to new key codes that do not conflict
1010*4882a593Smuzhiyun          * with the X apps that they are using.  Yeah, that'll take awhile.
1011*4882a593Smuzhiyun          */
1012*4882a593Smuzhiyun         if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4
1013*4882a593Smuzhiyun              && (GetKeyState(VK_MENU) & 0x8000))
1014*4882a593Smuzhiyun             || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK
1015*4882a593Smuzhiyun                 && (GetKeyState(VK_MENU) & 0x8000)
1016*4882a593Smuzhiyun                 && (GetKeyState(VK_CONTROL) & 0x8000))) {
1017*4882a593Smuzhiyun             /*
1018*4882a593Smuzhiyun              * Better leave this message here, just in case some unsuspecting
1019*4882a593Smuzhiyun              * user enters Alt + F4 and is surprised when the application
1020*4882a593Smuzhiyun              * quits.
1021*4882a593Smuzhiyun              */
1022*4882a593Smuzhiyun             ErrorF("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n");
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun             /* Display Exit dialog */
1025*4882a593Smuzhiyun             winDisplayExitDialog(s_pScreenPriv);
1026*4882a593Smuzhiyun             return 0;
1027*4882a593Smuzhiyun         }
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun         /*
1030*4882a593Smuzhiyun          * Don't do anything for the Windows keys, as focus will soon
1031*4882a593Smuzhiyun          * be returned to Windows.  We may be able to trap the Windows keys,
1032*4882a593Smuzhiyun          * but we should determine if that is desirable before doing so.
1033*4882a593Smuzhiyun          */
1034*4882a593Smuzhiyun         if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
1035*4882a593Smuzhiyun             break;
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun         /* Discard fake Ctrl_L events that precede AltGR on non-US keyboards */
1038*4882a593Smuzhiyun         if (winIsFakeCtrl_L(message, wParam, lParam))
1039*4882a593Smuzhiyun             return 0;
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun         /*
1042*4882a593Smuzhiyun          * Discard presses generated from Windows auto-repeat
1043*4882a593Smuzhiyun          */
1044*4882a593Smuzhiyun         if (lParam & (1 << 30)) {
1045*4882a593Smuzhiyun             switch (wParam) {
1046*4882a593Smuzhiyun                 /* ago: Pressing LControl while RControl is pressed is
1047*4882a593Smuzhiyun                  * Indicated as repeat. Fix this!
1048*4882a593Smuzhiyun                  */
1049*4882a593Smuzhiyun             case VK_CONTROL:
1050*4882a593Smuzhiyun             case VK_SHIFT:
1051*4882a593Smuzhiyun                 if (winCheckKeyPressed(wParam, lParam))
1052*4882a593Smuzhiyun                     return 0;
1053*4882a593Smuzhiyun                 break;
1054*4882a593Smuzhiyun             default:
1055*4882a593Smuzhiyun                 return 0;
1056*4882a593Smuzhiyun             }
1057*4882a593Smuzhiyun         }
1058*4882a593Smuzhiyun 
1059*4882a593Smuzhiyun         /* Translate Windows key code to X scan code */
1060*4882a593Smuzhiyun         iScanCode = winTranslateKey(wParam, lParam);
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun         /* Ignore repeats for CapsLock */
1063*4882a593Smuzhiyun         if (wParam == VK_CAPITAL)
1064*4882a593Smuzhiyun             lParam = 1;
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun         /* Send the key event(s) */
1067*4882a593Smuzhiyun         for (i = 0; i < LOWORD(lParam); ++i)
1068*4882a593Smuzhiyun             winSendKeyEvent(iScanCode, TRUE);
1069*4882a593Smuzhiyun         return 0;
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun     case WM_SYSKEYUP:
1072*4882a593Smuzhiyun     case WM_KEYUP:
1073*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1074*4882a593Smuzhiyun             break;
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun         /*
1077*4882a593Smuzhiyun          * Don't do anything for the Windows keys, as focus will soon
1078*4882a593Smuzhiyun          * be returned to Windows.  We may be able to trap the Windows keys,
1079*4882a593Smuzhiyun          * but we should determine if that is desirable before doing so.
1080*4882a593Smuzhiyun          */
1081*4882a593Smuzhiyun         if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
1082*4882a593Smuzhiyun             break;
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun         /* Ignore the fake Ctrl_L that follows an AltGr release */
1085*4882a593Smuzhiyun         if (winIsFakeCtrl_L(message, wParam, lParam))
1086*4882a593Smuzhiyun             return 0;
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun         /* Enqueue a keyup event */
1089*4882a593Smuzhiyun         iScanCode = winTranslateKey(wParam, lParam);
1090*4882a593Smuzhiyun         winSendKeyEvent(iScanCode, FALSE);
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun         /* Release all pressed shift keys */
1093*4882a593Smuzhiyun         if (wParam == VK_SHIFT)
1094*4882a593Smuzhiyun             winFixShiftKeys(iScanCode);
1095*4882a593Smuzhiyun         return 0;
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun     case WM_ACTIVATE:
1098*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1099*4882a593Smuzhiyun             break;
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun         /* TODO: Override display of window when we have a bad depth */
1102*4882a593Smuzhiyun         if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth) {
1103*4882a593Smuzhiyun             ErrorF("winWindowProc - WM_ACTIVATE - Bad depth, trying "
1104*4882a593Smuzhiyun                    "to override window activation\n");
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun             /* Minimize the window */
1107*4882a593Smuzhiyun             ShowWindow(hwnd, SW_MINIMIZE);
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun             /* Display dialog box */
1110*4882a593Smuzhiyun             if (g_hDlgDepthChange != NULL) {
1111*4882a593Smuzhiyun                 /* Make the existing dialog box active */
1112*4882a593Smuzhiyun                 SetActiveWindow(g_hDlgDepthChange);
1113*4882a593Smuzhiyun             }
1114*4882a593Smuzhiyun             else {
1115*4882a593Smuzhiyun                 /* TODO: Recreate the dialog box and bring to the top */
1116*4882a593Smuzhiyun                 ShowWindow(g_hDlgDepthChange, SW_SHOWDEFAULT);
1117*4882a593Smuzhiyun             }
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun             /* Don't do any other processing of this message */
1120*4882a593Smuzhiyun             return 0;
1121*4882a593Smuzhiyun         }
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun #if CYGDEBUG
1124*4882a593Smuzhiyun         winDebug("winWindowProc - WM_ACTIVATE\n");
1125*4882a593Smuzhiyun #endif
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun         /*
1128*4882a593Smuzhiyun          * Focus is being changed to another window.
1129*4882a593Smuzhiyun          * The other window may or may not belong to
1130*4882a593Smuzhiyun          * our process.
1131*4882a593Smuzhiyun          */
1132*4882a593Smuzhiyun 
1133*4882a593Smuzhiyun         /* Clear any lingering wheel delta */
1134*4882a593Smuzhiyun         s_pScreenPriv->iDeltaZ = 0;
1135*4882a593Smuzhiyun         s_pScreenPriv->iDeltaV = 0;
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun         /* Reshow the Windows mouse cursor if we are being deactivated */
1138*4882a593Smuzhiyun         if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE && !g_fCursor) {
1139*4882a593Smuzhiyun             /* Show Windows cursor */
1140*4882a593Smuzhiyun             g_fCursor = TRUE;
1141*4882a593Smuzhiyun             ShowCursor(TRUE);
1142*4882a593Smuzhiyun         }
1143*4882a593Smuzhiyun         return 0;
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun     case WM_ACTIVATEAPP:
1146*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
1147*4882a593Smuzhiyun             break;
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun #if CYGDEBUG || TRUE
1150*4882a593Smuzhiyun         winDebug("winWindowProc - WM_ACTIVATEAPP\n");
1151*4882a593Smuzhiyun #endif
1152*4882a593Smuzhiyun 
1153*4882a593Smuzhiyun         /* Activate or deactivate */
1154*4882a593Smuzhiyun         s_pScreenPriv->fActive = wParam;
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun         /* Reshow the Windows mouse cursor if we are being deactivated */
1157*4882a593Smuzhiyun         if (g_fSoftwareCursor && !s_pScreenPriv->fActive && !g_fCursor) {
1158*4882a593Smuzhiyun             /* Show Windows cursor */
1159*4882a593Smuzhiyun             g_fCursor = TRUE;
1160*4882a593Smuzhiyun             ShowCursor(TRUE);
1161*4882a593Smuzhiyun         }
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun         /* Make sure the clipboard chain is ok. */
1164*4882a593Smuzhiyun         winFixClipboardChain();
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun         /* Call engine specific screen activation/deactivation function */
1167*4882a593Smuzhiyun         (*s_pScreenPriv->pwinActivateApp) (s_pScreen);
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun #ifdef XWIN_MULTIWINDOWEXTWM
1170*4882a593Smuzhiyun         if (s_pScreenPriv->fActive) {
1171*4882a593Smuzhiyun             /* Restack all window unless using built-in wm. */
1172*4882a593Smuzhiyun             if (s_pScreenInfo->fMWExtWM)
1173*4882a593Smuzhiyun                 winMWExtWMRestackWindows(s_pScreen);
1174*4882a593Smuzhiyun         }
1175*4882a593Smuzhiyun #endif
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun         return 0;
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun     case WM_COMMAND:
1180*4882a593Smuzhiyun         switch (LOWORD(wParam)) {
1181*4882a593Smuzhiyun         case ID_APP_EXIT:
1182*4882a593Smuzhiyun             /* Display Exit dialog */
1183*4882a593Smuzhiyun             winDisplayExitDialog(s_pScreenPriv);
1184*4882a593Smuzhiyun             return 0;
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun         case ID_APP_HIDE_ROOT:
1187*4882a593Smuzhiyun             if (s_pScreenPriv->fRootWindowShown)
1188*4882a593Smuzhiyun                 ShowWindow(s_pScreenPriv->hwndScreen, SW_HIDE);
1189*4882a593Smuzhiyun             else
1190*4882a593Smuzhiyun                 ShowWindow(s_pScreenPriv->hwndScreen, SW_SHOW);
1191*4882a593Smuzhiyun             s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown;
1192*4882a593Smuzhiyun             return 0;
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun         case ID_APP_MONITOR_PRIMARY:
1195*4882a593Smuzhiyun             fPrimarySelection = !fPrimarySelection;
1196*4882a593Smuzhiyun             return 0;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun         case ID_APP_ABOUT:
1199*4882a593Smuzhiyun             /* Display the About box */
1200*4882a593Smuzhiyun             winDisplayAboutDialog(s_pScreenPriv);
1201*4882a593Smuzhiyun             return 0;
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun         default:
1204*4882a593Smuzhiyun             /* It's probably one of the custom menus... */
1205*4882a593Smuzhiyun             if (HandleCustomWM_COMMAND(0, LOWORD(wParam), s_pScreenPriv))
1206*4882a593Smuzhiyun                 return 0;
1207*4882a593Smuzhiyun         }
1208*4882a593Smuzhiyun         break;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun     case WM_GIVEUP:
1211*4882a593Smuzhiyun         /* Tell X that we are giving up */
1212*4882a593Smuzhiyun         if (s_pScreenInfo->fMultiWindow)
1213*4882a593Smuzhiyun             winDeinitMultiWindowWM();
1214*4882a593Smuzhiyun         GiveUp(0);
1215*4882a593Smuzhiyun         return 0;
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun     case WM_CLOSE:
1218*4882a593Smuzhiyun         /* Display Exit dialog */
1219*4882a593Smuzhiyun         winDisplayExitDialog(s_pScreenPriv);
1220*4882a593Smuzhiyun         return 0;
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun     case WM_SETCURSOR:
1223*4882a593Smuzhiyun         if (LOWORD(lParam) == HTCLIENT) {
1224*4882a593Smuzhiyun             if (!g_fSoftwareCursor)
1225*4882a593Smuzhiyun                 SetCursor(s_pScreenPriv->cursor.handle);
1226*4882a593Smuzhiyun             return TRUE;
1227*4882a593Smuzhiyun         }
1228*4882a593Smuzhiyun         break;
1229*4882a593Smuzhiyun 
1230*4882a593Smuzhiyun     default:
1231*4882a593Smuzhiyun         if (message == s_uTaskbarRestart) {
1232*4882a593Smuzhiyun             winInitNotifyIcon(s_pScreenPriv);
1233*4882a593Smuzhiyun         }
1234*4882a593Smuzhiyun         break;
1235*4882a593Smuzhiyun     }
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun     return DefWindowProc(hwnd, message, wParam, lParam);
1238*4882a593Smuzhiyun }
1239