xref: /OK3568_Linux_fs/external/xserver/hw/xwin/winmultiwindowwndproc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3*4882a593Smuzhiyun  *Copyright (C) Colin Harrison 2005-2008
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *Permission is hereby granted, free of charge, to any person obtaining
6*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
7*4882a593Smuzhiyun  *"Software"), to deal in the Software without restriction, including
8*4882a593Smuzhiyun  *without limitation the rights to use, copy, modify, merge, publish,
9*4882a593Smuzhiyun  *distribute, sublicense, and/or sell copies of the Software, and to
10*4882a593Smuzhiyun  *permit persons to whom the Software is furnished to do so, subject to
11*4882a593Smuzhiyun  *the following conditions:
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  *The above copyright notice and this permission notice shall be
14*4882a593Smuzhiyun  *included in all copies or substantial portions of the Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*4882a593Smuzhiyun  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*4882a593Smuzhiyun  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*4882a593Smuzhiyun  *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20*4882a593Smuzhiyun  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21*4882a593Smuzhiyun  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22*4882a593Smuzhiyun  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  *Except as contained in this notice, the name of the XFree86 Project
25*4882a593Smuzhiyun  *shall not be used in advertising or otherwise to promote the sale, use
26*4882a593Smuzhiyun  *or other dealings in this Software without prior written authorization
27*4882a593Smuzhiyun  *from the XFree86 Project.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Authors:	Kensuke Matsuzaki
30*4882a593Smuzhiyun  *		Earle F. Philhower, III
31*4882a593Smuzhiyun  *		Harold L Hunt II
32*4882a593Smuzhiyun  *              Colin Harrison
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 "dixevents.h"
40*4882a593Smuzhiyun #include "winmultiwindowclass.h"
41*4882a593Smuzhiyun #include "winprefs.h"
42*4882a593Smuzhiyun #include "winmsg.h"
43*4882a593Smuzhiyun #include "inputstr.h"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun  * Local globals
49*4882a593Smuzhiyun  */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun static UINT_PTR g_uipMousePollingTimerID = 0;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun  * Constant defines
55*4882a593Smuzhiyun  */
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define WIN_MULTIWINDOW_SHAPE		YES
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun  * ConstrainSize - Taken from TWM sources - Respects hints for sizing
61*4882a593Smuzhiyun  */
62*4882a593Smuzhiyun #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
63*4882a593Smuzhiyun static void
ConstrainSize(WinXSizeHints hints,int * widthp,int * heightp)64*4882a593Smuzhiyun ConstrainSize(WinXSizeHints hints, int *widthp, int *heightp)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun     int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
67*4882a593Smuzhiyun     int baseWidth, baseHeight;
68*4882a593Smuzhiyun     int dwidth = *widthp, dheight = *heightp;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun     if (hints.flags & PMinSize) {
71*4882a593Smuzhiyun         minWidth = hints.min_width;
72*4882a593Smuzhiyun         minHeight = hints.min_height;
73*4882a593Smuzhiyun     }
74*4882a593Smuzhiyun     else if (hints.flags & PBaseSize) {
75*4882a593Smuzhiyun         minWidth = hints.base_width;
76*4882a593Smuzhiyun         minHeight = hints.base_height;
77*4882a593Smuzhiyun     }
78*4882a593Smuzhiyun     else
79*4882a593Smuzhiyun         minWidth = minHeight = 1;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun     if (hints.flags & PBaseSize) {
82*4882a593Smuzhiyun         baseWidth = hints.base_width;
83*4882a593Smuzhiyun         baseHeight = hints.base_height;
84*4882a593Smuzhiyun     }
85*4882a593Smuzhiyun     else if (hints.flags & PMinSize) {
86*4882a593Smuzhiyun         baseWidth = hints.min_width;
87*4882a593Smuzhiyun         baseHeight = hints.min_height;
88*4882a593Smuzhiyun     }
89*4882a593Smuzhiyun     else
90*4882a593Smuzhiyun         baseWidth = baseHeight = 0;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun     if (hints.flags & PMaxSize) {
93*4882a593Smuzhiyun         maxWidth = hints.max_width;
94*4882a593Smuzhiyun         maxHeight = hints.max_height;
95*4882a593Smuzhiyun     }
96*4882a593Smuzhiyun     else {
97*4882a593Smuzhiyun         maxWidth = MAXINT;
98*4882a593Smuzhiyun         maxHeight = MAXINT;
99*4882a593Smuzhiyun     }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun     if (hints.flags & PResizeInc) {
102*4882a593Smuzhiyun         xinc = hints.width_inc;
103*4882a593Smuzhiyun         yinc = hints.height_inc;
104*4882a593Smuzhiyun     }
105*4882a593Smuzhiyun     else
106*4882a593Smuzhiyun         xinc = yinc = 1;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun     /*
109*4882a593Smuzhiyun      * First, clamp to min and max values
110*4882a593Smuzhiyun      */
111*4882a593Smuzhiyun     if (dwidth < minWidth)
112*4882a593Smuzhiyun         dwidth = minWidth;
113*4882a593Smuzhiyun     if (dheight < minHeight)
114*4882a593Smuzhiyun         dheight = minHeight;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun     if (dwidth > maxWidth)
117*4882a593Smuzhiyun         dwidth = maxWidth;
118*4882a593Smuzhiyun     if (dheight > maxHeight)
119*4882a593Smuzhiyun         dheight = maxHeight;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun     /*
122*4882a593Smuzhiyun      * Second, fit to base + N * inc
123*4882a593Smuzhiyun      */
124*4882a593Smuzhiyun     dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
125*4882a593Smuzhiyun     dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     /*
128*4882a593Smuzhiyun      * Third, adjust for aspect ratio
129*4882a593Smuzhiyun      */
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     /*
132*4882a593Smuzhiyun      * The math looks like this:
133*4882a593Smuzhiyun      *
134*4882a593Smuzhiyun      * minAspectX    dwidth     maxAspectX
135*4882a593Smuzhiyun      * ---------- <= ------- <= ----------
136*4882a593Smuzhiyun      * minAspectY    dheight    maxAspectY
137*4882a593Smuzhiyun      *
138*4882a593Smuzhiyun      * If that is multiplied out, then the width and height are
139*4882a593Smuzhiyun      * invalid in the following situations:
140*4882a593Smuzhiyun      *
141*4882a593Smuzhiyun      * minAspectX * dheight > minAspectY * dwidth
142*4882a593Smuzhiyun      * maxAspectX * dheight < maxAspectY * dwidth
143*4882a593Smuzhiyun      *
144*4882a593Smuzhiyun      */
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun     if (hints.flags & PAspect) {
147*4882a593Smuzhiyun         if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) {
148*4882a593Smuzhiyun             delta =
149*4882a593Smuzhiyun                 makemult(hints.min_aspect.x * dheight / hints.min_aspect.y -
150*4882a593Smuzhiyun                          dwidth, xinc);
151*4882a593Smuzhiyun             if (dwidth + delta <= maxWidth)
152*4882a593Smuzhiyun                 dwidth += delta;
153*4882a593Smuzhiyun             else {
154*4882a593Smuzhiyun                 delta =
155*4882a593Smuzhiyun                     makemult(dheight -
156*4882a593Smuzhiyun                              dwidth * hints.min_aspect.y / hints.min_aspect.x,
157*4882a593Smuzhiyun                              yinc);
158*4882a593Smuzhiyun                 if (dheight - delta >= minHeight)
159*4882a593Smuzhiyun                     dheight -= delta;
160*4882a593Smuzhiyun             }
161*4882a593Smuzhiyun         }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun         if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) {
164*4882a593Smuzhiyun             delta =
165*4882a593Smuzhiyun                 makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x -
166*4882a593Smuzhiyun                          dheight, yinc);
167*4882a593Smuzhiyun             if (dheight + delta <= maxHeight)
168*4882a593Smuzhiyun                 dheight += delta;
169*4882a593Smuzhiyun             else {
170*4882a593Smuzhiyun                 delta =
171*4882a593Smuzhiyun                     makemult(dwidth -
172*4882a593Smuzhiyun                              hints.max_aspect.x * dheight / hints.max_aspect.y,
173*4882a593Smuzhiyun                              xinc);
174*4882a593Smuzhiyun                 if (dwidth - delta >= minWidth)
175*4882a593Smuzhiyun                     dwidth -= delta;
176*4882a593Smuzhiyun             }
177*4882a593Smuzhiyun         }
178*4882a593Smuzhiyun     }
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun     /* Return computed values */
181*4882a593Smuzhiyun     *widthp = dwidth;
182*4882a593Smuzhiyun     *heightp = dheight;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun #undef makemult
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /*
188*4882a593Smuzhiyun  * ValidateSizing - Ensures size request respects hints
189*4882a593Smuzhiyun  */
190*4882a593Smuzhiyun static int
ValidateSizing(HWND hwnd,WindowPtr pWin,WPARAM wParam,LPARAM lParam)191*4882a593Smuzhiyun ValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun     WinXSizeHints sizeHints;
194*4882a593Smuzhiyun     RECT *rect;
195*4882a593Smuzhiyun     int iWidth, iHeight;
196*4882a593Smuzhiyun     RECT rcClient, rcWindow;
197*4882a593Smuzhiyun     int iBorderWidthX, iBorderWidthY;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun     /* Invalid input checking */
200*4882a593Smuzhiyun     if (pWin == NULL || lParam == 0)
201*4882a593Smuzhiyun         return FALSE;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     /* No size hints, no checking */
204*4882a593Smuzhiyun     if (!winMultiWindowGetWMNormalHints(pWin, &sizeHints))
205*4882a593Smuzhiyun         return FALSE;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     /* Avoid divide-by-zero */
208*4882a593Smuzhiyun     if (sizeHints.flags & PResizeInc) {
209*4882a593Smuzhiyun         if (sizeHints.width_inc == 0)
210*4882a593Smuzhiyun             sizeHints.width_inc = 1;
211*4882a593Smuzhiyun         if (sizeHints.height_inc == 0)
212*4882a593Smuzhiyun             sizeHints.height_inc = 1;
213*4882a593Smuzhiyun     }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun     rect = (RECT *) lParam;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun     iWidth = rect->right - rect->left;
218*4882a593Smuzhiyun     iHeight = rect->bottom - rect->top;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun     /* Now remove size of any borders and title bar */
221*4882a593Smuzhiyun     GetClientRect(hwnd, &rcClient);
222*4882a593Smuzhiyun     GetWindowRect(hwnd, &rcWindow);
223*4882a593Smuzhiyun     iBorderWidthX =
224*4882a593Smuzhiyun         (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
225*4882a593Smuzhiyun     iBorderWidthY =
226*4882a593Smuzhiyun         (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
227*4882a593Smuzhiyun     iWidth -= iBorderWidthX;
228*4882a593Smuzhiyun     iHeight -= iBorderWidthY;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun     /* Constrain the size to legal values */
231*4882a593Smuzhiyun     ConstrainSize(sizeHints, &iWidth, &iHeight);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun     /* Add back the size of borders and title bar */
234*4882a593Smuzhiyun     iWidth += iBorderWidthX;
235*4882a593Smuzhiyun     iHeight += iBorderWidthY;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     /* Adjust size according to where we're dragging from */
238*4882a593Smuzhiyun     switch (wParam) {
239*4882a593Smuzhiyun     case WMSZ_TOP:
240*4882a593Smuzhiyun     case WMSZ_TOPRIGHT:
241*4882a593Smuzhiyun     case WMSZ_BOTTOM:
242*4882a593Smuzhiyun     case WMSZ_BOTTOMRIGHT:
243*4882a593Smuzhiyun     case WMSZ_RIGHT:
244*4882a593Smuzhiyun         rect->right = rect->left + iWidth;
245*4882a593Smuzhiyun         break;
246*4882a593Smuzhiyun     default:
247*4882a593Smuzhiyun         rect->left = rect->right - iWidth;
248*4882a593Smuzhiyun         break;
249*4882a593Smuzhiyun     }
250*4882a593Smuzhiyun     switch (wParam) {
251*4882a593Smuzhiyun     case WMSZ_BOTTOM:
252*4882a593Smuzhiyun     case WMSZ_BOTTOMRIGHT:
253*4882a593Smuzhiyun     case WMSZ_BOTTOMLEFT:
254*4882a593Smuzhiyun     case WMSZ_RIGHT:
255*4882a593Smuzhiyun     case WMSZ_LEFT:
256*4882a593Smuzhiyun         rect->bottom = rect->top + iHeight;
257*4882a593Smuzhiyun         break;
258*4882a593Smuzhiyun     default:
259*4882a593Smuzhiyun         rect->top = rect->bottom - iHeight;
260*4882a593Smuzhiyun         break;
261*4882a593Smuzhiyun     }
262*4882a593Smuzhiyun     return TRUE;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun extern Bool winInDestroyWindowsWindow;
266*4882a593Smuzhiyun static Bool winInRaiseWindow = FALSE;
267*4882a593Smuzhiyun static void
winRaiseWindow(WindowPtr pWin)268*4882a593Smuzhiyun winRaiseWindow(WindowPtr pWin)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun     if (!winInDestroyWindowsWindow && !winInRaiseWindow) {
271*4882a593Smuzhiyun         BOOL oldstate = winInRaiseWindow;
272*4882a593Smuzhiyun         XID vlist[1] = { 0 };
273*4882a593Smuzhiyun         winInRaiseWindow = TRUE;
274*4882a593Smuzhiyun         /* Call configure window directly to make sure it gets processed
275*4882a593Smuzhiyun          * in time
276*4882a593Smuzhiyun          */
277*4882a593Smuzhiyun         ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
278*4882a593Smuzhiyun         winInRaiseWindow = oldstate;
279*4882a593Smuzhiyun     }
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun static
283*4882a593Smuzhiyun     void
winStartMousePolling(winPrivScreenPtr s_pScreenPriv)284*4882a593Smuzhiyun winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun     /*
287*4882a593Smuzhiyun      * Timer to poll mouse position.  This is needed to make
288*4882a593Smuzhiyun      * programs like xeyes follow the mouse properly when the
289*4882a593Smuzhiyun      * mouse pointer is outside of any X window.
290*4882a593Smuzhiyun      */
291*4882a593Smuzhiyun     if (g_uipMousePollingTimerID == 0)
292*4882a593Smuzhiyun         g_uipMousePollingTimerID = SetTimer(s_pScreenPriv->hwndScreen,
293*4882a593Smuzhiyun                                             WIN_POLLING_MOUSE_TIMER_ID,
294*4882a593Smuzhiyun                                             MOUSE_POLLING_INTERVAL, NULL);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun /*
298*4882a593Smuzhiyun  * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
299*4882a593Smuzhiyun  */
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun LRESULT CALLBACK
winTopLevelWindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)302*4882a593Smuzhiyun winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun     POINT ptMouse;
305*4882a593Smuzhiyun     HDC hdcUpdate;
306*4882a593Smuzhiyun     PAINTSTRUCT ps;
307*4882a593Smuzhiyun     WindowPtr pWin = NULL;
308*4882a593Smuzhiyun     winPrivWinPtr pWinPriv = NULL;
309*4882a593Smuzhiyun     ScreenPtr s_pScreen = NULL;
310*4882a593Smuzhiyun     winPrivScreenPtr s_pScreenPriv = NULL;
311*4882a593Smuzhiyun     winScreenInfo *s_pScreenInfo = NULL;
312*4882a593Smuzhiyun     HWND hwndScreen = NULL;
313*4882a593Smuzhiyun     DrawablePtr pDraw = NULL;
314*4882a593Smuzhiyun     winWMMessageRec wmMsg;
315*4882a593Smuzhiyun     Bool fWMMsgInitialized = FALSE;
316*4882a593Smuzhiyun     static Bool s_fTracking = FALSE;
317*4882a593Smuzhiyun     Bool needRestack = FALSE;
318*4882a593Smuzhiyun     LRESULT ret;
319*4882a593Smuzhiyun     static Bool hasEnteredSizeMove = FALSE;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun #if CYGDEBUG
322*4882a593Smuzhiyun     winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
323*4882a593Smuzhiyun                          lParam);
324*4882a593Smuzhiyun #endif
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun     /* Check if the Windows window property for our X window pointer is valid */
327*4882a593Smuzhiyun     if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) {
328*4882a593Smuzhiyun         /* Our X window pointer is valid */
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun         /* Get pointers to the drawable and the screen */
331*4882a593Smuzhiyun         pDraw = &pWin->drawable;
332*4882a593Smuzhiyun         s_pScreen = pWin->drawable.pScreen;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun         /* Get a pointer to our window privates */
335*4882a593Smuzhiyun         pWinPriv = winGetWindowPriv(pWin);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun         /* Get pointers to our screen privates and screen info */
338*4882a593Smuzhiyun         s_pScreenPriv = pWinPriv->pScreenPriv;
339*4882a593Smuzhiyun         s_pScreenInfo = s_pScreenPriv->pScreenInfo;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun         /* Get the handle for our screen-sized window */
342*4882a593Smuzhiyun         hwndScreen = s_pScreenPriv->hwndScreen;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun         /* */
345*4882a593Smuzhiyun         wmMsg.msg = 0;
346*4882a593Smuzhiyun         wmMsg.hwndWindow = hwnd;
347*4882a593Smuzhiyun         wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun         wmMsg.iX = pDraw->x;
350*4882a593Smuzhiyun         wmMsg.iY = pDraw->y;
351*4882a593Smuzhiyun         wmMsg.iWidth = pDraw->width;
352*4882a593Smuzhiyun         wmMsg.iHeight = pDraw->height;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun         fWMMsgInitialized = TRUE;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun #if 0
357*4882a593Smuzhiyun         /*
358*4882a593Smuzhiyun          * Print some debugging information
359*4882a593Smuzhiyun          */
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun         ErrorF("hWnd %08X\n", hwnd);
362*4882a593Smuzhiyun         ErrorF("pWin %08X\n", pWin);
363*4882a593Smuzhiyun         ErrorF("pDraw %08X\n", pDraw);
364*4882a593Smuzhiyun         ErrorF("\ttype %08X\n", pWin->drawable.type);
365*4882a593Smuzhiyun         ErrorF("\tclass %08X\n", pWin->drawable.class);
366*4882a593Smuzhiyun         ErrorF("\tdepth %08X\n", pWin->drawable.depth);
367*4882a593Smuzhiyun         ErrorF("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
368*4882a593Smuzhiyun         ErrorF("\tid %08X\n", pWin->drawable.id);
369*4882a593Smuzhiyun         ErrorF("\tx %08X\n", pWin->drawable.x);
370*4882a593Smuzhiyun         ErrorF("\ty %08X\n", pWin->drawable.y);
371*4882a593Smuzhiyun         ErrorF("\twidth %08X\n", pWin->drawable.width);
372*4882a593Smuzhiyun         ErrorF("\thenght %08X\n", pWin->drawable.height);
373*4882a593Smuzhiyun         ErrorF("\tpScreen %08X\n", pWin->drawable.pScreen);
374*4882a593Smuzhiyun         ErrorF("\tserialNumber %08X\n", pWin->drawable.serialNumber);
375*4882a593Smuzhiyun         ErrorF("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
376*4882a593Smuzhiyun         ErrorF("pWinPriv %08X\n", pWinPriv);
377*4882a593Smuzhiyun         ErrorF("s_pScreenPriv %08X\n", s_pScreenPriv);
378*4882a593Smuzhiyun         ErrorF("s_pScreenInfo %08X\n", s_pScreenInfo);
379*4882a593Smuzhiyun         ErrorF("hwndScreen %08X\n", hwndScreen);
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun     }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun     /* Branch on message type */
384*4882a593Smuzhiyun     switch (message) {
385*4882a593Smuzhiyun     case WM_CREATE:
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun         /* */
388*4882a593Smuzhiyun         SetProp(hwnd,
389*4882a593Smuzhiyun                 WIN_WINDOW_PROP,
390*4882a593Smuzhiyun                 (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun         /* */
393*4882a593Smuzhiyun         SetProp(hwnd,
394*4882a593Smuzhiyun                 WIN_WID_PROP,
395*4882a593Smuzhiyun                 (HANDLE) (INT_PTR) winGetWindowID(((LPCREATESTRUCT) lParam)->
396*4882a593Smuzhiyun                                                   lpCreateParams));
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun         /*
399*4882a593Smuzhiyun          * Make X windows' Z orders sync with Windows windows because
400*4882a593Smuzhiyun          * there can be AlwaysOnTop windows overlapped on the window
401*4882a593Smuzhiyun          * currently being created.
402*4882a593Smuzhiyun          */
403*4882a593Smuzhiyun         winReorderWindowsMultiWindow();
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun         /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
406*4882a593Smuzhiyun         {
407*4882a593Smuzhiyun             RECT rWindow;
408*4882a593Smuzhiyun             HRGN hRgnWindow;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun             GetWindowRect(hwnd, &rWindow);
411*4882a593Smuzhiyun             hRgnWindow = CreateRectRgnIndirect(&rWindow);
412*4882a593Smuzhiyun             SetWindowRgn(hwnd, hRgnWindow, TRUE);
413*4882a593Smuzhiyun             DeleteObject(hRgnWindow);
414*4882a593Smuzhiyun         }
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun         SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun         return 0;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     case WM_INIT_SYS_MENU:
421*4882a593Smuzhiyun         /*
422*4882a593Smuzhiyun          * Add whatever the setup file wants to for this window
423*4882a593Smuzhiyun          */
424*4882a593Smuzhiyun         SetupSysMenu(hwnd);
425*4882a593Smuzhiyun         return 0;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun     case WM_SYSCOMMAND:
428*4882a593Smuzhiyun         /*
429*4882a593Smuzhiyun          * Any window menu items go through here
430*4882a593Smuzhiyun          */
431*4882a593Smuzhiyun         if (HandleCustomWM_COMMAND(hwnd, LOWORD(wParam), s_pScreenPriv)) {
432*4882a593Smuzhiyun             /* Don't pass customized menus to DefWindowProc */
433*4882a593Smuzhiyun             return 0;
434*4882a593Smuzhiyun         }
435*4882a593Smuzhiyun         if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) {
436*4882a593Smuzhiyun             WINDOWPLACEMENT wndpl;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun             wndpl.length = sizeof(wndpl);
439*4882a593Smuzhiyun             if (GetWindowPlacement(hwnd, &wndpl) &&
440*4882a593Smuzhiyun                 wndpl.showCmd == SW_SHOWMINIMIZED)
441*4882a593Smuzhiyun                 needRestack = TRUE;
442*4882a593Smuzhiyun         }
443*4882a593Smuzhiyun         break;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun     case WM_INITMENU:
446*4882a593Smuzhiyun         /* Checks/Unchecks any menu items before they are displayed */
447*4882a593Smuzhiyun         HandleCustomWM_INITMENU(hwnd, (HMENU)wParam);
448*4882a593Smuzhiyun         break;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun     case WM_ERASEBKGND:
451*4882a593Smuzhiyun         /*
452*4882a593Smuzhiyun          * Pretend that we did erase the background but we don't care,
453*4882a593Smuzhiyun          * since we repaint the entire region anyhow
454*4882a593Smuzhiyun          * This avoids some flickering when resizing.
455*4882a593Smuzhiyun          */
456*4882a593Smuzhiyun         return TRUE;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun     case WM_PAINT:
459*4882a593Smuzhiyun         /* Only paint if our window handle is valid */
460*4882a593Smuzhiyun         if (hwndScreen == NULL)
461*4882a593Smuzhiyun             break;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun         /* BeginPaint gives us an hdc that clips to the invalidated region */
464*4882a593Smuzhiyun         hdcUpdate = BeginPaint(hwnd, &ps);
465*4882a593Smuzhiyun         /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
466*4882a593Smuzhiyun         if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
467*4882a593Smuzhiyun             ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
468*4882a593Smuzhiyun             EndPaint(hwnd, &ps);
469*4882a593Smuzhiyun             return 0;
470*4882a593Smuzhiyun         }
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun #ifdef XWIN_GLX_WINDOWS
473*4882a593Smuzhiyun         if (pWinPriv->fWglUsed) {
474*4882a593Smuzhiyun             /*
475*4882a593Smuzhiyun                For regions which are being drawn by GL, the shadow framebuffer doesn't have the
476*4882a593Smuzhiyun                correct bits, so don't bitblt from the shadow framebuffer
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun                XXX: For now, just leave it alone, but ideally we want to send an expose event to
479*4882a593Smuzhiyun                the window so it really redraws the affected region...
480*4882a593Smuzhiyun              */
481*4882a593Smuzhiyun             ValidateRect(hwnd, &(ps.rcPaint));
482*4882a593Smuzhiyun         }
483*4882a593Smuzhiyun         else
484*4882a593Smuzhiyun #endif
485*4882a593Smuzhiyun             /* Try to copy from the shadow buffer */
486*4882a593Smuzhiyun         if (!BitBlt(hdcUpdate,
487*4882a593Smuzhiyun                         ps.rcPaint.left, ps.rcPaint.top,
488*4882a593Smuzhiyun                         ps.rcPaint.right - ps.rcPaint.left,
489*4882a593Smuzhiyun                         ps.rcPaint.bottom - ps.rcPaint.top,
490*4882a593Smuzhiyun                         s_pScreenPriv->hdcShadow,
491*4882a593Smuzhiyun                         ps.rcPaint.left + pWin->drawable.x,
492*4882a593Smuzhiyun                         ps.rcPaint.top + pWin->drawable.y, SRCCOPY)) {
493*4882a593Smuzhiyun             LPVOID lpMsgBuf;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun             /* Display a fancy error message */
496*4882a593Smuzhiyun             FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
497*4882a593Smuzhiyun                           FORMAT_MESSAGE_FROM_SYSTEM |
498*4882a593Smuzhiyun                           FORMAT_MESSAGE_IGNORE_INSERTS,
499*4882a593Smuzhiyun                           NULL,
500*4882a593Smuzhiyun                           GetLastError(),
501*4882a593Smuzhiyun                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
502*4882a593Smuzhiyun                           (LPTSTR) &lpMsgBuf, 0, NULL);
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun             ErrorF("winTopLevelWindowProc - BitBlt failed: %s\n",
505*4882a593Smuzhiyun                    (LPSTR) lpMsgBuf);
506*4882a593Smuzhiyun             LocalFree(lpMsgBuf);
507*4882a593Smuzhiyun         }
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun         /* EndPaint frees the DC */
510*4882a593Smuzhiyun         EndPaint(hwnd, &ps);
511*4882a593Smuzhiyun         return 0;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     case WM_MOUSEMOVE:
514*4882a593Smuzhiyun         /* Unpack the client area mouse coordinates */
515*4882a593Smuzhiyun         ptMouse.x = GET_X_LPARAM(lParam);
516*4882a593Smuzhiyun         ptMouse.y = GET_Y_LPARAM(lParam);
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun         /* Translate the client area mouse coordinates to screen coordinates */
519*4882a593Smuzhiyun         ClientToScreen(hwnd, &ptMouse);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun         /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
522*4882a593Smuzhiyun         ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
523*4882a593Smuzhiyun         ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun         /* We can't do anything without privates */
526*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
527*4882a593Smuzhiyun             break;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun         /* Has the mouse pointer crossed screens? */
530*4882a593Smuzhiyun         if (s_pScreen != miPointerGetScreen(g_pwinPointer))
531*4882a593Smuzhiyun             miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
532*4882a593Smuzhiyun                                ptMouse.x - s_pScreenInfo->dwXOffset,
533*4882a593Smuzhiyun                                ptMouse.y - s_pScreenInfo->dwYOffset);
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun         /* Are we tracking yet? */
536*4882a593Smuzhiyun         if (!s_fTracking) {
537*4882a593Smuzhiyun             TRACKMOUSEEVENT tme;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun             /* Setup data structure */
540*4882a593Smuzhiyun             ZeroMemory(&tme, sizeof(tme));
541*4882a593Smuzhiyun             tme.cbSize = sizeof(tme);
542*4882a593Smuzhiyun             tme.dwFlags = TME_LEAVE;
543*4882a593Smuzhiyun             tme.hwndTrack = hwnd;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun             /* Call the tracking function */
546*4882a593Smuzhiyun             if (!TrackMouseEvent(&tme))
547*4882a593Smuzhiyun                 ErrorF("winTopLevelWindowProc - TrackMouseEvent failed\n");
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun             /* Flag that we are tracking now */
550*4882a593Smuzhiyun             s_fTracking = TRUE;
551*4882a593Smuzhiyun         }
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun         /* Hide or show the Windows mouse cursor */
554*4882a593Smuzhiyun         if (g_fSoftwareCursor && g_fCursor) {
555*4882a593Smuzhiyun             /* Hide Windows cursor */
556*4882a593Smuzhiyun             g_fCursor = FALSE;
557*4882a593Smuzhiyun             ShowCursor(FALSE);
558*4882a593Smuzhiyun         }
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun         /* Kill the timer used to poll mouse events */
561*4882a593Smuzhiyun         if (g_uipMousePollingTimerID != 0) {
562*4882a593Smuzhiyun             KillTimer(s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
563*4882a593Smuzhiyun             g_uipMousePollingTimerID = 0;
564*4882a593Smuzhiyun         }
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun         /* Deliver absolute cursor position to X Server */
567*4882a593Smuzhiyun         winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
568*4882a593Smuzhiyun                          ptMouse.y - s_pScreenInfo->dwYOffset);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun         return 0;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun     case WM_NCMOUSEMOVE:
573*4882a593Smuzhiyun         /*
574*4882a593Smuzhiyun          * We break instead of returning 0 since we need to call
575*4882a593Smuzhiyun          * DefWindowProc to get the mouse cursor changes
576*4882a593Smuzhiyun          * and min/max/close button highlighting in Windows XP.
577*4882a593Smuzhiyun          * The Platform SDK says that you should return 0 if you
578*4882a593Smuzhiyun          * process this message, but it fails to mention that you
579*4882a593Smuzhiyun          * will give up any default functionality if you do return 0.
580*4882a593Smuzhiyun          */
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun         /* We can't do anything without privates */
583*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
584*4882a593Smuzhiyun             break;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun         /* Non-client mouse movement, show Windows cursor */
587*4882a593Smuzhiyun         if (g_fSoftwareCursor && !g_fCursor) {
588*4882a593Smuzhiyun             g_fCursor = TRUE;
589*4882a593Smuzhiyun             ShowCursor(TRUE);
590*4882a593Smuzhiyun         }
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun         break;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun     case WM_MOUSELEAVE:
597*4882a593Smuzhiyun         /* Mouse has left our client area */
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun         /* Flag that we are no longer tracking */
600*4882a593Smuzhiyun         s_fTracking = FALSE;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun         /* Show the mouse cursor, if necessary */
603*4882a593Smuzhiyun         if (g_fSoftwareCursor && !g_fCursor) {
604*4882a593Smuzhiyun             g_fCursor = TRUE;
605*4882a593Smuzhiyun             ShowCursor(TRUE);
606*4882a593Smuzhiyun         }
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun         return 0;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun     case WM_LBUTTONDBLCLK:
613*4882a593Smuzhiyun     case WM_LBUTTONDOWN:
614*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
615*4882a593Smuzhiyun             break;
616*4882a593Smuzhiyun         g_fButton[0] = TRUE;
617*4882a593Smuzhiyun         SetCapture(hwnd);
618*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun     case WM_LBUTTONUP:
621*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
622*4882a593Smuzhiyun             break;
623*4882a593Smuzhiyun         g_fButton[0] = FALSE;
624*4882a593Smuzhiyun         ReleaseCapture();
625*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
626*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun     case WM_MBUTTONDBLCLK:
629*4882a593Smuzhiyun     case WM_MBUTTONDOWN:
630*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
631*4882a593Smuzhiyun             break;
632*4882a593Smuzhiyun         g_fButton[1] = TRUE;
633*4882a593Smuzhiyun         SetCapture(hwnd);
634*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun     case WM_MBUTTONUP:
637*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
638*4882a593Smuzhiyun             break;
639*4882a593Smuzhiyun         g_fButton[1] = FALSE;
640*4882a593Smuzhiyun         ReleaseCapture();
641*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
642*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun     case WM_RBUTTONDBLCLK:
645*4882a593Smuzhiyun     case WM_RBUTTONDOWN:
646*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
647*4882a593Smuzhiyun             break;
648*4882a593Smuzhiyun         g_fButton[2] = TRUE;
649*4882a593Smuzhiyun         SetCapture(hwnd);
650*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     case WM_RBUTTONUP:
653*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
654*4882a593Smuzhiyun             break;
655*4882a593Smuzhiyun         g_fButton[2] = FALSE;
656*4882a593Smuzhiyun         ReleaseCapture();
657*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
658*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun     case WM_XBUTTONDBLCLK:
661*4882a593Smuzhiyun     case WM_XBUTTONDOWN:
662*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
663*4882a593Smuzhiyun             break;
664*4882a593Smuzhiyun         SetCapture(hwnd);
665*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
666*4882a593Smuzhiyun                                      wParam);
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun     case WM_XBUTTONUP:
669*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
670*4882a593Smuzhiyun             break;
671*4882a593Smuzhiyun         ReleaseCapture();
672*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
673*4882a593Smuzhiyun         return winMouseButtonsHandle(s_pScreen, ButtonRelease,
674*4882a593Smuzhiyun                                      HIWORD(wParam) + 7, wParam);
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun     case WM_MOUSEWHEEL:
677*4882a593Smuzhiyun         if (SendMessage
678*4882a593Smuzhiyun             (hwnd, WM_NCHITTEST, 0,
679*4882a593Smuzhiyun              MAKELONG(GET_X_LPARAM(lParam),
680*4882a593Smuzhiyun                       GET_Y_LPARAM(lParam))) == HTCLIENT) {
681*4882a593Smuzhiyun             /* Pass the message to the root window */
682*4882a593Smuzhiyun             SendMessage(hwndScreen, message, wParam, lParam);
683*4882a593Smuzhiyun             return 0;
684*4882a593Smuzhiyun         }
685*4882a593Smuzhiyun         else
686*4882a593Smuzhiyun             break;
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun     case WM_MOUSEHWHEEL:
689*4882a593Smuzhiyun         if (SendMessage
690*4882a593Smuzhiyun             (hwnd, WM_NCHITTEST, 0,
691*4882a593Smuzhiyun              MAKELONG(GET_X_LPARAM(lParam),
692*4882a593Smuzhiyun                       GET_Y_LPARAM(lParam))) == HTCLIENT) {
693*4882a593Smuzhiyun             /* Pass the message to the root window */
694*4882a593Smuzhiyun             SendMessage(hwndScreen, message, wParam, lParam);
695*4882a593Smuzhiyun             return 0;
696*4882a593Smuzhiyun         }
697*4882a593Smuzhiyun         else
698*4882a593Smuzhiyun             break;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun     case WM_SETFOCUS:
701*4882a593Smuzhiyun         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
702*4882a593Smuzhiyun             break;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun         {
705*4882a593Smuzhiyun             /* Get the parent window for transient handling */
706*4882a593Smuzhiyun             HWND hParent = GetParent(hwnd);
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun             if (hParent && IsIconic(hParent))
709*4882a593Smuzhiyun                 ShowWindow(hParent, SW_RESTORE);
710*4882a593Smuzhiyun         }
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun         winRestoreModeKeyStates();
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun         /* Add the keyboard hook if possible */
715*4882a593Smuzhiyun         if (g_fKeyboardHookLL)
716*4882a593Smuzhiyun             g_fKeyboardHookLL = winInstallKeyboardHookLL();
717*4882a593Smuzhiyun         return 0;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun     case WM_KILLFOCUS:
720*4882a593Smuzhiyun         /* Pop any pressed keys since we are losing keyboard focus */
721*4882a593Smuzhiyun         winKeybdReleaseKeys();
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun         /* Remove our keyboard hook if it is installed */
724*4882a593Smuzhiyun         winRemoveKeyboardHookLL();
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun         /* Revert the X focus as well, but only if the Windows focus is going to another window */
727*4882a593Smuzhiyun         if (!wParam && pWin)
728*4882a593Smuzhiyun             DeleteWindowFromAnyEvents(pWin, FALSE);
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun         return 0;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun     case WM_SYSDEADCHAR:
733*4882a593Smuzhiyun     case WM_DEADCHAR:
734*4882a593Smuzhiyun         /*
735*4882a593Smuzhiyun          * NOTE: We do nothing with WM_*CHAR messages,
736*4882a593Smuzhiyun          * nor does the root window, so we can just toss these messages.
737*4882a593Smuzhiyun          */
738*4882a593Smuzhiyun         return 0;
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun     case WM_SYSKEYDOWN:
741*4882a593Smuzhiyun     case WM_KEYDOWN:
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun         /*
744*4882a593Smuzhiyun          * Don't pass Alt-F4 key combo to root window,
745*4882a593Smuzhiyun          * let Windows translate to WM_CLOSE and close this top-level window.
746*4882a593Smuzhiyun          *
747*4882a593Smuzhiyun          * NOTE: We purposely don't check the fUseWinKillKey setting because
748*4882a593Smuzhiyun          * it should only apply to the key handling for the root window,
749*4882a593Smuzhiyun          * not for top-level window-manager windows.
750*4882a593Smuzhiyun          *
751*4882a593Smuzhiyun          * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
752*4882a593Smuzhiyun          * because that is a key combo that no X app should be expecting to
753*4882a593Smuzhiyun          * receive, since it has historically been used to shutdown the X server.
754*4882a593Smuzhiyun          * Passing Ctrl-Alt-Backspace to the root window preserves that
755*4882a593Smuzhiyun          * behavior, assuming that -unixkill has been passed as a parameter.
756*4882a593Smuzhiyun          */
757*4882a593Smuzhiyun         if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000))
758*4882a593Smuzhiyun             break;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun #if CYGWINDOWING_DEBUG
761*4882a593Smuzhiyun         if (wParam == VK_ESCAPE) {
762*4882a593Smuzhiyun             /* Place for debug: put any tests and dumps here */
763*4882a593Smuzhiyun             WINDOWPLACEMENT windPlace;
764*4882a593Smuzhiyun             RECT rc;
765*4882a593Smuzhiyun             LPRECT pRect;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun             windPlace.length = sizeof(WINDOWPLACEMENT);
768*4882a593Smuzhiyun             GetWindowPlacement(hwnd, &windPlace);
769*4882a593Smuzhiyun             pRect = &windPlace.rcNormalPosition;
770*4882a593Smuzhiyun             ErrorF("\nCYGWINDOWING Dump:\n"
771*4882a593Smuzhiyun                    "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
772*4882a593Smuzhiyun                    pDraw->y, pDraw->width, pDraw->height);
773*4882a593Smuzhiyun             ErrorF("\twindPlace: (%d, %d) - %dx%d\n", (int)pRect->left,
774*4882a593Smuzhiyun                    (int)pRect->top, (int)(pRect->right - pRect->left),
775*4882a593Smuzhiyun                    (int)(pRect->bottom - pRect->top));
776*4882a593Smuzhiyun             if (GetClientRect(hwnd, &rc)) {
777*4882a593Smuzhiyun                 pRect = &rc;
778*4882a593Smuzhiyun                 ErrorF("\tClientRect: (%d, %d) - %dx%d\n", (int)pRect->left,
779*4882a593Smuzhiyun                        (int)pRect->top, (int)(pRect->right - pRect->left),
780*4882a593Smuzhiyun                        (int)(pRect->bottom - pRect->top));
781*4882a593Smuzhiyun             }
782*4882a593Smuzhiyun             if (GetWindowRect(hwnd, &rc)) {
783*4882a593Smuzhiyun                 pRect = &rc;
784*4882a593Smuzhiyun                 ErrorF("\tWindowRect: (%d, %d) - %dx%d\n", (int)pRect->left,
785*4882a593Smuzhiyun                        (int)pRect->top, (int)(pRect->right - pRect->left),
786*4882a593Smuzhiyun                        (int)(pRect->bottom - pRect->top));
787*4882a593Smuzhiyun             }
788*4882a593Smuzhiyun             ErrorF("\n");
789*4882a593Smuzhiyun         }
790*4882a593Smuzhiyun #endif
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun         /* Pass the message to the root window */
793*4882a593Smuzhiyun         return winWindowProc(hwndScreen, message, wParam, lParam);
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun     case WM_SYSKEYUP:
796*4882a593Smuzhiyun     case WM_KEYUP:
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun         /* Pass the message to the root window */
799*4882a593Smuzhiyun         return winWindowProc(hwndScreen, message, wParam, lParam);
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun     case WM_HOTKEY:
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun         /* Pass the message to the root window */
804*4882a593Smuzhiyun         SendMessage(hwndScreen, message, wParam, lParam);
805*4882a593Smuzhiyun         return 0;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun     case WM_ACTIVATE:
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun         /* Pass the message to the root window */
810*4882a593Smuzhiyun         SendMessage(hwndScreen, message, wParam, lParam);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun         if (LOWORD(wParam) != WA_INACTIVE) {
813*4882a593Smuzhiyun             /* Raise the window to the top in Z order */
814*4882a593Smuzhiyun             /* ago: Activate does not mean putting it to front! */
815*4882a593Smuzhiyun             /*
816*4882a593Smuzhiyun                wmMsg.msg = WM_WM_RAISE;
817*4882a593Smuzhiyun                if (fWMMsgInitialized)
818*4882a593Smuzhiyun                winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
819*4882a593Smuzhiyun              */
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun             /* Tell our Window Manager thread to activate the window */
822*4882a593Smuzhiyun             wmMsg.msg = WM_WM_ACTIVATE;
823*4882a593Smuzhiyun             if (fWMMsgInitialized)
824*4882a593Smuzhiyun                 if (!pWin || !pWin->overrideRedirect)   /* for OOo menus */
825*4882a593Smuzhiyun                     winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
826*4882a593Smuzhiyun         }
827*4882a593Smuzhiyun         /* Prevent the mouse wheel from stalling when another window is minimized */
828*4882a593Smuzhiyun         if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
829*4882a593Smuzhiyun             (HWND) lParam != NULL && (HWND) lParam != GetParent(hwnd))
830*4882a593Smuzhiyun             SetFocus(hwnd);
831*4882a593Smuzhiyun         return 0;
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun     case WM_ACTIVATEAPP:
834*4882a593Smuzhiyun         /*
835*4882a593Smuzhiyun          * This message is also sent to the root window
836*4882a593Smuzhiyun          * so we do nothing for individual multiwindow windows
837*4882a593Smuzhiyun          */
838*4882a593Smuzhiyun         break;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun     case WM_CLOSE:
841*4882a593Smuzhiyun         /* Remove AppUserModelID property */
842*4882a593Smuzhiyun         winSetAppUserModelID(hwnd, NULL);
843*4882a593Smuzhiyun         /* Branch on if the window was killed in X already */
844*4882a593Smuzhiyun         if (pWinPriv->fXKilled) {
845*4882a593Smuzhiyun             /* Window was killed, go ahead and destroy the window */
846*4882a593Smuzhiyun             DestroyWindow(hwnd);
847*4882a593Smuzhiyun         }
848*4882a593Smuzhiyun         else {
849*4882a593Smuzhiyun             /* Tell our Window Manager thread to kill the window */
850*4882a593Smuzhiyun             wmMsg.msg = WM_WM_KILL;
851*4882a593Smuzhiyun             if (fWMMsgInitialized)
852*4882a593Smuzhiyun                 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
853*4882a593Smuzhiyun         }
854*4882a593Smuzhiyun         return 0;
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun     case WM_DESTROY:
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun         /* Branch on if the window was killed in X already */
859*4882a593Smuzhiyun         if (pWinPriv && !pWinPriv->fXKilled) {
860*4882a593Smuzhiyun             ErrorF("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun             /* Tell our Window Manager thread to kill the window */
863*4882a593Smuzhiyun             wmMsg.msg = WM_WM_KILL;
864*4882a593Smuzhiyun             if (fWMMsgInitialized)
865*4882a593Smuzhiyun                 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
866*4882a593Smuzhiyun         }
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun         RemoveProp(hwnd, WIN_WINDOW_PROP);
869*4882a593Smuzhiyun         RemoveProp(hwnd, WIN_WID_PROP);
870*4882a593Smuzhiyun         RemoveProp(hwnd, WIN_NEEDMANAGE_PROP);
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun         break;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun     case WM_MOVE:
875*4882a593Smuzhiyun         /* Adjust the X Window to the moved Windows window */
876*4882a593Smuzhiyun         if (!hasEnteredSizeMove)
877*4882a593Smuzhiyun             winAdjustXWindow(pWin, hwnd);
878*4882a593Smuzhiyun         /* else: Wait for WM_EXITSIZEMOVE */
879*4882a593Smuzhiyun         return 0;
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun     case WM_SHOWWINDOW:
882*4882a593Smuzhiyun         /* Bail out if the window is being hidden */
883*4882a593Smuzhiyun         if (!wParam)
884*4882a593Smuzhiyun             return 0;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun         /* */
887*4882a593Smuzhiyun         if (!pWin->overrideRedirect) {
888*4882a593Smuzhiyun             HWND zstyle = HWND_NOTOPMOST;
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun             /* Flag that this window needs to be made active when clicked */
891*4882a593Smuzhiyun             SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun             /* Set the transient style flags */
894*4882a593Smuzhiyun             if (GetParent(hwnd))
895*4882a593Smuzhiyun                 SetWindowLongPtr(hwnd, GWL_STYLE,
896*4882a593Smuzhiyun                                  WS_POPUP | WS_OVERLAPPED | WS_SYSMENU |
897*4882a593Smuzhiyun                                  WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
898*4882a593Smuzhiyun             /* Set the window standard style flags */
899*4882a593Smuzhiyun             else
900*4882a593Smuzhiyun                 SetWindowLongPtr(hwnd, GWL_STYLE,
901*4882a593Smuzhiyun                                  (WS_POPUP | WS_OVERLAPPEDWINDOW |
902*4882a593Smuzhiyun                                   WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
903*4882a593Smuzhiyun                                  & ~WS_CAPTION & ~WS_SIZEBOX);
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun             winUpdateWindowPosition(hwnd, &zstyle);
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun             {
908*4882a593Smuzhiyun                 WinXWMHints hints;
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun                 if (winMultiWindowGetWMHints(pWin, &hints)) {
911*4882a593Smuzhiyun                     /*
912*4882a593Smuzhiyun                        Give the window focus, unless it has an InputHint
913*4882a593Smuzhiyun                        which is FALSE (this is used by e.g. glean to
914*4882a593Smuzhiyun                        avoid every test window grabbing the focus)
915*4882a593Smuzhiyun                      */
916*4882a593Smuzhiyun                     if (!((hints.flags & InputHint) && (!hints.input))) {
917*4882a593Smuzhiyun                         SetForegroundWindow(hwnd);
918*4882a593Smuzhiyun                     }
919*4882a593Smuzhiyun                 }
920*4882a593Smuzhiyun             }
921*4882a593Smuzhiyun             wmMsg.msg = WM_WM_MAP3;
922*4882a593Smuzhiyun         }
923*4882a593Smuzhiyun         else {                  /* It is an overridden window so make it top of Z stack */
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun             HWND forHwnd = GetForegroundWindow();
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun #if CYGWINDOWING_DEBUG
928*4882a593Smuzhiyun             ErrorF("overridden window is shown\n");
929*4882a593Smuzhiyun #endif
930*4882a593Smuzhiyun             if (forHwnd != NULL) {
931*4882a593Smuzhiyun                 if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)
932*4882a593Smuzhiyun                     XMING_SIGNATURE) {
933*4882a593Smuzhiyun                     if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
934*4882a593Smuzhiyun                         SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
935*4882a593Smuzhiyun                                      SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
936*4882a593Smuzhiyun                     else
937*4882a593Smuzhiyun                         SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
938*4882a593Smuzhiyun                                      SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
939*4882a593Smuzhiyun                 }
940*4882a593Smuzhiyun             }
941*4882a593Smuzhiyun             wmMsg.msg = WM_WM_MAP2;
942*4882a593Smuzhiyun         }
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun         /* Tell our Window Manager thread to map the window */
945*4882a593Smuzhiyun         if (fWMMsgInitialized)
946*4882a593Smuzhiyun             winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun         winStartMousePolling(s_pScreenPriv);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun         return 0;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun     case WM_SIZING:
953*4882a593Smuzhiyun         /* Need to legalize the size according to WM_NORMAL_HINTS */
954*4882a593Smuzhiyun         /* for applications like xterm */
955*4882a593Smuzhiyun         return ValidateSizing(hwnd, pWin, wParam, lParam);
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun     case WM_WINDOWPOSCHANGED:
958*4882a593Smuzhiyun     {
959*4882a593Smuzhiyun         LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun         if (!(pWinPos->flags & SWP_NOZORDER)) {
962*4882a593Smuzhiyun #if CYGWINDOWING_DEBUG
963*4882a593Smuzhiyun             winDebug("\twindow z order was changed\n");
964*4882a593Smuzhiyun #endif
965*4882a593Smuzhiyun             if (pWinPos->hwndInsertAfter == HWND_TOP
966*4882a593Smuzhiyun                 || pWinPos->hwndInsertAfter == HWND_TOPMOST
967*4882a593Smuzhiyun                 || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) {
968*4882a593Smuzhiyun #if CYGWINDOWING_DEBUG
969*4882a593Smuzhiyun                 winDebug("\traise to top\n");
970*4882a593Smuzhiyun #endif
971*4882a593Smuzhiyun                 /* Raise the window to the top in Z order */
972*4882a593Smuzhiyun                 winRaiseWindow(pWin);
973*4882a593Smuzhiyun             }
974*4882a593Smuzhiyun             else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) {
975*4882a593Smuzhiyun             }
976*4882a593Smuzhiyun             else {
977*4882a593Smuzhiyun                 /* Check if this window is top of X windows. */
978*4882a593Smuzhiyun                 HWND hWndAbove = NULL;
979*4882a593Smuzhiyun                 DWORD dwCurrentProcessID = GetCurrentProcessId();
980*4882a593Smuzhiyun                 DWORD dwWindowProcessID = 0;
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun                 for (hWndAbove = pWinPos->hwndInsertAfter;
983*4882a593Smuzhiyun                      hWndAbove != NULL;
984*4882a593Smuzhiyun                      hWndAbove = GetNextWindow(hWndAbove, GW_HWNDPREV)) {
985*4882a593Smuzhiyun                     /* Ignore other XWin process's window */
986*4882a593Smuzhiyun                     GetWindowThreadProcessId(hWndAbove, &dwWindowProcessID);
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun                     if ((dwWindowProcessID == dwCurrentProcessID)
989*4882a593Smuzhiyun                         && GetProp(hWndAbove, WIN_WINDOW_PROP)
990*4882a593Smuzhiyun                         && !IsWindowVisible(hWndAbove)
991*4882a593Smuzhiyun                         && !IsIconic(hWndAbove))        /* ignore minimized windows */
992*4882a593Smuzhiyun                         break;
993*4882a593Smuzhiyun                 }
994*4882a593Smuzhiyun                 /* If this is top of X windows in Windows stack,
995*4882a593Smuzhiyun                    raise it in X stack. */
996*4882a593Smuzhiyun                 if (hWndAbove == NULL) {
997*4882a593Smuzhiyun #if CYGWINDOWING_DEBUG
998*4882a593Smuzhiyun                     winDebug("\traise to top\n");
999*4882a593Smuzhiyun #endif
1000*4882a593Smuzhiyun                     winRaiseWindow(pWin);
1001*4882a593Smuzhiyun                 }
1002*4882a593Smuzhiyun             }
1003*4882a593Smuzhiyun         }
1004*4882a593Smuzhiyun     }
1005*4882a593Smuzhiyun         /*
1006*4882a593Smuzhiyun          * Pass the message to DefWindowProc to let the function
1007*4882a593Smuzhiyun          * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
1008*4882a593Smuzhiyun          */
1009*4882a593Smuzhiyun         break;
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun     case WM_ENTERSIZEMOVE:
1012*4882a593Smuzhiyun         hasEnteredSizeMove = TRUE;
1013*4882a593Smuzhiyun         return 0;
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun     case WM_EXITSIZEMOVE:
1016*4882a593Smuzhiyun         /* Adjust the X Window to the moved Windows window */
1017*4882a593Smuzhiyun         hasEnteredSizeMove = FALSE;
1018*4882a593Smuzhiyun         winAdjustXWindow(pWin, hwnd);
1019*4882a593Smuzhiyun         return 0;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun     case WM_SIZE:
1022*4882a593Smuzhiyun         /* see dix/window.c */
1023*4882a593Smuzhiyun #if CYGWINDOWING_DEBUG
1024*4882a593Smuzhiyun     {
1025*4882a593Smuzhiyun         char buf[64];
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun         switch (wParam) {
1028*4882a593Smuzhiyun         case SIZE_MINIMIZED:
1029*4882a593Smuzhiyun             strcpy(buf, "SIZE_MINIMIZED");
1030*4882a593Smuzhiyun             break;
1031*4882a593Smuzhiyun         case SIZE_MAXIMIZED:
1032*4882a593Smuzhiyun             strcpy(buf, "SIZE_MAXIMIZED");
1033*4882a593Smuzhiyun             break;
1034*4882a593Smuzhiyun         case SIZE_RESTORED:
1035*4882a593Smuzhiyun             strcpy(buf, "SIZE_RESTORED");
1036*4882a593Smuzhiyun             break;
1037*4882a593Smuzhiyun         default:
1038*4882a593Smuzhiyun             strcpy(buf, "UNKNOWN_FLAG");
1039*4882a593Smuzhiyun         }
1040*4882a593Smuzhiyun         ErrorF("winTopLevelWindowProc - WM_SIZE to %dx%d (%s)\n",
1041*4882a593Smuzhiyun                (int) LOWORD(lParam), (int) HIWORD(lParam), buf);
1042*4882a593Smuzhiyun     }
1043*4882a593Smuzhiyun #endif
1044*4882a593Smuzhiyun         if (!hasEnteredSizeMove) {
1045*4882a593Smuzhiyun             /* Adjust the X Window to the moved Windows window */
1046*4882a593Smuzhiyun             winAdjustXWindow(pWin, hwnd);
1047*4882a593Smuzhiyun         }
1048*4882a593Smuzhiyun         /* else: wait for WM_EXITSIZEMOVE */
1049*4882a593Smuzhiyun         return 0;               /* end of WM_SIZE handler */
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun     case WM_STYLECHANGING:
1052*4882a593Smuzhiyun         /*
1053*4882a593Smuzhiyun            When the style changes, adjust the Windows window size so the client area remains the same size,
1054*4882a593Smuzhiyun            and adjust the Windows window position so that the client area remains in the same place.
1055*4882a593Smuzhiyun          */
1056*4882a593Smuzhiyun     {
1057*4882a593Smuzhiyun         RECT newWinRect;
1058*4882a593Smuzhiyun         DWORD dwExStyle;
1059*4882a593Smuzhiyun         DWORD dwStyle;
1060*4882a593Smuzhiyun         DWORD newStyle = ((STYLESTRUCT *) lParam)->styleNew;
1061*4882a593Smuzhiyun         WINDOWINFO wi;
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun         dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
1064*4882a593Smuzhiyun         dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun         winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n",
1067*4882a593Smuzhiyun                  (unsigned int)dwStyle, (unsigned int)dwExStyle);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun         if (wParam == GWL_EXSTYLE)
1070*4882a593Smuzhiyun             dwExStyle = newStyle;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun         if (wParam == GWL_STYLE)
1073*4882a593Smuzhiyun             dwStyle = newStyle;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun         winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n",
1076*4882a593Smuzhiyun                  (unsigned int)dwStyle, (unsigned int)dwExStyle);
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun         /* Get client rect in screen coordinates */
1079*4882a593Smuzhiyun         wi.cbSize = sizeof(WINDOWINFO);
1080*4882a593Smuzhiyun         GetWindowInfo(hwnd, &wi);
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun         winDebug
1083*4882a593Smuzhiyun             ("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n",
1084*4882a593Smuzhiyun              (int)wi.rcClient.left, (int)wi.rcClient.top, (int)wi.rcClient.right,
1085*4882a593Smuzhiyun              (int)wi.rcClient.bottom, (int)(wi.rcClient.right - wi.rcClient.left),
1086*4882a593Smuzhiyun              (int)(wi.rcClient.bottom - wi.rcClient.top));
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun         newWinRect = wi.rcClient;
1089*4882a593Smuzhiyun         if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle))
1090*4882a593Smuzhiyun             winDebug
1091*4882a593Smuzhiyun                 ("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n");
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun         winDebug
1094*4882a593Smuzhiyun             ("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n",
1095*4882a593Smuzhiyun              (int)newWinRect.left, (int)newWinRect.top, (int)newWinRect.right,
1096*4882a593Smuzhiyun              (int)newWinRect.bottom, (int)(newWinRect.right - newWinRect.left),
1097*4882a593Smuzhiyun              (int)(newWinRect.bottom - newWinRect.top));
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun         /*
1100*4882a593Smuzhiyun            Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow()
1101*4882a593Smuzhiyun            which WM_SIZE does will use the current (unchanged) style.  Instead make a note to change it when
1102*4882a593Smuzhiyun            WM_STYLECHANGED is received...
1103*4882a593Smuzhiyun          */
1104*4882a593Smuzhiyun         pWinPriv->hDwp = BeginDeferWindowPos(1);
1105*4882a593Smuzhiyun         pWinPriv->hDwp =
1106*4882a593Smuzhiyun             DeferWindowPos(pWinPriv->hDwp, hwnd, NULL, newWinRect.left,
1107*4882a593Smuzhiyun                            newWinRect.top, newWinRect.right - newWinRect.left,
1108*4882a593Smuzhiyun                            newWinRect.bottom - newWinRect.top,
1109*4882a593Smuzhiyun                            SWP_NOACTIVATE | SWP_NOZORDER);
1110*4882a593Smuzhiyun     }
1111*4882a593Smuzhiyun         return 0;
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun     case WM_STYLECHANGED:
1114*4882a593Smuzhiyun     {
1115*4882a593Smuzhiyun         if (pWinPriv->hDwp) {
1116*4882a593Smuzhiyun             EndDeferWindowPos(pWinPriv->hDwp);
1117*4882a593Smuzhiyun             pWinPriv->hDwp = NULL;
1118*4882a593Smuzhiyun         }
1119*4882a593Smuzhiyun         winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n");
1120*4882a593Smuzhiyun     }
1121*4882a593Smuzhiyun         return 0;
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun     case WM_MOUSEACTIVATE:
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun         /* Check if this window needs to be made active when clicked */
1126*4882a593Smuzhiyun         if (!GetProp(pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) {
1127*4882a593Smuzhiyun #if CYGMULTIWINDOW_DEBUG
1128*4882a593Smuzhiyun             ErrorF("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
1129*4882a593Smuzhiyun                    "MA_NOACTIVATE\n");
1130*4882a593Smuzhiyun #endif
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun             /* */
1133*4882a593Smuzhiyun             return MA_NOACTIVATE;
1134*4882a593Smuzhiyun         }
1135*4882a593Smuzhiyun         break;
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun     case WM_SETCURSOR:
1138*4882a593Smuzhiyun         if (LOWORD(lParam) == HTCLIENT) {
1139*4882a593Smuzhiyun             if (!g_fSoftwareCursor)
1140*4882a593Smuzhiyun                 SetCursor(s_pScreenPriv->cursor.handle);
1141*4882a593Smuzhiyun             return TRUE;
1142*4882a593Smuzhiyun         }
1143*4882a593Smuzhiyun         break;
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun     default:
1146*4882a593Smuzhiyun         break;
1147*4882a593Smuzhiyun     }
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun     ret = DefWindowProc(hwnd, message, wParam, lParam);
1150*4882a593Smuzhiyun     /*
1151*4882a593Smuzhiyun      * If the window was minized we get the stack change before the window is restored
1152*4882a593Smuzhiyun      * and so it gets lost. Ensure there stacking order is correct.
1153*4882a593Smuzhiyun      */
1154*4882a593Smuzhiyun     if (needRestack)
1155*4882a593Smuzhiyun         winReorderWindowsMultiWindow();
1156*4882a593Smuzhiyun     return ret;
1157*4882a593Smuzhiyun }
1158