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> 52ed6184dfSmrg#include <xcb/composite.h> 531b5d61b8Smrg 546747b715Smrg#include <X11/Xwindows.h> 5505b261ecSmrg 5605b261ecSmrg/* Local headers */ 571b5d61b8Smrg#include "X11/Xdefs.h" // for Bool type 5805b261ecSmrg#include "winwindow.h" 596747b715Smrg#include "winprefs.h" 606747b715Smrg#include "window.h" 616747b715Smrg#include "pixmapstr.h" 626747b715Smrg#include "windowstr.h" 6335c4bbdfSmrg#include "winglobals.h" 6435c4bbdfSmrg#include "windisplay.h" 651b5d61b8Smrg#include "winmultiwindowicons.h" 66ed6184dfSmrg#include "winauth.h" 676747b715Smrg 686747b715Smrg/* We need the native HWND atom for intWM, so for consistency use the 691b5d61b8Smrg same name as extWM does */ 706747b715Smrg#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND" 7105b261ecSmrg 7235c4bbdfSmrg#ifndef HOST_NAME_MAX 7335c4bbdfSmrg#define HOST_NAME_MAX 255 7435c4bbdfSmrg#endif 7535c4bbdfSmrg 7605b261ecSmrgextern void winDebug(const char *format, ...); 776747b715Smrgextern void winReshapeMultiWindow(WindowPtr pWin); 786747b715Smrgextern void winUpdateRgnMultiWindow(WindowPtr pWin); 7905b261ecSmrg 8005b261ecSmrg#ifndef CYGDEBUG 8105b261ecSmrg#define CYGDEBUG NO 8205b261ecSmrg#endif 8305b261ecSmrg 8405b261ecSmrg/* 8505b261ecSmrg * Constant defines 8605b261ecSmrg */ 8705b261ecSmrg 8805b261ecSmrg#define WIN_CONNECT_RETRIES 5 8905b261ecSmrg#define WIN_CONNECT_DELAY 5 9005b261ecSmrg#ifdef HAS_DEVWINDOWS 9135c4bbdfSmrg#define WIN_MSG_QUEUE_FNAME "/dev/windows" 9205b261ecSmrg#endif 9305b261ecSmrg 9405b261ecSmrg/* 9505b261ecSmrg * Local structures 9605b261ecSmrg */ 9705b261ecSmrg 9805b261ecSmrgtypedef struct _WMMsgNodeRec { 9935c4bbdfSmrg winWMMessageRec msg; 10035c4bbdfSmrg struct _WMMsgNodeRec *pNext; 10105b261ecSmrg} WMMsgNodeRec, *WMMsgNodePtr; 10205b261ecSmrg 10305b261ecSmrgtypedef struct _WMMsgQueueRec { 10435c4bbdfSmrg struct _WMMsgNodeRec *pHead; 10535c4bbdfSmrg struct _WMMsgNodeRec *pTail; 10635c4bbdfSmrg pthread_mutex_t pmMutex; 10735c4bbdfSmrg pthread_cond_t pcNotEmpty; 10805b261ecSmrg} WMMsgQueueRec, *WMMsgQueuePtr; 10905b261ecSmrg 11005b261ecSmrgtypedef struct _WMInfo { 1111b5d61b8Smrg xcb_connection_t *conn; 11235c4bbdfSmrg WMMsgQueueRec wmMsgQueue; 1131b5d61b8Smrg xcb_atom_t atmWmProtos; 1141b5d61b8Smrg xcb_atom_t atmWmDelete; 1151b5d61b8Smrg xcb_atom_t atmWmTakeFocus; 1161b5d61b8Smrg xcb_atom_t atmPrivMap; 1171b5d61b8Smrg xcb_atom_t atmUtf8String; 1181b5d61b8Smrg xcb_atom_t atmNetWmName; 119ed6184dfSmrg xcb_atom_t atmCurrentDesktop; 120ed6184dfSmrg xcb_atom_t atmNumberDesktops; 121ed6184dfSmrg xcb_atom_t atmDesktopNames; 1221b5d61b8Smrg xcb_ewmh_connection_t ewmh; 123ed6184dfSmrg Bool fCompositeWM; 12405b261ecSmrg} WMInfoRec, *WMInfoPtr; 12505b261ecSmrg 12605b261ecSmrgtypedef struct _WMProcArgRec { 12735c4bbdfSmrg DWORD dwScreen; 12835c4bbdfSmrg WMInfoPtr pWMInfo; 12935c4bbdfSmrg pthread_mutex_t *ppmServerStarted; 13005b261ecSmrg} WMProcArgRec, *WMProcArgPtr; 13105b261ecSmrg 13205b261ecSmrgtypedef struct _XMsgProcArgRec { 1331b5d61b8Smrg xcb_connection_t *conn; 13435c4bbdfSmrg DWORD dwScreen; 13535c4bbdfSmrg WMInfoPtr pWMInfo; 13635c4bbdfSmrg pthread_mutex_t *ppmServerStarted; 13735c4bbdfSmrg HWND hwndScreen; 13805b261ecSmrg} XMsgProcArgRec, *XMsgProcArgPtr; 13905b261ecSmrg 14005b261ecSmrg/* 14105b261ecSmrg * Prototypes for local functions 14205b261ecSmrg */ 14305b261ecSmrg 14405b261ecSmrgstatic void 14535c4bbdfSmrg PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode); 14605b261ecSmrg 14735c4bbdfSmrgstatic WMMsgNodePtr PopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo); 14805b261ecSmrg 14905b261ecSmrgstatic Bool 15035c4bbdfSmrg InitQueue(WMMsgQueuePtr pQueue); 15105b261ecSmrg 15205b261ecSmrgstatic void 1531b5d61b8Smrg GetWindowName(WMInfoPtr pWMInfo, xcb_window_t iWin, char **ppWindowName); 15405b261ecSmrg 1551b5d61b8Smrgstatic void 1561b5d61b8Smrg SendXMessage(xcb_connection_t *conn, xcb_window_t iWin, xcb_atom_t atmType, long nData); 15705b261ecSmrg 15805b261ecSmrgstatic void 1591b5d61b8Smrg UpdateName(WMInfoPtr pWMInfo, xcb_window_t iWindow); 16005b261ecSmrg 16135c4bbdfSmrgstatic void *winMultiWindowWMProc(void *pArg); 16205b261ecSmrg 16335c4bbdfSmrgstatic void *winMultiWindowXMsgProc(void *pArg); 16405b261ecSmrg 16505b261ecSmrgstatic void 16635c4bbdfSmrg winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg); 16705b261ecSmrg 16805b261ecSmrg#if 0 16905b261ecSmrgstatic void 1701b5d61b8Smrg PreserveWin32Stack(WMInfoPtr pWMInfo, xcb_window_t iWindow, UINT direction); 17105b261ecSmrg#endif 17205b261ecSmrg 17305b261ecSmrgstatic Bool 1741b5d61b8SmrgCheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen); 17505b261ecSmrg 1766747b715Smrgstatic void 1771b5d61b8Smrg winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle); 1786747b715Smrg 1796747b715Smrgvoid 18035c4bbdfSmrg winUpdateWindowPosition(HWND hWnd, HWND * zstyle); 18105b261ecSmrg 18205b261ecSmrg/* 18305b261ecSmrg * Local globals 18405b261ecSmrg */ 18505b261ecSmrg 18635c4bbdfSmrgstatic Bool g_shutdown = FALSE; 1871b5d61b8Smrg 1881b5d61b8Smrg/* 1891b5d61b8Smrg * Translate msg id to text, for debug purposes 1901b5d61b8Smrg */ 1911b5d61b8Smrg 1921b5d61b8Smrg#if CYGMULTIWINDOW_DEBUG 1931b5d61b8Smrgstatic const char * 1941b5d61b8SmrgMessageName(winWMMessagePtr msg) 1951b5d61b8Smrg{ 1961b5d61b8Smrg switch (msg->msg) 1971b5d61b8Smrg { 1981b5d61b8Smrg case WM_WM_MOVE: 1991b5d61b8Smrg return "WM_WM_MOVE"; 2001b5d61b8Smrg break; 2011b5d61b8Smrg case WM_WM_SIZE: 2021b5d61b8Smrg return "WM_WM_SIZE"; 2031b5d61b8Smrg break; 2041b5d61b8Smrg case WM_WM_RAISE: 2051b5d61b8Smrg return "WM_WM_RAISE"; 2061b5d61b8Smrg break; 2071b5d61b8Smrg case WM_WM_LOWER: 2081b5d61b8Smrg return "WM_WM_LOWER"; 2091b5d61b8Smrg break; 2101b5d61b8Smrg case WM_WM_UNMAP: 2111b5d61b8Smrg return "WM_WM_UNMAP"; 2121b5d61b8Smrg break; 2131b5d61b8Smrg case WM_WM_KILL: 2141b5d61b8Smrg return "WM_WM_KILL"; 2151b5d61b8Smrg break; 2161b5d61b8Smrg case WM_WM_ACTIVATE: 2171b5d61b8Smrg return "WM_WM_ACTIVATE"; 2181b5d61b8Smrg break; 2191b5d61b8Smrg case WM_WM_NAME_EVENT: 2201b5d61b8Smrg return "WM_WM_NAME_EVENT"; 2211b5d61b8Smrg break; 2221b5d61b8Smrg case WM_WM_ICON_EVENT: 2231b5d61b8Smrg return "WM_WM_ICON_EVENT"; 2241b5d61b8Smrg break; 2251b5d61b8Smrg case WM_WM_CHANGE_STATE: 2261b5d61b8Smrg return "WM_WM_CHANGE_STATE"; 2271b5d61b8Smrg break; 228ed6184dfSmrg case WM_WM_MAP_UNMANAGED: 229ed6184dfSmrg return "WM_WM_MAP_UNMANAGED"; 2301b5d61b8Smrg break; 231ed6184dfSmrg case WM_WM_MAP_MANAGED: 232ed6184dfSmrg return "WM_WM_MAP_MANAGED"; 2331b5d61b8Smrg break; 2341b5d61b8Smrg case WM_WM_HINTS_EVENT: 2351b5d61b8Smrg return "WM_WM_HINTS_EVENT"; 2361b5d61b8Smrg break; 2371b5d61b8Smrg default: 2381b5d61b8Smrg return "Unknown Message"; 2391b5d61b8Smrg break; 2401b5d61b8Smrg } 2411b5d61b8Smrg} 2421b5d61b8Smrg#endif 2431b5d61b8Smrg 24405b261ecSmrg 24505b261ecSmrg/* 24605b261ecSmrg * PushMessage - Push a message onto the queue 24705b261ecSmrg */ 24805b261ecSmrg 24905b261ecSmrgstatic void 25035c4bbdfSmrgPushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) 25105b261ecSmrg{ 25205b261ecSmrg 25335c4bbdfSmrg /* Lock the queue mutex */ 25435c4bbdfSmrg pthread_mutex_lock(&pQueue->pmMutex); 25505b261ecSmrg 25635c4bbdfSmrg pNode->pNext = NULL; 25735c4bbdfSmrg 25835c4bbdfSmrg if (pQueue->pTail != NULL) { 25935c4bbdfSmrg pQueue->pTail->pNext = pNode; 26005b261ecSmrg } 26135c4bbdfSmrg pQueue->pTail = pNode; 26205b261ecSmrg 26335c4bbdfSmrg if (pQueue->pHead == NULL) { 26435c4bbdfSmrg pQueue->pHead = pNode; 26535c4bbdfSmrg } 26605b261ecSmrg 26735c4bbdfSmrg /* Release the queue mutex */ 26835c4bbdfSmrg pthread_mutex_unlock(&pQueue->pmMutex); 26905b261ecSmrg 27035c4bbdfSmrg /* Signal that the queue is not empty */ 27135c4bbdfSmrg pthread_cond_signal(&pQueue->pcNotEmpty); 27205b261ecSmrg} 27305b261ecSmrg 27405b261ecSmrg/* 27505b261ecSmrg * PopMessage - Pop a message from the queue 27605b261ecSmrg */ 27705b261ecSmrg 27805b261ecSmrgstatic WMMsgNodePtr 27935c4bbdfSmrgPopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo) 28005b261ecSmrg{ 28135c4bbdfSmrg WMMsgNodePtr pNode; 28205b261ecSmrg 28335c4bbdfSmrg /* Lock the queue mutex */ 28435c4bbdfSmrg pthread_mutex_lock(&pQueue->pmMutex); 28505b261ecSmrg 28635c4bbdfSmrg /* Wait for --- */ 28735c4bbdfSmrg while (pQueue->pHead == NULL) { 28835c4bbdfSmrg pthread_cond_wait(&pQueue->pcNotEmpty, &pQueue->pmMutex); 28905b261ecSmrg } 29035c4bbdfSmrg 29135c4bbdfSmrg pNode = pQueue->pHead; 29235c4bbdfSmrg if (pQueue->pHead != NULL) { 29335c4bbdfSmrg pQueue->pHead = pQueue->pHead->pNext; 29405b261ecSmrg } 29505b261ecSmrg 29635c4bbdfSmrg if (pQueue->pTail == pNode) { 29735c4bbdfSmrg pQueue->pTail = NULL; 29805b261ecSmrg } 29905b261ecSmrg 30035c4bbdfSmrg /* Release the queue mutex */ 30135c4bbdfSmrg pthread_mutex_unlock(&pQueue->pmMutex); 30205b261ecSmrg 30335c4bbdfSmrg return pNode; 30435c4bbdfSmrg} 30505b261ecSmrg 30605b261ecSmrg#if 0 30705b261ecSmrg/* 30835c4bbdfSmrg * HaveMessage - 30905b261ecSmrg */ 31005b261ecSmrg 31105b261ecSmrgstatic Bool 3121b5d61b8SmrgHaveMessage(WMMsgQueuePtr pQueue, UINT msg, xcb_window_t iWindow) 31305b261ecSmrg{ 31435c4bbdfSmrg WMMsgNodePtr pNode; 31535c4bbdfSmrg 31635c4bbdfSmrg for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) { 31735c4bbdfSmrg if (pNode->msg.msg == msg && pNode->msg.iWindow == iWindow) 31835c4bbdfSmrg return True; 31905b261ecSmrg } 32035c4bbdfSmrg 32135c4bbdfSmrg return False; 32205b261ecSmrg} 32305b261ecSmrg#endif 32405b261ecSmrg 32505b261ecSmrg/* 32605b261ecSmrg * InitQueue - Initialize the Window Manager message queue 32705b261ecSmrg */ 32805b261ecSmrg 32905b261ecSmrgstatic 33035c4bbdfSmrg Bool 33135c4bbdfSmrgInitQueue(WMMsgQueuePtr pQueue) 33205b261ecSmrg{ 33335c4bbdfSmrg /* Check if the pQueue pointer is NULL */ 33435c4bbdfSmrg if (pQueue == NULL) { 33535c4bbdfSmrg ErrorF("InitQueue - pQueue is NULL. Exiting.\n"); 33635c4bbdfSmrg return FALSE; 33705b261ecSmrg } 33805b261ecSmrg 33935c4bbdfSmrg /* Set the head and tail to NULL */ 34035c4bbdfSmrg pQueue->pHead = NULL; 34135c4bbdfSmrg pQueue->pTail = NULL; 34205b261ecSmrg 34335c4bbdfSmrg winDebug("InitQueue - Calling pthread_mutex_init\n"); 34405b261ecSmrg 34535c4bbdfSmrg /* Create synchronization objects */ 34635c4bbdfSmrg pthread_mutex_init(&pQueue->pmMutex, NULL); 34705b261ecSmrg 34835c4bbdfSmrg winDebug("InitQueue - pthread_mutex_init returned\n"); 34935c4bbdfSmrg winDebug("InitQueue - Calling pthread_cond_init\n"); 35005b261ecSmrg 35135c4bbdfSmrg pthread_cond_init(&pQueue->pcNotEmpty, NULL); 35205b261ecSmrg 35335c4bbdfSmrg winDebug("InitQueue - pthread_cond_init returned\n"); 35405b261ecSmrg 35535c4bbdfSmrg return TRUE; 35605b261ecSmrg} 35705b261ecSmrg 35835c4bbdfSmrgstatic 35935c4bbdfSmrgchar * 3601b5d61b8SmrgXutf8TextPropertyToString(WMInfoPtr pWMInfo, xcb_icccm_get_text_property_reply_t *xtp) 36135c4bbdfSmrg{ 36235c4bbdfSmrg char *pszReturnData; 36335c4bbdfSmrg 3641b5d61b8Smrg if ((xtp->encoding == XCB_ATOM_STRING) || // Latin1 ISO 8859-1 3651b5d61b8Smrg (xtp->encoding == pWMInfo->atmUtf8String)) { // UTF-8 ISO 10646 3661b5d61b8Smrg pszReturnData = strndup(xtp->name, xtp->name_len); 36735c4bbdfSmrg } 36835c4bbdfSmrg else { 3691b5d61b8Smrg // Converting from COMPOUND_TEXT to UTF-8 properly is complex to 3701b5d61b8Smrg // implement, and not very much use unless you have an old 3711b5d61b8Smrg // application which isn't UTF-8 aware. 3721b5d61b8Smrg ErrorF("Xutf8TextPropertyToString: text encoding %d is not implemented\n", xtp->encoding); 3731b5d61b8Smrg pszReturnData = strdup(""); 37435c4bbdfSmrg } 37535c4bbdfSmrg 37635c4bbdfSmrg return pszReturnData; 37735c4bbdfSmrg} 37805b261ecSmrg 37905b261ecSmrg/* 38005b261ecSmrg * GetWindowName - Retrieve the title of an X Window 38105b261ecSmrg */ 38205b261ecSmrg 38305b261ecSmrgstatic void 3841b5d61b8SmrgGetWindowName(WMInfoPtr pWMInfo, xcb_window_t iWin, char **ppWindowName) 38505b261ecSmrg{ 3861b5d61b8Smrg xcb_connection_t *conn = pWMInfo->conn; 3871b5d61b8Smrg char *pszWindowName = NULL; 38835c4bbdfSmrg 38905b261ecSmrg#if CYGMULTIWINDOW_DEBUG 39035c4bbdfSmrg ErrorF("GetWindowName\n"); 39105b261ecSmrg#endif 39205b261ecSmrg 3931b5d61b8Smrg /* Try to get window name from _NET_WM_NAME */ 3941b5d61b8Smrg { 3951b5d61b8Smrg xcb_get_property_cookie_t cookie; 3961b5d61b8Smrg xcb_get_property_reply_t *reply; 3971b5d61b8Smrg 3981b5d61b8Smrg cookie = xcb_get_property(pWMInfo->conn, FALSE, iWin, 3991b5d61b8Smrg pWMInfo->atmNetWmName, 4001b5d61b8Smrg XCB_GET_PROPERTY_TYPE_ANY, 0, INT_MAX); 4011b5d61b8Smrg reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL); 4021b5d61b8Smrg if (reply && (reply->type != XCB_NONE)) { 4031b5d61b8Smrg pszWindowName = strndup(xcb_get_property_value(reply), 4041b5d61b8Smrg xcb_get_property_value_length(reply)); 4051b5d61b8Smrg free(reply); 4061b5d61b8Smrg } 40705b261ecSmrg } 40805b261ecSmrg 4091b5d61b8Smrg /* Otherwise, try to get window name from WM_NAME */ 4101b5d61b8Smrg if (!pszWindowName) 4111b5d61b8Smrg { 4121b5d61b8Smrg xcb_get_property_cookie_t cookie; 4131b5d61b8Smrg xcb_icccm_get_text_property_reply_t reply; 4141b5d61b8Smrg 4151b5d61b8Smrg cookie = xcb_icccm_get_wm_name(conn, iWin); 4161b5d61b8Smrg if (!xcb_icccm_get_wm_name_reply(conn, cookie, &reply, NULL)) { 4171b5d61b8Smrg ErrorF("GetWindowName - xcb_icccm_get_wm_name_reply failed. No name.\n"); 4181b5d61b8Smrg *ppWindowName = NULL; 4191b5d61b8Smrg return; 4201b5d61b8Smrg } 4211b5d61b8Smrg 4221b5d61b8Smrg pszWindowName = Xutf8TextPropertyToString(pWMInfo, &reply); 4231b5d61b8Smrg xcb_icccm_get_text_property_reply_wipe(&reply); 4241b5d61b8Smrg } 4251b5d61b8Smrg 4261b5d61b8Smrg /* return the window name, unless... */ 4271b5d61b8Smrg *ppWindowName = pszWindowName; 42835c4bbdfSmrg 42935c4bbdfSmrg if (g_fHostInTitle) { 4301b5d61b8Smrg xcb_get_property_cookie_t cookie; 4311b5d61b8Smrg xcb_icccm_get_text_property_reply_t reply; 4321b5d61b8Smrg 43335c4bbdfSmrg /* Try to get client machine name */ 4341b5d61b8Smrg cookie = xcb_icccm_get_wm_client_machine(conn, iWin); 4351b5d61b8Smrg if (xcb_icccm_get_wm_client_machine_reply(conn, cookie, &reply, NULL)) { 4361b5d61b8Smrg char *pszClientMachine; 4371b5d61b8Smrg char *pszClientHostname; 4381b5d61b8Smrg char *dot; 4391b5d61b8Smrg char hostname[HOST_NAME_MAX + 1]; 4401b5d61b8Smrg 4411b5d61b8Smrg pszClientMachine = Xutf8TextPropertyToString(pWMInfo, &reply); 4421b5d61b8Smrg xcb_icccm_get_text_property_reply_wipe(&reply); 4431b5d61b8Smrg 4441b5d61b8Smrg /* If client machine name looks like a FQDN, find the hostname */ 4451b5d61b8Smrg pszClientHostname = strdup(pszClientMachine); 4461b5d61b8Smrg dot = strchr(pszClientHostname, '.'); 4471b5d61b8Smrg if (dot) 4481b5d61b8Smrg *dot = '\0'; 44935c4bbdfSmrg 45035c4bbdfSmrg /* 4511b5d61b8Smrg If we have a client machine hostname 4521b5d61b8Smrg and it's not the local hostname 45335c4bbdfSmrg and it's not already in the window title... 45435c4bbdfSmrg */ 4551b5d61b8Smrg if (strlen(pszClientHostname) && 45635c4bbdfSmrg !gethostname(hostname, HOST_NAME_MAX + 1) && 4571b5d61b8Smrg strcmp(hostname, pszClientHostname) && 4581b5d61b8Smrg (strstr(pszWindowName, pszClientHostname) == 0)) { 45935c4bbdfSmrg /* ... add '@<clientmachine>' to end of window name */ 46035c4bbdfSmrg *ppWindowName = 46135c4bbdfSmrg malloc(strlen(pszWindowName) + 46235c4bbdfSmrg strlen(pszClientMachine) + 2); 46335c4bbdfSmrg strcpy(*ppWindowName, pszWindowName); 46435c4bbdfSmrg strcat(*ppWindowName, "@"); 46535c4bbdfSmrg strcat(*ppWindowName, pszClientMachine); 46635c4bbdfSmrg 46735c4bbdfSmrg free(pszWindowName); 46835c4bbdfSmrg } 4691b5d61b8Smrg 4701b5d61b8Smrg free(pszClientMachine); 4711b5d61b8Smrg free(pszClientHostname); 47235c4bbdfSmrg } 47335c4bbdfSmrg } 47405b261ecSmrg} 47505b261ecSmrg 47635c4bbdfSmrg/* 47735c4bbdfSmrg * Does the client support the specified WM_PROTOCOLS protocol? 47835c4bbdfSmrg */ 47935c4bbdfSmrg 48035c4bbdfSmrgstatic Bool 4811b5d61b8SmrgIsWmProtocolAvailable(WMInfoPtr pWMInfo, xcb_window_t iWindow, xcb_atom_t atmProtocol) 48235c4bbdfSmrg{ 4831b5d61b8Smrg int i, found = 0; 4841b5d61b8Smrg xcb_get_property_cookie_t cookie; 4851b5d61b8Smrg xcb_icccm_get_wm_protocols_reply_t reply; 4861b5d61b8Smrg xcb_connection_t *conn = pWMInfo->conn; 4871b5d61b8Smrg 4881b5d61b8Smrg cookie = xcb_icccm_get_wm_protocols(conn, iWindow, pWMInfo->ewmh.WM_PROTOCOLS); 4891b5d61b8Smrg if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &reply, NULL)) { 4901b5d61b8Smrg for (i = 0; i < reply.atoms_len; ++i) 4911b5d61b8Smrg if (reply.atoms[i] == atmProtocol) { 4921b5d61b8Smrg ++found; 4931b5d61b8Smrg break; 4941b5d61b8Smrg } 4951b5d61b8Smrg xcb_icccm_get_wm_protocols_reply_wipe(&reply); 49635c4bbdfSmrg } 49735c4bbdfSmrg 49835c4bbdfSmrg return found > 0; 49935c4bbdfSmrg} 50005b261ecSmrg 50105b261ecSmrg/* 50205b261ecSmrg * Send a message to the X server from the WM thread 50305b261ecSmrg */ 50405b261ecSmrg 5051b5d61b8Smrgstatic void 5061b5d61b8SmrgSendXMessage(xcb_connection_t *conn, xcb_window_t iWin, xcb_atom_t atmType, long nData) 50705b261ecSmrg{ 5081b5d61b8Smrg xcb_client_message_event_t e; 50935c4bbdfSmrg 51035c4bbdfSmrg /* Prepare the X event structure */ 5111b5d61b8Smrg memset(&e, 0, sizeof(e)); 5121b5d61b8Smrg e.response_type = XCB_CLIENT_MESSAGE; 5131b5d61b8Smrg e.window = iWin; 5141b5d61b8Smrg e.type = atmType; 5151b5d61b8Smrg e.format = 32; 5161b5d61b8Smrg e.data.data32[0] = nData; 5171b5d61b8Smrg e.data.data32[1] = XCB_CURRENT_TIME; 51835c4bbdfSmrg 51935c4bbdfSmrg /* Send the event to X */ 5201b5d61b8Smrg xcb_send_event(conn, FALSE, iWin, XCB_EVENT_MASK_NO_EVENT, (const char *)&e); 52105b261ecSmrg} 52205b261ecSmrg 52335c4bbdfSmrg/* 52435c4bbdfSmrg * See if we can get the stored HWND for this window... 52535c4bbdfSmrg */ 52635c4bbdfSmrgstatic HWND 5271b5d61b8SmrggetHwnd(WMInfoPtr pWMInfo, xcb_window_t iWindow) 52835c4bbdfSmrg{ 5291b5d61b8Smrg HWND hWnd = NULL; 5301b5d61b8Smrg xcb_get_property_cookie_t cookie; 5311b5d61b8Smrg xcb_get_property_reply_t *reply; 5321b5d61b8Smrg 5331b5d61b8Smrg cookie = xcb_get_property(pWMInfo->conn, FALSE, iWindow, pWMInfo->atmPrivMap, 5341b5d61b8Smrg XCB_ATOM_INTEGER, 0L, sizeof(HWND)/4L); 5351b5d61b8Smrg reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL); 5361b5d61b8Smrg 5371b5d61b8Smrg if (reply) { 5381b5d61b8Smrg int length = xcb_get_property_value_length(reply); 5391b5d61b8Smrg HWND *value = xcb_get_property_value(reply); 5401b5d61b8Smrg 5411b5d61b8Smrg if (value && (length == sizeof(HWND))) { 5421b5d61b8Smrg hWnd = *value; 54335c4bbdfSmrg } 5441b5d61b8Smrg free(reply); 54535c4bbdfSmrg } 54635c4bbdfSmrg 54735c4bbdfSmrg /* Some sanity checks */ 54835c4bbdfSmrg if (!hWnd) 54935c4bbdfSmrg return NULL; 55035c4bbdfSmrg if (!IsWindow(hWnd)) 55135c4bbdfSmrg return NULL; 55235c4bbdfSmrg 55335c4bbdfSmrg return hWnd; 55435c4bbdfSmrg} 55505b261ecSmrg 5561b5d61b8Smrg/* 5571b5d61b8Smrg * Helper function to check for override-redirect 5581b5d61b8Smrg */ 5591b5d61b8Smrgstatic Bool 5601b5d61b8SmrgIsOverrideRedirect(xcb_connection_t *conn, xcb_window_t iWin) 5611b5d61b8Smrg{ 5621b5d61b8Smrg Bool result = FALSE; 5631b5d61b8Smrg xcb_get_window_attributes_reply_t *reply; 5641b5d61b8Smrg xcb_get_window_attributes_cookie_t cookie; 5651b5d61b8Smrg 5661b5d61b8Smrg cookie = xcb_get_window_attributes(conn, iWin); 5671b5d61b8Smrg reply = xcb_get_window_attributes_reply(conn, cookie, NULL); 5681b5d61b8Smrg if (reply) { 5691b5d61b8Smrg result = (reply->override_redirect != 0); 5701b5d61b8Smrg free(reply); 5711b5d61b8Smrg } 5721b5d61b8Smrg else { 5731b5d61b8Smrg ErrorF("IsOverrideRedirect: Failed to get window attributes\n"); 5741b5d61b8Smrg } 5751b5d61b8Smrg 5761b5d61b8Smrg return result; 5771b5d61b8Smrg} 5781b5d61b8Smrg 5791b5d61b8Smrg/* 5801b5d61b8Smrg * Helper function to get class and window names 5811b5d61b8Smrg*/ 5821b5d61b8Smrgstatic void 5831b5d61b8SmrgGetClassNames(WMInfoPtr pWMInfo, xcb_window_t iWindow, char **res_name, 5841b5d61b8Smrg char **res_class, char **window_name) 5851b5d61b8Smrg{ 5861b5d61b8Smrg xcb_get_property_cookie_t cookie1; 5871b5d61b8Smrg xcb_icccm_get_wm_class_reply_t reply1; 5881b5d61b8Smrg xcb_get_property_cookie_t cookie2; 5891b5d61b8Smrg xcb_icccm_get_text_property_reply_t reply2; 5901b5d61b8Smrg 5911b5d61b8Smrg cookie1 = xcb_icccm_get_wm_class(pWMInfo->conn, iWindow); 5921b5d61b8Smrg if (xcb_icccm_get_wm_class_reply(pWMInfo->conn, cookie1, &reply1, 5931b5d61b8Smrg NULL)) { 5941b5d61b8Smrg *res_name = strdup(reply1.instance_name); 5951b5d61b8Smrg *res_class = strdup(reply1.class_name); 5961b5d61b8Smrg xcb_icccm_get_wm_class_reply_wipe(&reply1); 5971b5d61b8Smrg } 5981b5d61b8Smrg else { 5991b5d61b8Smrg *res_name = strdup(""); 6001b5d61b8Smrg *res_class = strdup(""); 6011b5d61b8Smrg } 6021b5d61b8Smrg 6031b5d61b8Smrg cookie2 = xcb_icccm_get_wm_name(pWMInfo->conn, iWindow); 6041b5d61b8Smrg if (xcb_icccm_get_wm_name_reply(pWMInfo->conn, cookie2, &reply2, NULL)) { 6051b5d61b8Smrg *window_name = strndup(reply2.name, reply2.name_len); 6061b5d61b8Smrg xcb_icccm_get_text_property_reply_wipe(&reply2); 6071b5d61b8Smrg } 6081b5d61b8Smrg else { 6091b5d61b8Smrg *window_name = strdup(""); 6101b5d61b8Smrg } 6111b5d61b8Smrg} 6121b5d61b8Smrg 61305b261ecSmrg/* 61405b261ecSmrg * Updates the name of a HWND according to its X WM_NAME property 61505b261ecSmrg */ 61605b261ecSmrg 61705b261ecSmrgstatic void 6181b5d61b8SmrgUpdateName(WMInfoPtr pWMInfo, xcb_window_t iWindow) 61905b261ecSmrg{ 62035c4bbdfSmrg HWND hWnd; 62135c4bbdfSmrg 62235c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 62335c4bbdfSmrg if (!hWnd) 62435c4bbdfSmrg return; 62535c4bbdfSmrg 62635c4bbdfSmrg /* If window isn't override-redirect */ 6271b5d61b8Smrg if (!IsOverrideRedirect(pWMInfo->conn, iWindow)) { 62835c4bbdfSmrg char *pszWindowName; 62935c4bbdfSmrg 63035c4bbdfSmrg /* Get the X windows window name */ 6311b5d61b8Smrg GetWindowName(pWMInfo, iWindow, &pszWindowName); 63235c4bbdfSmrg 63335c4bbdfSmrg if (pszWindowName) { 63435c4bbdfSmrg /* Convert from UTF-8 to wide char */ 63535c4bbdfSmrg int iLen = 63635c4bbdfSmrg MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, NULL, 0); 63735c4bbdfSmrg wchar_t *pwszWideWindowName = 63835c4bbdfSmrg malloc(sizeof(wchar_t)*(iLen + 1)); 63935c4bbdfSmrg MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, 64035c4bbdfSmrg pwszWideWindowName, iLen); 64135c4bbdfSmrg 64235c4bbdfSmrg /* Set the Windows window name */ 64335c4bbdfSmrg SetWindowTextW(hWnd, pwszWideWindowName); 64435c4bbdfSmrg 64535c4bbdfSmrg free(pwszWideWindowName); 64635c4bbdfSmrg free(pszWindowName); 64735c4bbdfSmrg } 64805b261ecSmrg } 64935c4bbdfSmrg} 65035c4bbdfSmrg 65135c4bbdfSmrg/* 65235c4bbdfSmrg * Updates the icon of a HWND according to its X icon properties 65335c4bbdfSmrg */ 65435c4bbdfSmrg 65535c4bbdfSmrgstatic void 6561b5d61b8SmrgUpdateIcon(WMInfoPtr pWMInfo, xcb_window_t iWindow) 65735c4bbdfSmrg{ 65835c4bbdfSmrg HWND hWnd; 65935c4bbdfSmrg HICON hIconNew = NULL; 66035c4bbdfSmrg 66135c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 66235c4bbdfSmrg if (!hWnd) 66335c4bbdfSmrg return; 66435c4bbdfSmrg 66535c4bbdfSmrg /* If window isn't override-redirect */ 6661b5d61b8Smrg if (!IsOverrideRedirect(pWMInfo->conn, iWindow)) { 66735c4bbdfSmrg char *window_name = 0; 6681b5d61b8Smrg char *res_name = 0; 6691b5d61b8Smrg char *res_class = 0; 67035c4bbdfSmrg 6711b5d61b8Smrg GetClassNames(pWMInfo, iWindow, &res_name, &res_class, &window_name); 67235c4bbdfSmrg 6731b5d61b8Smrg hIconNew = winOverrideIcon(res_name, res_class, window_name); 67435c4bbdfSmrg 6751b5d61b8Smrg free(res_name); 6761b5d61b8Smrg free(res_class); 6771b5d61b8Smrg free(window_name); 6781b5d61b8Smrg winUpdateIcon(hWnd, pWMInfo->conn, iWindow, hIconNew); 67905b261ecSmrg } 68005b261ecSmrg} 68105b261ecSmrg 68235c4bbdfSmrg/* 68335c4bbdfSmrg * Updates the style of a HWND according to its X style properties 68435c4bbdfSmrg */ 68535c4bbdfSmrg 68635c4bbdfSmrgstatic void 6871b5d61b8SmrgUpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow) 68835c4bbdfSmrg{ 68935c4bbdfSmrg HWND hWnd; 69035c4bbdfSmrg HWND zstyle = HWND_NOTOPMOST; 69135c4bbdfSmrg UINT flags; 69235c4bbdfSmrg 69335c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 69435c4bbdfSmrg if (!hWnd) 69535c4bbdfSmrg return; 69635c4bbdfSmrg 69735c4bbdfSmrg /* Determine the Window style, which determines borders and clipping region... */ 6981b5d61b8Smrg winApplyHints(pWMInfo, iWindow, hWnd, &zstyle); 69935c4bbdfSmrg winUpdateWindowPosition(hWnd, &zstyle); 70035c4bbdfSmrg 701ed6184dfSmrg /* Apply the updated window style, without changing its show or activation state */ 70235c4bbdfSmrg flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; 70335c4bbdfSmrg if (zstyle == HWND_NOTOPMOST) 70435c4bbdfSmrg flags |= SWP_NOZORDER | SWP_NOOWNERZORDER; 70535c4bbdfSmrg SetWindowPos(hWnd, NULL, 0, 0, 0, 0, flags); 70635c4bbdfSmrg 70735c4bbdfSmrg /* 70835c4bbdfSmrg Use the WS_EX_TOOLWINDOW style to remove window from Alt-Tab window switcher 70935c4bbdfSmrg 71035c4bbdfSmrg According to MSDN, this is supposed to remove the window from the taskbar as well, 71135c4bbdfSmrg if we SW_HIDE before changing the style followed by SW_SHOW afterwards. 71235c4bbdfSmrg 71335c4bbdfSmrg But that doesn't seem to work reliably, and causes the window to flicker, so use 71435c4bbdfSmrg the iTaskbarList interface to tell the taskbar to show or hide this window. 71535c4bbdfSmrg */ 71635c4bbdfSmrg winShowWindowOnTaskbar(hWnd, 71735c4bbdfSmrg (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & 71835c4bbdfSmrg WS_EX_APPWINDOW) ? TRUE : FALSE); 71935c4bbdfSmrg} 72005b261ecSmrg 7211b5d61b8Smrg/* 7221b5d61b8Smrg * Updates the state of a HWND 7231b5d61b8Smrg * (only minimization supported at the moment) 7241b5d61b8Smrg */ 7251b5d61b8Smrg 7261b5d61b8Smrgstatic void 7271b5d61b8SmrgUpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow) 7281b5d61b8Smrg{ 7291b5d61b8Smrg HWND hWnd; 7301b5d61b8Smrg 7311b5d61b8Smrg winDebug("UpdateState: iWindow 0x%08x\n", (int)iWindow); 7321b5d61b8Smrg 7331b5d61b8Smrg hWnd = getHwnd(pWMInfo, iWindow); 7341b5d61b8Smrg if (!hWnd) 7351b5d61b8Smrg return; 7361b5d61b8Smrg 7371b5d61b8Smrg ShowWindow(hWnd, SW_MINIMIZE); 7381b5d61b8Smrg} 7391b5d61b8Smrg 74005b261ecSmrg#if 0 74105b261ecSmrg/* 74205b261ecSmrg * Fix up any differences between the X11 and Win32 window stacks 74305b261ecSmrg * starting at the window passed in 74405b261ecSmrg */ 74505b261ecSmrgstatic void 7461b5d61b8SmrgPreserveWin32Stack(WMInfoPtr pWMInfo, xcb_window_t iWindow, UINT direction) 74705b261ecSmrg{ 74835c4bbdfSmrg HWND hWnd; 74935c4bbdfSmrg DWORD myWinProcID, winProcID; 7501b5d61b8Smrg xcb_window_t xWindow; 75135c4bbdfSmrg WINDOWPLACEMENT wndPlace; 75235c4bbdfSmrg 75335c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 75435c4bbdfSmrg if (!hWnd) 75535c4bbdfSmrg return; 75635c4bbdfSmrg 75735c4bbdfSmrg GetWindowThreadProcessId(hWnd, &myWinProcID); 75805b261ecSmrg hWnd = GetNextWindow(hWnd, direction); 75905b261ecSmrg 76035c4bbdfSmrg while (hWnd) { 76135c4bbdfSmrg GetWindowThreadProcessId(hWnd, &winProcID); 76235c4bbdfSmrg if (winProcID == myWinProcID) { 76335c4bbdfSmrg wndPlace.length = sizeof(WINDOWPLACEMENT); 76435c4bbdfSmrg GetWindowPlacement(hWnd, &wndPlace); 76535c4bbdfSmrg if (!(wndPlace.showCmd == SW_HIDE || 76635c4bbdfSmrg wndPlace.showCmd == SW_MINIMIZE)) { 76735c4bbdfSmrg xWindow = (Window) GetProp(hWnd, WIN_WID_PROP); 76835c4bbdfSmrg if (xWindow) { 76935c4bbdfSmrg if (direction == GW_HWNDPREV) 77035c4bbdfSmrg XRaiseWindow(pWMInfo->pDisplay, xWindow); 77135c4bbdfSmrg else 77235c4bbdfSmrg XLowerWindow(pWMInfo->pDisplay, xWindow); 77335c4bbdfSmrg } 77435c4bbdfSmrg } 77535c4bbdfSmrg } 77635c4bbdfSmrg hWnd = GetNextWindow(hWnd, direction); 77735c4bbdfSmrg } 77835c4bbdfSmrg} 77935c4bbdfSmrg#endif /* PreserveWin32Stack */ 78005b261ecSmrg 78105b261ecSmrg/* 78205b261ecSmrg * winMultiWindowWMProc 78305b261ecSmrg */ 78405b261ecSmrg 78505b261ecSmrgstatic void * 78635c4bbdfSmrgwinMultiWindowWMProc(void *pArg) 78705b261ecSmrg{ 78835c4bbdfSmrg WMProcArgPtr pProcArg = (WMProcArgPtr) pArg; 78935c4bbdfSmrg WMInfoPtr pWMInfo = pProcArg->pWMInfo; 79035c4bbdfSmrg 79135c4bbdfSmrg /* Initialize the Window Manager */ 79235c4bbdfSmrg winInitMultiWindowWM(pWMInfo, pProcArg); 79335c4bbdfSmrg 79405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 79535c4bbdfSmrg ErrorF("winMultiWindowWMProc ()\n"); 79605b261ecSmrg#endif 79705b261ecSmrg 79835c4bbdfSmrg /* Loop until we explicitly break out */ 79935c4bbdfSmrg for (;;) { 80035c4bbdfSmrg WMMsgNodePtr pNode; 80135c4bbdfSmrg 80235c4bbdfSmrg /* Pop a message off of our queue */ 80335c4bbdfSmrg pNode = PopMessage(&pWMInfo->wmMsgQueue, pWMInfo); 80435c4bbdfSmrg if (pNode == NULL) { 80535c4bbdfSmrg /* Bail if PopMessage returns without a message */ 80635c4bbdfSmrg /* NOTE: Remember that PopMessage is a blocking function. */ 80735c4bbdfSmrg ErrorF("winMultiWindowWMProc - Queue is Empty? Exiting.\n"); 80835c4bbdfSmrg pthread_exit(NULL); 80935c4bbdfSmrg } 81005b261ecSmrg 81105b261ecSmrg#if CYGMULTIWINDOW_DEBUG 8121b5d61b8Smrg ErrorF("winMultiWindowWMProc - MSG: %s (%d) ID: %d\n", 8131b5d61b8Smrg MessageName(&(pNode->msg)), (int)pNode->msg.msg, (int)pNode->msg.dwID); 81405b261ecSmrg#endif 81505b261ecSmrg 81635c4bbdfSmrg /* Branch on the message type */ 81735c4bbdfSmrg switch (pNode->msg.msg) { 81805b261ecSmrg#if 0 81935c4bbdfSmrg case WM_WM_MOVE: 82035c4bbdfSmrg break; 82105b261ecSmrg 82235c4bbdfSmrg case WM_WM_SIZE: 82335c4bbdfSmrg break; 82405b261ecSmrg#endif 82505b261ecSmrg 82635c4bbdfSmrg case WM_WM_RAISE: 82735c4bbdfSmrg /* Raise the window */ 8281b5d61b8Smrg { 8291b5d61b8Smrg const static uint32_t values[] = { XCB_STACK_MODE_ABOVE }; 8301b5d61b8Smrg xcb_configure_window(pWMInfo->conn, pNode->msg.iWindow, 8311b5d61b8Smrg XCB_CONFIG_WINDOW_STACK_MODE, values); 8321b5d61b8Smrg } 8331b5d61b8Smrg 83405b261ecSmrg#if 0 83535c4bbdfSmrg PreserveWin32Stack(pWMInfo, pNode->msg.iWindow, GW_HWNDPREV); 83605b261ecSmrg#endif 83735c4bbdfSmrg break; 83805b261ecSmrg 83935c4bbdfSmrg case WM_WM_LOWER: 84035c4bbdfSmrg /* Lower the window */ 8411b5d61b8Smrg { 8421b5d61b8Smrg const static uint32_t values[] = { XCB_STACK_MODE_BELOW }; 8431b5d61b8Smrg xcb_configure_window(pWMInfo->conn, pNode->msg.iWindow, 8441b5d61b8Smrg XCB_CONFIG_WINDOW_STACK_MODE, values); 8451b5d61b8Smrg } 84635c4bbdfSmrg break; 84705b261ecSmrg 848ed6184dfSmrg case WM_WM_MAP_UNMANAGED: 84935c4bbdfSmrg /* Put a note as to the HWND associated with this Window */ 8501b5d61b8Smrg xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, 8511b5d61b8Smrg pNode->msg.iWindow, pWMInfo->atmPrivMap, 8521b5d61b8Smrg XCB_ATOM_INTEGER, 32, 8531b5d61b8Smrg sizeof(HWND)/4, &(pNode->msg.hwndWindow)); 85435c4bbdfSmrg 85535c4bbdfSmrg break; 85635c4bbdfSmrg 857ed6184dfSmrg case WM_WM_MAP_MANAGED: 85835c4bbdfSmrg /* Put a note as to the HWND associated with this Window */ 8591b5d61b8Smrg xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, 8601b5d61b8Smrg pNode->msg.iWindow, pWMInfo->atmPrivMap, 8611b5d61b8Smrg XCB_ATOM_INTEGER, 32, 8621b5d61b8Smrg sizeof(HWND)/4, &(pNode->msg.hwndWindow)); 8631b5d61b8Smrg 86435c4bbdfSmrg UpdateName(pWMInfo, pNode->msg.iWindow); 86535c4bbdfSmrg UpdateIcon(pWMInfo, pNode->msg.iWindow); 86635c4bbdfSmrg UpdateStyle(pWMInfo, pNode->msg.iWindow); 86735c4bbdfSmrg 86835c4bbdfSmrg 86935c4bbdfSmrg /* Reshape */ 87035c4bbdfSmrg { 87135c4bbdfSmrg WindowPtr pWin = 87235c4bbdfSmrg GetProp(pNode->msg.hwndWindow, WIN_WINDOW_PROP); 87335c4bbdfSmrg if (pWin) { 87435c4bbdfSmrg winReshapeMultiWindow(pWin); 87535c4bbdfSmrg winUpdateRgnMultiWindow(pWin); 87635c4bbdfSmrg } 87735c4bbdfSmrg } 87835c4bbdfSmrg 87935c4bbdfSmrg break; 88035c4bbdfSmrg 88135c4bbdfSmrg case WM_WM_UNMAP: 88205b261ecSmrg 88335c4bbdfSmrg /* Unmap the window */ 8841b5d61b8Smrg xcb_unmap_window(pWMInfo->conn, pNode->msg.iWindow); 88535c4bbdfSmrg break; 88635c4bbdfSmrg 88735c4bbdfSmrg case WM_WM_KILL: 88835c4bbdfSmrg { 88935c4bbdfSmrg /* --- */ 8901b5d61b8Smrg if (IsWmProtocolAvailable(pWMInfo, 89135c4bbdfSmrg pNode->msg.iWindow, 89235c4bbdfSmrg pWMInfo->atmWmDelete)) 8931b5d61b8Smrg SendXMessage(pWMInfo->conn, 89435c4bbdfSmrg pNode->msg.iWindow, 89535c4bbdfSmrg pWMInfo->atmWmProtos, pWMInfo->atmWmDelete); 89635c4bbdfSmrg else 8971b5d61b8Smrg xcb_kill_client(pWMInfo->conn, pNode->msg.iWindow); 89835c4bbdfSmrg } 89935c4bbdfSmrg break; 90035c4bbdfSmrg 90135c4bbdfSmrg case WM_WM_ACTIVATE: 90235c4bbdfSmrg /* Set the input focus */ 90335c4bbdfSmrg 90435c4bbdfSmrg /* 90535c4bbdfSmrg ICCCM 4.1.7 is pretty opaque, but it appears that the rules are 90635c4bbdfSmrg actually quite simple: 90735c4bbdfSmrg -- the WM_HINTS input field determines whether the WM should call 90835c4bbdfSmrg XSetInputFocus() 90935c4bbdfSmrg -- independently, the WM_TAKE_FOCUS protocol determines whether 91035c4bbdfSmrg the WM should send a WM_TAKE_FOCUS ClientMessage. 91135c4bbdfSmrg */ 91235c4bbdfSmrg { 91335c4bbdfSmrg Bool neverFocus = FALSE; 9141b5d61b8Smrg xcb_get_property_cookie_t cookie; 9151b5d61b8Smrg xcb_icccm_wm_hints_t hints; 9161b5d61b8Smrg 9171b5d61b8Smrg cookie = xcb_icccm_get_wm_hints(pWMInfo->conn, pNode->msg.iWindow); 9181b5d61b8Smrg if (xcb_icccm_get_wm_hints_reply(pWMInfo->conn, cookie, &hints, 9191b5d61b8Smrg NULL)) { 9201b5d61b8Smrg if (hints.flags & XCB_ICCCM_WM_HINT_INPUT) 9211b5d61b8Smrg neverFocus = !hints.input; 92235c4bbdfSmrg } 92335c4bbdfSmrg 92435c4bbdfSmrg if (!neverFocus) 9251b5d61b8Smrg xcb_set_input_focus(pWMInfo->conn, XCB_INPUT_FOCUS_POINTER_ROOT, 9261b5d61b8Smrg pNode->msg.iWindow, XCB_CURRENT_TIME); 92735c4bbdfSmrg 9281b5d61b8Smrg if (IsWmProtocolAvailable(pWMInfo, 92935c4bbdfSmrg pNode->msg.iWindow, 93035c4bbdfSmrg pWMInfo->atmWmTakeFocus)) 9311b5d61b8Smrg SendXMessage(pWMInfo->conn, 93235c4bbdfSmrg pNode->msg.iWindow, 93335c4bbdfSmrg pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus); 93435c4bbdfSmrg 93535c4bbdfSmrg } 93635c4bbdfSmrg break; 93735c4bbdfSmrg 93835c4bbdfSmrg case WM_WM_NAME_EVENT: 93935c4bbdfSmrg UpdateName(pWMInfo, pNode->msg.iWindow); 94035c4bbdfSmrg break; 94135c4bbdfSmrg 94235c4bbdfSmrg case WM_WM_ICON_EVENT: 94335c4bbdfSmrg UpdateIcon(pWMInfo, pNode->msg.iWindow); 94435c4bbdfSmrg break; 94535c4bbdfSmrg 94635c4bbdfSmrg case WM_WM_HINTS_EVENT: 94735c4bbdfSmrg { 94835c4bbdfSmrg /* Don't do anything if this is an override-redirect window */ 9491b5d61b8Smrg if (IsOverrideRedirect(pWMInfo->conn, pNode->msg.iWindow)) 95035c4bbdfSmrg break; 95135c4bbdfSmrg 95235c4bbdfSmrg UpdateStyle(pWMInfo, pNode->msg.iWindow); 95335c4bbdfSmrg } 95435c4bbdfSmrg break; 95535c4bbdfSmrg 95635c4bbdfSmrg case WM_WM_CHANGE_STATE: 9571b5d61b8Smrg UpdateState(pWMInfo, pNode->msg.iWindow); 95835c4bbdfSmrg break; 95935c4bbdfSmrg 96035c4bbdfSmrg default: 96135c4bbdfSmrg ErrorF("winMultiWindowWMProc - Unknown Message. Exiting.\n"); 96235c4bbdfSmrg pthread_exit(NULL); 96335c4bbdfSmrg break; 96435c4bbdfSmrg } 96535c4bbdfSmrg 96635c4bbdfSmrg /* Free the retrieved message */ 96735c4bbdfSmrg free(pNode); 96835c4bbdfSmrg 96935c4bbdfSmrg /* Flush any pending events on our display */ 9701b5d61b8Smrg xcb_flush(pWMInfo->conn); 9711b5d61b8Smrg 9721b5d61b8Smrg /* This is just laziness rather than making sure we used _checked everywhere */ 9731b5d61b8Smrg { 9741b5d61b8Smrg xcb_generic_event_t *event = xcb_poll_for_event(pWMInfo->conn); 9751b5d61b8Smrg if (event) { 9761b5d61b8Smrg if ((event->response_type & ~0x80) == 0) { 9771b5d61b8Smrg xcb_generic_error_t *err = (xcb_generic_error_t *)event; 9781b5d61b8Smrg ErrorF("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, " 9791b5d61b8Smrg "Major opcode: %i, Minor opcode: %i\n", 9801b5d61b8Smrg err->error_code, err->resource_id, 9811b5d61b8Smrg err->major_code, err->minor_code); 9821b5d61b8Smrg } 9831b5d61b8Smrg } 9841b5d61b8Smrg } 9851b5d61b8Smrg 9861b5d61b8Smrg /* I/O errors etc. */ 9871b5d61b8Smrg { 9881b5d61b8Smrg int e = xcb_connection_has_error(pWMInfo->conn); 9891b5d61b8Smrg if (e) { 9901b5d61b8Smrg ErrorF("winMultiWindowWMProc - Fatal error %d on xcb connection\n", e); 9911b5d61b8Smrg break; 9921b5d61b8Smrg } 9931b5d61b8Smrg } 99405b261ecSmrg } 99505b261ecSmrg 99635c4bbdfSmrg /* Free the condition variable */ 99735c4bbdfSmrg pthread_cond_destroy(&pWMInfo->wmMsgQueue.pcNotEmpty); 99835c4bbdfSmrg 99935c4bbdfSmrg /* Free the mutex variable */ 100035c4bbdfSmrg pthread_mutex_destroy(&pWMInfo->wmMsgQueue.pmMutex); 100135c4bbdfSmrg 100235c4bbdfSmrg /* Free the passed-in argument */ 100335c4bbdfSmrg free(pProcArg); 100435c4bbdfSmrg 100505b261ecSmrg#if CYGMULTIWINDOW_DEBUG 100635c4bbdfSmrg ErrorF("-winMultiWindowWMProc ()\n"); 100705b261ecSmrg#endif 100835c4bbdfSmrg return NULL; 100905b261ecSmrg} 101005b261ecSmrg 10111b5d61b8Smrgstatic xcb_atom_t 10121b5d61b8Smrgintern_atom(xcb_connection_t *conn, const char *atomName) 10131b5d61b8Smrg{ 10141b5d61b8Smrg xcb_intern_atom_reply_t *atom_reply; 10151b5d61b8Smrg xcb_intern_atom_cookie_t atom_cookie; 10161b5d61b8Smrg xcb_atom_t atom = XCB_ATOM_NONE; 10171b5d61b8Smrg 10181b5d61b8Smrg atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName); 10191b5d61b8Smrg atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL); 10201b5d61b8Smrg if (atom_reply) { 10211b5d61b8Smrg atom = atom_reply->atom; 10221b5d61b8Smrg free(atom_reply); 10231b5d61b8Smrg } 10241b5d61b8Smrg return atom; 10251b5d61b8Smrg} 10261b5d61b8Smrg 102705b261ecSmrg/* 102805b261ecSmrg * X message procedure 102905b261ecSmrg */ 103005b261ecSmrg 103105b261ecSmrgstatic void * 103235c4bbdfSmrgwinMultiWindowXMsgProc(void *pArg) 103305b261ecSmrg{ 103435c4bbdfSmrg winWMMessageRec msg; 103535c4bbdfSmrg XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg; 103635c4bbdfSmrg char pszDisplay[512]; 103735c4bbdfSmrg int iRetries; 10381b5d61b8Smrg xcb_atom_t atmWmName; 10391b5d61b8Smrg xcb_atom_t atmNetWmName; 10401b5d61b8Smrg xcb_atom_t atmWmHints; 10411b5d61b8Smrg xcb_atom_t atmWmChange; 10421b5d61b8Smrg xcb_atom_t atmNetWmIcon; 10431b5d61b8Smrg xcb_atom_t atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints; 104435c4bbdfSmrg int iReturn; 10451b5d61b8Smrg xcb_auth_info_t *auth_info; 1046ed6184dfSmrg xcb_screen_t *root_screen; 1047ed6184dfSmrg xcb_window_t root_window_id; 104835c4bbdfSmrg 104935c4bbdfSmrg winDebug("winMultiWindowXMsgProc - Hello\n"); 105035c4bbdfSmrg 105135c4bbdfSmrg /* Check that argument pointer is not invalid */ 105235c4bbdfSmrg if (pProcArg == NULL) { 105335c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - pProcArg is NULL. Exiting.\n"); 105435c4bbdfSmrg pthread_exit(NULL); 105505b261ecSmrg } 105605b261ecSmrg 10571b5d61b8Smrg winDebug("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n"); 105805b261ecSmrg 105935c4bbdfSmrg /* Grab the server started mutex - pause until we get it */ 106035c4bbdfSmrg iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted); 106135c4bbdfSmrg if (iReturn != 0) { 106235c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d. " 106335c4bbdfSmrg "Exiting.\n", iReturn); 106435c4bbdfSmrg pthread_exit(NULL); 106505b261ecSmrg } 106605b261ecSmrg 10671b5d61b8Smrg winDebug("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); 106805b261ecSmrg 106935c4bbdfSmrg /* Release the server started mutex */ 107035c4bbdfSmrg pthread_mutex_unlock(pProcArg->ppmServerStarted); 107105b261ecSmrg 10721b5d61b8Smrg winDebug("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n"); 107305b261ecSmrg 107435c4bbdfSmrg /* Setup the display connection string x */ 107535c4bbdfSmrg winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen); 107605b261ecSmrg 107735c4bbdfSmrg /* Print the display connection string */ 107835c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay); 107905b261ecSmrg 108035c4bbdfSmrg /* Use our generated cookie for authentication */ 10811b5d61b8Smrg auth_info = winGetXcbAuthInfo(); 10826747b715Smrg 108335c4bbdfSmrg /* Initialize retry count */ 108435c4bbdfSmrg iRetries = 0; 108505b261ecSmrg 108635c4bbdfSmrg /* Open the X display */ 108735c4bbdfSmrg do { 108835c4bbdfSmrg /* Try to open the display */ 10891b5d61b8Smrg pProcArg->conn = xcb_connect_to_display_with_auth_info(pszDisplay, 10901b5d61b8Smrg auth_info, NULL); 10911b5d61b8Smrg if (xcb_connection_has_error(pProcArg->conn)) { 109235c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - Could not open display, try: %d, " 109335c4bbdfSmrg "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY); 109435c4bbdfSmrg ++iRetries; 109535c4bbdfSmrg sleep(WIN_CONNECT_DELAY); 109635c4bbdfSmrg continue; 109735c4bbdfSmrg } 109835c4bbdfSmrg else 109935c4bbdfSmrg break; 110005b261ecSmrg } 11011b5d61b8Smrg while (xcb_connection_has_error(pProcArg->conn) && iRetries < WIN_CONNECT_RETRIES); 110235c4bbdfSmrg 110335c4bbdfSmrg /* Make sure that the display opened */ 11041b5d61b8Smrg if (xcb_connection_has_error(pProcArg->conn)) { 110535c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - Failed opening the display. " 110635c4bbdfSmrg "Exiting.\n"); 110735c4bbdfSmrg pthread_exit(NULL); 110805b261ecSmrg } 110905b261ecSmrg 11101b5d61b8Smrg ErrorF("winMultiWindowXMsgProc - xcb_connect() returned and " 111135c4bbdfSmrg "successfully opened the display.\n"); 111205b261ecSmrg 111335c4bbdfSmrg /* Check if another window manager is already running */ 11141b5d61b8Smrg if (CheckAnotherWindowManager(pProcArg->conn, pProcArg->dwScreen)) { 111535c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - " 111635c4bbdfSmrg "another window manager is running. Exiting.\n"); 111735c4bbdfSmrg pthread_exit(NULL); 111805b261ecSmrg } 11196747b715Smrg 1120ed6184dfSmrg /* Get root window id */ 1121ed6184dfSmrg root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen); 1122ed6184dfSmrg root_window_id = root_screen->root; 11231b5d61b8Smrg 1124ed6184dfSmrg { 11251b5d61b8Smrg /* Set WM_ICON_SIZE property indicating desired icon sizes */ 11261b5d61b8Smrg typedef struct { 11271b5d61b8Smrg uint32_t min_width, min_height; 11281b5d61b8Smrg uint32_t max_width, max_height; 11291b5d61b8Smrg int32_t width_inc, height_inc; 11301b5d61b8Smrg } xcb_wm_icon_size_hints_hints_t; 11311b5d61b8Smrg 11321b5d61b8Smrg xcb_wm_icon_size_hints_hints_t xis; 11331b5d61b8Smrg xis.min_width = xis.min_height = 16; 11341b5d61b8Smrg xis.max_width = xis.max_height = 48; 11351b5d61b8Smrg xis.width_inc = xis.height_inc = 16; 11361b5d61b8Smrg 11371b5d61b8Smrg xcb_change_property(pProcArg->conn, XCB_PROP_MODE_REPLACE, root_window_id, 11381b5d61b8Smrg XCB_ATOM_WM_ICON_SIZE, XCB_ATOM_WM_ICON_SIZE, 32, 11391b5d61b8Smrg sizeof(xis)/4, &xis); 114005b261ecSmrg } 114105b261ecSmrg 11421b5d61b8Smrg atmWmName = intern_atom(pProcArg->conn, "WM_NAME"); 11431b5d61b8Smrg atmNetWmName = intern_atom(pProcArg->conn, "_NET_WM_NAME"); 11441b5d61b8Smrg atmWmHints = intern_atom(pProcArg->conn, "WM_HINTS"); 11451b5d61b8Smrg atmWmChange = intern_atom(pProcArg->conn, "WM_CHANGE_STATE"); 11461b5d61b8Smrg atmNetWmIcon = intern_atom(pProcArg->conn, "_NET_WM_ICON"); 11471b5d61b8Smrg atmWindowState = intern_atom(pProcArg->conn, "_NET_WM_STATE"); 11481b5d61b8Smrg atmMotifWmHints = intern_atom(pProcArg->conn, "_MOTIF_WM_HINTS"); 11491b5d61b8Smrg atmWindowType = intern_atom(pProcArg->conn, "_NET_WM_WINDOW_TYPE"); 11501b5d61b8Smrg atmNormalHints = intern_atom(pProcArg->conn, "WM_NORMAL_HINTS"); 115135c4bbdfSmrg 115235c4bbdfSmrg /* 115335c4bbdfSmrg iiimxcf had a bug until 2009-04-27, assuming that the 115435c4bbdfSmrg WM_STATE atom exists, causing clients to fail with 115535c4bbdfSmrg a BadAtom X error if it doesn't. 115635c4bbdfSmrg 115735c4bbdfSmrg Since this is on in the default Solaris 10 install, 115835c4bbdfSmrg workaround this by making sure it does exist... 115935c4bbdfSmrg */ 11601b5d61b8Smrg intern_atom(pProcArg->conn, "WM_STATE"); 116135c4bbdfSmrg 1162ed6184dfSmrg /* 1163ed6184dfSmrg Enable Composite extension and redirect subwindows of the root window 1164ed6184dfSmrg */ 1165ed6184dfSmrg if (pProcArg->pWMInfo->fCompositeWM) { 1166ed6184dfSmrg const char *extension_name = "Composite"; 1167ed6184dfSmrg xcb_query_extension_cookie_t cookie; 1168ed6184dfSmrg xcb_query_extension_reply_t *reply; 1169ed6184dfSmrg 1170ed6184dfSmrg cookie = xcb_query_extension(pProcArg->conn, strlen(extension_name), extension_name); 1171ed6184dfSmrg reply = xcb_query_extension_reply(pProcArg->conn, cookie, NULL); 1172ed6184dfSmrg 1173ed6184dfSmrg if (reply && (reply->present)) { 1174ed6184dfSmrg xcb_composite_redirect_subwindows(pProcArg->conn, 1175ed6184dfSmrg root_window_id, 1176ed6184dfSmrg XCB_COMPOSITE_REDIRECT_AUTOMATIC); 1177ed6184dfSmrg 1178ed6184dfSmrg /* 1179ed6184dfSmrg We use automatic updating of the root window for two 1180ed6184dfSmrg reasons: 1181ed6184dfSmrg 1182ed6184dfSmrg 1) redirected window contents are mirrored to the root 1183ed6184dfSmrg window so that the root window draws correctly when shown. 1184ed6184dfSmrg 1185ed6184dfSmrg 2) updating the root window causes damage against the 1186ed6184dfSmrg shadow framebuffer, which ultimately causes WM_PAINT to be 1187ed6184dfSmrg sent to the affected window(s) to cause the damage regions 1188ed6184dfSmrg to be redrawn. 1189ed6184dfSmrg */ 1190ed6184dfSmrg 1191ed6184dfSmrg ErrorF("Using Composite redirection\n"); 1192ed6184dfSmrg 1193ed6184dfSmrg free(reply); 1194ed6184dfSmrg } 1195ed6184dfSmrg } 1196ed6184dfSmrg 119735c4bbdfSmrg /* Loop until we explicitly break out */ 119835c4bbdfSmrg while (1) { 11991b5d61b8Smrg xcb_generic_event_t *event; 12001b5d61b8Smrg uint8_t type; 12011b5d61b8Smrg Bool send_event; 12021b5d61b8Smrg 120335c4bbdfSmrg if (g_shutdown) 120435c4bbdfSmrg break; 120535c4bbdfSmrg 120635c4bbdfSmrg /* Fetch next event */ 12071b5d61b8Smrg event = xcb_wait_for_event(pProcArg->conn); 12081b5d61b8Smrg if (!event) { // returns NULL on I/O error 12091b5d61b8Smrg int e = xcb_connection_has_error(pProcArg->conn); 12101b5d61b8Smrg ErrorF("winMultiWindowXMsgProc - Fatal error %d on xcb connection\n", e); 12111b5d61b8Smrg break; 12121b5d61b8Smrg } 121335c4bbdfSmrg 12141b5d61b8Smrg type = event->response_type & ~0x80; 12151b5d61b8Smrg send_event = event->response_type & 0x80; 121635c4bbdfSmrg 12171b5d61b8Smrg winDebug("winMultiWindowXMsgProc - event %d\n", type); 121835c4bbdfSmrg 12191b5d61b8Smrg /* Branch on event type */ 12201b5d61b8Smrg if (type == 0) { 12211b5d61b8Smrg xcb_generic_error_t *err = (xcb_generic_error_t *)event; 12221b5d61b8Smrg ErrorF("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, " 12231b5d61b8Smrg "Major opcode: %i, Minor opcode: %i\n", 12241b5d61b8Smrg err->error_code, err->resource_id, 12251b5d61b8Smrg err->major_code, err->minor_code); 12261b5d61b8Smrg } 12271b5d61b8Smrg else if (type == XCB_CREATE_NOTIFY) { 12281b5d61b8Smrg xcb_create_notify_event_t *notify = (xcb_create_notify_event_t *)event; 12291b5d61b8Smrg 12301b5d61b8Smrg /* Request property change events */ 12311b5d61b8Smrg const static uint32_t mask_value[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; 12321b5d61b8Smrg xcb_change_window_attributes (pProcArg->conn, notify->window, 12331b5d61b8Smrg XCB_CW_EVENT_MASK, mask_value); 12341b5d61b8Smrg 12351b5d61b8Smrg /* If it's not override-redirect, set the border-width to 0 */ 12361b5d61b8Smrg if (!IsOverrideRedirect(pProcArg->conn, notify->window)) { 12371b5d61b8Smrg const static uint32_t width_value[] = { 0 }; 12381b5d61b8Smrg xcb_configure_window(pProcArg->conn, notify->window, 12391b5d61b8Smrg XCB_CONFIG_WINDOW_BORDER_WIDTH, width_value); 12401b5d61b8Smrg } 124135c4bbdfSmrg } 12421b5d61b8Smrg else if (type == XCB_MAP_NOTIFY) { 124335c4bbdfSmrg /* Fake a reparentNotify event as SWT/Motif expects a 124435c4bbdfSmrg Window Manager to reparent a top-level window when 124535c4bbdfSmrg it is mapped and waits until they do. 124635c4bbdfSmrg 124735c4bbdfSmrg We don't actually need to reparent, as the frame is 124835c4bbdfSmrg a native window, not an X window 124935c4bbdfSmrg 125035c4bbdfSmrg We do this on MapNotify, not MapRequest like a real 125135c4bbdfSmrg Window Manager would, so we don't have do get involved 125235c4bbdfSmrg in actually mapping the window via it's (non-existent) 125335c4bbdfSmrg parent... 125435c4bbdfSmrg 125535c4bbdfSmrg See sourceware bugzilla #9848 125635c4bbdfSmrg */ 125735c4bbdfSmrg 12581b5d61b8Smrg xcb_map_notify_event_t *notify = (xcb_map_notify_event_t *)event; 12591b5d61b8Smrg 12601b5d61b8Smrg xcb_get_geometry_cookie_t cookie; 12611b5d61b8Smrg xcb_get_geometry_reply_t *reply; 12621b5d61b8Smrg xcb_query_tree_cookie_t cookie_qt; 12631b5d61b8Smrg xcb_query_tree_reply_t *reply_qt; 12641b5d61b8Smrg 12651b5d61b8Smrg cookie = xcb_get_geometry(pProcArg->conn, notify->window); 12661b5d61b8Smrg cookie_qt = xcb_query_tree(pProcArg->conn, notify->window); 12671b5d61b8Smrg reply = xcb_get_geometry_reply(pProcArg->conn, cookie, NULL); 12681b5d61b8Smrg reply_qt = xcb_query_tree_reply(pProcArg->conn, cookie_qt, NULL); 126935c4bbdfSmrg 12701b5d61b8Smrg if (reply && reply_qt) { 127135c4bbdfSmrg /* 127235c4bbdfSmrg It's a top-level window if the parent window is a root window 127335c4bbdfSmrg Only non-override_redirect windows can get reparented 127435c4bbdfSmrg */ 12751b5d61b8Smrg if ((reply->root == reply_qt->parent) && !notify->override_redirect) { 12761b5d61b8Smrg xcb_reparent_notify_event_t event_send; 12771b5d61b8Smrg 1278ed6184dfSmrg event_send.response_type = XCB_REPARENT_NOTIFY; 12791b5d61b8Smrg event_send.event = notify->window; 12801b5d61b8Smrg event_send.window = notify->window; 12811b5d61b8Smrg event_send.parent = reply_qt->parent; 12821b5d61b8Smrg event_send.x = reply->x; 12831b5d61b8Smrg event_send.y = reply->y; 12841b5d61b8Smrg 12851b5d61b8Smrg xcb_send_event (pProcArg->conn, TRUE, notify->window, 12861b5d61b8Smrg XCB_EVENT_MASK_STRUCTURE_NOTIFY, 12871b5d61b8Smrg (const char *)&event_send); 12881b5d61b8Smrg 12891b5d61b8Smrg free(reply_qt); 12901b5d61b8Smrg free(reply); 129135c4bbdfSmrg } 129235c4bbdfSmrg } 129335c4bbdfSmrg } 12941b5d61b8Smrg else if (type == XCB_CONFIGURE_NOTIFY) { 12951b5d61b8Smrg if (!send_event) { 129635c4bbdfSmrg /* 129735c4bbdfSmrg Java applications using AWT on JRE 1.6.0 break with non-reparenting WMs AWT 129835c4bbdfSmrg doesn't explicitly know about (See sun bug #6434227) 129935c4bbdfSmrg 130035c4bbdfSmrg XDecoratedPeer.handleConfigureNotifyEvent() only processes non-synthetic 130135c4bbdfSmrg ConfigureNotify events to update window location if it's identified the 130235c4bbdfSmrg WM as a non-reparenting WM it knows about (compiz or lookingglass) 130335c4bbdfSmrg 130435c4bbdfSmrg Rather than tell all sorts of lies to get XWM to recognize us as one of 130535c4bbdfSmrg those, simply send a synthetic ConfigureNotify for every non-synthetic one 130635c4bbdfSmrg */ 13071b5d61b8Smrg xcb_configure_notify_event_t *notify = (xcb_configure_notify_event_t *)event; 13081b5d61b8Smrg xcb_configure_notify_event_t event_send = *notify; 130935c4bbdfSmrg 13101b5d61b8Smrg event_send.event = notify->window; 13111b5d61b8Smrg 13121b5d61b8Smrg xcb_send_event(pProcArg->conn, TRUE, notify->window, 13131b5d61b8Smrg XCB_EVENT_MASK_STRUCTURE_NOTIFY, 13141b5d61b8Smrg (const char *)&event_send); 131535c4bbdfSmrg } 131635c4bbdfSmrg } 13171b5d61b8Smrg else if (type == XCB_PROPERTY_NOTIFY) { 13181b5d61b8Smrg xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)event; 13191b5d61b8Smrg 13201b5d61b8Smrg if ((notify->atom == atmWmName) || 13211b5d61b8Smrg (notify->atom == atmNetWmName)) { 132235c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 132335c4bbdfSmrg 132435c4bbdfSmrg msg.msg = WM_WM_NAME_EVENT; 13251b5d61b8Smrg msg.iWindow = notify->window; 132635c4bbdfSmrg 132735c4bbdfSmrg /* Other fields ignored */ 132835c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 132935c4bbdfSmrg } 133035c4bbdfSmrg else { 133135c4bbdfSmrg /* 133235c4bbdfSmrg Several properties are considered for WM hints, check if this property change affects any of them... 133335c4bbdfSmrg (this list needs to be kept in sync with winApplyHints()) 133435c4bbdfSmrg */ 13351b5d61b8Smrg if ((notify->atom == atmWmHints) || 13361b5d61b8Smrg (notify->atom == atmWindowState) || 13371b5d61b8Smrg (notify->atom == atmMotifWmHints) || 13381b5d61b8Smrg (notify->atom == atmWindowType) || 13391b5d61b8Smrg (notify->atom == atmNormalHints)) { 134035c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 134135c4bbdfSmrg msg.msg = WM_WM_HINTS_EVENT; 13421b5d61b8Smrg msg.iWindow = notify->window; 134335c4bbdfSmrg 134435c4bbdfSmrg /* Other fields ignored */ 134535c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 134635c4bbdfSmrg } 134735c4bbdfSmrg 134835c4bbdfSmrg /* Not an else as WM_HINTS affects both style and icon */ 13491b5d61b8Smrg if ((notify->atom == atmWmHints) || 13501b5d61b8Smrg (notify->atom == atmNetWmIcon)) { 135135c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 135235c4bbdfSmrg msg.msg = WM_WM_ICON_EVENT; 13531b5d61b8Smrg msg.iWindow = notify->window; 135435c4bbdfSmrg 135535c4bbdfSmrg /* Other fields ignored */ 135635c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 13576747b715Smrg } 13586747b715Smrg } 13596747b715Smrg } 13601b5d61b8Smrg else if (type == XCB_CLIENT_MESSAGE) { 13611b5d61b8Smrg xcb_client_message_event_t *client_msg = (xcb_client_message_event_t *)event; 136235c4bbdfSmrg 13631b5d61b8Smrg if (client_msg->type == atmWmChange 13641b5d61b8Smrg && client_msg->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) { 13651b5d61b8Smrg ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n"); 136635c4bbdfSmrg 13671b5d61b8Smrg memset(&msg, 0, sizeof(msg)); 136835c4bbdfSmrg 13691b5d61b8Smrg msg.msg = WM_WM_CHANGE_STATE; 13701b5d61b8Smrg msg.iWindow = client_msg->window; 13711b5d61b8Smrg 13721b5d61b8Smrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 13731b5d61b8Smrg } 137435c4bbdfSmrg } 13751b5d61b8Smrg 13761b5d61b8Smrg /* Free the event */ 13771b5d61b8Smrg free(event); 137805b261ecSmrg } 137905b261ecSmrg 13801b5d61b8Smrg xcb_disconnect(pProcArg->conn); 138135c4bbdfSmrg pthread_exit(NULL); 138235c4bbdfSmrg return NULL; 138305b261ecSmrg} 138405b261ecSmrg 138505b261ecSmrg/* 138605b261ecSmrg * winInitWM - Entry point for the X server to spawn 138705b261ecSmrg * the Window Manager thread. Called from 138805b261ecSmrg * winscrinit.c/winFinishScreenInitFB (). 138905b261ecSmrg */ 139005b261ecSmrg 139105b261ecSmrgBool 139235c4bbdfSmrgwinInitWM(void **ppWMInfo, 139335c4bbdfSmrg pthread_t * ptWMProc, 139435c4bbdfSmrg pthread_t * ptXMsgProc, 139535c4bbdfSmrg pthread_mutex_t * ppmServerStarted, 1396ed6184dfSmrg int dwScreen, HWND hwndScreen, Bool compositeWM) 139705b261ecSmrg{ 139835c4bbdfSmrg WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec)); 139935c4bbdfSmrg WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec)); 140035c4bbdfSmrg XMsgProcArgPtr pXMsgArg = malloc(sizeof(XMsgProcArgRec)); 140135c4bbdfSmrg 140235c4bbdfSmrg /* Bail if the input parameters are bad */ 140335c4bbdfSmrg if (pArg == NULL || pWMInfo == NULL || pXMsgArg == NULL) { 140435c4bbdfSmrg ErrorF("winInitWM - malloc failed.\n"); 140535c4bbdfSmrg free(pArg); 140635c4bbdfSmrg free(pWMInfo); 140735c4bbdfSmrg free(pXMsgArg); 140835c4bbdfSmrg return FALSE; 140905b261ecSmrg } 141035c4bbdfSmrg 141135c4bbdfSmrg /* Zero the allocated memory */ 141235c4bbdfSmrg ZeroMemory(pArg, sizeof(WMProcArgRec)); 141335c4bbdfSmrg ZeroMemory(pWMInfo, sizeof(WMInfoRec)); 141435c4bbdfSmrg ZeroMemory(pXMsgArg, sizeof(XMsgProcArgRec)); 141535c4bbdfSmrg 141635c4bbdfSmrg /* Set a return pointer to the Window Manager info structure */ 141735c4bbdfSmrg *ppWMInfo = pWMInfo; 1418ed6184dfSmrg pWMInfo->fCompositeWM = compositeWM; 141935c4bbdfSmrg 142035c4bbdfSmrg /* Setup the argument structure for the thread function */ 142135c4bbdfSmrg pArg->dwScreen = dwScreen; 142235c4bbdfSmrg pArg->pWMInfo = pWMInfo; 142335c4bbdfSmrg pArg->ppmServerStarted = ppmServerStarted; 142435c4bbdfSmrg 1425ed6184dfSmrg /* Initialize the message queue */ 142635c4bbdfSmrg if (!InitQueue(&pWMInfo->wmMsgQueue)) { 142735c4bbdfSmrg ErrorF("winInitWM - InitQueue () failed.\n"); 142835c4bbdfSmrg return FALSE; 142905b261ecSmrg } 143035c4bbdfSmrg 143135c4bbdfSmrg /* Spawn a thread for the Window Manager */ 143235c4bbdfSmrg if (pthread_create(ptWMProc, NULL, winMultiWindowWMProc, pArg)) { 143335c4bbdfSmrg /* Bail if thread creation failed */ 143435c4bbdfSmrg ErrorF("winInitWM - pthread_create failed for Window Manager.\n"); 143535c4bbdfSmrg return FALSE; 143605b261ecSmrg } 143705b261ecSmrg 143835c4bbdfSmrg /* Spawn the XNextEvent thread, will send messages to WM */ 143935c4bbdfSmrg pXMsgArg->dwScreen = dwScreen; 144035c4bbdfSmrg pXMsgArg->pWMInfo = pWMInfo; 144135c4bbdfSmrg pXMsgArg->ppmServerStarted = ppmServerStarted; 144235c4bbdfSmrg pXMsgArg->hwndScreen = hwndScreen; 144335c4bbdfSmrg if (pthread_create(ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg)) { 144435c4bbdfSmrg /* Bail if thread creation failed */ 144535c4bbdfSmrg ErrorF("winInitWM - pthread_create failed on XMSG.\n"); 144635c4bbdfSmrg return FALSE; 144705b261ecSmrg } 144805b261ecSmrg 144905b261ecSmrg#if CYGDEBUG || YES 145035c4bbdfSmrg winDebug("winInitWM - Returning.\n"); 145105b261ecSmrg#endif 145205b261ecSmrg 145335c4bbdfSmrg return TRUE; 145405b261ecSmrg} 145505b261ecSmrg 145605b261ecSmrg/* 145705b261ecSmrg * Window manager thread - setup 145805b261ecSmrg */ 145905b261ecSmrg 146005b261ecSmrgstatic void 146135c4bbdfSmrgwinInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) 146205b261ecSmrg{ 146335c4bbdfSmrg int iRetries = 0; 146435c4bbdfSmrg char pszDisplay[512]; 146535c4bbdfSmrg int iReturn; 14661b5d61b8Smrg xcb_auth_info_t *auth_info; 1467ed6184dfSmrg xcb_screen_t *root_screen; 1468ed6184dfSmrg xcb_window_t root_window_id; 146905b261ecSmrg 147035c4bbdfSmrg winDebug("winInitMultiWindowWM - Hello\n"); 147105b261ecSmrg 147235c4bbdfSmrg /* Check that argument pointer is not invalid */ 147335c4bbdfSmrg if (pProcArg == NULL) { 147435c4bbdfSmrg ErrorF("winInitMultiWindowWM - pProcArg is NULL. Exiting.\n"); 147535c4bbdfSmrg pthread_exit(NULL); 147605b261ecSmrg } 147705b261ecSmrg 14781b5d61b8Smrg winDebug("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n"); 147905b261ecSmrg 148035c4bbdfSmrg /* Grab our garbage mutex to satisfy pthread_cond_wait */ 148135c4bbdfSmrg iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted); 148235c4bbdfSmrg if (iReturn != 0) { 148335c4bbdfSmrg ErrorF("winInitMultiWindowWM - pthread_mutex_lock () failed: %d. " 148435c4bbdfSmrg "Exiting.\n", iReturn); 148535c4bbdfSmrg pthread_exit(NULL); 148605b261ecSmrg } 148705b261ecSmrg 14881b5d61b8Smrg winDebug("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); 148905b261ecSmrg 149035c4bbdfSmrg /* Release the server started mutex */ 149135c4bbdfSmrg pthread_mutex_unlock(pProcArg->ppmServerStarted); 149205b261ecSmrg 14931b5d61b8Smrg winDebug("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); 14946747b715Smrg 149535c4bbdfSmrg /* Setup the display connection string x */ 149635c4bbdfSmrg winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen); 149735c4bbdfSmrg 149835c4bbdfSmrg /* Print the display connection string */ 149935c4bbdfSmrg ErrorF("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); 150035c4bbdfSmrg 150135c4bbdfSmrg /* Use our generated cookie for authentication */ 15021b5d61b8Smrg auth_info = winGetXcbAuthInfo(); 150335c4bbdfSmrg 150435c4bbdfSmrg /* Open the X display */ 150535c4bbdfSmrg do { 150635c4bbdfSmrg /* Try to open the display */ 15071b5d61b8Smrg pWMInfo->conn = xcb_connect_to_display_with_auth_info(pszDisplay, 15081b5d61b8Smrg auth_info, NULL); 15091b5d61b8Smrg if (xcb_connection_has_error(pWMInfo->conn)) { 151035c4bbdfSmrg ErrorF("winInitMultiWindowWM - Could not open display, try: %d, " 151135c4bbdfSmrg "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY); 151235c4bbdfSmrg ++iRetries; 151335c4bbdfSmrg sleep(WIN_CONNECT_DELAY); 151435c4bbdfSmrg continue; 151535c4bbdfSmrg } 151635c4bbdfSmrg else 151735c4bbdfSmrg break; 151805b261ecSmrg } 15191b5d61b8Smrg while (xcb_connection_has_error(pWMInfo->conn) && iRetries < WIN_CONNECT_RETRIES); 152035c4bbdfSmrg 152135c4bbdfSmrg /* Make sure that the display opened */ 15221b5d61b8Smrg if (xcb_connection_has_error(pWMInfo->conn)) { 152335c4bbdfSmrg ErrorF("winInitMultiWindowWM - Failed opening the display. " 152435c4bbdfSmrg "Exiting.\n"); 152535c4bbdfSmrg pthread_exit(NULL); 152605b261ecSmrg } 152705b261ecSmrg 15281b5d61b8Smrg ErrorF("winInitMultiWindowWM - xcb_connect () returned and " 152935c4bbdfSmrg "successfully opened the display.\n"); 153005b261ecSmrg 153135c4bbdfSmrg /* Create some atoms */ 15321b5d61b8Smrg pWMInfo->atmWmProtos = intern_atom(pWMInfo->conn, "WM_PROTOCOLS"); 15331b5d61b8Smrg pWMInfo->atmWmDelete = intern_atom(pWMInfo->conn, "WM_DELETE_WINDOW"); 15341b5d61b8Smrg pWMInfo->atmWmTakeFocus = intern_atom(pWMInfo->conn, "WM_TAKE_FOCUS"); 15351b5d61b8Smrg pWMInfo->atmPrivMap = intern_atom(pWMInfo->conn, WINDOWSWM_NATIVE_HWND); 15361b5d61b8Smrg pWMInfo->atmUtf8String = intern_atom(pWMInfo->conn, "UTF8_STRING"); 15371b5d61b8Smrg pWMInfo->atmNetWmName = intern_atom(pWMInfo->conn, "_NET_WM_NAME"); 1538ed6184dfSmrg pWMInfo->atmCurrentDesktop = intern_atom(pWMInfo->conn, "_NET_CURRENT_DESKTOP"); 1539ed6184dfSmrg pWMInfo->atmNumberDesktops = intern_atom(pWMInfo->conn, "_NET_NUMBER_OF_DESKTOPS"); 1540ed6184dfSmrg pWMInfo->atmDesktopNames = intern_atom(pWMInfo->conn, "__NET_DESKTOP_NAMES"); 15411b5d61b8Smrg 15421b5d61b8Smrg /* Initialization for the xcb_ewmh and EWMH atoms */ 15431b5d61b8Smrg { 15441b5d61b8Smrg xcb_intern_atom_cookie_t *atoms_cookie; 15451b5d61b8Smrg atoms_cookie = xcb_ewmh_init_atoms(pWMInfo->conn, &pWMInfo->ewmh); 15461b5d61b8Smrg if (xcb_ewmh_init_atoms_replies(&pWMInfo->ewmh, atoms_cookie, NULL)) { 15471b5d61b8Smrg /* Set the _NET_SUPPORTED atom for this context. 15481b5d61b8Smrg 15491b5d61b8Smrg TODO: Audit to ensure we implement everything defined as MUSTs 15501b5d61b8Smrg for window managers in the EWMH standard.*/ 15511b5d61b8Smrg xcb_atom_t supported[] = 15521b5d61b8Smrg { 15531b5d61b8Smrg pWMInfo->ewmh.WM_PROTOCOLS, 15541b5d61b8Smrg pWMInfo->ewmh._NET_SUPPORTED, 15551b5d61b8Smrg pWMInfo->ewmh._NET_SUPPORTING_WM_CHECK, 15561b5d61b8Smrg pWMInfo->ewmh._NET_CLOSE_WINDOW, 15571b5d61b8Smrg pWMInfo->ewmh._NET_WM_WINDOW_TYPE, 15581b5d61b8Smrg pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK, 15591b5d61b8Smrg pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH, 15601b5d61b8Smrg pWMInfo->ewmh._NET_WM_STATE, 15611b5d61b8Smrg pWMInfo->ewmh._NET_WM_STATE_HIDDEN, 15621b5d61b8Smrg pWMInfo->ewmh._NET_WM_STATE_ABOVE, 15631b5d61b8Smrg pWMInfo->ewmh._NET_WM_STATE_BELOW, 15641b5d61b8Smrg pWMInfo->ewmh._NET_WM_STATE_SKIP_TASKBAR, 15651b5d61b8Smrg }; 15661b5d61b8Smrg 15671b5d61b8Smrg xcb_ewmh_set_supported(&pWMInfo->ewmh, pProcArg->dwScreen, 15681b5d61b8Smrg ARRAY_SIZE(supported), supported); 15691b5d61b8Smrg } 15701b5d61b8Smrg else { 15711b5d61b8Smrg ErrorF("winInitMultiWindowWM - xcb_ewmh_init_atoms() failed\n"); 157235c4bbdfSmrg } 157305b261ecSmrg } 157405b261ecSmrg 1575ed6184dfSmrg /* Get root window id */ 1576ed6184dfSmrg root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen); 1577ed6184dfSmrg root_window_id = root_screen->root; 1578ed6184dfSmrg 1579ed6184dfSmrg /* 1580ed6184dfSmrg Set root window properties for describing multiple desktops to describe 1581ed6184dfSmrg the one desktop we have 1582ed6184dfSmrg */ 1583ed6184dfSmrg { 1584ed6184dfSmrg int data; 1585ed6184dfSmrg const char buf[] = "Desktop"; 1586ed6184dfSmrg 1587ed6184dfSmrg data = 0; 1588ed6184dfSmrg xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id, 1589ed6184dfSmrg pWMInfo->atmCurrentDesktop, XCB_ATOM_CARDINAL, 32, 1590ed6184dfSmrg 1, &data); 1591ed6184dfSmrg data = 1; 1592ed6184dfSmrg xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id, 1593ed6184dfSmrg pWMInfo->atmNumberDesktops, XCB_ATOM_CARDINAL, 32, 1594ed6184dfSmrg 1, &data); 1595ed6184dfSmrg 1596ed6184dfSmrg xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id, 1597ed6184dfSmrg pWMInfo->atmDesktopNames, pWMInfo->atmUtf8String, 8, 1598ed6184dfSmrg strlen(buf), (unsigned char *) buf); 1599ed6184dfSmrg } 1600ed6184dfSmrg 16011b5d61b8Smrg /* 16021b5d61b8Smrg Set the root window cursor to left_ptr (this controls the cursor an 1603ed6184dfSmrg application gets over its windows when it doesn't set one) 16041b5d61b8Smrg */ 16051b5d61b8Smrg { 16061b5d61b8Smrg#define XC_left_ptr 68 16071b5d61b8Smrg xcb_cursor_t cursor = xcb_generate_id(pWMInfo->conn); 16081b5d61b8Smrg xcb_font_t font = xcb_generate_id(pWMInfo->conn); 16091b5d61b8Smrg xcb_font_t *mask_font = &font; /* An alias to clarify */ 16101b5d61b8Smrg int shape = XC_left_ptr; 16111b5d61b8Smrg uint32_t mask = XCB_CW_CURSOR; 16121b5d61b8Smrg uint32_t value_list = cursor; 161305b261ecSmrg 16141b5d61b8Smrg static const uint16_t fgred = 0, fggreen = 0, fgblue = 0; 16151b5d61b8Smrg static const uint16_t bgred = 0xFFFF, bggreen = 0xFFFF, bgblue = 0xFFFF; 161605b261ecSmrg 16171b5d61b8Smrg xcb_open_font(pWMInfo->conn, font, sizeof("cursor"), "cursor"); 161805b261ecSmrg 16191b5d61b8Smrg xcb_create_glyph_cursor(pWMInfo->conn, cursor, font, *mask_font, 16201b5d61b8Smrg shape, shape + 1, 16211b5d61b8Smrg fgred, fggreen, fgblue, bgred, bggreen, bgblue); 162205b261ecSmrg 1623ed6184dfSmrg xcb_change_window_attributes(pWMInfo->conn, root_window_id, mask, &value_list); 162405b261ecSmrg 16251b5d61b8Smrg xcb_free_cursor(pWMInfo->conn, cursor); 16261b5d61b8Smrg xcb_close_font(pWMInfo->conn, font); 162735c4bbdfSmrg } 162835c4bbdfSmrg} 162905b261ecSmrg 163005b261ecSmrg/* 16311b5d61b8Smrg * winSendMessageToWM - Send a message from the X thread to the WM thread 163205b261ecSmrg */ 163305b261ecSmrg 16341b5d61b8Smrgvoid 16351b5d61b8SmrgwinSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg) 163605b261ecSmrg{ 16371b5d61b8Smrg WMMsgNodePtr pNode; 163835c4bbdfSmrg 16396747b715Smrg#if CYGMULTIWINDOW_DEBUG 16401b5d61b8Smrg ErrorF("winSendMessageToWM %s\n", MessageName(pMsg)); 16416747b715Smrg#endif 164205b261ecSmrg 16431b5d61b8Smrg pNode = malloc(sizeof(WMMsgNodeRec)); 16441b5d61b8Smrg if (pNode != NULL) { 16451b5d61b8Smrg memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec)); 16461b5d61b8Smrg PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode); 164735c4bbdfSmrg } 164805b261ecSmrg} 164905b261ecSmrg 165005b261ecSmrg/* 165105b261ecSmrg * Check if another window manager is running 165205b261ecSmrg */ 165305b261ecSmrg 165405b261ecSmrgstatic Bool 16551b5d61b8SmrgCheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen) 165605b261ecSmrg{ 16571b5d61b8Smrg Bool redirectError = FALSE; 16581b5d61b8Smrg 16591b5d61b8Smrg /* Get root window id */ 16601b5d61b8Smrg xcb_screen_t *root_screen = xcb_aux_get_screen(conn, dwScreen); 16611b5d61b8Smrg xcb_window_t root_window_id = root_screen->root; 16621b5d61b8Smrg 166335c4bbdfSmrg /* 166435c4bbdfSmrg Try to select the events which only one client at a time is allowed to select. 166535c4bbdfSmrg If this causes an error, another window manager is already running... 166635c4bbdfSmrg */ 16671b5d61b8Smrg const static uint32_t test_mask[] = { XCB_EVENT_MASK_RESIZE_REDIRECT | 16681b5d61b8Smrg XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | 16691b5d61b8Smrg XCB_EVENT_MASK_BUTTON_PRESS }; 16701b5d61b8Smrg 16711b5d61b8Smrg xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(conn, 16721b5d61b8Smrg root_window_id, 16731b5d61b8Smrg XCB_CW_EVENT_MASK, 16741b5d61b8Smrg test_mask); 16751b5d61b8Smrg xcb_generic_error_t *error; 16761b5d61b8Smrg if ((error = xcb_request_check(conn, cookie))) 16771b5d61b8Smrg { 16781b5d61b8Smrg redirectError = TRUE; 16791b5d61b8Smrg free(error); 16801b5d61b8Smrg } 168135c4bbdfSmrg 168235c4bbdfSmrg /* 168335c4bbdfSmrg Side effect: select the events we are actually interested in... 168435c4bbdfSmrg 16851b5d61b8Smrg Other WMs are not allowed, also select one of the events which only one client 168635c4bbdfSmrg at a time is allowed to select, so other window managers won't start... 168735c4bbdfSmrg */ 16881b5d61b8Smrg { 16891b5d61b8Smrg const uint32_t mask[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | 16901b5d61b8Smrg XCB_EVENT_MASK_BUTTON_PRESS }; 16911b5d61b8Smrg 16921b5d61b8Smrg xcb_change_window_attributes(conn, root_window_id, XCB_CW_EVENT_MASK, mask); 16931b5d61b8Smrg } 16941b5d61b8Smrg 169535c4bbdfSmrg return redirectError; 169605b261ecSmrg} 169705b261ecSmrg 169805b261ecSmrg/* 169905b261ecSmrg * Notify the MWM thread we're exiting and not to reconnect 170005b261ecSmrg */ 170105b261ecSmrg 170205b261ecSmrgvoid 170335c4bbdfSmrgwinDeinitMultiWindowWM(void) 170405b261ecSmrg{ 170535c4bbdfSmrg ErrorF("winDeinitMultiWindowWM - Noting shutdown in progress\n"); 170635c4bbdfSmrg g_shutdown = TRUE; 170705b261ecSmrg} 17086747b715Smrg 17096747b715Smrg/* Windows window styles */ 171035c4bbdfSmrg#define HINT_NOFRAME (1L<<0) 17116747b715Smrg#define HINT_BORDER (1L<<1) 171235c4bbdfSmrg#define HINT_SIZEBOX (1L<<2) 171335c4bbdfSmrg#define HINT_CAPTION (1L<<3) 17146747b715Smrg#define HINT_NOMAXIMIZE (1L<<4) 171535c4bbdfSmrg#define HINT_NOMINIMIZE (1L<<5) 171635c4bbdfSmrg#define HINT_NOSYSMENU (1L<<6) 171735c4bbdfSmrg#define HINT_SKIPTASKBAR (1L<<7) 17186747b715Smrg/* These two are used on their own */ 17196747b715Smrg#define HINT_MAX (1L<<0) 17206747b715Smrg#define HINT_MIN (1L<<1) 17216747b715Smrg 17226747b715Smrgstatic void 17231b5d61b8SmrgwinApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) 17246747b715Smrg{ 17251b5d61b8Smrg 17261b5d61b8Smrg xcb_connection_t *conn = pWMInfo->conn; 17271b5d61b8Smrg static xcb_atom_t windowState, motif_wm_hints; 17281b5d61b8Smrg static xcb_atom_t hiddenState, fullscreenState, belowState, aboveState, 172935c4bbdfSmrg skiptaskbarState; 17301b5d61b8Smrg static xcb_atom_t splashType; 173135c4bbdfSmrg static int generation; 17321b5d61b8Smrg 17331b5d61b8Smrg unsigned long hint = 0, maxmin = 0; 173435c4bbdfSmrg unsigned long style, exStyle; 173535c4bbdfSmrg 173635c4bbdfSmrg if (!hWnd) 173735c4bbdfSmrg return; 173835c4bbdfSmrg if (!IsWindow(hWnd)) 173935c4bbdfSmrg return; 174035c4bbdfSmrg 174135c4bbdfSmrg if (generation != serverGeneration) { 174235c4bbdfSmrg generation = serverGeneration; 17431b5d61b8Smrg windowState = intern_atom(conn, "_NET_WM_STATE"); 17441b5d61b8Smrg motif_wm_hints = intern_atom(conn, "_MOTIF_WM_HINTS"); 17451b5d61b8Smrg hiddenState = intern_atom(conn, "_NET_WM_STATE_HIDDEN"); 17461b5d61b8Smrg fullscreenState = intern_atom(conn, "_NET_WM_STATE_FULLSCREEN"); 17471b5d61b8Smrg belowState = intern_atom(conn, "_NET_WM_STATE_BELOW"); 17481b5d61b8Smrg aboveState = intern_atom(conn, "_NET_WM_STATE_ABOVE"); 17491b5d61b8Smrg skiptaskbarState = intern_atom(conn, "_NET_WM_STATE_SKIP_TASKBAR"); 17501b5d61b8Smrg splashType = intern_atom(conn, "_NET_WM_WINDOW_TYPE_SPLASHSCREEN"); 175135c4bbdfSmrg } 17526747b715Smrg 17531b5d61b8Smrg { 17541b5d61b8Smrg xcb_get_property_cookie_t cookie_wm_state = xcb_get_property(conn, FALSE, iWindow, windowState, XCB_ATOM_ATOM, 0L, INT_MAX); 17551b5d61b8Smrg xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie_wm_state, NULL); 17561b5d61b8Smrg if (reply) { 17571b5d61b8Smrg int i; 17581b5d61b8Smrg int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); 17591b5d61b8Smrg xcb_atom_t *pAtom = xcb_get_property_value(reply); 176035c4bbdfSmrg 176135c4bbdfSmrg for (i = 0; i < nitems; i++) { 176235c4bbdfSmrg if (pAtom[i] == skiptaskbarState) 176335c4bbdfSmrg hint |= HINT_SKIPTASKBAR; 176435c4bbdfSmrg if (pAtom[i] == hiddenState) 176535c4bbdfSmrg maxmin |= HINT_MIN; 176635c4bbdfSmrg else if (pAtom[i] == fullscreenState) 176735c4bbdfSmrg maxmin |= HINT_MAX; 176835c4bbdfSmrg if (pAtom[i] == belowState) 176935c4bbdfSmrg *zstyle = HWND_BOTTOM; 177035c4bbdfSmrg else if (pAtom[i] == aboveState) 177135c4bbdfSmrg *zstyle = HWND_TOPMOST; 177235c4bbdfSmrg } 177335c4bbdfSmrg 17741b5d61b8Smrg free(reply); 17751b5d61b8Smrg } 17766747b715Smrg } 17776747b715Smrg 17781b5d61b8Smrg { 17791b5d61b8Smrg xcb_get_property_cookie_t cookie_mwm_hint = xcb_get_property(conn, FALSE, iWindow, motif_wm_hints, motif_wm_hints, 0L, sizeof(MwmHints)); 17801b5d61b8Smrg xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie_mwm_hint, NULL); 17811b5d61b8Smrg if (reply) { 17821b5d61b8Smrg int nitems = xcb_get_property_value_length(reply)/4; 17831b5d61b8Smrg MwmHints *mwm_hint = xcb_get_property_value(reply); 17841b5d61b8Smrg if (mwm_hint && (nitems >= PropMwmHintsElements) && 178535c4bbdfSmrg (mwm_hint->flags & MwmHintsDecorations)) { 178635c4bbdfSmrg if (!mwm_hint->decorations) 178735c4bbdfSmrg hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); 178835c4bbdfSmrg else if (!(mwm_hint->decorations & MwmDecorAll)) { 178935c4bbdfSmrg if (mwm_hint->decorations & MwmDecorBorder) 179035c4bbdfSmrg hint |= HINT_BORDER; 179135c4bbdfSmrg if (mwm_hint->decorations & MwmDecorHandle) 179235c4bbdfSmrg hint |= HINT_SIZEBOX; 179335c4bbdfSmrg if (mwm_hint->decorations & MwmDecorTitle) 179435c4bbdfSmrg hint |= HINT_CAPTION; 179535c4bbdfSmrg if (!(mwm_hint->decorations & MwmDecorMenu)) 179635c4bbdfSmrg hint |= HINT_NOSYSMENU; 179735c4bbdfSmrg if (!(mwm_hint->decorations & MwmDecorMinimize)) 179835c4bbdfSmrg hint |= HINT_NOMINIMIZE; 179935c4bbdfSmrg if (!(mwm_hint->decorations & MwmDecorMaximize)) 180035c4bbdfSmrg hint |= HINT_NOMAXIMIZE; 180135c4bbdfSmrg } 180235c4bbdfSmrg else { 180335c4bbdfSmrg /* 180435c4bbdfSmrg MwmDecorAll means all decorations *except* those specified by other flag 180535c4bbdfSmrg bits that are set. Not yet implemented. 180635c4bbdfSmrg */ 180735c4bbdfSmrg } 180835c4bbdfSmrg } 18091b5d61b8Smrg free(reply); 18101b5d61b8Smrg } 181135c4bbdfSmrg } 181235c4bbdfSmrg 18131b5d61b8Smrg { 18141b5d61b8Smrg int i; 18151b5d61b8Smrg xcb_ewmh_get_atoms_reply_t type; 18161b5d61b8Smrg xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type(&pWMInfo->ewmh, iWindow); 18171b5d61b8Smrg if (xcb_ewmh_get_wm_window_type_reply(&pWMInfo->ewmh, cookie, &type, NULL)) { 18181b5d61b8Smrg for (i = 0; i < type.atoms_len; i++) { 18191b5d61b8Smrg if (type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK) { 182035c4bbdfSmrg hint = (hint & ~HINT_NOFRAME) | HINT_SKIPTASKBAR | HINT_SIZEBOX; 182135c4bbdfSmrg *zstyle = HWND_TOPMOST; 182235c4bbdfSmrg } 18231b5d61b8Smrg else if ((type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH) 18241b5d61b8Smrg || (type.atoms[i] == splashType)) { 18251b5d61b8Smrg hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); 18261b5d61b8Smrg *zstyle = HWND_TOPMOST; 18271b5d61b8Smrg } 182835c4bbdfSmrg } 18291b5d61b8Smrg } 18306747b715Smrg } 18316747b715Smrg 18326747b715Smrg { 18331b5d61b8Smrg xcb_size_hints_t size_hints; 18341b5d61b8Smrg xcb_get_property_cookie_t cookie; 18351b5d61b8Smrg 18361b5d61b8Smrg cookie = xcb_icccm_get_wm_normal_hints(conn, iWindow); 18371b5d61b8Smrg if (xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &size_hints, NULL)) { 18381b5d61b8Smrg if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) { 183935c4bbdfSmrg 18401b5d61b8Smrg /* Not maximizable if a maximum size is specified, and that size 18411b5d61b8Smrg is smaller (in either dimension) than the screen size */ 18421b5d61b8Smrg if ((size_hints.max_width < GetSystemMetrics(SM_CXVIRTUALSCREEN)) 18431b5d61b8Smrg || (size_hints.max_height < GetSystemMetrics(SM_CYVIRTUALSCREEN))) 18441b5d61b8Smrg hint |= HINT_NOMAXIMIZE; 184535c4bbdfSmrg 18461b5d61b8Smrg if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) { 184735c4bbdfSmrg /* 184835c4bbdfSmrg If both minimum size and maximum size are specified and are the same, 184935c4bbdfSmrg don't bother with a resizing frame 185035c4bbdfSmrg */ 18511b5d61b8Smrg if ((size_hints.min_width == size_hints.max_width) 18521b5d61b8Smrg && (size_hints.min_height == size_hints.max_height)) 185335c4bbdfSmrg hint = (hint & ~HINT_SIZEBOX); 185435c4bbdfSmrg } 185535c4bbdfSmrg } 185635c4bbdfSmrg } 18576747b715Smrg } 18586747b715Smrg 185935c4bbdfSmrg /* 186035c4bbdfSmrg Override hint settings from above with settings from config file and set 186135c4bbdfSmrg application id for grouping. 186235c4bbdfSmrg */ 186335c4bbdfSmrg { 186435c4bbdfSmrg char *application_id = 0; 18651b5d61b8Smrg char *window_name = 0; 18661b5d61b8Smrg char *res_name = 0; 18671b5d61b8Smrg char *res_class = 0; 186835c4bbdfSmrg 18691b5d61b8Smrg GetClassNames(pWMInfo, iWindow, &res_name, &res_class, &window_name); 187035c4bbdfSmrg 18711b5d61b8Smrg style = STYLE_NONE; 18721b5d61b8Smrg style = winOverrideStyle(res_name, res_class, window_name); 187335c4bbdfSmrg 187435c4bbdfSmrg#define APPLICATION_ID_FORMAT "%s.xwin.%s" 187535c4bbdfSmrg#define APPLICATION_ID_UNKNOWN "unknown" 18761b5d61b8Smrg if (res_class) { 18771b5d61b8Smrg asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME, 18781b5d61b8Smrg res_class); 187935c4bbdfSmrg } 188035c4bbdfSmrg else { 18811b5d61b8Smrg asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME, 18821b5d61b8Smrg APPLICATION_ID_UNKNOWN); 188335c4bbdfSmrg } 18841b5d61b8Smrg winSetAppUserModelID(hWnd, application_id); 18851b5d61b8Smrg 18861b5d61b8Smrg free(application_id); 18871b5d61b8Smrg free(res_name); 18881b5d61b8Smrg free(res_class); 18891b5d61b8Smrg free(window_name); 189035c4bbdfSmrg } 18916747b715Smrg 189235c4bbdfSmrg if (style & STYLE_TOPMOST) 189335c4bbdfSmrg *zstyle = HWND_TOPMOST; 189435c4bbdfSmrg else if (style & STYLE_MAXIMIZE) 189535c4bbdfSmrg maxmin = (hint & ~HINT_MIN) | HINT_MAX; 189635c4bbdfSmrg else if (style & STYLE_MINIMIZE) 189735c4bbdfSmrg maxmin = (hint & ~HINT_MAX) | HINT_MIN; 189835c4bbdfSmrg else if (style & STYLE_BOTTOM) 189935c4bbdfSmrg *zstyle = HWND_BOTTOM; 190035c4bbdfSmrg 190135c4bbdfSmrg if (maxmin & HINT_MAX) 190235c4bbdfSmrg SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); 190335c4bbdfSmrg else if (maxmin & HINT_MIN) 190435c4bbdfSmrg SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); 190535c4bbdfSmrg 190635c4bbdfSmrg if (style & STYLE_NOTITLE) 190735c4bbdfSmrg hint = 190835c4bbdfSmrg (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) | 190935c4bbdfSmrg HINT_SIZEBOX; 191035c4bbdfSmrg else if (style & STYLE_OUTLINE) 191135c4bbdfSmrg hint = 191235c4bbdfSmrg (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) | 191335c4bbdfSmrg HINT_BORDER; 191435c4bbdfSmrg else if (style & STYLE_NOFRAME) 191535c4bbdfSmrg hint = 191635c4bbdfSmrg (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | 191735c4bbdfSmrg HINT_NOFRAME; 191835c4bbdfSmrg 191935c4bbdfSmrg /* Now apply styles to window */ 192035c4bbdfSmrg style = GetWindowLongPtr(hWnd, GWL_STYLE); 192135c4bbdfSmrg if (!style) 192235c4bbdfSmrg return; /* GetWindowLongPointer returns 0 on failure, we hope this isn't a valid style */ 192335c4bbdfSmrg 192435c4bbdfSmrg style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ 192535c4bbdfSmrg 192635c4bbdfSmrg if (!(hint & ~HINT_SKIPTASKBAR)) /* No hints, default */ 192735c4bbdfSmrg style = style | WS_CAPTION | WS_SIZEBOX; 192835c4bbdfSmrg else if (hint & HINT_NOFRAME) /* No frame, no decorations */ 192935c4bbdfSmrg style = style & ~WS_CAPTION & ~WS_SIZEBOX; 193035c4bbdfSmrg else 193135c4bbdfSmrg style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) | 193235c4bbdfSmrg ((hint & HINT_SIZEBOX) ? WS_SIZEBOX : 0) | 193335c4bbdfSmrg ((hint & HINT_CAPTION) ? WS_CAPTION : 0); 193435c4bbdfSmrg 193535c4bbdfSmrg if (hint & HINT_NOMAXIMIZE) 193635c4bbdfSmrg style = style & ~WS_MAXIMIZEBOX; 193735c4bbdfSmrg 193835c4bbdfSmrg if (hint & HINT_NOMINIMIZE) 193935c4bbdfSmrg style = style & ~WS_MINIMIZEBOX; 194035c4bbdfSmrg 194135c4bbdfSmrg if (hint & HINT_NOSYSMENU) 194235c4bbdfSmrg style = style & ~WS_SYSMENU; 194335c4bbdfSmrg 194435c4bbdfSmrg if (hint & HINT_SKIPTASKBAR) 194535c4bbdfSmrg style = style & ~WS_MINIMIZEBOX; /* window will become lost if minimized */ 194635c4bbdfSmrg 194735c4bbdfSmrg SetWindowLongPtr(hWnd, GWL_STYLE, style); 194835c4bbdfSmrg 194935c4bbdfSmrg exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); 195035c4bbdfSmrg if (hint & HINT_SKIPTASKBAR) 195135c4bbdfSmrg exStyle = (exStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW; 195235c4bbdfSmrg else 195335c4bbdfSmrg exStyle = (exStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW; 195435c4bbdfSmrg SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle); 195535c4bbdfSmrg 195635c4bbdfSmrg winDebug 195735c4bbdfSmrg ("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n", 195835c4bbdfSmrg iWindow, hint, style, exStyle); 19596747b715Smrg} 19606747b715Smrg 19616747b715Smrgvoid 196235c4bbdfSmrgwinUpdateWindowPosition(HWND hWnd, HWND * zstyle) 19636747b715Smrg{ 196435c4bbdfSmrg int iX, iY, iWidth, iHeight; 196535c4bbdfSmrg int iDx, iDy; 196635c4bbdfSmrg RECT rcNew; 196735c4bbdfSmrg WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP); 196835c4bbdfSmrg DrawablePtr pDraw = NULL; 196935c4bbdfSmrg 197035c4bbdfSmrg if (!pWin) 197135c4bbdfSmrg return; 197235c4bbdfSmrg pDraw = &pWin->drawable; 197335c4bbdfSmrg if (!pDraw) 197435c4bbdfSmrg return; 197535c4bbdfSmrg 197635c4bbdfSmrg /* Get the X and Y location of the X window */ 197735c4bbdfSmrg iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); 197835c4bbdfSmrg iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); 197935c4bbdfSmrg 198035c4bbdfSmrg /* Get the height and width of the X window */ 198135c4bbdfSmrg iWidth = pWin->drawable.width; 198235c4bbdfSmrg iHeight = pWin->drawable.height; 198335c4bbdfSmrg 198435c4bbdfSmrg /* Setup a rectangle with the X window position and size */ 198535c4bbdfSmrg SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight); 198635c4bbdfSmrg 198735c4bbdfSmrg winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n", 198835c4bbdfSmrg rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); 198935c4bbdfSmrg 199035c4bbdfSmrg AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE, 199135c4bbdfSmrg GetWindowLongPtr(hWnd, GWL_EXSTYLE)); 199235c4bbdfSmrg 199335c4bbdfSmrg /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */ 199435c4bbdfSmrg if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) { 199535c4bbdfSmrg iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left; 199635c4bbdfSmrg rcNew.left += iDx; 199735c4bbdfSmrg rcNew.right += iDx; 19986747b715Smrg } 19996747b715Smrg 200035c4bbdfSmrg if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) { 200135c4bbdfSmrg iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top; 200235c4bbdfSmrg rcNew.top += iDy; 200335c4bbdfSmrg rcNew.bottom += iDy; 20046747b715Smrg } 20056747b715Smrg 200635c4bbdfSmrg winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n", 200735c4bbdfSmrg rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); 20086747b715Smrg 200935c4bbdfSmrg /* Position the Windows window */ 201035c4bbdfSmrg SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top, 201135c4bbdfSmrg rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0); 20126747b715Smrg 20136747b715Smrg} 2014