winmultiwindowwm.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 305b261ecSmrg * 405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 505b261ecSmrg * a copy of this software and associated documentation files (the 605b261ecSmrg *"Software"), to deal in the Software without restriction, including 705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1005b261ecSmrg *the following conditions: 1105b261ecSmrg * 1205b261ecSmrg *The above copyright notice and this permission notice shall be 1305b261ecSmrg *included in all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project 2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2505b261ecSmrg *or other dealings in this Software without prior written authorization 2605b261ecSmrg *from the XFree86 Project. 2705b261ecSmrg * 2805b261ecSmrg * Authors: Kensuke Matsuzaki 2905b261ecSmrg */ 3005b261ecSmrg 3105b261ecSmrg/* X headers */ 3205b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3305b261ecSmrg#include <xwin-config.h> 3405b261ecSmrg#endif 3505b261ecSmrg#include <stdio.h> 3605b261ecSmrg#include <stdlib.h> 3705b261ecSmrg#include <unistd.h> 3805b261ecSmrg#ifdef __CYGWIN__ 3905b261ecSmrg#include <sys/select.h> 4005b261ecSmrg#endif 4105b261ecSmrg#include <fcntl.h> 4205b261ecSmrg#include <setjmp.h> 4305b261ecSmrg#define HANDLE void * 4405b261ecSmrg#include <pthread.h> 4505b261ecSmrg#undef HANDLE 4605b261ecSmrg#include <X11/X.h> 4705b261ecSmrg#include <X11/Xatom.h> 4805b261ecSmrg#include <X11/Xlib.h> 4905b261ecSmrg#include <X11/Xlocale.h> 5005b261ecSmrg#include <X11/Xproto.h> 5105b261ecSmrg#include <X11/Xutil.h> 5205b261ecSmrg#include <X11/cursorfont.h> 5305b261ecSmrg 5405b261ecSmrg/* Windows headers */ 5505b261ecSmrg#ifdef __CYGWIN__ 5605b261ecSmrg/* Fixups to prevent collisions between Windows and X headers */ 5705b261ecSmrg#define ATOM DWORD 5805b261ecSmrg 5905b261ecSmrg#include <windows.h> 6005b261ecSmrg#else 6105b261ecSmrg#include <Xwindows.h> 6205b261ecSmrg#endif 6305b261ecSmrg 6405b261ecSmrg/* Local headers */ 6505b261ecSmrg#include "objbase.h" 6605b261ecSmrg#include "ddraw.h" 6705b261ecSmrg#include "winwindow.h" 6805b261ecSmrg#ifdef XWIN_MULTIWINDOWEXTWM 6905b261ecSmrg#include "windowswmstr.h" 7005b261ecSmrg#endif 7105b261ecSmrg 7205b261ecSmrgextern void winDebug(const char *format, ...); 7305b261ecSmrg 7405b261ecSmrg#ifndef CYGDEBUG 7505b261ecSmrg#define CYGDEBUG NO 7605b261ecSmrg#endif 7705b261ecSmrg 7805b261ecSmrg/* 7905b261ecSmrg * Constant defines 8005b261ecSmrg */ 8105b261ecSmrg 8205b261ecSmrg#define WIN_CONNECT_RETRIES 5 8305b261ecSmrg#define WIN_CONNECT_DELAY 5 8405b261ecSmrg#ifdef HAS_DEVWINDOWS 8505b261ecSmrg# define WIN_MSG_QUEUE_FNAME "/dev/windows" 8605b261ecSmrg#endif 8705b261ecSmrg#define WIN_JMP_OKAY 0 8805b261ecSmrg#define WIN_JMP_ERROR_IO 2 8905b261ecSmrg 9005b261ecSmrg 9105b261ecSmrg/* 9205b261ecSmrg * Local structures 9305b261ecSmrg */ 9405b261ecSmrg 9505b261ecSmrgtypedef struct _WMMsgNodeRec { 9605b261ecSmrg winWMMessageRec msg; 9705b261ecSmrg struct _WMMsgNodeRec *pNext; 9805b261ecSmrg} WMMsgNodeRec, *WMMsgNodePtr; 9905b261ecSmrg 10005b261ecSmrgtypedef struct _WMMsgQueueRec { 10105b261ecSmrg struct _WMMsgNodeRec *pHead; 10205b261ecSmrg struct _WMMsgNodeRec *pTail; 10305b261ecSmrg pthread_mutex_t pmMutex; 10405b261ecSmrg pthread_cond_t pcNotEmpty; 10505b261ecSmrg int nQueueSize; 10605b261ecSmrg} WMMsgQueueRec, *WMMsgQueuePtr; 10705b261ecSmrg 10805b261ecSmrgtypedef struct _WMInfo { 10905b261ecSmrg Display *pDisplay; 11005b261ecSmrg WMMsgQueueRec wmMsgQueue; 11105b261ecSmrg Atom atmWmProtos; 11205b261ecSmrg Atom atmWmDelete; 11305b261ecSmrg Atom atmPrivMap; 11405b261ecSmrg Bool fAllowOtherWM; 11505b261ecSmrg} WMInfoRec, *WMInfoPtr; 11605b261ecSmrg 11705b261ecSmrgtypedef struct _WMProcArgRec { 11805b261ecSmrg DWORD dwScreen; 11905b261ecSmrg WMInfoPtr pWMInfo; 12005b261ecSmrg pthread_mutex_t *ppmServerStarted; 12105b261ecSmrg} WMProcArgRec, *WMProcArgPtr; 12205b261ecSmrg 12305b261ecSmrgtypedef struct _XMsgProcArgRec { 12405b261ecSmrg Display *pDisplay; 12505b261ecSmrg DWORD dwScreen; 12605b261ecSmrg WMInfoPtr pWMInfo; 12705b261ecSmrg pthread_mutex_t *ppmServerStarted; 12805b261ecSmrg HWND hwndScreen; 12905b261ecSmrg} XMsgProcArgRec, *XMsgProcArgPtr; 13005b261ecSmrg 13105b261ecSmrg 13205b261ecSmrg/* 13305b261ecSmrg * References to external symbols 13405b261ecSmrg */ 13505b261ecSmrg 13605b261ecSmrgextern char *display; 13705b261ecSmrgextern void ErrorF (const char* /*f*/, ...); 13805b261ecSmrg 13905b261ecSmrg 14005b261ecSmrg/* 14105b261ecSmrg * Prototypes for local functions 14205b261ecSmrg */ 14305b261ecSmrg 14405b261ecSmrgstatic void 14505b261ecSmrgPushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode); 14605b261ecSmrg 14705b261ecSmrgstatic WMMsgNodePtr 14805b261ecSmrgPopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo); 14905b261ecSmrg 15005b261ecSmrgstatic Bool 15105b261ecSmrgInitQueue (WMMsgQueuePtr pQueue); 15205b261ecSmrg 15305b261ecSmrgstatic void 15405b261ecSmrgGetWindowName (Display * pDpy, Window iWin, char **ppName); 15505b261ecSmrg 15605b261ecSmrgstatic int 15705b261ecSmrgSendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData); 15805b261ecSmrg 15905b261ecSmrgstatic void 16005b261ecSmrgUpdateName (WMInfoPtr pWMInfo, Window iWindow); 16105b261ecSmrg 16205b261ecSmrgstatic void* 16305b261ecSmrgwinMultiWindowWMProc (void* pArg); 16405b261ecSmrg 16505b261ecSmrgstatic int 16605b261ecSmrgwinMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr); 16705b261ecSmrg 16805b261ecSmrgstatic int 16905b261ecSmrgwinMultiWindowWMIOErrorHandler (Display *pDisplay); 17005b261ecSmrg 17105b261ecSmrgstatic void * 17205b261ecSmrgwinMultiWindowXMsgProc (void *pArg); 17305b261ecSmrg 17405b261ecSmrgstatic int 17505b261ecSmrgwinMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr); 17605b261ecSmrg 17705b261ecSmrgstatic int 17805b261ecSmrgwinMultiWindowXMsgProcIOErrorHandler (Display *pDisplay); 17905b261ecSmrg 18005b261ecSmrgstatic int 18105b261ecSmrgwinRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr); 18205b261ecSmrg 18305b261ecSmrgstatic void 18405b261ecSmrgwinInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg); 18505b261ecSmrg 18605b261ecSmrg#if 0 18705b261ecSmrgstatic void 18805b261ecSmrgPreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction); 18905b261ecSmrg#endif 19005b261ecSmrg 19105b261ecSmrgstatic Bool 19205b261ecSmrgCheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen); 19305b261ecSmrg 19405b261ecSmrg 19505b261ecSmrg/* 19605b261ecSmrg * Local globals 19705b261ecSmrg */ 19805b261ecSmrg 19905b261ecSmrgstatic jmp_buf g_jmpWMEntry; 20005b261ecSmrgstatic jmp_buf g_jmpXMsgProcEntry; 20105b261ecSmrgstatic Bool g_shutdown = FALSE; 20205b261ecSmrgstatic Bool redirectError = FALSE; 20305b261ecSmrgstatic Bool g_fAnotherWMRunnig = FALSE; 20405b261ecSmrg 20505b261ecSmrg/* 20605b261ecSmrg * PushMessage - Push a message onto the queue 20705b261ecSmrg */ 20805b261ecSmrg 20905b261ecSmrgstatic void 21005b261ecSmrgPushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) 21105b261ecSmrg{ 21205b261ecSmrg 21305b261ecSmrg /* Lock the queue mutex */ 21405b261ecSmrg pthread_mutex_lock (&pQueue->pmMutex); 21505b261ecSmrg 21605b261ecSmrg pNode->pNext = NULL; 21705b261ecSmrg 21805b261ecSmrg if (pQueue->pTail != NULL) 21905b261ecSmrg { 22005b261ecSmrg pQueue->pTail->pNext = pNode; 22105b261ecSmrg } 22205b261ecSmrg pQueue->pTail = pNode; 22305b261ecSmrg 22405b261ecSmrg if (pQueue->pHead == NULL) 22505b261ecSmrg { 22605b261ecSmrg pQueue->pHead = pNode; 22705b261ecSmrg } 22805b261ecSmrg 22905b261ecSmrg 23005b261ecSmrg#if 0 23105b261ecSmrg switch (pNode->msg.msg) 23205b261ecSmrg { 23305b261ecSmrg case WM_WM_MOVE: 23405b261ecSmrg ErrorF ("\tWM_WM_MOVE\n"); 23505b261ecSmrg break; 23605b261ecSmrg case WM_WM_SIZE: 23705b261ecSmrg ErrorF ("\tWM_WM_SIZE\n"); 23805b261ecSmrg break; 23905b261ecSmrg case WM_WM_RAISE: 24005b261ecSmrg ErrorF ("\tWM_WM_RAISE\n"); 24105b261ecSmrg break; 24205b261ecSmrg case WM_WM_LOWER: 24305b261ecSmrg ErrorF ("\tWM_WM_LOWER\n"); 24405b261ecSmrg break; 24505b261ecSmrg case WM_WM_MAP: 24605b261ecSmrg ErrorF ("\tWM_WM_MAP\n"); 24705b261ecSmrg break; 24805b261ecSmrg case WM_WM_UNMAP: 24905b261ecSmrg ErrorF ("\tWM_WM_UNMAP\n"); 25005b261ecSmrg break; 25105b261ecSmrg case WM_WM_KILL: 25205b261ecSmrg ErrorF ("\tWM_WM_KILL\n"); 25305b261ecSmrg break; 25405b261ecSmrg case WM_WM_ACTIVATE: 25505b261ecSmrg ErrorF ("\tWM_WM_ACTIVATE\n"); 25605b261ecSmrg break; 25705b261ecSmrg default: 25805b261ecSmrg ErrorF ("\tUnknown Message.\n"); 25905b261ecSmrg break; 26005b261ecSmrg } 26105b261ecSmrg#endif 26205b261ecSmrg 26305b261ecSmrg /* Increase the count of elements in the queue by one */ 26405b261ecSmrg ++(pQueue->nQueueSize); 26505b261ecSmrg 26605b261ecSmrg /* Release the queue mutex */ 26705b261ecSmrg pthread_mutex_unlock (&pQueue->pmMutex); 26805b261ecSmrg 26905b261ecSmrg /* Signal that the queue is not empty */ 27005b261ecSmrg pthread_cond_signal (&pQueue->pcNotEmpty); 27105b261ecSmrg} 27205b261ecSmrg 27305b261ecSmrg 27405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 27505b261ecSmrg/* 27605b261ecSmrg * QueueSize - Return the size of the queue 27705b261ecSmrg */ 27805b261ecSmrg 27905b261ecSmrgstatic int 28005b261ecSmrgQueueSize (WMMsgQueuePtr pQueue) 28105b261ecSmrg{ 28205b261ecSmrg WMMsgNodePtr pNode; 28305b261ecSmrg int nSize = 0; 28405b261ecSmrg 28505b261ecSmrg /* Loop through all elements in the queue */ 28605b261ecSmrg for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) 28705b261ecSmrg ++nSize; 28805b261ecSmrg 28905b261ecSmrg return nSize; 29005b261ecSmrg} 29105b261ecSmrg#endif 29205b261ecSmrg 29305b261ecSmrg 29405b261ecSmrg/* 29505b261ecSmrg * PopMessage - Pop a message from the queue 29605b261ecSmrg */ 29705b261ecSmrg 29805b261ecSmrgstatic WMMsgNodePtr 29905b261ecSmrgPopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo) 30005b261ecSmrg{ 30105b261ecSmrg WMMsgNodePtr pNode; 30205b261ecSmrg 30305b261ecSmrg /* Lock the queue mutex */ 30405b261ecSmrg pthread_mutex_lock (&pQueue->pmMutex); 30505b261ecSmrg 30605b261ecSmrg /* Wait for --- */ 30705b261ecSmrg while (pQueue->pHead == NULL) 30805b261ecSmrg { 30905b261ecSmrg pthread_cond_wait (&pQueue->pcNotEmpty, &pQueue->pmMutex); 31005b261ecSmrg } 31105b261ecSmrg 31205b261ecSmrg pNode = pQueue->pHead; 31305b261ecSmrg if (pQueue->pHead != NULL) 31405b261ecSmrg { 31505b261ecSmrg pQueue->pHead = pQueue->pHead->pNext; 31605b261ecSmrg } 31705b261ecSmrg 31805b261ecSmrg if (pQueue->pTail == pNode) 31905b261ecSmrg { 32005b261ecSmrg pQueue->pTail = NULL; 32105b261ecSmrg } 32205b261ecSmrg 32305b261ecSmrg /* Drop the number of elements in the queue by one */ 32405b261ecSmrg --(pQueue->nQueueSize); 32505b261ecSmrg 32605b261ecSmrg#if CYGMULTIWINDOW_DEBUG 32705b261ecSmrg ErrorF ("Queue Size %d %d\n", pQueue->nQueueSize, QueueSize(pQueue)); 32805b261ecSmrg#endif 32905b261ecSmrg 33005b261ecSmrg /* Release the queue mutex */ 33105b261ecSmrg pthread_mutex_unlock (&pQueue->pmMutex); 33205b261ecSmrg 33305b261ecSmrg return pNode; 33405b261ecSmrg} 33505b261ecSmrg 33605b261ecSmrg 33705b261ecSmrg#if 0 33805b261ecSmrg/* 33905b261ecSmrg * HaveMessage - 34005b261ecSmrg */ 34105b261ecSmrg 34205b261ecSmrgstatic Bool 34305b261ecSmrgHaveMessage (WMMsgQueuePtr pQueue, UINT msg, Window iWindow) 34405b261ecSmrg{ 34505b261ecSmrg WMMsgNodePtr pNode; 34605b261ecSmrg 34705b261ecSmrg for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) 34805b261ecSmrg { 34905b261ecSmrg if (pNode->msg.msg==msg && pNode->msg.iWindow==iWindow) 35005b261ecSmrg return True; 35105b261ecSmrg } 35205b261ecSmrg 35305b261ecSmrg return False; 35405b261ecSmrg} 35505b261ecSmrg#endif 35605b261ecSmrg 35705b261ecSmrg 35805b261ecSmrg/* 35905b261ecSmrg * InitQueue - Initialize the Window Manager message queue 36005b261ecSmrg */ 36105b261ecSmrg 36205b261ecSmrgstatic 36305b261ecSmrgBool 36405b261ecSmrgInitQueue (WMMsgQueuePtr pQueue) 36505b261ecSmrg{ 36605b261ecSmrg /* Check if the pQueue pointer is NULL */ 36705b261ecSmrg if (pQueue == NULL) 36805b261ecSmrg { 36905b261ecSmrg ErrorF ("InitQueue - pQueue is NULL. Exiting.\n"); 37005b261ecSmrg return FALSE; 37105b261ecSmrg } 37205b261ecSmrg 37305b261ecSmrg /* Set the head and tail to NULL */ 37405b261ecSmrg pQueue->pHead = NULL; 37505b261ecSmrg pQueue->pTail = NULL; 37605b261ecSmrg 37705b261ecSmrg /* There are no elements initially */ 37805b261ecSmrg pQueue->nQueueSize = 0; 37905b261ecSmrg 38005b261ecSmrg#if CYGMULTIWINDOW_DEBUG 38105b261ecSmrg ErrorF ("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize, 38205b261ecSmrg QueueSize(pQueue)); 38305b261ecSmrg#endif 38405b261ecSmrg 38505b261ecSmrg ErrorF ("InitQueue - Calling pthread_mutex_init\n"); 38605b261ecSmrg 38705b261ecSmrg /* Create synchronization objects */ 38805b261ecSmrg pthread_mutex_init (&pQueue->pmMutex, NULL); 38905b261ecSmrg 39005b261ecSmrg ErrorF ("InitQueue - pthread_mutex_init returned\n"); 39105b261ecSmrg ErrorF ("InitQueue - Calling pthread_cond_init\n"); 39205b261ecSmrg 39305b261ecSmrg pthread_cond_init (&pQueue->pcNotEmpty, NULL); 39405b261ecSmrg 39505b261ecSmrg ErrorF ("InitQueue - pthread_cond_init returned\n"); 39605b261ecSmrg 39705b261ecSmrg return TRUE; 39805b261ecSmrg} 39905b261ecSmrg 40005b261ecSmrg 40105b261ecSmrg/* 40205b261ecSmrg * GetWindowName - Retrieve the title of an X Window 40305b261ecSmrg */ 40405b261ecSmrg 40505b261ecSmrgstatic void 40605b261ecSmrgGetWindowName (Display *pDisplay, Window iWin, char **ppName) 40705b261ecSmrg{ 40805b261ecSmrg int nResult, nNum; 40905b261ecSmrg char **ppList; 41005b261ecSmrg XTextProperty xtpName; 41105b261ecSmrg 41205b261ecSmrg#if CYGMULTIWINDOW_DEBUG 41305b261ecSmrg ErrorF ("GetWindowName\n"); 41405b261ecSmrg#endif 41505b261ecSmrg 41605b261ecSmrg /* Intialize ppName to NULL */ 41705b261ecSmrg *ppName = NULL; 41805b261ecSmrg 41905b261ecSmrg /* Try to get --- */ 42005b261ecSmrg nResult = XGetWMName (pDisplay, iWin, &xtpName); 42105b261ecSmrg if (!nResult || !xtpName.value || !xtpName.nitems) 42205b261ecSmrg { 42305b261ecSmrg#if CYGMULTIWINDOW_DEBUG 42405b261ecSmrg ErrorF ("GetWindowName - XGetWMName failed. No name.\n"); 42505b261ecSmrg#endif 42605b261ecSmrg return; 42705b261ecSmrg } 42805b261ecSmrg 42905b261ecSmrg /* */ 43005b261ecSmrg if (xtpName.encoding == XA_STRING) 43105b261ecSmrg { 43205b261ecSmrg /* */ 43305b261ecSmrg if (xtpName.value) 43405b261ecSmrg { 43505b261ecSmrg int size = xtpName.nitems * (xtpName.format >> 3); 43605b261ecSmrg *ppName = malloc(size + 1); 43705b261ecSmrg strncpy(*ppName, xtpName.value, size); 43805b261ecSmrg (*ppName)[size] = 0; 43905b261ecSmrg XFree (xtpName.value); 44005b261ecSmrg } 44105b261ecSmrg 44205b261ecSmrg#if CYGMULTIWINDOW_DEBUG 44305b261ecSmrg ErrorF ("GetWindowName - XA_STRING %s\n", *ppName); 44405b261ecSmrg#endif 44505b261ecSmrg } 44605b261ecSmrg else 44705b261ecSmrg { 44805b261ecSmrg if (XmbTextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum) >= Success && nNum > 0 && *ppList) 44905b261ecSmrg { 45005b261ecSmrg *ppName = strdup (*ppList); 45105b261ecSmrg XFreeStringList (ppList); 45205b261ecSmrg } 45305b261ecSmrg XFree (xtpName.value); 45405b261ecSmrg 45505b261ecSmrg#if CYGMULTIWINDOW_DEBUG 45605b261ecSmrg ErrorF ("GetWindowName - %s %s\n", 45705b261ecSmrg XGetAtomName (pDisplay, xtpName.encoding), *ppName); 45805b261ecSmrg#endif 45905b261ecSmrg } 46005b261ecSmrg 46105b261ecSmrg#if CYGMULTIWINDOW_DEBUG 46205b261ecSmrg ErrorF ("GetWindowName - Returning\n"); 46305b261ecSmrg#endif 46405b261ecSmrg} 46505b261ecSmrg 46605b261ecSmrg 46705b261ecSmrg/* 46805b261ecSmrg * Send a message to the X server from the WM thread 46905b261ecSmrg */ 47005b261ecSmrg 47105b261ecSmrgstatic int 47205b261ecSmrgSendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData) 47305b261ecSmrg{ 47405b261ecSmrg XEvent e; 47505b261ecSmrg 47605b261ecSmrg /* Prepare the X event structure */ 47705b261ecSmrg e.type = ClientMessage; 47805b261ecSmrg e.xclient.window = iWin; 47905b261ecSmrg e.xclient.message_type = atmType; 48005b261ecSmrg e.xclient.format = 32; 48105b261ecSmrg e.xclient.data.l[0] = nData; 48205b261ecSmrg e.xclient.data.l[1] = CurrentTime; 48305b261ecSmrg 48405b261ecSmrg /* Send the event to X */ 48505b261ecSmrg return XSendEvent (pDisplay, iWin, False, NoEventMask, &e); 48605b261ecSmrg} 48705b261ecSmrg 48805b261ecSmrg 48905b261ecSmrg/* 49005b261ecSmrg * Updates the name of a HWND according to its X WM_NAME property 49105b261ecSmrg */ 49205b261ecSmrg 49305b261ecSmrgstatic void 49405b261ecSmrgUpdateName (WMInfoPtr pWMInfo, Window iWindow) 49505b261ecSmrg{ 49605b261ecSmrg char *pszName; 49705b261ecSmrg Atom atmType; 49805b261ecSmrg int fmtRet; 49905b261ecSmrg unsigned long items, remain; 50005b261ecSmrg HWND *retHwnd, hWnd; 50105b261ecSmrg XWindowAttributes attr; 50205b261ecSmrg 50305b261ecSmrg hWnd = 0; 50405b261ecSmrg 50505b261ecSmrg /* See if we can get the cached HWND for this window... */ 50605b261ecSmrg if (XGetWindowProperty (pWMInfo->pDisplay, 50705b261ecSmrg iWindow, 50805b261ecSmrg pWMInfo->atmPrivMap, 50905b261ecSmrg 0, 51005b261ecSmrg 1, 51105b261ecSmrg False, 51205b261ecSmrg XA_INTEGER,//pWMInfo->atmPrivMap, 51305b261ecSmrg &atmType, 51405b261ecSmrg &fmtRet, 51505b261ecSmrg &items, 51605b261ecSmrg &remain, 51705b261ecSmrg (unsigned char **) &retHwnd) == Success) 51805b261ecSmrg { 51905b261ecSmrg if (retHwnd) 52005b261ecSmrg { 52105b261ecSmrg hWnd = *retHwnd; 52205b261ecSmrg XFree (retHwnd); 52305b261ecSmrg } 52405b261ecSmrg } 52505b261ecSmrg 52605b261ecSmrg /* Some sanity checks */ 52705b261ecSmrg if (!hWnd) return; 52805b261ecSmrg if (!IsWindow (hWnd)) return; 52905b261ecSmrg 53005b261ecSmrg /* Set the Windows window name */ 53105b261ecSmrg GetWindowName (pWMInfo->pDisplay, iWindow, &pszName); 53205b261ecSmrg if (pszName) 53305b261ecSmrg { 53405b261ecSmrg /* Get the window attributes */ 53505b261ecSmrg XGetWindowAttributes (pWMInfo->pDisplay, 53605b261ecSmrg iWindow, 53705b261ecSmrg &attr); 53805b261ecSmrg if (!attr.override_redirect) 53905b261ecSmrg { 54005b261ecSmrg SetWindowText (hWnd, pszName); 54105b261ecSmrg winUpdateIcon (iWindow); 54205b261ecSmrg } 54305b261ecSmrg 54405b261ecSmrg free (pszName); 54505b261ecSmrg } 54605b261ecSmrg} 54705b261ecSmrg 54805b261ecSmrg 54905b261ecSmrg#if 0 55005b261ecSmrg/* 55105b261ecSmrg * Fix up any differences between the X11 and Win32 window stacks 55205b261ecSmrg * starting at the window passed in 55305b261ecSmrg */ 55405b261ecSmrgstatic void 55505b261ecSmrgPreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction) 55605b261ecSmrg{ 55705b261ecSmrg Atom atmType; 55805b261ecSmrg int fmtRet; 55905b261ecSmrg unsigned long items, remain; 56005b261ecSmrg HWND hWnd, *retHwnd; 56105b261ecSmrg DWORD myWinProcID, winProcID; 56205b261ecSmrg Window xWindow; 56305b261ecSmrg WINDOWPLACEMENT wndPlace; 56405b261ecSmrg 56505b261ecSmrg hWnd = NULL; 56605b261ecSmrg /* See if we can get the cached HWND for this window... */ 56705b261ecSmrg if (XGetWindowProperty (pWMInfo->pDisplay, 56805b261ecSmrg iWindow, 56905b261ecSmrg pWMInfo->atmPrivMap, 57005b261ecSmrg 0, 57105b261ecSmrg 1, 57205b261ecSmrg False, 57305b261ecSmrg XA_INTEGER,//pWMInfo->atmPrivMap, 57405b261ecSmrg &atmType, 57505b261ecSmrg &fmtRet, 57605b261ecSmrg &items, 57705b261ecSmrg &remain, 57805b261ecSmrg (unsigned char **) &retHwnd) == Success) 57905b261ecSmrg { 58005b261ecSmrg if (retHwnd) 58105b261ecSmrg { 58205b261ecSmrg hWnd = *retHwnd; 58305b261ecSmrg XFree (retHwnd); 58405b261ecSmrg } 58505b261ecSmrg } 58605b261ecSmrg 58705b261ecSmrg if (!hWnd) return; 58805b261ecSmrg 58905b261ecSmrg GetWindowThreadProcessId (hWnd, &myWinProcID); 59005b261ecSmrg hWnd = GetNextWindow (hWnd, direction); 59105b261ecSmrg 59205b261ecSmrg while (hWnd) { 59305b261ecSmrg GetWindowThreadProcessId (hWnd, &winProcID); 59405b261ecSmrg if (winProcID == myWinProcID) 59505b261ecSmrg { 59605b261ecSmrg wndPlace.length = sizeof(WINDOWPLACEMENT); 59705b261ecSmrg GetWindowPlacement (hWnd, &wndPlace); 59805b261ecSmrg if ( !(wndPlace.showCmd==SW_HIDE || 59905b261ecSmrg wndPlace.showCmd==SW_MINIMIZE) ) 60005b261ecSmrg { 60105b261ecSmrg xWindow = (Window)GetProp (hWnd, WIN_WID_PROP); 60205b261ecSmrg if (xWindow) 60305b261ecSmrg { 60405b261ecSmrg if (direction==GW_HWNDPREV) 60505b261ecSmrg XRaiseWindow (pWMInfo->pDisplay, xWindow); 60605b261ecSmrg else 60705b261ecSmrg XLowerWindow (pWMInfo->pDisplay, xWindow); 60805b261ecSmrg } 60905b261ecSmrg } 61005b261ecSmrg } 61105b261ecSmrg hWnd = GetNextWindow(hWnd, direction); 61205b261ecSmrg } 61305b261ecSmrg} 61405b261ecSmrg#endif /* PreserveWin32Stack */ 61505b261ecSmrg 61605b261ecSmrg 61705b261ecSmrg/* 61805b261ecSmrg * winMultiWindowWMProc 61905b261ecSmrg */ 62005b261ecSmrg 62105b261ecSmrgstatic void * 62205b261ecSmrgwinMultiWindowWMProc (void *pArg) 62305b261ecSmrg{ 62405b261ecSmrg WMProcArgPtr pProcArg = (WMProcArgPtr)pArg; 62505b261ecSmrg WMInfoPtr pWMInfo = pProcArg->pWMInfo; 62605b261ecSmrg 62705b261ecSmrg /* Initialize the Window Manager */ 62805b261ecSmrg winInitMultiWindowWM (pWMInfo, pProcArg); 62905b261ecSmrg 63005b261ecSmrg#if CYGMULTIWINDOW_DEBUG 63105b261ecSmrg ErrorF ("winMultiWindowWMProc ()\n"); 63205b261ecSmrg#endif 63305b261ecSmrg 63405b261ecSmrg /* Loop until we explicity break out */ 63505b261ecSmrg for (;;) 63605b261ecSmrg { 63705b261ecSmrg WMMsgNodePtr pNode; 63805b261ecSmrg 63905b261ecSmrg if(g_fAnotherWMRunnig)/* Another Window manager exists. */ 64005b261ecSmrg { 64105b261ecSmrg Sleep (1000); 64205b261ecSmrg continue; 64305b261ecSmrg } 64405b261ecSmrg 64505b261ecSmrg /* Pop a message off of our queue */ 64605b261ecSmrg pNode = PopMessage (&pWMInfo->wmMsgQueue, pWMInfo); 64705b261ecSmrg if (pNode == NULL) 64805b261ecSmrg { 64905b261ecSmrg /* Bail if PopMessage returns without a message */ 65005b261ecSmrg /* NOTE: Remember that PopMessage is a blocking function. */ 65105b261ecSmrg ErrorF ("winMultiWindowWMProc - Queue is Empty? Exiting.\n"); 65205b261ecSmrg pthread_exit (NULL); 65305b261ecSmrg } 65405b261ecSmrg 65505b261ecSmrg#if CYGMULTIWINDOW_DEBUG 65605b261ecSmrg ErrorF ("winMultiWindowWMProc - %d ms MSG: %d ID: %d\n", 65705b261ecSmrg GetTickCount (), (int)pNode->msg.msg, (int)pNode->msg.dwID); 65805b261ecSmrg#endif 65905b261ecSmrg 66005b261ecSmrg /* Branch on the message type */ 66105b261ecSmrg switch (pNode->msg.msg) 66205b261ecSmrg { 66305b261ecSmrg#if 0 66405b261ecSmrg case WM_WM_MOVE: 66505b261ecSmrg ErrorF ("\tWM_WM_MOVE\n"); 66605b261ecSmrg break; 66705b261ecSmrg 66805b261ecSmrg case WM_WM_SIZE: 66905b261ecSmrg ErrorF ("\tWM_WM_SIZE\n"); 67005b261ecSmrg break; 67105b261ecSmrg#endif 67205b261ecSmrg 67305b261ecSmrg case WM_WM_RAISE: 67405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 67505b261ecSmrg ErrorF ("\tWM_WM_RAISE\n"); 67605b261ecSmrg#endif 67705b261ecSmrg /* Raise the window */ 67805b261ecSmrg XRaiseWindow (pWMInfo->pDisplay, pNode->msg.iWindow); 67905b261ecSmrg#if 0 68005b261ecSmrg PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV); 68105b261ecSmrg#endif 68205b261ecSmrg break; 68305b261ecSmrg 68405b261ecSmrg case WM_WM_LOWER: 68505b261ecSmrg#if CYGMULTIWINDOW_DEBUG 68605b261ecSmrg ErrorF ("\tWM_WM_LOWER\n"); 68705b261ecSmrg#endif 68805b261ecSmrg 68905b261ecSmrg /* Lower the window */ 69005b261ecSmrg XLowerWindow (pWMInfo->pDisplay, pNode->msg.iWindow); 69105b261ecSmrg break; 69205b261ecSmrg 69305b261ecSmrg case WM_WM_MAP: 69405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 69505b261ecSmrg ErrorF ("\tWM_WM_MAP\n"); 69605b261ecSmrg#endif 69705b261ecSmrg /* Put a note as to the HWND associated with this Window */ 69805b261ecSmrg XChangeProperty (pWMInfo->pDisplay, 69905b261ecSmrg pNode->msg.iWindow, 70005b261ecSmrg pWMInfo->atmPrivMap, 70105b261ecSmrg XA_INTEGER,//pWMInfo->atmPrivMap, 70205b261ecSmrg 32, 70305b261ecSmrg PropModeReplace, 70405b261ecSmrg (unsigned char *) &(pNode->msg.hwndWindow), 70505b261ecSmrg 1); 70605b261ecSmrg UpdateName (pWMInfo, pNode->msg.iWindow); 70705b261ecSmrg winUpdateIcon (pNode->msg.iWindow); 70805b261ecSmrg#if 0 70905b261ecSmrg /* Handles the case where there are AOT windows above it in W32 */ 71005b261ecSmrg PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV); 71105b261ecSmrg#endif 71205b261ecSmrg break; 71305b261ecSmrg 71405b261ecSmrg case WM_WM_UNMAP: 71505b261ecSmrg#if CYGMULTIWINDOW_DEBUG 71605b261ecSmrg ErrorF ("\tWM_WM_UNMAP\n"); 71705b261ecSmrg#endif 71805b261ecSmrg 71905b261ecSmrg /* Unmap the window */ 72005b261ecSmrg XUnmapWindow (pWMInfo->pDisplay, pNode->msg.iWindow); 72105b261ecSmrg break; 72205b261ecSmrg 72305b261ecSmrg case WM_WM_KILL: 72405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 72505b261ecSmrg ErrorF ("\tWM_WM_KILL\n"); 72605b261ecSmrg#endif 72705b261ecSmrg { 72805b261ecSmrg int i, n, found = 0; 72905b261ecSmrg Atom *protocols; 73005b261ecSmrg 73105b261ecSmrg /* --- */ 73205b261ecSmrg if (XGetWMProtocols (pWMInfo->pDisplay, 73305b261ecSmrg pNode->msg.iWindow, 73405b261ecSmrg &protocols, 73505b261ecSmrg &n)) 73605b261ecSmrg { 73705b261ecSmrg for (i = 0; i < n; ++i) 73805b261ecSmrg if (protocols[i] == pWMInfo->atmWmDelete) 73905b261ecSmrg ++found; 74005b261ecSmrg 74105b261ecSmrg XFree (protocols); 74205b261ecSmrg } 74305b261ecSmrg 74405b261ecSmrg /* --- */ 74505b261ecSmrg if (found) 74605b261ecSmrg SendXMessage (pWMInfo->pDisplay, 74705b261ecSmrg pNode->msg.iWindow, 74805b261ecSmrg pWMInfo->atmWmProtos, 74905b261ecSmrg pWMInfo->atmWmDelete); 75005b261ecSmrg else 75105b261ecSmrg XKillClient (pWMInfo->pDisplay, 75205b261ecSmrg pNode->msg.iWindow); 75305b261ecSmrg } 75405b261ecSmrg break; 75505b261ecSmrg 75605b261ecSmrg case WM_WM_ACTIVATE: 75705b261ecSmrg#if CYGMULTIWINDOW_DEBUG 75805b261ecSmrg ErrorF ("\tWM_WM_ACTIVATE\n"); 75905b261ecSmrg#endif 76005b261ecSmrg 76105b261ecSmrg /* Set the input focus */ 76205b261ecSmrg XSetInputFocus (pWMInfo->pDisplay, 76305b261ecSmrg pNode->msg.iWindow, 76405b261ecSmrg RevertToPointerRoot, 76505b261ecSmrg CurrentTime); 76605b261ecSmrg break; 76705b261ecSmrg 76805b261ecSmrg case WM_WM_NAME_EVENT: 76905b261ecSmrg UpdateName (pWMInfo, pNode->msg.iWindow); 77005b261ecSmrg break; 77105b261ecSmrg 77205b261ecSmrg case WM_WM_HINTS_EVENT: 77305b261ecSmrg winUpdateIcon (pNode->msg.iWindow); 77405b261ecSmrg break; 77505b261ecSmrg 77605b261ecSmrg case WM_WM_CHANGE_STATE: 77705b261ecSmrg /* Minimize the window in Windows */ 77805b261ecSmrg winMinimizeWindow (pNode->msg.iWindow); 77905b261ecSmrg break; 78005b261ecSmrg 78105b261ecSmrg default: 78205b261ecSmrg ErrorF ("winMultiWindowWMProc - Unknown Message. Exiting.\n"); 78305b261ecSmrg pthread_exit (NULL); 78405b261ecSmrg break; 78505b261ecSmrg } 78605b261ecSmrg 78705b261ecSmrg /* Free the retrieved message */ 78805b261ecSmrg free (pNode); 78905b261ecSmrg 79005b261ecSmrg /* Flush any pending events on our display */ 79105b261ecSmrg XFlush (pWMInfo->pDisplay); 79205b261ecSmrg } 79305b261ecSmrg 79405b261ecSmrg /* Free the condition variable */ 79505b261ecSmrg pthread_cond_destroy (&pWMInfo->wmMsgQueue.pcNotEmpty); 79605b261ecSmrg 79705b261ecSmrg /* Free the mutex variable */ 79805b261ecSmrg pthread_mutex_destroy (&pWMInfo->wmMsgQueue.pmMutex); 79905b261ecSmrg 80005b261ecSmrg /* Free the passed-in argument */ 80105b261ecSmrg free (pProcArg); 80205b261ecSmrg 80305b261ecSmrg#if CYGMULTIWINDOW_DEBUG 80405b261ecSmrg ErrorF("-winMultiWindowWMProc ()\n"); 80505b261ecSmrg#endif 80605b261ecSmrg} 80705b261ecSmrg 80805b261ecSmrg 80905b261ecSmrg/* 81005b261ecSmrg * X message procedure 81105b261ecSmrg */ 81205b261ecSmrg 81305b261ecSmrgstatic void * 81405b261ecSmrgwinMultiWindowXMsgProc (void *pArg) 81505b261ecSmrg{ 81605b261ecSmrg winWMMessageRec msg; 81705b261ecSmrg XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg; 81805b261ecSmrg char pszDisplay[512]; 81905b261ecSmrg int iRetries; 82005b261ecSmrg XEvent event; 82105b261ecSmrg Atom atmWmName; 82205b261ecSmrg Atom atmWmHints; 82305b261ecSmrg Atom atmWmChange; 82405b261ecSmrg int iReturn; 82505b261ecSmrg XIconSize *xis; 82605b261ecSmrg 82705b261ecSmrg ErrorF ("winMultiWindowXMsgProc - Hello\n"); 82805b261ecSmrg 82905b261ecSmrg /* Check that argument pointer is not invalid */ 83005b261ecSmrg if (pProcArg == NULL) 83105b261ecSmrg { 83205b261ecSmrg ErrorF ("winMultiWindowXMsgProc - pProcArg is NULL. Exiting.\n"); 83305b261ecSmrg pthread_exit (NULL); 83405b261ecSmrg } 83505b261ecSmrg 83605b261ecSmrg ErrorF ("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n"); 83705b261ecSmrg 83805b261ecSmrg /* Grab the server started mutex - pause until we get it */ 83905b261ecSmrg iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted); 84005b261ecSmrg if (iReturn != 0) 84105b261ecSmrg { 84205b261ecSmrg ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d. " 84305b261ecSmrg "Exiting.\n", 84405b261ecSmrg iReturn); 84505b261ecSmrg pthread_exit (NULL); 84605b261ecSmrg } 84705b261ecSmrg 84805b261ecSmrg ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); 84905b261ecSmrg 85005b261ecSmrg /* Allow multiple threads to access Xlib */ 85105b261ecSmrg if (XInitThreads () == 0) 85205b261ecSmrg { 85305b261ecSmrg ErrorF ("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n"); 85405b261ecSmrg pthread_exit (NULL); 85505b261ecSmrg } 85605b261ecSmrg 85705b261ecSmrg /* See if X supports the current locale */ 85805b261ecSmrg if (XSupportsLocale () == False) 85905b261ecSmrg { 86005b261ecSmrg ErrorF ("winMultiWindowXMsgProc - Locale not supported by X. " 86105b261ecSmrg "Exiting.\n"); 86205b261ecSmrg pthread_exit (NULL); 86305b261ecSmrg } 86405b261ecSmrg 86505b261ecSmrg /* Release the server started mutex */ 86605b261ecSmrg pthread_mutex_unlock (pProcArg->ppmServerStarted); 86705b261ecSmrg 86805b261ecSmrg ErrorF ("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n"); 86905b261ecSmrg 87005b261ecSmrg /* Set jump point for IO Error exits */ 87105b261ecSmrg iReturn = setjmp (g_jmpXMsgProcEntry); 87205b261ecSmrg 87305b261ecSmrg /* Check if we should continue operations */ 87405b261ecSmrg if (iReturn != WIN_JMP_ERROR_IO 87505b261ecSmrg && iReturn != WIN_JMP_OKAY) 87605b261ecSmrg { 87705b261ecSmrg /* setjmp returned an unknown value, exit */ 87805b261ecSmrg ErrorF ("winInitMultiWindowXMsgProc - setjmp returned: %d. Exiting.\n", 87905b261ecSmrg iReturn); 88005b261ecSmrg pthread_exit (NULL); 88105b261ecSmrg } 88205b261ecSmrg else if (iReturn == WIN_JMP_ERROR_IO) 88305b261ecSmrg { 88405b261ecSmrg ErrorF ("winInitMultiWindowXMsgProc - Caught IO Error. Exiting.\n"); 88505b261ecSmrg pthread_exit (NULL); 88605b261ecSmrg } 88705b261ecSmrg 88805b261ecSmrg /* Install our error handler */ 88905b261ecSmrg XSetErrorHandler (winMultiWindowXMsgProcErrorHandler); 89005b261ecSmrg XSetIOErrorHandler (winMultiWindowXMsgProcIOErrorHandler); 89105b261ecSmrg 89205b261ecSmrg /* Setup the display connection string x */ 89305b261ecSmrg snprintf (pszDisplay, 89405b261ecSmrg 512, "127.0.0.1:%s.%d", display, (int)pProcArg->dwScreen); 89505b261ecSmrg 89605b261ecSmrg /* Print the display connection string */ 89705b261ecSmrg ErrorF ("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay); 89805b261ecSmrg 89905b261ecSmrg /* Initialize retry count */ 90005b261ecSmrg iRetries = 0; 90105b261ecSmrg 90205b261ecSmrg /* Open the X display */ 90305b261ecSmrg do 90405b261ecSmrg { 90505b261ecSmrg /* Try to open the display */ 90605b261ecSmrg pProcArg->pDisplay = XOpenDisplay (pszDisplay); 90705b261ecSmrg if (pProcArg->pDisplay == NULL) 90805b261ecSmrg { 90905b261ecSmrg ErrorF ("winMultiWindowXMsgProc - Could not open display, try: %d, " 91005b261ecSmrg "sleeping: %d\n\f", 91105b261ecSmrg iRetries + 1, WIN_CONNECT_DELAY); 91205b261ecSmrg ++iRetries; 91305b261ecSmrg sleep (WIN_CONNECT_DELAY); 91405b261ecSmrg continue; 91505b261ecSmrg } 91605b261ecSmrg else 91705b261ecSmrg break; 91805b261ecSmrg } 91905b261ecSmrg while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); 92005b261ecSmrg 92105b261ecSmrg /* Make sure that the display opened */ 92205b261ecSmrg if (pProcArg->pDisplay == NULL) 92305b261ecSmrg { 92405b261ecSmrg ErrorF ("winMultiWindowXMsgProc - Failed opening the display. " 92505b261ecSmrg "Exiting.\n"); 92605b261ecSmrg pthread_exit (NULL); 92705b261ecSmrg } 92805b261ecSmrg 92905b261ecSmrg ErrorF ("winMultiWindowXMsgProc - XOpenDisplay () returned and " 93005b261ecSmrg "successfully opened the display.\n"); 93105b261ecSmrg 93205b261ecSmrg /* Check if another window manager is already running */ 93305b261ecSmrg if (pProcArg->pWMInfo->fAllowOtherWM) 93405b261ecSmrg { 93505b261ecSmrg g_fAnotherWMRunnig = CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen); 93605b261ecSmrg } else { 93705b261ecSmrg redirectError = FALSE; 93805b261ecSmrg XSetErrorHandler (winRedirectErrorHandler); 93905b261ecSmrg XSelectInput(pProcArg->pDisplay, 94005b261ecSmrg RootWindow (pProcArg->pDisplay, pProcArg->dwScreen), 94105b261ecSmrg SubstructureNotifyMask | ButtonPressMask); 94205b261ecSmrg XSync (pProcArg->pDisplay, 0); 94305b261ecSmrg XSetErrorHandler (winMultiWindowXMsgProcErrorHandler); 94405b261ecSmrg if (redirectError) 94505b261ecSmrg { 94605b261ecSmrg ErrorF ("winMultiWindowXMsgProc - " 94705b261ecSmrg "another window manager is running. Exiting.\n"); 94805b261ecSmrg pthread_exit (NULL); 94905b261ecSmrg } 95005b261ecSmrg g_fAnotherWMRunnig = FALSE; 95105b261ecSmrg } 95205b261ecSmrg 95305b261ecSmrg /* Set up the supported icon sizes */ 95405b261ecSmrg xis = XAllocIconSize (); 95505b261ecSmrg if (xis) 95605b261ecSmrg { 95705b261ecSmrg xis->min_width = xis->min_height = 16; 95805b261ecSmrg xis->max_width = xis->max_height = 48; 95905b261ecSmrg xis->width_inc = xis->height_inc = 16; 96005b261ecSmrg XSetIconSizes (pProcArg->pDisplay, 96105b261ecSmrg RootWindow (pProcArg->pDisplay, pProcArg->dwScreen), 96205b261ecSmrg xis, 96305b261ecSmrg 1); 96405b261ecSmrg XFree (xis); 96505b261ecSmrg } 96605b261ecSmrg 96705b261ecSmrg atmWmName = XInternAtom (pProcArg->pDisplay, 96805b261ecSmrg "WM_NAME", 96905b261ecSmrg False); 97005b261ecSmrg atmWmHints = XInternAtom (pProcArg->pDisplay, 97105b261ecSmrg "WM_HINTS", 97205b261ecSmrg False); 97305b261ecSmrg atmWmChange = XInternAtom (pProcArg->pDisplay, 97405b261ecSmrg "WM_CHANGE_STATE", 97505b261ecSmrg False); 97605b261ecSmrg 97705b261ecSmrg /* Loop until we explicitly break out */ 97805b261ecSmrg while (1) 97905b261ecSmrg { 98005b261ecSmrg if (g_shutdown) 98105b261ecSmrg break; 98205b261ecSmrg 98305b261ecSmrg if (pProcArg->pWMInfo->fAllowOtherWM && !XPending (pProcArg->pDisplay)) 98405b261ecSmrg { 98505b261ecSmrg if (CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen)) 98605b261ecSmrg { 98705b261ecSmrg if (!g_fAnotherWMRunnig) 98805b261ecSmrg { 98905b261ecSmrg g_fAnotherWMRunnig = TRUE; 99005b261ecSmrg SendMessage(*(HWND*)pProcArg->hwndScreen, WM_UNMANAGE, 0, 0); 99105b261ecSmrg } 99205b261ecSmrg } 99305b261ecSmrg else 99405b261ecSmrg { 99505b261ecSmrg if (g_fAnotherWMRunnig) 99605b261ecSmrg { 99705b261ecSmrg g_fAnotherWMRunnig = FALSE; 99805b261ecSmrg SendMessage(*(HWND*)pProcArg->hwndScreen, WM_MANAGE, 0, 0); 99905b261ecSmrg } 100005b261ecSmrg } 100105b261ecSmrg Sleep (500); 100205b261ecSmrg continue; 100305b261ecSmrg } 100405b261ecSmrg 100505b261ecSmrg /* Fetch next event */ 100605b261ecSmrg XNextEvent (pProcArg->pDisplay, &event); 100705b261ecSmrg 100805b261ecSmrg /* Branch on event type */ 100905b261ecSmrg if (event.type == CreateNotify) 101005b261ecSmrg { 101105b261ecSmrg XWindowAttributes attr; 101205b261ecSmrg 101305b261ecSmrg XSelectInput (pProcArg->pDisplay, 101405b261ecSmrg event.xcreatewindow.window, 101505b261ecSmrg PropertyChangeMask); 101605b261ecSmrg 101705b261ecSmrg /* Get the window attributes */ 101805b261ecSmrg XGetWindowAttributes (pProcArg->pDisplay, 101905b261ecSmrg event.xcreatewindow.window, 102005b261ecSmrg &attr); 102105b261ecSmrg 102205b261ecSmrg if (!attr.override_redirect) 102305b261ecSmrg XSetWindowBorderWidth(pProcArg->pDisplay, 102405b261ecSmrg event.xcreatewindow.window, 102505b261ecSmrg 0); 102605b261ecSmrg } 102705b261ecSmrg else if (event.type == PropertyNotify 102805b261ecSmrg && event.xproperty.atom == atmWmName) 102905b261ecSmrg { 103005b261ecSmrg memset (&msg, 0, sizeof (msg)); 103105b261ecSmrg 103205b261ecSmrg msg.msg = WM_WM_NAME_EVENT; 103305b261ecSmrg msg.iWindow = event.xproperty.window; 103405b261ecSmrg 103505b261ecSmrg /* Other fields ignored */ 103605b261ecSmrg winSendMessageToWM (pProcArg->pWMInfo, &msg); 103705b261ecSmrg } 103805b261ecSmrg else if (event.type == PropertyNotify 103905b261ecSmrg && event.xproperty.atom == atmWmHints) 104005b261ecSmrg { 104105b261ecSmrg memset (&msg, 0, sizeof (msg)); 104205b261ecSmrg 104305b261ecSmrg msg.msg = WM_WM_HINTS_EVENT; 104405b261ecSmrg msg.iWindow = event.xproperty.window; 104505b261ecSmrg 104605b261ecSmrg /* Other fields ignored */ 104705b261ecSmrg winSendMessageToWM (pProcArg->pWMInfo, &msg); 104805b261ecSmrg } 104905b261ecSmrg else if (event.type == ClientMessage 105005b261ecSmrg && event.xclient.message_type == atmWmChange 105105b261ecSmrg && event.xclient.data.l[0] == IconicState) 105205b261ecSmrg { 105305b261ecSmrg ErrorF ("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n"); 105405b261ecSmrg 105505b261ecSmrg memset (&msg, 0, sizeof (msg)); 105605b261ecSmrg 105705b261ecSmrg msg.msg = WM_WM_CHANGE_STATE; 105805b261ecSmrg msg.iWindow = event.xclient.window; 105905b261ecSmrg 106005b261ecSmrg winSendMessageToWM (pProcArg->pWMInfo, &msg); 106105b261ecSmrg } 106205b261ecSmrg } 106305b261ecSmrg 106405b261ecSmrg XCloseDisplay (pProcArg->pDisplay); 106505b261ecSmrg pthread_exit (NULL); 106605b261ecSmrg 106705b261ecSmrg} 106805b261ecSmrg 106905b261ecSmrg 107005b261ecSmrg/* 107105b261ecSmrg * winInitWM - Entry point for the X server to spawn 107205b261ecSmrg * the Window Manager thread. Called from 107305b261ecSmrg * winscrinit.c/winFinishScreenInitFB (). 107405b261ecSmrg */ 107505b261ecSmrg 107605b261ecSmrgBool 107705b261ecSmrgwinInitWM (void **ppWMInfo, 107805b261ecSmrg pthread_t *ptWMProc, 107905b261ecSmrg pthread_t *ptXMsgProc, 108005b261ecSmrg pthread_mutex_t *ppmServerStarted, 108105b261ecSmrg int dwScreen, 108205b261ecSmrg HWND hwndScreen, 108305b261ecSmrg BOOL allowOtherWM) 108405b261ecSmrg{ 108505b261ecSmrg WMProcArgPtr pArg = (WMProcArgPtr) malloc (sizeof(WMProcArgRec)); 108605b261ecSmrg WMInfoPtr pWMInfo = (WMInfoPtr) malloc (sizeof(WMInfoRec)); 108705b261ecSmrg XMsgProcArgPtr pXMsgArg = (XMsgProcArgPtr) malloc (sizeof(XMsgProcArgRec)); 108805b261ecSmrg 108905b261ecSmrg /* Bail if the input parameters are bad */ 109005b261ecSmrg if (pArg == NULL || pWMInfo == NULL) 109105b261ecSmrg { 109205b261ecSmrg ErrorF ("winInitWM - malloc failed.\n"); 109305b261ecSmrg return FALSE; 109405b261ecSmrg } 109505b261ecSmrg 109605b261ecSmrg /* Zero the allocated memory */ 109705b261ecSmrg ZeroMemory (pArg, sizeof (WMProcArgRec)); 109805b261ecSmrg ZeroMemory (pWMInfo, sizeof (WMInfoRec)); 109905b261ecSmrg ZeroMemory (pXMsgArg, sizeof (XMsgProcArgRec)); 110005b261ecSmrg 110105b261ecSmrg /* Set a return pointer to the Window Manager info structure */ 110205b261ecSmrg *ppWMInfo = pWMInfo; 110305b261ecSmrg pWMInfo->fAllowOtherWM = allowOtherWM; 110405b261ecSmrg 110505b261ecSmrg /* Setup the argument structure for the thread function */ 110605b261ecSmrg pArg->dwScreen = dwScreen; 110705b261ecSmrg pArg->pWMInfo = pWMInfo; 110805b261ecSmrg pArg->ppmServerStarted = ppmServerStarted; 110905b261ecSmrg 111005b261ecSmrg /* Intialize the message queue */ 111105b261ecSmrg if (!InitQueue (&pWMInfo->wmMsgQueue)) 111205b261ecSmrg { 111305b261ecSmrg ErrorF ("winInitWM - InitQueue () failed.\n"); 111405b261ecSmrg return FALSE; 111505b261ecSmrg } 111605b261ecSmrg 111705b261ecSmrg /* Spawn a thread for the Window Manager */ 111805b261ecSmrg if (pthread_create (ptWMProc, NULL, winMultiWindowWMProc, pArg)) 111905b261ecSmrg { 112005b261ecSmrg /* Bail if thread creation failed */ 112105b261ecSmrg ErrorF ("winInitWM - pthread_create failed for Window Manager.\n"); 112205b261ecSmrg return FALSE; 112305b261ecSmrg } 112405b261ecSmrg 112505b261ecSmrg /* Spawn the XNextEvent thread, will send messages to WM */ 112605b261ecSmrg pXMsgArg->dwScreen = dwScreen; 112705b261ecSmrg pXMsgArg->pWMInfo = pWMInfo; 112805b261ecSmrg pXMsgArg->ppmServerStarted = ppmServerStarted; 112905b261ecSmrg pXMsgArg->hwndScreen = hwndScreen; 113005b261ecSmrg if (pthread_create (ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg)) 113105b261ecSmrg { 113205b261ecSmrg /* Bail if thread creation failed */ 113305b261ecSmrg ErrorF ("winInitWM - pthread_create failed on XMSG.\n"); 113405b261ecSmrg return FALSE; 113505b261ecSmrg } 113605b261ecSmrg 113705b261ecSmrg#if CYGDEBUG || YES 113805b261ecSmrg winDebug ("winInitWM - Returning.\n"); 113905b261ecSmrg#endif 114005b261ecSmrg 114105b261ecSmrg return TRUE; 114205b261ecSmrg} 114305b261ecSmrg 114405b261ecSmrg 114505b261ecSmrg/* 114605b261ecSmrg * Window manager thread - setup 114705b261ecSmrg */ 114805b261ecSmrg 114905b261ecSmrgstatic void 115005b261ecSmrgwinInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) 115105b261ecSmrg{ 115205b261ecSmrg int iRetries = 0; 115305b261ecSmrg char pszDisplay[512]; 115405b261ecSmrg int iReturn; 115505b261ecSmrg 115605b261ecSmrg ErrorF ("winInitMultiWindowWM - Hello\n"); 115705b261ecSmrg 115805b261ecSmrg /* Check that argument pointer is not invalid */ 115905b261ecSmrg if (pProcArg == NULL) 116005b261ecSmrg { 116105b261ecSmrg ErrorF ("winInitMultiWindowWM - pProcArg is NULL. Exiting.\n"); 116205b261ecSmrg pthread_exit (NULL); 116305b261ecSmrg } 116405b261ecSmrg 116505b261ecSmrg ErrorF ("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n"); 116605b261ecSmrg 116705b261ecSmrg /* Grab our garbage mutex to satisfy pthread_cond_wait */ 116805b261ecSmrg iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted); 116905b261ecSmrg if (iReturn != 0) 117005b261ecSmrg { 117105b261ecSmrg ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () failed: %d. " 117205b261ecSmrg "Exiting.\n", 117305b261ecSmrg iReturn); 117405b261ecSmrg pthread_exit (NULL); 117505b261ecSmrg } 117605b261ecSmrg 117705b261ecSmrg ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); 117805b261ecSmrg 117905b261ecSmrg /* Allow multiple threads to access Xlib */ 118005b261ecSmrg if (XInitThreads () == 0) 118105b261ecSmrg { 118205b261ecSmrg ErrorF ("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n"); 118305b261ecSmrg pthread_exit (NULL); 118405b261ecSmrg } 118505b261ecSmrg 118605b261ecSmrg /* See if X supports the current locale */ 118705b261ecSmrg if (XSupportsLocale () == False) 118805b261ecSmrg { 118905b261ecSmrg ErrorF ("winInitMultiWindowWM - Locale not supported by X. Exiting.\n"); 119005b261ecSmrg pthread_exit (NULL); 119105b261ecSmrg } 119205b261ecSmrg 119305b261ecSmrg /* Release the server started mutex */ 119405b261ecSmrg pthread_mutex_unlock (pProcArg->ppmServerStarted); 119505b261ecSmrg 119605b261ecSmrg ErrorF ("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); 119705b261ecSmrg 119805b261ecSmrg /* Set jump point for IO Error exits */ 119905b261ecSmrg iReturn = setjmp (g_jmpWMEntry); 120005b261ecSmrg 120105b261ecSmrg /* Check if we should continue operations */ 120205b261ecSmrg if (iReturn != WIN_JMP_ERROR_IO 120305b261ecSmrg && iReturn != WIN_JMP_OKAY) 120405b261ecSmrg { 120505b261ecSmrg /* setjmp returned an unknown value, exit */ 120605b261ecSmrg ErrorF ("winInitMultiWindowWM - setjmp returned: %d. Exiting.\n", 120705b261ecSmrg iReturn); 120805b261ecSmrg pthread_exit (NULL); 120905b261ecSmrg } 121005b261ecSmrg else if (iReturn == WIN_JMP_ERROR_IO) 121105b261ecSmrg { 121205b261ecSmrg ErrorF ("winInitMultiWindowWM - Caught IO Error. Exiting.\n"); 121305b261ecSmrg pthread_exit (NULL); 121405b261ecSmrg } 121505b261ecSmrg 121605b261ecSmrg /* Install our error handler */ 121705b261ecSmrg XSetErrorHandler (winMultiWindowWMErrorHandler); 121805b261ecSmrg XSetIOErrorHandler (winMultiWindowWMIOErrorHandler); 121905b261ecSmrg 122005b261ecSmrg /* Setup the display connection string x */ 122105b261ecSmrg snprintf (pszDisplay, 122205b261ecSmrg 512, 122305b261ecSmrg "127.0.0.1:%s.%d", 122405b261ecSmrg display, 122505b261ecSmrg (int) pProcArg->dwScreen); 122605b261ecSmrg 122705b261ecSmrg /* Print the display connection string */ 122805b261ecSmrg ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); 122905b261ecSmrg 123005b261ecSmrg /* Open the X display */ 123105b261ecSmrg do 123205b261ecSmrg { 123305b261ecSmrg /* Try to open the display */ 123405b261ecSmrg pWMInfo->pDisplay = XOpenDisplay (pszDisplay); 123505b261ecSmrg if (pWMInfo->pDisplay == NULL) 123605b261ecSmrg { 123705b261ecSmrg ErrorF ("winInitMultiWindowWM - Could not open display, try: %d, " 123805b261ecSmrg "sleeping: %d\n\f", 123905b261ecSmrg iRetries + 1, WIN_CONNECT_DELAY); 124005b261ecSmrg ++iRetries; 124105b261ecSmrg sleep (WIN_CONNECT_DELAY); 124205b261ecSmrg continue; 124305b261ecSmrg } 124405b261ecSmrg else 124505b261ecSmrg break; 124605b261ecSmrg } 124705b261ecSmrg while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); 124805b261ecSmrg 124905b261ecSmrg /* Make sure that the display opened */ 125005b261ecSmrg if (pWMInfo->pDisplay == NULL) 125105b261ecSmrg { 125205b261ecSmrg ErrorF ("winInitMultiWindowWM - Failed opening the display. " 125305b261ecSmrg "Exiting.\n"); 125405b261ecSmrg pthread_exit (NULL); 125505b261ecSmrg } 125605b261ecSmrg 125705b261ecSmrg ErrorF ("winInitMultiWindowWM - XOpenDisplay () returned and " 125805b261ecSmrg "successfully opened the display.\n"); 125905b261ecSmrg 126005b261ecSmrg 126105b261ecSmrg /* Create some atoms */ 126205b261ecSmrg pWMInfo->atmWmProtos = XInternAtom (pWMInfo->pDisplay, 126305b261ecSmrg "WM_PROTOCOLS", 126405b261ecSmrg False); 126505b261ecSmrg pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay, 126605b261ecSmrg "WM_DELETE_WINDOW", 126705b261ecSmrg False); 126805b261ecSmrg#ifdef XWIN_MULTIWINDOWEXTWM 126905b261ecSmrg pWMInfo->atmPrivMap = XInternAtom (pWMInfo->pDisplay, 127005b261ecSmrg WINDOWSWM_NATIVE_HWND, 127105b261ecSmrg False); 127205b261ecSmrg#endif 127305b261ecSmrg 127405b261ecSmrg 127505b261ecSmrg if (1) { 127605b261ecSmrg Cursor cursor = XCreateFontCursor (pWMInfo->pDisplay, XC_left_ptr); 127705b261ecSmrg if (cursor) 127805b261ecSmrg { 127905b261ecSmrg XDefineCursor (pWMInfo->pDisplay, DefaultRootWindow(pWMInfo->pDisplay), cursor); 128005b261ecSmrg XFreeCursor (pWMInfo->pDisplay, cursor); 128105b261ecSmrg } 128205b261ecSmrg } 128305b261ecSmrg} 128405b261ecSmrg 128505b261ecSmrg 128605b261ecSmrg/* 128705b261ecSmrg * winSendMessageToWM - Send a message from the X thread to the WM thread 128805b261ecSmrg */ 128905b261ecSmrg 129005b261ecSmrgvoid 129105b261ecSmrgwinSendMessageToWM (void *pWMInfo, winWMMessagePtr pMsg) 129205b261ecSmrg{ 129305b261ecSmrg WMMsgNodePtr pNode; 129405b261ecSmrg 129505b261ecSmrg#if CYGMULTIWINDOW_DEBUG 129605b261ecSmrg ErrorF ("winSendMessageToWM ()\n"); 129705b261ecSmrg#endif 129805b261ecSmrg 129905b261ecSmrg pNode = (WMMsgNodePtr)malloc(sizeof(WMMsgNodeRec)); 130005b261ecSmrg if (pNode != NULL) 130105b261ecSmrg { 130205b261ecSmrg memcpy (&pNode->msg, pMsg, sizeof(winWMMessageRec)); 130305b261ecSmrg PushMessage (&((WMInfoPtr)pWMInfo)->wmMsgQueue, pNode); 130405b261ecSmrg } 130505b261ecSmrg} 130605b261ecSmrg 130705b261ecSmrg 130805b261ecSmrg/* 130905b261ecSmrg * Window manager error handler 131005b261ecSmrg */ 131105b261ecSmrg 131205b261ecSmrgstatic int 131305b261ecSmrgwinMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr) 131405b261ecSmrg{ 131505b261ecSmrg char pszErrorMsg[100]; 131605b261ecSmrg 131705b261ecSmrg if (pErr->request_code == X_ChangeWindowAttributes 131805b261ecSmrg && pErr->error_code == BadAccess) 131905b261ecSmrg { 132005b261ecSmrg ErrorF ("winMultiWindowWMErrorHandler - ChangeWindowAttributes " 132105b261ecSmrg "BadAccess.\n"); 132205b261ecSmrg return 0; 132305b261ecSmrg } 132405b261ecSmrg 132505b261ecSmrg XGetErrorText (pDisplay, 132605b261ecSmrg pErr->error_code, 132705b261ecSmrg pszErrorMsg, 132805b261ecSmrg sizeof (pszErrorMsg)); 132905b261ecSmrg ErrorF ("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg); 133005b261ecSmrg 133105b261ecSmrg return 0; 133205b261ecSmrg} 133305b261ecSmrg 133405b261ecSmrg 133505b261ecSmrg/* 133605b261ecSmrg * Window manager IO error handler 133705b261ecSmrg */ 133805b261ecSmrg 133905b261ecSmrgstatic int 134005b261ecSmrgwinMultiWindowWMIOErrorHandler (Display *pDisplay) 134105b261ecSmrg{ 134205b261ecSmrg ErrorF ("\nwinMultiWindowWMIOErrorHandler!\n\n"); 134305b261ecSmrg 134405b261ecSmrg if (g_shutdown) 134505b261ecSmrg pthread_exit(NULL); 134605b261ecSmrg 134705b261ecSmrg /* Restart at the main entry point */ 134805b261ecSmrg longjmp (g_jmpWMEntry, WIN_JMP_ERROR_IO); 134905b261ecSmrg 135005b261ecSmrg return 0; 135105b261ecSmrg} 135205b261ecSmrg 135305b261ecSmrg 135405b261ecSmrg/* 135505b261ecSmrg * X message procedure error handler 135605b261ecSmrg */ 135705b261ecSmrg 135805b261ecSmrgstatic int 135905b261ecSmrgwinMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr) 136005b261ecSmrg{ 136105b261ecSmrg char pszErrorMsg[100]; 136205b261ecSmrg 136305b261ecSmrg XGetErrorText (pDisplay, 136405b261ecSmrg pErr->error_code, 136505b261ecSmrg pszErrorMsg, 136605b261ecSmrg sizeof (pszErrorMsg)); 136705b261ecSmrg ErrorF ("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg); 136805b261ecSmrg 136905b261ecSmrg return 0; 137005b261ecSmrg} 137105b261ecSmrg 137205b261ecSmrg 137305b261ecSmrg/* 137405b261ecSmrg * X message procedure IO error handler 137505b261ecSmrg */ 137605b261ecSmrg 137705b261ecSmrgstatic int 137805b261ecSmrgwinMultiWindowXMsgProcIOErrorHandler (Display *pDisplay) 137905b261ecSmrg{ 138005b261ecSmrg ErrorF ("\nwinMultiWindowXMsgProcIOErrorHandler!\n\n"); 138105b261ecSmrg 138205b261ecSmrg /* Restart at the main entry point */ 138305b261ecSmrg longjmp (g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO); 138405b261ecSmrg 138505b261ecSmrg return 0; 138605b261ecSmrg} 138705b261ecSmrg 138805b261ecSmrg 138905b261ecSmrg/* 139005b261ecSmrg * Catch RedirectError to detect other window manager running 139105b261ecSmrg */ 139205b261ecSmrg 139305b261ecSmrgstatic int 139405b261ecSmrgwinRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr) 139505b261ecSmrg{ 139605b261ecSmrg redirectError = TRUE; 139705b261ecSmrg return 0; 139805b261ecSmrg} 139905b261ecSmrg 140005b261ecSmrg 140105b261ecSmrg/* 140205b261ecSmrg * Check if another window manager is running 140305b261ecSmrg */ 140405b261ecSmrg 140505b261ecSmrgstatic Bool 140605b261ecSmrgCheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen) 140705b261ecSmrg{ 140805b261ecSmrg redirectError = FALSE; 140905b261ecSmrg XSetErrorHandler (winRedirectErrorHandler); 141005b261ecSmrg XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen), 141105b261ecSmrg // SubstructureNotifyMask | ButtonPressMask 141205b261ecSmrg ColormapChangeMask | EnterWindowMask | PropertyChangeMask | 141305b261ecSmrg SubstructureRedirectMask | KeyPressMask | 141405b261ecSmrg ButtonPressMask | ButtonReleaseMask); 141505b261ecSmrg XSync (pDisplay, 0); 141605b261ecSmrg XSetErrorHandler (winMultiWindowXMsgProcErrorHandler); 141705b261ecSmrg XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen), 141805b261ecSmrg SubstructureNotifyMask); 141905b261ecSmrg XSync (pDisplay, 0); 142005b261ecSmrg if (redirectError) 142105b261ecSmrg { 142205b261ecSmrg //ErrorF ("CheckAnotherWindowManager() - another window manager is running. Exiting.\n"); 142305b261ecSmrg return TRUE; 142405b261ecSmrg } 142505b261ecSmrg else 142605b261ecSmrg { 142705b261ecSmrg return FALSE; 142805b261ecSmrg } 142905b261ecSmrg} 143005b261ecSmrg 143105b261ecSmrg/* 143205b261ecSmrg * Notify the MWM thread we're exiting and not to reconnect 143305b261ecSmrg */ 143405b261ecSmrg 143505b261ecSmrgvoid 143605b261ecSmrgwinDeinitMultiWindowWM () 143705b261ecSmrg{ 143805b261ecSmrg ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n"); 143905b261ecSmrg g_shutdown = TRUE; 144005b261ecSmrg} 1441