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;
|
||||
Atom atmWmProtos;
|
||||
Atom atmWmDelete;
|
||||
Atom atmWmTakeFocus;
|
||||
Atom atmPrivMap;
|
||||
Bool fAllowOtherWM;
|
||||
} WMInfoRec, *WMInfoPtr;
|
||||
|
@ -452,6 +453,27 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
|
|||
*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
|
||||
*/
|
||||
|
@ -805,21 +827,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);
|
||||
|
@ -832,11 +843,39 @@ winMultiWindowWMProc(void *pArg)
|
|||
#if CYGMULTIWINDOW_DEBUG
|
||||
ErrorF("\tWM_WM_ACTIVATE\n");
|
||||
#endif
|
||||
|
||||
/* Set the input focus */
|
||||
|
||||
/*
|
||||
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:
|
||||
|
@ -1404,6 +1443,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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user