diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2009-10-03 12:57:03 +0100 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2009-10-15 18:35:25 +0100 |
commit | 69094bffec191c2e6fd797f71d9b9b11ca38982c (patch) | |
tree | 6fe4ba9888fcefe7f89f48daac4321b6370261dc | |
parent | cbb831019386d5043e923dff91c0d139800f0649 (diff) |
Workaround for SWT/Motif bug
It expects all top-level windows to get reparented, and waits until they
do. So workaround that in our internal WM forcing a reparent event to
occur, even though we don't actually need to reparent the window to
frame it (as the frame is a native window, not an X window)
Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
-rw-r--r-- | hw/xwin/winmultiwindowwindow.c | 13 | ||||
-rw-r--r-- | hw/xwin/winmultiwindowwm.c | 119 |
2 files changed, 79 insertions, 53 deletions
diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 27f6bfbc3..f127646cd 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -65,19 +65,6 @@ static void winFindWindow (pointer value, XID id, pointer cdata); /* - * Macros - */ - -#define SubSend(pWin) \ - ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) - -#define StrSend(pWin) \ - ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) - -#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) - - -/* * CreateWindow - See Porting Layer Definition - p. 37 */ diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 2ef2d5940..dc0d9a83e 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -203,7 +203,7 @@ static jmp_buf g_jmpWMEntry; static jmp_buf g_jmpXMsgProcEntry; static Bool g_shutdown = FALSE; static Bool redirectError = FALSE; -static Bool g_fAnotherWMRunnig = FALSE; +static Bool g_fAnotherWMRunning = FALSE; /* * PushMessage - Push a message onto the queue @@ -629,7 +629,7 @@ winMultiWindowWMProc (void *pArg) { WMMsgNodePtr pNode; - if(g_fAnotherWMRunnig)/* Another Window manager exists. */ + if(g_fAnotherWMRunning)/* Another Window manager exists. */ { Sleep (1000); continue; @@ -942,26 +942,15 @@ winMultiWindowXMsgProc (void *pArg) "successfully opened the display.\n"); /* Check if another window manager is already running */ - if (pProcArg->pWMInfo->fAllowOtherWM) - { - g_fAnotherWMRunnig = CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen); - } else { - redirectError = FALSE; - XSetErrorHandler (winRedirectErrorHandler); - XSelectInput(pProcArg->pDisplay, - RootWindow (pProcArg->pDisplay, pProcArg->dwScreen), - SubstructureNotifyMask | ButtonPressMask); - XSync (pProcArg->pDisplay, 0); - XSetErrorHandler (winMultiWindowXMsgProcErrorHandler); - if (redirectError) - { - ErrorF ("winMultiWindowXMsgProc - " - "another window manager is running. Exiting.\n"); - pthread_exit (NULL); + g_fAnotherWMRunning = CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen); + + if (g_fAnotherWMRunning && !pProcArg->pWMInfo->fAllowOtherWM) + { + ErrorF ("winMultiWindowXMsgProc - " + "another window manager is running. Exiting.\n"); + pthread_exit (NULL); } - g_fAnotherWMRunnig = FALSE; - } - + /* Set up the supported icon sizes */ xis = XAllocIconSize (); if (xis) @@ -1006,17 +995,17 @@ winMultiWindowXMsgProc (void *pArg) { if (CheckAnotherWindowManager (pProcArg->pDisplay, pProcArg->dwScreen)) { - if (!g_fAnotherWMRunnig) + if (!g_fAnotherWMRunning) { - g_fAnotherWMRunnig = TRUE; + g_fAnotherWMRunning = TRUE; SendMessage(*(HWND*)pProcArg->hwndScreen, WM_UNMANAGE, 0, 0); } } else { - if (g_fAnotherWMRunnig) + if (g_fAnotherWMRunning) { - g_fAnotherWMRunnig = FALSE; + g_fAnotherWMRunning = FALSE; SendMessage(*(HWND*)pProcArg->hwndScreen, WM_MANAGE, 0, 0); } } @@ -1046,6 +1035,60 @@ winMultiWindowXMsgProc (void *pArg) event.xcreatewindow.window, 0); } + else if (event.type == MapNotify) + { + /* Fake a reparentNotify event as SWT/Motif expects a + Window Manager to reparent a top-level window when + it is mapped and waits until they do. + + We don't actually need to reparent, as the frame is + a native window, not an X window + + We do this on MapNotify, not MapRequest like a real + Window Manager would, so we don't have do get involved + in actually mapping the window via it's (non-existent) + parent... + + See sourceware bugzilla #9848 + */ + + XWindowAttributes attr; + Window root; + Window parent; + Window *children; + unsigned int nchildren; + + if (XGetWindowAttributes(event.xmap.display, + event.xmap.window, + &attr) && + XQueryTree(event.xmap.display, + event.xmap.window, + &root, &parent, &children, &nchildren)) + { + if (children) XFree(children); + + /* + It's a top-level window if the parent window is a root window + Only non-override_redirect windows can get reparented + */ + if ((attr.root == parent) && !event.xmap.override_redirect) + { + XEvent event_send; + + event_send.type = ReparentNotify; + event_send.xreparent.event = event.xmap.window; + event_send.xreparent.window = event.xmap.window; + event_send.xreparent.parent = parent; + event_send.xreparent.x = attr.x; + event_send.xreparent.y = attr.y; + + XSendEvent(event.xmap.display, + event.xmap.window, + True, StructureNotifyMask, + &event_send); + } + } + } else if (event.type == PropertyNotify && event.xproperty.atom == atmWmName) { @@ -1432,27 +1475,23 @@ winRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr) static Bool CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen) { + /* + Try to select the events which only one client at a time is allowed to select. + If this causes an error, another window manager is already running... + */ redirectError = FALSE; XSetErrorHandler (winRedirectErrorHandler); XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen), - // SubstructureNotifyMask | ButtonPressMask - ColormapChangeMask | EnterWindowMask | PropertyChangeMask | - SubstructureRedirectMask | KeyPressMask | - ButtonPressMask | ButtonReleaseMask); + ResizeRedirectMask | SubstructureRedirectMask | ButtonPressMask); XSync (pDisplay, 0); XSetErrorHandler (winMultiWindowXMsgProcErrorHandler); - XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen), - SubstructureNotifyMask); + + /* + Side effect: select the events we are actually interested in... + */ + XSelectInput(pDisplay, RootWindow (pDisplay, dwScreen), SubstructureNotifyMask); XSync (pDisplay, 0); - if (redirectError) - { - //ErrorF ("CheckAnotherWindowManager() - another window manager is running. Exiting.\n"); - return TRUE; - } - else - { - return FALSE; - } + return redirectError; } /* |