~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xwin/winmultiwindowwm.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
 
3
 *
 
4
 *Permission is hereby granted, free of charge, to any person obtaining
 
5
 * a copy of this software and associated documentation files (the
 
6
 *"Software"), to deal in the Software without restriction, including
 
7
 *without limitation the rights to use, copy, modify, merge, publish,
 
8
 *distribute, sublicense, and/or sell copies of the Software, and to
 
9
 *permit persons to whom the Software is furnished to do so, subject to
 
10
 *the following conditions:
 
11
 *
 
12
 *The above copyright notice and this permission notice shall be
 
13
 *included in all copies or substantial portions of the Software.
 
14
 *
 
15
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
16
 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
18
 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
 
19
 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 
20
 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
21
 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 *
 
23
 *Except as contained in this notice, the name of the XFree86 Project
 
24
 *shall not be used in advertising or otherwise to promote the sale, use
 
25
 *or other dealings in this Software without prior written authorization
 
26
 *from the XFree86 Project.
 
27
 *
 
28
 * Authors:     Kensuke Matsuzaki
 
29
 */
 
30
/* $XFree86: xc/programs/Xserver/hw/xwin/winwindow.c,v 1.5 2002/11/07 10:31:32 alanh Exp $ */
 
31
 
 
32
/* X headers */
 
33
#ifdef HAVE_XWIN_CONFIG_H
 
34
#include <xwin-config.h>
 
35
#endif
 
36
#include <stdio.h>
 
37
#include <stdlib.h>
 
38
#include <unistd.h>
 
39
#ifdef __CYGWIN__
 
40
#include <sys/select.h>
 
41
#endif
 
42
#include <fcntl.h>
 
43
#include <setjmp.h>
 
44
#define HANDLE void *
 
45
#include <pthread.h>
 
46
#undef HANDLE
 
47
#include <X11/X.h>
 
48
#include <X11/Xatom.h>
 
49
#include <X11/Xlib.h>
 
50
#include <X11/Xlocale.h>
 
51
#include <X11/Xproto.h>
 
52
#include <X11/Xutil.h>
 
53
#include <X11/cursorfont.h>
 
54
 
 
55
/* Windows headers */
 
56
#ifdef __CYGWIN__
 
57
/* Fixups to prevent collisions between Windows and X headers */
 
58
#define ATOM DWORD
 
59
 
 
60
#include <windows.h>
 
61
#else
 
62
#include <Xwindows.h>
 
63
#endif
 
64
 
 
65
/* Local headers */
 
66
#include "objbase.h"
 
67
#include "ddraw.h"
 
68
#include "winwindow.h"
 
69
#ifdef XWIN_MULTIWINDOWEXTWM
 
70
#include "windowswmstr.h"
 
71
#endif
 
72
 
 
73
extern void winDebug(const char *format, ...);
 
74
 
 
75
#ifndef CYGDEBUG
 
76
#define CYGDEBUG NO
 
77
#endif
 
78
 
 
79
/*
 
80
 * Constant defines
 
81
 */
 
82
 
 
83
#define WIN_CONNECT_RETRIES     5
 
84
#define WIN_CONNECT_DELAY       5
 
85
#ifdef HAS_DEVWINDOWS
 
86
# define WIN_MSG_QUEUE_FNAME    "/dev/windows"
 
87
#endif
 
88
#define WIN_JMP_OKAY            0
 
89
#define WIN_JMP_ERROR_IO        2
 
90
 
 
91
 
 
92
/*
 
93
 * Local structures
 
94
 */
 
95
 
 
96
typedef struct _WMMsgNodeRec {
 
97
  winWMMessageRec       msg;
 
98
  struct _WMMsgNodeRec  *pNext;
 
99
} WMMsgNodeRec, *WMMsgNodePtr;
 
100
 
 
101
typedef struct _WMMsgQueueRec {
 
102
  struct _WMMsgNodeRec  *pHead;
 
103
  struct _WMMsgNodeRec  *pTail;
 
104
  pthread_mutex_t       pmMutex;
 
105
  pthread_cond_t        pcNotEmpty;
 
106
  int                   nQueueSize;
 
107
} WMMsgQueueRec, *WMMsgQueuePtr;
 
108
 
 
109
typedef struct _WMInfo {
 
110
  Display               *pDisplay;
 
111
  WMMsgQueueRec         wmMsgQueue;
 
112
  Atom                  atmWmProtos;
 
113
  Atom                  atmWmDelete;
 
114
  Atom                  atmPrivMap;
 
115
  Bool                  fAllowOtherWM;
 
116
} WMInfoRec, *WMInfoPtr;
 
117
 
 
118
typedef struct _WMProcArgRec {
 
119
  DWORD                 dwScreen;
 
120
  WMInfoPtr             pWMInfo;
 
121
  pthread_mutex_t       *ppmServerStarted;
 
122
} WMProcArgRec, *WMProcArgPtr;
 
123
 
 
124
typedef struct _XMsgProcArgRec {
 
125
  Display               *pDisplay;
 
126
  DWORD                 dwScreen;
 
127
  WMInfoPtr             pWMInfo;
 
128
  pthread_mutex_t       *ppmServerStarted;
 
129
  HWND                  hwndScreen;
 
130
} XMsgProcArgRec, *XMsgProcArgPtr;
 
131
 
 
132
 
 
133
/*
 
134
 * References to external symbols
 
135
 */
 
136
 
 
137
extern char *display;
 
138
extern void ErrorF (const char* /*f*/, ...);
 
139
 
 
140
 
 
141
/*
 
142
 * Prototypes for local functions
 
143
 */
 
144
 
 
145
static void
 
146
PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode);
 
147
 
 
148
static WMMsgNodePtr
 
149
PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo);
 
150
 
 
151
static Bool
 
152
InitQueue (WMMsgQueuePtr pQueue);
 
153
 
 
154
static void
 
155
GetWindowName (Display * pDpy, Window iWin, char **ppName);
 
156
 
 
157
static int
 
158
SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData);
 
159
 
 
160
static void
 
161
UpdateName (WMInfoPtr pWMInfo, Window iWindow);
 
162
 
 
163
static void*
 
164
winMultiWindowWMProc (void* pArg);
 
165
 
 
166
static int
 
167
winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr);
 
168
 
 
169
static int
 
170
winMultiWindowWMIOErrorHandler (Display *pDisplay);
 
171
 
 
172
static void *
 
173
winMultiWindowXMsgProc (void *pArg);
 
174
 
 
175
static int
 
176
winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr);
 
177
 
 
178
static int
 
179
winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay);
 
180
 
 
181
static int
 
182
winRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr);
 
183
 
 
184
static void
 
185
winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg);
 
186
 
 
187
#if 0
 
188
static void
 
189
PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction);
 
190
#endif
 
191
 
 
192
static Bool
 
193
CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen);
 
194
 
 
195
 
 
196
/*
 
197
 * Local globals
 
198
 */
 
199
 
 
200
static jmp_buf                  g_jmpWMEntry;
 
