summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon TURNEY <jon.turney@dronecode.org.uk>2013-07-08 14:17:52 +0100
committerJon TURNEY <jon.turney@dronecode.org.uk>2013-07-08 14:17:52 +0100
commit2c461ca50c4acfca78acedbbae7dfdbc87612c30 (patch)
treee91b5c4835a75f99d4fea95ee75b734ae4a4d85a
parent17ef06f8b9729329575b69729bbc868c56f9e183 (diff)
parent87dc106f840c6fbcceed14135079b8e3b04c0ab6 (diff)
Merge branch 'cygwin-patches-for-1.14' into cygwin-release-1.14xserver-cygwin-1.14.2-1
-rw-r--r--hw/xwin/winmultiwindowwm.c77
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);