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