201
static jmp_buf                  g_jmpXMsgProcEntry;
 
202
static Bool                     g_shutdown = FALSE;
 
203
static Bool                     redirectError = FALSE;
 
204
static Bool                     g_fAnotherWMRunnig = FALSE;
 
205
 
 
206
/*
 
207
 * PushMessage - Push a message onto the queue
 
208
 */
 
209
 
 
210
static void
 
211
PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
 
212
{
 
213
 
 
214
  /* Lock the queue mutex */
 
215
  pthread_mutex_lock (&pQueue->pmMutex);
 
216
 
 
217
  pNode->pNext = NULL;
 
218
  
 
219
  if (pQueue->pTail != NULL)
 
220
    {
 
221
      pQueue->pTail->pNext = pNode;
 
222
    }
 
223
  pQueue->pTail = pNode;
 
224
  
 
225
  if (pQueue->pHead == NULL)
 
226
    {
 
227
      pQueue->pHead = pNode;
 
228
    }
 
229
 
 
230
 
 
231
#if 0
 
232
  switch (pNode->msg.msg)
 
233
    {
 
234
    case WM_WM_MOVE:
 
235
      ErrorF ("\tWM_WM_MOVE\n");
 
236
      break;
 
237
    case WM_WM_SIZE:
 
238
      ErrorF ("\tWM_WM_SIZE\n");
 
239
      break;
 
240
    case WM_WM_RAISE:
 
241
      ErrorF ("\tWM_WM_RAISE\n");
 
242
      break;
 
243
    case WM_WM_LOWER:
 
244
      ErrorF ("\tWM_WM_LOWER\n");
 
245
      break;
 
246
    case WM_WM_MAP:
 
247
      ErrorF ("\tWM_WM_MAP\n");
 
248
      break;
 
249
    case WM_WM_UNMAP:
 
250
      ErrorF ("\tWM_WM_UNMAP\n");
 
251
      break;
 
252
    case WM_WM_KILL:
 
253
      ErrorF ("\tWM_WM_KILL\n");
 
254
      break;
 
255
    case WM_WM_ACTIVATE:
 
256
      ErrorF ("\tWM_WM_ACTIVATE\n");
 
257
      break;
 
258
    default:
 
259
      ErrorF ("\tUnknown Message.\n");
 
260
      break;
 
261
    }
 
262
#endif
 
263
 
 
264
  /* Increase the count of elements in the queue by one */
 
265
  ++(pQueue->nQueueSize);
 
266
 
 
267
  /* Release the queue mutex */
 
268
  pthread_mutex_unlock (&pQueue->pmMutex);
 
269
 
 
270
  /* Signal that the queue is not empty */
 
271
  pthread_cond_signal (&pQueue->pcNotEmpty);
 
272
}
 
273
 
 
274
 
 
275
#if CYGMULTIWINDOW_DEBUG
 
276
/*
 
277
 * QueueSize - Return the size of the queue
 
278
 */
 
279
 
 
280
static int
 
281
QueueSize (WMMsgQueuePtr pQueue)
 
282
{
 
283
  WMMsgNodePtr          pNode;
 
284
  int                   nSize = 0;
 
285
  
 
286
  /* Loop through all elements in the queue */
 
287
  for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext)
 
288
    ++nSize;
 
289
 
 
290
  return nSize;
 
291
}
 
292
#endif
 
293
 
 
294
 
 
295
/*
 
296
 * PopMessage - Pop a message from the queue
 
297
 */
 
298
 
 
299
static WMMsgNodePtr
 
300
PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo)
 
301
{
 
302
  WMMsgNodePtr          pNode;
 
303
 
 
304
  /* Lock the queue mutex */
 
305
  pthread_mutex_lock (&pQueue->pmMutex);
 
306
 
 
307
  /* Wait for --- */
 
308
  while (pQueue->pHead == NULL)
 
309
    {
 
310
      pthread_cond_wait (&pQueue->pcNotEmpty, &pQueue->pmMutex);
 
311
    }
 
312
  
 
313
  pNode = pQueue->pHead;
 
314
  if (pQueue->pHead != NULL)
 
315
    {
 
316
      pQueue->pHead = pQueue->pHead->pNext;
 
317
    }
 
318
 
 
319
  if (pQueue->pTail == pNode)
 
320
    {
 
321
      pQueue->pTail = NULL;
 
322
    }
 
323
 
 
324
  /* Drop the number of elements in the queue by one */
 
325
  --(pQueue->nQueueSize);
 
326
 
 
327
#if CYGMULTIWINDOW_DEBUG
 
328
  ErrorF ("Queue Size %d %d\n", pQueue->nQueueSize, QueueSize(pQueue));
 
329
#endif
 
330
  
 
331
  /* Release the queue mutex */
 
332
  pthread_mutex_unlock (&pQueue->pmMutex);
 
333
 
 
334
  return pNode;
 
335
}
 
336
 
 
337
 
 
338
#if 0
 
339
/*
 
340
 * HaveMessage - 
 
341
 */
 
342
 
 
343
static Bool
 
344
HaveMessage (WMMsgQueuePtr pQueue, UINT msg, Window iWindow)
 
345
{
 
346
  WMMsgNodePtr pNode;
 
347
  
 
348
  for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext)
 
349
    {
 
350
      if (pNode->msg.msg==msg && pNode->msg.iWindow==iWindow)
 
351
        return True;
 
352
    }
 
353
  
 
354
  return False;
 
355
}
 
356
#endif
 
357
 
 
358
 
 
359
/*
 
360
 * InitQueue - Initialize the Window Manager message queue
 
361
 */
 
362
 
 
363
static
 
364
Bool
 
365
InitQueue (WMMsgQueuePtr pQueue)
 
366
{
 
367
  /* Check if the pQueue pointer is NULL */
 
368
  if (pQueue == NULL)
 
369
    {
 
370
      ErrorF ("InitQueue - pQueue is NULL.  Exiting.\n");
 
371
      return FALSE;
 
372
    }
 
373
 
 
374
  /* Set the head and tail to NULL */
 
375
  pQueue->pHead = NULL;
 
376
  pQueue->pTail = NULL;
 
377
 
 
378
  /* There are no elements initially */
 
379
  pQueue->nQueueSize = 0;
 
380
 
 
381
#if CYGMULTIWINDOW_DEBUG
 
382
  ErrorF ("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize,
 
383
          QueueSize(pQueue));
 
384
#endif
 
385
 
 
386
  ErrorF ("InitQueue - Calling pthread_mutex_init\n");
 
387
 
 
388
  /* Create synchronization objects */
 
389
  pthread_mutex_init (&pQueue->pmMutex, NULL);
 
390
 
 
391
  ErrorF ("InitQueue - pthread_mutex_init returned\n");
 
392
  ErrorF ("InitQueue - Calling pthread_cond_init\n");
 
393
 
 
394
  pthread_cond_init (&pQueue->pcNotEmpty, NULL);
 
395
 
 
396
  ErrorF ("InitQueue - pthread_cond_init returned\n");
 
397
 
 
398
  return TRUE;
 
399
}
 
