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