105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
305b261ecSmrg *
405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
505b261ecSmrg * a copy of this software and associated documentation files (the
605b261ecSmrg *"Software"), to deal in the Software without restriction, including
705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1005b261ecSmrg *the following conditions:
1105b261ecSmrg *
1205b261ecSmrg *The above copyright notice and this permission notice shall be
1305b261ecSmrg *included in all copies or substantial portions of the Software.
1405b261ecSmrg *
1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project
2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2505b261ecSmrg *or other dealings in this Software without prior written authorization
2605b261ecSmrg *from the XFree86 Project.
2705b261ecSmrg *
2805b261ecSmrg * Authors:	Dakshinamurthy Karra
2905b261ecSmrg *		Suhaib M Siddiqi
3005b261ecSmrg *		Peter Busch
3105b261ecSmrg *		Harold L Hunt II
3205b261ecSmrg *		MATSUZAKI Kensuke
3305b261ecSmrg */
3405b261ecSmrg
3505b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3605b261ecSmrg#include <xwin-config.h>
3705b261ecSmrg#endif
3805b261ecSmrg#include "win.h"
3905b261ecSmrg#include <commctrl.h>
4005b261ecSmrg#include "winprefs.h"
4105b261ecSmrg#include "winconfig.h"
4205b261ecSmrg#include "winmsg.h"
439ace9065Smrg#include "winmonitors.h"
4405b261ecSmrg#include "inputstr.h"
4535c4bbdfSmrg#include "winclipboard/winclipboard.h"
4605b261ecSmrg
4705b261ecSmrg/*
4805b261ecSmrg * Global variables
4905b261ecSmrg */
5005b261ecSmrg
5135c4bbdfSmrgBool g_fCursor = TRUE;
5235c4bbdfSmrgBool g_fButton[3] = { FALSE, FALSE, FALSE };
5305b261ecSmrg
5405b261ecSmrg/*
5505b261ecSmrg * Called by winWakeupHandler
5605b261ecSmrg * Processes current Windows message
5705b261ecSmrg */
5805b261ecSmrg
5905b261ecSmrgLRESULT CALLBACK
6035c4bbdfSmrgwinWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6105b261ecSmrg{
6235c4bbdfSmrg    static winPrivScreenPtr s_pScreenPriv = NULL;
6335c4bbdfSmrg    static winScreenInfo *s_pScreenInfo = NULL;
6435c4bbdfSmrg    static ScreenPtr s_pScreen = NULL;
6535c4bbdfSmrg    static HWND s_hwndLastPrivates = NULL;
6635c4bbdfSmrg    static Bool s_fTracking = FALSE;
6735c4bbdfSmrg    static unsigned long s_ulServerGeneration = 0;
6835c4bbdfSmrg    static UINT s_uTaskbarRestart = 0;
6935c4bbdfSmrg    int iScanCode;
7035c4bbdfSmrg    int i;
7105b261ecSmrg
7205b261ecSmrg#if CYGDEBUG
7335c4bbdfSmrg    winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam);
7405b261ecSmrg#endif
7535c4bbdfSmrg
7635c4bbdfSmrg    /* Watch for server regeneration */
7735c4bbdfSmrg    if (g_ulServerGeneration != s_ulServerGeneration) {
7835c4bbdfSmrg        /* Store new server generation */
7935c4bbdfSmrg        s_ulServerGeneration = g_ulServerGeneration;
8005b261ecSmrg    }
8105b261ecSmrg
8235c4bbdfSmrg    /* Only retrieve new privates pointers if window handle is null or changed */
8335c4bbdfSmrg    if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates)
8435c4bbdfSmrg        && (s_pScreenPriv = GetProp(hwnd, WIN_SCR_PROP)) != NULL) {
8505b261ecSmrg#if CYGDEBUG
8635c4bbdfSmrg        winDebug("winWindowProc - Setting privates handle\n");
8705b261ecSmrg#endif
8835c4bbdfSmrg        s_pScreenInfo = s_pScreenPriv->pScreenInfo;
8935c4bbdfSmrg        s_pScreen = s_pScreenInfo->pScreen;
9035c4bbdfSmrg        s_hwndLastPrivates = hwnd;
9105b261ecSmrg    }
9235c4bbdfSmrg    else if (s_pScreenPriv == NULL) {
9335c4bbdfSmrg        /* For safety, handle case that should never happen */
9435c4bbdfSmrg        s_pScreenInfo = NULL;
9535c4bbdfSmrg        s_pScreen = NULL;
9635c4bbdfSmrg        s_hwndLastPrivates = NULL;
9705b261ecSmrg    }
9805b261ecSmrg
9935c4bbdfSmrg    /* Branch on message type */
10035c4bbdfSmrg    switch (message) {
10105b261ecSmrg    case WM_TRAYICON:
10235c4bbdfSmrg        return winHandleIconMessage(hwnd, message, wParam, lParam,
10335c4bbdfSmrg                                    s_pScreenPriv);
10405b261ecSmrg
10505b261ecSmrg    case WM_CREATE:
10605b261ecSmrg#if CYGDEBUG
10735c4bbdfSmrg        winDebug("winWindowProc - WM_CREATE\n");
10805b261ecSmrg#endif
10935c4bbdfSmrg
11035c4bbdfSmrg        /*
11135c4bbdfSmrg         * Add a property to our display window that references
11235c4bbdfSmrg         * this screens' privates.
11335c4bbdfSmrg         *
11435c4bbdfSmrg         * This allows the window procedure to refer to the
11535c4bbdfSmrg         * appropriate window DC and shadow DC for the window that
11635c4bbdfSmrg         * it is processing.  We use this to repaint exposed
11735c4bbdfSmrg         * areas of our display window.
11835c4bbdfSmrg         */
11935c4bbdfSmrg        s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams;
12035c4bbdfSmrg        s_pScreenInfo = s_pScreenPriv->pScreenInfo;
12135c4bbdfSmrg        s_pScreen = s_pScreenInfo->pScreen;
12235c4bbdfSmrg        s_hwndLastPrivates = hwnd;
12335c4bbdfSmrg        s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
12435c4bbdfSmrg        SetProp(hwnd, WIN_SCR_PROP, s_pScreenPriv);
12535c4bbdfSmrg
12635c4bbdfSmrg        /* Setup tray icon */
12735c4bbdfSmrg        if (!s_pScreenInfo->fNoTrayIcon) {
12835c4bbdfSmrg            /*
12935c4bbdfSmrg             * NOTE: The WM_CREATE message is processed before CreateWindowEx
13035c4bbdfSmrg             * returns, so s_pScreenPriv->hwndScreen is invalid at this point.
13135c4bbdfSmrg             * We go ahead and copy our hwnd parameter over top of the screen
13235c4bbdfSmrg             * privates hwndScreen so that we have a valid value for
13335c4bbdfSmrg             * that member.  Otherwise, the tray icon will disappear
13435c4bbdfSmrg             * the first time you move the mouse over top of it.
13535c4bbdfSmrg             */
13635c4bbdfSmrg
13735c4bbdfSmrg            s_pScreenPriv->hwndScreen = hwnd;
13835c4bbdfSmrg
13935c4bbdfSmrg            winInitNotifyIcon(s_pScreenPriv);
14035c4bbdfSmrg        }
14135c4bbdfSmrg        return 0;
14205b261ecSmrg
14305b261ecSmrg    case WM_DISPLAYCHANGE:
14435c4bbdfSmrg        /*
14535c4bbdfSmrg           WM_DISPLAYCHANGE seems to be sent when the monitor layout or
146ed6184dfSmrg           any monitor's resolution or depth changes, but its lParam and
14735c4bbdfSmrg           wParam always indicate the resolution and bpp for the primary
14835c4bbdfSmrg           monitor (so ignore that as we could be on any monitor...)
14935c4bbdfSmrg         */
15035c4bbdfSmrg
15135c4bbdfSmrg        /* We cannot handle a display mode change during initialization */
15235c4bbdfSmrg        if (s_pScreenInfo == NULL)
15335c4bbdfSmrg            FatalError("winWindowProc - WM_DISPLAYCHANGE - The display "
154ed6184dfSmrg                       "mode changed while we were initializing.  This is "
15535c4bbdfSmrg                       "very bad and unexpected.  Exiting.\n");
15635c4bbdfSmrg
15735c4bbdfSmrg        /*
15835c4bbdfSmrg         * We do not care about display changes with
15935c4bbdfSmrg         * fullscreen DirectDraw engines, because those engines set
16035c4bbdfSmrg         * their own mode when they become active.
16135c4bbdfSmrg         */
16235c4bbdfSmrg        if (s_pScreenInfo->fFullScreen
1631b5d61b8Smrg            && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)) {
16435c4bbdfSmrg            break;
16535c4bbdfSmrg        }
1669ace9065Smrg
16735c4bbdfSmrg        ErrorF("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
16835c4bbdfSmrg               "new height: %d new bpp: %d\n",
16935c4bbdfSmrg               LOWORD(lParam), HIWORD(lParam), (int)wParam);
1709ace9065Smrg
17135c4bbdfSmrg        /* 0 bpp has no defined meaning, ignore this message */
17235c4bbdfSmrg        if (wParam == 0)
17335c4bbdfSmrg            break;
1749ace9065Smrg
17535c4bbdfSmrg        /*
17635c4bbdfSmrg         * Check for a disruptive change in depth.
17735c4bbdfSmrg         * We can only display a message for a disruptive depth change,
17835c4bbdfSmrg         * we cannot do anything to correct the situation.
17935c4bbdfSmrg         */
18035c4bbdfSmrg        /*
18135c4bbdfSmrg           XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT)
18235c4bbdfSmrg           has changed as well...
18335c4bbdfSmrg         */
18435c4bbdfSmrg        if (s_pScreenInfo->dwBPP !=
18535c4bbdfSmrg            GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL)) {
18635c4bbdfSmrg            if (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL) {
18735c4bbdfSmrg                /* Cannot display the visual until the depth is restored */
18835c4bbdfSmrg                ErrorF("winWindowProc - Disruptive change in depth\n");
18935c4bbdfSmrg
19035c4bbdfSmrg                /* Display depth change dialog */
19135c4bbdfSmrg                winDisplayDepthChangeDialog(s_pScreenPriv);
19235c4bbdfSmrg
19335c4bbdfSmrg                /* Flag that we have an invalid screen depth */
19435c4bbdfSmrg                s_pScreenPriv->fBadDepth = TRUE;
19535c4bbdfSmrg
19635c4bbdfSmrg                /* Minimize the display window */
19735c4bbdfSmrg                ShowWindow(hwnd, SW_MINIMIZE);
1989ace9065Smrg            }
19935c4bbdfSmrg            else {
20035c4bbdfSmrg                /* For GDI, performance may suffer until original depth is restored */
20135c4bbdfSmrg                ErrorF
20235c4bbdfSmrg                    ("winWindowProc - Performance may be non-optimal after change in depth\n");
2039ace9065Smrg            }
2049ace9065Smrg        }
20535c4bbdfSmrg        else {
20635c4bbdfSmrg            /* Flag that we have a valid screen depth */
20735c4bbdfSmrg            s_pScreenPriv->fBadDepth = FALSE;
2089ace9065Smrg        }
2099ace9065Smrg
21035c4bbdfSmrg        /*
21135c4bbdfSmrg           If we could cheaply check if this WM_DISPLAYCHANGE change
21235c4bbdfSmrg           affects the monitor(s) which this X screen is displayed on
21335c4bbdfSmrg           then we should do so here.  For the moment, assume it does.
21435c4bbdfSmrg           (this is probably usually the case so that might be an
21535c4bbdfSmrg           overoptimization)
21635c4bbdfSmrg         */
21735c4bbdfSmrg        {
21835c4bbdfSmrg            /*
21935c4bbdfSmrg               In rootless modes which are monitor or virtual desktop size
22035c4bbdfSmrg               use RandR to resize the X screen
22135c4bbdfSmrg             */
22235c4bbdfSmrg            if ((!s_pScreenInfo->fUserGaveHeightAndWidth) &&
223ed6184dfSmrg                (s_pScreenInfo->iResizeMode == resizeWithRandr) && (s_pScreenInfo->
22435c4bbdfSmrg                                                                    fRootless
22535c4bbdfSmrg                                                                    ||
22635c4bbdfSmrg                                                                    s_pScreenInfo->
22735c4bbdfSmrg                                                                    fMultiWindow
22835c4bbdfSmrg                )) {
2291b5d61b8Smrg                DWORD dwWidth = 0, dwHeight = 0;
23035c4bbdfSmrg
23135c4bbdfSmrg                if (s_pScreenInfo->fMultipleMonitors) {
23235c4bbdfSmrg                    /* resize to new virtual desktop size */
23335c4bbdfSmrg                    dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
23435c4bbdfSmrg                    dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
2359ace9065Smrg                }
23635c4bbdfSmrg                else {
23735c4bbdfSmrg                    /* resize to new size of specified monitor */
23835c4bbdfSmrg                    struct GetMonitorInfoData data;
23935c4bbdfSmrg
24035c4bbdfSmrg                    if (QueryMonitor(s_pScreenInfo->iMonitor, &data)) {
24135c4bbdfSmrg                            dwWidth = data.monitorWidth;
24235c4bbdfSmrg                            dwHeight = data.monitorHeight;
24335c4bbdfSmrg                            /*
24435c4bbdfSmrg                               XXX: monitor may have changed position,
24535c4bbdfSmrg                               so we might need to update xinerama data
24635c4bbdfSmrg                             */
2479ace9065Smrg                        }
24835c4bbdfSmrg                        else {
24935c4bbdfSmrg                            ErrorF("Monitor number %d no longer exists!\n",
25035c4bbdfSmrg                                   s_pScreenInfo->iMonitor);
2519ace9065Smrg                        }
2529ace9065Smrg                }
2539ace9065Smrg
25435c4bbdfSmrg                /*
25535c4bbdfSmrg                   XXX: probably a small bug here: we don't compute the work area
25635c4bbdfSmrg                   and allow for task bar
25735c4bbdfSmrg
25835c4bbdfSmrg                   XXX: generally, we don't allow for the task bar being moved after
25935c4bbdfSmrg                   the server is started
26035c4bbdfSmrg                 */
26135c4bbdfSmrg
26235c4bbdfSmrg                /* Set screen size to match new size, if it is different to current */
2631b5d61b8Smrg                if (((dwWidth != 0) && (dwHeight != 0)) &&
2641b5d61b8Smrg                    ((s_pScreenInfo->dwWidth != dwWidth) ||
2651b5d61b8Smrg                     (s_pScreenInfo->dwHeight != dwHeight))) {
26635c4bbdfSmrg                    winDoRandRScreenSetSize(s_pScreen,
26735c4bbdfSmrg                                            dwWidth,
26835c4bbdfSmrg                                            dwHeight,
26935c4bbdfSmrg                                            (dwWidth * 25.4) /
27035c4bbdfSmrg                                            monitorResolution,
27135c4bbdfSmrg                                            (dwHeight * 25.4) /
27235c4bbdfSmrg                                            monitorResolution);
2739ace9065Smrg                }
2749ace9065Smrg            }
27535c4bbdfSmrg            else {
27635c4bbdfSmrg                /*
27735c4bbdfSmrg                 * We can simply recreate the same-sized primary surface when
27835c4bbdfSmrg                 * the display dimensions change.
27935c4bbdfSmrg                 */
28035c4bbdfSmrg
28135c4bbdfSmrg                winDebug
28235c4bbdfSmrg                    ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
28335c4bbdfSmrg
28435c4bbdfSmrg                /* Release the old primary surface */
2851b5d61b8Smrg                if (*s_pScreenPriv->pwinReleasePrimarySurface)
2861b5d61b8Smrg                    (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
28735c4bbdfSmrg
28835c4bbdfSmrg                /* Create the new primary surface */
2891b5d61b8Smrg                if (*s_pScreenPriv->pwinCreatePrimarySurface)
2901b5d61b8Smrg                    (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
29135c4bbdfSmrg            }
29235c4bbdfSmrg        }
29305b261ecSmrg
29435c4bbdfSmrg        break;
29505b261ecSmrg
29605b261ecSmrg    case WM_SIZE:
29735c4bbdfSmrg    {
29835c4bbdfSmrg        SCROLLINFO si;
29935c4bbdfSmrg        RECT rcWindow;
30035c4bbdfSmrg        int iWidth, iHeight;
30105b261ecSmrg
30205b261ecSmrg#if CYGDEBUG
30335c4bbdfSmrg        winDebug("winWindowProc - WM_SIZE\n");
30405b261ecSmrg#endif
30505b261ecSmrg
30635c4bbdfSmrg        /* Break if we do not allow resizing */
3071b5d61b8Smrg        if ((s_pScreenInfo->iResizeMode == resizeNotAllowed)
30835c4bbdfSmrg            || !s_pScreenInfo->fDecoration
30935c4bbdfSmrg            || s_pScreenInfo->fRootless
31035c4bbdfSmrg            || s_pScreenInfo->fMultiWindow
31135c4bbdfSmrg            || s_pScreenInfo->fFullScreen)
31235c4bbdfSmrg            break;
31305b261ecSmrg
31435c4bbdfSmrg        /* No need to resize if we get minimized */
31535c4bbdfSmrg        if (wParam == SIZE_MINIMIZED)
31635c4bbdfSmrg            return 0;
31705b261ecSmrg
31835c4bbdfSmrg        ErrorF("winWindowProc - WM_SIZE - new client area w: %d h: %d\n",
31935c4bbdfSmrg               LOWORD(lParam), HIWORD(lParam));
3209ace9065Smrg
32135c4bbdfSmrg        if (s_pScreenInfo->iResizeMode == resizeWithRandr) {
3229ace9065Smrg            /* Actual resizing is done on WM_EXITSIZEMOVE */
3239ace9065Smrg            return 0;
32435c4bbdfSmrg        }
3259ace9065Smrg
3269ace9065Smrg        /* Otherwise iResizeMode == resizeWithScrollbars */
3279ace9065Smrg
32835c4bbdfSmrg        /*
32935c4bbdfSmrg         * Get the size of the whole window, including client area,
33035c4bbdfSmrg         * scrollbars, and non-client area decorations (caption, borders).
33135c4bbdfSmrg         * We do this because we need to check if the client area
33235c4bbdfSmrg         * without scrollbars is large enough to display the whole visual.
33335c4bbdfSmrg         * The new client area size passed by lParam already subtracts
33435c4bbdfSmrg         * the size of the scrollbars if they are currently displayed.
33535c4bbdfSmrg         * So checking is LOWORD(lParam) == visual_width and
33635c4bbdfSmrg         * HIWORD(lParam) == visual_height will never tell us to hide
33735c4bbdfSmrg         * the scrollbars because the client area would always be too small.
33835c4bbdfSmrg         * GetClientRect returns the same sizes given by lParam, so we
33935c4bbdfSmrg         * cannot use GetClientRect either.
34035c4bbdfSmrg         */
34135c4bbdfSmrg        GetWindowRect(hwnd, &rcWindow);
34235c4bbdfSmrg        iWidth = rcWindow.right - rcWindow.left;
34335c4bbdfSmrg        iHeight = rcWindow.bottom - rcWindow.top;
34435c4bbdfSmrg
34535c4bbdfSmrg        /* Subtract the frame size from the window size. */
34635c4bbdfSmrg        iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
34735c4bbdfSmrg        iHeight -= (2 * GetSystemMetrics(SM_CYSIZEFRAME)
34835c4bbdfSmrg                    + GetSystemMetrics(SM_CYCAPTION));
34935c4bbdfSmrg
35035c4bbdfSmrg        /*
35135c4bbdfSmrg         * Update scrollbar page sizes.
35235c4bbdfSmrg         * NOTE: If page size == range, then the scrollbar is
35335c4bbdfSmrg         * automatically hidden.
35435c4bbdfSmrg         */
35535c4bbdfSmrg
35635c4bbdfSmrg        /* Is the naked client area large enough to show the whole visual? */
35735c4bbdfSmrg        if (iWidth < s_pScreenInfo->dwWidth
35835c4bbdfSmrg            || iHeight < s_pScreenInfo->dwHeight) {
35935c4bbdfSmrg            /* Client area too small to display visual, use scrollbars */
36035c4bbdfSmrg            iWidth -= GetSystemMetrics(SM_CXVSCROLL);
36135c4bbdfSmrg            iHeight -= GetSystemMetrics(SM_CYHSCROLL);
36235c4bbdfSmrg        }
36335c4bbdfSmrg
36435c4bbdfSmrg        /* Set the horizontal scrollbar page size */
36535c4bbdfSmrg        si.cbSize = sizeof(si);
36635c4bbdfSmrg        si.fMask = SIF_PAGE | SIF_RANGE;
36735c4bbdfSmrg        si.nMin = 0;
36835c4bbdfSmrg        si.nMax = s_pScreenInfo->dwWidth - 1;
36935c4bbdfSmrg        si.nPage = iWidth;
37035c4bbdfSmrg        SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
37135c4bbdfSmrg
37235c4bbdfSmrg        /* Set the vertical scrollbar page size */
37335c4bbdfSmrg        si.cbSize = sizeof(si);
37435c4bbdfSmrg        si.fMask = SIF_PAGE | SIF_RANGE;
37535c4bbdfSmrg        si.nMin = 0;
37635c4bbdfSmrg        si.nMax = s_pScreenInfo->dwHeight - 1;
37735c4bbdfSmrg        si.nPage = iHeight;
37835c4bbdfSmrg        SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
37935c4bbdfSmrg
38035c4bbdfSmrg        /*
38135c4bbdfSmrg         * NOTE: Scrollbars may have moved if they were at the
38235c4bbdfSmrg         * far right/bottom, so we query their current position.
38335c4bbdfSmrg         */
38435c4bbdfSmrg
38535c4bbdfSmrg        /* Get the horizontal scrollbar position and set the offset */
38635c4bbdfSmrg        si.cbSize = sizeof(si);
38735c4bbdfSmrg        si.fMask = SIF_POS;
38835c4bbdfSmrg        GetScrollInfo(hwnd, SB_HORZ, &si);
38935c4bbdfSmrg        s_pScreenInfo->dwXOffset = -si.nPos;
39035c4bbdfSmrg
39135c4bbdfSmrg        /* Get the vertical scrollbar position and set the offset */
39235c4bbdfSmrg        si.cbSize = sizeof(si);
39335c4bbdfSmrg        si.fMask = SIF_POS;
39435c4bbdfSmrg        GetScrollInfo(hwnd, SB_VERT, &si);
39535c4bbdfSmrg        s_pScreenInfo->dwYOffset = -si.nPos;
39635c4bbdfSmrg    }
39735c4bbdfSmrg        return 0;
39835c4bbdfSmrg
39935c4bbdfSmrg    case WM_SYSCOMMAND:
40035c4bbdfSmrg        if (s_pScreenInfo->iResizeMode == resizeWithRandr &&
40135c4bbdfSmrg            ((wParam & 0xfff0) == SC_MAXIMIZE ||
40235c4bbdfSmrg             (wParam & 0xfff0) == SC_RESTORE))
40335c4bbdfSmrg            PostMessage(hwnd, WM_EXITSIZEMOVE, 0, 0);
40435c4bbdfSmrg        break;
40505b261ecSmrg
4069ace9065Smrg    case WM_ENTERSIZEMOVE:
40735c4bbdfSmrg        ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n");
40835c4bbdfSmrg        break;
4099ace9065Smrg
4109ace9065Smrg    case WM_EXITSIZEMOVE:
41135c4bbdfSmrg        ErrorF("winWindowProc - WM_EXITSIZEMOVE\n");
41235c4bbdfSmrg
41335c4bbdfSmrg        if (s_pScreenInfo->iResizeMode == resizeWithRandr) {
41435c4bbdfSmrg            /* Set screen size to match new client area, if it is different to current */
41535c4bbdfSmrg            RECT rcClient;
41635c4bbdfSmrg            DWORD dwWidth, dwHeight;
41735c4bbdfSmrg
41835c4bbdfSmrg            GetClientRect(hwnd, &rcClient);
41935c4bbdfSmrg            dwWidth = rcClient.right - rcClient.left;
42035c4bbdfSmrg            dwHeight = rcClient.bottom - rcClient.top;
42135c4bbdfSmrg
42235c4bbdfSmrg            if ((s_pScreenInfo->dwWidth != dwWidth) ||
42335c4bbdfSmrg                (s_pScreenInfo->dwHeight != dwHeight)) {
42435c4bbdfSmrg                /* mm = dots * (25.4 mm / inch) / (dots / inch) */
42535c4bbdfSmrg                winDoRandRScreenSetSize(s_pScreen,
42635c4bbdfSmrg                                        dwWidth,
42735c4bbdfSmrg                                        dwHeight,
42835c4bbdfSmrg                                        (dwWidth * 25.4) / monitorResolution,
42935c4bbdfSmrg                                        (dwHeight * 25.4) / monitorResolution);
4309ace9065Smrg            }
4319ace9065Smrg        }
4329ace9065Smrg
43335c4bbdfSmrg        break;
4349ace9065Smrg
43505b261ecSmrg    case WM_VSCROLL:
43635c4bbdfSmrg    {
43735c4bbdfSmrg        SCROLLINFO si;
43835c4bbdfSmrg        int iVertPos;
43905b261ecSmrg
44005b261ecSmrg#if CYGDEBUG
44135c4bbdfSmrg        winDebug("winWindowProc - WM_VSCROLL\n");
44205b261ecSmrg#endif
44335c4bbdfSmrg
44435c4bbdfSmrg        /* Get vertical scroll bar info */
44535c4bbdfSmrg        si.cbSize = sizeof(si);
44635c4bbdfSmrg        si.fMask = SIF_ALL;
44735c4bbdfSmrg        GetScrollInfo(hwnd, SB_VERT, &si);
44835c4bbdfSmrg
44935c4bbdfSmrg        /* Save the vertical position for comparison later */
45035c4bbdfSmrg        iVertPos = si.nPos;
45135c4bbdfSmrg
45235c4bbdfSmrg        /*
45335c4bbdfSmrg         * Don't forget:
45435c4bbdfSmrg         * moving the scrollbar to the DOWN, scroll the content UP
45535c4bbdfSmrg         */
45635c4bbdfSmrg        switch (LOWORD(wParam)) {
45735c4bbdfSmrg        case SB_TOP:
45835c4bbdfSmrg            si.nPos = si.nMin;
45935c4bbdfSmrg            break;
46035c4bbdfSmrg
46135c4bbdfSmrg        case SB_BOTTOM:
46235c4bbdfSmrg            si.nPos = si.nMax - si.nPage + 1;
46335c4bbdfSmrg            break;
46435c4bbdfSmrg
46535c4bbdfSmrg        case SB_LINEUP:
46635c4bbdfSmrg            si.nPos -= 1;
46735c4bbdfSmrg            break;
46835c4bbdfSmrg
46935c4bbdfSmrg        case SB_LINEDOWN:
47035c4bbdfSmrg            si.nPos += 1;
47135c4bbdfSmrg            break;
47235c4bbdfSmrg
47335c4bbdfSmrg        case SB_PAGEUP:
47435c4bbdfSmrg            si.nPos -= si.nPage;
47535c4bbdfSmrg            break;
47635c4bbdfSmrg
47735c4bbdfSmrg        case SB_PAGEDOWN:
47835c4bbdfSmrg            si.nPos += si.nPage;
47935c4bbdfSmrg            break;
48035c4bbdfSmrg
48135c4bbdfSmrg        case SB_THUMBTRACK:
48235c4bbdfSmrg            si.nPos = si.nTrackPos;
48335c4bbdfSmrg            break;
48435c4bbdfSmrg
48535c4bbdfSmrg        default:
48635c4bbdfSmrg            break;
48735c4bbdfSmrg        }
48835c4bbdfSmrg
48935c4bbdfSmrg        /*
49035c4bbdfSmrg         * We retrieve the position after setting it,
49135c4bbdfSmrg         * because Windows may adjust it.
49235c4bbdfSmrg         */
49335c4bbdfSmrg        si.fMask = SIF_POS;
49435c4bbdfSmrg        SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
49535c4bbdfSmrg        GetScrollInfo(hwnd, SB_VERT, &si);
49635c4bbdfSmrg
49735c4bbdfSmrg        /* Scroll the window if the position has changed */
49835c4bbdfSmrg        if (si.nPos != iVertPos) {
49935c4bbdfSmrg            /* Save the new offset for bit block transfers, etc. */
50035c4bbdfSmrg            s_pScreenInfo->dwYOffset = -si.nPos;
50135c4bbdfSmrg
50235c4bbdfSmrg            /* Change displayed region in the window */
50335c4bbdfSmrg            ScrollWindowEx(hwnd,
50435c4bbdfSmrg                           0,
50535c4bbdfSmrg                           iVertPos - si.nPos,
50635c4bbdfSmrg                           NULL, NULL, NULL, NULL, SW_INVALIDATE);
50735c4bbdfSmrg
50835c4bbdfSmrg            /* Redraw the window contents */
50935c4bbdfSmrg            UpdateWindow(hwnd);
51035c4bbdfSmrg        }
51135c4bbdfSmrg    }
51235c4bbdfSmrg        return 0;
51305b261ecSmrg
51405b261ecSmrg    case WM_HSCROLL:
51535c4bbdfSmrg    {
51635c4bbdfSmrg        SCROLLINFO si;
51735c4bbdfSmrg        int iHorzPos;
51805b261ecSmrg
51905b261ecSmrg#if CYGDEBUG
52035c4bbdfSmrg        winDebug("winWindowProc - WM_HSCROLL\n");
52105b261ecSmrg#endif
52235c4bbdfSmrg
52335c4bbdfSmrg        /* Get horizontal scroll bar info */
52435c4bbdfSmrg        si.cbSize = sizeof(si);
52535c4bbdfSmrg        si.fMask = SIF_ALL;
52635c4bbdfSmrg        GetScrollInfo(hwnd, SB_HORZ, &si);
52735c4bbdfSmrg
52835c4bbdfSmrg        /* Save the horizontal position for comparison later */
52935c4bbdfSmrg        iHorzPos = si.nPos;
53035c4bbdfSmrg
53135c4bbdfSmrg        /*
53235c4bbdfSmrg         * Don't forget:
53335c4bbdfSmrg         * moving the scrollbar to the RIGHT, scroll the content LEFT
53435c4bbdfSmrg         */
53535c4bbdfSmrg        switch (LOWORD(wParam)) {
53635c4bbdfSmrg        case SB_LEFT:
53735c4bbdfSmrg            si.nPos = si.nMin;
53835c4bbdfSmrg            break;
53935c4bbdfSmrg
54035c4bbdfSmrg        case SB_RIGHT:
54135c4bbdfSmrg            si.nPos = si.nMax - si.nPage + 1;
54235c4bbdfSmrg            break;
54335c4bbdfSmrg
54435c4bbdfSmrg        case SB_LINELEFT:
54535c4bbdfSmrg            si.nPos -= 1;
54635c4bbdfSmrg            break;
54735c4bbdfSmrg
54835c4bbdfSmrg        case SB_LINERIGHT:
54935c4bbdfSmrg            si.nPos += 1;
55035c4bbdfSmrg            break;
55135c4bbdfSmrg
55235c4bbdfSmrg        case SB_PAGELEFT:
55335c4bbdfSmrg            si.nPos -= si.nPage;
55435c4bbdfSmrg            break;
55535c4bbdfSmrg
55635c4bbdfSmrg        case SB_PAGERIGHT:
55735c4bbdfSmrg            si.nPos += si.nPage;
55835c4bbdfSmrg            break;
55935c4bbdfSmrg
56035c4bbdfSmrg        case SB_THUMBTRACK:
56135c4bbdfSmrg            si.nPos = si.nTrackPos;
56235c4bbdfSmrg            break;
56335c4bbdfSmrg
56435c4bbdfSmrg        default:
56535c4bbdfSmrg            break;
56635c4bbdfSmrg        }
56735c4bbdfSmrg
56835c4bbdfSmrg        /*
56935c4bbdfSmrg         * We retrieve the position after setting it,
57035c4bbdfSmrg         * because Windows may adjust it.
57135c4bbdfSmrg         */
57235c4bbdfSmrg        si.fMask = SIF_POS;
57335c4bbdfSmrg        SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
57435c4bbdfSmrg        GetScrollInfo(hwnd, SB_HORZ, &si);
57535c4bbdfSmrg
57635c4bbdfSmrg        /* Scroll the window if the position has changed */
57735c4bbdfSmrg        if (si.nPos != iHorzPos) {
57835c4bbdfSmrg            /* Save the new offset for bit block transfers, etc. */
57935c4bbdfSmrg            s_pScreenInfo->dwXOffset = -si.nPos;
58035c4bbdfSmrg
58135c4bbdfSmrg            /* Change displayed region in the window */
58235c4bbdfSmrg            ScrollWindowEx(hwnd,
58335c4bbdfSmrg                           iHorzPos - si.nPos,
58435c4bbdfSmrg                           0, NULL, NULL, NULL, NULL, SW_INVALIDATE);
58535c4bbdfSmrg
58635c4bbdfSmrg            /* Redraw the window contents */
58735c4bbdfSmrg            UpdateWindow(hwnd);
58835c4bbdfSmrg        }
58935c4bbdfSmrg    }
59035c4bbdfSmrg        return 0;
59105b261ecSmrg
59205b261ecSmrg    case WM_GETMINMAXINFO:
59335c4bbdfSmrg    {
59435c4bbdfSmrg        MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam;
59535c4bbdfSmrg        int iCaptionHeight;
59635c4bbdfSmrg        int iBorderHeight, iBorderWidth;
59735c4bbdfSmrg
59835c4bbdfSmrg#if CYGDEBUG
59935c4bbdfSmrg        winDebug("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %p\n",
60035c4bbdfSmrg                 s_pScreenInfo);
60105b261ecSmrg#endif
60205b261ecSmrg
60335c4bbdfSmrg        /* Can't do anything without screen info */
60435c4bbdfSmrg        if (s_pScreenInfo == NULL
60535c4bbdfSmrg            || (s_pScreenInfo->iResizeMode != resizeWithScrollbars)
60635c4bbdfSmrg            || s_pScreenInfo->fFullScreen || !s_pScreenInfo->fDecoration
60735c4bbdfSmrg            || s_pScreenInfo->fRootless
60835c4bbdfSmrg            || s_pScreenInfo->fMultiWindow
60935c4bbdfSmrg            )
61035c4bbdfSmrg            break;
61135c4bbdfSmrg
61235c4bbdfSmrg        /*
61335c4bbdfSmrg         * Here we can override the maximum tracking size, which
61435c4bbdfSmrg         * is the largest size that can be assigned to our window
61535c4bbdfSmrg         * via the sizing border.
61635c4bbdfSmrg         */
61735c4bbdfSmrg
61835c4bbdfSmrg        /*
61935c4bbdfSmrg         * FIXME: Do we only need to do this once, since our visual size
62035c4bbdfSmrg         * does not change?  Does Windows store this value statically
62135c4bbdfSmrg         * once we have set it once?
62235c4bbdfSmrg         */
62335c4bbdfSmrg
62435c4bbdfSmrg        /* Get the border and caption sizes */
62535c4bbdfSmrg        iCaptionHeight = GetSystemMetrics(SM_CYCAPTION);
62635c4bbdfSmrg        iBorderWidth = 2 * GetSystemMetrics(SM_CXSIZEFRAME);
62735c4bbdfSmrg        iBorderHeight = 2 * GetSystemMetrics(SM_CYSIZEFRAME);
62835c4bbdfSmrg
62935c4bbdfSmrg        /* Allow the full visual to be displayed */
63035c4bbdfSmrg        pMinMaxInfo->ptMaxTrackSize.x = s_pScreenInfo->dwWidth + iBorderWidth;
63135c4bbdfSmrg        pMinMaxInfo->ptMaxTrackSize.y
63235c4bbdfSmrg            = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight;
63335c4bbdfSmrg    }
63435c4bbdfSmrg        return 0;
63505b261ecSmrg
63605b261ecSmrg    case WM_ERASEBKGND:
63705b261ecSmrg#if CYGDEBUG
63835c4bbdfSmrg        winDebug("winWindowProc - WM_ERASEBKGND\n");
63905b261ecSmrg#endif
64035c4bbdfSmrg        /*
64135c4bbdfSmrg         * Pretend that we did erase the background but we don't care,
64235c4bbdfSmrg         * the application uses the full window estate. This avoids some
64335c4bbdfSmrg         * flickering when resizing.
64435c4bbdfSmrg         */
64535c4bbdfSmrg        return TRUE;
64605b261ecSmrg
64705b261ecSmrg    case WM_PAINT:
64805b261ecSmrg#if CYGDEBUG
64935c4bbdfSmrg        winDebug("winWindowProc - WM_PAINT\n");
65005b261ecSmrg#endif
65135c4bbdfSmrg        /* Only paint if we have privates and the server is enabled */
65235c4bbdfSmrg        if (s_pScreenPriv == NULL
65335c4bbdfSmrg            || !s_pScreenPriv->fEnabled
65435c4bbdfSmrg            || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive)
65535c4bbdfSmrg            || s_pScreenPriv->fBadDepth) {
65635c4bbdfSmrg            /* We don't want to paint */
65735c4bbdfSmrg            break;
65835c4bbdfSmrg        }
65935c4bbdfSmrg
66035c4bbdfSmrg        /* Break out here if we don't have a valid paint routine */
66135c4bbdfSmrg        if (s_pScreenPriv->pwinBltExposedRegions == NULL)
66235c4bbdfSmrg            break;
66335c4bbdfSmrg
66435c4bbdfSmrg        /* Call the engine dependent repainter */
66535c4bbdfSmrg        (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen);
66635c4bbdfSmrg        return 0;
66705b261ecSmrg
66805b261ecSmrg    case WM_PALETTECHANGED:
66935c4bbdfSmrg    {
67005b261ecSmrg#if CYGDEBUG
67135c4bbdfSmrg        winDebug("winWindowProc - WM_PALETTECHANGED\n");
67205b261ecSmrg#endif
67335c4bbdfSmrg        /*
67435c4bbdfSmrg         * Don't process if we don't have privates or a colormap,
67535c4bbdfSmrg         * or if we have an invalid depth.
67635c4bbdfSmrg         */
67735c4bbdfSmrg        if (s_pScreenPriv == NULL
67835c4bbdfSmrg            || s_pScreenPriv->pcmapInstalled == NULL
67935c4bbdfSmrg            || s_pScreenPriv->fBadDepth)
68035c4bbdfSmrg            break;
68135c4bbdfSmrg
68235c4bbdfSmrg        /* Return if we caused the palette to change */
68335c4bbdfSmrg        if ((HWND) wParam == hwnd) {
68435c4bbdfSmrg            /* Redraw the screen */
68535c4bbdfSmrg            (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
68635c4bbdfSmrg            return 0;
68735c4bbdfSmrg        }
68835c4bbdfSmrg
68935c4bbdfSmrg        /* Reinstall the windows palette */
69035c4bbdfSmrg        (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen);
69135c4bbdfSmrg
69235c4bbdfSmrg        /* Redraw the screen */
69335c4bbdfSmrg        (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
69435c4bbdfSmrg        return 0;
69535c4bbdfSmrg    }
69605b261ecSmrg
69705b261ecSmrg    case WM_MOUSEMOVE:
69835c4bbdfSmrg        /* We can't do anything without privates */
69935c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
70035c4bbdfSmrg            break;
70105b261ecSmrg
70235c4bbdfSmrg        /* We can't do anything without g_pwinPointer */
70335c4bbdfSmrg        if (g_pwinPointer == NULL)
70435c4bbdfSmrg            break;
70535c4bbdfSmrg
70635c4bbdfSmrg        /* Has the mouse pointer crossed screens? */
70735c4bbdfSmrg        if (s_pScreen != miPointerGetScreen(g_pwinPointer))
70835c4bbdfSmrg            miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
70935c4bbdfSmrg                               GET_X_LPARAM(lParam) - s_pScreenInfo->dwXOffset,
71035c4bbdfSmrg                               GET_Y_LPARAM(lParam) - s_pScreenInfo->dwYOffset);
71135c4bbdfSmrg
71235c4bbdfSmrg        /* Are we tracking yet? */
71335c4bbdfSmrg        if (!s_fTracking) {
71435c4bbdfSmrg            TRACKMOUSEEVENT tme;
71535c4bbdfSmrg
71635c4bbdfSmrg            /* Setup data structure */
71735c4bbdfSmrg            ZeroMemory(&tme, sizeof(tme));
71835c4bbdfSmrg            tme.cbSize = sizeof(tme);
71935c4bbdfSmrg            tme.dwFlags = TME_LEAVE;
72035c4bbdfSmrg            tme.hwndTrack = hwnd;
7216747b715Smrg
72235c4bbdfSmrg            /* Call the tracking function */
72335c4bbdfSmrg            if (!TrackMouseEvent(&tme))
72435c4bbdfSmrg                ErrorF("winWindowProc - TrackMouseEvent failed\n");
72535c4bbdfSmrg
72635c4bbdfSmrg            /* Flag that we are tracking now */
72735c4bbdfSmrg            s_fTracking = TRUE;
72835c4bbdfSmrg        }
72935c4bbdfSmrg
73035c4bbdfSmrg        /* Hide or show the Windows mouse cursor */
73135c4bbdfSmrg        if (g_fSoftwareCursor && g_fCursor &&
73235c4bbdfSmrg            (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer)) {
73335c4bbdfSmrg            /* Hide Windows cursor */
73435c4bbdfSmrg            g_fCursor = FALSE;
73535c4bbdfSmrg            ShowCursor(FALSE);
73635c4bbdfSmrg        }
73735c4bbdfSmrg        else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive
73835c4bbdfSmrg                 && !s_pScreenInfo->fLessPointer) {
73935c4bbdfSmrg            /* Show Windows cursor */
74035c4bbdfSmrg            g_fCursor = TRUE;
74135c4bbdfSmrg            ShowCursor(TRUE);
74235c4bbdfSmrg        }
74335c4bbdfSmrg
74435c4bbdfSmrg        /* Deliver absolute cursor position to X Server */
74535c4bbdfSmrg        winEnqueueMotion(GET_X_LPARAM(lParam) - s_pScreenInfo->dwXOffset,
74635c4bbdfSmrg                         GET_Y_LPARAM(lParam) - s_pScreenInfo->dwYOffset);
74735c4bbdfSmrg        return 0;
74805b261ecSmrg
74905b261ecSmrg    case WM_NCMOUSEMOVE:
75035c4bbdfSmrg        /*
75135c4bbdfSmrg         * We break instead of returning 0 since we need to call
75235c4bbdfSmrg         * DefWindowProc to get the mouse cursor changes
75335c4bbdfSmrg         * and min/max/close button highlighting in Windows XP.
75435c4bbdfSmrg         * The Platform SDK says that you should return 0 if you
75535c4bbdfSmrg         * process this message, but it fails to mention that you
75635c4bbdfSmrg         * will give up any default functionality if you do return 0.
75735c4bbdfSmrg         */
75835c4bbdfSmrg
75935c4bbdfSmrg        /* We can't do anything without privates */
76035c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
76135c4bbdfSmrg            break;
76235c4bbdfSmrg
76335c4bbdfSmrg        /* Non-client mouse movement, show Windows cursor */
76435c4bbdfSmrg        if (g_fSoftwareCursor && !g_fCursor) {
76535c4bbdfSmrg            g_fCursor = TRUE;
76635c4bbdfSmrg            ShowCursor(TRUE);
76735c4bbdfSmrg        }
76835c4bbdfSmrg        break;
76905b261ecSmrg
77005b261ecSmrg    case WM_MOUSELEAVE:
77135c4bbdfSmrg        /* Mouse has left our client area */
77205b261ecSmrg
77335c4bbdfSmrg        /* Flag that we are no longer tracking */
77435c4bbdfSmrg        s_fTracking = FALSE;
77505b261ecSmrg
77635c4bbdfSmrg        /* Show the mouse cursor, if necessary */
77735c4bbdfSmrg        if (g_fSoftwareCursor && !g_fCursor) {
77835c4bbdfSmrg            g_fCursor = TRUE;
77935c4bbdfSmrg            ShowCursor(TRUE);
78035c4bbdfSmrg        }
78135c4bbdfSmrg        return 0;
78205b261ecSmrg
78305b261ecSmrg    case WM_LBUTTONDBLCLK:
78405b261ecSmrg    case WM_LBUTTONDOWN:
78535c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
78635c4bbdfSmrg            break;
787ed6184dfSmrg        if (s_pScreenInfo->fRootless)
78835c4bbdfSmrg            SetCapture(hwnd);
78935c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
79035c4bbdfSmrg
79105b261ecSmrg    case WM_LBUTTONUP:
79235c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
79335c4bbdfSmrg            break;
794ed6184dfSmrg        if (s_pScreenInfo->fRootless)
79535c4bbdfSmrg            ReleaseCapture();
79635c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
79705b261ecSmrg
79805b261ecSmrg    case WM_MBUTTONDBLCLK:
79905b261ecSmrg    case WM_MBUTTONDOWN:
80035c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
80135c4bbdfSmrg            break;
802ed6184dfSmrg        if (s_pScreenInfo->fRootless)
80335c4bbdfSmrg            SetCapture(hwnd);
80435c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
80535c4bbdfSmrg
80605b261ecSmrg    case WM_MBUTTONUP:
80735c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
80835c4bbdfSmrg            break;
809ed6184dfSmrg        if (s_pScreenInfo->fRootless)
81035c4bbdfSmrg            ReleaseCapture();
81135c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
81235c4bbdfSmrg
81305b261ecSmrg    case WM_RBUTTONDBLCLK:
81405b261ecSmrg    case WM_RBUTTONDOWN:
81535c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
81635c4bbdfSmrg            break;
817ed6184dfSmrg        if (s_pScreenInfo->fRootless)
81835c4bbdfSmrg            SetCapture(hwnd);
81935c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
82035c4bbdfSmrg
82105b261ecSmrg    case WM_RBUTTONUP:
82235c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
82335c4bbdfSmrg            break;
824ed6184dfSmrg        if (s_pScreenInfo->fRootless)
82535c4bbdfSmrg            ReleaseCapture();
82635c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
82705b261ecSmrg
82805b261ecSmrg    case WM_XBUTTONDBLCLK:
82905b261ecSmrg    case WM_XBUTTONDOWN:
83035c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
83135c4bbdfSmrg            break;
832ed6184dfSmrg        if (s_pScreenInfo->fRootless)
83335c4bbdfSmrg            SetCapture(hwnd);
83435c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
83535c4bbdfSmrg                                     wParam);
83605b261ecSmrg    case WM_XBUTTONUP:
83735c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
83835c4bbdfSmrg            break;
839ed6184dfSmrg        if (s_pScreenInfo->fRootless)
84035c4bbdfSmrg            ReleaseCapture();
84135c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease,
84235c4bbdfSmrg                                     HIWORD(wParam) + 7, wParam);
84305b261ecSmrg
84405b261ecSmrg    case WM_TIMER:
84535c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
84635c4bbdfSmrg            break;
84735c4bbdfSmrg
84835c4bbdfSmrg        /* Branch on the timer id */
84935c4bbdfSmrg        switch (wParam) {
85035c4bbdfSmrg        case WIN_E3B_TIMER_ID:
85135c4bbdfSmrg            /* Send delayed button press */
85235c4bbdfSmrg            winMouseButtonsSendEvent(ButtonPress,
85335c4bbdfSmrg                                     s_pScreenPriv->iE3BCachedPress);
85435c4bbdfSmrg
85535c4bbdfSmrg            /* Kill this timer */
85635c4bbdfSmrg            KillTimer(s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
85735c4bbdfSmrg
85835c4bbdfSmrg            /* Clear screen privates flags */
85935c4bbdfSmrg            s_pScreenPriv->iE3BCachedPress = 0;
86035c4bbdfSmrg            break;
86135c4bbdfSmrg
86235c4bbdfSmrg        case WIN_POLLING_MOUSE_TIMER_ID:
86335c4bbdfSmrg        {
86435c4bbdfSmrg            static POINT last_point;
86535c4bbdfSmrg            POINT point;
86635c4bbdfSmrg            WPARAM wL, wM, wR, wShift, wCtrl;
86735c4bbdfSmrg            LPARAM lPos;
86835c4bbdfSmrg
86935c4bbdfSmrg            /* Get the current position of the mouse cursor */
87035c4bbdfSmrg            GetCursorPos(&point);
87135c4bbdfSmrg
87235c4bbdfSmrg            /* Map from screen (-X, -Y) to root (0, 0) */
87335c4bbdfSmrg            point.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
87435c4bbdfSmrg            point.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
87535c4bbdfSmrg
87635c4bbdfSmrg            /* If the mouse pointer has moved, deliver absolute cursor position to X Server */
87735c4bbdfSmrg            if (last_point.x != point.x || last_point.y != point.y) {
87835c4bbdfSmrg                winEnqueueMotion(point.x, point.y);
87935c4bbdfSmrg                last_point.x = point.x;
88035c4bbdfSmrg                last_point.y = point.y;
88135c4bbdfSmrg            }
88235c4bbdfSmrg
88335c4bbdfSmrg            /* Check if a button was released but we didn't see it */
88435c4bbdfSmrg            GetCursorPos(&point);
88535c4bbdfSmrg            wL = (GetKeyState(VK_LBUTTON) & 0x8000) ? MK_LBUTTON : 0;
88635c4bbdfSmrg            wM = (GetKeyState(VK_MBUTTON) & 0x8000) ? MK_MBUTTON : 0;
88735c4bbdfSmrg            wR = (GetKeyState(VK_RBUTTON) & 0x8000) ? MK_RBUTTON : 0;
88835c4bbdfSmrg            wShift = (GetKeyState(VK_SHIFT) & 0x8000) ? MK_SHIFT : 0;
88935c4bbdfSmrg            wCtrl = (GetKeyState(VK_CONTROL) & 0x8000) ? MK_CONTROL : 0;
89035c4bbdfSmrg            lPos = MAKELPARAM(point.x, point.y);
89135c4bbdfSmrg            if (g_fButton[0] && !wL)
89235c4bbdfSmrg                PostMessage(hwnd, WM_LBUTTONUP, wCtrl | wM | wR | wShift, lPos);
89335c4bbdfSmrg            if (g_fButton[1] && !wM)
89435c4bbdfSmrg                PostMessage(hwnd, WM_MBUTTONUP, wCtrl | wL | wR | wShift, lPos);
89535c4bbdfSmrg            if (g_fButton[2] && !wR)
89635c4bbdfSmrg                PostMessage(hwnd, WM_RBUTTONUP, wCtrl | wL | wM | wShift, lPos);
89735c4bbdfSmrg        }
89835c4bbdfSmrg        }
89935c4bbdfSmrg        return 0;
90005b261ecSmrg
90105b261ecSmrg    case WM_CTLCOLORSCROLLBAR:
90235c4bbdfSmrg        FatalError("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not "
90335c4bbdfSmrg                   "supposed to get this message.  Exiting.\n");
90435c4bbdfSmrg        return 0;
90505b261ecSmrg
90605b261ecSmrg    case WM_MOUSEWHEEL:
90735c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
90835c4bbdfSmrg            break;
90935c4bbdfSmrg#if CYGDEBUG
91035c4bbdfSmrg        winDebug("winWindowProc - WM_MOUSEWHEEL\n");
91135c4bbdfSmrg#endif
91235c4bbdfSmrg        /* Button4 = WheelUp */
91335c4bbdfSmrg        /* Button5 = WheelDown */
91435c4bbdfSmrg        winMouseWheel(&(s_pScreenPriv->iDeltaZ), GET_WHEEL_DELTA_WPARAM(wParam), Button4, Button5);
91535c4bbdfSmrg        break;
91635c4bbdfSmrg
91735c4bbdfSmrg    case WM_MOUSEHWHEEL:
91835c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
91935c4bbdfSmrg            break;
92005b261ecSmrg#if CYGDEBUG
92135c4bbdfSmrg        winDebug("winWindowProc - WM_MOUSEHWHEEL\n");
92205b261ecSmrg#endif
92335c4bbdfSmrg        /* Button7 = TiltRight */
92435c4bbdfSmrg        /* Button6 = TiltLeft */
92535c4bbdfSmrg        winMouseWheel(&(s_pScreenPriv->iDeltaV), GET_WHEEL_DELTA_WPARAM(wParam), 7, 6);
92635c4bbdfSmrg        break;
92705b261ecSmrg
92805b261ecSmrg    case WM_SETFOCUS:
92935c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
93035c4bbdfSmrg            break;
93105b261ecSmrg
93235c4bbdfSmrg        /* Restore the state of all mode keys */
93335c4bbdfSmrg        winRestoreModeKeyStates();
93405b261ecSmrg
93535c4bbdfSmrg        /* Add the keyboard hook if possible */
93635c4bbdfSmrg        if (g_fKeyboardHookLL)
93735c4bbdfSmrg            g_fKeyboardHookLL = winInstallKeyboardHookLL();
93835c4bbdfSmrg        return 0;
93905b261ecSmrg
94005b261ecSmrg    case WM_KILLFOCUS:
94135c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
94235c4bbdfSmrg            break;
94305b261ecSmrg
94435c4bbdfSmrg        /* Release any pressed keys */
94535c4bbdfSmrg        winKeybdReleaseKeys();
94605b261ecSmrg
94735c4bbdfSmrg        /* Remove our keyboard hook if it is installed */
94835c4bbdfSmrg        winRemoveKeyboardHookLL();
94935c4bbdfSmrg        return 0;
95005b261ecSmrg
95105b261ecSmrg    case WM_SYSKEYDOWN:
95205b261ecSmrg    case WM_KEYDOWN:
95335c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
95435c4bbdfSmrg            break;
95535c4bbdfSmrg
95635c4bbdfSmrg        /*
95735c4bbdfSmrg         * FIXME: Catching Alt-F4 like this is really terrible.  This should
95835c4bbdfSmrg         * be generalized to handle other Windows keyboard signals.  Actually,
95935c4bbdfSmrg         * the list keys to catch and the actions to perform when caught should
96035c4bbdfSmrg         * be configurable; that way user's can customize the keys that they
96135c4bbdfSmrg         * need to have passed through to their window manager or apps, or they
96235c4bbdfSmrg         * can remap certain actions to new key codes that do not conflict
96335c4bbdfSmrg         * with the X apps that they are using.  Yeah, that'll take awhile.
96435c4bbdfSmrg         */
96535c4bbdfSmrg        if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4
96635c4bbdfSmrg             && (GetKeyState(VK_MENU) & 0x8000))
96735c4bbdfSmrg            || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK
96835c4bbdfSmrg                && (GetKeyState(VK_MENU) & 0x8000)
96935c4bbdfSmrg                && (GetKeyState(VK_CONTROL) & 0x8000))) {
97035c4bbdfSmrg            /*
97135c4bbdfSmrg             * Better leave this message here, just in case some unsuspecting
97235c4bbdfSmrg             * user enters Alt + F4 and is surprised when the application
97335c4bbdfSmrg             * quits.
97435c4bbdfSmrg             */
97535c4bbdfSmrg            ErrorF("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n");
97635c4bbdfSmrg
97735c4bbdfSmrg            /* Display Exit dialog */
97835c4bbdfSmrg            winDisplayExitDialog(s_pScreenPriv);
97935c4bbdfSmrg            return 0;
98035c4bbdfSmrg        }
98135c4bbdfSmrg
98235c4bbdfSmrg        /*
98335c4bbdfSmrg         * Don't do anything for the Windows keys, as focus will soon
98435c4bbdfSmrg         * be returned to Windows.  We may be able to trap the Windows keys,
98535c4bbdfSmrg         * but we should determine if that is desirable before doing so.
98635c4bbdfSmrg         */
98735c4bbdfSmrg        if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
98805b261ecSmrg            break;
98935c4bbdfSmrg
99035c4bbdfSmrg        /* Discard fake Ctrl_L events that precede AltGR on non-US keyboards */
99135c4bbdfSmrg        if (winIsFakeCtrl_L(message, wParam, lParam))
99205b261ecSmrg            return 0;
99335c4bbdfSmrg
99435c4bbdfSmrg        /*
99535c4bbdfSmrg         * Discard presses generated from Windows auto-repeat
99635c4bbdfSmrg         */
99735c4bbdfSmrg        if (lParam & (1 << 30)) {
99835c4bbdfSmrg            switch (wParam) {
99935c4bbdfSmrg                /* ago: Pressing LControl while RControl is pressed is
100035c4bbdfSmrg                 * Indicated as repeat. Fix this!
100135c4bbdfSmrg                 */
100235c4bbdfSmrg            case VK_CONTROL:
100335c4bbdfSmrg            case VK_SHIFT:
100435c4bbdfSmrg                if (winCheckKeyPressed(wParam, lParam))
100535c4bbdfSmrg                    return 0;
100635c4bbdfSmrg                break;
100735c4bbdfSmrg            default:
100835c4bbdfSmrg                return 0;
100935c4bbdfSmrg            }
101005b261ecSmrg        }
101135c4bbdfSmrg
101235c4bbdfSmrg        /* Translate Windows key code to X scan code */
101335c4bbdfSmrg        iScanCode = winTranslateKey(wParam, lParam);
101435c4bbdfSmrg
101535c4bbdfSmrg        /* Ignore repeats for CapsLock */
101635c4bbdfSmrg        if (wParam == VK_CAPITAL)
101735c4bbdfSmrg            lParam = 1;
101835c4bbdfSmrg
101935c4bbdfSmrg        /* Send the key event(s) */
102035c4bbdfSmrg        for (i = 0; i < LOWORD(lParam); ++i)
102135c4bbdfSmrg            winSendKeyEvent(iScanCode, TRUE);
102235c4bbdfSmrg        return 0;
102305b261ecSmrg
102405b261ecSmrg    case WM_SYSKEYUP:
102505b261ecSmrg    case WM_KEYUP:
102635c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
102735c4bbdfSmrg            break;
102835c4bbdfSmrg
102935c4bbdfSmrg        /*
103035c4bbdfSmrg         * Don't do anything for the Windows keys, as focus will soon
103135c4bbdfSmrg         * be returned to Windows.  We may be able to trap the Windows keys,
103235c4bbdfSmrg         * but we should determine if that is desirable before doing so.
103335c4bbdfSmrg         */
103435c4bbdfSmrg        if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
103535c4bbdfSmrg            break;
103635c4bbdfSmrg
103735c4bbdfSmrg        /* Ignore the fake Ctrl_L that follows an AltGr release */
103835c4bbdfSmrg        if (winIsFakeCtrl_L(message, wParam, lParam))
103935c4bbdfSmrg            return 0;
104035c4bbdfSmrg
104135c4bbdfSmrg        /* Enqueue a keyup event */
104235c4bbdfSmrg        iScanCode = winTranslateKey(wParam, lParam);
104335c4bbdfSmrg        winSendKeyEvent(iScanCode, FALSE);
104435c4bbdfSmrg
104535c4bbdfSmrg        /* Release all pressed shift keys */
104635c4bbdfSmrg        if (wParam == VK_SHIFT)
104735c4bbdfSmrg            winFixShiftKeys(iScanCode);
104835c4bbdfSmrg        return 0;
104905b261ecSmrg
105005b261ecSmrg    case WM_ACTIVATE:
105135c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
105235c4bbdfSmrg            break;
105335c4bbdfSmrg
105435c4bbdfSmrg        /* TODO: Override display of window when we have a bad depth */
105535c4bbdfSmrg        if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth) {
105635c4bbdfSmrg            ErrorF("winWindowProc - WM_ACTIVATE - Bad depth, trying "
105735c4bbdfSmrg                   "to override window activation\n");
105835c4bbdfSmrg
105935c4bbdfSmrg            /* Minimize the window */
106035c4bbdfSmrg            ShowWindow(hwnd, SW_MINIMIZE);
106135c4bbdfSmrg
106235c4bbdfSmrg            /* Display dialog box */
106335c4bbdfSmrg            if (g_hDlgDepthChange != NULL) {
106435c4bbdfSmrg                /* Make the existing dialog box active */
106535c4bbdfSmrg                SetActiveWindow(g_hDlgDepthChange);
106635c4bbdfSmrg            }
106735c4bbdfSmrg            else {
106835c4bbdfSmrg                /* TODO: Recreate the dialog box and bring to the top */
106935c4bbdfSmrg                ShowWindow(g_hDlgDepthChange, SW_SHOWDEFAULT);
107035c4bbdfSmrg            }
107135c4bbdfSmrg
107235c4bbdfSmrg            /* Don't do any other processing of this message */
107335c4bbdfSmrg            return 0;
107435c4bbdfSmrg        }
107505b261ecSmrg
107605b261ecSmrg#if CYGDEBUG
107735c4bbdfSmrg        winDebug("winWindowProc - WM_ACTIVATE\n");
107805b261ecSmrg#endif
107905b261ecSmrg
108035c4bbdfSmrg        /*
108135c4bbdfSmrg         * Focus is being changed to another window.
108235c4bbdfSmrg         * The other window may or may not belong to
108335c4bbdfSmrg         * our process.
108435c4bbdfSmrg         */
108535c4bbdfSmrg
108635c4bbdfSmrg        /* Clear any lingering wheel delta */
108735c4bbdfSmrg        s_pScreenPriv->iDeltaZ = 0;
108835c4bbdfSmrg        s_pScreenPriv->iDeltaV = 0;
108935c4bbdfSmrg
109035c4bbdfSmrg        /* Reshow the Windows mouse cursor if we are being deactivated */
109135c4bbdfSmrg        if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE && !g_fCursor) {
109235c4bbdfSmrg            /* Show Windows cursor */
109335c4bbdfSmrg            g_fCursor = TRUE;
109435c4bbdfSmrg            ShowCursor(TRUE);
109535c4bbdfSmrg        }
109635c4bbdfSmrg        return 0;
109705b261ecSmrg
109805b261ecSmrg    case WM_ACTIVATEAPP:
109935c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
110035c4bbdfSmrg            break;
110105b261ecSmrg
110205b261ecSmrg#if CYGDEBUG || TRUE
110335c4bbdfSmrg        winDebug("winWindowProc - WM_ACTIVATEAPP\n");
110405b261ecSmrg#endif
110505b261ecSmrg
110635c4bbdfSmrg        /* Activate or deactivate */
110735c4bbdfSmrg        s_pScreenPriv->fActive = wParam;
110805b261ecSmrg
110935c4bbdfSmrg        /* Reshow the Windows mouse cursor if we are being deactivated */
111035c4bbdfSmrg        if (g_fSoftwareCursor && !s_pScreenPriv->fActive && !g_fCursor) {
111135c4bbdfSmrg            /* Show Windows cursor */
111235c4bbdfSmrg            g_fCursor = TRUE;
111335c4bbdfSmrg            ShowCursor(TRUE);
111435c4bbdfSmrg        }
111505b261ecSmrg
111635c4bbdfSmrg        /* Call engine specific screen activation/deactivation function */
111735c4bbdfSmrg        (*s_pScreenPriv->pwinActivateApp) (s_pScreen);
111805b261ecSmrg
111935c4bbdfSmrg        return 0;
112005b261ecSmrg
112105b261ecSmrg    case WM_COMMAND:
112235c4bbdfSmrg        switch (LOWORD(wParam)) {
112335c4bbdfSmrg        case ID_APP_EXIT:
112435c4bbdfSmrg            /* Display Exit dialog */
112535c4bbdfSmrg            winDisplayExitDialog(s_pScreenPriv);
112635c4bbdfSmrg            return 0;
112705b261ecSmrg
112835c4bbdfSmrg        case ID_APP_HIDE_ROOT:
112935c4bbdfSmrg            if (s_pScreenPriv->fRootWindowShown)
113035c4bbdfSmrg                ShowWindow(s_pScreenPriv->hwndScreen, SW_HIDE);
113135c4bbdfSmrg            else
113235c4bbdfSmrg                ShowWindow(s_pScreenPriv->hwndScreen, SW_SHOW);
113335c4bbdfSmrg            s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown;
113435c4bbdfSmrg            return 0;
113535c4bbdfSmrg
113635c4bbdfSmrg        case ID_APP_MONITOR_PRIMARY:
113735c4bbdfSmrg            fPrimarySelection = !fPrimarySelection;
113835c4bbdfSmrg            return 0;
113905b261ecSmrg
114035c4bbdfSmrg        case ID_APP_ABOUT:
114135c4bbdfSmrg            /* Display the About box */
114235c4bbdfSmrg            winDisplayAboutDialog(s_pScreenPriv);
114335c4bbdfSmrg            return 0;
114405b261ecSmrg
114535c4bbdfSmrg        default:
114635c4bbdfSmrg            /* It's probably one of the custom menus... */
11471b5d61b8Smrg            if (HandleCustomWM_COMMAND(0, LOWORD(wParam), s_pScreenPriv))
114835c4bbdfSmrg                return 0;
114935c4bbdfSmrg        }
115035c4bbdfSmrg        break;
115105b261ecSmrg
115205b261ecSmrg    case WM_GIVEUP:
115335c4bbdfSmrg        /* Tell X that we are giving up */
115435c4bbdfSmrg        if (s_pScreenInfo->fMultiWindow)
115535c4bbdfSmrg            winDeinitMultiWindowWM();
115635c4bbdfSmrg        GiveUp(0);
115735c4bbdfSmrg        return 0;
115805b261ecSmrg
115905b261ecSmrg    case WM_CLOSE:
116035c4bbdfSmrg        /* Display Exit dialog */
116135c4bbdfSmrg        winDisplayExitDialog(s_pScreenPriv);
116235c4bbdfSmrg        return 0;
116305b261ecSmrg
116405b261ecSmrg    case WM_SETCURSOR:
116535c4bbdfSmrg        if (LOWORD(lParam) == HTCLIENT) {
116635c4bbdfSmrg            if (!g_fSoftwareCursor)
116735c4bbdfSmrg                SetCursor(s_pScreenPriv->cursor.handle);
116835c4bbdfSmrg            return TRUE;
116935c4bbdfSmrg        }
117035c4bbdfSmrg        break;
117105b261ecSmrg
117205b261ecSmrg    default:
1173ed6184dfSmrg        if ((message == s_uTaskbarRestart) && !s_pScreenInfo->fNoTrayIcon)  {
117435c4bbdfSmrg            winInitNotifyIcon(s_pScreenPriv);
117535c4bbdfSmrg        }
117635c4bbdfSmrg        break;
117705b261ecSmrg    }
117805b261ecSmrg
117935c4bbdfSmrg    return DefWindowProc(hwnd, message, wParam, lParam);
118005b261ecSmrg}
1181