winmultiwindowwm.c revision 35c4bbdf
105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 36747b715Smrg *Copyright (C) Colin Harrison 2005-2009 405b261ecSmrg * 505b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 605b261ecSmrg * a copy of this software and associated documentation files (the 705b261ecSmrg *"Software"), to deal in the Software without restriction, including 805b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 905b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 1005b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1105b261ecSmrg *the following conditions: 1205b261ecSmrg * 1305b261ecSmrg *The above copyright notice and this permission notice shall be 1405b261ecSmrg *included in all copies or substantial portions of the Software. 1505b261ecSmrg * 1605b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1705b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1805b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1905b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 2005b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2105b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2205b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2305b261ecSmrg * 2405b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project 2505b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2605b261ecSmrg *or other dealings in this Software without prior written authorization 2705b261ecSmrg *from the XFree86 Project. 2805b261ecSmrg * 2905b261ecSmrg * Authors: Kensuke Matsuzaki 306747b715Smrg * Colin Harrison 3105b261ecSmrg */ 3205b261ecSmrg 3305b261ecSmrg/* X headers */ 3405b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3505b261ecSmrg#include <xwin-config.h> 3605b261ecSmrg#endif 3705b261ecSmrg#include <stdio.h> 3805b261ecSmrg#include <stdlib.h> 3905b261ecSmrg#include <unistd.h> 4005b261ecSmrg#ifdef __CYGWIN__ 4105b261ecSmrg#include <sys/select.h> 4205b261ecSmrg#endif 4305b261ecSmrg#include <fcntl.h> 4405b261ecSmrg#include <setjmp.h> 4505b261ecSmrg#define HANDLE void * 4605b261ecSmrg#include <pthread.h> 4705b261ecSmrg#undef HANDLE 4805b261ecSmrg#include <X11/X.h> 4905b261ecSmrg#include <X11/Xatom.h> 5005b261ecSmrg#include <X11/Xlib.h> 5105b261ecSmrg#include <X11/Xlocale.h> 5205b261ecSmrg#include <X11/Xproto.h> 5305b261ecSmrg#include <X11/Xutil.h> 5405b261ecSmrg#include <X11/cursorfont.h> 556747b715Smrg#include <X11/Xwindows.h> 5605b261ecSmrg 5705b261ecSmrg/* Local headers */ 5805b261ecSmrg#include "winwindow.h" 596747b715Smrg#include "winprefs.h" 606747b715Smrg#include "window.h" 616747b715Smrg#include "pixmapstr.h" 626747b715Smrg#include "windowstr.h" 6335c4bbdfSmrg#include "winglobals.h" 6435c4bbdfSmrg#include "windisplay.h" 656747b715Smrg 6605b261ecSmrg#ifdef XWIN_MULTIWINDOWEXTWM 676747b715Smrg#include <X11/extensions/windowswmstr.h> 686747b715Smrg#else 696747b715Smrg/* We need the native HWND atom for intWM, so for consistency use the 706747b715Smrg same name as extWM would if we were building with enabled... */ 716747b715Smrg#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND" 7205b261ecSmrg#endif 7305b261ecSmrg 7435c4bbdfSmrg#ifndef HOST_NAME_MAX 7535c4bbdfSmrg#define HOST_NAME_MAX 255 7635c4bbdfSmrg#endif 7735c4bbdfSmrg 7805b261ecSmrgextern void winDebug(const char *format, ...); 796747b715Smrgextern void winReshapeMultiWindow(WindowPtr pWin); 806747b715Smrgextern void winUpdateRgnMultiWindow(WindowPtr pWin); 8105b261ecSmrg 8205b261ecSmrg#ifndef CYGDEBUG 8305b261ecSmrg#define CYGDEBUG NO 8405b261ecSmrg#endif 8505b261ecSmrg 8605b261ecSmrg/* 8705b261ecSmrg * Constant defines 8805b261ecSmrg */ 8905b261ecSmrg 9005b261ecSmrg#define WIN_CONNECT_RETRIES 5 9105b261ecSmrg#define WIN_CONNECT_DELAY 5 9205b261ecSmrg#ifdef HAS_DEVWINDOWS 9335c4bbdfSmrg#define WIN_MSG_QUEUE_FNAME "/dev/windows" 9405b261ecSmrg#endif 9505b261ecSmrg#define WIN_JMP_OKAY 0 9605b261ecSmrg#define WIN_JMP_ERROR_IO 2 9705b261ecSmrg 9805b261ecSmrg/* 9905b261ecSmrg * Local structures 10005b261ecSmrg */ 10105b261ecSmrg 10205b261ecSmrgtypedef struct _WMMsgNodeRec { 10335c4bbdfSmrg winWMMessageRec msg; 10435c4bbdfSmrg struct _WMMsgNodeRec *pNext; 10505b261ecSmrg} WMMsgNodeRec, *WMMsgNodePtr; 10605b261ecSmrg 10705b261ecSmrgtypedef struct _WMMsgQueueRec { 10835c4bbdfSmrg struct _WMMsgNodeRec *pHead; 10935c4bbdfSmrg struct _WMMsgNodeRec *pTail; 11035c4bbdfSmrg pthread_mutex_t pmMutex; 11135c4bbdfSmrg pthread_cond_t pcNotEmpty; 11235c4bbdfSmrg int nQueueSize; 11305b261ecSmrg} WMMsgQueueRec, *WMMsgQueuePtr; 11405b261ecSmrg 11505b261ecSmrgtypedef struct _WMInfo { 11635c4bbdfSmrg Display *pDisplay; 11735c4bbdfSmrg WMMsgQueueRec wmMsgQueue; 11835c4bbdfSmrg Atom atmWmProtos; 11935c4bbdfSmrg Atom atmWmDelete; 12035c4bbdfSmrg Atom atmWmTakeFocus; 12135c4bbdfSmrg Atom atmPrivMap; 12235c4bbdfSmrg Bool fAllowOtherWM; 12305b261ecSmrg} WMInfoRec, *WMInfoPtr; 12405b261ecSmrg 12505b261ecSmrgtypedef struct _WMProcArgRec { 12635c4bbdfSmrg DWORD dwScreen; 12735c4bbdfSmrg WMInfoPtr pWMInfo; 12835c4bbdfSmrg pthread_mutex_t *ppmServerStarted; 12905b261ecSmrg} WMProcArgRec, *WMProcArgPtr; 13005b261ecSmrg 13105b261ecSmrgtypedef struct _XMsgProcArgRec { 13235c4bbdfSmrg Display *pDisplay; 13335c4bbdfSmrg DWORD dwScreen; 13435c4bbdfSmrg WMInfoPtr pWMInfo; 13535c4bbdfSmrg pthread_mutex_t *ppmServerStarted; 13635c4bbdfSmrg HWND hwndScreen; 13705b261ecSmrg} XMsgProcArgRec, *XMsgProcArgPtr; 13805b261ecSmrg 13905b261ecSmrg/* 14005b261ecSmrg * Prototypes for local functions 14105b261ecSmrg */ 14205b261ecSmrg 14305b261ecSmrgstatic void 14435c4bbdfSmrg PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode); 14505b261ecSmrg 14635c4bbdfSmrgstatic WMMsgNodePtr PopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo); 14705b261ecSmrg 14805b261ecSmrgstatic Bool 14935c4bbdfSmrg InitQueue(WMMsgQueuePtr pQueue); 15005b261ecSmrg 15105b261ecSmrgstatic void 15235c4bbdfSmrg GetWindowName(Display * pDpy, Window iWin, char **ppWindowName); 15305b261ecSmrg 15405b261ecSmrgstatic int 15535c4bbdfSmrg SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData); 15605b261ecSmrg 15705b261ecSmrgstatic void 15835c4bbdfSmrg UpdateName(WMInfoPtr pWMInfo, Window iWindow); 15905b261ecSmrg 16035c4bbdfSmrgstatic void *winMultiWindowWMProc(void *pArg); 16105b261ecSmrg 16205b261ecSmrgstatic int 16335c4bbdfSmrg winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr); 16405b261ecSmrg 16505b261ecSmrgstatic int 16635c4bbdfSmrg winMultiWindowWMIOErrorHandler(Display * pDisplay); 16705b261ecSmrg 16835c4bbdfSmrgstatic void *winMultiWindowXMsgProc(void *pArg); 16905b261ecSmrg 17005b261ecSmrgstatic int 17135c4bbdfSmrg winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr); 17205b261ecSmrg 17305b261ecSmrgstatic int 17435c4bbdfSmrg winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay); 17505b261ecSmrg 17605b261ecSmrgstatic int 17735c4bbdfSmrg winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr); 17805b261ecSmrg 17905b261ecSmrgstatic void 18035c4bbdfSmrg winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg); 18105b261ecSmrg 18205b261ecSmrg#if 0 18305b261ecSmrgstatic void 18435c4bbdfSmrg PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction); 18505b261ecSmrg#endif 18605b261ecSmrg 18705b261ecSmrgstatic Bool 18835c4bbdfSmrg 18935c4bbdfSmrgCheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen, 19035c4bbdfSmrg Bool fAllowOtherWM); 19105b261ecSmrg 1926747b715Smrgstatic void 19335c4bbdfSmrg winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle); 1946747b715Smrg 1956747b715Smrgvoid 19635c4bbdfSmrg winUpdateWindowPosition(HWND hWnd, HWND * zstyle); 19705b261ecSmrg 19805b261ecSmrg/* 19905b261ecSmrg * Local globals 20005b261ecSmrg */ 20105b261ecSmrg 20235c4bbdfSmrgstatic jmp_buf g_jmpWMEntry; 20335c4bbdfSmrgstatic XIOErrorHandler g_winMultiWindowWMOldIOErrorHandler; 20435c4bbdfSmrgstatic pthread_t g_winMultiWindowWMThread; 20535c4bbdfSmrgstatic jmp_buf g_jmpXMsgProcEntry; 20635c4bbdfSmrgstatic XIOErrorHandler g_winMultiWindowXMsgProcOldIOErrorHandler; 20735c4bbdfSmrgstatic pthread_t g_winMultiWindowXMsgProcThread; 20835c4bbdfSmrgstatic Bool g_shutdown = FALSE; 20935c4bbdfSmrgstatic Bool redirectError = FALSE; 21035c4bbdfSmrgstatic Bool g_fAnotherWMRunning = FALSE; 21105b261ecSmrg 21205b261ecSmrg/* 21305b261ecSmrg * PushMessage - Push a message onto the queue 21405b261ecSmrg */ 21505b261ecSmrg 21605b261ecSmrgstatic void 21735c4bbdfSmrgPushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) 21805b261ecSmrg{ 21905b261ecSmrg 22035c4bbdfSmrg /* Lock the queue mutex */ 22135c4bbdfSmrg pthread_mutex_lock(&pQueue->pmMutex); 22205b261ecSmrg 22335c4bbdfSmrg pNode->pNext = NULL; 22435c4bbdfSmrg 22535c4bbdfSmrg if (pQueue->pTail != NULL) { 22635c4bbdfSmrg pQueue->pTail->pNext = pNode; 22705b261ecSmrg } 22835c4bbdfSmrg pQueue->pTail = pNode; 22905b261ecSmrg 23035c4bbdfSmrg if (pQueue->pHead == NULL) { 23135c4bbdfSmrg pQueue->pHead = pNode; 23235c4bbdfSmrg } 23305b261ecSmrg 23405b261ecSmrg#if 0 23535c4bbdfSmrg switch (pNode->msg.msg) { 23605b261ecSmrg case WM_WM_MOVE: 23735c4bbdfSmrg ErrorF("\tWM_WM_MOVE\n"); 23835c4bbdfSmrg break; 23905b261ecSmrg case WM_WM_SIZE: 24035c4bbdfSmrg ErrorF("\tWM_WM_SIZE\n"); 24135c4bbdfSmrg break; 24205b261ecSmrg case WM_WM_RAISE: 24335c4bbdfSmrg ErrorF("\tWM_WM_RAISE\n"); 24435c4bbdfSmrg break; 24505b261ecSmrg case WM_WM_LOWER: 24635c4bbdfSmrg ErrorF("\tWM_WM_LOWER\n"); 24735c4bbdfSmrg break; 24805b261ecSmrg case WM_WM_MAP: 24935c4bbdfSmrg ErrorF("\tWM_WM_MAP\n"); 25035c4bbdfSmrg break; 2516747b715Smrg case WM_WM_MAP2: 25235c4bbdfSmrg ErrorF("\tWM_WM_MAP2\n"); 25335c4bbdfSmrg break; 2546747b715Smrg case WM_WM_MAP3: 25535c4bbdfSmrg ErrorF("\tWM_WM_MAP3\n"); 25635c4bbdfSmrg break; 25705b261ecSmrg case WM_WM_UNMAP: 25835c4bbdfSmrg ErrorF("\tWM_WM_UNMAP\n"); 25935c4bbdfSmrg break; 26005b261ecSmrg case WM_WM_KILL: 26135c4bbdfSmrg ErrorF("\tWM_WM_KILL\n"); 26235c4bbdfSmrg break; 26305b261ecSmrg case WM_WM_ACTIVATE: 26435c4bbdfSmrg ErrorF("\tWM_WM_ACTIVATE\n"); 26535c4bbdfSmrg break; 26605b261ecSmrg default: 26735c4bbdfSmrg ErrorF("\tUnknown Message.\n"); 26835c4bbdfSmrg break; 26905b261ecSmrg } 27005b261ecSmrg#endif 27105b261ecSmrg 27235c4bbdfSmrg /* Increase the count of elements in the queue by one */ 27335c4bbdfSmrg ++(pQueue->nQueueSize); 27405b261ecSmrg 27535c4bbdfSmrg /* Release the queue mutex */ 27635c4bbdfSmrg pthread_mutex_unlock(&pQueue->pmMutex); 27705b261ecSmrg 27835c4bbdfSmrg /* Signal that the queue is not empty */ 27935c4bbdfSmrg pthread_cond_signal(&pQueue->pcNotEmpty); 28005b261ecSmrg} 28105b261ecSmrg 28205b261ecSmrg#if CYGMULTIWINDOW_DEBUG 28305b261ecSmrg/* 28405b261ecSmrg * QueueSize - Return the size of the queue 28505b261ecSmrg */ 28605b261ecSmrg 28705b261ecSmrgstatic int 28835c4bbdfSmrgQueueSize(WMMsgQueuePtr pQueue) 28905b261ecSmrg{ 29035c4bbdfSmrg WMMsgNodePtr pNode; 29135c4bbdfSmrg int nSize = 0; 29235c4bbdfSmrg 29335c4bbdfSmrg /* Loop through all elements in the queue */ 29435c4bbdfSmrg for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) 29535c4bbdfSmrg ++nSize; 29635c4bbdfSmrg 29735c4bbdfSmrg return nSize; 29805b261ecSmrg} 29905b261ecSmrg#endif 30005b261ecSmrg 30105b261ecSmrg/* 30205b261ecSmrg * PopMessage - Pop a message from the queue 30305b261ecSmrg */ 30405b261ecSmrg 30505b261ecSmrgstatic WMMsgNodePtr 30635c4bbdfSmrgPopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo) 30705b261ecSmrg{ 30835c4bbdfSmrg WMMsgNodePtr pNode; 30905b261ecSmrg 31035c4bbdfSmrg /* Lock the queue mutex */ 31135c4bbdfSmrg pthread_mutex_lock(&pQueue->pmMutex); 31205b261ecSmrg 31335c4bbdfSmrg /* Wait for --- */ 31435c4bbdfSmrg while (pQueue->pHead == NULL) { 31535c4bbdfSmrg pthread_cond_wait(&pQueue->pcNotEmpty, &pQueue->pmMutex); 31605b261ecSmrg } 31735c4bbdfSmrg 31835c4bbdfSmrg pNode = pQueue->pHead; 31935c4bbdfSmrg if (pQueue->pHead != NULL) { 32035c4bbdfSmrg pQueue->pHead = pQueue->pHead->pNext; 32105b261ecSmrg } 32205b261ecSmrg 32335c4bbdfSmrg if (pQueue->pTail == pNode) { 32435c4bbdfSmrg pQueue->pTail = NULL; 32505b261ecSmrg } 32605b261ecSmrg 32735c4bbdfSmrg /* Drop the number of elements in the queue by one */ 32835c4bbdfSmrg --(pQueue->nQueueSize); 32905b261ecSmrg 33005b261ecSmrg#if CYGMULTIWINDOW_DEBUG 33135c4bbdfSmrg ErrorF("Queue Size %d %d\n", pQueue->nQueueSize, QueueSize(pQueue)); 33205b261ecSmrg#endif 33305b261ecSmrg 33435c4bbdfSmrg /* Release the queue mutex */ 33535c4bbdfSmrg pthread_mutex_unlock(&pQueue->pmMutex); 33605b261ecSmrg 33735c4bbdfSmrg return pNode; 33835c4bbdfSmrg} 33905b261ecSmrg 34005b261ecSmrg#if 0 34105b261ecSmrg/* 34235c4bbdfSmrg * HaveMessage - 34305b261ecSmrg */ 34405b261ecSmrg 34505b261ecSmrgstatic Bool 34635c4bbdfSmrgHaveMessage(WMMsgQueuePtr pQueue, UINT msg, Window iWindow) 34705b261ecSmrg{ 34835c4bbdfSmrg WMMsgNodePtr pNode; 34935c4bbdfSmrg 35035c4bbdfSmrg for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) { 35135c4bbdfSmrg if (pNode->msg.msg == msg && pNode->msg.iWindow == iWindow) 35235c4bbdfSmrg return True; 35305b261ecSmrg } 35435c4bbdfSmrg 35535c4bbdfSmrg return False; 35605b261ecSmrg} 35705b261ecSmrg#endif 35805b261ecSmrg 35905b261ecSmrg/* 36005b261ecSmrg * InitQueue - Initialize the Window Manager message queue 36105b261ecSmrg */ 36205b261ecSmrg 36305b261ecSmrgstatic 36435c4bbdfSmrg Bool 36535c4bbdfSmrgInitQueue(WMMsgQueuePtr pQueue) 36605b261ecSmrg{ 36735c4bbdfSmrg /* Check if the pQueue pointer is NULL */ 36835c4bbdfSmrg if (pQueue == NULL) { 36935c4bbdfSmrg ErrorF("InitQueue - pQueue is NULL. Exiting.\n"); 37035c4bbdfSmrg return FALSE; 37105b261ecSmrg } 37205b261ecSmrg 37335c4bbdfSmrg /* Set the head and tail to NULL */ 37435c4bbdfSmrg pQueue->pHead = NULL; 37535c4bbdfSmrg pQueue->pTail = NULL; 37605b261ecSmrg 37735c4bbdfSmrg /* There are no elements initially */ 37835c4bbdfSmrg pQueue->nQueueSize = 0; 37905b261ecSmrg 38005b261ecSmrg#if CYGMULTIWINDOW_DEBUG 38135c4bbdfSmrg winDebug("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize, 38235c4bbdfSmrg QueueSize(pQueue)); 38305b261ecSmrg#endif 38405b261ecSmrg 38535c4bbdfSmrg winDebug("InitQueue - Calling pthread_mutex_init\n"); 38605b261ecSmrg 38735c4bbdfSmrg /* Create synchronization objects */ 38835c4bbdfSmrg pthread_mutex_init(&pQueue->pmMutex, NULL); 38905b261ecSmrg 39035c4bbdfSmrg winDebug("InitQueue - pthread_mutex_init returned\n"); 39135c4bbdfSmrg winDebug("InitQueue - Calling pthread_cond_init\n"); 39205b261ecSmrg 39335c4bbdfSmrg pthread_cond_init(&pQueue->pcNotEmpty, NULL); 39405b261ecSmrg 39535c4bbdfSmrg winDebug("InitQueue - pthread_cond_init returned\n"); 39605b261ecSmrg 39735c4bbdfSmrg return TRUE; 39805b261ecSmrg} 39905b261ecSmrg 40035c4bbdfSmrgstatic 40135c4bbdfSmrgchar * 40235c4bbdfSmrgXutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp) 40335c4bbdfSmrg{ 40435c4bbdfSmrg int nNum; 40535c4bbdfSmrg char **ppList; 40635c4bbdfSmrg char *pszReturnData; 40735c4bbdfSmrg 40835c4bbdfSmrg if (Xutf8TextPropertyToTextList(pDisplay, xtp, &ppList, &nNum) >= Success && 40935c4bbdfSmrg nNum > 0 && *ppList) { 41035c4bbdfSmrg int i; 41135c4bbdfSmrg int iLen = 0; 41235c4bbdfSmrg 41335c4bbdfSmrg for (i = 0; i < nNum; i++) 41435c4bbdfSmrg iLen += strlen(ppList[i]); 41535c4bbdfSmrg pszReturnData = malloc(iLen + 1); 41635c4bbdfSmrg pszReturnData[0] = '\0'; 41735c4bbdfSmrg for (i = 0; i < nNum; i++) 41835c4bbdfSmrg strcat(pszReturnData, ppList[i]); 41935c4bbdfSmrg if (ppList) 42035c4bbdfSmrg XFreeStringList(ppList); 42135c4bbdfSmrg } 42235c4bbdfSmrg else { 42335c4bbdfSmrg pszReturnData = malloc(1); 42435c4bbdfSmrg pszReturnData[0] = '\0'; 42535c4bbdfSmrg } 42635c4bbdfSmrg 42735c4bbdfSmrg return pszReturnData; 42835c4bbdfSmrg} 42905b261ecSmrg 43005b261ecSmrg/* 43105b261ecSmrg * GetWindowName - Retrieve the title of an X Window 43205b261ecSmrg */ 43305b261ecSmrg 43405b261ecSmrgstatic void 43535c4bbdfSmrgGetWindowName(Display * pDisplay, Window iWin, char **ppWindowName) 43605b261ecSmrg{ 43735c4bbdfSmrg int nResult; 43835c4bbdfSmrg XTextProperty xtpWindowName; 43935c4bbdfSmrg XTextProperty xtpClientMachine; 44035c4bbdfSmrg char *pszWindowName; 44135c4bbdfSmrg char *pszClientMachine; 44235c4bbdfSmrg char hostname[HOST_NAME_MAX + 1]; 44335c4bbdfSmrg 44405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 44535c4bbdfSmrg ErrorF("GetWindowName\n"); 44605b261ecSmrg#endif 44705b261ecSmrg 44835c4bbdfSmrg /* Intialize ppWindowName to NULL */ 44935c4bbdfSmrg *ppWindowName = NULL; 45005b261ecSmrg 45135c4bbdfSmrg /* Try to get window name */ 45235c4bbdfSmrg nResult = XGetWMName(pDisplay, iWin, &xtpWindowName); 45335c4bbdfSmrg if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) { 45405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 45535c4bbdfSmrg ErrorF("GetWindowName - XGetWMName failed. No name.\n"); 45605b261ecSmrg#endif 45735c4bbdfSmrg return; 45805b261ecSmrg } 45905b261ecSmrg 46035c4bbdfSmrg pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName); 46135c4bbdfSmrg XFree(xtpWindowName.value); 46235c4bbdfSmrg 46335c4bbdfSmrg if (g_fHostInTitle) { 46435c4bbdfSmrg /* Try to get client machine name */ 46535c4bbdfSmrg nResult = XGetWMClientMachine(pDisplay, iWin, &xtpClientMachine); 46635c4bbdfSmrg if (nResult && xtpClientMachine.value && xtpClientMachine.nitems) { 46735c4bbdfSmrg pszClientMachine = 46835c4bbdfSmrg Xutf8TextPropertyToString(pDisplay, &xtpClientMachine); 46935c4bbdfSmrg XFree(xtpClientMachine.value); 47035c4bbdfSmrg 47135c4bbdfSmrg /* 47235c4bbdfSmrg If we have a client machine name 47335c4bbdfSmrg and it's not the local host name 47435c4bbdfSmrg and it's not already in the window title... 47535c4bbdfSmrg */ 47635c4bbdfSmrg if (strlen(pszClientMachine) && 47735c4bbdfSmrg !gethostname(hostname, HOST_NAME_MAX + 1) && 47835c4bbdfSmrg strcmp(hostname, pszClientMachine) && 47935c4bbdfSmrg (strstr(pszWindowName, pszClientMachine) == 0)) { 48035c4bbdfSmrg /* ... add '@<clientmachine>' to end of window name */ 48135c4bbdfSmrg *ppWindowName = 48235c4bbdfSmrg malloc(strlen(pszWindowName) + 48335c4bbdfSmrg strlen(pszClientMachine) + 2); 48435c4bbdfSmrg strcpy(*ppWindowName, pszWindowName); 48535c4bbdfSmrg strcat(*ppWindowName, "@"); 48635c4bbdfSmrg strcat(*ppWindowName, pszClientMachine); 48735c4bbdfSmrg 48835c4bbdfSmrg free(pszWindowName); 48935c4bbdfSmrg free(pszClientMachine); 49035c4bbdfSmrg 49135c4bbdfSmrg return; 49235c4bbdfSmrg } 49335c4bbdfSmrg } 49435c4bbdfSmrg } 49505b261ecSmrg 49635c4bbdfSmrg /* otherwise just return the window name */ 49735c4bbdfSmrg *ppWindowName = pszWindowName; 49805b261ecSmrg} 49905b261ecSmrg 50035c4bbdfSmrg/* 50135c4bbdfSmrg * Does the client support the specified WM_PROTOCOLS protocol? 50235c4bbdfSmrg */ 50335c4bbdfSmrg 50435c4bbdfSmrgstatic Bool 50535c4bbdfSmrgIsWmProtocolAvailable(Display * pDisplay, Window iWindow, Atom atmProtocol) 50635c4bbdfSmrg{ 50735c4bbdfSmrg int i, n, found = 0; 50835c4bbdfSmrg Atom *protocols; 50935c4bbdfSmrg 51035c4bbdfSmrg if (XGetWMProtocols(pDisplay, iWindow, &protocols, &n)) { 51135c4bbdfSmrg for (i = 0; i < n; ++i) 51235c4bbdfSmrg if (protocols[i] == atmProtocol) 51335c4bbdfSmrg ++found; 51435c4bbdfSmrg 51535c4bbdfSmrg XFree(protocols); 51635c4bbdfSmrg } 51735c4bbdfSmrg 51835c4bbdfSmrg return found > 0; 51935c4bbdfSmrg} 52005b261ecSmrg 52105b261ecSmrg/* 52205b261ecSmrg * Send a message to the X server from the WM thread 52305b261ecSmrg */ 52405b261ecSmrg 52505b261ecSmrgstatic int 52635c4bbdfSmrgSendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData) 52705b261ecSmrg{ 52835c4bbdfSmrg XEvent e; 52935c4bbdfSmrg 53035c4bbdfSmrg /* Prepare the X event structure */ 53135c4bbdfSmrg e.type = ClientMessage; 53235c4bbdfSmrg e.xclient.window = iWin; 53335c4bbdfSmrg e.xclient.message_type = atmType; 53435c4bbdfSmrg e.xclient.format = 32; 53535c4bbdfSmrg e.xclient.data.l[0] = nData; 53635c4bbdfSmrg e.xclient.data.l[1] = CurrentTime; 53735c4bbdfSmrg 53835c4bbdfSmrg /* Send the event to X */ 53935c4bbdfSmrg return XSendEvent(pDisplay, iWin, False, NoEventMask, &e); 54005b261ecSmrg} 54105b261ecSmrg 54235c4bbdfSmrg/* 54335c4bbdfSmrg * See if we can get the stored HWND for this window... 54435c4bbdfSmrg */ 54535c4bbdfSmrgstatic HWND 54635c4bbdfSmrggetHwnd(WMInfoPtr pWMInfo, Window iWindow) 54735c4bbdfSmrg{ 54835c4bbdfSmrg Atom atmType; 54935c4bbdfSmrg int fmtRet; 55035c4bbdfSmrg unsigned long items, remain; 55135c4bbdfSmrg HWND *retHwnd, hWnd = NULL; 55235c4bbdfSmrg 55335c4bbdfSmrg if (XGetWindowProperty(pWMInfo->pDisplay, 55435c4bbdfSmrg iWindow, 55535c4bbdfSmrg pWMInfo->atmPrivMap, 55635c4bbdfSmrg 0, 55735c4bbdfSmrg sizeof(HWND)/4, 55835c4bbdfSmrg False, 55935c4bbdfSmrg XA_INTEGER, 56035c4bbdfSmrg &atmType, 56135c4bbdfSmrg &fmtRet, 56235c4bbdfSmrg &items, 56335c4bbdfSmrg &remain, (unsigned char **) &retHwnd) == Success) { 56435c4bbdfSmrg if (retHwnd) { 56535c4bbdfSmrg hWnd = *retHwnd; 56635c4bbdfSmrg XFree(retHwnd); 56735c4bbdfSmrg } 56835c4bbdfSmrg } 56935c4bbdfSmrg 57035c4bbdfSmrg /* Some sanity checks */ 57135c4bbdfSmrg if (!hWnd) 57235c4bbdfSmrg return NULL; 57335c4bbdfSmrg if (!IsWindow(hWnd)) 57435c4bbdfSmrg return NULL; 57535c4bbdfSmrg 57635c4bbdfSmrg return hWnd; 57735c4bbdfSmrg} 57805b261ecSmrg 57905b261ecSmrg/* 58005b261ecSmrg * Updates the name of a HWND according to its X WM_NAME property 58105b261ecSmrg */ 58205b261ecSmrg 58305b261ecSmrgstatic void 58435c4bbdfSmrgUpdateName(WMInfoPtr pWMInfo, Window iWindow) 58505b261ecSmrg{ 58635c4bbdfSmrg HWND hWnd; 58735c4bbdfSmrg XWindowAttributes attr; 58835c4bbdfSmrg 58935c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 59035c4bbdfSmrg if (!hWnd) 59135c4bbdfSmrg return; 59235c4bbdfSmrg 59335c4bbdfSmrg /* If window isn't override-redirect */ 59435c4bbdfSmrg XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr); 59535c4bbdfSmrg if (!attr.override_redirect) { 59635c4bbdfSmrg char *pszWindowName; 59735c4bbdfSmrg 59835c4bbdfSmrg /* Get the X windows window name */ 59935c4bbdfSmrg GetWindowName(pWMInfo->pDisplay, iWindow, &pszWindowName); 60035c4bbdfSmrg 60135c4bbdfSmrg if (pszWindowName) { 60235c4bbdfSmrg /* Convert from UTF-8 to wide char */ 60335c4bbdfSmrg int iLen = 60435c4bbdfSmrg MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, NULL, 0); 60535c4bbdfSmrg wchar_t *pwszWideWindowName = 60635c4bbdfSmrg malloc(sizeof(wchar_t)*(iLen + 1)); 60735c4bbdfSmrg MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, 60835c4bbdfSmrg pwszWideWindowName, iLen); 60935c4bbdfSmrg 61035c4bbdfSmrg /* Set the Windows window name */ 61135c4bbdfSmrg SetWindowTextW(hWnd, pwszWideWindowName); 61235c4bbdfSmrg 61335c4bbdfSmrg free(pwszWideWindowName); 61435c4bbdfSmrg free(pszWindowName); 61535c4bbdfSmrg } 61605b261ecSmrg } 61735c4bbdfSmrg} 61835c4bbdfSmrg 61935c4bbdfSmrg/* 62035c4bbdfSmrg * Updates the icon of a HWND according to its X icon properties 62135c4bbdfSmrg */ 62235c4bbdfSmrg 62335c4bbdfSmrgstatic void 62435c4bbdfSmrgUpdateIcon(WMInfoPtr pWMInfo, Window iWindow) 62535c4bbdfSmrg{ 62635c4bbdfSmrg HWND hWnd; 62735c4bbdfSmrg HICON hIconNew = NULL; 62835c4bbdfSmrg XWindowAttributes attr; 62935c4bbdfSmrg 63035c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 63135c4bbdfSmrg if (!hWnd) 63235c4bbdfSmrg return; 63335c4bbdfSmrg 63435c4bbdfSmrg /* If window isn't override-redirect */ 63535c4bbdfSmrg XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr); 63635c4bbdfSmrg if (!attr.override_redirect) { 63735c4bbdfSmrg XClassHint class_hint = { 0, 0 }; 63835c4bbdfSmrg char *window_name = 0; 63935c4bbdfSmrg 64035c4bbdfSmrg if (XGetClassHint(pWMInfo->pDisplay, iWindow, &class_hint)) { 64135c4bbdfSmrg XFetchName(pWMInfo->pDisplay, iWindow, &window_name); 64235c4bbdfSmrg 64335c4bbdfSmrg hIconNew = 64435c4bbdfSmrg (HICON) winOverrideIcon(class_hint.res_name, 64535c4bbdfSmrg class_hint.res_class, window_name); 64635c4bbdfSmrg 64735c4bbdfSmrg if (class_hint.res_name) 64835c4bbdfSmrg XFree(class_hint.res_name); 64935c4bbdfSmrg if (class_hint.res_class) 65035c4bbdfSmrg XFree(class_hint.res_class); 65135c4bbdfSmrg if (window_name) 65235c4bbdfSmrg XFree(window_name); 65335c4bbdfSmrg } 65405b261ecSmrg } 65535c4bbdfSmrg 65635c4bbdfSmrg winUpdateIcon(hWnd, pWMInfo->pDisplay, iWindow, hIconNew); 65705b261ecSmrg} 65805b261ecSmrg 65935c4bbdfSmrg/* 66035c4bbdfSmrg * Updates the style of a HWND according to its X style properties 66135c4bbdfSmrg */ 66235c4bbdfSmrg 66335c4bbdfSmrgstatic void 66435c4bbdfSmrgUpdateStyle(WMInfoPtr pWMInfo, Window iWindow) 66535c4bbdfSmrg{ 66635c4bbdfSmrg HWND hWnd; 66735c4bbdfSmrg HWND zstyle = HWND_NOTOPMOST; 66835c4bbdfSmrg UINT flags; 66935c4bbdfSmrg 67035c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 67135c4bbdfSmrg if (!hWnd) 67235c4bbdfSmrg return; 67335c4bbdfSmrg 67435c4bbdfSmrg /* Determine the Window style, which determines borders and clipping region... */ 67535c4bbdfSmrg winApplyHints(pWMInfo->pDisplay, iWindow, hWnd, &zstyle); 67635c4bbdfSmrg winUpdateWindowPosition(hWnd, &zstyle); 67735c4bbdfSmrg 67835c4bbdfSmrg /* Apply the updated window style, without changing it's show or activation state */ 67935c4bbdfSmrg flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; 68035c4bbdfSmrg if (zstyle == HWND_NOTOPMOST) 68135c4bbdfSmrg flags |= SWP_NOZORDER | SWP_NOOWNERZORDER; 68235c4bbdfSmrg SetWindowPos(hWnd, NULL, 0, 0, 0, 0, flags); 68335c4bbdfSmrg 68435c4bbdfSmrg /* 68535c4bbdfSmrg Use the WS_EX_TOOLWINDOW style to remove window from Alt-Tab window switcher 68635c4bbdfSmrg 68735c4bbdfSmrg According to MSDN, this is supposed to remove the window from the taskbar as well, 68835c4bbdfSmrg if we SW_HIDE before changing the style followed by SW_SHOW afterwards. 68935c4bbdfSmrg 69035c4bbdfSmrg But that doesn't seem to work reliably, and causes the window to flicker, so use 69135c4bbdfSmrg the iTaskbarList interface to tell the taskbar to show or hide this window. 69235c4bbdfSmrg */ 69335c4bbdfSmrg winShowWindowOnTaskbar(hWnd, 69435c4bbdfSmrg (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & 69535c4bbdfSmrg WS_EX_APPWINDOW) ? TRUE : FALSE); 69635c4bbdfSmrg} 69705b261ecSmrg 69805b261ecSmrg#if 0 69905b261ecSmrg/* 70005b261ecSmrg * Fix up any differences between the X11 and Win32 window stacks 70105b261ecSmrg * starting at the window passed in 70205b261ecSmrg */ 70305b261ecSmrgstatic void 70405b261ecSmrgPreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction) 70505b261ecSmrg{ 70635c4bbdfSmrg HWND hWnd; 70735c4bbdfSmrg DWORD myWinProcID, winProcID; 70835c4bbdfSmrg Window xWindow; 70935c4bbdfSmrg WINDOWPLACEMENT wndPlace; 71035c4bbdfSmrg 71135c4bbdfSmrg hWnd = getHwnd(pWMInfo, iWindow); 71235c4bbdfSmrg if (!hWnd) 71335c4bbdfSmrg return; 71435c4bbdfSmrg 71535c4bbdfSmrg GetWindowThreadProcessId(hWnd, &myWinProcID); 71605b261ecSmrg hWnd = GetNextWindow(hWnd, direction); 71705b261ecSmrg 71835c4bbdfSmrg while (hWnd) { 71935c4bbdfSmrg GetWindowThreadProcessId(hWnd, &winProcID); 72035c4bbdfSmrg if (winProcID == myWinProcID) { 72135c4bbdfSmrg wndPlace.length = sizeof(WINDOWPLACEMENT); 72235c4bbdfSmrg GetWindowPlacement(hWnd, &wndPlace); 72335c4bbdfSmrg if (!(wndPlace.showCmd == SW_HIDE || 72435c4bbdfSmrg wndPlace.showCmd == SW_MINIMIZE)) { 72535c4bbdfSmrg xWindow = (Window) GetProp(hWnd, WIN_WID_PROP); 72635c4bbdfSmrg if (xWindow) { 72735c4bbdfSmrg if (direction == GW_HWNDPREV) 72835c4bbdfSmrg XRaiseWindow(pWMInfo->pDisplay, xWindow); 72935c4bbdfSmrg else 73035c4bbdfSmrg XLowerWindow(pWMInfo->pDisplay, xWindow); 73135c4bbdfSmrg } 73235c4bbdfSmrg } 73335c4bbdfSmrg } 73435c4bbdfSmrg hWnd = GetNextWindow(hWnd, direction); 73535c4bbdfSmrg } 73635c4bbdfSmrg} 73735c4bbdfSmrg#endif /* PreserveWin32Stack */ 73805b261ecSmrg 73905b261ecSmrg/* 74005b261ecSmrg * winMultiWindowWMProc 74105b261ecSmrg */ 74205b261ecSmrg 74305b261ecSmrgstatic void * 74435c4bbdfSmrgwinMultiWindowWMProc(void *pArg) 74505b261ecSmrg{ 74635c4bbdfSmrg WMProcArgPtr pProcArg = (WMProcArgPtr) pArg; 74735c4bbdfSmrg WMInfoPtr pWMInfo = pProcArg->pWMInfo; 74835c4bbdfSmrg 74935c4bbdfSmrg /* Initialize the Window Manager */ 75035c4bbdfSmrg winInitMultiWindowWM(pWMInfo, pProcArg); 75135c4bbdfSmrg 75205b261ecSmrg#if CYGMULTIWINDOW_DEBUG 75335c4bbdfSmrg ErrorF("winMultiWindowWMProc ()\n"); 75405b261ecSmrg#endif 75505b261ecSmrg 75635c4bbdfSmrg /* Loop until we explicitly break out */ 75735c4bbdfSmrg for (;;) { 75835c4bbdfSmrg WMMsgNodePtr pNode; 75935c4bbdfSmrg 76035c4bbdfSmrg if (g_fAnotherWMRunning) { /* Another Window manager exists. */ 76135c4bbdfSmrg Sleep(1000); 76235c4bbdfSmrg continue; 76335c4bbdfSmrg } 76435c4bbdfSmrg 76535c4bbdfSmrg /* Pop a message off of our queue */ 76635c4bbdfSmrg pNode = PopMessage(&pWMInfo->wmMsgQueue, pWMInfo); 76735c4bbdfSmrg if (pNode == NULL) { 76835c4bbdfSmrg /* Bail if PopMessage returns without a message */ 76935c4bbdfSmrg /* NOTE: Remember that PopMessage is a blocking function. */ 77035c4bbdfSmrg ErrorF("winMultiWindowWMProc - Queue is Empty? Exiting.\n"); 77135c4bbdfSmrg pthread_exit(NULL); 77235c4bbdfSmrg } 77305b261ecSmrg 77405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 77535c4bbdfSmrg ErrorF("winMultiWindowWMProc - MSG: %d ID: %d\n", 77635c4bbdfSmrg (int) pNode->msg.msg, (int) pNode->msg.dwID); 77705b261ecSmrg#endif 77805b261ecSmrg 77935c4bbdfSmrg /* Branch on the message type */ 78035c4bbdfSmrg switch (pNode->msg.msg) { 78105b261ecSmrg#if 0 78235c4bbdfSmrg case WM_WM_MOVE: 78335c4bbdfSmrg ErrorF("\tWM_WM_MOVE\n"); 78435c4bbdfSmrg break; 78505b261ecSmrg 78635c4bbdfSmrg case WM_WM_SIZE: 78735c4bbdfSmrg ErrorF("\tWM_WM_SIZE\n"); 78835c4bbdfSmrg break; 78905b261ecSmrg#endif 79005b261ecSmrg 79135c4bbdfSmrg case WM_WM_RAISE: 79205b261ecSmrg#if CYGMULTIWINDOW_DEBUG 79335c4bbdfSmrg ErrorF("\tWM_WM_RAISE\n"); 79405b261ecSmrg#endif 79535c4bbdfSmrg /* Raise the window */ 79635c4bbdfSmrg XRaiseWindow(pWMInfo->pDisplay, pNode->msg.iWindow); 79705b261ecSmrg#if 0 79835c4bbdfSmrg PreserveWin32Stack(pWMInfo, pNode->msg.iWindow, GW_HWNDPREV); 79905b261ecSmrg#endif 80035c4bbdfSmrg break; 80105b261ecSmrg 80235c4bbdfSmrg case WM_WM_LOWER: 80305b261ecSmrg#if CYGMULTIWINDOW_DEBUG 80435c4bbdfSmrg ErrorF("\tWM_WM_LOWER\n"); 80505b261ecSmrg#endif 80605b261ecSmrg 80735c4bbdfSmrg /* Lower the window */ 80835c4bbdfSmrg XLowerWindow(pWMInfo->pDisplay, pNode->msg.iWindow); 80935c4bbdfSmrg break; 81005b261ecSmrg 81135c4bbdfSmrg case WM_WM_MAP: 81205b261ecSmrg#if CYGMULTIWINDOW_DEBUG 81335c4bbdfSmrg ErrorF("\tWM_WM_MAP\n"); 81405b261ecSmrg#endif 81535c4bbdfSmrg /* Put a note as to the HWND associated with this Window */ 81635c4bbdfSmrg XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, 81735c4bbdfSmrg 32, 81835c4bbdfSmrg PropModeReplace, 81935c4bbdfSmrg (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4); 82035c4bbdfSmrg UpdateName(pWMInfo, pNode->msg.iWindow); 82135c4bbdfSmrg UpdateIcon(pWMInfo, pNode->msg.iWindow); 82235c4bbdfSmrg break; 82335c4bbdfSmrg 82435c4bbdfSmrg case WM_WM_MAP2: 8256747b715Smrg#if CYGMULTIWINDOW_DEBUG 82635c4bbdfSmrg ErrorF("\tWM_WM_MAP2\n"); 82705b261ecSmrg#endif 82835c4bbdfSmrg XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, 82935c4bbdfSmrg 32, 83035c4bbdfSmrg PropModeReplace, 83135c4bbdfSmrg (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4); 83235c4bbdfSmrg break; 83335c4bbdfSmrg 83435c4bbdfSmrg case WM_WM_MAP3: 8356747b715Smrg#if CYGMULTIWINDOW_DEBUG 83635c4bbdfSmrg ErrorF("\tWM_WM_MAP3\n"); 8376747b715Smrg#endif 83835c4bbdfSmrg /* Put a note as to the HWND associated with this Window */ 83935c4bbdfSmrg XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, 84035c4bbdfSmrg 32, 84135c4bbdfSmrg PropModeReplace, 84235c4bbdfSmrg (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4); 84335c4bbdfSmrg UpdateName(pWMInfo, pNode->msg.iWindow); 84435c4bbdfSmrg UpdateIcon(pWMInfo, pNode->msg.iWindow); 84535c4bbdfSmrg UpdateStyle(pWMInfo, pNode->msg.iWindow); 84635c4bbdfSmrg 84735c4bbdfSmrg 84835c4bbdfSmrg /* Reshape */ 84935c4bbdfSmrg { 85035c4bbdfSmrg WindowPtr pWin = 85135c4bbdfSmrg GetProp(pNode->msg.hwndWindow, WIN_WINDOW_PROP); 85235c4bbdfSmrg if (pWin) { 85335c4bbdfSmrg winReshapeMultiWindow(pWin); 85435c4bbdfSmrg winUpdateRgnMultiWindow(pWin); 85535c4bbdfSmrg } 85635c4bbdfSmrg } 85735c4bbdfSmrg 85835c4bbdfSmrg break; 85935c4bbdfSmrg 86035c4bbdfSmrg case WM_WM_UNMAP: 86105b261ecSmrg#if CYGMULTIWINDOW_DEBUG 86235c4bbdfSmrg ErrorF("\tWM_WM_UNMAP\n"); 86305b261ecSmrg#endif 86405b261ecSmrg 86535c4bbdfSmrg /* Unmap the window */ 86635c4bbdfSmrg XUnmapWindow(pWMInfo->pDisplay, pNode->msg.iWindow); 86735c4bbdfSmrg break; 86835c4bbdfSmrg 86935c4bbdfSmrg case WM_WM_KILL: 87005b261ecSmrg#if CYGMULTIWINDOW_DEBUG 87135c4bbdfSmrg ErrorF("\tWM_WM_KILL\n"); 87205b261ecSmrg#endif 87335c4bbdfSmrg { 87435c4bbdfSmrg /* --- */ 87535c4bbdfSmrg if (IsWmProtocolAvailable(pWMInfo->pDisplay, 87635c4bbdfSmrg pNode->msg.iWindow, 87735c4bbdfSmrg pWMInfo->atmWmDelete)) 87835c4bbdfSmrg SendXMessage(pWMInfo->pDisplay, 87935c4bbdfSmrg pNode->msg.iWindow, 88035c4bbdfSmrg pWMInfo->atmWmProtos, pWMInfo->atmWmDelete); 88135c4bbdfSmrg else 88235c4bbdfSmrg XKillClient(pWMInfo->pDisplay, pNode->msg.iWindow); 88335c4bbdfSmrg } 88435c4bbdfSmrg break; 88535c4bbdfSmrg 88635c4bbdfSmrg case WM_WM_ACTIVATE: 88705b261ecSmrg#if CYGMULTIWINDOW_DEBUG 88835c4bbdfSmrg ErrorF("\tWM_WM_ACTIVATE\n"); 88905b261ecSmrg#endif 89035c4bbdfSmrg /* Set the input focus */ 89135c4bbdfSmrg 89235c4bbdfSmrg /* 89335c4bbdfSmrg ICCCM 4.1.7 is pretty opaque, but it appears that the rules are 89435c4bbdfSmrg actually quite simple: 89535c4bbdfSmrg -- the WM_HINTS input field determines whether the WM should call 89635c4bbdfSmrg XSetInputFocus() 89735c4bbdfSmrg -- independently, the WM_TAKE_FOCUS protocol determines whether 89835c4bbdfSmrg the WM should send a WM_TAKE_FOCUS ClientMessage. 89935c4bbdfSmrg */ 90035c4bbdfSmrg { 90135c4bbdfSmrg Bool neverFocus = FALSE; 90235c4bbdfSmrg XWMHints *hints = XGetWMHints(pWMInfo->pDisplay, pNode->msg.iWindow); 90335c4bbdfSmrg 90435c4bbdfSmrg if (hints) { 90535c4bbdfSmrg if (hints->flags & InputHint) 90635c4bbdfSmrg neverFocus = !hints->input; 90735c4bbdfSmrg XFree(hints); 90835c4bbdfSmrg } 90935c4bbdfSmrg 91035c4bbdfSmrg if (!neverFocus) 91135c4bbdfSmrg XSetInputFocus(pWMInfo->pDisplay, 91235c4bbdfSmrg pNode->msg.iWindow, 91335c4bbdfSmrg RevertToPointerRoot, CurrentTime); 91435c4bbdfSmrg 91535c4bbdfSmrg if (IsWmProtocolAvailable(pWMInfo->pDisplay, 91635c4bbdfSmrg pNode->msg.iWindow, 91735c4bbdfSmrg pWMInfo->atmWmTakeFocus)) 91835c4bbdfSmrg SendXMessage(pWMInfo->pDisplay, 91935c4bbdfSmrg pNode->msg.iWindow, 92035c4bbdfSmrg pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus); 92135c4bbdfSmrg 92235c4bbdfSmrg } 92335c4bbdfSmrg break; 92435c4bbdfSmrg 92535c4bbdfSmrg case WM_WM_NAME_EVENT: 92635c4bbdfSmrg UpdateName(pWMInfo, pNode->msg.iWindow); 92735c4bbdfSmrg break; 92835c4bbdfSmrg 92935c4bbdfSmrg case WM_WM_ICON_EVENT: 93035c4bbdfSmrg UpdateIcon(pWMInfo, pNode->msg.iWindow); 93135c4bbdfSmrg break; 93235c4bbdfSmrg 93335c4bbdfSmrg case WM_WM_HINTS_EVENT: 93435c4bbdfSmrg { 93535c4bbdfSmrg XWindowAttributes attr; 93635c4bbdfSmrg 93735c4bbdfSmrg /* Don't do anything if this is an override-redirect window */ 93835c4bbdfSmrg XGetWindowAttributes (pWMInfo->pDisplay, pNode->msg.iWindow, &attr); 93935c4bbdfSmrg if (attr.override_redirect) 94035c4bbdfSmrg break; 94135c4bbdfSmrg 94235c4bbdfSmrg UpdateStyle(pWMInfo, pNode->msg.iWindow); 94335c4bbdfSmrg } 94435c4bbdfSmrg break; 94535c4bbdfSmrg 94635c4bbdfSmrg case WM_WM_CHANGE_STATE: 94735c4bbdfSmrg /* Minimize the window in Windows */ 94835c4bbdfSmrg winMinimizeWindow(pNode->msg.iWindow); 94935c4bbdfSmrg break; 95035c4bbdfSmrg 95135c4bbdfSmrg default: 95235c4bbdfSmrg ErrorF("winMultiWindowWMProc - Unknown Message. Exiting.\n"); 95335c4bbdfSmrg pthread_exit(NULL); 95435c4bbdfSmrg break; 95535c4bbdfSmrg } 95635c4bbdfSmrg 95735c4bbdfSmrg /* Free the retrieved message */ 95835c4bbdfSmrg free(pNode); 95935c4bbdfSmrg 96035c4bbdfSmrg /* Flush any pending events on our display */ 96135c4bbdfSmrg XFlush(pWMInfo->pDisplay); 96205b261ecSmrg } 96305b261ecSmrg 96435c4bbdfSmrg /* Free the condition variable */ 96535c4bbdfSmrg pthread_cond_destroy(&pWMInfo->wmMsgQueue.pcNotEmpty); 96635c4bbdfSmrg 96735c4bbdfSmrg /* Free the mutex variable */ 96835c4bbdfSmrg pthread_mutex_destroy(&pWMInfo->wmMsgQueue.pmMutex); 96935c4bbdfSmrg 97035c4bbdfSmrg /* Free the passed-in argument */ 97135c4bbdfSmrg free(pProcArg); 97235c4bbdfSmrg 97305b261ecSmrg#if CYGMULTIWINDOW_DEBUG 97435c4bbdfSmrg ErrorF("-winMultiWindowWMProc ()\n"); 97505b261ecSmrg#endif 97635c4bbdfSmrg return NULL; 97705b261ecSmrg} 97805b261ecSmrg 97905b261ecSmrg/* 98005b261ecSmrg * X message procedure 98105b261ecSmrg */ 98205b261ecSmrg 98305b261ecSmrgstatic void * 98435c4bbdfSmrgwinMultiWindowXMsgProc(void *pArg) 98505b261ecSmrg{ 98635c4bbdfSmrg winWMMessageRec msg; 98735c4bbdfSmrg XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg; 98835c4bbdfSmrg char pszDisplay[512]; 98935c4bbdfSmrg int iRetries; 99035c4bbdfSmrg XEvent event; 99135c4bbdfSmrg Atom atmWmName; 99235c4bbdfSmrg Atom atmWmHints; 99335c4bbdfSmrg Atom atmWmChange; 99435c4bbdfSmrg Atom atmNetWmIcon; 99535c4bbdfSmrg Atom atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints; 99635c4bbdfSmrg int iReturn; 99735c4bbdfSmrg XIconSize *xis; 99835c4bbdfSmrg 99935c4bbdfSmrg winDebug("winMultiWindowXMsgProc - Hello\n"); 100035c4bbdfSmrg 100135c4bbdfSmrg /* Check that argument pointer is not invalid */ 100235c4bbdfSmrg if (pProcArg == NULL) { 100335c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - pProcArg is NULL. Exiting.\n"); 100435c4bbdfSmrg pthread_exit(NULL); 100505b261ecSmrg } 100605b261ecSmrg 100735c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n"); 100805b261ecSmrg 100935c4bbdfSmrg /* Grab the server started mutex - pause until we get it */ 101035c4bbdfSmrg iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted); 101135c4bbdfSmrg if (iReturn != 0) { 101235c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d. " 101335c4bbdfSmrg "Exiting.\n", iReturn); 101435c4bbdfSmrg pthread_exit(NULL); 101505b261ecSmrg } 101605b261ecSmrg 101735c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); 101805b261ecSmrg 101935c4bbdfSmrg /* Allow multiple threads to access Xlib */ 102035c4bbdfSmrg if (XInitThreads() == 0) { 102135c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n"); 102235c4bbdfSmrg pthread_exit(NULL); 102305b261ecSmrg } 102405b261ecSmrg 102535c4bbdfSmrg /* See if X supports the current locale */ 102635c4bbdfSmrg if (XSupportsLocale() == False) { 102735c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - Warning: locale not supported by X\n"); 102805b261ecSmrg } 102905b261ecSmrg 103035c4bbdfSmrg /* Release the server started mutex */ 103135c4bbdfSmrg pthread_mutex_unlock(pProcArg->ppmServerStarted); 103205b261ecSmrg 103335c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n"); 103405b261ecSmrg 103535c4bbdfSmrg /* Install our error handler */ 103635c4bbdfSmrg XSetErrorHandler(winMultiWindowXMsgProcErrorHandler); 103735c4bbdfSmrg g_winMultiWindowXMsgProcThread = pthread_self(); 103835c4bbdfSmrg g_winMultiWindowXMsgProcOldIOErrorHandler = 103935c4bbdfSmrg XSetIOErrorHandler(winMultiWindowXMsgProcIOErrorHandler); 104035c4bbdfSmrg 104135c4bbdfSmrg /* Set jump point for IO Error exits */ 104235c4bbdfSmrg iReturn = setjmp(g_jmpXMsgProcEntry); 104335c4bbdfSmrg 104435c4bbdfSmrg /* Check if we should continue operations */ 104535c4bbdfSmrg if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) { 104635c4bbdfSmrg /* setjmp returned an unknown value, exit */ 104735c4bbdfSmrg ErrorF("winInitMultiWindowXMsgProc - setjmp returned: %d. Exiting.\n", 104835c4bbdfSmrg iReturn); 104935c4bbdfSmrg pthread_exit(NULL); 105005b261ecSmrg } 105135c4bbdfSmrg else if (iReturn == WIN_JMP_ERROR_IO) { 105235c4bbdfSmrg ErrorF("winInitMultiWindowXMsgProc - Caught IO Error. Exiting.\n"); 105335c4bbdfSmrg pthread_exit(NULL); 105405b261ecSmrg } 105505b261ecSmrg 105635c4bbdfSmrg /* Setup the display connection string x */ 105735c4bbdfSmrg winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen); 105805b261ecSmrg 105935c4bbdfSmrg /* Print the display connection string */ 106035c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay); 106105b261ecSmrg 106235c4bbdfSmrg /* Use our generated cookie for authentication */ 106335c4bbdfSmrg winSetAuthorization(); 10646747b715Smrg 106535c4bbdfSmrg /* Initialize retry count */ 106635c4bbdfSmrg iRetries = 0; 106705b261ecSmrg 106835c4bbdfSmrg /* Open the X display */ 106935c4bbdfSmrg do { 107035c4bbdfSmrg /* Try to open the display */ 107135c4bbdfSmrg pProcArg->pDisplay = XOpenDisplay(pszDisplay); 107235c4bbdfSmrg if (pProcArg->pDisplay == NULL) { 107335c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - Could not open display, try: %d, " 107435c4bbdfSmrg "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY); 107535c4bbdfSmrg ++iRetries; 107635c4bbdfSmrg sleep(WIN_CONNECT_DELAY); 107735c4bbdfSmrg continue; 107835c4bbdfSmrg } 107935c4bbdfSmrg else 108035c4bbdfSmrg break; 108105b261ecSmrg } 108235c4bbdfSmrg while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); 108335c4bbdfSmrg 108435c4bbdfSmrg /* Make sure that the display opened */ 108535c4bbdfSmrg if (pProcArg->pDisplay == NULL) { 108635c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - Failed opening the display. " 108735c4bbdfSmrg "Exiting.\n"); 108835c4bbdfSmrg pthread_exit(NULL); 108905b261ecSmrg } 109005b261ecSmrg 109135c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - XOpenDisplay () returned and " 109235c4bbdfSmrg "successfully opened the display.\n"); 109305b261ecSmrg 109435c4bbdfSmrg /* Check if another window manager is already running */ 109535c4bbdfSmrg g_fAnotherWMRunning = 109635c4bbdfSmrg CheckAnotherWindowManager(pProcArg->pDisplay, pProcArg->dwScreen, 109735c4bbdfSmrg pProcArg->pWMInfo->fAllowOtherWM); 10986747b715Smrg 109935c4bbdfSmrg if (g_fAnotherWMRunning && !pProcArg->pWMInfo->fAllowOtherWM) { 110035c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - " 110135c4bbdfSmrg "another window manager is running. Exiting.\n"); 110235c4bbdfSmrg pthread_exit(NULL); 110305b261ecSmrg } 11046747b715Smrg 110535c4bbdfSmrg /* Set up the supported icon sizes */ 110635c4bbdfSmrg xis = XAllocIconSize(); 110735c4bbdfSmrg if (xis) { 110835c4bbdfSmrg xis->min_width = xis->min_height = 16; 110935c4bbdfSmrg xis->max_width = xis->max_height = 48; 111035c4bbdfSmrg xis->width_inc = xis->height_inc = 16; 111135c4bbdfSmrg XSetIconSizes(pProcArg->pDisplay, 111235c4bbdfSmrg RootWindow(pProcArg->pDisplay, pProcArg->dwScreen), 111335c4bbdfSmrg xis, 1); 111435c4bbdfSmrg XFree(xis); 111505b261ecSmrg } 111605b261ecSmrg 111735c4bbdfSmrg atmWmName = XInternAtom(pProcArg->pDisplay, "WM_NAME", False); 111835c4bbdfSmrg atmWmHints = XInternAtom(pProcArg->pDisplay, "WM_HINTS", False); 111935c4bbdfSmrg atmWmChange = XInternAtom(pProcArg->pDisplay, "WM_CHANGE_STATE", False); 112035c4bbdfSmrg atmNetWmIcon = XInternAtom(pProcArg->pDisplay, "_NET_WM_ICON", False); 112135c4bbdfSmrg atmWindowState = XInternAtom(pProcArg->pDisplay, "_NET_WM_STATE", False); 112235c4bbdfSmrg atmMotifWmHints = XInternAtom(pProcArg->pDisplay, "_MOTIF_WM_HINTS", False); 112335c4bbdfSmrg atmWindowType = XInternAtom(pProcArg->pDisplay, "_NET_WM_WINDOW_TYPE", False); 112435c4bbdfSmrg atmNormalHints = XInternAtom(pProcArg->pDisplay, "WM_NORMAL_HINTS", False); 112535c4bbdfSmrg 112635c4bbdfSmrg /* 112735c4bbdfSmrg iiimxcf had a bug until 2009-04-27, assuming that the 112835c4bbdfSmrg WM_STATE atom exists, causing clients to fail with 112935c4bbdfSmrg a BadAtom X error if it doesn't. 113035c4bbdfSmrg 113135c4bbdfSmrg Since this is on in the default Solaris 10 install, 113235c4bbdfSmrg workaround this by making sure it does exist... 113335c4bbdfSmrg */ 113435c4bbdfSmrg XInternAtom(pProcArg->pDisplay, "WM_STATE", 0); 113535c4bbdfSmrg 113635c4bbdfSmrg /* Loop until we explicitly break out */ 113735c4bbdfSmrg while (1) { 113835c4bbdfSmrg if (g_shutdown) 113935c4bbdfSmrg break; 114035c4bbdfSmrg 114135c4bbdfSmrg if (pProcArg->pWMInfo->fAllowOtherWM && !XPending(pProcArg->pDisplay)) { 114235c4bbdfSmrg if (CheckAnotherWindowManager 114335c4bbdfSmrg (pProcArg->pDisplay, pProcArg->dwScreen, TRUE)) { 114435c4bbdfSmrg if (!g_fAnotherWMRunning) { 114535c4bbdfSmrg g_fAnotherWMRunning = TRUE; 114635c4bbdfSmrg SendMessage(pProcArg->hwndScreen, WM_UNMANAGE, 0, 0); 114735c4bbdfSmrg } 114835c4bbdfSmrg } 114935c4bbdfSmrg else { 115035c4bbdfSmrg if (g_fAnotherWMRunning) { 115135c4bbdfSmrg g_fAnotherWMRunning = FALSE; 115235c4bbdfSmrg SendMessage(pProcArg->hwndScreen, WM_MANAGE, 0, 0); 115335c4bbdfSmrg } 115435c4bbdfSmrg } 115535c4bbdfSmrg Sleep(500); 115635c4bbdfSmrg continue; 115735c4bbdfSmrg } 115805b261ecSmrg 115935c4bbdfSmrg /* Fetch next event */ 116035c4bbdfSmrg XNextEvent(pProcArg->pDisplay, &event); 116135c4bbdfSmrg 116235c4bbdfSmrg /* Branch on event type */ 116335c4bbdfSmrg if (event.type == CreateNotify) { 116435c4bbdfSmrg XWindowAttributes attr; 116535c4bbdfSmrg 116635c4bbdfSmrg XSelectInput(pProcArg->pDisplay, 116735c4bbdfSmrg event.xcreatewindow.window, PropertyChangeMask); 116835c4bbdfSmrg 116935c4bbdfSmrg /* Get the window attributes */ 117035c4bbdfSmrg XGetWindowAttributes(pProcArg->pDisplay, 117135c4bbdfSmrg event.xcreatewindow.window, &attr); 117235c4bbdfSmrg 117335c4bbdfSmrg if (!attr.override_redirect) 117435c4bbdfSmrg XSetWindowBorderWidth(pProcArg->pDisplay, 117535c4bbdfSmrg event.xcreatewindow.window, 0); 117635c4bbdfSmrg } 117735c4bbdfSmrg else if (event.type == MapNotify) { 117835c4bbdfSmrg /* Fake a reparentNotify event as SWT/Motif expects a 117935c4bbdfSmrg Window Manager to reparent a top-level window when 118035c4bbdfSmrg it is mapped and waits until they do. 118135c4bbdfSmrg 118235c4bbdfSmrg We don't actually need to reparent, as the frame is 118335c4bbdfSmrg a native window, not an X window 118435c4bbdfSmrg 118535c4bbdfSmrg We do this on MapNotify, not MapRequest like a real 118635c4bbdfSmrg Window Manager would, so we don't have do get involved 118735c4bbdfSmrg in actually mapping the window via it's (non-existent) 118835c4bbdfSmrg parent... 118935c4bbdfSmrg 119035c4bbdfSmrg See sourceware bugzilla #9848 119135c4bbdfSmrg */ 119235c4bbdfSmrg 119335c4bbdfSmrg XWindowAttributes attr; 119435c4bbdfSmrg Window root; 119535c4bbdfSmrg Window parent; 119635c4bbdfSmrg Window *children; 119735c4bbdfSmrg unsigned int nchildren; 119835c4bbdfSmrg 119935c4bbdfSmrg if (XGetWindowAttributes(event.xmap.display, 120035c4bbdfSmrg event.xmap.window, 120135c4bbdfSmrg &attr) && 120235c4bbdfSmrg XQueryTree(event.xmap.display, 120335c4bbdfSmrg event.xmap.window, 120435c4bbdfSmrg &root, &parent, &children, &nchildren)) { 120535c4bbdfSmrg if (children) 120635c4bbdfSmrg XFree(children); 120735c4bbdfSmrg 120835c4bbdfSmrg /* 120935c4bbdfSmrg It's a top-level window if the parent window is a root window 121035c4bbdfSmrg Only non-override_redirect windows can get reparented 121135c4bbdfSmrg */ 121235c4bbdfSmrg if ((attr.root == parent) && !event.xmap.override_redirect) { 121335c4bbdfSmrg XEvent event_send; 121435c4bbdfSmrg 121535c4bbdfSmrg event_send.type = ReparentNotify; 121635c4bbdfSmrg event_send.xreparent.event = event.xmap.window; 121735c4bbdfSmrg event_send.xreparent.window = event.xmap.window; 121835c4bbdfSmrg event_send.xreparent.parent = parent; 121935c4bbdfSmrg event_send.xreparent.x = attr.x; 122035c4bbdfSmrg event_send.xreparent.y = attr.y; 122135c4bbdfSmrg 122235c4bbdfSmrg XSendEvent(event.xmap.display, 122335c4bbdfSmrg event.xmap.window, 122435c4bbdfSmrg True, StructureNotifyMask, &event_send); 122535c4bbdfSmrg } 122635c4bbdfSmrg } 122735c4bbdfSmrg } 122835c4bbdfSmrg else if (event.type == ConfigureNotify) { 122935c4bbdfSmrg if (!event.xconfigure.send_event) { 123035c4bbdfSmrg /* 123135c4bbdfSmrg Java applications using AWT on JRE 1.6.0 break with non-reparenting WMs AWT 123235c4bbdfSmrg doesn't explicitly know about (See sun bug #6434227) 123335c4bbdfSmrg 123435c4bbdfSmrg XDecoratedPeer.handleConfigureNotifyEvent() only processes non-synthetic 123535c4bbdfSmrg ConfigureNotify events to update window location if it's identified the 123635c4bbdfSmrg WM as a non-reparenting WM it knows about (compiz or lookingglass) 123735c4bbdfSmrg 123835c4bbdfSmrg Rather than tell all sorts of lies to get XWM to recognize us as one of 123935c4bbdfSmrg those, simply send a synthetic ConfigureNotify for every non-synthetic one 124035c4bbdfSmrg */ 124135c4bbdfSmrg XEvent event_send = event; 124235c4bbdfSmrg 124335c4bbdfSmrg event_send.xconfigure.send_event = TRUE; 124435c4bbdfSmrg event_send.xconfigure.event = event.xconfigure.window; 124535c4bbdfSmrg XSendEvent(event.xconfigure.display, 124635c4bbdfSmrg event.xconfigure.window, 124735c4bbdfSmrg True, StructureNotifyMask, &event_send); 124835c4bbdfSmrg } 124935c4bbdfSmrg } 125035c4bbdfSmrg else if (event.type == PropertyNotify) { 125135c4bbdfSmrg if (event.xproperty.atom == atmWmName) { 125235c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 125335c4bbdfSmrg 125435c4bbdfSmrg msg.msg = WM_WM_NAME_EVENT; 125535c4bbdfSmrg msg.iWindow = event.xproperty.window; 125635c4bbdfSmrg 125735c4bbdfSmrg /* Other fields ignored */ 125835c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 125935c4bbdfSmrg } 126035c4bbdfSmrg else { 126135c4bbdfSmrg /* 126235c4bbdfSmrg Several properties are considered for WM hints, check if this property change affects any of them... 126335c4bbdfSmrg (this list needs to be kept in sync with winApplyHints()) 126435c4bbdfSmrg */ 126535c4bbdfSmrg if ((event.xproperty.atom == atmWmHints) || 126635c4bbdfSmrg (event.xproperty.atom == atmWindowState) || 126735c4bbdfSmrg (event.xproperty.atom == atmMotifWmHints) || 126835c4bbdfSmrg (event.xproperty.atom == atmWindowType) || 126935c4bbdfSmrg (event.xproperty.atom == atmNormalHints)) { 127035c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 127135c4bbdfSmrg msg.msg = WM_WM_HINTS_EVENT; 127235c4bbdfSmrg msg.iWindow = event.xproperty.window; 127335c4bbdfSmrg 127435c4bbdfSmrg /* Other fields ignored */ 127535c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 127635c4bbdfSmrg } 127735c4bbdfSmrg 127835c4bbdfSmrg /* Not an else as WM_HINTS affects both style and icon */ 127935c4bbdfSmrg if ((event.xproperty.atom == atmWmHints) || 128035c4bbdfSmrg (event.xproperty.atom == atmNetWmIcon)) { 128135c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 128235c4bbdfSmrg msg.msg = WM_WM_ICON_EVENT; 128335c4bbdfSmrg msg.iWindow = event.xproperty.window; 128435c4bbdfSmrg 128535c4bbdfSmrg /* Other fields ignored */ 128635c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 12876747b715Smrg } 12886747b715Smrg } 12896747b715Smrg } 129035c4bbdfSmrg else if (event.type == ClientMessage 129135c4bbdfSmrg && event.xclient.message_type == atmWmChange 129235c4bbdfSmrg && event.xclient.data.l[0] == IconicState) { 129335c4bbdfSmrg ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n"); 129435c4bbdfSmrg 129535c4bbdfSmrg memset(&msg, 0, sizeof(msg)); 129635c4bbdfSmrg 129735c4bbdfSmrg msg.msg = WM_WM_CHANGE_STATE; 129835c4bbdfSmrg msg.iWindow = event.xclient.window; 129935c4bbdfSmrg 130035c4bbdfSmrg winSendMessageToWM(pProcArg->pWMInfo, &msg); 130135c4bbdfSmrg } 130205b261ecSmrg } 130305b261ecSmrg 130435c4bbdfSmrg XCloseDisplay(pProcArg->pDisplay); 130535c4bbdfSmrg pthread_exit(NULL); 130635c4bbdfSmrg return NULL; 130705b261ecSmrg} 130805b261ecSmrg 130905b261ecSmrg/* 131005b261ecSmrg * winInitWM - Entry point for the X server to spawn 131105b261ecSmrg * the Window Manager thread. Called from 131205b261ecSmrg * winscrinit.c/winFinishScreenInitFB (). 131305b261ecSmrg */ 131405b261ecSmrg 131505b261ecSmrgBool 131635c4bbdfSmrgwinInitWM(void **ppWMInfo, 131735c4bbdfSmrg pthread_t * ptWMProc, 131835c4bbdfSmrg pthread_t * ptXMsgProc, 131935c4bbdfSmrg pthread_mutex_t * ppmServerStarted, 132035c4bbdfSmrg int dwScreen, HWND hwndScreen, BOOL allowOtherWM) 132105b261ecSmrg{ 132235c4bbdfSmrg WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec)); 132335c4bbdfSmrg WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec)); 132435c4bbdfSmrg XMsgProcArgPtr pXMsgArg = malloc(sizeof(XMsgProcArgRec)); 132535c4bbdfSmrg 132635c4bbdfSmrg /* Bail if the input parameters are bad */ 132735c4bbdfSmrg if (pArg == NULL || pWMInfo == NULL || pXMsgArg == NULL) { 132835c4bbdfSmrg ErrorF("winInitWM - malloc failed.\n"); 132935c4bbdfSmrg free(pArg); 133035c4bbdfSmrg free(pWMInfo); 133135c4bbdfSmrg free(pXMsgArg); 133235c4bbdfSmrg return FALSE; 133305b261ecSmrg } 133435c4bbdfSmrg 133535c4bbdfSmrg /* Zero the allocated memory */ 133635c4bbdfSmrg ZeroMemory(pArg, sizeof(WMProcArgRec)); 133735c4bbdfSmrg ZeroMemory(pWMInfo, sizeof(WMInfoRec)); 133835c4bbdfSmrg ZeroMemory(pXMsgArg, sizeof(XMsgProcArgRec)); 133935c4bbdfSmrg 134035c4bbdfSmrg /* Set a return pointer to the Window Manager info structure */ 134135c4bbdfSmrg *ppWMInfo = pWMInfo; 134235c4bbdfSmrg pWMInfo->fAllowOtherWM = allowOtherWM; 134335c4bbdfSmrg 134435c4bbdfSmrg /* Setup the argument structure for the thread function */ 134535c4bbdfSmrg pArg->dwScreen = dwScreen; 134635c4bbdfSmrg pArg->pWMInfo = pWMInfo; 134735c4bbdfSmrg pArg->ppmServerStarted = ppmServerStarted; 134835c4bbdfSmrg 134935c4bbdfSmrg /* Intialize the message queue */ 135035c4bbdfSmrg if (!InitQueue(&pWMInfo->wmMsgQueue)) { 135135c4bbdfSmrg ErrorF("winInitWM - InitQueue () failed.\n"); 135235c4bbdfSmrg return FALSE; 135305b261ecSmrg } 135435c4bbdfSmrg 135535c4bbdfSmrg /* Spawn a thread for the Window Manager */ 135635c4bbdfSmrg if (pthread_create(ptWMProc, NULL, winMultiWindowWMProc, pArg)) { 135735c4bbdfSmrg /* Bail if thread creation failed */ 135835c4bbdfSmrg ErrorF("winInitWM - pthread_create failed for Window Manager.\n"); 135935c4bbdfSmrg return FALSE; 136005b261ecSmrg } 136105b261ecSmrg 136235c4bbdfSmrg /* Spawn the XNextEvent thread, will send messages to WM */ 136335c4bbdfSmrg pXMsgArg->dwScreen = dwScreen; 136435c4bbdfSmrg pXMsgArg->pWMInfo = pWMInfo; 136535c4bbdfSmrg pXMsgArg->ppmServerStarted = ppmServerStarted; 136635c4bbdfSmrg pXMsgArg->hwndScreen = hwndScreen; 136735c4bbdfSmrg if (pthread_create(ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg)) { 136835c4bbdfSmrg /* Bail if thread creation failed */ 136935c4bbdfSmrg ErrorF("winInitWM - pthread_create failed on XMSG.\n"); 137035c4bbdfSmrg return FALSE; 137105b261ecSmrg } 137205b261ecSmrg 137305b261ecSmrg#if CYGDEBUG || YES 137435c4bbdfSmrg winDebug("winInitWM - Returning.\n"); 137505b261ecSmrg#endif 137605b261ecSmrg 137735c4bbdfSmrg return TRUE; 137805b261ecSmrg} 137905b261ecSmrg 138005b261ecSmrg/* 138105b261ecSmrg * Window manager thread - setup 138205b261ecSmrg */ 138305b261ecSmrg 138405b261ecSmrgstatic void 138535c4bbdfSmrgwinInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) 138605b261ecSmrg{ 138735c4bbdfSmrg int iRetries = 0; 138835c4bbdfSmrg char pszDisplay[512]; 138935c4bbdfSmrg int iReturn; 139005b261ecSmrg 139135c4bbdfSmrg winDebug("winInitMultiWindowWM - Hello\n"); 139205b261ecSmrg 139335c4bbdfSmrg /* Check that argument pointer is not invalid */ 139435c4bbdfSmrg if (pProcArg == NULL) { 139535c4bbdfSmrg ErrorF("winInitMultiWindowWM - pProcArg is NULL. Exiting.\n"); 139635c4bbdfSmrg pthread_exit(NULL); 139705b261ecSmrg } 139805b261ecSmrg 139935c4bbdfSmrg ErrorF("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n"); 140005b261ecSmrg 140135c4bbdfSmrg /* Grab our garbage mutex to satisfy pthread_cond_wait */ 140235c4bbdfSmrg iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted); 140335c4bbdfSmrg if (iReturn != 0) { 140435c4bbdfSmrg ErrorF("winInitMultiWindowWM - pthread_mutex_lock () failed: %d. " 140535c4bbdfSmrg "Exiting.\n", iReturn); 140635c4bbdfSmrg pthread_exit(NULL); 140705b261ecSmrg } 140805b261ecSmrg 140935c4bbdfSmrg ErrorF("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); 141005b261ecSmrg 141135c4bbdfSmrg /* Allow multiple threads to access Xlib */ 141235c4bbdfSmrg if (XInitThreads() == 0) { 141335c4bbdfSmrg ErrorF("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n"); 141435c4bbdfSmrg pthread_exit(NULL); 141505b261ecSmrg } 141605b261ecSmrg 141735c4bbdfSmrg /* See if X supports the current locale */ 141835c4bbdfSmrg if (XSupportsLocale() == False) { 141935c4bbdfSmrg ErrorF("winInitMultiWindowWM - Warning: Locale not supported by X.\n"); 142005b261ecSmrg } 142105b261ecSmrg 142235c4bbdfSmrg /* Release the server started mutex */ 142335c4bbdfSmrg pthread_mutex_unlock(pProcArg->ppmServerStarted); 142405b261ecSmrg 142535c4bbdfSmrg ErrorF("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); 142605b261ecSmrg 142735c4bbdfSmrg /* Install our error handler */ 142835c4bbdfSmrg XSetErrorHandler(winMultiWindowWMErrorHandler); 142935c4bbdfSmrg g_winMultiWindowWMThread = pthread_self(); 143035c4bbdfSmrg g_winMultiWindowWMOldIOErrorHandler = 143135c4bbdfSmrg XSetIOErrorHandler(winMultiWindowWMIOErrorHandler); 143205b261ecSmrg 143335c4bbdfSmrg /* Set jump point for IO Error exits */ 143435c4bbdfSmrg iReturn = setjmp(g_jmpWMEntry); 143505b261ecSmrg 143635c4bbdfSmrg /* Check if we should continue operations */ 143735c4bbdfSmrg if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) { 143835c4bbdfSmrg /* setjmp returned an unknown value, exit */ 143935c4bbdfSmrg ErrorF("winInitMultiWindowWM - setjmp returned: %d. Exiting.\n", 144035c4bbdfSmrg iReturn); 144135c4bbdfSmrg pthread_exit(NULL); 144235c4bbdfSmrg } 144335c4bbdfSmrg else if (iReturn == WIN_JMP_ERROR_IO) { 144435c4bbdfSmrg ErrorF("winInitMultiWindowWM - Caught IO Error. Exiting.\n"); 144535c4bbdfSmrg pthread_exit(NULL); 144635c4bbdfSmrg } 14476747b715Smrg 144835c4bbdfSmrg /* Setup the display connection string x */ 144935c4bbdfSmrg winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen); 145035c4bbdfSmrg 145135c4bbdfSmrg /* Print the display connection string */ 145235c4bbdfSmrg ErrorF("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); 145335c4bbdfSmrg 145435c4bbdfSmrg /* Use our generated cookie for authentication */ 145535c4bbdfSmrg winSetAuthorization(); 145635c4bbdfSmrg 145735c4bbdfSmrg /* Open the X display */ 145835c4bbdfSmrg do { 145935c4bbdfSmrg /* Try to open the display */ 146035c4bbdfSmrg pWMInfo->pDisplay = XOpenDisplay(pszDisplay); 146135c4bbdfSmrg if (pWMInfo->pDisplay == NULL) { 146235c4bbdfSmrg ErrorF("winInitMultiWindowWM - Could not open display, try: %d, " 146335c4bbdfSmrg "sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY); 146435c4bbdfSmrg ++iRetries; 146535c4bbdfSmrg sleep(WIN_CONNECT_DELAY); 146635c4bbdfSmrg continue; 146735c4bbdfSmrg } 146835c4bbdfSmrg else 146935c4bbdfSmrg break; 147005b261ecSmrg } 147135c4bbdfSmrg while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); 147235c4bbdfSmrg 147335c4bbdfSmrg /* Make sure that the display opened */ 147435c4bbdfSmrg if (pWMInfo->pDisplay == NULL) { 147535c4bbdfSmrg ErrorF("winInitMultiWindowWM - Failed opening the display. " 147635c4bbdfSmrg "Exiting.\n"); 147735c4bbdfSmrg pthread_exit(NULL); 147805b261ecSmrg } 147905b261ecSmrg 148035c4bbdfSmrg ErrorF("winInitMultiWindowWM - XOpenDisplay () returned and " 148135c4bbdfSmrg "successfully opened the display.\n"); 148205b261ecSmrg 148335c4bbdfSmrg /* Create some atoms */ 148435c4bbdfSmrg pWMInfo->atmWmProtos = XInternAtom(pWMInfo->pDisplay, 148535c4bbdfSmrg "WM_PROTOCOLS", False); 148635c4bbdfSmrg pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay, 148735c4bbdfSmrg "WM_DELETE_WINDOW", False); 148835c4bbdfSmrg pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay, 148935c4bbdfSmrg "WM_TAKE_FOCUS", False); 14906747b715Smrg 149135c4bbdfSmrg pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay, 149235c4bbdfSmrg WINDOWSWM_NATIVE_HWND, False); 149305b261ecSmrg 149435c4bbdfSmrg if (1) { 149535c4bbdfSmrg Cursor cursor = XCreateFontCursor(pWMInfo->pDisplay, XC_left_ptr); 149605b261ecSmrg 149735c4bbdfSmrg if (cursor) { 149835c4bbdfSmrg XDefineCursor(pWMInfo->pDisplay, 149935c4bbdfSmrg DefaultRootWindow(pWMInfo->pDisplay), cursor); 150035c4bbdfSmrg XFreeCursor(pWMInfo->pDisplay, cursor); 150135c4bbdfSmrg } 150205b261ecSmrg } 150305b261ecSmrg} 150405b261ecSmrg 150505b261ecSmrg/* 150605b261ecSmrg * winSendMessageToWM - Send a message from the X thread to the WM thread 150705b261ecSmrg */ 150805b261ecSmrg 150905b261ecSmrgvoid 151035c4bbdfSmrgwinSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg) 151105b261ecSmrg{ 151235c4bbdfSmrg WMMsgNodePtr pNode; 151335c4bbdfSmrg 151405b261ecSmrg#if CYGMULTIWINDOW_DEBUG 151535c4bbdfSmrg ErrorF("winSendMessageToWM ()\n"); 151605b261ecSmrg#endif 151735c4bbdfSmrg 151835c4bbdfSmrg pNode = malloc(sizeof(WMMsgNodeRec)); 151935c4bbdfSmrg if (pNode != NULL) { 152035c4bbdfSmrg memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec)); 152135c4bbdfSmrg PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode); 152205b261ecSmrg } 152305b261ecSmrg} 152405b261ecSmrg 152505b261ecSmrg/* 152605b261ecSmrg * Window manager error handler 152705b261ecSmrg */ 152805b261ecSmrg 152905b261ecSmrgstatic int 153035c4bbdfSmrgwinMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr) 153105b261ecSmrg{ 153235c4bbdfSmrg char pszErrorMsg[100]; 153305b261ecSmrg 153435c4bbdfSmrg if (pErr->request_code == X_ChangeWindowAttributes 153535c4bbdfSmrg && pErr->error_code == BadAccess) { 153635c4bbdfSmrg ErrorF("winMultiWindowWMErrorHandler - ChangeWindowAttributes " 153735c4bbdfSmrg "BadAccess.\n"); 153835c4bbdfSmrg return 0; 153905b261ecSmrg } 154005b261ecSmrg 154135c4bbdfSmrg XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg)); 154235c4bbdfSmrg ErrorF("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg); 154335c4bbdfSmrg 154435c4bbdfSmrg return 0; 154535c4bbdfSmrg} 154605b261ecSmrg 154705b261ecSmrg/* 154805b261ecSmrg * Window manager IO error handler 154905b261ecSmrg */ 155005b261ecSmrg 155105b261ecSmrgstatic int 155235c4bbdfSmrgwinMultiWindowWMIOErrorHandler(Display * pDisplay) 155305b261ecSmrg{ 155435c4bbdfSmrg ErrorF("winMultiWindowWMIOErrorHandler!\n"); 155505b261ecSmrg 155635c4bbdfSmrg if (pthread_equal(pthread_self(), g_winMultiWindowWMThread)) { 155735c4bbdfSmrg if (g_shutdown) 155835c4bbdfSmrg pthread_exit(NULL); 155905b261ecSmrg 156035c4bbdfSmrg /* Restart at the main entry point */ 156135c4bbdfSmrg longjmp(g_jmpWMEntry, WIN_JMP_ERROR_IO); 156235c4bbdfSmrg } 156305b261ecSmrg 156435c4bbdfSmrg if (g_winMultiWindowWMOldIOErrorHandler) 156535c4bbdfSmrg g_winMultiWindowWMOldIOErrorHandler(pDisplay); 156635c4bbdfSmrg 156735c4bbdfSmrg return 0; 156835c4bbdfSmrg} 156905b261ecSmrg 157005b261ecSmrg/* 157105b261ecSmrg * X message procedure error handler 157205b261ecSmrg */ 157305b261ecSmrg 157405b261ecSmrgstatic int 157535c4bbdfSmrgwinMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr) 157605b261ecSmrg{ 157735c4bbdfSmrg char pszErrorMsg[100]; 157835c4bbdfSmrg 157935c4bbdfSmrg XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg)); 15806747b715Smrg#if CYGMULTIWINDOW_DEBUG 158135c4bbdfSmrg ErrorF("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg); 15826747b715Smrg#endif 158305b261ecSmrg 158435c4bbdfSmrg return 0; 158535c4bbdfSmrg} 158605b261ecSmrg 158705b261ecSmrg/* 158805b261ecSmrg * X message procedure IO error handler 158905b261ecSmrg */ 159005b261ecSmrg 159105b261ecSmrgstatic int 159235c4bbdfSmrgwinMultiWindowXMsgProcIOErrorHandler(Display * pDisplay) 159305b261ecSmrg{ 159435c4bbdfSmrg ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n"); 159505b261ecSmrg 159635c4bbdfSmrg if (pthread_equal(pthread_self(), g_winMultiWindowXMsgProcThread)) { 159735c4bbdfSmrg /* Restart at the main entry point */ 159835c4bbdfSmrg longjmp(g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO); 159935c4bbdfSmrg } 160005b261ecSmrg 160135c4bbdfSmrg if (g_winMultiWindowXMsgProcOldIOErrorHandler) 160235c4bbdfSmrg g_winMultiWindowXMsgProcOldIOErrorHandler(pDisplay); 160335c4bbdfSmrg 160435c4bbdfSmrg return 0; 160535c4bbdfSmrg} 160605b261ecSmrg 160705b261ecSmrg/* 160805b261ecSmrg * Catch RedirectError to detect other window manager running 160905b261ecSmrg */ 161005b261ecSmrg 161105b261ecSmrgstatic int 161235c4bbdfSmrgwinRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr) 161305b261ecSmrg{ 161435c4bbdfSmrg redirectError = TRUE; 161535c4bbdfSmrg return 0; 161605b261ecSmrg} 161705b261ecSmrg 161805b261ecSmrg/* 161905b261ecSmrg * Check if another window manager is running 162005b261ecSmrg */ 162105b261ecSmrg 162205b261ecSmrgstatic Bool 162335c4bbdfSmrgCheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen, 162435c4bbdfSmrg Bool fAllowOtherWM) 162505b261ecSmrg{ 162635c4bbdfSmrg /* 162735c4bbdfSmrg Try to select the events which only one client at a time is allowed to select. 162835c4bbdfSmrg If this causes an error, another window manager is already running... 162935c4bbdfSmrg */ 163035c4bbdfSmrg redirectError = FALSE; 163135c4bbdfSmrg XSetErrorHandler(winRedirectErrorHandler); 163235c4bbdfSmrg XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen), 163335c4bbdfSmrg ResizeRedirectMask | SubstructureRedirectMask | 163435c4bbdfSmrg ButtonPressMask); 163535c4bbdfSmrg XSync(pDisplay, 0); 163635c4bbdfSmrg XSetErrorHandler(winMultiWindowXMsgProcErrorHandler); 163735c4bbdfSmrg 163835c4bbdfSmrg /* 163935c4bbdfSmrg Side effect: select the events we are actually interested in... 164035c4bbdfSmrg 164135c4bbdfSmrg If other WMs are not allowed, also select one of the events which only one client 164235c4bbdfSmrg at a time is allowed to select, so other window managers won't start... 164335c4bbdfSmrg */ 164435c4bbdfSmrg XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen), 164535c4bbdfSmrg SubstructureNotifyMask | (!fAllowOtherWM ? ButtonPressMask : 164635c4bbdfSmrg 0)); 164735c4bbdfSmrg XSync(pDisplay, 0); 164835c4bbdfSmrg return redirectError; 164905b261ecSmrg} 165005b261ecSmrg 165105b261ecSmrg/* 165205b261ecSmrg * Notify the MWM thread we're exiting and not to reconnect 165305b261ecSmrg */ 165405b261ecSmrg 165505b261ecSmrgvoid 165635c4bbdfSmrgwinDeinitMultiWindowWM(void) 165705b261ecSmrg{ 165835c4bbdfSmrg ErrorF("winDeinitMultiWindowWM - Noting shutdown in progress\n"); 165935c4bbdfSmrg g_shutdown = TRUE; 166005b261ecSmrg} 16616747b715Smrg 16626747b715Smrg/* Windows window styles */ 166335c4bbdfSmrg#define HINT_NOFRAME (1L<<0) 16646747b715Smrg#define HINT_BORDER (1L<<1) 166535c4bbdfSmrg#define HINT_SIZEBOX (1L<<2) 166635c4bbdfSmrg#define HINT_CAPTION (1L<<3) 16676747b715Smrg#define HINT_NOMAXIMIZE (1L<<4) 166835c4bbdfSmrg#define HINT_NOMINIMIZE (1L<<5) 166935c4bbdfSmrg#define HINT_NOSYSMENU (1L<<6) 167035c4bbdfSmrg#define HINT_SKIPTASKBAR (1L<<7) 16716747b715Smrg/* These two are used on their own */ 16726747b715Smrg#define HINT_MAX (1L<<0) 16736747b715Smrg#define HINT_MIN (1L<<1) 16746747b715Smrg 16756747b715Smrgstatic void 167635c4bbdfSmrgwinApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) 16776747b715Smrg{ 167835c4bbdfSmrg static Atom windowState, motif_wm_hints, windowType; 167935c4bbdfSmrg static Atom hiddenState, fullscreenState, belowState, aboveState, 168035c4bbdfSmrg skiptaskbarState; 168135c4bbdfSmrg static Atom dockWindow; 168235c4bbdfSmrg static int generation; 168335c4bbdfSmrg Atom type, *pAtom = NULL; 168435c4bbdfSmrg int format; 168535c4bbdfSmrg unsigned long hint = 0, maxmin = 0, nitems = 0, left = 0; 168635c4bbdfSmrg unsigned long style, exStyle; 168735c4bbdfSmrg MwmHints *mwm_hint = NULL; 168835c4bbdfSmrg 168935c4bbdfSmrg if (!hWnd) 169035c4bbdfSmrg return; 169135c4bbdfSmrg if (!IsWindow(hWnd)) 169235c4bbdfSmrg return; 169335c4bbdfSmrg 169435c4bbdfSmrg if (generation != serverGeneration) { 169535c4bbdfSmrg generation = serverGeneration; 169635c4bbdfSmrg windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False); 169735c4bbdfSmrg motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False); 169835c4bbdfSmrg windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False); 169935c4bbdfSmrg hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False); 170035c4bbdfSmrg fullscreenState = 170135c4bbdfSmrg XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False); 170235c4bbdfSmrg belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False); 170335c4bbdfSmrg aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False); 170435c4bbdfSmrg dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False); 170535c4bbdfSmrg skiptaskbarState = 170635c4bbdfSmrg XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", False); 170735c4bbdfSmrg } 17086747b715Smrg 170935c4bbdfSmrg if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, 171035c4bbdfSmrg MAXINT, False, XA_ATOM, &type, &format, 171135c4bbdfSmrg &nitems, &left, 171235c4bbdfSmrg (unsigned char **) &pAtom) == Success) { 171335c4bbdfSmrg if (pAtom ) { 171435c4bbdfSmrg unsigned long i; 171535c4bbdfSmrg 171635c4bbdfSmrg for (i = 0; i < nitems; i++) { 171735c4bbdfSmrg if (pAtom[i] == skiptaskbarState) 171835c4bbdfSmrg hint |= HINT_SKIPTASKBAR; 171935c4bbdfSmrg if (pAtom[i] == hiddenState) 172035c4bbdfSmrg maxmin |= HINT_MIN; 172135c4bbdfSmrg else if (pAtom[i] == fullscreenState) 172235c4bbdfSmrg maxmin |= HINT_MAX; 172335c4bbdfSmrg if (pAtom[i] == belowState) 172435c4bbdfSmrg *zstyle = HWND_BOTTOM; 172535c4bbdfSmrg else if (pAtom[i] == aboveState) 172635c4bbdfSmrg *zstyle = HWND_TOPMOST; 172735c4bbdfSmrg } 172835c4bbdfSmrg 172935c4bbdfSmrg XFree(pAtom); 173035c4bbdfSmrg } 17316747b715Smrg } 17326747b715Smrg 173335c4bbdfSmrg nitems = left = 0; 173435c4bbdfSmrg if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L, 173535c4bbdfSmrg PropMwmHintsElements, False, motif_wm_hints, &type, 173635c4bbdfSmrg &format, &nitems, &left, 173735c4bbdfSmrg (unsigned char **) &mwm_hint) == Success) { 173835c4bbdfSmrg if (mwm_hint && nitems == PropMwmHintsElements && 173935c4bbdfSmrg (mwm_hint->flags & MwmHintsDecorations)) { 174035c4bbdfSmrg if (!mwm_hint->decorations) 174135c4bbdfSmrg hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); 174235c4bbdfSmrg else if (!(mwm_hint->decorations & MwmDecorAll)) { 174335c4bbdfSmrg if (mwm_hint->decorations & MwmDecorBorder) 174435c4bbdfSmrg hint |= HINT_BORDER; 174535c4bbdfSmrg if (mwm_hint->decorations & MwmDecorHandle) 174635c4bbdfSmrg hint |= HINT_SIZEBOX; 174735c4bbdfSmrg if (mwm_hint->decorations & MwmDecorTitle) 174835c4bbdfSmrg hint |= HINT_CAPTION; 174935c4bbdfSmrg if (!(mwm_hint->decorations & MwmDecorMenu)) 175035c4bbdfSmrg hint |= HINT_NOSYSMENU; 175135c4bbdfSmrg if (!(mwm_hint->decorations & MwmDecorMinimize)) 175235c4bbdfSmrg hint |= HINT_NOMINIMIZE; 175335c4bbdfSmrg if (!(mwm_hint->decorations & MwmDecorMaximize)) 175435c4bbdfSmrg hint |= HINT_NOMAXIMIZE; 175535c4bbdfSmrg } 175635c4bbdfSmrg else { 175735c4bbdfSmrg /* 175835c4bbdfSmrg MwmDecorAll means all decorations *except* those specified by other flag 175935c4bbdfSmrg bits that are set. Not yet implemented. 176035c4bbdfSmrg */ 176135c4bbdfSmrg } 176235c4bbdfSmrg } 176335c4bbdfSmrg if (mwm_hint) 176435c4bbdfSmrg XFree(mwm_hint); 176535c4bbdfSmrg } 176635c4bbdfSmrg 176735c4bbdfSmrg nitems = left = 0; 176835c4bbdfSmrg pAtom = NULL; 176935c4bbdfSmrg if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L, 177035c4bbdfSmrg 1L, False, XA_ATOM, &type, &format, 177135c4bbdfSmrg &nitems, &left, 177235c4bbdfSmrg (unsigned char **) &pAtom) == Success) { 177335c4bbdfSmrg if (pAtom && nitems == 1) { 177435c4bbdfSmrg if (*pAtom == dockWindow) { 177535c4bbdfSmrg hint = (hint & ~HINT_NOFRAME) | HINT_SKIPTASKBAR | HINT_SIZEBOX; 177635c4bbdfSmrg *zstyle = HWND_TOPMOST; 177735c4bbdfSmrg } 177835c4bbdfSmrg } 177935c4bbdfSmrg if (pAtom) 178035c4bbdfSmrg XFree(pAtom); 17816747b715Smrg } 17826747b715Smrg 17836747b715Smrg { 178435c4bbdfSmrg XSizeHints *normal_hint = XAllocSizeHints(); 178535c4bbdfSmrg long supplied; 178635c4bbdfSmrg 178735c4bbdfSmrg if (normal_hint && 178835c4bbdfSmrg XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied)) { 178935c4bbdfSmrg if (normal_hint->flags & PMaxSize) { 179035c4bbdfSmrg /* Not maximizable if a maximum size is specified */ 179135c4bbdfSmrg hint |= HINT_NOMAXIMIZE; 179235c4bbdfSmrg 179335c4bbdfSmrg if (normal_hint->flags & PMinSize) { 179435c4bbdfSmrg /* 179535c4bbdfSmrg If both minimum size and maximum size are specified and are the same, 179635c4bbdfSmrg don't bother with a resizing frame 179735c4bbdfSmrg */ 179835c4bbdfSmrg if ((normal_hint->min_width == normal_hint->max_width) 179935c4bbdfSmrg && (normal_hint->min_height == normal_hint->max_height)) 180035c4bbdfSmrg hint = (hint & ~HINT_SIZEBOX); 180135c4bbdfSmrg } 180235c4bbdfSmrg } 180335c4bbdfSmrg } 180435c4bbdfSmrg XFree(normal_hint); 18056747b715Smrg } 18066747b715Smrg 180735c4bbdfSmrg /* 180835c4bbdfSmrg Override hint settings from above with settings from config file and set 180935c4bbdfSmrg application id for grouping. 181035c4bbdfSmrg */ 181135c4bbdfSmrg { 181235c4bbdfSmrg XClassHint class_hint = { 0, 0 }; 181335c4bbdfSmrg char *window_name = 0; 181435c4bbdfSmrg char *application_id = 0; 181535c4bbdfSmrg 181635c4bbdfSmrg if (XGetClassHint(pDisplay, iWindow, &class_hint)) { 181735c4bbdfSmrg XFetchName(pDisplay, iWindow, &window_name); 181835c4bbdfSmrg 181935c4bbdfSmrg style = 182035c4bbdfSmrg winOverrideStyle(class_hint.res_name, class_hint.res_class, 182135c4bbdfSmrg window_name); 182235c4bbdfSmrg 182335c4bbdfSmrg#define APPLICATION_ID_FORMAT "%s.xwin.%s" 182435c4bbdfSmrg#define APPLICATION_ID_UNKNOWN "unknown" 182535c4bbdfSmrg if (class_hint.res_class) { 182635c4bbdfSmrg asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME, 182735c4bbdfSmrg class_hint.res_class); 182835c4bbdfSmrg } 182935c4bbdfSmrg else { 183035c4bbdfSmrg asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME, 183135c4bbdfSmrg APPLICATION_ID_UNKNOWN); 183235c4bbdfSmrg } 183335c4bbdfSmrg winSetAppUserModelID(hWnd, application_id); 183435c4bbdfSmrg 183535c4bbdfSmrg if (class_hint.res_name) 183635c4bbdfSmrg XFree(class_hint.res_name); 183735c4bbdfSmrg if (class_hint.res_class) 183835c4bbdfSmrg XFree(class_hint.res_class); 183935c4bbdfSmrg if (application_id) 184035c4bbdfSmrg free(application_id); 184135c4bbdfSmrg if (window_name) 184235c4bbdfSmrg XFree(window_name); 184335c4bbdfSmrg } 184435c4bbdfSmrg else { 184535c4bbdfSmrg style = STYLE_NONE; 184635c4bbdfSmrg } 184735c4bbdfSmrg } 18486747b715Smrg 184935c4bbdfSmrg if (style & STYLE_TOPMOST) 185035c4bbdfSmrg *zstyle = HWND_TOPMOST; 185135c4bbdfSmrg else if (style & STYLE_MAXIMIZE) 185235c4bbdfSmrg maxmin = (hint & ~HINT_MIN) | HINT_MAX; 185335c4bbdfSmrg else if (style & STYLE_MINIMIZE) 185435c4bbdfSmrg maxmin = (hint & ~HINT_MAX) | HINT_MIN; 185535c4bbdfSmrg else if (style & STYLE_BOTTOM) 185635c4bbdfSmrg *zstyle = HWND_BOTTOM; 185735c4bbdfSmrg 185835c4bbdfSmrg if (maxmin & HINT_MAX) 185935c4bbdfSmrg SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); 186035c4bbdfSmrg else if (maxmin & HINT_MIN) 186135c4bbdfSmrg SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); 186235c4bbdfSmrg 186335c4bbdfSmrg if (style & STYLE_NOTITLE) 186435c4bbdfSmrg hint = 186535c4bbdfSmrg (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) | 186635c4bbdfSmrg HINT_SIZEBOX; 186735c4bbdfSmrg else if (style & STYLE_OUTLINE) 186835c4bbdfSmrg hint = 186935c4bbdfSmrg (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) | 187035c4bbdfSmrg HINT_BORDER; 187135c4bbdfSmrg else if (style & STYLE_NOFRAME) 187235c4bbdfSmrg hint = 187335c4bbdfSmrg (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | 187435c4bbdfSmrg HINT_NOFRAME; 187535c4bbdfSmrg 187635c4bbdfSmrg /* Now apply styles to window */ 187735c4bbdfSmrg style = GetWindowLongPtr(hWnd, GWL_STYLE); 187835c4bbdfSmrg if (!style) 187935c4bbdfSmrg return; /* GetWindowLongPointer returns 0 on failure, we hope this isn't a valid style */ 188035c4bbdfSmrg 188135c4bbdfSmrg style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ 188235c4bbdfSmrg 188335c4bbdfSmrg if (!(hint & ~HINT_SKIPTASKBAR)) /* No hints, default */ 188435c4bbdfSmrg style = style | WS_CAPTION | WS_SIZEBOX; 188535c4bbdfSmrg else if (hint & HINT_NOFRAME) /* No frame, no decorations */ 188635c4bbdfSmrg style = style & ~WS_CAPTION & ~WS_SIZEBOX; 188735c4bbdfSmrg else 188835c4bbdfSmrg style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) | 188935c4bbdfSmrg ((hint & HINT_SIZEBOX) ? WS_SIZEBOX : 0) | 189035c4bbdfSmrg ((hint & HINT_CAPTION) ? WS_CAPTION : 0); 189135c4bbdfSmrg 189235c4bbdfSmrg if (hint & HINT_NOMAXIMIZE) 189335c4bbdfSmrg style = style & ~WS_MAXIMIZEBOX; 189435c4bbdfSmrg 189535c4bbdfSmrg if (hint & HINT_NOMINIMIZE) 189635c4bbdfSmrg style = style & ~WS_MINIMIZEBOX; 189735c4bbdfSmrg 189835c4bbdfSmrg if (hint & HINT_NOSYSMENU) 189935c4bbdfSmrg style = style & ~WS_SYSMENU; 190035c4bbdfSmrg 190135c4bbdfSmrg if (hint & HINT_SKIPTASKBAR) 190235c4bbdfSmrg style = style & ~WS_MINIMIZEBOX; /* window will become lost if minimized */ 190335c4bbdfSmrg 190435c4bbdfSmrg SetWindowLongPtr(hWnd, GWL_STYLE, style); 190535c4bbdfSmrg 190635c4bbdfSmrg exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); 190735c4bbdfSmrg if (hint & HINT_SKIPTASKBAR) 190835c4bbdfSmrg exStyle = (exStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW; 190935c4bbdfSmrg else 191035c4bbdfSmrg exStyle = (exStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW; 191135c4bbdfSmrg SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle); 191235c4bbdfSmrg 191335c4bbdfSmrg winDebug 191435c4bbdfSmrg ("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n", 191535c4bbdfSmrg iWindow, hint, style, exStyle); 19166747b715Smrg} 19176747b715Smrg 19186747b715Smrgvoid 191935c4bbdfSmrgwinUpdateWindowPosition(HWND hWnd, HWND * zstyle) 19206747b715Smrg{ 192135c4bbdfSmrg int iX, iY, iWidth, iHeight; 192235c4bbdfSmrg int iDx, iDy; 192335c4bbdfSmrg RECT rcNew; 192435c4bbdfSmrg WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP); 192535c4bbdfSmrg DrawablePtr pDraw = NULL; 192635c4bbdfSmrg 192735c4bbdfSmrg if (!pWin) 192835c4bbdfSmrg return; 192935c4bbdfSmrg pDraw = &pWin->drawable; 193035c4bbdfSmrg if (!pDraw) 193135c4bbdfSmrg return; 193235c4bbdfSmrg 193335c4bbdfSmrg /* Get the X and Y location of the X window */ 193435c4bbdfSmrg iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); 193535c4bbdfSmrg iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); 193635c4bbdfSmrg 193735c4bbdfSmrg /* Get the height and width of the X window */ 193835c4bbdfSmrg iWidth = pWin->drawable.width; 193935c4bbdfSmrg iHeight = pWin->drawable.height; 194035c4bbdfSmrg 194135c4bbdfSmrg /* Setup a rectangle with the X window position and size */ 194235c4bbdfSmrg SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight); 194335c4bbdfSmrg 194435c4bbdfSmrg winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n", 194535c4bbdfSmrg rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); 194635c4bbdfSmrg 194735c4bbdfSmrg AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE, 194835c4bbdfSmrg GetWindowLongPtr(hWnd, GWL_EXSTYLE)); 194935c4bbdfSmrg 195035c4bbdfSmrg /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */ 195135c4bbdfSmrg if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) { 195235c4bbdfSmrg iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left; 195335c4bbdfSmrg rcNew.left += iDx; 195435c4bbdfSmrg rcNew.right += iDx; 19556747b715Smrg } 19566747b715Smrg 195735c4bbdfSmrg if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) { 195835c4bbdfSmrg iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top; 195935c4bbdfSmrg rcNew.top += iDy; 196035c4bbdfSmrg rcNew.bottom += iDy; 19616747b715Smrg } 19626747b715Smrg 196335c4bbdfSmrg winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n", 196435c4bbdfSmrg rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); 19656747b715Smrg 196635c4bbdfSmrg /* Position the Windows window */ 196735c4bbdfSmrg SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top, 196835c4bbdfSmrg rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0); 19696747b715Smrg 19706747b715Smrg} 1971