2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *Copyright (C) Colin Harrison 2005-2009
5 *Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 *"Software"), to deal in the Software without restriction, including
8 *without limitation the rights to use, copy, modify, merge, publish,
9 *distribute, sublicense, and/or sell copies of the Software, and to
10 *permit persons to whom the Software is furnished to do so, subject to
11 *the following conditions:
13 *The above copyright notice and this permission notice shall be
14 *included in all copies or substantial portions of the Software.
16 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *Except as contained in this notice, the name of the XFree86 Project
25 *shall not be used in advertising or otherwise to promote the sale, use
26 *or other dealings in this Software without prior written authorization
27 *from the XFree86 Project.
29 * Authors: Kensuke Matsuzaki
34 #ifdef HAVE_XWIN_CONFIG_H
35 #include <xwin-config.h>
41 #include <sys/select.h>
49 #include <X11/Xatom.h>
51 #include <X11/Xlocale.h>
52 #include <X11/Xproto.h>
53 #include <X11/Xutil.h>
54 #include <X11/cursorfont.h>
55 #include <X11/Xwindows.h>
60 #include "winwindow.h"
63 #include "pixmapstr.h"
64 #include "windowstr.h"
66 #ifdef XWIN_MULTIWINDOWEXTWM
67 #include <X11/extensions/windowswmstr.h>
69 /* We need the native HWND atom for intWM, so for consistency use the
70 same name as extWM would if we were building with enabled... */
71 #define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
74 extern void winDebug(const char *format, ...);
75 extern void winReshapeMultiWindow(WindowPtr pWin);
76 extern void winUpdateRgnMultiWindow(WindowPtr pWin);
86 #define WIN_CONNECT_RETRIES 5
87 #define WIN_CONNECT_DELAY 5
89 #define WIN_MSG_QUEUE_FNAME "/dev/windows"
91 #define WIN_JMP_OKAY 0
92 #define WIN_JMP_ERROR_IO 2
98 typedef struct _WMMsgNodeRec {
100 struct _WMMsgNodeRec *pNext;
101 } WMMsgNodeRec, *WMMsgNodePtr;
103 typedef struct _WMMsgQueueRec {
104 struct _WMMsgNodeRec *pHead;
105 struct _WMMsgNodeRec *pTail;
106 pthread_mutex_t pmMutex;
107 pthread_cond_t pcNotEmpty;
109 } WMMsgQueueRec, *WMMsgQueuePtr;
111 typedef struct _WMInfo {
113 WMMsgQueueRec wmMsgQueue;
118 } WMInfoRec, *WMInfoPtr;
120 typedef struct _WMProcArgRec {
123 pthread_mutex_t *ppmServerStarted;
124 } WMProcArgRec, *WMProcArgPtr;
126 typedef struct _XMsgProcArgRec {
130 pthread_mutex_t *ppmServerStarted;
132 } XMsgProcArgRec, *XMsgProcArgPtr;
135 * References to external symbols
138 extern char *display;
139 extern void ErrorF(const char * /*f */ , ...);
142 * Prototypes for local functions
146 PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode);
148 static WMMsgNodePtr PopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo);
151 InitQueue(WMMsgQueuePtr pQueue);
154 GetWindowName(Display * pDpy, Window iWin, char **ppWindowName);
157 SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData);
160 UpdateName(WMInfoPtr pWMInfo, Window iWindow);
162 static void *winMultiWindowWMProc(void *pArg);
165 winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr);
168 winMultiWindowWMIOErrorHandler(Display * pDisplay);
170 static void *winMultiWindowXMsgProc(void *pArg);
173 winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr);
176 winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay);
179 winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr);
182 winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg);
186 PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction);
191 CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
195 winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle);
198 winUpdateWindowPosition(HWND hWnd, Bool reshape, HWND * zstyle);
204 static jmp_buf g_jmpWMEntry;
205 static XIOErrorHandler g_winMultiWindowWMOldIOErrorHandler;
206 static pthread_t g_winMultiWindowWMThread;
207 static jmp_buf g_jmpXMsgProcEntry;
208 static XIOErrorHandler g_winMultiWindowXMsgProcOldIOErrorHandler;
209 static pthread_t g_winMultiWindowXMsgProcThread;
210 static Bool g_shutdown = FALSE;
211 static Bool redirectError = FALSE;
212 static Bool g_fAnotherWMRunning = FALSE;
215 * PushMessage - Push a message onto the queue
219 PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
222 /* Lock the queue mutex */
223 pthread_mutex_lock(&pQueue->pmMutex);
227 if (pQueue->pTail != NULL) {
228 pQueue->pTail->pNext = pNode;
230 pQueue->pTail = pNode;
232 if (pQueue->pHead == NULL) {
233 pQueue->pHead = pNode;
237 switch (pNode->msg.msg) {
239 ErrorF("\tWM_WM_MOVE\n");
242 ErrorF("\tWM_WM_SIZE\n");
245 ErrorF("\tWM_WM_RAISE\n");
248 ErrorF("\tWM_WM_LOWER\n");
251 ErrorF("\tWM_WM_MAP\n");
254 ErrorF("\tWM_WM_MAP2\n");
257 ErrorF("\tWM_WM_MAP3\n");
260 ErrorF("\tWM_WM_UNMAP\n");
263 ErrorF("\tWM_WM_KILL\n");
266 ErrorF("\tWM_WM_ACTIVATE\n");
269 ErrorF("\tUnknown Message.\n");
274 /* Increase the count of elements in the queue by one */
275 ++(pQueue->nQueueSize);
277 /* Release the queue mutex */
278 pthread_mutex_unlock(&pQueue->pmMutex);
280 /* Signal that the queue is not empty */
281 pthread_cond_signal(&pQueue->pcNotEmpty);
284 #if CYGMULTIWINDOW_DEBUG
286 * QueueSize - Return the size of the queue
290 QueueSize(WMMsgQueuePtr pQueue)
295 /* Loop through all elements in the queue */
296 for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext)
304 * PopMessage - Pop a message from the queue
308 PopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo)
312 /* Lock the queue mutex */
313 pthread_mutex_lock(&pQueue->pmMutex);
316 while (pQueue->pHead == NULL) {
317 pthread_cond_wait(&pQueue->pcNotEmpty, &pQueue->pmMutex);
320 pNode = pQueue->pHead;
321 if (pQueue->pHead != NULL) {
322 pQueue->pHead = pQueue->pHead->pNext;
325 if (pQueue->pTail == pNode) {
326 pQueue->pTail = NULL;
329 /* Drop the number of elements in the queue by one */
330 --(pQueue->nQueueSize);
332 #if CYGMULTIWINDOW_DEBUG
333 ErrorF("Queue Size %d %d\n", pQueue->nQueueSize, QueueSize(pQueue));
336 /* Release the queue mutex */
337 pthread_mutex_unlock(&pQueue->pmMutex);
348 HaveMessage(WMMsgQueuePtr pQueue, UINT msg, Window iWindow)
352 for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) {
353 if (pNode->msg.msg == msg && pNode->msg.iWindow == iWindow)
362 * InitQueue - Initialize the Window Manager message queue
367 InitQueue(WMMsgQueuePtr pQueue)
369 /* Check if the pQueue pointer is NULL */
370 if (pQueue == NULL) {
371 ErrorF("InitQueue - pQueue is NULL. Exiting.\n");
375 /* Set the head and tail to NULL */
376 pQueue->pHead = NULL;
377 pQueue->pTail = NULL;
379 /* There are no elements initially */
380 pQueue->nQueueSize = 0;
382 #if CYGMULTIWINDOW_DEBUG
383 winDebug("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize,
387 winDebug("InitQueue - Calling pthread_mutex_init\n");
389 /* Create synchronization objects */
390 pthread_mutex_init(&pQueue->pmMutex, NULL);
392 winDebug("InitQueue - pthread_mutex_init returned\n");
393 winDebug("InitQueue - Calling pthread_cond_init\n");
395 pthread_cond_init(&pQueue->pcNotEmpty, NULL);
397 winDebug("InitQueue - pthread_cond_init returned\n");
404 Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp)
410 if (Xutf8TextPropertyToTextList(pDisplay, xtp, &ppList, &nNum) >= Success &&
411 nNum > 0 && *ppList) {
415 for (i = 0; i < nNum; i++)
416 iLen += strlen(ppList[i]);
417 pszReturnData = (char *) malloc(iLen + 1);
418 pszReturnData[0] = '\0';
419 for (i = 0; i < nNum; i++)
420 strcat(pszReturnData, ppList[i]);
422 XFreeStringList(ppList);
425 pszReturnData = (char *) malloc(1);
426 pszReturnData[0] = '\0';
429 return pszReturnData;
433 * GetWindowName - Retrieve the title of an X Window
437 GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
440 XTextProperty xtpWindowName;
443 #if CYGMULTIWINDOW_DEBUG
444 ErrorF("GetWindowName\n");
447 /* Intialize ppWindowName to NULL */
448 *ppWindowName = NULL;
450 /* Try to get window name */
451 nResult = XGetWMName(pDisplay, iWin, &xtpWindowName);
452 if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) {
453 #if CYGMULTIWINDOW_DEBUG
454 ErrorF("GetWindowName - XGetWMName failed. No name.\n");
459 pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName);
460 XFree(xtpWindowName.value);
461 *ppWindowName = pszWindowName;
465 * Send a message to the X server from the WM thread
469 SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData)
473 /* Prepare the X event structure */
474 e.type = ClientMessage;
475 e.xclient.window = iWin;
476 e.xclient.message_type = atmType;
477 e.xclient.format = 32;
478 e.xclient.data.l[0] = nData;
479 e.xclient.data.l[1] = CurrentTime;
481 /* Send the event to X */
482 return XSendEvent(pDisplay, iWin, False, NoEventMask, &e);
486 * See if we can get the stored HWND for this window...
489 getHwnd(WMInfoPtr pWMInfo, Window iWindow)
493 unsigned long items, remain;
494 HWND *retHwnd, hWnd = NULL;
496 if (XGetWindowProperty(pWMInfo->pDisplay,
506 &remain, (unsigned char **) &retHwnd) == Success) {
513 /* Some sanity checks */
523 * Updates the name of a HWND according to its X WM_NAME property
527 UpdateName(WMInfoPtr pWMInfo, Window iWindow)
531 XWindowAttributes attr;
533 hWnd = getHwnd(pWMInfo, iWindow);
537 /* If window isn't override-redirect */
538 XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
539 if (!attr.override_redirect) {
542 /* Get the X windows window name */
543 GetWindowName(pWMInfo->pDisplay, iWindow, &pszWindowName);
546 /* Convert from UTF-8 to wide char */
548 MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, NULL, 0);
549 wchar_t *pwszWideWindowName =
550 (wchar_t *) malloc(sizeof(wchar_t) * (iLen + 1));
551 MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1,
552 pwszWideWindowName, iLen);
554 /* Set the Windows window name */
555 SetWindowTextW(hWnd, pwszWideWindowName);
557 free(pwszWideWindowName);
564 * Updates the icon of a HWND according to its X icon properties
568 UpdateIcon(WMInfoPtr pWMInfo, Window iWindow)
571 HICON hIconNew = NULL;
572 XWindowAttributes attr;
574 hWnd = getHwnd(pWMInfo, iWindow);
578 /* If window isn't override-redirect */
579 XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
580 if (!attr.override_redirect) {
581 XClassHint class_hint = { 0, 0 };
582 char *window_name = 0;
584 if (XGetClassHint(pWMInfo->pDisplay, iWindow, &class_hint)) {
585 XFetchName(pWMInfo->pDisplay, iWindow, &window_name);
588 (HICON) winOverrideIcon(class_hint.res_name,
589 class_hint.res_class, window_name);
591 if (class_hint.res_name)
592 XFree(class_hint.res_name);
593 if (class_hint.res_class)
594 XFree(class_hint.res_class);
600 winUpdateIcon(hWnd, pWMInfo->pDisplay, iWindow, hIconNew);
605 * Fix up any differences between the X11 and Win32 window stacks
606 * starting at the window passed in
609 PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction)
612 DWORD myWinProcID, winProcID;
614 WINDOWPLACEMENT wndPlace;
616 hWnd = getHwnd(pWMInfo, iWindow);
620 GetWindowThreadProcessId(hWnd, &myWinProcID);
621 hWnd = GetNextWindow(hWnd, direction);
624 GetWindowThreadProcessId(hWnd, &winProcID);
625 if (winProcID == myWinProcID) {
626 wndPlace.length = sizeof(WINDOWPLACEMENT);
627 GetWindowPlacement(hWnd, &wndPlace);
628 if (!(wndPlace.showCmd == SW_HIDE ||
629 wndPlace.showCmd == SW_MINIMIZE)) {
630 xWindow = (Window) GetProp(hWnd, WIN_WID_PROP);
632 if (direction == GW_HWNDPREV)
633 XRaiseWindow(pWMInfo->pDisplay, xWindow);
635 XLowerWindow(pWMInfo->pDisplay, xWindow);
639 hWnd = GetNextWindow(hWnd, direction);
642 #endif /* PreserveWin32Stack */
645 * winMultiWindowWMProc
649 winMultiWindowWMProc(void *pArg)
651 WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
652 WMInfoPtr pWMInfo = pProcArg->pWMInfo;
654 /* Initialize the Window Manager */
655 winInitMultiWindowWM(pWMInfo, pProcArg);
657 #if CYGMULTIWINDOW_DEBUG
658 ErrorF("winMultiWindowWMProc ()\n");
661 /* Loop until we explicitly break out */
665 if (g_fAnotherWMRunning) { /* Another Window manager exists. */
670 /* Pop a message off of our queue */
671 pNode = PopMessage(&pWMInfo->wmMsgQueue, pWMInfo);
673 /* Bail if PopMessage returns without a message */
674 /* NOTE: Remember that PopMessage is a blocking function. */
675 ErrorF("winMultiWindowWMProc - Queue is Empty? Exiting.\n");
679 #if CYGMULTIWINDOW_DEBUG
680 ErrorF("winMultiWindowWMProc - %d ms MSG: %d ID: %d\n",
681 GetTickCount(), (int) pNode->msg.msg, (int) pNode->msg.dwID);
684 /* Branch on the message type */
685 switch (pNode->msg.msg) {
688 ErrorF("\tWM_WM_MOVE\n");
692 ErrorF("\tWM_WM_SIZE\n");
697 #if CYGMULTIWINDOW_DEBUG
698 ErrorF("\tWM_WM_RAISE\n");
700 /* Raise the window */
701 XRaiseWindow(pWMInfo->pDisplay, pNode->msg.iWindow);
703 PreserveWin32Stack(pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
708 #if CYGMULTIWINDOW_DEBUG
709 ErrorF("\tWM_WM_LOWER\n");
712 /* Lower the window */
713 XLowerWindow(pWMInfo->pDisplay, pNode->msg.iWindow);
717 #if CYGMULTIWINDOW_DEBUG
718 ErrorF("\tWM_WM_MAP\n");
720 /* Put a note as to the HWND associated with this Window */
721 XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, //pWMInfo->atmPrivMap,
724 (unsigned char *) &(pNode->msg.hwndWindow), 1);
725 UpdateName(pWMInfo, pNode->msg.iWindow);
726 UpdateIcon(pWMInfo, pNode->msg.iWindow);
730 #if CYGMULTIWINDOW_DEBUG
731 ErrorF("\tWM_WM_MAP2\n");
733 XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, //pWMInfo->atmPrivMap,
736 (unsigned char *) &(pNode->msg.hwndWindow), 1);
740 #if CYGMULTIWINDOW_DEBUG
741 ErrorF("\tWM_WM_MAP3\n");
743 /* Put a note as to the HWND associated with this Window */
744 XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, //pWMInfo->atmPrivMap,
747 (unsigned char *) &(pNode->msg.hwndWindow), 1);
748 UpdateName(pWMInfo, pNode->msg.iWindow);
749 UpdateIcon(pWMInfo, pNode->msg.iWindow);
751 HWND zstyle = HWND_NOTOPMOST;
753 winApplyHints(pWMInfo->pDisplay, pNode->msg.iWindow,
754 pNode->msg.hwndWindow, &zstyle);
755 winUpdateWindowPosition(pNode->msg.hwndWindow, TRUE, &zstyle);
760 #if CYGMULTIWINDOW_DEBUG
761 ErrorF("\tWM_WM_UNMAP\n");
764 /* Unmap the window */
765 XUnmapWindow(pWMInfo->pDisplay, pNode->msg.iWindow);
769 #if CYGMULTIWINDOW_DEBUG
770 ErrorF("\tWM_WM_KILL\n");
777 if (XGetWMProtocols(pWMInfo->pDisplay,
778 pNode->msg.iWindow, &protocols, &n)) {
779 for (i = 0; i < n; ++i)
780 if (protocols[i] == pWMInfo->atmWmDelete)
788 SendXMessage(pWMInfo->pDisplay,
790 pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
792 XKillClient(pWMInfo->pDisplay, pNode->msg.iWindow);
797 #if CYGMULTIWINDOW_DEBUG
798 ErrorF("\tWM_WM_ACTIVATE\n");
801 /* Set the input focus */
802 XSetInputFocus(pWMInfo->pDisplay,
804 RevertToPointerRoot, CurrentTime);
807 case WM_WM_NAME_EVENT:
808 UpdateName(pWMInfo, pNode->msg.iWindow);
811 case WM_WM_ICON_EVENT:
812 UpdateIcon(pWMInfo, pNode->msg.iWindow);
815 case WM_WM_CHANGE_STATE:
816 /* Minimize the window in Windows */
817 winMinimizeWindow(pNode->msg.iWindow);
821 ErrorF("winMultiWindowWMProc - Unknown Message. Exiting.\n");
826 /* Free the retrieved message */
829 /* Flush any pending events on our display */
830 XFlush(pWMInfo->pDisplay);
833 /* Free the condition variable */
834 pthread_cond_destroy(&pWMInfo->wmMsgQueue.pcNotEmpty);
836 /* Free the mutex variable */
837 pthread_mutex_destroy(&pWMInfo->wmMsgQueue.pmMutex);
839 /* Free the passed-in argument */
842 #if CYGMULTIWINDOW_DEBUG
843 ErrorF("-winMultiWindowWMProc ()\n");
849 * X message procedure
853 winMultiWindowXMsgProc(void *pArg)
856 XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg;
857 char pszDisplay[512];
867 winDebug("winMultiWindowXMsgProc - Hello\n");
869 /* Check that argument pointer is not invalid */
870 if (pProcArg == NULL) {
871 ErrorF("winMultiWindowXMsgProc - pProcArg is NULL. Exiting.\n");
875 ErrorF("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n");
877 /* Grab the server started mutex - pause until we get it */
878 iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted);
880 ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d. "
881 "Exiting.\n", iReturn);
885 ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n");
887 /* Allow multiple threads to access Xlib */
888 if (XInitThreads() == 0) {
889 ErrorF("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n");
893 /* See if X supports the current locale */
894 if (XSupportsLocale() == False) {
895 ErrorF("winMultiWindowXMsgProc - Warning: locale not supported by X\n");
898 /* Release the server started mutex */
899 pthread_mutex_unlock(pProcArg->ppmServerStarted);
901 ErrorF("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
903 /* Install our error handler */
904 XSetErrorHandler(winMultiWindowXMsgProcErrorHandler);
905 g_winMultiWindowXMsgProcThread = pthread_self();
906 g_winMultiWindowXMsgProcOldIOErrorHandler =
907 XSetIOErrorHandler(winMultiWindowXMsgProcIOErrorHandler);
909 /* Set jump point for IO Error exits */
910 iReturn = setjmp(g_jmpXMsgProcEntry);
912 /* Check if we should continue operations */
913 if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
914 /* setjmp returned an unknown value, exit */
915 ErrorF("winInitMultiWindowXMsgProc - setjmp returned: %d. Exiting.\n",
919 else if (iReturn == WIN_JMP_ERROR_IO) {
920 ErrorF("winInitMultiWindowXMsgProc - Caught IO Error. Exiting.\n");
924 /* Setup the display connection string x */
926 512, "127.0.0.1:%s.%d", display, (int) pProcArg->dwScreen);
928 /* Print the display connection string */
929 ErrorF("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay);
931 /* Use our generated cookie for authentication */
932 winSetAuthorization();
934 /* Initialize retry count */
937 /* Open the X display */
939 /* Try to open the display */
940 pProcArg->pDisplay = XOpenDisplay(pszDisplay);
941 if (pProcArg->pDisplay == NULL) {
942 ErrorF("winMultiWindowXMsgProc - Could not open display, try: %d, "
943 "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
945 sleep(WIN_CONNECT_DELAY);
951 while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
953 /* Make sure that the display opened */
954 if (pProcArg->pDisplay == NULL) {
955 ErrorF("winMultiWindowXMsgProc - Failed opening the display. "
960 ErrorF("winMultiWindowXMsgProc - XOpenDisplay () returned and "
961 "successfully opened the display.\n");
963 /* Check if another window manager is already running */
964 g_fAnotherWMRunning =
965 CheckAnotherWindowManager(pProcArg->pDisplay, pProcArg->dwScreen,
966 pProcArg->pWMInfo->fAllowOtherWM);
968 if (g_fAnotherWMRunning && !pProcArg->pWMInfo->fAllowOtherWM) {
969 ErrorF("winMultiWindowXMsgProc - "
970 "another window manager is running. Exiting.\n");
974 /* Set up the supported icon sizes */
975 xis = XAllocIconSize();
977 xis->min_width = xis->min_height = 16;
978 xis->max_width = xis->max_height = 48;
979 xis->width_inc = xis->height_inc = 16;
980 XSetIconSizes(pProcArg->pDisplay,
981 RootWindow(pProcArg->pDisplay, pProcArg->dwScreen),
986 atmWmName = XInternAtom(pProcArg->pDisplay, "WM_NAME", False);
987 atmWmHints = XInternAtom(pProcArg->pDisplay, "WM_HINTS", False);
988 atmWmChange = XInternAtom(pProcArg->pDisplay, "WM_CHANGE_STATE", False);
989 atmNetWmIcon = XInternAtom(pProcArg->pDisplay, "_NET_WM_ICON", False);
992 iiimxcf had a bug until 2009-04-27, assuming that the
993 WM_STATE atom exists, causing clients to fail with
994 a BadAtom X error if it doesn't.
996 Since this is on in the default Solaris 10 install,
997 workaround this by making sure it does exist...
999 XInternAtom(pProcArg->pDisplay, "WM_STATE", 0);
1001 /* Loop until we explicitly break out */
1006 if (pProcArg->pWMInfo->fAllowOtherWM && !XPending(pProcArg->pDisplay)) {
1007 if (CheckAnotherWindowManager
1008 (pProcArg->pDisplay, pProcArg->dwScreen, TRUE)) {
1009 if (!g_fAnotherWMRunning) {
1010 g_fAnotherWMRunning = TRUE;
1011 SendMessage(*(HWND *) pProcArg->hwndScreen, WM_UNMANAGE, 0,
1016 if (g_fAnotherWMRunning) {
1017 g_fAnotherWMRunning = FALSE;
1018 SendMessage(*(HWND *) pProcArg->hwndScreen, WM_MANAGE, 0,
1026 /* Fetch next event */
1027 XNextEvent(pProcArg->pDisplay, &event);
1029 /* Branch on event type */
1030 if (event.type == CreateNotify) {
1031 XWindowAttributes attr;
1033 XSelectInput(pProcArg->pDisplay,
1034 event.xcreatewindow.window, PropertyChangeMask);
1036 /* Get the window attributes */
1037 XGetWindowAttributes(pProcArg->pDisplay,
1038 event.xcreatewindow.window, &attr);
1040 if (!attr.override_redirect)
1041 XSetWindowBorderWidth(pProcArg->pDisplay,
1042 event.xcreatewindow.window, 0);
1044 else if (event.type == MapNotify) {
1045 /* Fake a reparentNotify event as SWT/Motif expects a
1046 Window Manager to reparent a top-level window when
1047 it is mapped and waits until they do.
1049 We don't actually need to reparent, as the frame is
1050 a native window, not an X window
1052 We do this on MapNotify, not MapRequest like a real
1053 Window Manager would, so we don't have do get involved
1054 in actually mapping the window via it's (non-existent)
1057 See sourceware bugzilla #9848
1060 XWindowAttributes attr;
1064 unsigned int nchildren;
1066 if (XGetWindowAttributes(event.xmap.display,
1069 XQueryTree(event.xmap.display,
1071 &root, &parent, &children, &nchildren)) {
1076 It's a top-level window if the parent window is a root window
1077 Only non-override_redirect windows can get reparented
1079 if ((attr.root == parent) && !event.xmap.override_redirect) {
1082 event_send.type = ReparentNotify;
1083 event_send.xreparent.event = event.xmap.window;
1084 event_send.xreparent.window = event.xmap.window;
1085 event_send.xreparent.parent = parent;
1086 event_send.xreparent.x = attr.x;
1087 event_send.xreparent.y = attr.y;
1089 XSendEvent(event.xmap.display,
1091 True, StructureNotifyMask, &event_send);
1095 else if (event.type == ConfigureNotify) {
1096 if (!event.xconfigure.send_event) {
1098 Java applications using AWT on JRE 1.6.0 break with non-reparenting WMs AWT
1099 doesn't explicitly know about (See sun bug #6434227)
1101 XDecoratedPeer.handleConfigureNotifyEvent() only processes non-synthetic
1102 ConfigureNotify events to update window location if it's identified the
1103 WM as a non-reparenting WM it knows about (compiz or lookingglass)
1105 Rather than tell all sorts of lies to get XWM to recognize us as one of
1106 those, simply send a synthetic ConfigureNotify for every non-synthetic one
1108 XEvent event_send = event;
1110 event_send.xconfigure.send_event = TRUE;
1111 event_send.xconfigure.event = event.xconfigure.window;
1112 XSendEvent(event.xconfigure.display,
1113 event.xconfigure.window,
1114 True, StructureNotifyMask, &event_send);
1117 else if (event.type == PropertyNotify) {
1118 if (event.xproperty.atom == atmWmName) {
1119 memset(&msg, 0, sizeof(msg));
1121 msg.msg = WM_WM_NAME_EVENT;
1122 msg.iWindow = event.xproperty.window;
1124 /* Other fields ignored */
1125 winSendMessageToWM(pProcArg->pWMInfo, &msg);
1127 else if ((event.xproperty.atom == atmWmHints) ||
1128 (event.xproperty.atom == atmNetWmIcon)) {
1129 memset(&msg, 0, sizeof(msg));
1130 msg.msg = WM_WM_ICON_EVENT;
1131 msg.iWindow = event.xproperty.window;
1133 /* Other fields ignored */
1134 winSendMessageToWM(pProcArg->pWMInfo, &msg);
1137 else if (event.type == ClientMessage
1138 && event.xclient.message_type == atmWmChange
1139 && event.xclient.data.l[0] == IconicState) {
1140 ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
1142 memset(&msg, 0, sizeof(msg));
1144 msg.msg = WM_WM_CHANGE_STATE;
1145 msg.iWindow = event.xclient.window;
1147 winSendMessageToWM(pProcArg->pWMInfo, &msg);
1151 XCloseDisplay(pProcArg->pDisplay);
1157 * winInitWM - Entry point for the X server to spawn
1158 * the Window Manager thread. Called from
1159 * winscrinit.c/winFinishScreenInitFB ().
1163 winInitWM(void **ppWMInfo,
1164 pthread_t * ptWMProc,
1165 pthread_t * ptXMsgProc,
1166 pthread_mutex_t * ppmServerStarted,
1167 int dwScreen, HWND hwndScreen, BOOL allowOtherWM)
1169 WMProcArgPtr pArg = (WMProcArgPtr) malloc(sizeof(WMProcArgRec));
1170 WMInfoPtr pWMInfo = (WMInfoPtr) malloc(sizeof(WMInfoRec));
1171 XMsgProcArgPtr pXMsgArg = (XMsgProcArgPtr) malloc(sizeof(XMsgProcArgRec));
1173 /* Bail if the input parameters are bad */
1174 if (pArg == NULL || pWMInfo == NULL || pXMsgArg == NULL) {
1175 ErrorF("winInitWM - malloc failed.\n");
1182 /* Zero the allocated memory */
1183 ZeroMemory(pArg, sizeof(WMProcArgRec));
1184 ZeroMemory(pWMInfo, sizeof(WMInfoRec));
1185 ZeroMemory(pXMsgArg, sizeof(XMsgProcArgRec));
1187 /* Set a return pointer to the Window Manager info structure */
1188 *ppWMInfo = pWMInfo;
1189 pWMInfo->fAllowOtherWM = allowOtherWM;
1191 /* Setup the argument structure for the thread function */
1192 pArg->dwScreen = dwScreen;
1193 pArg->pWMInfo = pWMInfo;
1194 pArg->ppmServerStarted = ppmServerStarted;
1196 /* Intialize the message queue */
1197 if (!InitQueue(&pWMInfo->wmMsgQueue)) {
1198 ErrorF("winInitWM - InitQueue () failed.\n");
1202 /* Spawn a thread for the Window Manager */
1203 if (pthread_create(ptWMProc, NULL, winMultiWindowWMProc, pArg)) {
1204 /* Bail if thread creation failed */
1205 ErrorF("winInitWM - pthread_create failed for Window Manager.\n");
1209 /* Spawn the XNextEvent thread, will send messages to WM */
1210 pXMsgArg->dwScreen = dwScreen;
1211 pXMsgArg->pWMInfo = pWMInfo;
1212 pXMsgArg->ppmServerStarted = ppmServerStarted;
1213 pXMsgArg->hwndScreen = hwndScreen;
1214 if (pthread_create(ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg)) {
1215 /* Bail if thread creation failed */
1216 ErrorF("winInitWM - pthread_create failed on XMSG.\n");
1221 winDebug("winInitWM - Returning.\n");
1228 * Window manager thread - setup
1232 winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
1235 char pszDisplay[512];
1238 winDebug("winInitMultiWindowWM - Hello\n");
1240 /* Check that argument pointer is not invalid */
1241 if (pProcArg == NULL) {
1242 ErrorF("winInitMultiWindowWM - pProcArg is NULL. Exiting.\n");
1246 ErrorF("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n");
1248 /* Grab our garbage mutex to satisfy pthread_cond_wait */
1249 iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted);
1251 ErrorF("winInitMultiWindowWM - pthread_mutex_lock () failed: %d. "
1252 "Exiting.\n", iReturn);
1256 ErrorF("winInitMultiWindowWM - pthread_mutex_lock () returned.\n");
1258 /* Allow multiple threads to access Xlib */
1259 if (XInitThreads() == 0) {
1260 ErrorF("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n");
1264 /* See if X supports the current locale */
1265 if (XSupportsLocale() == False) {
1266 ErrorF("winInitMultiWindowWM - Warning: Locale not supported by X.\n");
1269 /* Release the server started mutex */
1270 pthread_mutex_unlock(pProcArg->ppmServerStarted);
1272 ErrorF("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
1274 /* Install our error handler */
1275 XSetErrorHandler(winMultiWindowWMErrorHandler);
1276 g_winMultiWindowWMThread = pthread_self();
1277 g_winMultiWindowWMOldIOErrorHandler =
1278 XSetIOErrorHandler(winMultiWindowWMIOErrorHandler);
1280 /* Set jump point for IO Error exits */
1281 iReturn = setjmp(g_jmpWMEntry);
1283 /* Check if we should continue operations */
1284 if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
1285 /* setjmp returned an unknown value, exit */
1286 ErrorF("winInitMultiWindowWM - setjmp returned: %d. Exiting.\n",
1290 else if (iReturn == WIN_JMP_ERROR_IO) {
1291 ErrorF("winInitMultiWindowWM - Caught IO Error. Exiting.\n");
1295 /* Setup the display connection string x */
1296 snprintf(pszDisplay,
1297 512, "127.0.0.1:%s.%d", display, (int) pProcArg->dwScreen);
1299 /* Print the display connection string */
1300 ErrorF("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay);
1302 /* Use our generated cookie for authentication */
1303 winSetAuthorization();
1305 /* Open the X display */
1307 /* Try to open the display */
1308 pWMInfo->pDisplay = XOpenDisplay(pszDisplay);
1309 if (pWMInfo->pDisplay == NULL) {
1310 ErrorF("winInitMultiWindowWM - Could not open display, try: %d, "
1311 "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
1313 sleep(WIN_CONNECT_DELAY);
1319 while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
1321 /* Make sure that the display opened */
1322 if (pWMInfo->pDisplay == NULL) {
1323 ErrorF("winInitMultiWindowWM - Failed opening the display. "
1328 ErrorF("winInitMultiWindowWM - XOpenDisplay () returned and "
1329 "successfully opened the display.\n");
1331 /* Create some atoms */
1332 pWMInfo->atmWmProtos = XInternAtom(pWMInfo->pDisplay,
1333 "WM_PROTOCOLS", False);
1334 pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay,
1335 "WM_DELETE_WINDOW", False);
1337 pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay,
1338 WINDOWSWM_NATIVE_HWND, False);
1341 Cursor cursor = XCreateFontCursor(pWMInfo->pDisplay, XC_left_ptr);
1344 XDefineCursor(pWMInfo->pDisplay,
1345 DefaultRootWindow(pWMInfo->pDisplay), cursor);
1346 XFreeCursor(pWMInfo->pDisplay, cursor);
1352 * winSendMessageToWM - Send a message from the X thread to the WM thread
1356 winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
1360 #if CYGMULTIWINDOW_DEBUG
1361 ErrorF("winSendMessageToWM ()\n");
1364 pNode = (WMMsgNodePtr) malloc(sizeof(WMMsgNodeRec));
1365 if (pNode != NULL) {
1366 memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec));
1367 PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode);
1372 * Window manager error handler
1376 winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr)
1378 char pszErrorMsg[100];
1380 if (pErr->request_code == X_ChangeWindowAttributes
1381 && pErr->error_code == BadAccess) {
1382 ErrorF("winMultiWindowWMErrorHandler - ChangeWindowAttributes "
1387 XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
1388 ErrorF("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg);
1394 * Window manager IO error handler
1398 winMultiWindowWMIOErrorHandler(Display * pDisplay)
1400 ErrorF("winMultiWindowWMIOErrorHandler!\n\n");
1402 if (pthread_equal(pthread_self(), g_winMultiWindowWMThread)) {
1406 /* Restart at the main entry point */
1407 longjmp(g_jmpWMEntry, WIN_JMP_ERROR_IO);
1410 if (g_winMultiWindowWMOldIOErrorHandler)
1411 g_winMultiWindowWMOldIOErrorHandler(pDisplay);
1417 * X message procedure error handler
1421 winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr)
1423 char pszErrorMsg[100];
1425 XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
1426 #if CYGMULTIWINDOW_DEBUG
1427 ErrorF("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg);
1434 * X message procedure IO error handler
1438 winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay)
1440 ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n\n");
1442 if (pthread_equal(pthread_self(), g_winMultiWindowXMsgProcThread)) {
1443 /* Restart at the main entry point */
1444 longjmp(g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO);
1447 if (g_winMultiWindowXMsgProcOldIOErrorHandler)
1448 g_winMultiWindowXMsgProcOldIOErrorHandler(pDisplay);
1454 * Catch RedirectError to detect other window manager running
1458 winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr)
1460 redirectError = TRUE;
1465 * Check if another window manager is running
1469 CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
1473 Try to select the events which only one client at a time is allowed to select.
1474 If this causes an error, another window manager is already running...
1476 redirectError = FALSE;
1477 XSetErrorHandler(winRedirectErrorHandler);
1478 XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen),
1479 ResizeRedirectMask | SubstructureRedirectMask |
1482 XSetErrorHandler(winMultiWindowXMsgProcErrorHandler);
1485 Side effect: select the events we are actually interested in...
1487 If other WMs are not allowed, also select one of the events which only one client
1488 at a time is allowed to select, so other window managers won't start...
1490 XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen),
1491 SubstructureNotifyMask | (!fAllowOtherWM ? ButtonPressMask :
1494 return redirectError;
1498 * Notify the MWM thread we're exiting and not to reconnect
1502 winDeinitMultiWindowWM(void)
1504 ErrorF("winDeinitMultiWindowWM - Noting shutdown in progress\n");
1508 /* Windows window styles */
1509 #define HINT_NOFRAME (1l<<0)
1510 #define HINT_BORDER (1L<<1)
1511 #define HINT_SIZEBOX (1l<<2)
1512 #define HINT_CAPTION (1l<<3)
1513 #define HINT_NOMAXIMIZE (1L<<4)
1514 #define HINT_NOMINIMIZE (1L<<5)
1515 #define HINT_NOSYSMENU (1L<<6)
1516 /* These two are used on their own */
1517 #define HINT_MAX (1L<<0)
1518 #define HINT_MIN (1L<<1)
1521 winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
1523 static Atom windowState, motif_wm_hints, windowType;
1524 static Atom hiddenState, fullscreenState, belowState, aboveState;
1525 static Atom dockWindow;
1526 static int generation;
1527 Atom type, *pAtom = NULL;
1529 unsigned long hint = 0, maxmin = 0, style, nitems = 0, left = 0;
1530 MwmHints *mwm_hint = NULL;
1534 if (!IsWindow(hWnd))
1537 if (generation != serverGeneration) {
1538 generation = serverGeneration;
1539 windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False);
1540 motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False);
1541 windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False);
1542 hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False);
1544 XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False);
1545 belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False);
1546 aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False);
1547 dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False);
1550 if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
1551 1L, False, XA_ATOM, &type, &format,
1553 (unsigned char **) &pAtom) == Success) {
1554 if (pAtom && nitems == 1) {
1555 if (*pAtom == hiddenState)
1557 else if (*pAtom == fullscreenState)
1559 if (*pAtom == belowState)
1560 *zstyle = HWND_BOTTOM;
1561 else if (*pAtom == aboveState)
1562 *zstyle = HWND_TOPMOST;
1569 if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L,
1570 PropMwmHintsElements, False, motif_wm_hints, &type,
1571 &format, &nitems, &left,
1572 (unsigned char **) &mwm_hint) == Success) {
1573 if (mwm_hint && nitems == PropMwmHintsElements &&
1574 (mwm_hint->flags & MwmHintsDecorations)) {
1575 if (!mwm_hint->decorations)
1576 hint |= HINT_NOFRAME;
1577 else if (!(mwm_hint->decorations & MwmDecorAll)) {
1578 if (mwm_hint->decorations & MwmDecorBorder)
1579 hint |= HINT_BORDER;
1580 if (mwm_hint->decorations & MwmDecorHandle)
1581 hint |= HINT_SIZEBOX;
1582 if (mwm_hint->decorations & MwmDecorTitle)
1583 hint |= HINT_CAPTION;
1584 if (!(mwm_hint->decorations & MwmDecorMenu))
1585 hint |= HINT_NOSYSMENU;
1586 if (!(mwm_hint->decorations & MwmDecorMinimize))
1587 hint |= HINT_NOMINIMIZE;
1588 if (!(mwm_hint->decorations & MwmDecorMaximize))
1589 hint |= HINT_NOMAXIMIZE;
1593 MwmDecorAll means all decorations *except* those specified by other flag
1594 bits that are set. Not yet implemented.
1604 if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L,
1605 1L, False, XA_ATOM, &type, &format,
1607 (unsigned char **) &pAtom) == Success) {
1608 if (pAtom && nitems == 1) {
1609 if (*pAtom == dockWindow) {
1610 hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */
1611 *zstyle = HWND_TOPMOST;
1619 XSizeHints *normal_hint = XAllocSizeHints();
1623 (XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied) ==
1625 if (normal_hint->flags & PMaxSize) {
1626 /* Not maximizable if a maximum size is specified */
1627 hint |= HINT_NOMAXIMIZE;
1629 if (normal_hint->flags & PMinSize) {
1631 If both minimum size and maximum size are specified and are the same,
1632 don't bother with a resizing frame
1634 if ((normal_hint->min_width == normal_hint->max_width)
1635 && (normal_hint->min_height == normal_hint->max_height))
1636 hint = (hint & ~HINT_SIZEBOX);
1643 /* Override hint settings from above with settings from config file */
1645 XClassHint class_hint = { 0, 0 };
1646 char *window_name = 0;
1648 if (XGetClassHint(pDisplay, iWindow, &class_hint)) {
1649 XFetchName(pDisplay, iWindow, &window_name);
1652 winOverrideStyle(class_hint.res_name, class_hint.res_class,
1655 if (class_hint.res_name)
1656 XFree(class_hint.res_name);
1657 if (class_hint.res_class)
1658 XFree(class_hint.res_class);
1667 if (style & STYLE_TOPMOST)
1668 *zstyle = HWND_TOPMOST;
1669 else if (style & STYLE_MAXIMIZE)
1670 maxmin = (hint & ~HINT_MIN) | HINT_MAX;
1671 else if (style & STYLE_MINIMIZE)
1672 maxmin = (hint & ~HINT_MAX) | HINT_MIN;
1673 else if (style & STYLE_BOTTOM)
1674 *zstyle = HWND_BOTTOM;
1676 if (maxmin & HINT_MAX)
1677 SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
1678 else if (maxmin & HINT_MIN)
1679 SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
1681 if (style & STYLE_NOTITLE)
1683 (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) |
1685 else if (style & STYLE_OUTLINE)
1687 (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) |
1689 else if (style & STYLE_NOFRAME)
1691 (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) |
1694 /* Now apply styles to window */
1695 style = GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */
1699 if (!hint) /* All on */
1700 style = style | WS_CAPTION | WS_SIZEBOX;
1701 else if (hint & HINT_NOFRAME) /* All off */
1702 style = style & ~WS_CAPTION & ~WS_SIZEBOX;
1704 style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) |
1705 ((hint & HINT_SIZEBOX) ? WS_SIZEBOX : 0) |
1706 ((hint & HINT_CAPTION) ? WS_CAPTION : 0);
1708 if (hint & HINT_NOMAXIMIZE)
1709 style = style & ~WS_MAXIMIZEBOX;
1711 if (hint & HINT_NOMINIMIZE)
1712 style = style & ~WS_MINIMIZEBOX;
1714 if (hint & HINT_NOSYSMENU)
1715 style = style & ~WS_SYSMENU;
1717 SetWindowLongPtr(hWnd, GWL_STYLE, style);
1721 winUpdateWindowPosition(HWND hWnd, Bool reshape, HWND * zstyle)
1723 int iX, iY, iWidth, iHeight;
1726 WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
1727 DrawablePtr pDraw = NULL;
1731 pDraw = &pWin->drawable;
1735 /* Get the X and Y location of the X window */
1736 iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
1737 iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
1739 /* Get the height and width of the X window */
1740 iWidth = pWin->drawable.width;
1741 iHeight = pWin->drawable.height;
1743 /* Setup a rectangle with the X window position and size */
1744 SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
1746 winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
1747 rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
1749 AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
1750 GetWindowLongPtr(hWnd, GWL_EXSTYLE));
1752 /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
1753 if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
1754 iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
1759 if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
1760 iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
1762 rcNew.bottom += iDy;
1765 winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
1766 rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
1768 /* Position the Windows window */
1769 SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
1770 rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
1773 winReshapeMultiWindow(pWin);
1774 winUpdateRgnMultiWindow(pWin);