winmultiwindowwndproc.c revision 35c4bbdf
105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
36747b715Smrg *Copyright (C) Colin Harrison 2005-2008
405b261ecSmrg *
505b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
605b261ecSmrg * a copy of this software and associated documentation files (the
705b261ecSmrg *"Software"), to deal in the Software without restriction, including
805b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
905b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
1005b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1105b261ecSmrg *the following conditions:
1205b261ecSmrg *
1305b261ecSmrg *The above copyright notice and this permission notice shall be
1405b261ecSmrg *included in all copies or substantial portions of the Software.
1505b261ecSmrg *
1605b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1705b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1805b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1905b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
2005b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2105b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2205b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2305b261ecSmrg *
2405b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project
2505b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2605b261ecSmrg *or other dealings in this Software without prior written authorization
2705b261ecSmrg *from the XFree86 Project.
2805b261ecSmrg *
2905b261ecSmrg * Authors:	Kensuke Matsuzaki
3005b261ecSmrg *		Earle F. Philhower, III
3105b261ecSmrg *		Harold L Hunt II
326747b715Smrg *              Colin Harrison
3305b261ecSmrg */
3405b261ecSmrg
3505b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3605b261ecSmrg#include <xwin-config.h>
3705b261ecSmrg#endif
3805b261ecSmrg#include "win.h"
3905b261ecSmrg#include "dixevents.h"
4005b261ecSmrg#include "winmultiwindowclass.h"
4105b261ecSmrg#include "winprefs.h"
4205b261ecSmrg#include "winmsg.h"
4305b261ecSmrg#include "inputstr.h"
4405b261ecSmrg
4535c4bbdfSmrgextern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
4605b261ecSmrg
4705b261ecSmrg/*
4805b261ecSmrg * Local globals
4905b261ecSmrg */
5005b261ecSmrg
5135c4bbdfSmrgstatic UINT_PTR g_uipMousePollingTimerID = 0;
5205b261ecSmrg
5305b261ecSmrg/*
5405b261ecSmrg * Constant defines
5505b261ecSmrg */
5605b261ecSmrg
5705b261ecSmrg#define WIN_MULTIWINDOW_SHAPE		YES
5805b261ecSmrg
5905b261ecSmrg/*
6005b261ecSmrg * ConstrainSize - Taken from TWM sources - Respects hints for sizing
6105b261ecSmrg */
6205b261ecSmrg#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
6305b261ecSmrgstatic void
6435c4bbdfSmrgConstrainSize(WinXSizeHints hints, int *widthp, int *heightp)
6505b261ecSmrg{
6635c4bbdfSmrg    int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
6735c4bbdfSmrg    int baseWidth, baseHeight;
6835c4bbdfSmrg    int dwidth = *widthp, dheight = *heightp;
6935c4bbdfSmrg
7035c4bbdfSmrg    if (hints.flags & PMinSize) {
7135c4bbdfSmrg        minWidth = hints.min_width;
7235c4bbdfSmrg        minHeight = hints.min_height;
7305b261ecSmrg    }
7435c4bbdfSmrg    else if (hints.flags & PBaseSize) {
7535c4bbdfSmrg        minWidth = hints.base_width;
7635c4bbdfSmrg        minHeight = hints.base_height;
7705b261ecSmrg    }
7835c4bbdfSmrg    else
7935c4bbdfSmrg        minWidth = minHeight = 1;
8035c4bbdfSmrg
8135c4bbdfSmrg    if (hints.flags & PBaseSize) {
8235c4bbdfSmrg        baseWidth = hints.base_width;
8335c4bbdfSmrg        baseHeight = hints.base_height;
8405b261ecSmrg    }
8535c4bbdfSmrg    else if (hints.flags & PMinSize) {
8635c4bbdfSmrg        baseWidth = hints.min_width;
8735c4bbdfSmrg        baseHeight = hints.min_height;
8835c4bbdfSmrg    }
8935c4bbdfSmrg    else
9035c4bbdfSmrg        baseWidth = baseHeight = 0;
9105b261ecSmrg
9235c4bbdfSmrg    if (hints.flags & PMaxSize) {
9335c4bbdfSmrg        maxWidth = hints.max_width;
9435c4bbdfSmrg        maxHeight = hints.max_height;
9505b261ecSmrg    }
9635c4bbdfSmrg    else {
9735c4bbdfSmrg        maxWidth = MAXINT;
9835c4bbdfSmrg        maxHeight = MAXINT;
9905b261ecSmrg    }
10005b261ecSmrg
10135c4bbdfSmrg    if (hints.flags & PResizeInc) {
10235c4bbdfSmrg        xinc = hints.width_inc;
10335c4bbdfSmrg        yinc = hints.height_inc;
10405b261ecSmrg    }
10535c4bbdfSmrg    else
10635c4bbdfSmrg        xinc = yinc = 1;
10735c4bbdfSmrg
10835c4bbdfSmrg    /*
10935c4bbdfSmrg     * First, clamp to min and max values
11035c4bbdfSmrg     */
11135c4bbdfSmrg    if (dwidth < minWidth)
11235c4bbdfSmrg        dwidth = minWidth;
11335c4bbdfSmrg    if (dheight < minHeight)
11435c4bbdfSmrg        dheight = minHeight;
11535c4bbdfSmrg
11635c4bbdfSmrg    if (dwidth > maxWidth)
11735c4bbdfSmrg        dwidth = maxWidth;
11835c4bbdfSmrg    if (dheight > maxHeight)
11935c4bbdfSmrg        dheight = maxHeight;
12035c4bbdfSmrg
12135c4bbdfSmrg    /*
12235c4bbdfSmrg     * Second, fit to base + N * inc
12335c4bbdfSmrg     */
12435c4bbdfSmrg    dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
12535c4bbdfSmrg    dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
12635c4bbdfSmrg
12735c4bbdfSmrg    /*
12835c4bbdfSmrg     * Third, adjust for aspect ratio
12935c4bbdfSmrg     */
13035c4bbdfSmrg
13135c4bbdfSmrg    /*
13235c4bbdfSmrg     * The math looks like this:
13335c4bbdfSmrg     *
13435c4bbdfSmrg     * minAspectX    dwidth     maxAspectX
13535c4bbdfSmrg     * ---------- <= ------- <= ----------
13635c4bbdfSmrg     * minAspectY    dheight    maxAspectY
13735c4bbdfSmrg     *
13835c4bbdfSmrg     * If that is multiplied out, then the width and height are
13935c4bbdfSmrg     * invalid in the following situations:
14035c4bbdfSmrg     *
14135c4bbdfSmrg     * minAspectX * dheight > minAspectY * dwidth
14235c4bbdfSmrg     * maxAspectX * dheight < maxAspectY * dwidth
14335c4bbdfSmrg     *
14435c4bbdfSmrg     */
14535c4bbdfSmrg
14635c4bbdfSmrg    if (hints.flags & PAspect) {
14735c4bbdfSmrg        if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) {
14835c4bbdfSmrg            delta =
14935c4bbdfSmrg                makemult(hints.min_aspect.x * dheight / hints.min_aspect.y -
15035c4bbdfSmrg                         dwidth, xinc);
15135c4bbdfSmrg            if (dwidth + delta <= maxWidth)
15235c4bbdfSmrg                dwidth += delta;
15335c4bbdfSmrg            else {
15435c4bbdfSmrg                delta =
15535c4bbdfSmrg                    makemult(dheight -
15635c4bbdfSmrg                             dwidth * hints.min_aspect.y / hints.min_aspect.x,
15735c4bbdfSmrg                             yinc);
15835c4bbdfSmrg                if (dheight - delta >= minHeight)
15935c4bbdfSmrg                    dheight -= delta;
16005b261ecSmrg            }
16105b261ecSmrg        }
16235c4bbdfSmrg
16335c4bbdfSmrg        if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) {
16435c4bbdfSmrg            delta =
16535c4bbdfSmrg                makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x -
16635c4bbdfSmrg                         dheight, yinc);
16735c4bbdfSmrg            if (dheight + delta <= maxHeight)
16835c4bbdfSmrg                dheight += delta;
16935c4bbdfSmrg            else {
17035c4bbdfSmrg                delta =
17135c4bbdfSmrg                    makemult(dwidth -
17235c4bbdfSmrg                             hints.max_aspect.x * dheight / hints.max_aspect.y,
17335c4bbdfSmrg                             xinc);
17435c4bbdfSmrg                if (dwidth - delta >= minWidth)
17535c4bbdfSmrg                    dwidth -= delta;
17605b261ecSmrg            }
17705b261ecSmrg        }
17805b261ecSmrg    }
17905b261ecSmrg
18035c4bbdfSmrg    /* Return computed values */
18135c4bbdfSmrg    *widthp = dwidth;
18235c4bbdfSmrg    *heightp = dheight;
18335c4bbdfSmrg}
18405b261ecSmrg
18535c4bbdfSmrg#undef makemult
18605b261ecSmrg
18705b261ecSmrg/*
18805b261ecSmrg * ValidateSizing - Ensures size request respects hints
18905b261ecSmrg */
19005b261ecSmrgstatic int
19135c4bbdfSmrgValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam)
19205b261ecSmrg{
19335c4bbdfSmrg    WinXSizeHints sizeHints;
19435c4bbdfSmrg    RECT *rect;
19535c4bbdfSmrg    int iWidth, iHeight;
19635c4bbdfSmrg    RECT rcClient, rcWindow;
19735c4bbdfSmrg    int iBorderWidthX, iBorderWidthY;
19835c4bbdfSmrg
19935c4bbdfSmrg    /* Invalid input checking */
20035c4bbdfSmrg    if (pWin == NULL || lParam == 0)
20135c4bbdfSmrg        return FALSE;
20235c4bbdfSmrg
20335c4bbdfSmrg    /* No size hints, no checking */
20435c4bbdfSmrg    if (!winMultiWindowGetWMNormalHints(pWin, &sizeHints))
20535c4bbdfSmrg        return FALSE;
20635c4bbdfSmrg
20735c4bbdfSmrg    /* Avoid divide-by-zero */
20835c4bbdfSmrg    if (sizeHints.flags & PResizeInc) {
20935c4bbdfSmrg        if (sizeHints.width_inc == 0)
21035c4bbdfSmrg            sizeHints.width_inc = 1;
21135c4bbdfSmrg        if (sizeHints.height_inc == 0)
21235c4bbdfSmrg            sizeHints.height_inc = 1;
21305b261ecSmrg    }
21435c4bbdfSmrg
21535c4bbdfSmrg    rect = (RECT *) lParam;
21635c4bbdfSmrg
21735c4bbdfSmrg    iWidth = rect->right - rect->left;
21835c4bbdfSmrg    iHeight = rect->bottom - rect->top;
21935c4bbdfSmrg
22035c4bbdfSmrg    /* Now remove size of any borders and title bar */
22135c4bbdfSmrg    GetClientRect(hwnd, &rcClient);
22235c4bbdfSmrg    GetWindowRect(hwnd, &rcWindow);
22335c4bbdfSmrg    iBorderWidthX =
22435c4bbdfSmrg        (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
22535c4bbdfSmrg    iBorderWidthY =
22635c4bbdfSmrg        (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
22735c4bbdfSmrg    iWidth -= iBorderWidthX;
22835c4bbdfSmrg    iHeight -= iBorderWidthY;
22935c4bbdfSmrg
23035c4bbdfSmrg    /* Constrain the size to legal values */
23135c4bbdfSmrg    ConstrainSize(sizeHints, &iWidth, &iHeight);
23235c4bbdfSmrg
23335c4bbdfSmrg    /* Add back the size of borders and title bar */
23435c4bbdfSmrg    iWidth += iBorderWidthX;
23535c4bbdfSmrg    iHeight += iBorderWidthY;
23635c4bbdfSmrg
23735c4bbdfSmrg    /* Adjust size according to where we're dragging from */
23835c4bbdfSmrg    switch (wParam) {
23935c4bbdfSmrg    case WMSZ_TOP:
24035c4bbdfSmrg    case WMSZ_TOPRIGHT:
24135c4bbdfSmrg    case WMSZ_BOTTOM:
24235c4bbdfSmrg    case WMSZ_BOTTOMRIGHT:
24335c4bbdfSmrg    case WMSZ_RIGHT:
24435c4bbdfSmrg        rect->right = rect->left + iWidth;
24535c4bbdfSmrg        break;
24635c4bbdfSmrg    default:
24735c4bbdfSmrg        rect->left = rect->right - iWidth;
24835c4bbdfSmrg        break;
24935c4bbdfSmrg    }
25035c4bbdfSmrg    switch (wParam) {
25135c4bbdfSmrg    case WMSZ_BOTTOM:
25235c4bbdfSmrg    case WMSZ_BOTTOMRIGHT:
25335c4bbdfSmrg    case WMSZ_BOTTOMLEFT:
25435c4bbdfSmrg    case WMSZ_RIGHT:
25535c4bbdfSmrg    case WMSZ_LEFT:
25635c4bbdfSmrg        rect->bottom = rect->top + iHeight;
25735c4bbdfSmrg        break;
25835c4bbdfSmrg    default:
25935c4bbdfSmrg        rect->top = rect->bottom - iHeight;
26035c4bbdfSmrg        break;
26135c4bbdfSmrg    }
26235c4bbdfSmrg    return TRUE;
26305b261ecSmrg}
26405b261ecSmrg
26505b261ecSmrgextern Bool winInDestroyWindowsWindow;
26605b261ecSmrgstatic Bool winInRaiseWindow = FALSE;
26735c4bbdfSmrgstatic void
26835c4bbdfSmrgwinRaiseWindow(WindowPtr pWin)
26905b261ecSmrg{
27035c4bbdfSmrg    if (!winInDestroyWindowsWindow && !winInRaiseWindow) {
27135c4bbdfSmrg        BOOL oldstate = winInRaiseWindow;
27235c4bbdfSmrg        XID vlist[1] = { 0 };
27335c4bbdfSmrg        winInRaiseWindow = TRUE;
27435c4bbdfSmrg        /* Call configure window directly to make sure it gets processed
27535c4bbdfSmrg         * in time
27635c4bbdfSmrg         */
27735c4bbdfSmrg        ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
27835c4bbdfSmrg        winInRaiseWindow = oldstate;
27935c4bbdfSmrg    }
28005b261ecSmrg}
28105b261ecSmrg
2826747b715Smrgstatic
28335c4bbdfSmrg    void
28435c4bbdfSmrgwinStartMousePolling(winPrivScreenPtr s_pScreenPriv)
2856747b715Smrg{
28635c4bbdfSmrg    /*
28735c4bbdfSmrg     * Timer to poll mouse position.  This is needed to make
28835c4bbdfSmrg     * programs like xeyes follow the mouse properly when the
28935c4bbdfSmrg     * mouse pointer is outside of any X window.
29035c4bbdfSmrg     */
29135c4bbdfSmrg    if (g_uipMousePollingTimerID == 0)
29235c4bbdfSmrg        g_uipMousePollingTimerID = SetTimer(s_pScreenPriv->hwndScreen,
29335c4bbdfSmrg                                            WIN_POLLING_MOUSE_TIMER_ID,
29435c4bbdfSmrg                                            MOUSE_POLLING_INTERVAL, NULL);
2956747b715Smrg}
29605b261ecSmrg
29705b261ecSmrg/*
29805b261ecSmrg * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
29905b261ecSmrg */
30005b261ecSmrg
30105b261ecSmrgLRESULT CALLBACK
30235c4bbdfSmrgwinTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
30305b261ecSmrg{
30435c4bbdfSmrg    POINT ptMouse;
30535c4bbdfSmrg    HDC hdcUpdate;
30635c4bbdfSmrg    PAINTSTRUCT ps;
30735c4bbdfSmrg    WindowPtr pWin = NULL;
30835c4bbdfSmrg    winPrivWinPtr pWinPriv = NULL;
30935c4bbdfSmrg    ScreenPtr s_pScreen = NULL;
31035c4bbdfSmrg    winPrivScreenPtr s_pScreenPriv = NULL;
31135c4bbdfSmrg    winScreenInfo *s_pScreenInfo = NULL;
31235c4bbdfSmrg    HWND hwndScreen = NULL;
31335c4bbdfSmrg    DrawablePtr pDraw = NULL;
31435c4bbdfSmrg    winWMMessageRec wmMsg;
31535c4bbdfSmrg    Bool fWMMsgInitialized = FALSE;
31635c4bbdfSmrg    static Bool s_fTracking = FALSE;
31735c4bbdfSmrg    Bool needRestack = FALSE;
31835c4bbdfSmrg    LRESULT ret;
31935c4bbdfSmrg    static Bool hasEnteredSizeMove = FALSE;
32005b261ecSmrg
32105b261ecSmrg#if CYGDEBUG
32235c4bbdfSmrg    winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
32335c4bbdfSmrg                         lParam);
32405b261ecSmrg#endif
32505b261ecSmrg
32635c4bbdfSmrg    /* Check if the Windows window property for our X window pointer is valid */
32735c4bbdfSmrg    if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) {
32835c4bbdfSmrg        /* Our X window pointer is valid */
32935c4bbdfSmrg
33035c4bbdfSmrg        /* Get pointers to the drawable and the screen */
33135c4bbdfSmrg        pDraw = &pWin->drawable;
33235c4bbdfSmrg        s_pScreen = pWin->drawable.pScreen;
33305b261ecSmrg
33435c4bbdfSmrg        /* Get a pointer to our window privates */
33535c4bbdfSmrg        pWinPriv = winGetWindowPriv(pWin);
33605b261ecSmrg
33735c4bbdfSmrg        /* Get pointers to our screen privates and screen info */
33835c4bbdfSmrg        s_pScreenPriv = pWinPriv->pScreenPriv;
33935c4bbdfSmrg        s_pScreenInfo = s_pScreenPriv->pScreenInfo;
34005b261ecSmrg
34135c4bbdfSmrg        /* Get the handle for our screen-sized window */
34235c4bbdfSmrg        hwndScreen = s_pScreenPriv->hwndScreen;
34305b261ecSmrg
34435c4bbdfSmrg        /* */
34535c4bbdfSmrg        wmMsg.msg = 0;
34635c4bbdfSmrg        wmMsg.hwndWindow = hwnd;
34735c4bbdfSmrg        wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP);
34805b261ecSmrg
34935c4bbdfSmrg        wmMsg.iX = pDraw->x;
35035c4bbdfSmrg        wmMsg.iY = pDraw->y;
35135c4bbdfSmrg        wmMsg.iWidth = pDraw->width;
35235c4bbdfSmrg        wmMsg.iHeight = pDraw->height;
35305b261ecSmrg
35435c4bbdfSmrg        fWMMsgInitialized = TRUE;
35505b261ecSmrg
35605b261ecSmrg#if 0
35735c4bbdfSmrg        /*
35835c4bbdfSmrg         * Print some debugging information
35935c4bbdfSmrg         */
36035c4bbdfSmrg
36135c4bbdfSmrg        ErrorF("hWnd %08X\n", hwnd);
36235c4bbdfSmrg        ErrorF("pWin %08X\n", pWin);
36335c4bbdfSmrg        ErrorF("pDraw %08X\n", pDraw);
36435c4bbdfSmrg        ErrorF("\ttype %08X\n", pWin->drawable.type);
36535c4bbdfSmrg        ErrorF("\tclass %08X\n", pWin->drawable.class);
36635c4bbdfSmrg        ErrorF("\tdepth %08X\n", pWin->drawable.depth);
36735c4bbdfSmrg        ErrorF("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
36835c4bbdfSmrg        ErrorF("\tid %08X\n", pWin->drawable.id);
36935c4bbdfSmrg        ErrorF("\tx %08X\n", pWin->drawable.x);
37035c4bbdfSmrg        ErrorF("\ty %08X\n", pWin->drawable.y);
37135c4bbdfSmrg        ErrorF("\twidth %08X\n", pWin->drawable.width);
37235c4bbdfSmrg        ErrorF("\thenght %08X\n", pWin->drawable.height);
37335c4bbdfSmrg        ErrorF("\tpScreen %08X\n", pWin->drawable.pScreen);
37435c4bbdfSmrg        ErrorF("\tserialNumber %08X\n", pWin->drawable.serialNumber);
37535c4bbdfSmrg        ErrorF("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
37635c4bbdfSmrg        ErrorF("pWinPriv %08X\n", pWinPriv);
37735c4bbdfSmrg        ErrorF("s_pScreenPriv %08X\n", s_pScreenPriv);
37835c4bbdfSmrg        ErrorF("s_pScreenInfo %08X\n", s_pScreenInfo);
37935c4bbdfSmrg        ErrorF("hwndScreen %08X\n", hwndScreen);
38005b261ecSmrg#endif
38105b261ecSmrg    }
38205b261ecSmrg
38335c4bbdfSmrg    /* Branch on message type */
38435c4bbdfSmrg    switch (message) {
38505b261ecSmrg    case WM_CREATE:
38605b261ecSmrg
38735c4bbdfSmrg        /* */
38835c4bbdfSmrg        SetProp(hwnd,
38935c4bbdfSmrg                WIN_WINDOW_PROP,
39035c4bbdfSmrg                (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams);
39135c4bbdfSmrg
39235c4bbdfSmrg        /* */
39335c4bbdfSmrg        SetProp(hwnd,
39435c4bbdfSmrg                WIN_WID_PROP,
39535c4bbdfSmrg                (HANDLE) (INT_PTR) winGetWindowID(((LPCREATESTRUCT) lParam)->
39635c4bbdfSmrg                                                  lpCreateParams));
39735c4bbdfSmrg
39835c4bbdfSmrg        /*
39935c4bbdfSmrg         * Make X windows' Z orders sync with Windows windows because
40035c4bbdfSmrg         * there can be AlwaysOnTop windows overlapped on the window
40135c4bbdfSmrg         * currently being created.
40235c4bbdfSmrg         */
40335c4bbdfSmrg        winReorderWindowsMultiWindow();
40435c4bbdfSmrg
40535c4bbdfSmrg        /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
40635c4bbdfSmrg        {
40735c4bbdfSmrg            RECT rWindow;
40835c4bbdfSmrg            HRGN hRgnWindow;
40935c4bbdfSmrg
41035c4bbdfSmrg            GetWindowRect(hwnd, &rWindow);
41135c4bbdfSmrg            hRgnWindow = CreateRectRgnIndirect(&rWindow);
41235c4bbdfSmrg            SetWindowRgn(hwnd, hRgnWindow, TRUE);
41335c4bbdfSmrg            DeleteObject(hRgnWindow);
41435c4bbdfSmrg        }
41535c4bbdfSmrg
41635c4bbdfSmrg        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE);
41735c4bbdfSmrg
41835c4bbdfSmrg        return 0;
41905b261ecSmrg
42005b261ecSmrg    case WM_INIT_SYS_MENU:
42135c4bbdfSmrg        /*
42235c4bbdfSmrg         * Add whatever the setup file wants to for this window
42335c4bbdfSmrg         */
42435c4bbdfSmrg        SetupSysMenu(hwnd);
42535c4bbdfSmrg        return 0;
42605b261ecSmrg
42705b261ecSmrg    case WM_SYSCOMMAND:
42835c4bbdfSmrg        /*
42935c4bbdfSmrg         * Any window menu items go through here
43035c4bbdfSmrg         */
43135c4bbdfSmrg        if (HandleCustomWM_COMMAND(hwnd, LOWORD(wParam))) {
43235c4bbdfSmrg            /* Don't pass customized menus to DefWindowProc */
43335c4bbdfSmrg            return 0;
43435c4bbdfSmrg        }
43535c4bbdfSmrg        if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) {
43635c4bbdfSmrg            WINDOWPLACEMENT wndpl;
43735c4bbdfSmrg
43835c4bbdfSmrg            wndpl.length = sizeof(wndpl);
43935c4bbdfSmrg            if (GetWindowPlacement(hwnd, &wndpl) &&
44035c4bbdfSmrg                wndpl.showCmd == SW_SHOWMINIMIZED)
44135c4bbdfSmrg                needRestack = TRUE;
44235c4bbdfSmrg        }
44335c4bbdfSmrg        break;
44405b261ecSmrg
44505b261ecSmrg    case WM_INITMENU:
44635c4bbdfSmrg        /* Checks/Unchecks any menu items before they are displayed */
44735c4bbdfSmrg        HandleCustomWM_INITMENU(hwnd, (HMENU)wParam);
44835c4bbdfSmrg        break;
44905b261ecSmrg
4506747b715Smrg    case WM_ERASEBKGND:
45135c4bbdfSmrg        /*
45235c4bbdfSmrg         * Pretend that we did erase the background but we don't care,
45335c4bbdfSmrg         * since we repaint the entire region anyhow
45435c4bbdfSmrg         * This avoids some flickering when resizing.
45535c4bbdfSmrg         */
45635c4bbdfSmrg        return TRUE;
4576747b715Smrg
45805b261ecSmrg    case WM_PAINT:
45935c4bbdfSmrg        /* Only paint if our window handle is valid */
46035c4bbdfSmrg        if (hwndScreen == NULL)
46135c4bbdfSmrg            break;
46235c4bbdfSmrg
46335c4bbdfSmrg        /* BeginPaint gives us an hdc that clips to the invalidated region */
46435c4bbdfSmrg        hdcUpdate = BeginPaint(hwnd, &ps);
46535c4bbdfSmrg        /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
46635c4bbdfSmrg        if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
46735c4bbdfSmrg            ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
46835c4bbdfSmrg            EndPaint(hwnd, &ps);
46935c4bbdfSmrg            return 0;
47035c4bbdfSmrg        }
47135c4bbdfSmrg
47235c4bbdfSmrg#ifdef XWIN_GLX_WINDOWS
47335c4bbdfSmrg        if (pWinPriv->fWglUsed) {
47435c4bbdfSmrg            /*
47535c4bbdfSmrg               For regions which are being drawn by GL, the shadow framebuffer doesn't have the
47635c4bbdfSmrg               correct bits, so don't bitblt from the shadow framebuffer
47735c4bbdfSmrg
47835c4bbdfSmrg               XXX: For now, just leave it alone, but ideally we want to send an expose event to
47935c4bbdfSmrg               the window so it really redraws the affected region...
48035c4bbdfSmrg             */
48135c4bbdfSmrg            ValidateRect(hwnd, &(ps.rcPaint));
48235c4bbdfSmrg        }
48335c4bbdfSmrg        else
48435c4bbdfSmrg#endif
48535c4bbdfSmrg            /* Try to copy from the shadow buffer */
48635c4bbdfSmrg        if (!BitBlt(hdcUpdate,
48735c4bbdfSmrg                        ps.rcPaint.left, ps.rcPaint.top,
48835c4bbdfSmrg                        ps.rcPaint.right - ps.rcPaint.left,
48935c4bbdfSmrg                        ps.rcPaint.bottom - ps.rcPaint.top,
49035c4bbdfSmrg                        s_pScreenPriv->hdcShadow,
49135c4bbdfSmrg                        ps.rcPaint.left + pWin->drawable.x,
49235c4bbdfSmrg                        ps.rcPaint.top + pWin->drawable.y, SRCCOPY)) {
49335c4bbdfSmrg            LPVOID lpMsgBuf;
49435c4bbdfSmrg
49535c4bbdfSmrg            /* Display a fancy error message */
49635c4bbdfSmrg            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
49735c4bbdfSmrg                          FORMAT_MESSAGE_FROM_SYSTEM |
49835c4bbdfSmrg                          FORMAT_MESSAGE_IGNORE_INSERTS,
49935c4bbdfSmrg                          NULL,
50035c4bbdfSmrg                          GetLastError(),
50135c4bbdfSmrg                          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
50235c4bbdfSmrg                          (LPTSTR) &lpMsgBuf, 0, NULL);
50335c4bbdfSmrg
50435c4bbdfSmrg            ErrorF("winTopLevelWindowProc - BitBlt failed: %s\n",
50535c4bbdfSmrg                   (LPSTR) lpMsgBuf);
50635c4bbdfSmrg            LocalFree(lpMsgBuf);
50735c4bbdfSmrg        }
50835c4bbdfSmrg
50935c4bbdfSmrg        /* EndPaint frees the DC */
51035c4bbdfSmrg        EndPaint(hwnd, &ps);
51135c4bbdfSmrg        return 0;
51205b261ecSmrg
51305b261ecSmrg    case WM_MOUSEMOVE:
51435c4bbdfSmrg        /* Unpack the client area mouse coordinates */
51535c4bbdfSmrg        ptMouse.x = GET_X_LPARAM(lParam);
51635c4bbdfSmrg        ptMouse.y = GET_Y_LPARAM(lParam);
51735c4bbdfSmrg
51835c4bbdfSmrg        /* Translate the client area mouse coordinates to screen coordinates */
51935c4bbdfSmrg        ClientToScreen(hwnd, &ptMouse);
52035c4bbdfSmrg
52135c4bbdfSmrg        /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
52235c4bbdfSmrg        ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
52335c4bbdfSmrg        ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
52435c4bbdfSmrg
52535c4bbdfSmrg        /* We can't do anything without privates */
52635c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
52735c4bbdfSmrg            break;
52835c4bbdfSmrg
52935c4bbdfSmrg        /* Has the mouse pointer crossed screens? */
53035c4bbdfSmrg        if (s_pScreen != miPointerGetScreen(g_pwinPointer))
53135c4bbdfSmrg            miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
53235c4bbdfSmrg                               ptMouse.x - s_pScreenInfo->dwXOffset,
53335c4bbdfSmrg                               ptMouse.y - s_pScreenInfo->dwYOffset);
53435c4bbdfSmrg
53535c4bbdfSmrg        /* Are we tracking yet? */
53635c4bbdfSmrg        if (!s_fTracking) {
53735c4bbdfSmrg            TRACKMOUSEEVENT tme;
53835c4bbdfSmrg
53935c4bbdfSmrg            /* Setup data structure */
54035c4bbdfSmrg            ZeroMemory(&tme, sizeof(tme));
54135c4bbdfSmrg            tme.cbSize = sizeof(tme);
54235c4bbdfSmrg            tme.dwFlags = TME_LEAVE;
54335c4bbdfSmrg            tme.hwndTrack = hwnd;
54435c4bbdfSmrg
54535c4bbdfSmrg            /* Call the tracking function */
54635c4bbdfSmrg            if (!TrackMouseEvent(&tme))
54735c4bbdfSmrg                ErrorF("winTopLevelWindowProc - TrackMouseEvent failed\n");
54835c4bbdfSmrg
54935c4bbdfSmrg            /* Flag that we are tracking now */
55035c4bbdfSmrg            s_fTracking = TRUE;
55135c4bbdfSmrg        }
55235c4bbdfSmrg
55335c4bbdfSmrg        /* Hide or show the Windows mouse cursor */
55435c4bbdfSmrg        if (g_fSoftwareCursor && g_fCursor) {
55535c4bbdfSmrg            /* Hide Windows cursor */
55635c4bbdfSmrg            g_fCursor = FALSE;
55735c4bbdfSmrg            ShowCursor(FALSE);
55835c4bbdfSmrg        }
55935c4bbdfSmrg
56035c4bbdfSmrg        /* Kill the timer used to poll mouse events */
56135c4bbdfSmrg        if (g_uipMousePollingTimerID != 0) {
56235c4bbdfSmrg            KillTimer(s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
56335c4bbdfSmrg            g_uipMousePollingTimerID = 0;
56435c4bbdfSmrg        }
56535c4bbdfSmrg
56635c4bbdfSmrg        /* Deliver absolute cursor position to X Server */
56735c4bbdfSmrg        winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
56835c4bbdfSmrg                         ptMouse.y - s_pScreenInfo->dwYOffset);
56935c4bbdfSmrg
57035c4bbdfSmrg        return 0;
57135c4bbdfSmrg
57205b261ecSmrg    case WM_NCMOUSEMOVE:
57335c4bbdfSmrg        /*
57435c4bbdfSmrg         * We break instead of returning 0 since we need to call
57535c4bbdfSmrg         * DefWindowProc to get the mouse cursor changes
57635c4bbdfSmrg         * and min/max/close button highlighting in Windows XP.
57735c4bbdfSmrg         * The Platform SDK says that you should return 0 if you
57835c4bbdfSmrg         * process this message, but it fails to mention that you
57935c4bbdfSmrg         * will give up any default functionality if you do return 0.
58035c4bbdfSmrg         */
58135c4bbdfSmrg
58235c4bbdfSmrg        /* We can't do anything without privates */
58335c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
58435c4bbdfSmrg            break;
58535c4bbdfSmrg
58635c4bbdfSmrg        /* Non-client mouse movement, show Windows cursor */
58735c4bbdfSmrg        if (g_fSoftwareCursor && !g_fCursor) {
58835c4bbdfSmrg            g_fCursor = TRUE;
58935c4bbdfSmrg            ShowCursor(TRUE);
59035c4bbdfSmrg        }
59135c4bbdfSmrg
59235c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
59335c4bbdfSmrg
59435c4bbdfSmrg        break;
59505b261ecSmrg
59605b261ecSmrg    case WM_MOUSELEAVE:
59735c4bbdfSmrg        /* Mouse has left our client area */
59805b261ecSmrg
59935c4bbdfSmrg        /* Flag that we are no longer tracking */
60035c4bbdfSmrg        s_fTracking = FALSE;
60105b261ecSmrg
60235c4bbdfSmrg        /* Show the mouse cursor, if necessary */
60335c4bbdfSmrg        if (g_fSoftwareCursor && !g_fCursor) {
60435c4bbdfSmrg            g_fCursor = TRUE;
60535c4bbdfSmrg            ShowCursor(TRUE);
60635c4bbdfSmrg        }
60705b261ecSmrg
60835c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
6096747b715Smrg
61035c4bbdfSmrg        return 0;
61105b261ecSmrg
61205b261ecSmrg    case WM_LBUTTONDBLCLK:
61305b261ecSmrg    case WM_LBUTTONDOWN:
61435c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
61535c4bbdfSmrg            break;
61635c4bbdfSmrg        g_fButton[0] = TRUE;
61735c4bbdfSmrg        SetCapture(hwnd);
61835c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
6196747b715Smrg
62005b261ecSmrg    case WM_LBUTTONUP:
62135c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
62235c4bbdfSmrg            break;
62335c4bbdfSmrg        g_fButton[0] = FALSE;
62435c4bbdfSmrg        ReleaseCapture();
62535c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
62635c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
62705b261ecSmrg
62805b261ecSmrg    case WM_MBUTTONDBLCLK:
62905b261ecSmrg    case WM_MBUTTONDOWN:
63035c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
63135c4bbdfSmrg            break;
63235c4bbdfSmrg        g_fButton[1] = TRUE;
63335c4bbdfSmrg        SetCapture(hwnd);
63435c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
6356747b715Smrg
63605b261ecSmrg    case WM_MBUTTONUP:
63735c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
63835c4bbdfSmrg            break;
63935c4bbdfSmrg        g_fButton[1] = FALSE;
64035c4bbdfSmrg        ReleaseCapture();
64135c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
64235c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
6436747b715Smrg
64405b261ecSmrg    case WM_RBUTTONDBLCLK:
64505b261ecSmrg    case WM_RBUTTONDOWN:
64635c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
64735c4bbdfSmrg            break;
64835c4bbdfSmrg        g_fButton[2] = TRUE;
64935c4bbdfSmrg        SetCapture(hwnd);
65035c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
6516747b715Smrg
65205b261ecSmrg    case WM_RBUTTONUP:
65335c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
65435c4bbdfSmrg            break;
65535c4bbdfSmrg        g_fButton[2] = FALSE;
65635c4bbdfSmrg        ReleaseCapture();
65735c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
65835c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
65905b261ecSmrg
66005b261ecSmrg    case WM_XBUTTONDBLCLK:
66105b261ecSmrg    case WM_XBUTTONDOWN:
66235c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
66335c4bbdfSmrg            break;
66435c4bbdfSmrg        SetCapture(hwnd);
66535c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
66635c4bbdfSmrg                                     wParam);
6676747b715Smrg
66805b261ecSmrg    case WM_XBUTTONUP:
66935c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
67035c4bbdfSmrg            break;
67135c4bbdfSmrg        ReleaseCapture();
67235c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
67335c4bbdfSmrg        return winMouseButtonsHandle(s_pScreen, ButtonRelease,
67435c4bbdfSmrg                                     HIWORD(wParam) + 7, wParam);
67505b261ecSmrg
67605b261ecSmrg    case WM_MOUSEWHEEL:
67735c4bbdfSmrg        if (SendMessage
67835c4bbdfSmrg            (hwnd, WM_NCHITTEST, 0,
67935c4bbdfSmrg             MAKELONG(GET_X_LPARAM(lParam),
68035c4bbdfSmrg                      GET_Y_LPARAM(lParam))) == HTCLIENT) {
68135c4bbdfSmrg            /* Pass the message to the root window */
68235c4bbdfSmrg            SendMessage(hwndScreen, message, wParam, lParam);
68335c4bbdfSmrg            return 0;
68435c4bbdfSmrg        }
68535c4bbdfSmrg        else
68635c4bbdfSmrg            break;
68735c4bbdfSmrg
68835c4bbdfSmrg    case WM_MOUSEHWHEEL:
68935c4bbdfSmrg        if (SendMessage
69035c4bbdfSmrg            (hwnd, WM_NCHITTEST, 0,
69135c4bbdfSmrg             MAKELONG(GET_X_LPARAM(lParam),
69235c4bbdfSmrg                      GET_Y_LPARAM(lParam))) == HTCLIENT) {
69335c4bbdfSmrg            /* Pass the message to the root window */
69435c4bbdfSmrg            SendMessage(hwndScreen, message, wParam, lParam);
69535c4bbdfSmrg            return 0;
69635c4bbdfSmrg        }
69735c4bbdfSmrg        else
69835c4bbdfSmrg            break;
69905b261ecSmrg
70005b261ecSmrg    case WM_SETFOCUS:
70135c4bbdfSmrg        if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
70235c4bbdfSmrg            break;
70335c4bbdfSmrg
70435c4bbdfSmrg        {
70535c4bbdfSmrg            /* Get the parent window for transient handling */
70635c4bbdfSmrg            HWND hParent = GetParent(hwnd);
70735c4bbdfSmrg
70835c4bbdfSmrg            if (hParent && IsIconic(hParent))
70935c4bbdfSmrg                ShowWindow(hParent, SW_RESTORE);
71035c4bbdfSmrg        }
71135c4bbdfSmrg
71235c4bbdfSmrg        winRestoreModeKeyStates();
71335c4bbdfSmrg
71435c4bbdfSmrg        /* Add the keyboard hook if possible */
71535c4bbdfSmrg        if (g_fKeyboardHookLL)
71635c4bbdfSmrg            g_fKeyboardHookLL = winInstallKeyboardHookLL();
71735c4bbdfSmrg        return 0;
71835c4bbdfSmrg
71905b261ecSmrg    case WM_KILLFOCUS:
72035c4bbdfSmrg        /* Pop any pressed keys since we are losing keyboard focus */
72135c4bbdfSmrg        winKeybdReleaseKeys();
72235c4bbdfSmrg
72335c4bbdfSmrg        /* Remove our keyboard hook if it is installed */
72435c4bbdfSmrg        winRemoveKeyboardHookLL();
72535c4bbdfSmrg
72635c4bbdfSmrg        /* Revert the X focus as well, but only if the Windows focus is going to another window */
72735c4bbdfSmrg        if (!wParam && pWin)
72835c4bbdfSmrg            DeleteWindowFromAnyEvents(pWin, FALSE);
72905b261ecSmrg
73035c4bbdfSmrg        return 0;
73105b261ecSmrg
73235c4bbdfSmrg    case WM_SYSDEADCHAR:
73305b261ecSmrg    case WM_DEADCHAR:
73435c4bbdfSmrg        /*
73535c4bbdfSmrg         * NOTE: We do nothing with WM_*CHAR messages,
73635c4bbdfSmrg         * nor does the root window, so we can just toss these messages.
73735c4bbdfSmrg         */
73835c4bbdfSmrg        return 0;
73905b261ecSmrg
74005b261ecSmrg    case WM_SYSKEYDOWN:
74105b261ecSmrg    case WM_KEYDOWN:
74205b261ecSmrg
74335c4bbdfSmrg        /*
74435c4bbdfSmrg         * Don't pass Alt-F4 key combo to root window,
74535c4bbdfSmrg         * let Windows translate to WM_CLOSE and close this top-level window.
74635c4bbdfSmrg         *
74735c4bbdfSmrg         * NOTE: We purposely don't check the fUseWinKillKey setting because
74835c4bbdfSmrg         * it should only apply to the key handling for the root window,
74935c4bbdfSmrg         * not for top-level window-manager windows.
75035c4bbdfSmrg         *
75135c4bbdfSmrg         * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
75235c4bbdfSmrg         * because that is a key combo that no X app should be expecting to
75335c4bbdfSmrg         * receive, since it has historically been used to shutdown the X server.
75435c4bbdfSmrg         * Passing Ctrl-Alt-Backspace to the root window preserves that
75535c4bbdfSmrg         * behavior, assuming that -unixkill has been passed as a parameter.
75635c4bbdfSmrg         */
75735c4bbdfSmrg        if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000))
75835c4bbdfSmrg            break;
75905b261ecSmrg
76005b261ecSmrg#if CYGWINDOWING_DEBUG
76135c4bbdfSmrg        if (wParam == VK_ESCAPE) {
76235c4bbdfSmrg            /* Place for debug: put any tests and dumps here */
76335c4bbdfSmrg            WINDOWPLACEMENT windPlace;
76435c4bbdfSmrg            RECT rc;
76535c4bbdfSmrg            LPRECT pRect;
76635c4bbdfSmrg
76735c4bbdfSmrg            windPlace.length = sizeof(WINDOWPLACEMENT);
76835c4bbdfSmrg            GetWindowPlacement(hwnd, &windPlace);
76935c4bbdfSmrg            pRect = &windPlace.rcNormalPosition;
77035c4bbdfSmrg            ErrorF("\nCYGWINDOWING Dump:\n"
77135c4bbdfSmrg                   "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
77235c4bbdfSmrg                   pDraw->y, pDraw->width, pDraw->height);
77335c4bbdfSmrg            ErrorF("\twindPlace: (%d, %d) - %dx%d\n", (int)pRect->left,
77435c4bbdfSmrg                   (int)pRect->top, (int)(pRect->right - pRect->left),
77535c4bbdfSmrg                   (int)(pRect->bottom - pRect->top));
77635c4bbdfSmrg            if (GetClientRect(hwnd, &rc)) {
77735c4bbdfSmrg                pRect = &rc;
77835c4bbdfSmrg                ErrorF("\tClientRect: (%d, %d) - %dx%d\n", (int)pRect->left,
77935c4bbdfSmrg                       (int)pRect->top, (int)(pRect->right - pRect->left),
78035c4bbdfSmrg                       (int)(pRect->bottom - pRect->top));
78135c4bbdfSmrg            }
78235c4bbdfSmrg            if (GetWindowRect(hwnd, &rc)) {
78335c4bbdfSmrg                pRect = &rc;
78435c4bbdfSmrg                ErrorF("\tWindowRect: (%d, %d) - %dx%d\n", (int)pRect->left,
78535c4bbdfSmrg                       (int)pRect->top, (int)(pRect->right - pRect->left),
78635c4bbdfSmrg                       (int)(pRect->bottom - pRect->top));
78735c4bbdfSmrg            }
78835c4bbdfSmrg            ErrorF("\n");
78935c4bbdfSmrg        }
79005b261ecSmrg#endif
79135c4bbdfSmrg
79235c4bbdfSmrg        /* Pass the message to the root window */
79335c4bbdfSmrg        return winWindowProc(hwndScreen, message, wParam, lParam);
79405b261ecSmrg
79505b261ecSmrg    case WM_SYSKEYUP:
79605b261ecSmrg    case WM_KEYUP:
79705b261ecSmrg
79835c4bbdfSmrg        /* Pass the message to the root window */
79935c4bbdfSmrg        return winWindowProc(hwndScreen, message, wParam, lParam);
80005b261ecSmrg
80105b261ecSmrg    case WM_HOTKEY:
80205b261ecSmrg
80335c4bbdfSmrg        /* Pass the message to the root window */
80435c4bbdfSmrg        SendMessage(hwndScreen, message, wParam, lParam);
80535c4bbdfSmrg        return 0;
80605b261ecSmrg
80705b261ecSmrg    case WM_ACTIVATE:
80805b261ecSmrg
80935c4bbdfSmrg        /* Pass the message to the root window */
81035c4bbdfSmrg        SendMessage(hwndScreen, message, wParam, lParam);
81135c4bbdfSmrg
81235c4bbdfSmrg        if (LOWORD(wParam) != WA_INACTIVE) {
81335c4bbdfSmrg            /* Raise the window to the top in Z order */
81435c4bbdfSmrg            /* ago: Activate does not mean putting it to front! */
81535c4bbdfSmrg            /*
81635c4bbdfSmrg               wmMsg.msg = WM_WM_RAISE;
81735c4bbdfSmrg               if (fWMMsgInitialized)
81835c4bbdfSmrg               winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
81935c4bbdfSmrg             */
82035c4bbdfSmrg
82135c4bbdfSmrg            /* Tell our Window Manager thread to activate the window */
82235c4bbdfSmrg            wmMsg.msg = WM_WM_ACTIVATE;
82335c4bbdfSmrg            if (fWMMsgInitialized)
82435c4bbdfSmrg                if (!pWin || !pWin->overrideRedirect)   /* for OOo menus */
82535c4bbdfSmrg                    winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
82635c4bbdfSmrg        }
82735c4bbdfSmrg        /* Prevent the mouse wheel from stalling when another window is minimized */
82835c4bbdfSmrg        if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
82935c4bbdfSmrg            (HWND) lParam != NULL && (HWND) lParam != GetParent(hwnd))
83035c4bbdfSmrg            SetFocus(hwnd);
83135c4bbdfSmrg        return 0;
83205b261ecSmrg
83305b261ecSmrg    case WM_ACTIVATEAPP:
83435c4bbdfSmrg        /*
83535c4bbdfSmrg         * This message is also sent to the root window
83635c4bbdfSmrg         * so we do nothing for individual multiwindow windows
83735c4bbdfSmrg         */
83835c4bbdfSmrg        break;
83905b261ecSmrg
84005b261ecSmrg    case WM_CLOSE:
84135c4bbdfSmrg        /* Remove AppUserModelID property */
84235c4bbdfSmrg        winSetAppUserModelID(hwnd, NULL);
84335c4bbdfSmrg        /* Branch on if the window was killed in X already */
84435c4bbdfSmrg        if (pWinPriv->fXKilled) {
84535c4bbdfSmrg            /* Window was killed, go ahead and destroy the window */
84635c4bbdfSmrg            DestroyWindow(hwnd);
84735c4bbdfSmrg        }
84835c4bbdfSmrg        else {
84935c4bbdfSmrg            /* Tell our Window Manager thread to kill the window */
85035c4bbdfSmrg            wmMsg.msg = WM_WM_KILL;
85135c4bbdfSmrg            if (fWMMsgInitialized)
85235c4bbdfSmrg                winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
85335c4bbdfSmrg        }
85435c4bbdfSmrg        return 0;
85505b261ecSmrg
85605b261ecSmrg    case WM_DESTROY:
85705b261ecSmrg
85835c4bbdfSmrg        /* Branch on if the window was killed in X already */
85935c4bbdfSmrg        if (pWinPriv && !pWinPriv->fXKilled) {
86035c4bbdfSmrg            ErrorF("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
86105b261ecSmrg
86235c4bbdfSmrg            /* Tell our Window Manager thread to kill the window */
86335c4bbdfSmrg            wmMsg.msg = WM_WM_KILL;
86435c4bbdfSmrg            if (fWMMsgInitialized)
86535c4bbdfSmrg                winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
86635c4bbdfSmrg        }
86735c4bbdfSmrg
86835c4bbdfSmrg        RemoveProp(hwnd, WIN_WINDOW_PROP);
86935c4bbdfSmrg        RemoveProp(hwnd, WIN_WID_PROP);
87035c4bbdfSmrg        RemoveProp(hwnd, WIN_NEEDMANAGE_PROP);
87105b261ecSmrg
87235c4bbdfSmrg        break;
87305b261ecSmrg
87405b261ecSmrg    case WM_MOVE:
87535c4bbdfSmrg        /* Adjust the X Window to the moved Windows window */
87635c4bbdfSmrg        if (!hasEnteredSizeMove)
87735c4bbdfSmrg            winAdjustXWindow(pWin, hwnd);
87835c4bbdfSmrg        /* else: Wait for WM_EXITSIZEMOVE */
87935c4bbdfSmrg        return 0;
88005b261ecSmrg
88105b261ecSmrg    case WM_SHOWWINDOW:
88235c4bbdfSmrg        /* Bail out if the window is being hidden */
88335c4bbdfSmrg        if (!wParam)
88435c4bbdfSmrg            return 0;
88535c4bbdfSmrg
88635c4bbdfSmrg        /* */
88735c4bbdfSmrg        if (!pWin->overrideRedirect) {
88835c4bbdfSmrg            HWND zstyle = HWND_NOTOPMOST;
88935c4bbdfSmrg
89035c4bbdfSmrg            /* Flag that this window needs to be made active when clicked */
89135c4bbdfSmrg            SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
89235c4bbdfSmrg
89335c4bbdfSmrg            /* Set the transient style flags */
89435c4bbdfSmrg            if (GetParent(hwnd))
89535c4bbdfSmrg                SetWindowLongPtr(hwnd, GWL_STYLE,
89635c4bbdfSmrg                                 WS_POPUP | WS_OVERLAPPED | WS_SYSMENU |
89735c4bbdfSmrg                                 WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
89835c4bbdfSmrg            /* Set the window standard style flags */
89935c4bbdfSmrg            else
90035c4bbdfSmrg                SetWindowLongPtr(hwnd, GWL_STYLE,
90135c4bbdfSmrg                                 (WS_POPUP | WS_OVERLAPPEDWINDOW |
90235c4bbdfSmrg                                  WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
90335c4bbdfSmrg                                 & ~WS_CAPTION & ~WS_SIZEBOX);
90435c4bbdfSmrg
90535c4bbdfSmrg            winUpdateWindowPosition(hwnd, &zstyle);
90635c4bbdfSmrg
90735c4bbdfSmrg            {
90835c4bbdfSmrg                WinXWMHints hints;
90935c4bbdfSmrg
91035c4bbdfSmrg                if (winMultiWindowGetWMHints(pWin, &hints)) {
91135c4bbdfSmrg                    /*
91235c4bbdfSmrg                       Give the window focus, unless it has an InputHint
91335c4bbdfSmrg                       which is FALSE (this is used by e.g. glean to
91435c4bbdfSmrg                       avoid every test window grabbing the focus)
91535c4bbdfSmrg                     */
91635c4bbdfSmrg                    if (!((hints.flags & InputHint) && (!hints.input))) {
91735c4bbdfSmrg                        SetForegroundWindow(hwnd);
91835c4bbdfSmrg                    }
91935c4bbdfSmrg                }
92035c4bbdfSmrg            }
92135c4bbdfSmrg            wmMsg.msg = WM_WM_MAP3;
92235c4bbdfSmrg        }
92335c4bbdfSmrg        else {                  /* It is an overridden window so make it top of Z stack */
92435c4bbdfSmrg
92535c4bbdfSmrg            HWND forHwnd = GetForegroundWindow();
92635c4bbdfSmrg
92705b261ecSmrg#if CYGWINDOWING_DEBUG
92835c4bbdfSmrg            ErrorF("overridden window is shown\n");
92905b261ecSmrg#endif
93035c4bbdfSmrg            if (forHwnd != NULL) {
93135c4bbdfSmrg                if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)
93235c4bbdfSmrg                    XMING_SIGNATURE) {
93335c4bbdfSmrg                    if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
93435c4bbdfSmrg                        SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
93535c4bbdfSmrg                                     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
93635c4bbdfSmrg                    else
93735c4bbdfSmrg                        SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
93835c4bbdfSmrg                                     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
93935c4bbdfSmrg                }
94035c4bbdfSmrg            }
94135c4bbdfSmrg            wmMsg.msg = WM_WM_MAP2;
94235c4bbdfSmrg        }
94335c4bbdfSmrg
94435c4bbdfSmrg        /* Tell our Window Manager thread to map the window */
94535c4bbdfSmrg        if (fWMMsgInitialized)
94635c4bbdfSmrg            winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
94735c4bbdfSmrg
94835c4bbdfSmrg        winStartMousePolling(s_pScreenPriv);
94935c4bbdfSmrg
95035c4bbdfSmrg        return 0;
95105b261ecSmrg
95205b261ecSmrg    case WM_SIZING:
95335c4bbdfSmrg        /* Need to legalize the size according to WM_NORMAL_HINTS */
95435c4bbdfSmrg        /* for applications like xterm */
95535c4bbdfSmrg        return ValidateSizing(hwnd, pWin, wParam, lParam);
95605b261ecSmrg
95705b261ecSmrg    case WM_WINDOWPOSCHANGED:
95835c4bbdfSmrg    {
95935c4bbdfSmrg        LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
96005b261ecSmrg
96135c4bbdfSmrg        if (!(pWinPos->flags & SWP_NOZORDER)) {
96205b261ecSmrg#if CYGWINDOWING_DEBUG
96335c4bbdfSmrg            winDebug("\twindow z order was changed\n");
96405b261ecSmrg#endif
96535c4bbdfSmrg            if (pWinPos->hwndInsertAfter == HWND_TOP
96635c4bbdfSmrg                || pWinPos->hwndInsertAfter == HWND_TOPMOST
96735c4bbdfSmrg                || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) {
96805b261ecSmrg#if CYGWINDOWING_DEBUG
96935c4bbdfSmrg                winDebug("\traise to top\n");
97005b261ecSmrg#endif
97135c4bbdfSmrg                /* Raise the window to the top in Z order */
97235c4bbdfSmrg                winRaiseWindow(pWin);
97335c4bbdfSmrg            }
97435c4bbdfSmrg            else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) {
97535c4bbdfSmrg            }
97635c4bbdfSmrg            else {
97735c4bbdfSmrg                /* Check if this window is top of X windows. */
97835c4bbdfSmrg                HWND hWndAbove = NULL;
97935c4bbdfSmrg                DWORD dwCurrentProcessID = GetCurrentProcessId();
98035c4bbdfSmrg                DWORD dwWindowProcessID = 0;
98135c4bbdfSmrg
98235c4bbdfSmrg                for (hWndAbove = pWinPos->hwndInsertAfter;
98335c4bbdfSmrg                     hWndAbove != NULL;
98435c4bbdfSmrg                     hWndAbove = GetNextWindow(hWndAbove, GW_HWNDPREV)) {
98535c4bbdfSmrg                    /* Ignore other XWin process's window */
98635c4bbdfSmrg                    GetWindowThreadProcessId(hWndAbove, &dwWindowProcessID);
98735c4bbdfSmrg
98835c4bbdfSmrg                    if ((dwWindowProcessID == dwCurrentProcessID)
98935c4bbdfSmrg                        && GetProp(hWndAbove, WIN_WINDOW_PROP)
99035c4bbdfSmrg                        && !IsWindowVisible(hWndAbove)
99135c4bbdfSmrg                        && !IsIconic(hWndAbove))        /* ignore minimized windows */
99235c4bbdfSmrg                        break;
99335c4bbdfSmrg                }
99435c4bbdfSmrg                /* If this is top of X windows in Windows stack,
99535c4bbdfSmrg                   raise it in X stack. */
99635c4bbdfSmrg                if (hWndAbove == NULL) {
99705b261ecSmrg#if CYGWINDOWING_DEBUG
99835c4bbdfSmrg                    winDebug("\traise to top\n");
99905b261ecSmrg#endif
100035c4bbdfSmrg                    winRaiseWindow(pWin);
100135c4bbdfSmrg                }
100235c4bbdfSmrg            }
100335c4bbdfSmrg        }
100435c4bbdfSmrg    }
100535c4bbdfSmrg        /*
100635c4bbdfSmrg         * Pass the message to DefWindowProc to let the function
100735c4bbdfSmrg         * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
100835c4bbdfSmrg         */
100935c4bbdfSmrg        break;
101035c4bbdfSmrg
101135c4bbdfSmrg    case WM_ENTERSIZEMOVE:
101235c4bbdfSmrg        hasEnteredSizeMove = TRUE;
101335c4bbdfSmrg        return 0;
101435c4bbdfSmrg
101535c4bbdfSmrg    case WM_EXITSIZEMOVE:
101635c4bbdfSmrg        /* Adjust the X Window to the moved Windows window */
101735c4bbdfSmrg        hasEnteredSizeMove = FALSE;
101835c4bbdfSmrg        winAdjustXWindow(pWin, hwnd);
101935c4bbdfSmrg        return 0;
102005b261ecSmrg
102105b261ecSmrg    case WM_SIZE:
102235c4bbdfSmrg        /* see dix/window.c */
102305b261ecSmrg#if CYGWINDOWING_DEBUG
102435c4bbdfSmrg    {
102535c4bbdfSmrg        char buf[64];
102635c4bbdfSmrg
102735c4bbdfSmrg        switch (wParam) {
102835c4bbdfSmrg        case SIZE_MINIMIZED:
102935c4bbdfSmrg            strcpy(buf, "SIZE_MINIMIZED");
103035c4bbdfSmrg            break;
103135c4bbdfSmrg        case SIZE_MAXIMIZED:
103235c4bbdfSmrg            strcpy(buf, "SIZE_MAXIMIZED");
103335c4bbdfSmrg            break;
103435c4bbdfSmrg        case SIZE_RESTORED:
103535c4bbdfSmrg            strcpy(buf, "SIZE_RESTORED");
103635c4bbdfSmrg            break;
103735c4bbdfSmrg        default:
103835c4bbdfSmrg            strcpy(buf, "UNKNOWN_FLAG");
103935c4bbdfSmrg        }
104035c4bbdfSmrg        ErrorF("winTopLevelWindowProc - WM_SIZE to %dx%d (%s)\n",
104135c4bbdfSmrg               (int) LOWORD(lParam), (int) HIWORD(lParam), buf);
104235c4bbdfSmrg    }
104305b261ecSmrg#endif
104435c4bbdfSmrg        if (!hasEnteredSizeMove) {
104535c4bbdfSmrg            /* Adjust the X Window to the moved Windows window */
104635c4bbdfSmrg            winAdjustXWindow(pWin, hwnd);
104735c4bbdfSmrg        }
104835c4bbdfSmrg        /* else: wait for WM_EXITSIZEMOVE */
104935c4bbdfSmrg        return 0;               /* end of WM_SIZE handler */
105035c4bbdfSmrg
105135c4bbdfSmrg    case WM_STYLECHANGING:
105235c4bbdfSmrg        /*
105335c4bbdfSmrg           When the style changes, adjust the Windows window size so the client area remains the same size,
105435c4bbdfSmrg           and adjust the Windows window position so that the client area remains in the same place.
105535c4bbdfSmrg         */
105635c4bbdfSmrg    {
105735c4bbdfSmrg        RECT newWinRect;
105835c4bbdfSmrg        DWORD dwExStyle;
105935c4bbdfSmrg        DWORD dwStyle;
106035c4bbdfSmrg        DWORD newStyle = ((STYLESTRUCT *) lParam)->styleNew;
106135c4bbdfSmrg        WINDOWINFO wi;
106235c4bbdfSmrg
106335c4bbdfSmrg        dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
106435c4bbdfSmrg        dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
106535c4bbdfSmrg
106635c4bbdfSmrg        winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n",
106735c4bbdfSmrg                 (unsigned int)dwStyle, (unsigned int)dwExStyle);
106835c4bbdfSmrg
106935c4bbdfSmrg        if (wParam == GWL_EXSTYLE)
107035c4bbdfSmrg            dwExStyle = newStyle;
107135c4bbdfSmrg
107235c4bbdfSmrg        if (wParam == GWL_STYLE)
107335c4bbdfSmrg            dwStyle = newStyle;
107435c4bbdfSmrg
107535c4bbdfSmrg        winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n",
107635c4bbdfSmrg                 (unsigned int)dwStyle, (unsigned int)dwExStyle);
107735c4bbdfSmrg
107835c4bbdfSmrg        /* Get client rect in screen coordinates */
107935c4bbdfSmrg        wi.cbSize = sizeof(WINDOWINFO);
108035c4bbdfSmrg        GetWindowInfo(hwnd, &wi);
108135c4bbdfSmrg
108235c4bbdfSmrg        winDebug
108335c4bbdfSmrg            ("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n",
108435c4bbdfSmrg             (int)wi.rcClient.left, (int)wi.rcClient.top, (int)wi.rcClient.right,
108535c4bbdfSmrg             (int)wi.rcClient.bottom, (int)(wi.rcClient.right - wi.rcClient.left),
108635c4bbdfSmrg             (int)(wi.rcClient.bottom - wi.rcClient.top));
108735c4bbdfSmrg
108835c4bbdfSmrg        newWinRect = wi.rcClient;
108935c4bbdfSmrg        if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle))
109035c4bbdfSmrg            winDebug
109135c4bbdfSmrg                ("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n");
109235c4bbdfSmrg
109335c4bbdfSmrg        winDebug
109435c4bbdfSmrg            ("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n",
109535c4bbdfSmrg             (int)newWinRect.left, (int)newWinRect.top, (int)newWinRect.right,
109635c4bbdfSmrg             (int)newWinRect.bottom, (int)(newWinRect.right - newWinRect.left),
109735c4bbdfSmrg             (int)(newWinRect.bottom - newWinRect.top));
109835c4bbdfSmrg
109935c4bbdfSmrg        /*
110035c4bbdfSmrg           Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow()
110135c4bbdfSmrg           which WM_SIZE does will use the current (unchanged) style.  Instead make a note to change it when
110235c4bbdfSmrg           WM_STYLECHANGED is received...
110335c4bbdfSmrg         */
110435c4bbdfSmrg        pWinPriv->hDwp = BeginDeferWindowPos(1);
110535c4bbdfSmrg        pWinPriv->hDwp =
110635c4bbdfSmrg            DeferWindowPos(pWinPriv->hDwp, hwnd, NULL, newWinRect.left,
110735c4bbdfSmrg                           newWinRect.top, newWinRect.right - newWinRect.left,
110835c4bbdfSmrg                           newWinRect.bottom - newWinRect.top,
110935c4bbdfSmrg                           SWP_NOACTIVATE | SWP_NOZORDER);
111035c4bbdfSmrg    }
111135c4bbdfSmrg        return 0;
111235c4bbdfSmrg
111335c4bbdfSmrg    case WM_STYLECHANGED:
111435c4bbdfSmrg    {
111535c4bbdfSmrg        if (pWinPriv->hDwp) {
111635c4bbdfSmrg            EndDeferWindowPos(pWinPriv->hDwp);
111735c4bbdfSmrg            pWinPriv->hDwp = NULL;
111835c4bbdfSmrg        }
111935c4bbdfSmrg        winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n");
112035c4bbdfSmrg    }
112135c4bbdfSmrg        return 0;
112205b261ecSmrg
112305b261ecSmrg    case WM_MOUSEACTIVATE:
112405b261ecSmrg
112535c4bbdfSmrg        /* Check if this window needs to be made active when clicked */
112635c4bbdfSmrg        if (!GetProp(pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) {
112705b261ecSmrg#if CYGMULTIWINDOW_DEBUG
112835c4bbdfSmrg            ErrorF("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
112935c4bbdfSmrg                   "MA_NOACTIVATE\n");
113005b261ecSmrg#endif
113105b261ecSmrg
113235c4bbdfSmrg            /* */
113335c4bbdfSmrg            return MA_NOACTIVATE;
113435c4bbdfSmrg        }
113535c4bbdfSmrg        break;
113605b261ecSmrg
113705b261ecSmrg    case WM_SETCURSOR:
113835c4bbdfSmrg        if (LOWORD(lParam) == HTCLIENT) {
113935c4bbdfSmrg            if (!g_fSoftwareCursor)
114035c4bbdfSmrg                SetCursor(s_pScreenPriv->cursor.handle);
114135c4bbdfSmrg            return TRUE;
114235c4bbdfSmrg        }
114335c4bbdfSmrg        break;
114405b261ecSmrg
114505b261ecSmrg    default:
114635c4bbdfSmrg        break;
114705b261ecSmrg    }
114805b261ecSmrg
114935c4bbdfSmrg    ret = DefWindowProc(hwnd, message, wParam, lParam);
115035c4bbdfSmrg    /*
115135c4bbdfSmrg     * If the window was minized we get the stack change before the window is restored
115235c4bbdfSmrg     * and so it gets lost. Ensure there stacking order is correct.
115335c4bbdfSmrg     */
115435c4bbdfSmrg    if (needRestack)
115535c4bbdfSmrg        winReorderWindowsMultiWindow();
115635c4bbdfSmrg    return ret;
115705b261ecSmrg}
1158