400
 
 
401
 
 
402
/*
 
403
 * GetWindowName - Retrieve the title of an X Window
 
404
 */
 
405
 
 
406
static void
 
407
GetWindowName (Display *pDisplay, Window iWin, char **ppName)
 
408
{
 
409
  int                   nResult, nNum;
 
410
  char                  **ppList;
 
411
  XTextProperty         xtpName;
 
412
  
 
413
#if CYGMULTIWINDOW_DEBUG
 
414
  ErrorF ("GetWindowName\n");
 
415
#endif
 
416
 
 
417
  /* Intialize ppName to NULL */
 
418
  *ppName = NULL;
 
419
 
 
420
  /* Try to get --- */
 
421
  nResult = XGetWMName (pDisplay, iWin, &xtpName);
 
422
  if (!nResult || !xtpName.value || !xtpName.nitems)
 
423
    {
 
424
#if CYGMULTIWINDOW_DEBUG
 
425
      ErrorF ("GetWindowName - XGetWMName failed.  No name.\n");
 
426
#endif
 
427
      return;
 
428
    }
 
429
  
 
430
  /* */
 
431
  if (xtpName.encoding == XA_STRING)
 
432
    {
 
433
      /* */
 
434
      if (xtpName.value)
 
435
        {
 
436
          int size = xtpName.nitems * (xtpName.format >> 3);
 
437
          *ppName = malloc(size + 1);
 
438
          strncpy(*ppName, xtpName.value, size);
 
439
          (*ppName)[size] = 0;
 
440
          XFree (xtpName.value);
 
441
        }
 
442
 
 
443
#if CYGMULTIWINDOW_DEBUG
 
444
      ErrorF ("GetWindowName - XA_STRING %s\n", *ppName);
 
445
#endif
 
446
    }
 
447
  else
 
448
    {
 
449
      XmbTextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum);
 
450
 
 
451
      /* */
 
452
      if (nNum && ppList && *ppList)
 
453
        {
 
454
          *ppName = strdup (*ppList);
 
455
          XFreeStringList (ppList);
 
456
        }
 
457
      XFree (xtpName.value);
 
458
 
 
459
#if CYGMULTIWINDOW_DEBUG
 
460
      ErrorF ("GetWindowName - %s %s\n",
 
461
              XGetAtomName (pDisplay, xtpName.encoding), *ppName);
 
462
#endif
 
463
    }
 
464
 
 
465
#if CYGMULTIWINDOW_DEBUG
 
466
  ErrorF ("GetWindowName - Returning\n");
 
467
#endif
 
468
}
 
469
 
 
470
 
 
471
/*
 
472
 * Send a message to the X server from the WM thread
 
473
 */
 
474
 
 
475
static int
 
476
SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData)
 
477
{
 
478
  XEvent                e;
 
479
 
 
480
  /* Prepare the X event structure */
 
481
  e.type = ClientMessage;
 
482
  e.xclient.window = iWin;
 
483
  e.xclient.message_type = atmType;
 
484
  e.xclient.format = 32;
 
485
  e.xclient.data.l[0] = nData;
 
486
  e.xclient.data.l[1] = CurrentTime;
 
487
 
 
488
  /* Send the event to X */
 
489
  return XSendEvent (pDisplay, iWin, False, NoEventMask, &e);
 
490
}
 
491
 
 
492
 
 
493
/*
 
494
 * Updates the name of a HWND according to its X WM_NAME property
 
495
 */
 
496
 
 
497
static void
 
498
UpdateName (WMInfoPtr pWMInfo, Window iWindow)
 
499
{
 
500
  char                  *pszName;
 
501
  Atom                  atmType;
 
502
  int                   fmtRet;
 
503
  unsigned long         items, remain;
 
504
  HWND                  *retHwnd, hWnd;
 
505
  XWindowAttributes     attr;
 
506
 
 
507
  hWnd = 0;
 
508
 
 
509
  /* See if we can get the cached HWND for this window... */
 
510
  if (XGetWindowProperty (pWMInfo->pDisplay,
 
511
                          iWindow,
 
512
                          pWMInfo->atmPrivMap,
 
513
                          0,
 
514
                          1,
 
515
                          False,
 
516
                          XA_INTEGER,//pWMInfo->atmPrivMap,
 
517
                          &atmType,
 
518
                          &fmtRet,
 
519
                          &items,
 
520
                          &remain,
 
521
                          (unsigned char **) &retHwnd) == Success)
 
522
    {
 
523
      if (retHwnd)
 
524
        {
 
525
          hWnd = *retHwnd;
 
526
          XFree (retHwnd);
 
527
        }
 
528
    }
 
529
  
 
530
  /* Some sanity checks */
 
531
  if (!hWnd) return;
 
532
  if (!IsWindow (hWnd)) return;
 
533
 
 
534
  /* Set the Windows window name */
 
535
  GetWindowName (pWMInfo->pDisplay, iWindow, &pszName);
 
536
  if (pszName)
 
537
    {
 
538
      /* Get the window attributes */
 
539
      XGetWindowAttributes (pWMInfo->pDisplay,
 
540
                            iWindow,
 
541
                            &attr);
 
542
      if (!attr.override_redirect)
 
543
        {
 
544
          SetWindowText (hWnd, pszName);
 
545
          winUpdateIcon (iWindow);
 
546
        }
 
547
 
 
548
      free (pszName);
 
549
    }
 
550
}
 
551
 
 
552
 
 
553
#if 0
 
554
/*
 
555
 * Fix up any differences between the X11 and Win32 window stacks
 
556
 * starting at the window passed in
 
557
 */
 
558
static void
 
559
PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction)
 
560
{
 
561
  Atom                  atmType;
 
562
  int                   fmtRet;
 
563
  unsigned long         items, remain;
 
564
  HWND                  hWnd, *retHwnd;
 
565
  DWORD                 myWinProcID, winProcID;
 
566
  Window                xWindow;
 
567
  WINDOWPLACEMENT       wndPlace;
 
568
  
 
569
  hWnd = NULL;
 
570
  /* See if we can get the cached HWND for this window... */
 
571
  if (XGetWindowProperty (pWMInfo->pDisplay,
 
572
                          iWindow,
 
573
                          pWMInfo->atmPrivMap,
 
574
                          0,
 
575
                          1,
 
576
                          False,
 
577
                          XA_INTEGER,//pWMInfo->atmPrivMap,
 
578
                          &atmType,
 
579
                          &fmtRet,
 
580
                          &items,
 
581
                          &remain,
 
582
                          (unsigned char **) &retHwnd) == Success)
 
583
    {
 
584
      if (retHwnd)
 
585
        {
 
586
          hWnd = *retHwnd;
 
587
          XFree (retHwnd);
 
588
        }
 
589
    }
 
590
  
 
591
  if (!hWnd) return;
 
592
  
 
593
  GetWindowThreadProcessId (hWnd, &myWinProcID);
 
594
  hWnd = GetNextWindow (hWnd, direction);
 
595
  
 
596
  while (hWnd) {
 
597
    GetWindowThreadProcessId (hWnd, &winProcID);
 
598
    if (winProcID == myWinProcID)
 
599
      {
 
600
        wndPlace.length = sizeof(WINDOWPLACEMENT);
 
601
        GetWindowPlacement (hWnd, &wndPlace);
 
602
        if ( !(wndPlace.showCmd==SW_HIDE ||
 
603
               wndPlace.showCmd==SW_MINIMIZE) )
 
604
          {
 
605
            xWindow = (Window)GetProp (hWnd, WIN_WID_PROP);
 
606
            if (xWindow)
 
607
              {
 
608
                if (direction==GW_HWNDPREV)
 
609
                  XRaiseWindow (pWMInfo->pDisplay, xWindow);
 
610
                else
 
611
                  XLowerWindow (pWMInfo->pDisplay, xWindow);
 
612
              }
 
613
          }
 
614
      }
 
615
    hWnd = GetNextWindow(hWnd, direction);
 
616
  }
 
617
}
 
