2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
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:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
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.
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.
28 * Authors: Dakshinamurthy Karra
35 #ifdef HAVE_XWIN_CONFIG_H
36 #include <xwin-config.h>
41 #include "winconfig.h"
43 #include "winmonitors.h"
50 Bool g_fCursor
= TRUE
;
51 Bool g_fButton
[3] = { FALSE
, FALSE
, FALSE
};
54 * Called by winWakeupHandler
55 * Processes current Windows message
59 winWindowProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
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;
72 winDebugWin32Message("winWindowProc", hwnd
, message
, wParam
, lParam
);
75 /* Watch for server regeneration */
76 if (g_ulServerGeneration
!= s_ulServerGeneration
) {
77 /* Store new server generation */
78 s_ulServerGeneration
= g_ulServerGeneration
;
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
) {
85 winDebug("winWindowProc - Setting privates handle\n");
87 s_pScreenInfo
= s_pScreenPriv
->pScreenInfo
;
88 s_pScreen
= s_pScreenInfo
->pScreen
;
89 s_hwndLastPrivates
= hwnd
;
91 else if (s_pScreenPriv
== NULL
) {
92 /* For safety, handle case that should never happen */
95 s_hwndLastPrivates
= NULL
;
98 /* Branch on message type */
101 return winHandleIconMessage(hwnd
, message
, wParam
, lParam
,
106 winDebug("winWindowProc - WM_CREATE\n");
110 * Add a property to our display window that references
111 * this screens' privates.
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.
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
);
125 /* Setup tray icon */
126 if (!s_pScreenInfo
->fNoTrayIcon
) {
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.
136 s_pScreenPriv
->hwndScreen
= hwnd
;
138 winInitNotifyIcon(s_pScreenPriv
);
142 case WM_DISPLAYCHANGE
:
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...)
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");
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.
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
171 ErrorF("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
172 "new height: %d new bpp: %d\n",
173 LOWORD(lParam
), HIWORD(lParam
), wParam
);
175 /* 0 bpp has no defined meaning, ignore this message */
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.
185 XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT)
186 has changed as well...
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
196 /* Cannot display the visual until the depth is restored */
197 ErrorF("winWindowProc - Disruptive change in depth\n");
199 /* Display depth change dialog */
200 winDisplayDepthChangeDialog(s_pScreenPriv
);
202 /* Flag that we have an invalid screen depth */
203 s_pScreenPriv
->fBadDepth
= TRUE
;
205 /* Minimize the display window */
206 ShowWindow(hwnd
, SW_MINIMIZE
);
209 /* For GDI, performance may suffer until original depth is restored */
211 ("winWindowProc - Performance may be non-optimal after change in depth\n");
215 /* Flag that we have a valid screen depth */
216 s_pScreenPriv
->fBadDepth
= FALSE
;
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
228 In rootless modes which are monitor or virtual desktop size
229 use RandR to resize the X screen
231 if ((!s_pScreenInfo
->fUserGaveHeightAndWidth
) &&
232 (s_pScreenInfo
->iResizeMode
== resizeWithRandr
) && (FALSE
233 #ifdef XWIN_MULTIWINDOWEXTWM
241 #ifdef XWIN_MULTIWINDOW
247 DWORD dwWidth
, dwHeight
;
249 if (s_pScreenInfo
->fMultipleMonitors
) {
250 /* resize to new virtual desktop size */
251 dwWidth
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
252 dwHeight
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
255 /* resize to new size of specified monitor */
256 struct GetMonitorInfoData data
;
258 if (QueryMonitor(s_pScreenInfo
->iMonitor
, &data
)) {
259 if (data
.bMonitorSpecifiedExists
== TRUE
) {
260 dwWidth
= data
.monitorWidth
;
261 dwHeight
= data
.monitorHeight
;
263 XXX: monitor may have changed position,
264 so we might need to update xinerama data
268 ErrorF("Monitor number %d no longer exists!\n",
269 s_pScreenInfo
->iMonitor
);
275 XXX: probably a small bug here: we don't compute the work area
276 and allow for task bar
278 XXX: generally, we don't allow for the task bar being moved after
279 the server is started
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
,
296 * We can simply recreate the same-sized primary surface when
297 * the display dimensions change.
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).
309 ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
311 /* Release the old primary surface */
312 (*s_pScreenPriv
->pwinReleasePrimarySurface
) (s_pScreen
);
314 /* Create the new primary surface */
315 (*s_pScreenPriv
->pwinCreatePrimarySurface
) (s_pScreen
);
328 winDebug("winWindowProc - WM_SIZE\n");
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
337 || s_pScreenInfo
->fRootless
338 #ifdef XWIN_MULTIWINDOW
339 || s_pScreenInfo
->fMultiWindow
341 || s_pScreenInfo
->fFullScreen
)
344 /* No need to resize if we get minimized */
345 if (wParam
== SIZE_MINIMIZED
)
348 ErrorF("winWindowProc - WM_SIZE - new client area w: %d h: %d\n",
349 LOWORD(lParam
), HIWORD(lParam
));
351 if (s_pScreenInfo
->iResizeMode
== resizeWithRandr
) {
352 /* Actual resizing is done on WM_EXITSIZEMOVE */
356 /* Otherwise iResizeMode == resizeWithScrollbars */
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.
371 GetWindowRect(hwnd
, &rcWindow
);
372 iWidth
= rcWindow
.right
- rcWindow
.left
;
373 iHeight
= rcWindow
.bottom
- rcWindow
.top
;
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
));
381 * Update scrollbar page sizes.
382 * NOTE: If page size == range, then the scrollbar is
383 * automatically hidden.
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
);
394 /* Set the horizontal scrollbar page size */
395 si
.cbSize
= sizeof(si
);
396 si
.fMask
= SIF_PAGE
| SIF_RANGE
;
398 si
.nMax
= s_pScreenInfo
->dwWidth
- 1;
400 SetScrollInfo(hwnd
, SB_HORZ
, &si
, TRUE
);
402 /* Set the vertical scrollbar page size */
403 si
.cbSize
= sizeof(si
);
404 si
.fMask
= SIF_PAGE
| SIF_RANGE
;
406 si
.nMax
= s_pScreenInfo
->dwHeight
- 1;
408 SetScrollInfo(hwnd
, SB_VERT
, &si
, TRUE
);
411 * NOTE: Scrollbars may have moved if they were at the
412 * far right/bottom, so we query their current position.
415 /* Get the horizontal scrollbar position and set the offset */
416 si
.cbSize
= sizeof(si
);
418 GetScrollInfo(hwnd
, SB_HORZ
, &si
);
419 s_pScreenInfo
->dwXOffset
= -si
.nPos
;
421 /* Get the vertical scrollbar position and set the offset */
422 si
.cbSize
= sizeof(si
);
424 GetScrollInfo(hwnd
, SB_VERT
, &si
);
425 s_pScreenInfo
->dwYOffset
= -si
.nPos
;
430 if (s_pScreenInfo
->iResizeMode
== resizeWithRandr
&&
431 ((wParam
& 0xfff0) == SC_MAXIMIZE
||
432 (wParam
& 0xfff0) == SC_RESTORE
))
433 PostMessage(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
436 case WM_ENTERSIZEMOVE
:
437 ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n");
440 case WM_EXITSIZEMOVE
:
441 ErrorF("winWindowProc - WM_EXITSIZEMOVE\n");
443 if (s_pScreenInfo
->iResizeMode
== resizeWithRandr
) {
444 /* Set screen size to match new client area, if it is different to current */
446 DWORD dwWidth
, dwHeight
;
448 GetClientRect(hwnd
, &rcClient
);
449 dwWidth
= rcClient
.right
- rcClient
.left
;
450 dwHeight
= rcClient
.bottom
- rcClient
.top
;
452 if ((s_pScreenInfo
->dwWidth
!= dwWidth
) ||
453 (s_pScreenInfo
->dwHeight
!= dwHeight
)) {
454 /* mm = dots * (25.4 mm / inch) / (dots / inch) */
455 winDoRandRScreenSetSize(s_pScreen
,
458 (dwWidth
* 25.4) / monitorResolution
,
459 (dwHeight
* 25.4) / monitorResolution
);
471 winDebug("winWindowProc - WM_VSCROLL\n");
474 /* Get vertical scroll bar info */
475 si
.cbSize
= sizeof(si
);
477 GetScrollInfo(hwnd
, SB_VERT
, &si
);
479 /* Save the vertical position for comparison later */
484 * moving the scrollbar to the DOWN, scroll the content UP
486 switch (LOWORD(wParam
)) {
492 si
.nPos
= si
.nMax
- si
.nPage
+ 1;
512 si
.nPos
= si
.nTrackPos
;
520 * We retrieve the position after setting it,
521 * because Windows may adjust it.
524 SetScrollInfo(hwnd
, SB_VERT
, &si
, TRUE
);
525 GetScrollInfo(hwnd
, SB_VERT
, &si
);
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
;
532 /* Change displayed region in the window */
536 NULL
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
538 /* Redraw the window contents */
550 winDebug("winWindowProc - WM_HSCROLL\n");
553 /* Get horizontal scroll bar info */
554 si
.cbSize
= sizeof(si
);
556 GetScrollInfo(hwnd
, SB_HORZ
, &si
);
558 /* Save the horizontal position for comparison later */
563 * moving the scrollbar to the RIGHT, scroll the content LEFT
565 switch (LOWORD(wParam
)) {
571 si
.nPos
= si
.nMax
- si
.nPage
+ 1;
591 si
.nPos
= si
.nTrackPos
;
599 * We retrieve the position after setting it,
600 * because Windows may adjust it.
603 SetScrollInfo(hwnd
, SB_HORZ
, &si
, TRUE
);
604 GetScrollInfo(hwnd
, SB_HORZ
, &si
);
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
;
611 /* Change displayed region in the window */
614 0, NULL
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
616 /* Redraw the window contents */
622 case WM_GETMINMAXINFO
:
624 MINMAXINFO
*pMinMaxInfo
= (MINMAXINFO
*) lParam
;
626 int iBorderHeight
, iBorderWidth
;
629 winDebug("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n",
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
640 || s_pScreenInfo
->fRootless
641 #ifdef XWIN_MULTIWINDOW
642 || s_pScreenInfo
->fMultiWindow
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.
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?
659 /* Get the border and caption sizes */
660 iCaptionHeight
= GetSystemMetrics(SM_CYCAPTION
);
661 iBorderWidth
= 2 * GetSystemMetrics(SM_CXSIZEFRAME
);
662 iBorderHeight
= 2 * GetSystemMetrics(SM_CYSIZEFRAME
);
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
;
673 winDebug("winWindowProc - WM_ERASEBKGND\n");
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.
684 winDebug("winWindowProc - WM_PAINT\n");
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 */
695 /* Break out here if we don't have a valid paint routine */
696 if (s_pScreenPriv
->pwinBltExposedRegions
== NULL
)
699 /* Call the engine dependent repainter */
700 (*s_pScreenPriv
->pwinBltExposedRegions
) (s_pScreen
);
703 case WM_PALETTECHANGED
:
706 winDebug("winWindowProc - WM_PALETTECHANGED\n");
709 * Don't process if we don't have privates or a colormap,
710 * or if we have an invalid depth.
712 if (s_pScreenPriv
== NULL
713 || s_pScreenPriv
->pcmapInstalled
== NULL
714 || s_pScreenPriv
->fBadDepth
)
717 /* Return if we caused the palette to change */
718 if ((HWND
) wParam
== hwnd
) {
719 /* Redraw the screen */
720 (*s_pScreenPriv
->pwinRedrawScreen
) (s_pScreen
);
724 /* Reinstall the windows palette */
725 (*s_pScreenPriv
->pwinRealizeInstalledPalette
) (s_pScreen
);
727 /* Redraw the screen */
728 (*s_pScreenPriv
->pwinRedrawScreen
) (s_pScreen
);
733 /* We can't do anything without privates */
734 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
737 /* We can't do anything without g_pwinPointer */
738 if (g_pwinPointer
== NULL
)
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
);
747 /* Are we tracking yet? */
751 /* Setup data structure */
752 ZeroMemory(&tme
, sizeof(tme
));
753 tme
.cbSize
= sizeof(tme
);
754 tme
.dwFlags
= TME_LEAVE
;
755 tme
.hwndTrack
= hwnd
;
757 /* Call the tracking function */
758 if (!TrackMouseEvent(&tme
))
759 ErrorF("winWindowProc - TrackMouseEvent failed\n");
761 /* Flag that we are tracking now */
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 */
772 else if (g_fSoftwareCursor
&& !g_fCursor
&& !s_pScreenPriv
->fActive
773 && !s_pScreenInfo
->fLessPointer
) {
774 /* Show Windows cursor */
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
);
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.
794 /* We can't do anything without privates */
795 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
798 /* Non-client mouse movement, show Windows cursor */
799 if (g_fSoftwareCursor
&& !g_fCursor
) {
806 /* Mouse has left our client area */
808 /* Flag that we are no longer tracking */
811 /* Show the mouse cursor, if necessary */
812 if (g_fSoftwareCursor
&& !g_fCursor
) {
818 case WM_LBUTTONDBLCLK
:
820 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
822 if (s_pScreenInfo
->fRootless
823 #ifdef XWIN_MULTIWINDOWEXTWM
824 || s_pScreenInfo
->fMWExtWM
828 return winMouseButtonsHandle(s_pScreen
, ButtonPress
, Button1
, wParam
);
831 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
833 if (s_pScreenInfo
->fRootless
834 #ifdef XWIN_MULTIWINDOWEXTWM
835 || s_pScreenInfo
->fMWExtWM
839 return winMouseButtonsHandle(s_pScreen
, ButtonRelease
, Button1
, wParam
);
841 case WM_MBUTTONDBLCLK
:
843 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
845 if (s_pScreenInfo
->fRootless
846 #ifdef XWIN_MULTIWINDOWEXTWM
847 || s_pScreenInfo
->fMWExtWM
851 return winMouseButtonsHandle(s_pScreen
, ButtonPress
, Button2
, wParam
);
854 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
856 if (s_pScreenInfo
->fRootless
857 #ifdef XWIN_MULTIWINDOWEXTWM
858 || s_pScreenInfo
->fMWExtWM
862 return winMouseButtonsHandle(s_pScreen
, ButtonRelease
, Button2
, wParam
);
864 case WM_RBUTTONDBLCLK
:
866 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
868 if (s_pScreenInfo
->fRootless
869 #ifdef XWIN_MULTIWINDOWEXTWM
870 || s_pScreenInfo
->fMWExtWM
874 return winMouseButtonsHandle(s_pScreen
, ButtonPress
, Button3
, wParam
);
877 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
879 if (s_pScreenInfo
->fRootless
880 #ifdef XWIN_MULTIWINDOWEXTWM
881 || s_pScreenInfo
->fMWExtWM
885 return winMouseButtonsHandle(s_pScreen
, ButtonRelease
, Button3
, wParam
);
887 case WM_XBUTTONDBLCLK
:
889 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
891 if (s_pScreenInfo
->fRootless
892 #ifdef XWIN_MULTIWINDOWEXTWM
893 || s_pScreenInfo
->fMWExtWM
897 return winMouseButtonsHandle(s_pScreen
, ButtonPress
, HIWORD(wParam
) + 7,
900 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
902 if (s_pScreenInfo
->fRootless
903 #ifdef XWIN_MULTIWINDOWEXTWM
904 || s_pScreenInfo
->fMWExtWM
908 return winMouseButtonsHandle(s_pScreen
, ButtonRelease
,
909 HIWORD(wParam
) + 7, wParam
);
912 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
915 /* Branch on the timer id */
917 case WIN_E3B_TIMER_ID
:
918 /* Send delayed button press */
919 winMouseButtonsSendEvent(ButtonPress
,
920 s_pScreenPriv
->iE3BCachedPress
);
922 /* Kill this timer */
923 KillTimer(s_pScreenPriv
->hwndScreen
, WIN_E3B_TIMER_ID
);
925 /* Clear screen privates flags */
926 s_pScreenPriv
->iE3BCachedPress
= 0;
929 case WIN_POLLING_MOUSE_TIMER_ID
:
931 static POINT last_point
;
933 WPARAM wL
, wM
, wR
, wShift
, wCtrl
;
936 /* Get the current position of the mouse cursor */
937 GetCursorPos(&point
);
939 /* Map from screen (-X, -Y) to root (0, 0) */
940 point
.x
-= GetSystemMetrics(SM_XVIRTUALSCREEN
);
941 point
.y
-= GetSystemMetrics(SM_YVIRTUALSCREEN
);
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
;
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
);
968 case WM_CTLCOLORSCROLLBAR
:
969 FatalError("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not "
970 "supposed to get this message. Exiting.\n");
974 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
977 winDebug("winWindowProc - WM_MOUSEWHEEL\n");
979 /* Button4 = WheelUp */
980 /* Button5 = WheelDown */
981 winMouseWheel(&(s_pScreenPriv
->iDeltaZ
), GET_WHEEL_DELTA_WPARAM(wParam
), Button4
, Button5
);
985 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
988 winDebug("winWindowProc - WM_MOUSEHWHEEL\n");
990 /* Button7 = TiltRight */
991 /* Button6 = TiltLeft */
992 winMouseWheel(&(s_pScreenPriv
->iDeltaV
), GET_WHEEL_DELTA_WPARAM(wParam
), 7, 6);
996 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
999 /* Restore the state of all mode keys */
1000 winRestoreModeKeyStates();
1002 /* Add the keyboard hook if possible */
1003 if (g_fKeyboardHookLL
)
1004 g_fKeyboardHookLL
= winInstallKeyboardHookLL();
1008 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
1011 /* Release any pressed keys */
1012 winKeybdReleaseKeys();
1014 /* Remove our keyboard hook if it is installed */
1015 winRemoveKeyboardHookLL();
1020 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
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.
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))) {
1038 * Better leave this message here, just in case some unsuspecting
1039 * user enters Alt + F4 and is surprised when the application
1042 ErrorF("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n");
1044 /* Display Exit dialog */
1045 winDisplayExitDialog(s_pScreenPriv
);
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.
1054 if ((wParam
== VK_LWIN
|| wParam
== VK_RWIN
) && !g_fKeyboardHookLL
)
1057 /* Discard fake Ctrl_L events that precede AltGR on non-US keyboards */
1058 if (winIsFakeCtrl_L(message
, wParam
, lParam
))
1062 * Discard presses generated from Windows auto-repeat
1064 if (lParam
& (1 << 30)) {
1066 /* ago: Pressing LControl while RControl is pressed is
1067 * Indicated as repeat. Fix this!
1071 if (winCheckKeyPressed(wParam
, lParam
))
1079 /* Translate Windows key code to X scan code */
1080 iScanCode
= winTranslateKey(wParam
, lParam
);
1082 /* Ignore repeats for CapsLock */
1083 if (wParam
== VK_CAPITAL
)
1086 /* Send the key event(s) */
1087 for (i
= 0; i
< LOWORD(lParam
); ++i
)
1088 winSendKeyEvent(iScanCode
, TRUE
);
1093 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
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.
1101 if ((wParam
== VK_LWIN
|| wParam
== VK_RWIN
) && !g_fKeyboardHookLL
)
1104 /* Ignore the fake Ctrl_L that follows an AltGr release */
1105 if (winIsFakeCtrl_L(message
, wParam
, lParam
))
1108 /* Enqueue a keyup event */
1109 iScanCode
= winTranslateKey(wParam
, lParam
);
1110 winSendKeyEvent(iScanCode
, FALSE
);
1112 /* Release all pressed shift keys */
1113 if (wParam
== VK_SHIFT
)
1114 winFixShiftKeys(iScanCode
);
1118 if (s_pScreenPriv
== NULL
)
1121 /* Call the engine-specific hot key handler */
1122 (*s_pScreenPriv
->pwinHotKeyAltTab
) (s_pScreen
);
1126 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
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");
1134 /* Minimize the window */
1135 ShowWindow(hwnd
, SW_MINIMIZE
);
1137 /* Display dialog box */
1138 if (g_hDlgDepthChange
!= NULL
) {
1139 /* Make the existing dialog box active */
1140 SetActiveWindow(g_hDlgDepthChange
);
1143 /* TODO: Recreate the dialog box and bring to the top */
1144 ShowWindow(g_hDlgDepthChange
, SW_SHOWDEFAULT
);
1147 /* Don't do any other processing of this message */
1152 winDebug("winWindowProc - WM_ACTIVATE\n");
1156 * Focus is being changed to another window.
1157 * The other window may or may not belong to
1161 /* Clear any lingering wheel delta */
1162 s_pScreenPriv
->iDeltaZ
= 0;
1163 s_pScreenPriv
->iDeltaV
= 0;
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 */
1173 case WM_ACTIVATEAPP
:
1174 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
1177 #if CYGDEBUG || TRUE
1178 winDebug("winWindowProc - WM_ACTIVATEAPP\n");
1181 /* Activate or deactivate */
1182 s_pScreenPriv
->fActive
= wParam
;
1184 /* Reshow the Windows mouse cursor if we are being deactivated */
1185 if (g_fSoftwareCursor
&& !s_pScreenPriv
->fActive
&& !g_fCursor
) {
1186 /* Show Windows cursor */
1191 #ifdef XWIN_CLIPBOARD
1192 /* Make sure the clipboard chain is ok. */
1193 winFixClipboardChain();
1196 /* Call engine specific screen activation/deactivation function */
1197 (*s_pScreenPriv
->pwinActivateApp
) (s_pScreen
);
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
);
1210 switch (LOWORD(wParam
)) {
1212 /* Display Exit dialog */
1213 winDisplayExitDialog(s_pScreenPriv
);
1216 #ifdef XWIN_MULTIWINDOW
1217 case ID_APP_HIDE_ROOT
:
1218 if (s_pScreenPriv
->fRootWindowShown
)
1219 ShowWindow(s_pScreenPriv
->hwndScreen
, SW_HIDE
);
1221 ShowWindow(s_pScreenPriv
->hwndScreen
, SW_SHOW
);
1222 s_pScreenPriv
->fRootWindowShown
= !s_pScreenPriv
->fRootWindowShown
;
1227 /* Display the About box */
1228 winDisplayAboutDialog(s_pScreenPriv
);
1232 /* It's probably one of the custom menus... */
1233 if (HandleCustomWM_COMMAND(0, LOWORD(wParam
)))
1239 /* Tell X that we are giving up */
1240 #ifdef XWIN_MULTIWINDOW
1241 if (s_pScreenInfo
->fMultiWindow
)
1242 winDeinitMultiWindowWM();
1248 /* Display Exit dialog */
1249 winDisplayExitDialog(s_pScreenPriv
);
1253 if (LOWORD(lParam
) == HTCLIENT
) {
1254 if (!g_fSoftwareCursor
)
1255 SetCursor(s_pScreenPriv
->cursor
.handle
);
1260 #ifdef XWIN_MULTIWINDOWEXTWM
1262 ErrorF("winWindowProc - WM_MANAGE\n");
1263 s_pScreenInfo
->fAnotherWMRunning
= FALSE
;
1265 if (s_pScreenInfo
->fInternalWM
) {
1266 EnumThreadWindows(g_dwCurrentThreadID
, winMWExtWMDecorateWindow
, 0);
1267 //RootlessRepositionWindows (s_pScreen);
1272 ErrorF("winWindowProc - WM_UNMANAGE\n");
1273 s_pScreenInfo
->fAnotherWMRunning
= TRUE
;
1275 if (s_pScreenInfo
->fInternalWM
) {
1276 EnumThreadWindows(g_dwCurrentThreadID
, winMWExtWMDecorateWindow
, 0);
1277 winMWExtWMRestackWindows(s_pScreen
);
1283 if (message
== s_uTaskbarRestart
) {
1284 winInitNotifyIcon(s_pScreenPriv
);
1289 return DefWindowProc(hwnd
, message
, wParam
, lParam
);