hw/xwin: More closely follow ICCCM for setting input focus
In multiwindow mode, more closely follow ICCCM section 4.1.7 when setting X input focus to a window when the native Windows window acquires input focus: - If InputHint is FALSE, don't use XSetInputFocus() - If the window supports the WM_TAKE_FOCUS protocol, send a WM_TAKE_FOCUS message This helps JDK 1.7 clients acquire the focus correctly. Also, factor out checking client support for a given WM_PROTOCOLS protocol as a separate function. Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk> Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
parent
0fc84a2bb6
commit
b634e90989
|
@ -111,6 +111,7 @@ typedef struct _WMInfo {
|
||||||
WMMsgQueueRec wmMsgQueue;
|
WMMsgQueueRec wmMsgQueue;
|
||||||
Atom atmWmProtos;
|
Atom atmWmProtos;
|
||||||
Atom atmWmDelete;
|
Atom atmWmDelete;
|
||||||
|
Atom atmWmTakeFocus;
|
||||||
Atom atmPrivMap;
|
Atom atmPrivMap;
|
||||||
Bool fAllowOtherWM;
|
Bool fAllowOtherWM;
|
||||||
} WMInfoRec, *WMInfoPtr;
|
} WMInfoRec, *WMInfoPtr;
|
||||||
|
@ -452,6 +453,27 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
|
||||||
*ppWindowName = pszWindowName;
|
*ppWindowName = pszWindowName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* Send a message to the X server from the WM thread
|
||||||
*/
|
*/
|
||||||
|
@ -805,21 +827,10 @@ winMultiWindowWMProc(void *pArg)
|
||||||
ErrorF("\tWM_WM_KILL\n");
|
ErrorF("\tWM_WM_KILL\n");
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int i, n, found = 0;
|
|
||||||
Atom *protocols;
|
|
||||||
|
|
||||||
/* --- */
|
/* --- */
|
||||||
if (XGetWMProtocols(pWMInfo->pDisplay,
|
if (IsWmProtocolAvailable(pWMInfo->pDisplay,
|
||||||
pNode->msg.iWindow, &protocols, &n)) {
|
pNode->msg.iWindow,
|
||||||
for (i = 0; i < n; ++i)
|
pWMInfo->atmWmDelete))
|
||||||
if (protocols[i] == pWMInfo->atmWmDelete)
|
|
||||||
++found;
|
|
||||||
|
|
||||||
XFree(protocols);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- */
|
|
||||||
if (found)
|
|
||||||
SendXMessage(pWMInfo->pDisplay,
|
SendXMessage(pWMInfo->pDisplay,
|
||||||
pNode->msg.iWindow,
|
pNode->msg.iWindow,
|
||||||
pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
|
pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
|
||||||
|
@ -832,11 +843,39 @@ winMultiWindowWMProc(void *pArg)
|
||||||
#if CYGMULTIWINDOW_DEBUG
|
#if CYGMULTIWINDOW_DEBUG
|
||||||
ErrorF("\tWM_WM_ACTIVATE\n");
|
ErrorF("\tWM_WM_ACTIVATE\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set the input focus */
|
/* 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;
|
break;
|
||||||
|
|
||||||
case WM_WM_NAME_EVENT:
|
case WM_WM_NAME_EVENT:
|
||||||
|
@ -1404,6 +1443,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
|
||||||
"WM_PROTOCOLS", False);
|
"WM_PROTOCOLS", False);
|
||||||
pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay,
|
pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay,
|
||||||
"WM_DELETE_WINDOW", False);
|
"WM_DELETE_WINDOW", False);
|
||||||
|
pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay,
|
||||||
|
"WM_TAKE_FOCUS", False);
|
||||||
|
|
||||||
pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay,
|
pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay,
|
||||||
WINDOWSWM_NATIVE_HWND, False);
|
WINDOWSWM_NATIVE_HWND, False);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user