618
#endif /* PreserveWin32Stack */
 
619
 
 
620
 
 
621
/*
 
622
 * winMultiWindowWMProc
 
623
 */
 
624
 
 
625
static void *
 
626
winMultiWindowWMProc (void *pArg)
 
627
{
 
628
  WMProcArgPtr          pProcArg = (WMProcArgPtr)pArg;
 
629
  WMInfoPtr             pWMInfo = pProcArg->pWMInfo;
 
630
  
 
631
  /* Initialize the Window Manager */
 
632
  winInitMultiWindowWM (pWMInfo, pProcArg);
 
633
  
 
634
#if CYGMULTIWINDOW_DEBUG
 
635
  ErrorF ("winMultiWindowWMProc ()\n");
 
636
#endif
 
637
 
 
638
  /* Loop until we explicity break out */
 
639
  for (;;)
 
640
    {
 
641
      WMMsgNodePtr      pNode;
 
642
 
 
643
      if(g_fAnotherWMRunnig)/* Another Window manager exists. */
 
644
        {
 
645
          Sleep (1000);
 
646
          continue;
 
647
        }
 
648
 
 
649
      /* Pop a message off of our queue */
 
650
      pNode = PopMessage (&pWMInfo->wmMsgQueue, pWMInfo);
 
651
      if (pNode == NULL)
 
652
        {
 
653
          /* Bail if PopMessage returns without a message */
 
654
          /* NOTE: Remember that PopMessage is a blocking function. */
 
655
          ErrorF ("winMultiWindowWMProc - Queue is Empty?  Exiting.\n");
 
656
          pthread_exit (NULL);
 
657
        }
 
658
 
 
659
#if CYGMULTIWINDOW_DEBUG
 
660
      ErrorF ("winMultiWindowWMProc - %d ms MSG: %d ID: %d\n",
 
661
              GetTickCount (), (int)pNode->msg.msg, (int)pNode->msg.dwID);
 
662
#endif
 
663
 
 
664
      /* Branch on the message type */
 
665
      switch (pNode->msg.msg)
 
666
        {
 
667
#if 0
 
668
        case WM_WM_MOVE:
 
669
          ErrorF ("\tWM_WM_MOVE\n");
 
670
          break;
 
671
 
 
672
        case WM_WM_SIZE:
 
673
          ErrorF ("\tWM_WM_SIZE\n");
 
674
          break;
 
675
#endif
 
676
 
 
677
        case WM_WM_RAISE:
 
678
#if CYGMULTIWINDOW_DEBUG
 
679
          ErrorF ("\tWM_WM_RAISE\n");
 
680
#endif
 
681
          /* Raise the window */
 
682
          XRaiseWindow (pWMInfo->pDisplay, pNode->msg.iWindow);
 
683
#if 0
 
684
          PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
 
685
#endif
 
686
          break;
 
687
 
 
688
        case WM_WM_LOWER:
 
689
#if CYGMULTIWINDOW_DEBUG
 
690
          ErrorF ("\tWM_WM_LOWER\n");
 
691
#endif
 
692
 
 
693
          /* Lower the window */
 
694
          XLowerWindow (pWMInfo->pDisplay, pNode->msg.iWindow);
 
695
          break;
 
696
 
 
697
        case WM_WM_MAP:
 
698
#if CYGMULTIWINDOW_DEBUG
 
699
          ErrorF ("\tWM_WM_MAP\n");
 
700
#endif
 
701
          /* Put a note as to the HWND associated with this Window */
 
702
          XChangeProperty (pWMInfo->pDisplay,
 
703
                           pNode->msg.iWindow,
 
704
                           pWMInfo->atmPrivMap,
 
705
                           XA_INTEGER,//pWMInfo->atmPrivMap,
 
706
                           32,
 
707
                           PropModeReplace,
 
708
                           (unsigned char *) &(pNode->msg.hwndWindow),
 
709
                           1);
 
710
          UpdateName (pWMInfo, pNode->msg.iWindow);
 
711
          winUpdateIcon (pNode->msg.iWindow);
 
712
#if 0
 
713
          /* Handles the case where there are AOT windows above it in W32 */
 
714
          PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
 
715
#endif
 
716
          break;
 
717
 
 
718
        case WM_WM_UNMAP:
 
719
#if CYGMULTIWINDOW_DEBUG
 
720
          ErrorF ("\tWM_WM_UNMAP\n");
 
721
#endif
 
722
          
 
723
          /* Unmap the window */
 
724
          XUnmapWindow (pWMInfo->pDisplay, pNode->msg.iWindow);
 
725
          break;
 
726
 
 
727
        case WM_WM_KILL:
 
728
#if CYGMULTIWINDOW_DEBUG
 
729
          ErrorF ("\tWM_WM_KILL\n");
 
730
#endif
 
731
          {
 
732
            int                         i, n, found = 0;
 
733
            Atom                        *protocols;
 
734
            
 
735
            /* --- */
 
736
            if (XGetWMProtocols (pWMInfo->pDisplay,
 
737
                                 pNode->msg.iWindow,
 
738
                                 &protocols,
 
739
                                 &n))
 
740
              {
 
741
                for (i = 0; i < n; ++i)
 
742
                  if (protocols[i] == pWMInfo->atmWmDelete)
 
743
                    ++found;
 
744
                
 
745
                XFree (protocols);
 
746
              }
 
747
 
 
748
            /* --- */
 
749
            if (found)
 
750
              SendXMessage (pWMInfo->pDisplay,
 
751
                            pNode->msg.iWindow,
 
752
                            pWMInfo->atmWmProtos,
 
753
                            pWMInfo->atmWmDelete);
 
754
            else
 
755
              XKillClient (pWMInfo->pDisplay,
 
756
                           pNode->msg.iWindow);
 
757
          }
 
758
          break;
 
759
 
 
760
        case WM_WM_ACTIVATE:
 
761
#if CYGMULTIWINDOW_DEBUG
 
762
          ErrorF ("\tWM_WM_ACTIVATE\n");
 
763
#endif
 
764
          
 
765
          /* Set the input focus */
 
766
          XSetInputFocus (pWMInfo->pDisplay,
 
767
                          pNode->msg.iWindow,
 
768
                          RevertToPointerRoot,
 
769
                          CurrentTime);
 
770
          break;
 
771
 
 
772
        case WM_WM_NAME_EVENT:
 
773
          UpdateName (pWMInfo, pNode->msg.iWindow);
 
774
          break;
 
775
 
 
776
        case WM_WM_HINTS_EVENT:
 
777
          winUpdateIcon (pNode->msg.iWindow);
 
778
          break;
 
779
 
 
780
        case WM_WM_CHANGE_STATE:
 
781
          /* Minimize the window in Windows */
 
782
          winMinimizeWindow (pNode->msg.iWindow);
 
783
          break;
 
784
 
 
785
        default:
 
786
          ErrorF ("winMultiWindowWMProc - Unknown Message.  Exiting.\n");
 
787
          pthread_exit (NULL);
 
788
          break;
 
789
        }
 
790
 
 
791
      /* Free the retrieved message */
 
792
      free (pNode);
 
793
 
 
794
      /* Flush any pending events on our display */
 
795
      XFlush (pWMInfo->pDisplay);
 
796
    }
 
797
 
 
798
  /* Free the condition variable */
 
799
  pthread_cond_destroy (&pWMInfo->wmMsgQueue.pcNotEmpty);
 
800
  
 
801
  /* Free the mutex variable */
 
802
  pthread_mutex_destroy (&pWMInfo->wmMsgQueue.pmMutex);
 
803
  
 
804
  /* Free the passed-in argument */
 
805
  free (pProcArg);
 
806
  
 
807
#if CYGMULTIWINDOW_DEBUG
 
808
  ErrorF("-winMultiWindowWMProc ()\n");
 
809
#endif
 
810
}
 
