diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2013-07-08 14:17:52 +0100 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2013-07-08 14:17:52 +0100 |
commit | 2c461ca50c4acfca78acedbbae7dfdbc87612c30 (patch) | |
tree | e91b5c4835a75f99d4fea95ee75b734ae4a4d85a | |
parent | 17ef06f8b9729329575b69729bbc868c56f9e183 (diff) | |
parent | 87dc106f840c6fbcceed14135079b8e3b04c0ab6 (diff) |
Merge branch 'cygwin-patches-for-1.14' into cygwin-release-1.14xserver-cygwin-1.14.2-1
-rw-r--r-- | hw/xwin/winmultiwindowwm.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 95df867e6..7b44a7384 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -123,6 +123,7 @@ typedef struct _WMInfo { WMMsgQueueRec wmMsgQueue; Atom atmWmProtos; Atom atmWmDelete; + Atom atmWmTakeFocus; Atom atmPrivMap; Bool fAllowOtherWM; } WMInfoRec, *WMInfoPtr; @@ -508,6 +509,27 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName) } /* + * Does the client support the specified WM_PROTOCOLS protocol? + */ + +static Bool +IsWmProtocolAvailable(Display * pDisplay, Window iWindow, Atom atmProtocol) +{ + int i, n, found = 0; + Atom *protocols; + + if (XGetWMProtocols(pDisplay, iWindow, &protocols, &n)) { + for (i = 0; i < n; ++i) + if (protocols[i] == atmProtocol) + ++found; + + XFree(protocols); + } + + return found > 0; +} + +/* * Send a message to the X server from the WM thread */ @@ -886,21 +908,10 @@ winMultiWindowWMProc(void *pArg) ErrorF("\tWM_WM_KILL\n"); #endif { - int i, n, found = 0; - Atom *protocols; - /* --- */ - if (XGetWMProtocols(pWMInfo->pDisplay, - pNode->msg.iWindow, &protocols, &n)) { - for (i = 0; i < n; ++i) - if (protocols[i] == pWMInfo->atmWmDelete) - ++found; - - XFree(protocols); - } - - /* --- */ - if (found) + if (IsWmProtocolAvailable(pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmWmDelete)) SendXMessage(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmWmProtos, pWMInfo->atmWmDelete); @@ -913,11 +924,39 @@ winMultiWindowWMProc(void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF("\tWM_WM_ACTIVATE\n"); #endif - /* Set the input focus */ - XSetInputFocus(pWMInfo->pDisplay, - pNode->msg.iWindow, - RevertToPointerRoot, CurrentTime); + + /* + ICCCM 4.1.7 is pretty opaque, but it appears that the rules are + actually quite simple: + -- the WM_HINTS input field determines whether the WM should call + XSetInputFocus() + -- independently, the WM_TAKE_FOCUS protocol determines whether + the WM should send a WM_TAKE_FOCUS ClientMessage. + */ + { + Bool neverFocus = FALSE; + XWMHints *hints = XGetWMHints(pWMInfo->pDisplay, pNode->msg.iWindow); + + if (hints) { + if (hints->flags & InputHint) + neverFocus = !hints->input; + XFree(hints); + } + + if (!neverFocus) + XSetInputFocus(pWMInfo->pDisplay, + pNode->msg.iWindow, + RevertToPointerRoot, CurrentTime); + + if (IsWmProtocolAvailable(pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmWmTakeFocus)) + SendXMessage(pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus); + + } break; case WM_WM_NAME_EVENT: @@ -1472,6 +1511,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) "WM_PROTOCOLS", False); pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay, "WM_DELETE_WINDOW", False); + pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay, + "WM_TAKE_FOCUS", False); pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay, WINDOWSWM_NATIVE_HWND, False); |