winmultiwindowwm.c revision 1b5d61b8
105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
36747b715Smrg *Copyright (C) Colin Harrison 2005-2009
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
306747b715Smrg *              Colin Harrison
3105b261ecSmrg */
3205b261ecSmrg
3305b261ecSmrg/* X headers */
3405b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3505b261ecSmrg#include <xwin-config.h>
3605b261ecSmrg#endif
3705b261ecSmrg#include <stdio.h>
3805b261ecSmrg#include <stdlib.h>
3905b261ecSmrg#include <unistd.h>
4005b261ecSmrg#ifdef __CYGWIN__
4105b261ecSmrg#include <sys/select.h>
4205b261ecSmrg#endif
4305b261ecSmrg#include <fcntl.h>
4405b261ecSmrg#include <setjmp.h>
4505b261ecSmrg#define HANDLE void *
4605b261ecSmrg#include <pthread.h>
4705b261ecSmrg#undef HANDLE
481b5d61b8Smrg#include <xcb/xcb.h>
491b5d61b8Smrg#include <xcb/xcb_icccm.h>
501b5d61b8Smrg#include <xcb/xcb_ewmh.h>
511b5d61b8Smrg#include <xcb/xcb_aux.h>
521b5d61b8Smrg
536747b715Smrg#include <X11/Xwindows.h>
5405b261ecSmrg
5505b261ecSmrg/* Local headers */
561b5d61b8Smrg#include "X11/Xdefs.h" // for Bool type
5705b261ecSmrg#include "winwindow.h"
586747b715Smrg#include "winprefs.h"
596747b715Smrg#include "window.h"
606747b715Smrg#include "pixmapstr.h"
616747b715Smrg#include "windowstr.h"
6235c4bbdfSmrg#include "winglobals.h"
6335c4bbdfSmrg#include "windisplay.h"
641b5d61b8Smrg#include "winmultiwindowicons.h"
656747b715Smrg
666747b715Smrg/* We need the native HWND atom for intWM, so for consistency use the
671b5d61b8Smrg   same name as extWM does */
686747b715Smrg#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
6905b261ecSmrg
7035c4bbdfSmrg#ifndef HOST_NAME_MAX
7135c4bbdfSmrg#define HOST_NAME_MAX 255
7235c4bbdfSmrg#endif
7335c4bbdfSmrg
7405b261ecSmrgextern void winDebug(const char *format, ...);
756747b715Smrgextern void winReshapeMultiWindow(WindowPtr pWin);
766747b715Smrgextern void winUpdateRgnMultiWindow(WindowPtr pWin);
771b5d61b8Smrgextern xcb_auth_info_t *winGetXcbAuthInfo(void);
7805b261ecSmrg
7905b261ecSmrg#ifndef CYGDEBUG
8005b261ecSmrg#define CYGDEBUG NO
8105b261ecSmrg#endif
8205b261ecSmrg
8305b261ecSmrg/*
8405b261ecSmrg * Constant defines
8505b261ecSmrg */
8605b261ecSmrg
8705b261ecSmrg#define WIN_CONNECT_RETRIES	5
8805b261ecSmrg#define WIN_CONNECT_DELAY	5
8905b261ecSmrg#ifdef HAS_DEVWINDOWS
9035c4bbdfSmrg#define WIN_MSG_QUEUE_FNAME	"/dev/windows"
9105b261ecSmrg#endif
9205b261ecSmrg
9305b261ecSmrg/*
9405b261ecSmrg * Local structures
9505b261ecSmrg */
9605b261ecSmrg
9705b261ecSmrgtypedef struct _WMMsgNodeRec {
9835c4bbdfSmrg    winWMMessageRec msg;
9935c4bbdfSmrg    struct _WMMsgNodeRec *pNext;
10005b261ecSmrg} WMMsgNodeRec, *WMMsgNodePtr;
10105b261ecSmrg
10205b261ecSmrgtypedef struct _WMMsgQueueRec {
10335c4bbdfSmrg    struct _WMMsgNodeRec *pHead;
10435c4bbdfSmrg    struct _WMMsgNodeRec *pTail;
10535c4bbdfSmrg    pthread_mutex_t pmMutex;
10635c4bbdfSmrg    pthread_cond_t pcNotEmpty;
10705b261ecSmrg} WMMsgQueueRec, *WMMsgQueuePtr;
10805b261ecSmrg
10905b261ecSmrgtypedef struct _WMInfo {
1101b5d61b8Smrg    xcb_connection_t *conn;
11135c4bbdfSmrg    WMMsgQueueRec wmMsgQueue;
1121b5d61b8Smrg    xcb_atom_t atmWmProtos;
1131b5d61b8Smrg    xcb_atom_t atmWmDelete;
1141b5d61b8Smrg    xcb_atom_t atmWmTakeFocus;
1151b5d61b8Smrg    xcb_atom_t atmPrivMap;
1161b5d61b8Smrg    xcb_atom_t atmUtf8String;
1171b5d61b8Smrg    xcb_atom_t atmNetWmName;
1181b5d61b8Smrg    xcb_ewmh_connection_t ewmh;
11905b261ecSmrg} WMInfoRec, *WMInfoPtr;
12005b261ecSmrg
12105b261ecSmrgtypedef struct _WMProcArgRec {
12235c4bbdfSmrg    DWORD dwScreen;
12335c4bbdfSmrg    WMInfoPtr pWMInfo;
12435c4bbdfSmrg    pthread_mutex_t *ppmServerStarted;
12505b261ecSmrg} WMProcArgRec, *WMProcArgPtr;
12605b261ecSmrg
12705b261ecSmrgtypedef struct _XMsgProcArgRec {
1281b5d61b8Smrg    xcb_connection_t *conn;
12935c4bbdfSmrg    DWORD dwScreen;
13035c4bbdfSmrg    WMInfoPtr pWMInfo;
13135c4bbdfSmrg    pthread_mutex_t *ppmServerStarted;
13235c4bbdfSmrg    HWND hwndScreen;
13305b261ecSmrg} XMsgProcArgRec, *XMsgProcArgPtr;
13405b261ecSmrg
13505b261ecSmrg/*
13605b261ecSmrg * Prototypes for local functions
13705b261ecSmrg */
13805b261ecSmrg
13905b261ecSmrgstatic void
14035c4bbdfSmrg PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode);
14105b261ecSmrg
14235c4bbdfSmrgstatic WMMsgNodePtr PopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo);
14305b261ecSmrg
14405b261ecSmrgstatic Bool
14535c4bbdfSmrg InitQueue(WMMsgQueuePtr pQueue);
14605b261ecSmrg
14705b261ecSmrgstatic void
1481b5d61b8Smrg GetWindowName(WMInfoPtr pWMInfo, xcb_window_t iWin, char **ppWindowName);
14905b261ecSmrg
1501b5d61b8Smrgstatic void
1511b5d61b8Smrg SendXMessage(xcb_connection_t *conn, xcb_window_t iWin, xcb_atom_t atmType, long nData);
15205b261ecSmrg
15305b261ecSmrgstatic void
1541b5d61b8Smrg UpdateName(WMInfoPtr pWMInfo, xcb_window_t iWindow);
15505b261ecSmrg
15635c4bbdfSmrgstatic void *winMultiWindowWMProc(void *pArg);
15705b261ecSmrg
15835c4bbdfSmrgstatic void *winMultiWindowXMsgProc(void *pArg);
15905b261ecSmrg
16005b261ecSmrgstatic void
16135c4bbdfSmrg winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg);
16205b261ecSmrg
16305b261ecSmrg#if 0
16405b261ecSmrgstatic void
1651b5d61b8Smrg PreserveWin32Stack(WMInfoPtr pWMInfo, xcb_window_t iWindow, UINT direction);
16605b261ecSmrg#endif
16705b261ecSmrg
16805b261ecSmrgstatic Bool
1691b5d61b8SmrgCheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen);
17005b261ecSmrg
1716747b715Smrgstatic void
1721b5d61b8Smrg winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle);
1736747b715Smrg
1746747b715Smrgvoid
17535c4bbdfSmrg winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
17605b261ecSmrg
17705b261ecSmrg/*
17805b261ecSmrg * Local globals
17905b261ecSmrg */
18005b261ecSmrg
18135c4bbdfSmrgstatic Bool g_shutdown = FALSE;
1821b5d61b8Smrg
1831b5d61b8Smrg/*
1841b5d61b8Smrg * Translate msg id to text, for debug purposes
1851b5d61b8Smrg */
1861b5d61b8Smrg
1871b5d61b8Smrg#if CYGMULTIWINDOW_DEBUG
1881b5d61b8Smrgstatic const char *
1891b5d61b8SmrgMessageName(winWMMessagePtr msg)
1901b5d61b8Smrg{
1911b5d61b8Smrg  switch (msg->msg)
1921b5d61b8Smrg    {
1931b5d61b8Smrg    case WM_WM_MOVE:
1941b5d61b8Smrg      return "WM_WM_MOVE";
1951b5d61b8Smrg      break;
1961b5d61b8Smrg    case WM_WM_SIZE:
1971b5d61b8Smrg      return "WM_WM_SIZE";
1981b5d61b8Smrg      break;
1991b5d61b8Smrg    case WM_WM_RAISE:
2001b5d61b8Smrg      return "WM_WM_RAISE";
2011b5d61b8Smrg      break;
2021b5d61b8Smrg    case WM_WM_LOWER:
2031b5d61b8Smrg      return "WM_WM_LOWER";
2041b5d61b8Smrg      break;
2051b5d61b8Smrg    case WM_WM_UNMAP:
2061b5d61b8Smrg      return "WM_WM_UNMAP";
2071b5d61b8Smrg      break;
2081b5d61b8Smrg    case WM_WM_KILL:
2091b5d61b8Smrg      return "WM_WM_KILL";
2101b5d61b8Smrg      break;
2111b5d61b8Smrg    case WM_WM_ACTIVATE:
2121b5d61b8Smrg      return "WM_WM_ACTIVATE";
2131b5d61b8Smrg      break;
2141b5d61b8Smrg    case WM_WM_NAME_EVENT:
2151b5d61b8Smrg      return "WM_WM_NAME_EVENT";
2161b5d61b8Smrg      break;
2171b5d61b8Smrg    case WM_WM_ICON_EVENT:
2181b5d61b8Smrg      return "WM_WM_ICON_EVENT";
2191b5d61b8Smrg      break;
2201b5d61b8Smrg    case WM_WM_CHANGE_STATE:
2211b5d61b8Smrg      return "WM_WM_CHANGE_STATE";
2221b5d61b8Smrg      break;
2231b5d61b8Smrg    case WM_WM_MAP2:
2241b5d61b8Smrg      return "WM_WM_MAP2";
2251b5d61b8Smrg      break;
2261b5d61b8Smrg    case WM_WM_MAP3:
2271b5d61b8Smrg      return "WM_WM_MAP3";
2281b5d61b8Smrg      break;
2291b5d61b8Smrg    case WM_WM_HINTS_EVENT:
2301b5d61b8Smrg      return "WM_WM_HINTS_EVENT";
2311b5d61b8Smrg      break;
2321b5d61b8Smrg    default:
2331b5d61b8Smrg      return "Unknown Message";
2341b5d61b8Smrg      break;
2351b5d61b8Smrg    }
2361b5d61b8Smrg}
2371b5d61b8Smrg#endif
2381b5d61b8Smrg
23905b261ecSmrg
24005b261ecSmrg/*
24105b261ecSmrg * PushMessage - Push a message onto the queue
24205b261ecSmrg */
24305b261ecSmrg
24405b261ecSmrgstatic void
24535c4bbdfSmrgPushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
24605b261ecSmrg{
24705b261ecSmrg
24835c4bbdfSmrg    /* Lock the queue mutex */
24935c4bbdfSmrg    pthread_mutex_lock(&pQueue->pmMutex);
25005b261ecSmrg
25135c4bbdfSmrg    pNode->pNext = NULL;
25235c4bbdfSmrg
25335c4bbdfSmrg    if (pQueue->pTail != NULL) {
25435c4bbdfSmrg        pQueue->pTail->pNext = pNode;
25505b261ecSmrg    }
25635c4bbdfSmrg    pQueue->pTail = pNode;
25705b261ecSmrg
25835c4bbdfSmrg    if (pQueue->pHead == NULL) {
25935c4bbdfSmrg        pQueue->pHead = pNode;
26035c4bbdfSmrg    }
26105b261ecSmrg
26235c4bbdfSmrg    /* Release the queue mutex */
26335c4bbdfSmrg    pthread_mutex_unlock(&pQueue->pmMutex);
26405b261ecSmrg
26535c4bbdfSmrg    /* Signal that the queue is not empty */
26635c4bbdfSmrg    pthread_cond_signal(&pQueue->pcNotEmpty);
26705b261ecSmrg}
26805b261ecSmrg
26905b261ecSmrg/*
27005b261ecSmrg * PopMessage - Pop a message from the queue
27105b261ecSmrg */
27205b261ecSmrg
27305b261ecSmrgstatic WMMsgNodePtr
27435c4bbdfSmrgPopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo)
27505b261ecSmrg{
27635c4bbdfSmrg    WMMsgNodePtr pNode;
27705b261ecSmrg
27835c4bbdfSmrg    /* Lock the queue mutex */
27935c4bbdfSmrg    pthread_mutex_lock(&pQueue->pmMutex);
28005b261ecSmrg
28135c4bbdfSmrg    /* Wait for --- */
28235c4bbdfSmrg    while (pQueue->pHead == NULL) {
28335c4bbdfSmrg        pthread_cond_wait(&pQueue->pcNotEmpty, &pQueue->pmMutex);
28405b261ecSmrg    }
28535c4bbdfSmrg
28635c4bbdfSmrg    pNode = pQueue->pHead;
28735c4bbdfSmrg    if (pQueue->pHead != NULL) {
28835c4bbdfSmrg        pQueue->pHead = pQueue->pHead->pNext;
28905b261ecSmrg    }
29005b261ecSmrg
29135c4bbdfSmrg    if (pQueue->pTail == pNode) {
29235c4bbdfSmrg        pQueue->pTail = NULL;
29305b261ecSmrg    }
29405b261ecSmrg
29535c4bbdfSmrg    /* Release the queue mutex */
29635c4bbdfSmrg    pthread_mutex_unlock(&pQueue->pmMutex);
29705b261ecSmrg
29835c4bbdfSmrg    return pNode;
29935c4bbdfSmrg}
30005b261ecSmrg
30105b261ecSmrg#if 0
30205b261ecSmrg/*
30335c4bbdfSmrg * HaveMessage -
30405b261ecSmrg */
30505b261ecSmrg
30605b261ecSmrgstatic Bool
3071b5d61b8SmrgHaveMessage(WMMsgQueuePtr pQueue, UINT msg, xcb_window_t iWindow)
30805b261ecSmrg{
30935c4bbdfSmrg    WMMsgNodePtr pNode;
31035c4bbdfSmrg
31135c4bbdfSmrg    for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) {
31235c4bbdfSmrg        if (pNode->msg.msg == msg && pNode->msg.iWindow == iWindow)
31335c4bbdfSmrg            return True;
31405b261ecSmrg    }
31535c4bbdfSmrg
31635c4bbdfSmrg    return False;
31705b261ecSmrg}
31805b261ecSmrg#endif
31905b261ecSmrg
32005b261ecSmrg/*
32105b261ecSmrg * InitQueue - Initialize the Window Manager message queue
32205b261ecSmrg */
32305b261ecSmrg
32405b261ecSmrgstatic
32535c4bbdfSmrg    Bool
32635c4bbdfSmrgInitQueue(WMMsgQueuePtr pQueue)
32705b261ecSmrg{
32835c4bbdfSmrg    /* Check if the pQueue pointer is NULL */
32935c4bbdfSmrg    if (pQueue == NULL) {
33035c4bbdfSmrg        ErrorF("InitQueue - pQueue is NULL.  Exiting.\n");
33135c4bbdfSmrg        return FALSE;
33205b261ecSmrg    }
33305b261ecSmrg
33435c4bbdfSmrg    /* Set the head and tail to NULL */
33535c4bbdfSmrg    pQueue->pHead = NULL;
33635c4bbdfSmrg    pQueue->pTail = NULL;
33705b261ecSmrg
33835c4bbdfSmrg    winDebug("InitQueue - Calling pthread_mutex_init\n");
33905b261ecSmrg
34035c4bbdfSmrg    /* Create synchronization objects */
34135c4bbdfSmrg    pthread_mutex_init(&pQueue->pmMutex, NULL);
34205b261ecSmrg
34335c4bbdfSmrg    winDebug("InitQueue - pthread_mutex_init returned\n");
34435c4bbdfSmrg    winDebug("InitQueue - Calling pthread_cond_init\n");
34505b261ecSmrg
34635c4bbdfSmrg    pthread_cond_init(&pQueue->pcNotEmpty, NULL);
34705b261ecSmrg
34835c4bbdfSmrg    winDebug("InitQueue - pthread_cond_init returned\n");
34905b261ecSmrg
35035c4bbdfSmrg    return TRUE;
35105b261ecSmrg}
35205b261ecSmrg
35335c4bbdfSmrgstatic
35435c4bbdfSmrgchar *
3551b5d61b8SmrgXutf8TextPropertyToString(WMInfoPtr pWMInfo, xcb_icccm_get_text_property_reply_t *xtp)
35635c4bbdfSmrg{
35735c4bbdfSmrg    char *pszReturnData;
35835c4bbdfSmrg
3591b5d61b8Smrg    if ((xtp->encoding == XCB_ATOM_STRING) ||        // Latin1 ISO 8859-1
3601b5d61b8Smrg        (xtp->encoding == pWMInfo->atmUtf8String)) { // UTF-8  ISO 10646
3611b5d61b8Smrg        pszReturnData = strndup(xtp->name, xtp->name_len);
36235c4bbdfSmrg    }
36335c4bbdfSmrg    else {
3641b5d61b8Smrg        // Converting from COMPOUND_TEXT to UTF-8 properly is complex to
3651b5d61b8Smrg        // implement, and not very much use unless you have an old
3661b5d61b8Smrg        // application which isn't UTF-8 aware.
3671b5d61b8Smrg        ErrorF("Xutf8TextPropertyToString: text encoding %d is not implemented\n", xtp->encoding);
3681b5d61b8Smrg        pszReturnData = strdup("");
36935c4bbdfSmrg    }
37035c4bbdfSmrg
37135c4bbdfSmrg    return pszReturnData;
37235c4bbdfSmrg}
37305b261ecSmrg
37405b261ecSmrg/*
37505b261ecSmrg * GetWindowName - Retrieve the title of an X Window
37605b261ecSmrg */
37705b261ecSmrg
37805b261ecSmrgstatic void
3791b5d61b8SmrgGetWindowName(WMInfoPtr pWMInfo, xcb_window_t iWin, char **ppWindowName)
38005b261ecSmrg{
3811b5d61b8Smrg    xcb_connection_t *conn = pWMInfo->conn;
3821b5d61b8Smrg    char *pszWindowName = NULL;
38335c4bbdfSmrg
38405b261ecSmrg#if CYGMULTIWINDOW_DEBUG
38535c4bbdfSmrg    ErrorF("GetWindowName\n");
38605b261ecSmrg#endif
38705b261ecSmrg
3881b5d61b8Smrg    /* Try to get window name from _NET_WM_NAME */
3891b5d61b8Smrg    {
3901b5d61b8Smrg        xcb_get_property_cookie_t cookie;
3911b5d61b8Smrg        xcb_get_property_reply_t *reply;
3921b5d61b8Smrg
3931b5d61b8Smrg        cookie = xcb_get_property(pWMInfo->conn, FALSE, iWin,
3941b5d61b8Smrg                                  pWMInfo->atmNetWmName,
3951b5d61b8Smrg                                  XCB_GET_PROPERTY_TYPE_ANY, 0, INT_MAX);
3961b5d61b8Smrg        reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL);
3971b5d61b8Smrg        if (reply && (reply->type != XCB_NONE)) {
3981b5d61b8Smrg            pszWindowName = strndup(xcb_get_property_value(reply),
3991b5d61b8Smrg                                    xcb_get_property_value_length(reply));
4001b5d61b8Smrg            free(reply);
4011b5d61b8Smrg        }
40205b261ecSmrg    }
40305b261ecSmrg
4041b5d61b8Smrg    /* Otherwise, try to get window name from WM_NAME */
4051b5d61b8Smrg    if (!pszWindowName)
4061b5d61b8Smrg        {
4071b5d61b8Smrg            xcb_get_property_cookie_t cookie;
4081b5d61b8Smrg            xcb_icccm_get_text_property_reply_t reply;
4091b5d61b8Smrg
4101b5d61b8Smrg            cookie = xcb_icccm_get_wm_name(conn, iWin);
4111b5d61b8Smrg            if (!xcb_icccm_get_wm_name_reply(conn, cookie, &reply, NULL)) {
4121b5d61b8Smrg                ErrorF("GetWindowName - xcb_icccm_get_wm_name_reply failed.  No name.\n");
4131b5d61b8Smrg                *ppWindowName = NULL;
4141b5d61b8Smrg                return;
4151b5d61b8Smrg            }
4161b5d61b8Smrg
4171b5d61b8Smrg            pszWindowName = Xutf8TextPropertyToString(pWMInfo, &reply);
4181b5d61b8Smrg            xcb_icccm_get_text_property_reply_wipe(&reply);
4191b5d61b8Smrg        }
4201b5d61b8Smrg
4211b5d61b8Smrg    /* return the window name, unless... */
4221b5d61b8Smrg    *ppWindowName = pszWindowName;
42335c4bbdfSmrg
42435c4bbdfSmrg    if (g_fHostInTitle) {
4251b5d61b8Smrg        xcb_get_property_cookie_t cookie;
4261b5d61b8Smrg        xcb_icccm_get_text_property_reply_t reply;
4271b5d61b8Smrg
42835c4bbdfSmrg        /* Try to get client machine name */
4291b5d61b8Smrg        cookie = xcb_icccm_get_wm_client_machine(conn, iWin);
4301b5d61b8Smrg        if (xcb_icccm_get_wm_client_machine_reply(conn, cookie, &reply, NULL)) {
4311b5d61b8Smrg            char *pszClientMachine;
4321b5d61b8Smrg            char *pszClientHostname;
4331b5d61b8Smrg            char *dot;
4341b5d61b8Smrg            char hostname[HOST_NAME_MAX + 1];
4351b5d61b8Smrg
4361b5d61b8Smrg            pszClientMachine = Xutf8TextPropertyToString(pWMInfo, &reply);
4371b5d61b8Smrg            xcb_icccm_get_text_property_reply_wipe(&reply);
4381b5d61b8Smrg
4391b5d61b8Smrg            /* If client machine name looks like a FQDN, find the hostname */
4401b5d61b8Smrg            pszClientHostname = strdup(pszClientMachine);
4411b5d61b8Smrg            dot = strchr(pszClientHostname, '.');
4421b5d61b8Smrg            if (dot)
4431b5d61b8Smrg                *dot = '\0';
44435c4bbdfSmrg
44535c4bbdfSmrg            /*
4461b5d61b8Smrg               If we have a client machine hostname
4471b5d61b8Smrg               and it's not the local hostname
44835c4bbdfSmrg               and it's not already in the window title...
44935c4bbdfSmrg             */
4501b5d61b8Smrg            if (strlen(pszClientHostname) &&
45135c4bbdfSmrg                !gethostname(hostname, HOST_NAME_MAX + 1) &&
4521b5d61b8Smrg                strcmp(hostname, pszClientHostname) &&
4531b5d61b8Smrg                (strstr(pszWindowName, pszClientHostname) == 0)) {
45435c4bbdfSmrg                /* ... add '@<clientmachine>' to end of window name */
45535c4bbdfSmrg                *ppWindowName =
45635c4bbdfSmrg                    malloc(strlen(pszWindowName) +
45735c4bbdfSmrg                           strlen(pszClientMachine) + 2);
45835c4bbdfSmrg                strcpy(*ppWindowName, pszWindowName);
45935c4bbdfSmrg                strcat(*ppWindowName, "@");
46035c4bbdfSmrg                strcat(*ppWindowName, pszClientMachine);
46135c4bbdfSmrg
46235c4bbdfSmrg                free(pszWindowName);
46335c4bbdfSmrg            }
4641b5d61b8Smrg
4651b5d61b8Smrg            free(pszClientMachine);
4661b5d61b8Smrg            free(pszClientHostname);
46735c4bbdfSmrg        }
46835c4bbdfSmrg    }
46905b261ecSmrg}
47005b261ecSmrg
47135c4bbdfSmrg/*
47235c4bbdfSmrg * Does the client support the specified WM_PROTOCOLS protocol?
47335c4bbdfSmrg */
47435c4bbdfSmrg
47535c4bbdfSmrgstatic Bool
4761b5d61b8SmrgIsWmProtocolAvailable(WMInfoPtr pWMInfo, xcb_window_t iWindow, xcb_atom_t atmProtocol)
47735c4bbdfSmrg{
4781b5d61b8Smrg  int i, found = 0;
4791b5d61b8Smrg  xcb_get_property_cookie_t cookie;
4801b5d61b8Smrg  xcb_icccm_get_wm_protocols_reply_t reply;
4811b5d61b8Smrg  xcb_connection_t *conn = pWMInfo->conn;
4821b5d61b8Smrg
4831b5d61b8Smrg  cookie = xcb_icccm_get_wm_protocols(conn, iWindow, pWMInfo->ewmh.WM_PROTOCOLS);
4841b5d61b8Smrg  if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &reply, NULL)) {
4851b5d61b8Smrg    for (i = 0; i < reply.atoms_len; ++i)
4861b5d61b8Smrg      if (reply.atoms[i] == atmProtocol) {
4871b5d61b8Smrg              ++found;
4881b5d61b8Smrg              break;
4891b5d61b8Smrg      }
4901b5d61b8Smrg    xcb_icccm_get_wm_protocols_reply_wipe(&reply);
49135c4bbdfSmrg  }
49235c4bbdfSmrg
49335c4bbdfSmrg  return found > 0;
49435c4bbdfSmrg}
49505b261ecSmrg
49605b261ecSmrg/*
49705b261ecSmrg * Send a message to the X server from the WM thread
49805b261ecSmrg */
49905b261ecSmrg
5001b5d61b8Smrgstatic void
5011b5d61b8SmrgSendXMessage(xcb_connection_t *conn, xcb_window_t iWin, xcb_atom_t atmType, long nData)
50205b261ecSmrg{
5031b5d61b8Smrg    xcb_client_message_event_t e;
50435c4bbdfSmrg
50535c4bbdfSmrg    /* Prepare the X event structure */
5061b5d61b8Smrg    memset(&e, 0, sizeof(e));
5071b5d61b8Smrg    e.response_type = XCB_CLIENT_MESSAGE;
5081b5d61b8Smrg    e.window = iWin;
5091b5d61b8Smrg    e.type = atmType;
5101b5d61b8Smrg    e.format = 32;
5111b5d61b8Smrg    e.data.data32[0] = nData;
5121b5d61b8Smrg    e.data.data32[1] = XCB_CURRENT_TIME;
51335c4bbdfSmrg
51435c4bbdfSmrg    /* Send the event to X */
5151b5d61b8Smrg    xcb_send_event(conn, FALSE, iWin, XCB_EVENT_MASK_NO_EVENT, (const char *)&e);
51605b261ecSmrg}
51705b261ecSmrg
51835c4bbdfSmrg/*
51935c4bbdfSmrg * See if we can get the stored HWND for this window...
52035c4bbdfSmrg */
52135c4bbdfSmrgstatic HWND
5221b5d61b8SmrggetHwnd(WMInfoPtr pWMInfo, xcb_window_t iWindow)
52335c4bbdfSmrg{
5241b5d61b8Smrg    HWND hWnd = NULL;
5251b5d61b8Smrg    xcb_get_property_cookie_t cookie;
5261b5d61b8Smrg    xcb_get_property_reply_t *reply;
5271b5d61b8Smrg
5281b5d61b8Smrg    cookie = xcb_get_property(pWMInfo->conn, FALSE, iWindow, pWMInfo->atmPrivMap,
5291b5d61b8Smrg                              XCB_ATOM_INTEGER, 0L, sizeof(HWND)/4L);
5301b5d61b8Smrg    reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL);
5311b5d61b8Smrg
5321b5d61b8Smrg    if (reply) {
5331b5d61b8Smrg        int length = xcb_get_property_value_length(reply);
5341b5d61b8Smrg        HWND *value = xcb_get_property_value(reply);
5351b5d61b8Smrg
5361b5d61b8Smrg        if (value && (length == sizeof(HWND))) {
5371b5d61b8Smrg            hWnd = *value;
53835c4bbdfSmrg        }
5391b5d61b8Smrg        free(reply);
54035c4bbdfSmrg    }
54135c4bbdfSmrg
54235c4bbdfSmrg    /* Some sanity checks */
54335c4bbdfSmrg    if (!hWnd)
54435c4bbdfSmrg        return NULL;
54535c4bbdfSmrg    if (!IsWindow(hWnd))
54635c4bbdfSmrg        return NULL;
54735c4bbdfSmrg
54835c4bbdfSmrg    return hWnd;
54935c4bbdfSmrg}
55005b261ecSmrg
5511b5d61b8Smrg/*
5521b5d61b8Smrg * Helper function to check for override-redirect
5531b5d61b8Smrg */
5541b5d61b8Smrgstatic Bool
5551b5d61b8SmrgIsOverrideRedirect(xcb_connection_t *conn, xcb_window_t iWin)
5561b5d61b8Smrg{
5571b5d61b8Smrg    Bool result = FALSE;
5581b5d61b8Smrg    xcb_get_window_attributes_reply_t *reply;
5591b5d61b8Smrg    xcb_get_window_attributes_cookie_t cookie;
5601b5d61b8Smrg
5611b5d61b8Smrg    cookie = xcb_get_window_attributes(conn, iWin);
5621b5d61b8Smrg    reply = xcb_get_window_attributes_reply(conn, cookie, NULL);
5631b5d61b8Smrg    if (reply) {
5641b5d61b8Smrg        result = (reply->override_redirect != 0);
5651b5d61b8Smrg        free(reply);
5661b5d61b8Smrg    }
5671b5d61b8Smrg    else {
5681b5d61b8Smrg        ErrorF("IsOverrideRedirect: Failed to get window attributes\n");
5691b5d61b8Smrg    }
5701b5d61b8Smrg
5711b5d61b8Smrg    return result;
5721b5d61b8Smrg}
5731b5d61b8Smrg
5741b5d61b8Smrg/*
5751b5d61b8Smrg * Helper function to get class and window names
5761b5d61b8Smrg*/
5771b5d61b8Smrgstatic void
5781b5d61b8SmrgGetClassNames(WMInfoPtr pWMInfo, xcb_window_t iWindow, char **res_name,
5791b5d61b8Smrg              char **res_class, char **window_name)
5801b5d61b8Smrg{
5811b5d61b8Smrg    xcb_get_property_cookie_t cookie1;
5821b5d61b8Smrg    xcb_icccm_get_wm_class_reply_t reply1;
5831b5d61b8Smrg    xcb_get_property_cookie_t cookie2;
5841b5d61b8Smrg    xcb_icccm_get_text_property_reply_t reply2;
5851b5d61b8Smrg
5861b5d61b8Smrg    cookie1 = xcb_icccm_get_wm_class(pWMInfo->conn, iWindow);
5871b5d61b8Smrg    if (xcb_icccm_get_wm_class_reply(pWMInfo->conn, cookie1, &reply1,
5881b5d61b8Smrg                                     NULL)) {
5891b5d61b8Smrg        *res_name = strdup(reply1.instance_name);
5901b5d61b8Smrg        *res_class = strdup(reply1.class_name);
5911b5d61b8Smrg        xcb_icccm_get_wm_class_reply_wipe(&reply1);
5921b5d61b8Smrg    }
5931b5d61b8Smrg    else {
5941b5d61b8Smrg        *res_name = strdup("");
5951b5d61b8Smrg        *res_class = strdup("");
5961b5d61b8Smrg    }
5971b5d61b8Smrg
5981b5d61b8Smrg    cookie2 = xcb_icccm_get_wm_name(pWMInfo->conn, iWindow);
5991b5d61b8Smrg    if (xcb_icccm_get_wm_name_reply(pWMInfo->conn, cookie2, &reply2, NULL)) {
6001b5d61b8Smrg        *window_name = strndup(reply2.name, reply2.name_len);
6011b5d61b8Smrg        xcb_icccm_get_text_property_reply_wipe(&reply2);
6021b5d61b8Smrg    }
6031b5d61b8Smrg    else {
6041b5d61b8Smrg        *window_name = strdup("");
6051b5d61b8Smrg    }
6061b5d61b8Smrg}
6071b5d61b8Smrg
60805b261ecSmrg/*
60905b261ecSmrg * Updates the name of a HWND according to its X WM_NAME property
61005b261ecSmrg */
61105b261ecSmrg
61205b261ecSmrgstatic void
6131b5d61b8SmrgUpdateName(WMInfoPtr pWMInfo, xcb_window_t iWindow)
61405b261ecSmrg{
61535c4bbdfSmrg    HWND hWnd;
61635c4bbdfSmrg
61735c4bbdfSmrg    hWnd = getHwnd(pWMInfo, iWindow);
61835c4bbdfSmrg    if (!hWnd)
61935c4bbdfSmrg        return;
62035c4bbdfSmrg
62135c4bbdfSmrg    /* If window isn't override-redirect */
6221b5d61b8Smrg    if (!IsOverrideRedirect(pWMInfo->conn, iWindow)) {
62335c4bbdfSmrg        char *pszWindowName;
62435c4bbdfSmrg
62535c4bbdfSmrg        /* Get the X windows window name */
6261b5d61b8Smrg        GetWindowName(pWMInfo, iWindow, &pszWindowName);
62735c4bbdfSmrg
62835c4bbdfSmrg        if (pszWindowName) {
62935c4bbdfSmrg            /* Convert from UTF-8 to wide char */
63035c4bbdfSmrg            int iLen =
63135c4bbdfSmrg                MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, NULL, 0);
63235c4bbdfSmrg            wchar_t *pwszWideWindowName =
63335c4bbdfSmrg                malloc(sizeof(wchar_t)*(iLen + 1));
63435c4bbdfSmrg            MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1,
63535c4bbdfSmrg                                pwszWideWindowName, iLen);
63635c4bbdfSmrg
63735c4bbdfSmrg            /* Set the Windows window name */
63835c4bbdfSmrg            SetWindowTextW(hWnd, pwszWideWindowName);
63935c4bbdfSmrg
64035c4bbdfSmrg            free(pwszWideWindowName);
64135c4bbdfSmrg            free(pszWindowName);
64235c4bbdfSmrg        }
64305b261ecSmrg    }
64435c4bbdfSmrg}
64535c4bbdfSmrg
64635c4bbdfSmrg/*
64735c4bbdfSmrg * Updates the icon of a HWND according to its X icon properties
64835c4bbdfSmrg */
64935c4bbdfSmrg
65035c4bbdfSmrgstatic void
6511b5d61b8SmrgUpdateIcon(WMInfoPtr pWMInfo, xcb_window_t iWindow)
65235c4bbdfSmrg{
65335c4bbdfSmrg    HWND hWnd;
65435c4bbdfSmrg    HICON hIconNew = NULL;
65535c4bbdfSmrg
65635c4bbdfSmrg    hWnd = getHwnd(pWMInfo, iWindow);
65735c4bbdfSmrg    if (!hWnd)
65835c4bbdfSmrg        return;
65935c4bbdfSmrg
66035c4bbdfSmrg    /* If window isn't override-redirect */
6611b5d61b8Smrg    if (!IsOverrideRedirect(pWMInfo->conn, iWindow)) {
66235c4bbdfSmrg        char *window_name = 0;
6631b5d61b8Smrg        char *res_name = 0;
6641b5d61b8Smrg        char *res_class = 0;
66535c4bbdfSmrg
6661b5d61b8Smrg        GetClassNames(pWMInfo, iWindow, &res_name, &res_class, &window_name);
66735c4bbdfSmrg
6681b5d61b8Smrg        hIconNew = winOverrideIcon(res_name, res_class, window_name);
66935c4bbdfSmrg
6701b5d61b8Smrg        free(res_name);
6711b5d61b8Smrg        free(res_class);
6721b5d61b8Smrg        free(window_name);
6731b5d61b8Smrg        winUpdateIcon(hWnd, pWMInfo->conn, iWindow, hIconNew);
67405b261ecSmrg    }
67505b261ecSmrg}
67605b261ecSmrg
67735c4bbdfSmrg/*
67835c4bbdfSmrg * Updates the style of a HWND according to its X style properties
67935c4bbdfSmrg */
68035c4bbdfSmrg
68135c4bbdfSmrgstatic void
6821b5d61b8SmrgUpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow)
68335c4bbdfSmrg{
68435c4bbdfSmrg    HWND hWnd;
68535c4bbdfSmrg    HWND zstyle = HWND_NOTOPMOST;
68635c4bbdfSmrg    UINT flags;
68735c4bbdfSmrg
68835c4bbdfSmrg    hWnd = getHwnd(pWMInfo, iWindow);
68935c4bbdfSmrg    if (!hWnd)
69035c4bbdfSmrg        return;
69135c4bbdfSmrg
69235c4bbdfSmrg    /* Determine the Window style, which determines borders and clipping region... */
6931b5d61b8Smrg    winApplyHints(pWMInfo, iWindow, hWnd, &zstyle);
69435c4bbdfSmrg    winUpdateWindowPosition(hWnd, &zstyle);
69535c4bbdfSmrg
69635c4bbdfSmrg    /* Apply the updated window style, without changing it's show or activation state */
69735c4bbdfSmrg    flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
69835c4bbdfSmrg    if (zstyle == HWND_NOTOPMOST)
69935c4bbdfSmrg        flags |= SWP_NOZORDER | SWP_NOOWNERZORDER;
70035c4bbdfSmrg    SetWindowPos(hWnd, NULL, 0, 0, 0, 0, flags);
70135c4bbdfSmrg
70235c4bbdfSmrg    /*
70335c4bbdfSmrg       Use the WS_EX_TOOLWINDOW style to remove window from Alt-Tab window switcher
70435c4bbdfSmrg
70535c4bbdfSmrg       According to MSDN, this is supposed to remove the window from the taskbar as well,
70635c4bbdfSmrg       if we SW_HIDE before changing the style followed by SW_SHOW afterwards.
70735c4bbdfSmrg
70835c4bbdfSmrg       But that doesn't seem to work reliably, and causes the window to flicker, so use
70935c4bbdfSmrg       the iTaskbarList interface to tell the taskbar to show or hide this window.
71035c4bbdfSmrg     */
71135c4bbdfSmrg    winShowWindowOnTaskbar(hWnd,
71235c4bbdfSmrg                           (GetWindowLongPtr(hWnd, GWL_EXSTYLE) &
71335c4bbdfSmrg                            WS_EX_APPWINDOW) ? TRUE : FALSE);
71435c4bbdfSmrg}
71505b261ecSmrg
7161b5d61b8Smrg/*
7171b5d61b8Smrg * Updates the state of a HWND
7181b5d61b8Smrg * (only minimization supported at the moment)
7191b5d61b8Smrg */
7201b5d61b8Smrg
7211b5d61b8Smrgstatic void
7221b5d61b8SmrgUpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow)
7231b5d61b8Smrg{
7241b5d61b8Smrg    HWND hWnd;
7251b5d61b8Smrg
7261b5d61b8Smrg    winDebug("UpdateState: iWindow 0x%08x\n", (int)iWindow);
7271b5d61b8Smrg
7281b5d61b8Smrg    hWnd = getHwnd(pWMInfo, iWindow);
7291b5d61b8Smrg    if (!hWnd)
7301b5d61b8Smrg        return;
7311b5d61b8Smrg
7321b5d61b8Smrg    ShowWindow(hWnd, SW_MINIMIZE);
7331b5d61b8Smrg}
7341b5d61b8Smrg
73505b261ecSmrg#if 0
73605b261ecSmrg/*
73705b261ecSmrg * Fix up any differences between the X11 and Win32 window stacks
73805b261ecSmrg * starting at the window passed in
73905b261ecSmrg */
74005b261ecSmrgstatic void
7411b5d61b8SmrgPreserveWin32Stack(WMInfoPtr pWMInfo, xcb_window_t iWindow, UINT direction)
74205b261ecSmrg{
74335c4bbdfSmrg    HWND hWnd;
74435c4bbdfSmrg    DWORD myWinProcID, winProcID;
7451b5d61b8Smrg    xcb_window_t xWindow;
74635c4bbdfSmrg    WINDOWPLACEMENT wndPlace;
74735c4bbdfSmrg
74835c4bbdfSmrg    hWnd = getHwnd(pWMInfo, iWindow);
74935c4bbdfSmrg    if (!hWnd)
75035c4bbdfSmrg        return;
75135c4bbdfSmrg
75235c4bbdfSmrg    GetWindowThreadProcessId(hWnd, &myWinProcID);
75305b261ecSmrg    hWnd = GetNextWindow(hWnd, direction);
75405b261ecSmrg
75535c4bbdfSmrg    while (hWnd) {
75635c4bbdfSmrg        GetWindowThreadProcessId(hWnd, &winProcID);
75735c4bbdfSmrg        if (winProcID == myWinProcID) {
75835c4bbdfSmrg            wndPlace.length = sizeof(WINDOWPLACEMENT);
75935c4bbdfSmrg            GetWindowPlacement(hWnd, &wndPlace);
76035c4bbdfSmrg            if (!(wndPlace.showCmd == SW_HIDE ||
76135c4bbdfSmrg                  wndPlace.showCmd == SW_MINIMIZE)) {
76235c4bbdfSmrg                xWindow = (Window) GetProp(hWnd, WIN_WID_PROP);
76335c4bbdfSmrg                if (xWindow) {
76435c4bbdfSmrg                    if (direction == GW_HWNDPREV)
76535c4bbdfSmrg                        XRaiseWindow(pWMInfo->pDisplay, xWindow);
76635c4bbdfSmrg                    else
76735c4bbdfSmrg                        XLowerWindow(pWMInfo->pDisplay, xWindow);
76835c4bbdfSmrg                }
76935c4bbdfSmrg            }
77035c4bbdfSmrg        }
77135c4bbdfSmrg        hWnd = GetNextWindow(hWnd, direction);
77235c4bbdfSmrg    }
77335c4bbdfSmrg}
77435c4bbdfSmrg#endif                          /* PreserveWin32Stack */
77505b261ecSmrg
77605b261ecSmrg/*
77705b261ecSmrg * winMultiWindowWMProc
77805b261ecSmrg */
77905b261ecSmrg
78005b261ecSmrgstatic void *
78135c4bbdfSmrgwinMultiWindowWMProc(void *pArg)
78205b261ecSmrg{
78335c4bbdfSmrg    WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
78435c4bbdfSmrg    WMInfoPtr pWMInfo = pProcArg->pWMInfo;
78535c4bbdfSmrg
78635c4bbdfSmrg    /* Initialize the Window Manager */
78735c4bbdfSmrg    winInitMultiWindowWM(pWMInfo, pProcArg);
78835c4bbdfSmrg
78905b261ecSmrg#if CYGMULTIWINDOW_DEBUG
79035c4bbdfSmrg    ErrorF("winMultiWindowWMProc ()\n");
79105b261ecSmrg#endif
79205b261ecSmrg
79335c4bbdfSmrg    /* Loop until we explicitly break out */
79435c4bbdfSmrg    for (;;) {
79535c4bbdfSmrg        WMMsgNodePtr pNode;
79635c4bbdfSmrg
79735c4bbdfSmrg        /* Pop a message off of our queue */
79835c4bbdfSmrg        pNode = PopMessage(&pWMInfo->wmMsgQueue, pWMInfo);
79935c4bbdfSmrg        if (pNode == NULL) {
80035c4bbdfSmrg            /* Bail if PopMessage returns without a message */
80135c4bbdfSmrg            /* NOTE: Remember that PopMessage is a blocking function. */
80235c4bbdfSmrg            ErrorF("winMultiWindowWMProc - Queue is Empty?  Exiting.\n");
80335c4bbdfSmrg            pthread_exit(NULL);
80435c4bbdfSmrg        }
80505b261ecSmrg
80605b261ecSmrg#if CYGMULTIWINDOW_DEBUG
8071b5d61b8Smrg        ErrorF("winMultiWindowWMProc - MSG: %s (%d) ID: %d\n",
8081b5d61b8Smrg               MessageName(&(pNode->msg)), (int)pNode->msg.msg, (int)pNode->msg.dwID);
80905b261ecSmrg#endif
81005b261ecSmrg
81135c4bbdfSmrg        /* Branch on the message type */
81235c4bbdfSmrg        switch (pNode->msg.msg) {
81305b261ecSmrg#if 0
81435c4bbdfSmrg        case WM_WM_MOVE:
81535c4bbdfSmrg            break;
81605b261ecSmrg
81735c4bbdfSmrg        case WM_WM_SIZE:
81835c4bbdfSmrg            break;
81905b261ecSmrg#endif
82005b261ecSmrg
82135c4bbdfSmrg        case WM_WM_RAISE:
82235c4bbdfSmrg            /* Raise the window */
8231b5d61b8Smrg            {
8241b5d61b8Smrg                const static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
8251b5d61b8Smrg                xcb_configure_window(pWMInfo->conn, pNode->msg.iWindow,
8261b5d61b8Smrg                                     XCB_CONFIG_WINDOW_STACK_MODE, values);
8271b5d61b8Smrg            }
8281b5d61b8Smrg
82905b261ecSmrg#if 0
83035c4bbdfSmrg            PreserveWin32Stack(pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
83105b261ecSmrg#endif
83235c4bbdfSmrg            break;
83305b261ecSmrg
83435c4bbdfSmrg        case WM_WM_LOWER:
83535c4bbdfSmrg            /* Lower the window */
8361b5d61b8Smrg            {
8371b5d61b8Smrg                const static uint32_t values[] = { XCB_STACK_MODE_BELOW };
8381b5d61b8Smrg                xcb_configure_window(pWMInfo->conn, pNode->msg.iWindow,
8391b5d61b8Smrg                                     XCB_CONFIG_WINDOW_STACK_MODE, values);
8401b5d61b8Smrg            }
84135c4bbdfSmrg            break;
84205b261ecSmrg
8431b5d61b8Smrg        case WM_WM_MAP2:
84435c4bbdfSmrg            /* Put a note as to the HWND associated with this Window */
8451b5d61b8Smrg            xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
8461b5d61b8Smrg                                pNode->msg.iWindow, pWMInfo->atmPrivMap,
8471b5d61b8Smrg                                XCB_ATOM_INTEGER, 32,
8481b5d61b8Smrg                                sizeof(HWND)/4, &(pNode->msg.hwndWindow));
84935c4bbdfSmrg
85035c4bbdfSmrg            break;
85135c4bbdfSmrg
85235c4bbdfSmrg        case WM_WM_MAP3:
85335c4bbdfSmrg            /* Put a note as to the HWND associated with this Window */
8541b5d61b8Smrg            xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
8551b5d61b8Smrg                                pNode->msg.iWindow, pWMInfo->atmPrivMap,
8561b5d61b8Smrg                                XCB_ATOM_INTEGER, 32,
8571b5d61b8Smrg                                sizeof(HWND)/4, &(pNode->msg.hwndWindow));
8581b5d61b8Smrg
85935c4bbdfSmrg            UpdateName(pWMInfo, pNode->msg.iWindow);
86035c4bbdfSmrg            UpdateIcon(pWMInfo, pNode->msg.iWindow);
86135c4bbdfSmrg            UpdateStyle(pWMInfo, pNode->msg.iWindow);
86235c4bbdfSmrg
86335c4bbdfSmrg
86435c4bbdfSmrg            /* Reshape */
86535c4bbdfSmrg            {
86635c4bbdfSmrg                WindowPtr pWin =
86735c4bbdfSmrg                    GetProp(pNode->msg.hwndWindow, WIN_WINDOW_PROP);
86835c4bbdfSmrg                if (pWin) {
86935c4bbdfSmrg                    winReshapeMultiWindow(pWin);
87035c4bbdfSmrg                    winUpdateRgnMultiWindow(pWin);
87135c4bbdfSmrg                }
87235c4bbdfSmrg            }
87335c4bbdfSmrg
87435c4bbdfSmrg            break;
87535c4bbdfSmrg
87635c4bbdfSmrg        case WM_WM_UNMAP:
87705b261ecSmrg
87835c4bbdfSmrg            /* Unmap the window */
8791b5d61b8Smrg            xcb_unmap_window(pWMInfo->conn, pNode->msg.iWindow);
88035c4bbdfSmrg            break;
88135c4bbdfSmrg
88235c4bbdfSmrg        case WM_WM_KILL:
88335c4bbdfSmrg            {
88435c4bbdfSmrg                /* --- */
8851b5d61b8Smrg                if (IsWmProtocolAvailable(pWMInfo,
88635c4bbdfSmrg                                          pNode->msg.iWindow,
88735c4bbdfSmrg                                          pWMInfo->atmWmDelete))
8881b5d61b8Smrg                    SendXMessage(pWMInfo->conn,
88935c4bbdfSmrg                                 pNode->msg.iWindow,
89035c4bbdfSmrg                                 pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
89135c4bbdfSmrg                else
8921b5d61b8Smrg                    xcb_kill_client(pWMInfo->conn, pNode->msg.iWindow);
89335c4bbdfSmrg            }
89435c4bbdfSmrg            break;
89535c4bbdfSmrg
89635c4bbdfSmrg        case WM_WM_ACTIVATE:
89735c4bbdfSmrg            /* Set the input focus */
89835c4bbdfSmrg
89935c4bbdfSmrg            /*
90035c4bbdfSmrg               ICCCM 4.1.7 is pretty opaque, but it appears that the rules are
90135c4bbdfSmrg               actually quite simple:
90235c4bbdfSmrg               -- the WM_HINTS input field determines whether the WM should call
90335c4bbdfSmrg               XSetInputFocus()
90435c4bbdfSmrg               -- independently, the WM_TAKE_FOCUS protocol determines whether
90535c4bbdfSmrg               the WM should send a WM_TAKE_FOCUS ClientMessage.
90635c4bbdfSmrg            */
90735c4bbdfSmrg            {
90835c4bbdfSmrg              Bool neverFocus = FALSE;
9091b5d61b8Smrg              xcb_get_property_cookie_t cookie;
9101b5d61b8Smrg              xcb_icccm_wm_hints_t hints;
9111b5d61b8Smrg
9121b5d61b8Smrg              cookie = xcb_icccm_get_wm_hints(pWMInfo->conn, pNode->msg.iWindow);
9131b5d61b8Smrg              if (xcb_icccm_get_wm_hints_reply(pWMInfo->conn, cookie, &hints,
9141b5d61b8Smrg                                               NULL)) {
9151b5d61b8Smrg                if (hints.flags & XCB_ICCCM_WM_HINT_INPUT)
9161b5d61b8Smrg                  neverFocus = !hints.input;
91735c4bbdfSmrg              }
91835c4bbdfSmrg
91935c4bbdfSmrg              if (!neverFocus)
9201b5d61b8Smrg                xcb_set_input_focus(pWMInfo->conn, XCB_INPUT_FOCUS_POINTER_ROOT,
9211b5d61b8Smrg                                    pNode->msg.iWindow, XCB_CURRENT_TIME);
92235c4bbdfSmrg
9231b5d61b8Smrg              if (IsWmProtocolAvailable(pWMInfo,
92435c4bbdfSmrg                                        pNode->msg.iWindow,
92535c4bbdfSmrg                                        pWMInfo->atmWmTakeFocus))
9261b5d61b8Smrg                SendXMessage(pWMInfo->conn,
92735c4bbdfSmrg                             pNode->msg.iWindow,
92835c4bbdfSmrg                             pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus);
92935c4bbdfSmrg
93035c4bbdfSmrg            }
93135c4bbdfSmrg            break;
93235c4bbdfSmrg
93335c4bbdfSmrg        case WM_WM_NAME_EVENT:
93435c4bbdfSmrg            UpdateName(pWMInfo, pNode->msg.iWindow);
93535c4bbdfSmrg            break;
93635c4bbdfSmrg
93735c4bbdfSmrg        case WM_WM_ICON_EVENT:
93835c4bbdfSmrg            UpdateIcon(pWMInfo, pNode->msg.iWindow);
93935c4bbdfSmrg            break;
94035c4bbdfSmrg
94135c4bbdfSmrg        case WM_WM_HINTS_EVENT:
94235c4bbdfSmrg            {
94335c4bbdfSmrg            /* Don't do anything if this is an override-redirect window */
9441b5d61b8Smrg            if (IsOverrideRedirect(pWMInfo->conn, pNode->msg.iWindow))
94535c4bbdfSmrg              break;
94635c4bbdfSmrg
94735c4bbdfSmrg            UpdateStyle(pWMInfo, pNode->msg.iWindow);
94835c4bbdfSmrg            }
94935c4bbdfSmrg            break;
95035c4bbdfSmrg
95135c4bbdfSmrg        case WM_WM_CHANGE_STATE:
9521b5d61b8Smrg            UpdateState(pWMInfo, pNode->msg.iWindow);
95335c4bbdfSmrg            break;
95435c4bbdfSmrg
95535c4bbdfSmrg        default:
95635c4bbdfSmrg            ErrorF("winMultiWindowWMProc - Unknown Message.  Exiting.\n");
95735c4bbdfSmrg            pthread_exit(NULL);
95835c4bbdfSmrg            break;
95935c4bbdfSmrg        }
96035c4bbdfSmrg
96135c4bbdfSmrg        /* Free the retrieved message */
96235c4bbdfSmrg        free(pNode);
96335c4bbdfSmrg
96435c4bbdfSmrg        /* Flush any pending events on our display */
9651b5d61b8Smrg        xcb_flush(pWMInfo->conn);
9661b5d61b8Smrg
9671b5d61b8Smrg        /* This is just laziness rather than making sure we used _checked everywhere */
9681b5d61b8Smrg        {
9691b5d61b8Smrg            xcb_generic_event_t *event = xcb_poll_for_event(pWMInfo->conn);
9701b5d61b8Smrg            if (event) {
9711b5d61b8Smrg                if ((event->response_type & ~0x80) == 0) {
9721b5d61b8Smrg                    xcb_generic_error_t *err = (xcb_generic_error_t *)event;
9731b5d61b8Smrg                    ErrorF("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, "
9741b5d61b8Smrg                           "Major opcode: %i, Minor opcode: %i\n",
9751b5d61b8Smrg                           err->error_code, err->resource_id,
9761b5d61b8Smrg                           err->major_code, err->minor_code);
9771b5d61b8Smrg                }
9781b5d61b8Smrg            }
9791b5d61b8Smrg        }
9801b5d61b8Smrg
9811b5d61b8Smrg        /* I/O errors etc. */
9821b5d61b8Smrg        {
9831b5d61b8Smrg            int e = xcb_connection_has_error(pWMInfo->conn);
9841b5d61b8Smrg            if (e) {
9851b5d61b8Smrg                ErrorF("winMultiWindowWMProc - Fatal error %d on xcb connection\n", e);
9861b5d61b8Smrg                break;
9871b5d61b8Smrg            }
9881b5d61b8Smrg        }
98905b261ecSmrg    }
99005b261ecSmrg
99135c4bbdfSmrg    /* Free the condition variable */
99235c4bbdfSmrg    pthread_cond_destroy(&pWMInfo->wmMsgQueue.pcNotEmpty);
99335c4bbdfSmrg
99435c4bbdfSmrg    /* Free the mutex variable */
99535c4bbdfSmrg    pthread_mutex_destroy(&pWMInfo->wmMsgQueue.pmMutex);
99635c4bbdfSmrg
99735c4bbdfSmrg    /* Free the passed-in argument */
99835c4bbdfSmrg    free(pProcArg);
99935c4bbdfSmrg
100005b261ecSmrg#if CYGMULTIWINDOW_DEBUG
100135c4bbdfSmrg    ErrorF("-winMultiWindowWMProc ()\n");
100205b261ecSmrg#endif
100335c4bbdfSmrg    return NULL;
100405b261ecSmrg}
100505b261ecSmrg
10061b5d61b8Smrgstatic xcb_atom_t
10071b5d61b8Smrgintern_atom(xcb_connection_t *conn, const char *atomName)
10081b5d61b8Smrg{
10091b5d61b8Smrg  xcb_intern_atom_reply_t *atom_reply;
10101b5d61b8Smrg  xcb_intern_atom_cookie_t atom_cookie;
10111b5d61b8Smrg  xcb_atom_t atom = XCB_ATOM_NONE;
10121b5d61b8Smrg
10131b5d61b8Smrg  atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
10141b5d61b8Smrg  atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
10151b5d61b8Smrg  if (atom_reply) {
10161b5d61b8Smrg    atom = atom_reply->atom;
10171b5d61b8Smrg    free(atom_reply);
10181b5d61b8Smrg  }
10191b5d61b8Smrg  return atom;
10201b5d61b8Smrg}
10211b5d61b8Smrg
102205b261ecSmrg/*
102305b261ecSmrg * X message procedure
102405b261ecSmrg */
102505b261ecSmrg
102605b261ecSmrgstatic void *
102735c4bbdfSmrgwinMultiWindowXMsgProc(void *pArg)
102805b261ecSmrg{
102935c4bbdfSmrg    winWMMessageRec msg;
103035c4bbdfSmrg    XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg;
103135c4bbdfSmrg    char pszDisplay[512];
103235c4bbdfSmrg    int iRetries;
10331b5d61b8Smrg    xcb_atom_t atmWmName;
10341b5d61b8Smrg    xcb_atom_t atmNetWmName;
10351b5d61b8Smrg    xcb_atom_t atmWmHints;
10361b5d61b8Smrg    xcb_atom_t atmWmChange;
10371b5d61b8Smrg    xcb_atom_t atmNetWmIcon;
10381b5d61b8Smrg    xcb_atom_t atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints;
103935c4bbdfSmrg    int iReturn;
10401b5d61b8Smrg    xcb_auth_info_t *auth_info;
104135c4bbdfSmrg
104235c4bbdfSmrg    winDebug("winMultiWindowXMsgProc - Hello\n");
104335c4bbdfSmrg
104435c4bbdfSmrg    /* Check that argument pointer is not invalid */
104535c4bbdfSmrg    if (pProcArg == NULL) {
104635c4bbdfSmrg        ErrorF("winMultiWindowXMsgProc - pProcArg is NULL.  Exiting.\n");
104735c4bbdfSmrg        pthread_exit(NULL);
104805b261ecSmrg    }
104905b261ecSmrg
10501b5d61b8Smrg    winDebug("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n");
105105b261ecSmrg
105235c4bbdfSmrg    /* Grab the server started mutex - pause until we get it */
105335c4bbdfSmrg    iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted);
105435c4bbdfSmrg    if (iReturn != 0) {
105535c4bbdfSmrg        ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d.  "
105635c4bbdfSmrg               "Exiting.\n", iReturn);
105735c4bbdfSmrg        pthread_exit(NULL);
105805b261ecSmrg    }
105905b261ecSmrg
10601b5d61b8Smrg    winDebug("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n");
106105b261ecSmrg
106235c4bbdfSmrg    /* Release the server started mutex */
106335c4bbdfSmrg    pthread_mutex_unlock(pProcArg->ppmServerStarted);
106405b261ecSmrg
10651b5d61b8Smrg    winDebug("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
106605b261ecSmrg
106735c4bbdfSmrg    /* Setup the display connection string x */
106835c4bbdfSmrg    winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen);
106905b261ecSmrg
107035c4bbdfSmrg    /* Print the display connection string */
107135c4bbdfSmrg    ErrorF("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay);
107205b261ecSmrg
107335c4bbdfSmrg    /* Use our generated cookie for authentication */
10741b5d61b8Smrg    auth_info = winGetXcbAuthInfo();
10756747b715Smrg
107635c4bbdfSmrg    /* Initialize retry count */
107735c4bbdfSmrg    iRetries = 0;
107805b261ecSmrg
107935c4bbdfSmrg    /* Open the X display */
108035c4bbdfSmrg    do {
108135c4bbdfSmrg        /* Try to open the display */
10821b5d61b8Smrg        pProcArg->conn = xcb_connect_to_display_with_auth_info(pszDisplay,
10831b5d61b8Smrg                                                               auth_info, NULL);
10841b5d61b8Smrg        if (xcb_connection_has_error(pProcArg->conn)) {
108535c4bbdfSmrg            ErrorF("winMultiWindowXMsgProc - Could not open display, try: %d, "
108635c4bbdfSmrg                   "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
108735c4bbdfSmrg            ++iRetries;
108835c4bbdfSmrg            sleep(WIN_CONNECT_DELAY);
108935c4bbdfSmrg            continue;
109035c4bbdfSmrg        }
109135c4bbdfSmrg        else
109235c4bbdfSmrg            break;
109305b261ecSmrg    }
10941b5d61b8Smrg    while (xcb_connection_has_error(pProcArg->conn) && iRetries < WIN_CONNECT_RETRIES);
109535c4bbdfSmrg
109635c4bbdfSmrg    /* Make sure that the display opened */
10971b5d61b8Smrg    if (xcb_connection_has_error(pProcArg->conn)) {
109835c4bbdfSmrg        ErrorF("winMultiWindowXMsgProc - Failed opening the display.  "
109935c4bbdfSmrg               "Exiting.\n");
110035c4bbdfSmrg        pthread_exit(NULL);
110105b261ecSmrg    }
110205b261ecSmrg
11031b5d61b8Smrg    ErrorF("winMultiWindowXMsgProc - xcb_connect() returned and "
110435c4bbdfSmrg           "successfully opened the display.\n");
110505b261ecSmrg
110635c4bbdfSmrg    /* Check if another window manager is already running */
11071b5d61b8Smrg    if (CheckAnotherWindowManager(pProcArg->conn, pProcArg->dwScreen)) {
110835c4bbdfSmrg        ErrorF("winMultiWindowXMsgProc - "
110935c4bbdfSmrg               "another window manager is running.  Exiting.\n");
111035c4bbdfSmrg        pthread_exit(NULL);
111105b261ecSmrg    }
11126747b715Smrg
11131b5d61b8Smrg    {
11141b5d61b8Smrg        /* Get root window id */
11151b5d61b8Smrg        xcb_screen_t *root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen);
11161b5d61b8Smrg        xcb_window_t root_window_id = root_screen->root;
11171b5d61b8Smrg
11181b5d61b8Smrg        /* Set WM_ICON_SIZE property indicating desired icon sizes */
11191b5d61b8Smrg        typedef struct {
11201b5d61b8Smrg            uint32_t min_width, min_height;
11211b5d61b8Smrg            uint32_t max_width, max_height;
11221b5d61b8Smrg            int32_t width_inc, height_inc;
11231b5d61b8Smrg        } xcb_wm_icon_size_hints_hints_t;
11241b5d61b8Smrg
11251b5d61b8Smrg        xcb_wm_icon_size_hints_hints_t xis;
11261b5d61b8Smrg        xis.min_width = xis.min_height = 16;
11271b5d61b8Smrg        xis.max_width = xis.max_height = 48;
11281b5d61b8Smrg        xis.width_inc = xis.height_inc = 16;
11291b5d61b8Smrg
11301b5d61b8Smrg        xcb_change_property(pProcArg->conn, XCB_PROP_MODE_REPLACE, root_window_id,
11311b5d61b8Smrg                            XCB_ATOM_WM_ICON_SIZE, XCB_ATOM_WM_ICON_SIZE, 32,
11321b5d61b8Smrg                            sizeof(xis)/4, &xis);
113305b261ecSmrg    }
113405b261ecSmrg
11351b5d61b8Smrg    atmWmName = intern_atom(pProcArg->conn, "WM_NAME");
11361b5d61b8Smrg    atmNetWmName = intern_atom(pProcArg->conn, "_NET_WM_NAME");
11371b5d61b8Smrg    atmWmHints = intern_atom(pProcArg->conn, "WM_HINTS");
11381b5d61b8Smrg    atmWmChange = intern_atom(pProcArg->conn, "WM_CHANGE_STATE");
11391b5d61b8Smrg    atmNetWmIcon = intern_atom(pProcArg->conn, "_NET_WM_ICON");
11401b5d61b8Smrg    atmWindowState = intern_atom(pProcArg->conn, "_NET_WM_STATE");
11411b5d61b8Smrg    atmMotifWmHints = intern_atom(pProcArg->conn, "_MOTIF_WM_HINTS");
11421b5d61b8Smrg    atmWindowType = intern_atom(pProcArg->conn, "_NET_WM_WINDOW_TYPE");
11431b5d61b8Smrg    atmNormalHints = intern_atom(pProcArg->conn, "WM_NORMAL_HINTS");
114435c4bbdfSmrg
114535c4bbdfSmrg    /*
114635c4bbdfSmrg       iiimxcf had a bug until 2009-04-27, assuming that the
114735c4bbdfSmrg       WM_STATE atom exists, causing clients to fail with
114835c4bbdfSmrg       a BadAtom X error if it doesn't.
114935c4bbdfSmrg
115035c4bbdfSmrg       Since this is on in the default Solaris 10 install,
115135c4bbdfSmrg       workaround this by making sure it does exist...
115235c4bbdfSmrg     */
11531b5d61b8Smrg    intern_atom(pProcArg->conn, "WM_STATE");
115435c4bbdfSmrg
115535c4bbdfSmrg    /* Loop until we explicitly break out */
115635c4bbdfSmrg    while (1) {
11571b5d61b8Smrg        xcb_generic_event_t *event;
11581b5d61b8Smrg        uint8_t type;
11591b5d61b8Smrg        Bool send_event;
11601b5d61b8Smrg
116135c4bbdfSmrg        if (g_shutdown)
116235c4bbdfSmrg            break;
116335c4bbdfSmrg
116435c4bbdfSmrg        /* Fetch next event */
11651b5d61b8Smrg        event = xcb_wait_for_event(pProcArg->conn);
11661b5d61b8Smrg        if (!event) { // returns NULL on I/O error
11671b5d61b8Smrg            int e = xcb_connection_has_error(pProcArg->conn);
11681b5d61b8Smrg            ErrorF("winMultiWindowXMsgProc - Fatal error %d on xcb connection\n", e);
11691b5d61b8Smrg            break;
11701b5d61b8Smrg        }
117135c4bbdfSmrg
11721b5d61b8Smrg        type = event->response_type & ~0x80;
11731b5d61b8Smrg        send_event = event->response_type & 0x80;
117435c4bbdfSmrg
11751b5d61b8Smrg        winDebug("winMultiWindowXMsgProc - event %d\n", type);
117635c4bbdfSmrg
11771b5d61b8Smrg        /* Branch on event type */
11781b5d61b8Smrg        if (type == 0) {
11791b5d61b8Smrg            xcb_generic_error_t *err = (xcb_generic_error_t *)event;
11801b5d61b8Smrg            ErrorF("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, "
11811b5d61b8Smrg                   "Major opcode: %i, Minor opcode: %i\n",
11821b5d61b8Smrg                   err->error_code, err->resource_id,
11831b5d61b8Smrg                   err->major_code, err->minor_code);
11841b5d61b8Smrg            }
11851b5d61b8Smrg        else if (type == XCB_CREATE_NOTIFY) {
11861b5d61b8Smrg            xcb_create_notify_event_t *notify = (xcb_create_notify_event_t *)event;
11871b5d61b8Smrg
11881b5d61b8Smrg            /* Request property change events */
11891b5d61b8Smrg            const static uint32_t mask_value[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
11901b5d61b8Smrg            xcb_change_window_attributes (pProcArg->conn, notify->window,
11911b5d61b8Smrg                                          XCB_CW_EVENT_MASK, mask_value);
11921b5d61b8Smrg
11931b5d61b8Smrg            /* If it's not override-redirect, set the border-width to 0 */
11941b5d61b8Smrg            if (!IsOverrideRedirect(pProcArg->conn, notify->window)) {
11951b5d61b8Smrg                const static uint32_t width_value[] = { 0 };
11961b5d61b8Smrg                xcb_configure_window(pProcArg->conn, notify->window,
11971b5d61b8Smrg                                     XCB_CONFIG_WINDOW_BORDER_WIDTH, width_value);
11981b5d61b8Smrg            }
119935c4bbdfSmrg        }
12001b5d61b8Smrg        else if (type == XCB_MAP_NOTIFY) {
120135c4bbdfSmrg            /* Fake a reparentNotify event as SWT/Motif expects a
120235c4bbdfSmrg               Window Manager to reparent a top-level window when
120335c4bbdfSmrg               it is mapped and waits until they do.
120435c4bbdfSmrg
120535c4bbdfSmrg               We don't actually need to reparent, as the frame is
120635c4bbdfSmrg               a native window, not an X window
120735c4bbdfSmrg
120835c4bbdfSmrg               We do this on MapNotify, not MapRequest like a real
120935c4bbdfSmrg               Window Manager would, so we don't have do get involved
121035c4bbdfSmrg               in actually mapping the window via it's (non-existent)
121135c4bbdfSmrg               parent...
121235c4bbdfSmrg
121335c4bbdfSmrg               See sourceware bugzilla #9848
121435c4bbdfSmrg             */
121535c4bbdfSmrg
12161b5d61b8Smrg            xcb_map_notify_event_t *notify = (xcb_map_notify_event_t *)event;
12171b5d61b8Smrg
12181b5d61b8Smrg            xcb_get_geometry_cookie_t cookie;
12191b5d61b8Smrg            xcb_get_geometry_reply_t *reply;
12201b5d61b8Smrg            xcb_query_tree_cookie_t cookie_qt;
12211b5d61b8Smrg            xcb_query_tree_reply_t *reply_qt;
12221b5d61b8Smrg
12231b5d61b8Smrg            cookie = xcb_get_geometry(pProcArg->conn, notify->window);
12241b5d61b8Smrg            cookie_qt = xcb_query_tree(pProcArg->conn, notify->window);
12251b5d61b8Smrg            reply = xcb_get_geometry_reply(pProcArg->conn, cookie, NULL);
12261b5d61b8Smrg            reply_qt = xcb_query_tree_reply(pProcArg->conn, cookie_qt, NULL);
122735c4bbdfSmrg
12281b5d61b8Smrg            if (reply && reply_qt) {
122935c4bbdfSmrg                /*
123035c4bbdfSmrg                   It's a top-level window if the parent window is a root window
123135c4bbdfSmrg                   Only non-override_redirect windows can get reparented
123235c4bbdfSmrg                 */
12331b5d61b8Smrg                if ((reply->root == reply_qt->parent) && !notify->override_redirect) {
12341b5d61b8Smrg                    xcb_reparent_notify_event_t event_send;
12351b5d61b8Smrg
12361b5d61b8Smrg                    event_send.response_type = ReparentNotify;
12371b5d61b8Smrg                    event_send.event = notify->window;
12381b5d61b8Smrg                    event_send.window = notify->window;
12391b5d61b8Smrg                    event_send.parent = reply_qt->parent;
12401b5d61b8Smrg                    event_send.x = reply->x;
12411b5d61b8Smrg                    event_send.y = reply->y;
12421b5d61b8Smrg
12431b5d61b8Smrg                    xcb_send_event (pProcArg->conn, TRUE, notify->window,
12441b5d61b8Smrg                                    XCB_EVENT_MASK_STRUCTURE_NOTIFY,
12451b5d61b8Smrg                                    (const char *)&event_send);
12461b5d61b8Smrg
12471b5d61b8Smrg                    free(reply_qt);
12481b5d61b8Smrg                    free(reply);
124935c4bbdfSmrg                }
125035c4bbdfSmrg            }
125135c4bbdfSmrg        }
12521b5d61b8Smrg        else if (type == XCB_CONFIGURE_NOTIFY) {
12531b5d61b8Smrg            if (!send_event) {
125435c4bbdfSmrg                /*
125535c4bbdfSmrg                   Java applications using AWT on JRE 1.6.0 break with non-reparenting WMs AWT
125635c4bbdfSmrg                   doesn't explicitly know about (See sun bug #6434227)
125735c4bbdfSmrg
125835c4bbdfSmrg                   XDecoratedPeer.handleConfigureNotifyEvent() only processes non-synthetic
125935c4bbdfSmrg                   ConfigureNotify events to update window location if it's identified the
126035c4bbdfSmrg                   WM as a non-reparenting WM it knows about (compiz or lookingglass)
126135c4bbdfSmrg
126235c4bbdfSmrg                   Rather than tell all sorts of lies to get XWM to recognize us as one of
126335c4bbdfSmrg                   those, simply send a synthetic ConfigureNotify for every non-synthetic one
126435c4bbdfSmrg                 */
12651b5d61b8Smrg                xcb_configure_notify_event_t *notify = (xcb_configure_notify_event_t *)event;
12661b5d61b8Smrg                xcb_configure_notify_event_t event_send = *notify;
126735c4bbdfSmrg
12681b5d61b8Smrg                event_send.event = notify->window;
12691b5d61b8Smrg
12701b5d61b8Smrg                xcb_send_event(pProcArg->conn, TRUE, notify->window,
12711b5d61b8Smrg                               XCB_EVENT_MASK_STRUCTURE_NOTIFY,
12721b5d61b8Smrg                               (const char *)&event_send);
127335c4bbdfSmrg            }
127435c4bbdfSmrg        }
12751b5d61b8Smrg        else if (type ==  XCB_PROPERTY_NOTIFY) {
12761b5d61b8Smrg            xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)event;
12771b5d61b8Smrg
12781b5d61b8Smrg            if ((notify->atom == atmWmName) ||
12791b5d61b8Smrg                (notify->atom == atmNetWmName)) {
128035c4bbdfSmrg                memset(&msg, 0, sizeof(msg));
128135c4bbdfSmrg
128235c4bbdfSmrg                msg.msg = WM_WM_NAME_EVENT;
12831b5d61b8Smrg                msg.iWindow = notify->window;
128435c4bbdfSmrg
128535c4bbdfSmrg                /* Other fields ignored */
128635c4bbdfSmrg                winSendMessageToWM(pProcArg->pWMInfo, &msg);
128735c4bbdfSmrg            }
128835c4bbdfSmrg            else {
128935c4bbdfSmrg                /*
129035c4bbdfSmrg                   Several properties are considered for WM hints, check if this property change affects any of them...
129135c4bbdfSmrg                   (this list needs to be kept in sync with winApplyHints())
129235c4bbdfSmrg                 */
12931b5d61b8Smrg                if ((notify->atom == atmWmHints) ||
12941b5d61b8Smrg                    (notify->atom == atmWindowState) ||
12951b5d61b8Smrg                    (notify->atom == atmMotifWmHints) ||
12961b5d61b8Smrg                    (notify->atom == atmWindowType) ||
12971b5d61b8Smrg                    (notify->atom == atmNormalHints)) {
129835c4bbdfSmrg                    memset(&msg, 0, sizeof(msg));
129935c4bbdfSmrg                    msg.msg = WM_WM_HINTS_EVENT;
13001b5d61b8Smrg                    msg.iWindow = notify->window;
130135c4bbdfSmrg
130235c4bbdfSmrg                    /* Other fields ignored */
130335c4bbdfSmrg                    winSendMessageToWM(pProcArg->pWMInfo, &msg);
130435c4bbdfSmrg                }
130535c4bbdfSmrg
130635c4bbdfSmrg                /* Not an else as WM_HINTS affects both style and icon */
13071b5d61b8Smrg                if ((notify->atom == atmWmHints) ||
13081b5d61b8Smrg                    (notify->atom == atmNetWmIcon)) {
130935c4bbdfSmrg                    memset(&msg, 0, sizeof(msg));
131035c4bbdfSmrg                    msg.msg = WM_WM_ICON_EVENT;
13111b5d61b8Smrg                    msg.iWindow = notify->window;
131235c4bbdfSmrg
131335c4bbdfSmrg                    /* Other fields ignored */
131435c4bbdfSmrg                    winSendMessageToWM(pProcArg->pWMInfo, &msg);
13156747b715Smrg                }
13166747b715Smrg            }
13176747b715Smrg        }
13181b5d61b8Smrg        else if (type == XCB_CLIENT_MESSAGE) {
13191b5d61b8Smrg            xcb_client_message_event_t *client_msg = (xcb_client_message_event_t *)event;
132035c4bbdfSmrg
13211b5d61b8Smrg            if (client_msg->type == atmWmChange
13221b5d61b8Smrg                 && client_msg->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) {
13231b5d61b8Smrg                ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
132435c4bbdfSmrg
13251b5d61b8Smrg                memset(&msg, 0, sizeof(msg));
132635c4bbdfSmrg
13271b5d61b8Smrg                msg.msg = WM_WM_CHANGE_STATE;
13281b5d61b8Smrg                msg.iWindow = client_msg->window;
13291b5d61b8Smrg
13301b5d61b8Smrg                winSendMessageToWM(pProcArg->pWMInfo, &msg);
13311b5d61b8Smrg            }
133235c4bbdfSmrg        }
13331b5d61b8Smrg
13341b5d61b8Smrg        /* Free the event */
13351b5d61b8Smrg        free(event);
133605b261ecSmrg    }
133705b261ecSmrg
13381b5d61b8Smrg    xcb_disconnect(pProcArg->conn);
133935c4bbdfSmrg    pthread_exit(NULL);
134035c4bbdfSmrg    return NULL;
134105b261ecSmrg}
134205b261ecSmrg
134305b261ecSmrg/*
134405b261ecSmrg * winInitWM - Entry point for the X server to spawn
134505b261ecSmrg * the Window Manager thread.  Called from
134605b261ecSmrg * winscrinit.c/winFinishScreenInitFB ().
134705b261ecSmrg */
134805b261ecSmrg
134905b261ecSmrgBool
135035c4bbdfSmrgwinInitWM(void **ppWMInfo,
135135c4bbdfSmrg          pthread_t * ptWMProc,
135235c4bbdfSmrg          pthread_t * ptXMsgProc,
135335c4bbdfSmrg          pthread_mutex_t * ppmServerStarted,
13541b5d61b8Smrg          int dwScreen, HWND hwndScreen)
135505b261ecSmrg{
135635c4bbdfSmrg    WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec));
135735c4bbdfSmrg    WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec));
135835c4bbdfSmrg    XMsgProcArgPtr pXMsgArg = malloc(sizeof(XMsgProcArgRec));
135935c4bbdfSmrg
136035c4bbdfSmrg    /* Bail if the input parameters are bad */
136135c4bbdfSmrg    if (pArg == NULL || pWMInfo == NULL || pXMsgArg == NULL) {
136235c4bbdfSmrg        ErrorF("winInitWM - malloc failed.\n");
136335c4bbdfSmrg        free(pArg);
136435c4bbdfSmrg        free(pWMInfo);
136535c4bbdfSmrg        free(pXMsgArg);
136635c4bbdfSmrg        return FALSE;
136705b261ecSmrg    }
136835c4bbdfSmrg
136935c4bbdfSmrg    /* Zero the allocated memory */
137035c4bbdfSmrg    ZeroMemory(pArg, sizeof(WMProcArgRec));
137135c4bbdfSmrg    ZeroMemory(pWMInfo, sizeof(WMInfoRec));
137235c4bbdfSmrg    ZeroMemory(pXMsgArg, sizeof(XMsgProcArgRec));
137335c4bbdfSmrg
137435c4bbdfSmrg    /* Set a return pointer to the Window Manager info structure */
137535c4bbdfSmrg    *ppWMInfo = pWMInfo;
137635c4bbdfSmrg
137735c4bbdfSmrg    /* Setup the argument structure for the thread function */
137835c4bbdfSmrg    pArg->dwScreen = dwScreen;
137935c4bbdfSmrg    pArg->pWMInfo = pWMInfo;
138035c4bbdfSmrg    pArg->ppmServerStarted = ppmServerStarted;
138135c4bbdfSmrg
138235c4bbdfSmrg    /* Intialize the message queue */
138335c4bbdfSmrg    if (!InitQueue(&pWMInfo->wmMsgQueue)) {
138435c4bbdfSmrg        ErrorF("winInitWM - InitQueue () failed.\n");
138535c4bbdfSmrg        return FALSE;
138605b261ecSmrg    }
138735c4bbdfSmrg
138835c4bbdfSmrg    /* Spawn a thread for the Window Manager */
138935c4bbdfSmrg    if (pthread_create(ptWMProc, NULL, winMultiWindowWMProc, pArg)) {
139035c4bbdfSmrg        /* Bail if thread creation failed */
139135c4bbdfSmrg        ErrorF("winInitWM - pthread_create failed for Window Manager.\n");
139235c4bbdfSmrg        return FALSE;
139305b261ecSmrg    }
139405b261ecSmrg
139535c4bbdfSmrg    /* Spawn the XNextEvent thread, will send messages to WM */
139635c4bbdfSmrg    pXMsgArg->dwScreen = dwScreen;
139735c4bbdfSmrg    pXMsgArg->pWMInfo = pWMInfo;
139835c4bbdfSmrg    pXMsgArg->ppmServerStarted = ppmServerStarted;
139935c4bbdfSmrg    pXMsgArg->hwndScreen = hwndScreen;
140035c4bbdfSmrg    if (pthread_create(ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg)) {
140135c4bbdfSmrg        /* Bail if thread creation failed */
140235c4bbdfSmrg        ErrorF("winInitWM - pthread_create failed on XMSG.\n");
140335c4bbdfSmrg        return FALSE;
140405b261ecSmrg    }
140505b261ecSmrg
140605b261ecSmrg#if CYGDEBUG || YES
140735c4bbdfSmrg    winDebug("winInitWM - Returning.\n");
140805b261ecSmrg#endif
140905b261ecSmrg
141035c4bbdfSmrg    return TRUE;
141105b261ecSmrg}
141205b261ecSmrg
141305b261ecSmrg/*
141405b261ecSmrg * Window manager thread - setup
141505b261ecSmrg */
141605b261ecSmrg
141705b261ecSmrgstatic void
141835c4bbdfSmrgwinInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
141905b261ecSmrg{
142035c4bbdfSmrg    int iRetries = 0;
142135c4bbdfSmrg    char pszDisplay[512];
142235c4bbdfSmrg    int iReturn;
14231b5d61b8Smrg    xcb_auth_info_t *auth_info;
142405b261ecSmrg
142535c4bbdfSmrg    winDebug("winInitMultiWindowWM - Hello\n");
142605b261ecSmrg
142735c4bbdfSmrg    /* Check that argument pointer is not invalid */
142835c4bbdfSmrg    if (pProcArg == NULL) {
142935c4bbdfSmrg        ErrorF("winInitMultiWindowWM - pProcArg is NULL.  Exiting.\n");
143035c4bbdfSmrg        pthread_exit(NULL);
143105b261ecSmrg    }
143205b261ecSmrg
14331b5d61b8Smrg    winDebug("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n");
143405b261ecSmrg
143535c4bbdfSmrg    /* Grab our garbage mutex to satisfy pthread_cond_wait */
143635c4bbdfSmrg    iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted);
143735c4bbdfSmrg    if (iReturn != 0) {
143835c4bbdfSmrg        ErrorF("winInitMultiWindowWM - pthread_mutex_lock () failed: %d.  "
143935c4bbdfSmrg               "Exiting.\n", iReturn);
144035c4bbdfSmrg        pthread_exit(NULL);
144105b261ecSmrg    }
144205b261ecSmrg
14431b5d61b8Smrg    winDebug("winInitMultiWindowWM - pthread_mutex_lock () returned.\n");
144405b261ecSmrg
144535c4bbdfSmrg    /* Release the server started mutex */
144635c4bbdfSmrg    pthread_mutex_unlock(pProcArg->ppmServerStarted);
144705b261ecSmrg
14481b5d61b8Smrg    winDebug("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
14496747b715Smrg
145035c4bbdfSmrg    /* Setup the display connection string x */
145135c4bbdfSmrg    winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen);
145235c4bbdfSmrg
145335c4bbdfSmrg    /* Print the display connection string */
145435c4bbdfSmrg    ErrorF("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay);
145535c4bbdfSmrg
145635c4bbdfSmrg    /* Use our generated cookie for authentication */
14571b5d61b8Smrg    auth_info = winGetXcbAuthInfo();
145835c4bbdfSmrg
145935c4bbdfSmrg    /* Open the X display */
146035c4bbdfSmrg    do {
146135c4bbdfSmrg        /* Try to open the display */
14621b5d61b8Smrg        pWMInfo->conn = xcb_connect_to_display_with_auth_info(pszDisplay,
14631b5d61b8Smrg                                                              auth_info, NULL);
14641b5d61b8Smrg        if (xcb_connection_has_error(pWMInfo->conn)) {
146535c4bbdfSmrg            ErrorF("winInitMultiWindowWM - Could not open display, try: %d, "
146635c4bbdfSmrg                   "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
146735c4bbdfSmrg            ++iRetries;
146835c4bbdfSmrg            sleep(WIN_CONNECT_DELAY);
146935c4bbdfSmrg            continue;
147035c4bbdfSmrg        }
147135c4bbdfSmrg        else
147235c4bbdfSmrg            break;
147305b261ecSmrg    }
14741b5d61b8Smrg    while (xcb_connection_has_error(pWMInfo->conn) && iRetries < WIN_CONNECT_RETRIES);
147535c4bbdfSmrg
147635c4bbdfSmrg    /* Make sure that the display opened */
14771b5d61b8Smrg    if (xcb_connection_has_error(pWMInfo->conn)) {
147835c4bbdfSmrg        ErrorF("winInitMultiWindowWM - Failed opening the display.  "
147935c4bbdfSmrg               "Exiting.\n");
148035c4bbdfSmrg        pthread_exit(NULL);
148105b261ecSmrg    }
148205b261ecSmrg
14831b5d61b8Smrg    ErrorF("winInitMultiWindowWM - xcb_connect () returned and "
148435c4bbdfSmrg           "successfully opened the display.\n");
148505b261ecSmrg
148635c4bbdfSmrg    /* Create some atoms */
14871b5d61b8Smrg    pWMInfo->atmWmProtos = intern_atom(pWMInfo->conn, "WM_PROTOCOLS");
14881b5d61b8Smrg    pWMInfo->atmWmDelete = intern_atom(pWMInfo->conn, "WM_DELETE_WINDOW");
14891b5d61b8Smrg    pWMInfo->atmWmTakeFocus = intern_atom(pWMInfo->conn, "WM_TAKE_FOCUS");
14901b5d61b8Smrg    pWMInfo->atmPrivMap = intern_atom(pWMInfo->conn, WINDOWSWM_NATIVE_HWND);
14911b5d61b8Smrg    pWMInfo->atmUtf8String = intern_atom(pWMInfo->conn, "UTF8_STRING");
14921b5d61b8Smrg    pWMInfo->atmNetWmName = intern_atom(pWMInfo->conn, "_NET_WM_NAME");
14931b5d61b8Smrg
14941b5d61b8Smrg    /* Initialization for the xcb_ewmh and EWMH atoms */
14951b5d61b8Smrg    {
14961b5d61b8Smrg        xcb_intern_atom_cookie_t *atoms_cookie;
14971b5d61b8Smrg        atoms_cookie = xcb_ewmh_init_atoms(pWMInfo->conn, &pWMInfo->ewmh);
14981b5d61b8Smrg        if (xcb_ewmh_init_atoms_replies(&pWMInfo->ewmh, atoms_cookie, NULL)) {
14991b5d61b8Smrg            /* Set the _NET_SUPPORTED atom for this context.
15001b5d61b8Smrg
15011b5d61b8Smrg               TODO: Audit to ensure we implement everything defined as MUSTs
15021b5d61b8Smrg               for window managers in the EWMH standard.*/
15031b5d61b8Smrg            xcb_atom_t supported[] =
15041b5d61b8Smrg                {
15051b5d61b8Smrg                    pWMInfo->ewmh.WM_PROTOCOLS,
15061b5d61b8Smrg                    pWMInfo->ewmh._NET_SUPPORTED,
15071b5d61b8Smrg                    pWMInfo->ewmh._NET_SUPPORTING_WM_CHECK,
15081b5d61b8Smrg                    pWMInfo->ewmh._NET_CLOSE_WINDOW,
15091b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_WINDOW_TYPE,
15101b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK,
15111b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH,
15121b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_STATE,
15131b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_STATE_HIDDEN,
15141b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_STATE_ABOVE,
15151b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_STATE_BELOW,
15161b5d61b8Smrg                    pWMInfo->ewmh._NET_WM_STATE_SKIP_TASKBAR,
15171b5d61b8Smrg                };
15181b5d61b8Smrg
15191b5d61b8Smrg            xcb_ewmh_set_supported(&pWMInfo->ewmh, pProcArg->dwScreen,
15201b5d61b8Smrg                                   ARRAY_SIZE(supported), supported);
15211b5d61b8Smrg        }
15221b5d61b8Smrg        else {
15231b5d61b8Smrg            ErrorF("winInitMultiWindowWM - xcb_ewmh_init_atoms() failed\n");
152435c4bbdfSmrg        }
152505b261ecSmrg    }
152605b261ecSmrg
15271b5d61b8Smrg    /*
15281b5d61b8Smrg      Set the root window cursor to left_ptr (this controls the cursor an
15291b5d61b8Smrg      application gets over it's windows when it doesn't set one)
15301b5d61b8Smrg    */
15311b5d61b8Smrg    {
15321b5d61b8Smrg#define XC_left_ptr 68
15331b5d61b8Smrg        xcb_cursor_t cursor = xcb_generate_id(pWMInfo->conn);
15341b5d61b8Smrg        xcb_font_t font = xcb_generate_id(pWMInfo->conn);
15351b5d61b8Smrg        xcb_font_t *mask_font = &font; /* An alias to clarify */
15361b5d61b8Smrg        int shape = XC_left_ptr;
15371b5d61b8Smrg        uint32_t mask = XCB_CW_CURSOR;
15381b5d61b8Smrg        uint32_t value_list = cursor;
153905b261ecSmrg
15401b5d61b8Smrg        xcb_screen_t *root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen);
15411b5d61b8Smrg        xcb_window_t window = root_screen->root;
154235c4bbdfSmrg
15431b5d61b8Smrg        static const uint16_t fgred = 0, fggreen = 0, fgblue = 0;
15441b5d61b8Smrg        static const uint16_t bgred = 0xFFFF, bggreen = 0xFFFF, bgblue = 0xFFFF;
154505b261ecSmrg
15461b5d61b8Smrg        xcb_open_font(pWMInfo->conn, font, sizeof("cursor"), "cursor");
154705b261ecSmrg
15481b5d61b8Smrg        xcb_create_glyph_cursor(pWMInfo->conn, cursor, font, *mask_font,
15491b5d61b8Smrg                                shape, shape + 1,
15501b5d61b8Smrg                                fgred, fggreen, fgblue, bgred, bggreen, bgblue);
155105b261ecSmrg
15521b5d61b8Smrg        xcb_change_window_attributes(pWMInfo->conn, window, mask, &value_list);
155305b261ecSmrg
15541b5d61b8Smrg        xcb_free_cursor(pWMInfo->conn, cursor);
15551b5d61b8Smrg        xcb_close_font(pWMInfo->conn, font);
155635c4bbdfSmrg    }
155735c4bbdfSmrg}
155805b261ecSmrg
155905b261ecSmrg/*
15601b5d61b8Smrg * winSendMessageToWM - Send a message from the X thread to the WM thread
156105b261ecSmrg */
156205b261ecSmrg
15631b5d61b8Smrgvoid
15641b5d61b8SmrgwinSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
156505b261ecSmrg{
15661b5d61b8Smrg    WMMsgNodePtr pNode;
156735c4bbdfSmrg
15686747b715Smrg#if CYGMULTIWINDOW_DEBUG
15691b5d61b8Smrg    ErrorF("winSendMessageToWM %s\n", MessageName(pMsg));
15706747b715Smrg#endif
157105b261ecSmrg
15721b5d61b8Smrg    pNode = malloc(sizeof(WMMsgNodeRec));
15731b5d61b8Smrg    if (pNode != NULL) {
15741b5d61b8Smrg        memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec));
15751b5d61b8Smrg        PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode);
157635c4bbdfSmrg    }
157705b261ecSmrg}
157805b261ecSmrg
157905b261ecSmrg/*
158005b261ecSmrg * Check if another window manager is running
158105b261ecSmrg */
158205b261ecSmrg
158305b261ecSmrgstatic Bool
15841b5d61b8SmrgCheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen)
158505b261ecSmrg{
15861b5d61b8Smrg    Bool redirectError = FALSE;
15871b5d61b8Smrg
15881b5d61b8Smrg    /* Get root window id */
15891b5d61b8Smrg    xcb_screen_t *root_screen = xcb_aux_get_screen(conn, dwScreen);
15901b5d61b8Smrg    xcb_window_t root_window_id = root_screen->root;
15911b5d61b8Smrg
159235c4bbdfSmrg    /*
159335c4bbdfSmrg       Try to select the events which only one client at a time is allowed to select.
159435c4bbdfSmrg       If this causes an error, another window manager is already running...
159535c4bbdfSmrg     */
15961b5d61b8Smrg    const static uint32_t test_mask[] = { XCB_EVENT_MASK_RESIZE_REDIRECT |
15971b5d61b8Smrg                                       XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
15981b5d61b8Smrg                                       XCB_EVENT_MASK_BUTTON_PRESS };
15991b5d61b8Smrg
16001b5d61b8Smrg    xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(conn,
16011b5d61b8Smrg                                                                    root_window_id,
16021b5d61b8Smrg                                                                    XCB_CW_EVENT_MASK,
16031b5d61b8Smrg                                                                    test_mask);
16041b5d61b8Smrg    xcb_generic_error_t *error;
16051b5d61b8Smrg    if ((error = xcb_request_check(conn, cookie)))
16061b5d61b8Smrg        {
16071b5d61b8Smrg            redirectError = TRUE;
16081b5d61b8Smrg            free(error);
16091b5d61b8Smrg        }
161035c4bbdfSmrg
161135c4bbdfSmrg    /*
161235c4bbdfSmrg       Side effect: select the events we are actually interested in...
161335c4bbdfSmrg
16141b5d61b8Smrg       Other WMs are not allowed, also select one of the events which only one client
161535c4bbdfSmrg       at a time is allowed to select, so other window managers won't start...
161635c4bbdfSmrg     */
16171b5d61b8Smrg    {
16181b5d61b8Smrg        const uint32_t mask[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
16191b5d61b8Smrg                                  XCB_EVENT_MASK_BUTTON_PRESS };
16201b5d61b8Smrg
16211b5d61b8Smrg        xcb_change_window_attributes(conn, root_window_id, XCB_CW_EVENT_MASK, mask);
16221b5d61b8Smrg    }
16231b5d61b8Smrg
162435c4bbdfSmrg    return redirectError;
162505b261ecSmrg}
162605b261ecSmrg
162705b261ecSmrg/*
162805b261ecSmrg * Notify the MWM thread we're exiting and not to reconnect
162905b261ecSmrg */
163005b261ecSmrg
163105b261ecSmrgvoid
163235c4bbdfSmrgwinDeinitMultiWindowWM(void)
163305b261ecSmrg{
163435c4bbdfSmrg    ErrorF("winDeinitMultiWindowWM - Noting shutdown in progress\n");
163535c4bbdfSmrg    g_shutdown = TRUE;
163605b261ecSmrg}
16376747b715Smrg
16386747b715Smrg/* Windows window styles */
163935c4bbdfSmrg#define HINT_NOFRAME	(1L<<0)
16406747b715Smrg#define HINT_BORDER	(1L<<1)
164135c4bbdfSmrg#define HINT_SIZEBOX	(1L<<2)
164235c4bbdfSmrg#define HINT_CAPTION	(1L<<3)
16436747b715Smrg#define HINT_NOMAXIMIZE (1L<<4)
164435c4bbdfSmrg#define HINT_NOMINIMIZE (1L<<5)
164535c4bbdfSmrg#define HINT_NOSYSMENU  (1L<<6)
164635c4bbdfSmrg#define HINT_SKIPTASKBAR (1L<<7)
16476747b715Smrg/* These two are used on their own */
16486747b715Smrg#define HINT_MAX	(1L<<0)
16496747b715Smrg#define HINT_MIN	(1L<<1)
16506747b715Smrg
16516747b715Smrgstatic void
16521b5d61b8SmrgwinApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
16536747b715Smrg{
16541b5d61b8Smrg
16551b5d61b8Smrg    xcb_connection_t *conn = pWMInfo->conn;
16561b5d61b8Smrg    static xcb_atom_t windowState, motif_wm_hints;
16571b5d61b8Smrg    static xcb_atom_t hiddenState, fullscreenState, belowState, aboveState,
165835c4bbdfSmrg        skiptaskbarState;
16591b5d61b8Smrg    static xcb_atom_t splashType;
166035c4bbdfSmrg    static int generation;
16611b5d61b8Smrg
16621b5d61b8Smrg    unsigned long hint = 0, maxmin = 0;
166335c4bbdfSmrg    unsigned long style, exStyle;
166435c4bbdfSmrg
166535c4bbdfSmrg    if (!hWnd)
166635c4bbdfSmrg        return;
166735c4bbdfSmrg    if (!IsWindow(hWnd))
166835c4bbdfSmrg        return;
166935c4bbdfSmrg
167035c4bbdfSmrg    if (generation != serverGeneration) {
167135c4bbdfSmrg        generation = serverGeneration;
16721b5d61b8Smrg        windowState = intern_atom(conn, "_NET_WM_STATE");
16731b5d61b8Smrg        motif_wm_hints = intern_atom(conn, "_MOTIF_WM_HINTS");
16741b5d61b8Smrg        hiddenState = intern_atom(conn, "_NET_WM_STATE_HIDDEN");
16751b5d61b8Smrg        fullscreenState = intern_atom(conn, "_NET_WM_STATE_FULLSCREEN");
16761b5d61b8Smrg        belowState = intern_atom(conn, "_NET_WM_STATE_BELOW");
16771b5d61b8Smrg        aboveState = intern_atom(conn, "_NET_WM_STATE_ABOVE");
16781b5d61b8Smrg        skiptaskbarState = intern_atom(conn, "_NET_WM_STATE_SKIP_TASKBAR");
16791b5d61b8Smrg        splashType = intern_atom(conn, "_NET_WM_WINDOW_TYPE_SPLASHSCREEN");
168035c4bbdfSmrg    }
16816747b715Smrg
16821b5d61b8Smrg    {
16831b5d61b8Smrg      xcb_get_property_cookie_t cookie_wm_state = xcb_get_property(conn, FALSE, iWindow, windowState, XCB_ATOM_ATOM, 0L, INT_MAX);
16841b5d61b8Smrg      xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie_wm_state, NULL);
16851b5d61b8Smrg      if (reply) {
16861b5d61b8Smrg        int i;
16871b5d61b8Smrg        int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
16881b5d61b8Smrg        xcb_atom_t *pAtom = xcb_get_property_value(reply);
168935c4bbdfSmrg
169035c4bbdfSmrg            for (i = 0; i < nitems; i++) {
169135c4bbdfSmrg                if (pAtom[i] == skiptaskbarState)
169235c4bbdfSmrg                    hint |= HINT_SKIPTASKBAR;
169335c4bbdfSmrg                if (pAtom[i] == hiddenState)
169435c4bbdfSmrg                    maxmin |= HINT_MIN;
169535c4bbdfSmrg                else if (pAtom[i] == fullscreenState)
169635c4bbdfSmrg                    maxmin |= HINT_MAX;
169735c4bbdfSmrg                if (pAtom[i] == belowState)
169835c4bbdfSmrg                    *zstyle = HWND_BOTTOM;
169935c4bbdfSmrg                else if (pAtom[i] == aboveState)
170035c4bbdfSmrg                    *zstyle = HWND_TOPMOST;
170135c4bbdfSmrg            }
170235c4bbdfSmrg
17031b5d61b8Smrg            free(reply);
17041b5d61b8Smrg      }
17056747b715Smrg    }
17066747b715Smrg
17071b5d61b8Smrg    {
17081b5d61b8Smrg      xcb_get_property_cookie_t cookie_mwm_hint = xcb_get_property(conn, FALSE, iWindow, motif_wm_hints, motif_wm_hints, 0L, sizeof(MwmHints));
17091b5d61b8Smrg      xcb_get_property_reply_t *reply =  xcb_get_property_reply(conn, cookie_mwm_hint, NULL);
17101b5d61b8Smrg      if (reply) {
17111b5d61b8Smrg        int nitems = xcb_get_property_value_length(reply)/4;
17121b5d61b8Smrg        MwmHints *mwm_hint = xcb_get_property_value(reply);
17131b5d61b8Smrg        if (mwm_hint && (nitems >= PropMwmHintsElements) &&
171435c4bbdfSmrg            (mwm_hint->flags & MwmHintsDecorations)) {
171535c4bbdfSmrg            if (!mwm_hint->decorations)
171635c4bbdfSmrg                hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
171735c4bbdfSmrg            else if (!(mwm_hint->decorations & MwmDecorAll)) {
171835c4bbdfSmrg                if (mwm_hint->decorations & MwmDecorBorder)
171935c4bbdfSmrg                    hint |= HINT_BORDER;
172035c4bbdfSmrg                if (mwm_hint->decorations & MwmDecorHandle)
172135c4bbdfSmrg                    hint |= HINT_SIZEBOX;
172235c4bbdfSmrg                if (mwm_hint->decorations & MwmDecorTitle)
172335c4bbdfSmrg                    hint |= HINT_CAPTION;
172435c4bbdfSmrg                if (!(mwm_hint->decorations & MwmDecorMenu))
172535c4bbdfSmrg                    hint |= HINT_NOSYSMENU;
172635c4bbdfSmrg                if (!(mwm_hint->decorations & MwmDecorMinimize))
172735c4bbdfSmrg                    hint |= HINT_NOMINIMIZE;
172835c4bbdfSmrg                if (!(mwm_hint->decorations & MwmDecorMaximize))
172935c4bbdfSmrg                    hint |= HINT_NOMAXIMIZE;
173035c4bbdfSmrg            }
173135c4bbdfSmrg            else {
173235c4bbdfSmrg                /*
173335c4bbdfSmrg                   MwmDecorAll means all decorations *except* those specified by other flag
173435c4bbdfSmrg                   bits that are set.  Not yet implemented.
173535c4bbdfSmrg                 */
173635c4bbdfSmrg            }
173735c4bbdfSmrg        }
17381b5d61b8Smrg        free(reply);
17391b5d61b8Smrg      }
174035c4bbdfSmrg    }
174135c4bbdfSmrg
17421b5d61b8Smrg    {
17431b5d61b8Smrg      int i;
17441b5d61b8Smrg      xcb_ewmh_get_atoms_reply_t type;
17451b5d61b8Smrg      xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type(&pWMInfo->ewmh, iWindow);
17461b5d61b8Smrg      if (xcb_ewmh_get_wm_window_type_reply(&pWMInfo->ewmh, cookie, &type, NULL)) {
17471b5d61b8Smrg        for (i = 0; i < type.atoms_len; i++) {
17481b5d61b8Smrg            if (type.atoms[i] ==  pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK) {
174935c4bbdfSmrg                hint = (hint & ~HINT_NOFRAME) | HINT_SKIPTASKBAR | HINT_SIZEBOX;
175035c4bbdfSmrg                *zstyle = HWND_TOPMOST;
175135c4bbdfSmrg            }
17521b5d61b8Smrg            else if ((type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH)
17531b5d61b8Smrg                     || (type.atoms[i] == splashType)) {
17541b5d61b8Smrg                hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
17551b5d61b8Smrg                *zstyle = HWND_TOPMOST;
17561b5d61b8Smrg            }
175735c4bbdfSmrg        }
17581b5d61b8Smrg      }
17596747b715Smrg    }
17606747b715Smrg
17616747b715Smrg    {
17621b5d61b8Smrg        xcb_size_hints_t size_hints;
17631b5d61b8Smrg        xcb_get_property_cookie_t cookie;
17641b5d61b8Smrg
17651b5d61b8Smrg        cookie = xcb_icccm_get_wm_normal_hints(conn, iWindow);
17661b5d61b8Smrg        if (xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &size_hints, NULL)) {
17671b5d61b8Smrg            if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) {
176835c4bbdfSmrg
17691b5d61b8Smrg                /* Not maximizable if a maximum size is specified, and that size
17701b5d61b8Smrg                   is smaller (in either dimension) than the screen size */
17711b5d61b8Smrg                if ((size_hints.max_width < GetSystemMetrics(SM_CXVIRTUALSCREEN))
17721b5d61b8Smrg                    || (size_hints.max_height < GetSystemMetrics(SM_CYVIRTUALSCREEN)))
17731b5d61b8Smrg                    hint |= HINT_NOMAXIMIZE;
177435c4bbdfSmrg
17751b5d61b8Smrg                if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
177635c4bbdfSmrg                    /*
177735c4bbdfSmrg                       If both minimum size and maximum size are specified and are the same,
177835c4bbdfSmrg                       don't bother with a resizing frame
177935c4bbdfSmrg                     */
17801b5d61b8Smrg                    if ((size_hints.min_width == size_hints.max_width)
17811b5d61b8Smrg                        && (size_hints.min_height == size_hints.max_height))
178235c4bbdfSmrg                        hint = (hint & ~HINT_SIZEBOX);
178335c4bbdfSmrg                }
178435c4bbdfSmrg            }
178535c4bbdfSmrg        }
17866747b715Smrg    }
17876747b715Smrg
178835c4bbdfSmrg    /*
178935c4bbdfSmrg       Override hint settings from above with settings from config file and set
179035c4bbdfSmrg       application id for grouping.
179135c4bbdfSmrg     */
179235c4bbdfSmrg    {
179335c4bbdfSmrg        char *application_id = 0;
17941b5d61b8Smrg        char *window_name = 0;
17951b5d61b8Smrg        char *res_name = 0;
17961b5d61b8Smrg        char *res_class = 0;
179735c4bbdfSmrg
17981b5d61b8Smrg        GetClassNames(pWMInfo, iWindow, &res_name, &res_class, &window_name);
179935c4bbdfSmrg
18001b5d61b8Smrg        style = STYLE_NONE;
18011b5d61b8Smrg        style = winOverrideStyle(res_name, res_class, window_name);
180235c4bbdfSmrg
180335c4bbdfSmrg#define APPLICATION_ID_FORMAT	"%s.xwin.%s"
180435c4bbdfSmrg#define APPLICATION_ID_UNKNOWN "unknown"
18051b5d61b8Smrg        if (res_class) {
18061b5d61b8Smrg            asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME,
18071b5d61b8Smrg                     res_class);
180835c4bbdfSmrg        }
180935c4bbdfSmrg        else {
18101b5d61b8Smrg            asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME,
18111b5d61b8Smrg                     APPLICATION_ID_UNKNOWN);
181235c4bbdfSmrg        }
18131b5d61b8Smrg        winSetAppUserModelID(hWnd, application_id);
18141b5d61b8Smrg
18151b5d61b8Smrg        free(application_id);
18161b5d61b8Smrg        free(res_name);
18171b5d61b8Smrg        free(res_class);
18181b5d61b8Smrg        free(window_name);
181935c4bbdfSmrg    }
18206747b715Smrg
182135c4bbdfSmrg    if (style & STYLE_TOPMOST)
182235c4bbdfSmrg        *zstyle = HWND_TOPMOST;
182335c4bbdfSmrg    else if (style & STYLE_MAXIMIZE)
182435c4bbdfSmrg        maxmin = (hint & ~HINT_MIN) | HINT_MAX;
182535c4bbdfSmrg    else if (style & STYLE_MINIMIZE)
182635c4bbdfSmrg        maxmin = (hint & ~HINT_MAX) | HINT_MIN;
182735c4bbdfSmrg    else if (style & STYLE_BOTTOM)
182835c4bbdfSmrg        *zstyle = HWND_BOTTOM;
182935c4bbdfSmrg
183035c4bbdfSmrg    if (maxmin & HINT_MAX)
183135c4bbdfSmrg        SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
183235c4bbdfSmrg    else if (maxmin & HINT_MIN)
183335c4bbdfSmrg        SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
183435c4bbdfSmrg
183535c4bbdfSmrg    if (style & STYLE_NOTITLE)
183635c4bbdfSmrg        hint =
183735c4bbdfSmrg            (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) |
183835c4bbdfSmrg            HINT_SIZEBOX;
183935c4bbdfSmrg    else if (style & STYLE_OUTLINE)
184035c4bbdfSmrg        hint =
184135c4bbdfSmrg            (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) |
184235c4bbdfSmrg            HINT_BORDER;
184335c4bbdfSmrg    else if (style & STYLE_NOFRAME)
184435c4bbdfSmrg        hint =
184535c4bbdfSmrg            (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) |
184635c4bbdfSmrg            HINT_NOFRAME;
184735c4bbdfSmrg
184835c4bbdfSmrg    /* Now apply styles to window */
184935c4bbdfSmrg    style = GetWindowLongPtr(hWnd, GWL_STYLE);
185035c4bbdfSmrg    if (!style)
185135c4bbdfSmrg        return;                 /* GetWindowLongPointer returns 0 on failure, we hope this isn't a valid style */
185235c4bbdfSmrg
185335c4bbdfSmrg    style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */
185435c4bbdfSmrg
185535c4bbdfSmrg    if (!(hint & ~HINT_SKIPTASKBAR))    /* No hints, default */
185635c4bbdfSmrg        style = style | WS_CAPTION | WS_SIZEBOX;
185735c4bbdfSmrg    else if (hint & HINT_NOFRAME)       /* No frame, no decorations */
185835c4bbdfSmrg        style = style & ~WS_CAPTION & ~WS_SIZEBOX;
185935c4bbdfSmrg    else
186035c4bbdfSmrg        style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) |
186135c4bbdfSmrg            ((hint & HINT_SIZEBOX) ? WS_SIZEBOX : 0) |
186235c4bbdfSmrg            ((hint & HINT_CAPTION) ? WS_CAPTION : 0);
186335c4bbdfSmrg
186435c4bbdfSmrg    if (hint & HINT_NOMAXIMIZE)
186535c4bbdfSmrg        style = style & ~WS_MAXIMIZEBOX;
186635c4bbdfSmrg
186735c4bbdfSmrg    if (hint & HINT_NOMINIMIZE)
186835c4bbdfSmrg        style = style & ~WS_MINIMIZEBOX;
186935c4bbdfSmrg
187035c4bbdfSmrg    if (hint & HINT_NOSYSMENU)
187135c4bbdfSmrg        style = style & ~WS_SYSMENU;
187235c4bbdfSmrg
187335c4bbdfSmrg    if (hint & HINT_SKIPTASKBAR)
187435c4bbdfSmrg        style = style & ~WS_MINIMIZEBOX;        /* window will become lost if minimized */
187535c4bbdfSmrg
187635c4bbdfSmrg    SetWindowLongPtr(hWnd, GWL_STYLE, style);
187735c4bbdfSmrg
187835c4bbdfSmrg    exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
187935c4bbdfSmrg    if (hint & HINT_SKIPTASKBAR)
188035c4bbdfSmrg        exStyle = (exStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW;
188135c4bbdfSmrg    else
188235c4bbdfSmrg        exStyle = (exStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW;
188335c4bbdfSmrg    SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle);
188435c4bbdfSmrg
188535c4bbdfSmrg    winDebug
188635c4bbdfSmrg        ("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n",
188735c4bbdfSmrg         iWindow, hint, style, exStyle);
18886747b715Smrg}
18896747b715Smrg
18906747b715Smrgvoid
189135c4bbdfSmrgwinUpdateWindowPosition(HWND hWnd, HWND * zstyle)
18926747b715Smrg{
189335c4bbdfSmrg    int iX, iY, iWidth, iHeight;
189435c4bbdfSmrg    int iDx, iDy;
189535c4bbdfSmrg    RECT rcNew;
189635c4bbdfSmrg    WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
189735c4bbdfSmrg    DrawablePtr pDraw = NULL;
189835c4bbdfSmrg
189935c4bbdfSmrg    if (!pWin)
190035c4bbdfSmrg        return;
190135c4bbdfSmrg    pDraw = &pWin->drawable;
190235c4bbdfSmrg    if (!pDraw)
190335c4bbdfSmrg        return;
190435c4bbdfSmrg
190535c4bbdfSmrg    /* Get the X and Y location of the X window */
190635c4bbdfSmrg    iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
190735c4bbdfSmrg    iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
190835c4bbdfSmrg
190935c4bbdfSmrg    /* Get the height and width of the X window */
191035c4bbdfSmrg    iWidth = pWin->drawable.width;
191135c4bbdfSmrg    iHeight = pWin->drawable.height;
191235c4bbdfSmrg
191335c4bbdfSmrg    /* Setup a rectangle with the X window position and size */
191435c4bbdfSmrg    SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
191535c4bbdfSmrg
191635c4bbdfSmrg    winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
191735c4bbdfSmrg             rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
191835c4bbdfSmrg
191935c4bbdfSmrg    AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
192035c4bbdfSmrg                       GetWindowLongPtr(hWnd, GWL_EXSTYLE));
192135c4bbdfSmrg
192235c4bbdfSmrg    /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
192335c4bbdfSmrg    if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
192435c4bbdfSmrg        iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
192535c4bbdfSmrg        rcNew.left += iDx;
192635c4bbdfSmrg        rcNew.right += iDx;
19276747b715Smrg    }
19286747b715Smrg
192935c4bbdfSmrg    if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
193035c4bbdfSmrg        iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
193135c4bbdfSmrg        rcNew.top += iDy;
193235c4bbdfSmrg        rcNew.bottom += iDy;
19336747b715Smrg    }
19346747b715Smrg
193535c4bbdfSmrg    winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
193635c4bbdfSmrg             rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
19376747b715Smrg
193835c4bbdfSmrg    /* Position the Windows window */
193935c4bbdfSmrg    SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
194035c4bbdfSmrg                 rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
19416747b715Smrg
19426747b715Smrg}
1943