811
 
 
812
 
 
813
/*
 
814
 * X message procedure
 
815
 */
 
816
 
 
817
static void *
 
818
winMultiWindowXMsgProc (void *pArg)
 
819
{
 
820
  winWMMessageRec       msg;
 
821
  XMsgProcArgPtr        pProcArg = (XMsgProcArgPtr) pArg;
 
822
  char                  pszDisplay[512];
 
823
  int                   iRetries;
 
824
  XEvent                event;
 
825
  Atom                  atmWmName;
 
826
  Atom                  atmWmHints;
 
827
  Atom                  atmWmChange;
 
828
  int                   iReturn;
 
829
  XIconSize             *xis;
 
830
 
 
831
  ErrorF ("winMultiWindowXMsgProc - Hello\n");
 
832
 
 
833
  /* Check that argument pointer is not invalid */
 
834
  if (pProcArg == NULL)
 
835
    {
 
836
      ErrorF ("winMultiWindowXMsgProc - pProcArg is NULL.  Exiting.\n");
 
837
      pthread_exit (NULL);
 
838
    }
 
839
 
 
840
  ErrorF ("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n");
 
841
 
 
842
  /* Grab the server started mutex - pause until we get it */
 
843
  iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted);
 
844
  if (iReturn != 0)
 
845
    {
 
846
      ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d.  "
 
847
              "Exiting.\n",
 
848
              iReturn);
 
849
      pthread_exit (NULL);
 
850
    }
 
851
 
 
852
  ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n");
 
853
 
 
854
  /* Allow multiple threads to access Xlib */
 
855
  if (XInitThreads () == 0)
 
856
    {
 
857
      ErrorF ("winMultiWindowXMsgProc - XInitThreads () failed.  Exiting.\n");
 
858
      pthread_exit (NULL);
 
859
    }
 
860
 
 
861
  /* See if X supports the current locale */
 
862
  if (XSupportsLocale () == False)
 
863
    {
 
864
      ErrorF ("winMultiWindowXMsgProc - Locale not supported by X.  "
 
865
              "Exiting.\n");
 
866
      pthread_exit (NULL);
 
867
    }
 
868
 
 
869
  /* Release the server started mutex */
 
870
  pthread_mutex_unlock (pProcArg->ppmServerStarted);
 
