diff options
Diffstat (limited to 'hw/xwin/winmultiwindowwm.c')
-rw-r--r-- | hw/xwin/winmultiwindowwm.c | 458 |
1 files changed, 367 insertions, 91 deletions
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index ab4dd27f6..a60d36135 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -27,7 +27,7 @@ * * Authors: Kensuke Matsuzaki */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winmultiwindowwm.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winmultiwindowwm.c,v 1.3 2003/10/02 13:30:11 eich Exp $ */ /* X headers */ #include <stdio.h> @@ -61,7 +61,6 @@ #define WIN_CONNECT_RETRIES 5 #define WIN_CONNECT_DELAY 5 #define WIN_MSG_QUEUE_FNAME "/dev/windows" -#define WM_WM_X_EVENT 1 #define WIN_JMP_OKAY 0 #define WIN_JMP_ERROR_IO 2 @@ -87,6 +86,7 @@ typedef struct _WMInfo { WMMsgQueueRec wmMsgQueue; Atom atmWmProtos; Atom atmWmDelete; + Atom atmPrivMap; } WMInfoRec, *WMInfoPtr; typedef struct _WMProcArgRec { @@ -95,6 +95,13 @@ typedef struct _WMProcArgRec { pthread_mutex_t *ppmServerStarted; } WMProcArgRec, *WMProcArgPtr; +typedef struct _XMsgProcArgRec { + Display *pDisplay; + DWORD dwScreen; + WMInfoPtr pWMInfo; + pthread_mutex_t *ppmServerStarted; +} XMsgProcArgRec, *XMsgProcArgPtr; + /* * References to external symbols @@ -103,6 +110,7 @@ typedef struct _WMProcArgRec { extern char *display; extern void ErrorF (const char* /*f*/, ...); extern Bool g_fCalledSetLocale; +extern Bool g_fCalledXInitThreads; /* @@ -113,7 +121,7 @@ static void PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode); static WMMsgNodePtr -PopMessage (WMMsgQueuePtr pQueue); +PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo); static Bool InitQueue (WMMsgQueuePtr pQueue); @@ -124,15 +132,18 @@ GetWindowName (Display * pDpy, Window iWin, char **ppName); static int SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData); +static void +UpdateName (WMInfoPtr pWMInfo, Window iWindow); + static void* winMultiWindowWMProc (void* pArg); -static Bool -FlushXEvents (WMInfoPtr pWMInfo); - static int winMultiWindowWMErrorHandler (Display *pDisp, XErrorEvent *e); +static void * +winMultiWindowXMsgProc (void *pArg); + static void winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg); @@ -146,6 +157,7 @@ winMutliWindowWMIOErrorHandler (Display *pDisplay); static int g_nQueueSize; static jmp_buf g_jmpEntry; +static Bool g_shutdown = FALSE; @@ -212,7 +224,7 @@ PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) } -#if 0 +#if CYGMULTIWINDOW_DEBUG /* * QueueSize - Return the size of the queue */ @@ -233,11 +245,11 @@ QueueSize (WMMsgQueuePtr pQueue) /* - * PopMessage - + * PopMessage - Pop a message from the queue */ static WMMsgNodePtr -PopMessage (WMMsgQueuePtr pQueue) +PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo) { WMMsgNodePtr pNode; @@ -339,7 +351,7 @@ InitQueue (WMMsgQueuePtr pQueue) /* - * GetWindowName - + * GetWindowName - Retrieve the title of an X Window */ static void @@ -360,7 +372,9 @@ GetWindowName (Display *pDisplay, Window iWin, char **ppName) nResult = XGetWMName (pDisplay, iWin, &xtpName); if (!nResult || !xtpName.value || !xtpName.nitems) { +#if CYGMULTIWINDOW_DEBUG ErrorF ("GetWindowName - XGetWMName failed. No name.\n"); +#endif return; } @@ -375,7 +389,7 @@ GetWindowName (Display *pDisplay, Window iWin, char **ppName) } #if CYGMULTIWINDOW_DEBUG - ErrorF ("XA_STRING %s\n", *ppName); + ErrorF ("GetWindowName - XA_STRING %s\n", *ppName); #endif } else @@ -383,7 +397,7 @@ GetWindowName (Display *pDisplay, Window iWin, char **ppName) XmbTextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum); /* */ - if (nNum && *ppList) + if (nNum && ppList && *ppList) { XFree (xtpName.value); *ppName = strdup (*ppList); @@ -391,13 +405,14 @@ GetWindowName (Display *pDisplay, Window iWin, char **ppName) } #if CYGMULTIWINDOW_DEBUG - ErrorF ("%s %s\n", XGetAtomName (pDisplay, xtpName.encoding), *ppName); + ErrorF ("GetWindowName - %s %s\n", + XGetAtomName (pDisplay, xtpName.encoding), *ppName); #endif } #if CYGMULTIWINDOW_DEBUG - ErrorF ("-GetWindowName\n"); + ErrorF ("GetWindowName - Returning\n"); #endif } @@ -425,6 +440,66 @@ SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData) /* + * Updates the name of a HWND according to its X WM_NAME property + */ + +static void +UpdateName (WMInfoPtr pWMInfo, Window iWindow) +{ + char *pszName; + Atom atmType; + int fmtRet; + unsigned long items, remain; + HWND *retHwnd, hWnd; + XWindowAttributes attr; + + hWnd = 0; + + /* See if we can get the cached HWND for this window... */ + if (XGetWindowProperty (pWMInfo->pDisplay, + iWindow, + pWMInfo->atmPrivMap, + 0, + 1, + False, + pWMInfo->atmPrivMap, + &atmType, + &fmtRet, + &items, + &remain, + (unsigned char **) &retHwnd) == Success) + { + if (retHwnd) + { + hWnd = *retHwnd; + XFree (retHwnd); + } + } + + /* Some sanity checks */ + if (!hWnd) return; + if (!IsWindow (hWnd)) return; + + /* Set the Windows window name */ + GetWindowName (pWMInfo->pDisplay, iWindow, &pszName); + if (pszName) + { + /* Get the window attributes */ + XGetWindowAttributes (pWMInfo->pDisplay, + iWindow, + &attr); + if (!attr.override_redirect) + { + SetWindowText (hWnd, pszName); + winUpdateIcon (iWindow); + } + + free (pszName); + } +} + + +/* * winMultiWindowWMProc */ @@ -447,7 +522,7 @@ winMultiWindowWMProc (void *pArg) WMMsgNodePtr pNode; /* Pop a message off of our queue */ - pNode = PopMessage (&pWMInfo->wmMsgQueue); + pNode = PopMessage (&pWMInfo->wmMsgQueue, pWMInfo); if (pNode == NULL) { /* Bail if PopMessage returns without a message */ @@ -496,25 +571,17 @@ winMultiWindowWMProc (void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF ("\tWM_WM_MAP\n"); #endif - { - XWindowAttributes attr; - char *pszName; -#if 0 - XWMHints *pHints; -#endif - - /* Get the window attributes */ - XGetWindowAttributes (pWMInfo->pDisplay, - pNode->msg.iWindow, - &attr); - if (!attr.override_redirect) - { - /* Set the Windows window name */ - GetWindowName(pWMInfo->pDisplay, pNode->msg.iWindow, &pszName); - SetWindowText (pNode->msg.hwndWindow, pszName); - free (pszName); - } - } + /* Put a note as to the HWND associated with this Window */ + XChangeProperty (pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmPrivMap, + pWMInfo->atmPrivMap, + 32, + PropModeReplace, + (unsigned char *) &(pNode->msg.hwndWindow), + 1); + UpdateName (pWMInfo, pNode->msg.iWindow); + winUpdateIcon (pNode->msg.iWindow); break; case WM_WM_UNMAP: @@ -523,7 +590,7 @@ winMultiWindowWMProc (void *pArg) #endif /* Unmap the window */ - XUnmapWindow(pWMInfo->pDisplay, pNode->msg.iWindow); + XUnmapWindow (pWMInfo->pDisplay, pNode->msg.iWindow); break; case WM_WM_KILL: @@ -571,9 +638,17 @@ winMultiWindowWMProc (void *pArg) CurrentTime); break; - case WM_WM_X_EVENT: - /* Process all X events in the Window Manager event queue */ - FlushXEvents (pWMInfo); + case WM_WM_NAME_EVENT: + UpdateName (pWMInfo, pNode->msg.iWindow); + break; + + case WM_WM_HINTS_EVENT: + winUpdateIcon (pNode->msg.iWindow); + break; + + case WM_WM_CHANGE_STATE: + /* Minimize the window in Windows */ + winMinimizeWindow (pNode->msg.iWindow); break; default: @@ -605,71 +680,227 @@ winMultiWindowWMProc (void *pArg) /* - * FlushXEvents - Process any pending X events + * winMultiWindowWMErrorHandler - Our application specific error handler */ -static Bool -FlushXEvents (WMInfoPtr pWMInfo) +static int +winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr) { - XEvent event; - -#if CYGMULTIWINDOW_DEBUG - ErrorF ("FlushXEvents ()\n"); -#endif + char pszErrorMsg[100]; - /* Process all pending events */ - while (XPending (pWMInfo->pDisplay)) + if (pErr->request_code == X_ChangeWindowAttributes + && pErr->error_code == BadAccess) { - /* Get the next event - will not block because one is ready */ - XNextEvent (pWMInfo->pDisplay, &event); - + ErrorF ("winMultiWindowWMErrorHandler - ChangeWindowAttributes " + "BadAccess.\n"); #if 0 - /* Branch on the event type */ - switch (event.type) - { - } + pthread_exit (NULL); #endif + return 0; } + + XGetErrorText (pDisplay, + pErr->error_code, + pszErrorMsg, + sizeof (pszErrorMsg)); + ErrorF ("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg); -#if CYGMULTIWINDOW_DEBUG - ErrorF ("-FlushXEvents ()\n"); + if (pErr->error_code == BadWindow + || pErr->error_code == BadMatch + || pErr->error_code == BadDrawable) + { +#if 0 + pthread_exit (NULL); #endif + return 0; + } - return True; + pthread_exit (NULL); + return 0; } /* - * winMultiWindowWMErrorHandler - Our application specific error handler + * */ -static int -winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr) +static void * +winMultiWindowXMsgProc (void *pArg) { - char pszErrorMsg[100]; + winWMMessageRec msg; + XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg; + char pszDisplay[512]; + int iRetries; + XEvent event; + Atom atmWmName; + Atom atmWmHints; + Atom atmWmChange; + int iReturn; + XIconSize *xis; - if (pErr->request_code == X_ChangeWindowAttributes - && pErr->error_code == BadAccess) + ErrorF ("winMultiWindowXMsgProc - Hello\n"); + + /* Check that argument pointer is not invalid */ + if (pProcArg == NULL) { - ErrorF ("ChangeWindowAttributes BadAccess.\n"); + ErrorF ("winMultiWindowXMsgProc - pProcArg is NULL, bailing.\n"); pthread_exit (NULL); } + + ErrorF ("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n"); + + /* Grab the server started mutex - pause until we get it */ + iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted); + if (iReturn != 0) + { + ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () failed: %d\n", + iReturn); + pthread_exit (NULL); + } + + ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); + + /* Only call XInitThreads once for the whole process */ + if (!g_fCalledXInitThreads) + { + /* Allow multiple threads to access Xlib */ + if (XInitThreads () == 0) + { + ErrorF ("winMultiWindowXMsgProc - XInitThreads () failed.\n"); + pthread_exit (NULL); + } + + /* Flag that XInitThreads has been called */ + g_fCalledXInitThreads = TRUE; + + ErrorF ("winMultiWindowXMsgProc - XInitThreads () returned.\n"); + } + + /* Release the server started mutex */ + pthread_mutex_unlock (pProcArg->ppmServerStarted); + + ErrorF ("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n"); + + /* Setup the display connection string x */ + snprintf (pszDisplay, + 512, "127.0.0.1:%s.%d", display, (int)pProcArg->dwScreen); + + /* Print the display connection string */ + ErrorF ("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay); - XGetErrorText (pDisplay, - pErr->error_code, - pszErrorMsg, - sizeof (pszErrorMsg)); - ErrorF ("ERROR: %s\n", pszErrorMsg); + iRetries = 0; - if (pErr->error_code==BadWindow - || pErr->error_code==BadMatch - || pErr->error_code==BadDrawable) + /* Open the X display */ + do { + /* Try to open the display */ + pProcArg->pDisplay = XOpenDisplay (pszDisplay); + if (pProcArg->pDisplay == NULL) + { + ErrorF ("winMultiWindowXMsgProc - Could not open display, try: %d, " + "sleeping: %d\n\f", + iRetries + 1, WIN_CONNECT_DELAY); + ++iRetries; + sleep (WIN_CONNECT_DELAY); + continue; + } + else + break; + } + while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); + + /* Make sure that the display opened */ + if (pProcArg->pDisplay == NULL) + { + ErrorF ("winMultiWindowXMsgProcwinInitMultiWindowWM - " + "Failed opening the display, giving up.\n\f"); pthread_exit (NULL); } - pthread_exit (NULL); - return 0; + ErrorF ("winMultiWindowXMsgProc - XOpenDisplay () returned and " + "successfully opened the display.\n"); + + /* Install our error handler */ + XSetErrorHandler (winMultiWindowWMErrorHandler); + XSetIOErrorHandler (winMutliWindowWMIOErrorHandler); + + XSelectInput (pProcArg->pDisplay, + RootWindow(pProcArg->pDisplay, pProcArg->dwScreen), + SubstructureNotifyMask); + + /* Set up the supported icon sizes */ + xis = XAllocIconSize (); + if (xis) + { + xis->min_width = xis->min_height = 16; + xis->max_width = xis->max_height = 48; + xis->width_inc = xis->height_inc = 16; + XSetIconSizes (pProcArg->pDisplay, + RootWindow (pProcArg->pDisplay, pProcArg->dwScreen), + xis, + 1); + XFree (xis); + } + + atmWmName = XInternAtom (pProcArg->pDisplay, + "WM_NAME", + False); + atmWmHints = XInternAtom (pProcArg->pDisplay, + "WM_HINTS", + False); + atmWmChange = XInternAtom (pProcArg->pDisplay, + "WM_CHANGE_STATE", + False); + + /* Loop until we explicitly break out */ + while (1) + { + /* Fetch next event */ + XNextEvent (pProcArg->pDisplay, &event); + + /* Branch on event type */ + if (event.type == CreateNotify) + { + XSelectInput (pProcArg->pDisplay, + event.xcreatewindow.window, + PropertyChangeMask); + } + else if (event.type == PropertyNotify + && event.xproperty.atom == atmWmName) + { + memset (&msg, 0, sizeof (msg)); + + msg.msg = WM_WM_NAME_EVENT; + msg.iWindow = event.xproperty.window; + + /* Other fields ignored */ + winSendMessageToWM (pProcArg->pWMInfo, &msg); + } + else if (event.type == PropertyNotify + && event.xproperty.atom == atmWmHints) + { + memset (&msg, 0, sizeof (msg)); + + msg.msg = WM_WM_HINTS_EVENT; + msg.iWindow = event.xproperty.window; + + /* Other fields ignored */ + winSendMessageToWM (pProcArg->pWMInfo, &msg); + } + else if (event.type == ClientMessage + && event.xclient.message_type == atmWmChange + && event.xclient.data.l[0] == IconicState) + { + ErrorF ("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n"); + + memset (&msg, 0, sizeof (msg)); + + msg.msg = WM_WM_CHANGE_STATE; + msg.iWindow = event.xclient.window; + + winSendMessageToWM (pProcArg->pWMInfo, &msg); + } + } } @@ -682,12 +913,14 @@ winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr) Bool winInitWM (void **ppWMInfo, pthread_t *ptWMProc, + pthread_t *ptXMsgProc, pthread_mutex_t *ppmServerStarted, int dwScreen) { - WMProcArgPtr pArg = (WMProcArgPtr)malloc (sizeof(WMProcArgRec)); - WMInfoPtr pWMInfo = (WMInfoPtr)malloc (sizeof(WMInfoRec)); - + WMProcArgPtr pArg = (WMProcArgPtr) malloc (sizeof(WMProcArgRec)); + WMInfoPtr pWMInfo = (WMInfoPtr) malloc (sizeof(WMInfoRec)); + XMsgProcArgPtr pXMsgArg = (XMsgProcArgPtr) malloc (sizeof(XMsgProcArgRec)); + /* Bail if the input parameters are bad */ if (pArg == NULL || pWMInfo == NULL) { @@ -714,7 +947,18 @@ winInitWM (void **ppWMInfo, if (pthread_create (ptWMProc, NULL, winMultiWindowWMProc, pArg)) { /* Bail if thread creation failed */ - ErrorF ("winInitWM - pthread_create failed.\n"); + ErrorF ("winInitWM - pthread_create failed for Window Manager.\n"); + return FALSE; + } + + /* Spawn the XNextEvent thread, will send messages to WM */ + pXMsgArg->dwScreen = dwScreen; + pXMsgArg->pWMInfo = pWMInfo; + pXMsgArg->ppmServerStarted = ppmServerStarted; + if (pthread_create (ptXMsgProc, NULL, winMultiWindowXMsgProc, pXMsgArg)) + { + /* Bail if thread creation failed */ + ErrorF ("winInitWM - pthread_create failed on XMSG.\n"); return FALSE; } @@ -788,21 +1032,28 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) /* Flag that we have called setlocale */ g_fCalledSetLocale = TRUE; - /* Release the garbage mutex */ + /* Only call XInitThreads once for the whole process */ + if (!g_fCalledXInitThreads) + { + /* Allow multiple threads to access Xlib */ + if (XInitThreads () == 0) + { + ErrorF ("winInitMultiWindowWM - XInitThreads () failed.\n"); + pthread_exit (NULL); + } + + /* Flag that XInitThreads has been called */ + g_fCalledXInitThreads = TRUE; + + ErrorF ("winInitMultiWindowWM - XInitThreads () returned.\n"); + } + + /* Release the server started mutex */ pthread_mutex_unlock (pProcArg->ppmServerStarted); ErrorF ("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); - /* Allow multiple threads to access Xlib */ - if (XInitThreads () == 0) - { - ErrorF ("winInitMultiWindowWM - XInitThreads () failed.\n"); - pthread_exit (NULL); - } - - ErrorF ("winInitMultiWindowWM - XInitThreads () returned.\n"); - - /* Set jump point for Error exits */ + /* Set jump point for IO Error exits */ iReturn = setjmp (g_jmpEntry); /* Check if we should continue operations */ @@ -814,13 +1065,23 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) iReturn); pthread_exit (NULL); } + else if (g_shutdown) + { + /* Shutting down, the X server severed out connection! */ + ErrorF ("winInitMultiWindowWM - Detected shutdown in progress\n"); + pthread_exit (NULL); + } else if (iReturn == WIN_JMP_ERROR_IO) { ErrorF ("winInitMultiWindowWM - setjmp returned WIN_JMP_ERROR_IO\n"); } /* Setup the display connection string x */ - snprintf (pszDisplay, 512, "127.0.0.1:%s.%d", display, pProcArg->dwScreen); + snprintf (pszDisplay, + 512, + "127.0.0.1:%s.%d", + display, + (int) pProcArg->dwScreen); /* Print the display connection string */ ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); @@ -866,6 +1127,9 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay, "WM_DELETE_WINDOW", False); + pWMInfo->atmPrivMap = XInternAtom (pWMInfo->pDisplay, + WIN_HWND_CACHE, + False); } @@ -905,3 +1169,15 @@ winMutliWindowWMIOErrorHandler (Display *pDisplay) return 0; } + + +/* + * Notify the MWM thread we're exiting and not to reconnect + */ + +void +winDeinitMultiWindowWM () +{ + ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n"); + g_shutdown = TRUE; +} |