2
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
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:
12
*The above copyright notice and this permission notice shall be
13
*included in all copies or substantial portions of the Software.
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.
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.
28
* Authors: Kensuke Matsuzaki
30
/* $XFree86: xc/programs/Xserver/hw/xwin/winwindow.c,v 1.5 2002/11/07 10:31:32 alanh Exp $ */
33
#ifdef HAVE_XWIN_CONFIG_H
34
#include <xwin-config.h>
40
#include <sys/select.h>
48
#include <X11/Xatom.h>
50
#include <X11/Xlocale.h>
51
#include <X11/Xproto.h>
52
#include <X11/Xutil.h>
53
#include <X11/cursorfont.h>
57
/* Fixups to prevent collisions between Windows and X headers */
68
#include "winwindow.h"
69
#ifdef XWIN_MULTIWINDOWEXTWM
70
#include "windowswmstr.h"
73
extern void winDebug(const char *format, ...);
83
#define WIN_CONNECT_RETRIES 5
84
#define WIN_CONNECT_DELAY 5
86
# define WIN_MSG_QUEUE_FNAME "/dev/windows"
88
#define WIN_JMP_OKAY 0
89
#define WIN_JMP_ERROR_IO 2
96
typedef struct _WMMsgNodeRec {
98
struct _WMMsgNodeRec *pNext;
99
} WMMsgNodeRec, *WMMsgNodePtr;
101
typedef struct _WMMsgQueueRec {
102
struct _WMMsgNodeRec *pHead;
103
struct _WMMsgNodeRec *pTail;
104
pthread_mutex_t pmMutex;
105
pthread_cond_t pcNotEmpty;
107
} WMMsgQueueRec, *WMMsgQueuePtr;
109
typedef struct _WMInfo {
111
WMMsgQueueRec wmMsgQueue;
116
} WMInfoRec, *WMInfoPtr;
118
typedef struct _WMProcArgRec {
121
pthread_mutex_t *ppmServerStarted;
122
} WMProcArgRec, *WMProcArgPtr;
124
typedef struct _XMsgProcArgRec {
128
pthread_mutex_t *ppmServerStarted;
130
} XMsgProcArgRec, *XMsgProcArgPtr;
134
* References to external symbols
137
extern char *display;
138
extern void ErrorF (const char* /*f*/, ...);
142
* Prototypes for local functions
146
PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode);
149
PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo);
152
InitQueue (WMMsgQueuePtr pQueue);
155
GetWindowName (Display * pDpy, Window iWin, char **ppName);
158
SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData);
161
UpdateName (WMInfoPtr pWMInfo, Window iWindow);
164
winMultiWindowWMProc (void* pArg);
167
winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr);
170
winMultiWindowWMIOErrorHandler (Display *pDisplay);
173
winMultiWindowXMsgProc (void *pArg);
176
winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr);
179
winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay);
182
winRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr);
185
winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg);
189
PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction);
193
CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen);
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;
207
* PushMessage - Push a message onto the queue
211
PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
214
/* Lock the queue mutex */
215
pthread_mutex_lock (&pQueue->pmMutex);
219
if (pQueue->pTail != NULL)
221
pQueue->pTail->pNext = pNode;
223
pQueue->pTail = pNode;
225
if (pQueue->pHead == NULL)
227
pQueue->pHead = pNode;
232
switch (pNode->msg.msg)
235
ErrorF ("\tWM_WM_MOVE\n");
238
ErrorF ("\tWM_WM_SIZE\n");
241
ErrorF ("\tWM_WM_RAISE\n");
244
ErrorF ("\tWM_WM_LOWER\n");
247
ErrorF ("\tWM_WM_MAP\n");
250
ErrorF ("\tWM_WM_UNMAP\n");
253
ErrorF ("\tWM_WM_KILL\n");
256
ErrorF ("\tWM_WM_ACTIVATE\n");
259
ErrorF ("\tUnknown Message.\n");
264
/* Increase the count of elements in the queue by one */
265
++(pQueue->nQueueSize);
267
/* Release the queue mutex */
268
pthread_mutex_unlock (&pQueue->pmMutex);
270
/* Signal that the queue is not empty */
271
pthread_cond_signal (&pQueue->pcNotEmpty);
275
#if CYGMULTIWINDOW_DEBUG
277
* QueueSize - Return the size of the queue
281
QueueSize (WMMsgQueuePtr pQueue)
286
/* Loop through all elements in the queue */
287
for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext)
296
* PopMessage - Pop a message from the queue
300
PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo)
304
/* Lock the queue mutex */
305
pthread_mutex_lock (&pQueue->pmMutex);
308
while (pQueue->pHead == NULL)
310
pthread_cond_wait (&pQueue->pcNotEmpty, &pQueue->pmMutex);
313
pNode = pQueue->pHead;
314
if (pQueue->pHead != NULL)
316
pQueue->pHead = pQueue->pHead->pNext;
319
if (pQueue->pTail == pNode)
321
pQueue->pTail = NULL;
324
/* Drop the number of elements in the queue by one */
325
--(pQueue->nQueueSize);
327
#if CYGMULTIWINDOW_DEBUG
328
ErrorF ("Queue Size %d %d\n", pQueue->nQueueSize, QueueSize(pQueue));
331
/* Release the queue mutex */
332
pthread_mutex_unlock (&pQueue->pmMutex);
344
HaveMessage (WMMsgQueuePtr pQueue, UINT msg, Window iWindow)
348
for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext)
350
if (pNode->msg.msg==msg && pNode->msg.iWindow==iWindow)
360
* InitQueue - Initialize the Window Manager message queue
365
InitQueue (WMMsgQueuePtr pQueue)
367
/* Check if the pQueue pointer is NULL */
370
ErrorF ("InitQueue - pQueue is NULL. Exiting.\n");
374
/* Set the head and tail to NULL */
375
pQueue->pHead = NULL;
376
pQueue->pTail = NULL;
378
/* There are no elements initially */
379
pQueue->nQueueSize = 0;
381
#if CYGMULTIWINDOW_DEBUG
382
ErrorF ("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize,
386
ErrorF ("InitQueue - Calling pthread_mutex_init\n");
388
/* Create synchronization objects */
389
pthread_mutex_init (&pQueue->pmMutex, NULL);
391
ErrorF ("InitQueue - pthread_mutex_init returned\n");
392
ErrorF ("InitQueue - Calling pthread_cond_init\n");
394
pthread_cond_init (&pQueue->pcNotEmpty, NULL);
396
ErrorF ("InitQueue - pthread_cond_init returned\n");
403
* GetWindowName - Retrieve the title of an X Window
407
GetWindowName (Display *pDisplay, Window iWin, char **ppName)
411
XTextProperty xtpName;
413
#if CYGMULTIWINDOW_DEBUG
414
ErrorF ("GetWindowName\n");
417
/* Intialize ppName to NULL */
421
nResult = XGetWMName (pDisplay, iWin, &xtpName);
422
if (!nResult || !xtpName.value || !xtpName.nitems)
424
#if CYGMULTIWINDOW_DEBUG
425
ErrorF ("GetWindowName - XGetWMName failed. No name.\n");
431
if (xtpName.encoding == XA_STRING)
436
int size = xtpName.nitems * (xtpName.format >> 3);
437
*ppName = malloc(size + 1);
438
strncpy(*ppName, xtpName.value, size);
440
XFree (xtpName.value);
443
#if CYGMULTIWINDOW_DEBUG
444
ErrorF ("GetWindowName - XA_STRING %s\n", *ppName);
449
XmbTextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum);
452
if (nNum && ppList && *ppList)
454
*ppName = strdup (*ppList);
455
XFreeStringList (ppList);
457
XFree (xtpName.value);
459
#if CYGMULTIWINDOW_DEBUG
460
ErrorF ("GetWindowName - %s %s\n",
461
XGetAtomName (pDisplay, xtpName.encoding), *ppName);
465
#if CYGMULTIWINDOW_DEBUG
466
ErrorF ("GetWindowName - Returning\n");
472
* Send a message to the X server from the WM thread
476
SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData)
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;
488
/* Send the event to X */
489
return XSendEvent (pDisplay, iWin, False, NoEventMask, &e);
494
* Updates the name of a HWND according to its X WM_NAME property
498
UpdateName (WMInfoPtr pWMInfo, Window iWindow)
503
unsigned long items, remain;
505
XWindowAttributes attr;
509
/* See if we can get the cached HWND for this window... */
510
if (XGetWindowProperty (pWMInfo->pDisplay,
516
XA_INTEGER,//pWMInfo->atmPrivMap,
521
(unsigned char **) &retHwnd) == Success)
530
/* Some sanity checks */
532
if (!IsWindow (hWnd)) return;
534
/* Set the Windows window name */
535
GetWindowName (pWMInfo->pDisplay, iWindow, &pszName);
538
/* Get the window attributes */
539
XGetWindowAttributes (pWMInfo->pDisplay,
542
if (!attr.override_redirect)
544
SetWindowText (hWnd, pszName);
545
winUpdateIcon (iWindow);
555
* Fix up any differences between the X11 and Win32 window stacks
556
* starting at the window passed in
559
PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction)
563
unsigned long items, remain;
565
DWORD myWinProcID, winProcID;
567
WINDOWPLACEMENT wndPlace;
570
/* See if we can get the cached HWND for this window... */
571
if (XGetWindowProperty (pWMInfo->pDisplay,
577
XA_INTEGER,//pWMInfo->atmPrivMap,
582
(unsigned char **) &retHwnd) == Success)
593
GetWindowThreadProcessId (hWnd, &myWinProcID);
594
hWnd = GetNextWindow (hWnd, direction);
597
GetWindowThreadProcessId (hWnd, &winProcID);
598
if (winProcID == myWinProcID)
600
wndPlace.length = sizeof(WINDOWPLACEMENT);
601
GetWindowPlacement (hWnd, &wndPlace);
602
if ( !(wndPlace.showCmd==SW_HIDE ||
603
wndPlace.showCmd==SW_MINIMIZE) )
605
xWindow = (Window)GetProp (hWnd, WIN_WID_PROP);
608
if (direction==GW_HWNDPREV)
609
XRaiseWindow (pWMInfo->pDisplay, xWindow);
611
XLowerWindow (pWMInfo->pDisplay, xWindow);
615
hWnd = GetNextWindow(hWnd, direction);
618
#endif /* PreserveWin32Stack */
622
* winMultiWindowWMProc
626
winMultiWindowWMProc (void *pArg)
628
WMProcArgPtr pProcArg = (WMProcArgPtr)pArg;
629
WMInfoPtr pWMInfo = pProcArg->pWMInfo;
631
/* Initialize the Window Manager */
632
winInitMultiWindowWM (pWMInfo, pProcArg);
634
#if CYGMULTIWINDOW_DEBUG
635
ErrorF ("winMultiWindowWMProc ()\n");
638
/* Loop until we explicity break out */
643
if(g_fAnotherWMRunnig)/* Another Window manager exists. */
649
/* Pop a message off of our queue */
650
pNode = PopMessage (&pWMInfo->wmMsgQueue, pWMInfo);
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");
659
#if CYGMULTIWINDOW_DEBUG
660
ErrorF ("winMultiWindowWMProc - %d ms MSG: %d ID: %d\n",
661
GetTickCount (), (int)pNode->msg.msg, (int)pNode->msg.dwID);
664
/* Branch on the message type */
665
switch (pNode->msg.msg)
669
ErrorF ("\tWM_WM_MOVE\n");
673
ErrorF ("\tWM_WM_SIZE\n");
678
#if CYGMULTIWINDOW_DEBUG
679
ErrorF ("\tWM_WM_RAISE\n");
681
/* Raise the window */
682
XRaiseWindow (pWMInfo->pDisplay, pNode->msg.iWindow);
684
PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
689
#if CYGMULTIWINDOW_DEBUG
690
ErrorF ("\tWM_WM_LOWER\n");
693
/* Lower the window */
694
XLowerWindow (pWMInfo->pDisplay, pNode->msg.iWindow);
698
#if CYGMULTIWINDOW_DEBUG
699
ErrorF ("\tWM_WM_MAP\n");
701
/* Put a note as to the HWND associated with this Window */
702
XChangeProperty (pWMInfo->pDisplay,
705
XA_INTEGER,//pWMInfo->atmPrivMap,
708
(unsigned char *) &(pNode->msg.hwndWindow),
710
UpdateName (pWMInfo, pNode->msg.iWindow);
711
winUpdateIcon (pNode->msg.iWindow);
713
/* Handles the case where there are AOT windows above it in W32 */
714
PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
719
#if CYGMULTIWINDOW_DEBUG
720
ErrorF ("\tWM_WM_UNMAP\n");
723
/* Unmap the window */
724
XUnmapWindow (pWMInfo->pDisplay, pNode->msg.iWindow);
728
#if CYGMULTIWINDOW_DEBUG
729
ErrorF ("\tWM_WM_KILL\n");
736
if (XGetWMProtocols (pWMInfo->pDisplay,
741
for (i = 0; i < n; ++i)
742
if (protocols[i] == pWMInfo->atmWmDelete)
750
SendXMessage (pWMInfo->pDisplay,
752
pWMInfo->atmWmProtos,
753
pWMInfo->atmWmDelete);
755
XKillClient (pWMInfo->pDisplay,
761
#if CYGMULTIWINDOW_DEBUG
762
ErrorF ("\tWM_WM_ACTIVATE\n");
765
/* Set the input focus */
766
XSetInputFocus (pWMInfo->pDisplay,
772
case WM_WM_NAME_EVENT:
773
UpdateName (pWMInfo, pNode->msg.iWindow);
776
case WM_WM_HINTS_EVENT:
777
winUpdateIcon (pNode->msg.iWindow);
780
case WM_WM_CHANGE_STATE:
781
/* Minimize the window in Windows */
782
winMinimizeWindow (pNode->msg.iWindow);
786
ErrorF ("winMultiWindowWMProc - Unknown Message. Exiting.\n");
791
/* Free the retrieved message */
794
/* Flush any pending events on our display */
795
XFlush (pWMInfo->pDisplay);
798
/* Free the condition variable */
799
pthread_cond_destroy (&pWMInfo->wmMsgQueue.pcNotEmpty);
801
/* Free the mutex variable */
802
pthread_mutex_destroy (&pWMInfo->wmMsgQueue.pmMutex);
804
/* Free the passed-in argument */
807
#if CYGMULTIWINDOW_DEBUG
808
ErrorF("-winMultiWindowWMProc ()\n");
814
* X message procedure
818
winMultiWindowXMsgProc (void *pArg)
821
XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg;
822
char pszDisplay[512];
831
ErrorF ("winMultiWindowXMsgProc - Hello\n");
833
/* Check that argument pointer is not invalid */
834
if (pProcArg == NULL)
836
ErrorF ("winMultiWindowXMsgProc - pProcArg is NULL. Exiting.\n");
840
ErrorF ("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n");
842
/* Grab the server started mutex - pause until we get it */
843
iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted);
846
ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d. "
852
ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n");
854
/* Allow multiple threads to access Xlib */
855
if (XInitThreads () == 0)
857
ErrorF ("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n");
861
/* See if X supports the current locale */
862
if (XSupportsLocale () == False)
864
ErrorF ("winMultiWindowXMsgProc - Locale not supported by X. "
869
/* Release the server started mutex */
870
pthread_mutex_unlock (pProcArg->ppmServerStarted);
872
ErrorF ("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
874
/* Set jump point for IO Error exits */
875
iReturn = setjmp (g_jmpXMsgProcEntry);
877
/* Check if we should continue operations */
878
if (iReturn != WIN_JMP_ERROR_IO
879
&& iReturn != WIN_JMP_OKAY)
881
/* setjmp returned an unknown value, exit */
882
ErrorF ("winInitMultiWindowXMsgProc - setjmp returned: %d. Exiting.\n",
886
else if (iReturn == WIN_JMP_ERROR_IO)
888
ErrorF ("winInitMultiWindowXMsgProc - Caught IO Error. Exiting.\n");
892
/* Install our error handler */
893
XSetErrorHandler (winMultiWindowXMsgProcErrorHandler);
894
XSetIOErrorHandler (winMultiWindowXMsgProcIOErrorHandler);
896
/* Setup the display connection string x */
897
snprintf (pszDisplay,
898
512, "127.0.0.1:%s.%d", display, (int)pProcArg->dwScreen);
900
/* Print the display connection string */
901
ErrorF ("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay);
903
/* Initialize retry count */
906
/* Open the X display */
909
/* Try to open the display */
910
pProcArg->pDisplay = XOpenDisplay (pszDisplay);
911
if (pProcArg->pDisplay == NULL)
913
ErrorF ("winMultiWindowXMsgProc - Could not open display, try: %d, "
915
iRetries + 1, WIN_CONNECT_DELAY);
917
sleep (WIN_CONNECT_DELAY);
923
while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
925
/* Make sure that the display opened */
926
if (pProcArg->pDisplay == NULL)
928
ErrorF ("winMultiWindowXMsgProc - Failed opening the display. "
933
ErrorF ("winMultiWindowXMsgProc - XOpenDisplay () returned and "
934
"successfully opened the display.\n");
936
/* Check if another window manager is already running */
937
if (pProcArg->pWMInfo->fAllowOtherWM)
939
g_fAnotherWMRunnig = CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen);
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);
950
ErrorF ("winMultiWindowXMsgProc - "
951
"another window manager is running. Exiting.\n");
954
g_fAnotherWMRunnig = FALSE;
957
/* Set up the supported icon sizes */
958
xis = XAllocIconSize ();
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),
971
atmWmName = XInternAtom (pProcArg->pDisplay,
974
atmWmHints = XInternAtom (pProcArg->pDisplay,
977
atmWmChange = XInternAtom (pProcArg->pDisplay,
981
/* Loop until we explicitly break out */
987
if (pProcArg->pWMInfo->fAllowOtherWM && !XPending (pProcArg->pDisplay))
989
if (CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen))
991
if (!g_fAnotherWMRunnig)
993
g_fAnotherWMRunnig = TRUE;
994
SendMessage(*(HWND*)pProcArg->hwndScreen, WM_UNMANAGE, 0, 0);
999
if (g_fAnotherWMRunnig)
1001
g_fAnotherWMRunnig = FALSE;
1002
SendMessage(*(HWND*)pProcArg->hwndScreen, WM_MANAGE, 0, 0);
1009
/* Fetch next event */
1010
XNextEvent (pProcArg->pDisplay, &event);
1012
/* Branch on event type */
1013
if (event.type == CreateNotify)
1015
XWindowAttributes attr;
1017
XSelectInput (pProcArg->pDisplay,
1018
event.xcreatewindow.window,
1019
PropertyChangeMask);
1021
/* Get the window attributes */
1022
XGetWindowAttributes (pProcArg->pDisplay,
1023
event.xcreatewindow.window,
1026
if (!attr.override_redirect)
1027
XSetWindowBorderWidth(pProcArg->pDisplay,
1028
event.xcreatewindow.window,
1031
else if (event.type == PropertyNotify
1032
&& event.xproperty.atom == atmWmName)
1034
memset (&msg, 0, sizeof (msg));
1036
msg.msg = WM_WM_NAME_EVENT;
1037
msg.iWindow = event.xproperty.window;
1039
/* Other fields ignored */
1040
winSendMessageToWM (pProcArg->pWMInfo, &msg);
1042
else if (event.type == PropertyNotify
1043
&& event.xproperty.atom == atmWmHints)
1045
memset (&msg, 0, sizeof (msg));
1047
msg.msg = WM_WM_HINTS_EVENT;
1048
msg.iWindow = event.xproperty.window;
1050
/* Other fields ignored */
1051
winSendMessageToWM (pProcArg->pWMInfo, &msg);
1053
else if (event.type == ClientMessage
1054
&& event.xclient.message_type == atmWmChange
1055
&& event.xclient.data.l[0] == IconicState)
1057
ErrorF ("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
1059
memset (&msg, 0, sizeof (msg));
1061
msg.msg = WM_WM_CHANGE_STATE;
1062
msg.iWindow = event.xclient.window;
1064
winSendMessageToWM (pProcArg->pWMInfo, &msg);
1068
XCloseDisplay (pProcArg->pDisplay);
1069
pthread_exit (NULL);
1075
* winInitWM - Entry point for the X server to spawn
1076
* the Window Manager thread. Called from
1077
* winscrinit.c/winFinishScreenInitFB ().
1081
winInitWM (void **ppWMInfo,
1082
pthread_t *ptWMProc,
1083
pthread_t *ptXMsgProc,
1084
pthread_mutex_t *ppmServerStarted,
1089
WMProcArgPtr pArg = (WMProcArgPtr) malloc (sizeof(WMProcArgRec));
1090
WMInfoPtr pWMInfo = (WMInfoPtr) malloc (sizeof(WMInfoRec));
1091
XMsgProcArgPtr pXMsgArg = (XMsgProcArgPtr) malloc (sizeof(XMsgProcArgRec));
1093
/* Bail if the input parameters are bad */
1094
if (pArg == NULL || pWMInfo == NULL)
1096
ErrorF ("winInitWM - malloc failed.\n");
1100
/* Zero the allocated memory */
1101
ZeroMemory (pArg, sizeof (WMProcArgRec));
1102
ZeroMemory (pWMInfo, sizeof (WMInfoRec));
1103
ZeroMemory (pXMsgArg, sizeof (XMsgProcArgRec));
1105
/* Set a return pointer to the Window Manager info structure */
1106
*ppWMInfo = pWMInfo;
1107
pWMInfo->fAllowOtherWM = allowOtherWM;
1109
/* Setup the argument structure for the thread function */
1110
pArg->dwScreen = dwScreen;
1111
pArg->pWMInfo = pWMInfo;
1112
pArg->ppmServerStarted = ppmServerStarted;
1114
/* Intialize the message queue */
1115
if (!InitQueue (&pWMInfo->wmMsgQueue))
1117
ErrorF ("winInitWM - InitQueue () failed.\n");
1121
/* Spawn a thread for the Window Manager */
1122
if (pthread_create (ptWMProc, NULL, winMultiWindowWMProc, pArg))
1124
/* Bail if thread creation failed */
1125
ErrorF ("winInitWM - pthread_create failed for Window Manager.\n");
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))
1136
/* Bail if thread creation failed */
1137
ErrorF ("winInitWM - pthread_create failed on XMSG.\n");
1142
winDebug ("winInitWM - Returning.\n");
1150
* Window manager thread - setup
1154
winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
1157
char pszDisplay[512];
1160
ErrorF ("winInitMultiWindowWM - Hello\n");
1162
/* Check that argument pointer is not invalid */
1163
if (pProcArg == NULL)
1165
ErrorF ("winInitMultiWindowWM - pProcArg is NULL. Exiting.\n");
1166
pthread_exit (NULL);
1169
ErrorF ("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n");
1171
/* Grab our garbage mutex to satisfy pthread_cond_wait */
1172
iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted);
1175
ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () failed: %d. "
1178
pthread_exit (NULL);
1181
ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () returned.\n");
1183
/* Allow multiple threads to access Xlib */
1184
if (XInitThreads () == 0)
1186
ErrorF ("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n");
1187
pthread_exit (NULL);
1190
/* See if X supports the current locale */
1191
if (XSupportsLocale () == False)
1193
ErrorF ("winInitMultiWindowWM - Locale not supported by X. Exiting.\n");
1194
pthread_exit (NULL);
1197
/* Release the server started mutex */
1198
pthread_mutex_unlock (pProcArg->ppmServerStarted);
1200
ErrorF ("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
1202
/* Set jump point for IO Error exits */
1203
iReturn = setjmp (g_jmpWMEntry);
1205
/* Check if we should continue operations */
1206
if (iReturn != WIN_JMP_ERROR_IO
1207
&& iReturn != WIN_JMP_OKAY)
1209
/* setjmp returned an unknown value, exit */
1210
ErrorF ("winInitMultiWindowWM - setjmp returned: %d. Exiting.\n",
1212
pthread_exit (NULL);
1214
else if (iReturn == WIN_JMP_ERROR_IO)
1216
ErrorF ("winInitMultiWindowWM - Caught IO Error. Exiting.\n");
1217
pthread_exit (NULL);
1220
/* Install our error handler */
1221
XSetErrorHandler (winMultiWindowWMErrorHandler);
1222
XSetIOErrorHandler (winMultiWindowWMIOErrorHandler);
1224
/* Setup the display connection string x */
1225
snprintf (pszDisplay,
1229
(int) pProcArg->dwScreen);
1231
/* Print the display connection string */
1232
ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay);
1234
/* Open the X display */
1237
/* Try to open the display */
1238
pWMInfo->pDisplay = XOpenDisplay (pszDisplay);
1239
if (pWMInfo->pDisplay == NULL)
1241
ErrorF ("winInitMultiWindowWM - Could not open display, try: %d, "
1243
iRetries + 1, WIN_CONNECT_DELAY);
1245
sleep (WIN_CONNECT_DELAY);
1251
while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
1253
/* Make sure that the display opened */
1254
if (pWMInfo->pDisplay == NULL)
1256
ErrorF ("winInitMultiWindowWM - Failed opening the display. "
1258
pthread_exit (NULL);
1261
ErrorF ("winInitMultiWindowWM - XOpenDisplay () returned and "
1262
"successfully opened the display.\n");
1265
/* Create some atoms */
1266
pWMInfo->atmWmProtos = XInternAtom (pWMInfo->pDisplay,
1269
pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay,
1272
#ifdef XWIN_MULTIWINDOWEXTWM
1273
pWMInfo->atmPrivMap = XInternAtom (pWMInfo->pDisplay,
1274
WINDOWSWM_NATIVE_HWND,
1280
Cursor cursor = XCreateFontCursor (pWMInfo->pDisplay, XC_left_ptr);
1283
XDefineCursor (pWMInfo->pDisplay, DefaultRootWindow(pWMInfo->pDisplay), cursor);
1284
XFreeCursor (pWMInfo->pDisplay, cursor);
1291
* winSendMessageToWM - Send a message from the X thread to the WM thread
1295
winSendMessageToWM (void *pWMInfo, winWMMessagePtr pMsg)
1299
#if CYGMULTIWINDOW_DEBUG
1300
ErrorF ("winSendMessageToWM ()\n");
1303
pNode = (WMMsgNodePtr)malloc(sizeof(WMMsgNodeRec));
1306
memcpy (&pNode->msg, pMsg, sizeof(winWMMessageRec));
1307
PushMessage (&((WMInfoPtr)pWMInfo)->wmMsgQueue, pNode);
1313
* Window manager error handler
1317
winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr)
1319
char pszErrorMsg[100];
1321
if (pErr->request_code == X_ChangeWindowAttributes
1322
&& pErr->error_code == BadAccess)
1324
ErrorF ("winMultiWindowWMErrorHandler - ChangeWindowAttributes "
1329
XGetErrorText (pDisplay,
1332
sizeof (pszErrorMsg));
1333
ErrorF ("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg);
1340
* Window manager IO error handler
1344
winMultiWindowWMIOErrorHandler (Display *pDisplay)
1346
ErrorF ("\nwinMultiWindowWMIOErrorHandler!\n\n");
1351
/* Restart at the main entry point */
1352
longjmp (g_jmpWMEntry, WIN_JMP_ERROR_IO);
1359
* X message procedure error handler
1363
winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr)
1365
char pszErrorMsg[100];
1367
XGetErrorText (pDisplay,
1370
sizeof (pszErrorMsg));
1371
ErrorF ("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg);
1378
* X message procedure IO error handler
1382
winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay)
1384
ErrorF ("\nwinMultiWindowXMsgProcIOErrorHandler!\n\n");
1386
/* Restart at the main entry point */
1387
longjmp (g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO);
1394
* Catch RedirectError to detect other window manager running
1398
winRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr)
1400
redirectError = TRUE;
1406
* Check if another window manager is running
1410
CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen)
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);
1426
//ErrorF ("CheckAnotherWindowManager() - another window manager is running. Exiting.\n");
1436
* Notify the MWM thread we're exiting and not to reconnect
1440
winDeinitMultiWindowWM ()
1442
ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n");