871
 
 
872
  ErrorF ("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
 
873
 
 
874
  /* Set jump point for IO Error exits */
 
875
  iReturn = setjmp (g_jmpXMsgProcEntry);
 
876
  
 
877
  /* Check if we should continue operations */
 
878
  if (iReturn != WIN_JMP_ERROR_IO
 
879
      && iReturn != WIN_JMP_OKAY)
 
880
    {
 
881
      /* setjmp returned an unknown value, exit */
 
882
      ErrorF ("winInitMultiWindowXMsgProc - setjmp returned: %d.  Exiting.\n",
 
883
              iReturn);
 
884
      pthread_exit (NULL);
 
885
    }
 
886
  else if (iReturn == WIN_JMP_ERROR_IO)
 
887
    {
 
888
      ErrorF ("winInitMultiWindowXMsgProc - Caught IO Error.  Exiting.\n");
 
889
      pthread_exit (NULL);
 
890
    }
 
891
 
 
892
  /* Install our error handler */
 
893
  XSetErrorHandler (winMultiWindowXMsgProcErrorHandler);
 
894
  XSetIOErrorHandler (winMultiWindowXMsgProcIOErrorHandler);
 
895
 
 
896
  /* Setup the display connection string x */
 
897
  snprintf (pszDisplay,
 
898
            512, "127.0.0.1:%s.%d", display, (int)pProcArg->dwScreen);
 
899
 
 
900
  /* Print the display connection string */
 
901
  ErrorF ("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay);
 
902
  
 
903
  /* Initialize retry count */
 
904
  iRetries = 0;
 
905
 
 
906
  /* Open the X display */
 
907
  do
 
908
    {
 
909
      /* Try to open the display */
 
910
      pProcArg->pDisplay = XOpenDisplay (pszDisplay);
 
911
      if (pProcArg->pDisplay == NULL)
 
912
        {
 
913
          ErrorF ("winMultiWindowXMsgProc - Could not open display, try: %d, "
 
914
                  "sleeping: %d\n\f",
 
915
                  iRetries + 1, WIN_CONNECT_DELAY);
 
916
          ++iRetries;
 
917
          sleep (WIN_CONNECT_DELAY);
 
918
          continue;
 
919
        }
 
920
      else
 
921
        break;
 
922
    }
 
923
  while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
 
924
  
 
925
  /* Make sure that the display opened */
 
926
  if (pProcArg->pDisplay == NULL)
 
927
    {
 
928
      ErrorF ("winMultiWindowXMsgProc - Failed opening the display.  "
 
929
              "Exiting.\n");
 
930
      pthread_exit (NULL);
 
931
    }
 
932
 
 
933
  ErrorF ("winMultiWindowXMsgProc - XOpenDisplay () returned and "
 
934
          "successfully opened the display.\n");
 
935
 
 
936
  /* Check if another window manager is already running */
 
937
  if (pProcArg->pWMInfo->fAllowOtherWM)
 
938
  {
 
939
    g_fAnotherWMRunnig = CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen);
 
940
  } else {
 
941
    redirectError = FALSE;
 
942
    XSetErrorHandler (winRedirectErrorHandler);          
 
943
    XSelectInput(pProcArg->pDisplay,     
 
944
        RootWindow (pProcArg->pDisplay, pProcArg->dwScreen),     
 
945
        SubstructureNotifyMask | ButtonPressMask);       
 
946
    XSync (pProcArg->pDisplay, 0);       
 
947
    XSetErrorHandler (winMultiWindowXMsgProcErrorHandler);       
 
948
    if (redirectError)   
 
949
    {    
 
950
      ErrorF ("winMultiWindowXMsgProc - "        
 
951
          "another window manager is running.  Exiting.\n");     
 
952
      pthread_exit (NULL);       
 
953
    }
 
954
    g_fAnotherWMRunnig = FALSE;
 
955
  }
 
956
  
 
957
  /* Set up the supported icon sizes */
 
958
  xis = XAllocIconSize ();
 
959
  if (xis)
 
960
    {
 
961
      xis->min_width = xis->min_height = 16;
 
962
      xis->max_width = xis->max_height = 48;
 
963
      xis->width_inc = xis->height_inc = 16;
 
964
      XSetIconSizes (pProcArg->pDisplay,
 
965
                     RootWindow (pProcArg->pDisplay, pProcArg->dwScreen),
 
966
                     xis,
 
967
                     1);
 
968
      XFree (xis);
 
969
    }
 
970
 
 
971
  atmWmName   = XInternAtom (pProcArg->pDisplay,
 
972
                             "WM_NAME",
 
973
                             False);
 
974
  atmWmHints   = XInternAtom (pProcArg->pDisplay,
 
975
                              "WM_HINTS",
 
976
                              False);
 
977
  atmWmChange  = XInternAtom (pProcArg->pDisplay,
 
978
                              "WM_CHANGE_STATE",
 
979
                              False);
 
980
 
 
981
  /* Loop until we explicitly break out */
 
982
  while (1)
 
983
    {
 
984
      if (g_shutdown)
 
985
        break;
 
986
 
 
987
      if (pProcArg->pWMInfo->fAllowOtherWM && !XPending (pProcArg->pDisplay))
 
988
        {
 
989
          if (CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen))
 
990
            {
 
991
              if (!g_fAnotherWMRunnig)
 
992
                {
 
993
                  g_fAnotherWMRunnig = TRUE;
 
994
                  SendMessage(*(HWND*)pProcArg->hwndScreen, WM_UNMANAGE, 0, 0);
 
995
                }
 
996
            }
 
997
          else
 
998
            {
 
999
              if (g_fAnotherWMRunnig)
 
1000
                {
 
1001
                  g_fAnotherWMRunnig = FALSE;
 
1002
                  SendMessage(*(HWND*)pProcArg->hwndScreen, WM_MANAGE, 0, 0);
 
1003
                }
 
1004
            }
 
1005
          Sleep (500);
 
1006
          continue;
 
1007
        }
 
1008
 
 
1009
      /* Fetch next event */
 
1010
      XNextEvent (pProcArg->pDisplay, &event);
 
1011
 
 
1012
      /* Branch on event type */
 
1013
      if (event.type == CreateNotify)
 
1014
        {
 
1015
          XWindowAttributes     attr;
 
1016
 
 
1017
          XSelectInput (pProcArg->pDisplay,
 
1018
                        event.xcreatewindow.window,
 
1019
                        PropertyChangeMask);
 
1020
 
 
1021
          /* Get the window attributes */
 
1022
          XGetWindowAttributes (pProcArg->pDisplay,
 
1023
                                event.xcreatewindow.window,
 
1024
                                &attr);
 
1025
 
 
1026
          if (!attr.override_redirect)
 
1027
            XSetWindowBorderWidth(pProcArg->pDisplay,
 
1028
                                  event.xcreatewindow.window,
 
1029
                                  0);
 
1030
        }
 
1031
      else if (event.type == PropertyNotify
 
1032
               && event.xproperty.atom == atmWmName)
 
1033
        {
 
1034
          memset (&msg, 0, sizeof (msg));
 
1035
 
 
1036
          msg.msg = WM_WM_NAME_EVENT;
 
1037
          msg.iWindow = event.xproperty.window;
 
1038
 
 
1039
          /* Other fields ignored */
 
1040
          winSendMessageToWM (pProcArg->pWMInfo, &msg);
 
1041
        }
 
1042
      else if (event.type == PropertyNotify
 
1043
               && event.xproperty.atom == atmWmHints)
 
1044
        {
 
1045
          memset (&msg, 0, sizeof (msg));
 
1046
 
 
1047
          msg.msg = WM_WM_HINTS_EVENT;
 
1048
          msg.iWindow = event.xproperty.window;
 
1049
 
 
1050
          /* Other fields ignored */
 
1051
          winSendMessageToWM (pProcArg->pWMInfo, &msg);
 
1052
        }
 
1053
      else if (event.type == ClientMessage
 
1054
               && event.xclient.message_type == atmWmChange
 
1055
               && event.xclient.data.l[0] == IconicState)
 
1056
        {
 
1057
          ErrorF ("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
 
1058
 
 
1059
          memset (&msg, 0, sizeof (msg));
 
1060
 
 
1061
          msg.msg = WM_WM_CHANGE_STATE;
 
1062
          msg.iWindow = event.xclient.window;
 
1063
 
 
1064
          winSendMessageToWM (pProcArg->pWMInfo, &msg);
 
1065
        }
 
1066
    }
 
1067
 
 
1068
  XCloseDisplay (pProcArg->pDisplay);
 
1069
  pthread_exit (NULL);
 
1070
 
 
1071
}
 
1072
 
 
1073
 
 
1074
/*
 
1075
 * winInitWM - Entry point for the X server to spawn
 
1076
 * the Window Manager thread.  Called from
 
1077
 * winscrinit.c/winFinishScreenInitFB ().
 
1078
 */
 
1079
 
 
1080
Bool
 
1081
winInitWM (void **ppWMInfo,
 
1082
           pthread_t *ptWMProc,
 
1083
           pthread_t *ptXMsgProc,
 
1084
           pthread_mutex_t *ppmServerStarted,
 
1085
           int dwScreen,
 
1086
           HWND hwndScreen,
 
1087
           BOOL allowOtherWM)
 
