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