1088
{
 
1089
  WMProcArgPtr          pArg = (WMProcArgPtr) malloc (sizeof(WMProcArgRec));
 
1090
  WMInfoPtr             pWMInfo = (WMInfoPtr) malloc (sizeof(WMInfoRec));
 
1091
  XMsgProcArgPtr        pXMsgArg = (XMsgProcArgPtr) malloc (sizeof(XMsgProcArgRec));
 
1092
 
 
1093
  /* Bail if the input parameters are bad */
 
1094
  if (pArg == NULL || pWMInfo == NULL)
 
1095
    {
 
1096
      ErrorF ("winInitWM - malloc failed.\n");
 
1097
      return FALSE;
 
1098
    }
 
1099
  
 
1100
  /* Zero the allocated memory */
 
1101
  ZeroMemory (pArg, sizeof (WMProcArgRec));
 
1102
  ZeroMemory (pWMInfo, sizeof (WMInfoRec));
 
1103
  ZeroMemory (pXMsgArg, sizeof (XMsgProcArgRec));
 
1104
 
 
1105
  /* Set a return pointer to the Window Manager info structure */
 
1106
  *ppWMInfo = pWMInfo;
 
1107
  pWMInfo->fAllowOtherWM = allowOtherWM;
 
1108
 
 
1109
  /* Setup the argument structure for the thread function */
 
1110
  pArg->dwScreen = dwScreen;
 
1111
  pArg->pWMInfo = pWMInfo;
 
1112
  pArg->ppmServerStarted = ppmServerStarted;
 
1113
  
 
1114
  /* Intialize the message queue */
 
1115
  if (!InitQueue (&pWMInfo->wmMsgQueue))
 
1116
    {
 
1117
      ErrorF ("winInitWM - InitQueue () failed.\n");
 
1118
      return FALSE;
 
1119
    }
 
1120
  
 
1121
  /* Spawn a thread for the Window Manager */
 
1122
  if (pthread_create (ptWMProc, NULL, winMultiWindowWMProc, pArg))
 
1123
    {
 
1124
      /* Bail if thread creation failed */
 
1125
      ErrorF ("winInitWM - pthread_create failed for Window Manager.\n");
 
1126
      return FALSE;
 
1127
    }
 
1128
 
 
1129
  /* Spawn the XNextEvent thread, will send messages to WM */
 
1130
  pXMsgArg->dwScreen = dwScreen;
 
1131
  pXMsgArg->pWMInfo = pWMInfo;
 
1132
  pXMsgArg->ppmServerStarted = ppmServerStarted;
 
1133
  pXMsgArg->hwndScreen = hwndScreen;
 
1134
  if (pthread_create (ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg))
 
1135
    {
 
1136
      /* Bail if thread creation failed */
 
1137
      ErrorF ("winInitWM - pthread_create failed on XMSG.\n");
 
1138
      return FALSE;
 
1139
    }
 
1140
 
 
1141
#if CYGDEBUG || YES
 
1142
  winDebug ("winInitWM - Returning.\n");
 
1143
#endif
 
1144
 
 
1145
  return TRUE;
 
1146
}
 
1147
 
 
1148
 
 
1149
/*
 
1150
 * Window manager thread - setup
 
1151
 */
 
1152
 
 
1153
static void
 
1154
winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
 
1155
{
 
1156
  int                   iRetries = 0;
 
1157
  char                  pszDisplay[512];
 
1158
  int                   iReturn;
 
1159
 
 
1160
  ErrorF ("winInitMultiWindowWM - Hello\n");
 
1161
 
 
1162
  /* Check that argument pointer is not invalid */
 
1163
  if (pProcArg == NULL)
 
1164
    {
 
1165
      ErrorF ("winInitMultiWindowWM - pProcArg is NULL.  Exiting.\n");
 
1166
      pthread_exit (NULL);
 
1167
    }
 
1168
 
 
1169
  ErrorF ("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n");
 
1170
 
 
1171
  /* Grab our garbage mutex to satisfy pthread_cond_wait */
 
1172
  iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted);
 
1173
  if (iReturn != 0)
 
1174
    {
 
1175
      ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () failed: %d.  "
 
1176
              "Exiting.\n",
 
1177
              iReturn);
 
1178
      pthread_exit (NULL);
 
1179
    }
 
1180
 
 
1181
  ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () returned.\n");
 
1182
 
 
1183
  /* Allow multiple threads to access Xlib */
 
1184
  if (XInitThreads () == 0)
 
1185
    {
 
1186
      ErrorF ("winInitMultiWindowWM - XInitThreads () failed.  Exiting.\n");
 
1187
      pthread_exit (NULL);
 
1188
    }
 
1189
 
 
1190
  /* See if X supports the current locale */
 
1191
  if (XSupportsLocale () == False)
 
1192
    {
 
1193
      ErrorF ("winInitMultiWindowWM - Locale not supported by X.  Exiting.\n");
 
1194
      pthread_exit (NULL);
 
1195
    }
 
1196
 
 
1197
  /* Release the server started mutex */
 
1198
  pthread_mutex_unlock (pProcArg->ppmServerStarted);
 
1199
 
 
1200
  ErrorF ("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
 
1201
 
 
1202
  /* Set jump point for IO Error exits */
 
1203
  iReturn = setjmp (g_jmpWMEntry);
 
1204
  
 
1205
  /* Check if we should continue operations */
 
1206
  if (iReturn != WIN_JMP_ERROR_IO
 
1207
      && iReturn != WIN_JMP_OKAY)
 
1208
    {
 
1209
      /* setjmp returned an unknown value, exit */
 
1210
      ErrorF ("winInitMultiWindowWM - setjmp returned: %d.  Exiting.\n",
 
1211
              iReturn);
 
1212
      pthread_exit (NULL);
 
1213
    }
 
1214
  else if (iReturn == WIN_JMP_ERROR_IO)
 
1215
    {
 
1216
      ErrorF ("winInitMultiWindowWM - Caught IO Error.  Exiting.\n");
 
1217
      pthread_exit (NULL);
 
1218
    }
 
1219
 
 
1220
  /* Install our error handler */
 
1221
  XSetErrorHandler (winMultiWindowWMErrorHandler);
 
1222
  XSetIOErrorHandler (winMultiWindowWMIOErrorHandler);
 
1223
 
 
1224
  /* Setup the display connection string x */
 
1225
  snprintf (pszDisplay,
 
1226
            512,
 
1227
            "127.0.0.1:%s.%d",
 
1228
            display,
 
1229
            (int) pProcArg->dwScreen);
 
1230
 
 
1231
  /* Print the display connection string */
 
1232
  ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay);
 
1233
  
 
1234
  /* Open the X display */
 
1235
  do
 
1236
    {
 
1237
      /* Try to open the display */
 
1238
      pWMInfo->pDisplay = XOpenDisplay (pszDisplay);
 
1239
      if (pWMInfo->pDisplay == NULL)
 
1240
        {
 
1241
          ErrorF ("winInitMultiWindowWM - Could not open display, try: %d, "
 
1242
                  "sleeping: %d\n\f",
 
1243
                  iRetries + 1, WIN_CONNECT_DELAY);
 
1244
          ++iRetries;
 
1245
          sleep (WIN_CONNECT_DELAY);
 
1246
          continue;
 
1247
        }
 
1248
      else
 
1249
        break;
 
1250
    }
 
1251
  while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
 
1252
  
 
1253
  /* Make sure that the display opened */
 
1254
  if (pWMInfo->pDisplay == NULL)
 
1255
    {
 
1256
      ErrorF ("winInitMultiWindowWM - Failed opening the display.  "
 
1257
              "Exiting.\n");
 
1258
      pthread_exit (NULL);
 
1259
    }
 
1260
 
 
1261
  ErrorF ("winInitMultiWindowWM - XOpenDisplay () returned and "
 
1262
          "successfully opened the display.\n");
 
1263
  
 
1264
 
 
1265
  /* Create some atoms */
 
1266
  pWMInfo->atmWmProtos = XInternAtom (pWMInfo->pDisplay,
 
1267
                                      "WM_PROTOCOLS",
 
1268
                                      False);
 
1269
  pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay,
 
1270
                                      "WM_DELETE_WINDOW",
 
1271
                                      False);
 
1272
#ifdef XWIN_MULTIWINDOWEXTWM
 
1273
  pWMInfo->atmPrivMap  = XInternAtom (pWMInfo->pDisplay,
 
1274
                                      WINDOWSWM_NATIVE_HWND,
 
1275
                                      False);
 
1276
#endif
 
1277
 
 
1278
 
 
1279
  if (1) {
 
1280
    Cursor cursor = XCreateFontCursor (pWMInfo->pDisplay, XC_left_ptr);
 
1281
    if (cursor)
 
1282
    {
 
1283
      XDefineCursor (pWMInfo->pDisplay, DefaultRootWindow(pWMInfo->pDisplay), cursor);
 
1284
      XFreeCursor (pWMInfo->pDisplay, cursor);
 
1285
    }
 
1286
  }
 
1287
}
 
1288
 
 
1289
 
 
1290
/*
 
1291
 * winSendMessageToWM - Send a message from the X thread to the WM thread
 
1292
 */
 
1293
 
 
1294
void
 
1295
winSendMessageToWM (void *pWMInfo, winWMMessagePtr pMsg)
 
1296
{
 
1297
  WMMsgNodePtr pNode;
 
1298
  
 
1299
#if CYGMULTIWINDOW_DEBUG
 
1300
  ErrorF ("winSendMessageToWM ()\n");
 
1301
#endif
 
1302
  
 
1303
  pNode = (WMMsgNodePtr)malloc(sizeof(WMMsgNodeRec));
 
1304
  if (pNode != NULL)
 
1305
    {
 
1306
      memcpy (&pNode->msg, pMsg, sizeof(winWMMessageRec));
 
1307
      PushMessage (&((WMInfoPtr)pWMInfo)->wmMsgQueue, pNode);
 
1308
    }
 
1309
}
 
1310
 
 
1311
 
 
1312
/*
 
1313
 * Window manager error handler
 
1314
 */
 
1315
 
 
1316
static int
 
1317
winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr)
 
1318
{
 
1319
  char pszErrorMsg[100];
 
1320
 
 
1321
  if (pErr->request_code == X_ChangeWindowAttributes
 
1322
      && pErr->error_code == BadAccess)
 
1323
    {
 
1324
      ErrorF ("winMultiWindowWMErrorHandler - ChangeWindowAttributes "
 
1325
              "BadAccess.\n");
 
1326
      return 0;
 
1327
    }
 
1328
  
 
1329
  XGetErrorText (pDisplay,
 
1330
                 pErr->error_code,
 
1331
                 pszErrorMsg,
 
1332
                 sizeof (pszErrorMsg));
 
1333
  ErrorF ("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg);
 
1334
 
 
1335
  return 0;
 
1336
}
 
1337
 
 
1338
 
 
1339
/*
 
1340
 * Window manager IO error handler
 
1341
 */
 
1342
 
 
1343
static int
 
1344
winMultiWindowWMIOErrorHandler (Display *pDisplay)
 
1345
{
 
1346
  ErrorF ("\nwinMultiWindowWMIOErrorHandler!\n\n");
 
1347
 
 
1348
  if (g_shutdown)
 
1349
    pthread_exit(NULL);
 
1350
 
 
1351
  /* Restart at the main entry point */
 
1352
  longjmp (g_jmpWMEntry, WIN_JMP_ERROR_IO);
 
1353
  
 
1354
  return 0;
 
1355
}
 
1356
 
 
1357
 
 
1358
/*
 
1359
 * X message procedure error handler
 
1360
 */
 
1361
 
 
1362
static int
 
1363
winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr)
 
1364
{
 
1365
  char pszErrorMsg[100];
 
1366
  
 
1367
  XGetErrorText (pDisplay,
 
1368
                 pErr->error_code,
 
1369
                 pszErrorMsg,
 
1370
                 sizeof (pszErrorMsg));
 
1371
  ErrorF ("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg);
 
1372
  
 
1373
  return 0;
 
1374
}
 
1375
 
 
1376
 
 
1377
/*
 
1378
 * X message procedure IO error handler
 
1379
 */
 
1380
 
 
1381
static int
 
1382
winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay)
 
1383
{
 
1384
  ErrorF ("\nwinMultiWindowXMsgProcIOErrorHandler!\n\n");
 
1385
 
 
1386
  /* Restart at the main entry point */
 
1387
  longjmp (g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO);
 
1388
  
 
1389
  return 0;
 
1390
}
 
1391
 
 
1392
 
 
1393
/*
 
1394
 * Catch RedirectError to detect other window manager running
 
1395
 */
 
1396
 
 
1397
static int
 
1398
winRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr)
 
1399
{
 
1400
  redirectError = TRUE;
 
1401
  return 0;
 
1402
}
 
1403
 
 
1404
 
 
1405
/*
 
1406
 * Check if another window manager is running
 
1407
 */
 
1408
 
 
1409
static Bool
 
1410
CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen)
 
1411
{
 
1412
  redirectError = FALSE;
 
1413
  XSetErrorHandler (winRedirectErrorHandler);
 
1414
  XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen),
 
1415
               // SubstructureNotifyMask | ButtonPressMask
 
1416
               ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
 
1417
               SubstructureRedirectMask | KeyPressMask |
 
1418
               ButtonPressMask | ButtonReleaseMask);
 
1419
  XSync (pDisplay, 0);
 
1420
  XSetErrorHandler (winMultiWindowXMsgProcErrorHandler);
 
1421
  XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen),
 
1422
               SubstructureNotifyMask);
 
1423
  XSync (pDisplay, 0);
 
1424
  if (redirectError)
 
1425
    {
 
1426
      //ErrorF ("CheckAnotherWindowManager() - another window manager is running.  Exiting.\n");
 
1427
      return TRUE;
 
1428
    }
 
1429
  else
 
1430
    {
 
1431
      return FALSE;
 
1432
    }
 
1433
}
 
1434
 
 
1435
/*
 
1436
 * Notify the MWM thread we're exiting and not to reconnect
 
1437
 */
 
1438
 
 
1439
void
 
1440
winDeinitMultiWindowWM ()
 
1441
{
 
1442
  ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n");
 
1443
  g_shutdown = TRUE;
 
1444
}