yet MORE changes to how focusin/out's are handled. more edge case fixing, this time with focus fallback when unmapping a window in sloppy focus mode.
This commit is contained in:
parent
b426f7667d
commit
01debc76b9
1 changed files with 61 additions and 33 deletions
|
@ -26,6 +26,13 @@ static void event_handle_root(XEvent *e);
|
||||||
static void event_handle_client(Client *c, XEvent *e);
|
static void event_handle_client(Client *c, XEvent *e);
|
||||||
static void event_handle_menu(Menu *menu, XEvent *e);
|
static void event_handle_menu(Menu *menu, XEvent *e);
|
||||||
|
|
||||||
|
#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \
|
||||||
|
(e)->xfocus.detail > NotifyNonlinearVirtual)
|
||||||
|
#define INVALID_FOCUSOUT(e) ((e)->xfocus.mode == NotifyGrab || \
|
||||||
|
(e)->xfocus.detail == NotifyInferior || \
|
||||||
|
(e)->xfocus.detail == NotifyAncestor || \
|
||||||
|
(e)->xfocus.detail > NotifyNonlinearVirtual)
|
||||||
|
|
||||||
Time event_lasttime = 0;
|
Time event_lasttime = 0;
|
||||||
|
|
||||||
/*! The value of the mask for the NumLock modifier */
|
/*! The value of the mask for the NumLock modifier */
|
||||||
|
@ -239,19 +246,18 @@ static gboolean event_ignore(XEvent *e, Client *client)
|
||||||
{
|
{
|
||||||
switch(e->type) {
|
switch(e->type) {
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
#ifdef DEBUG_FOCUS
|
|
||||||
g_message("FocusIn on %lx mode %d detail %d", window,
|
|
||||||
e->xfocus.mode, e->xfocus.detail);
|
|
||||||
#endif
|
|
||||||
/* NotifyAncestor is not ignored in FocusIn like it is in FocusOut
|
/* NotifyAncestor is not ignored in FocusIn like it is in FocusOut
|
||||||
because of RevertToPointerRoot. If the focus ends up reverting to
|
because of RevertToPointerRoot. If the focus ends up reverting to
|
||||||
pointer root on a workspace change, then the FocusIn event that we
|
pointer root on a workspace change, then the FocusIn event that we
|
||||||
want will be of type NotifyAncestor. This situation does not occur
|
want will be of type NotifyAncestor. This situation does not occur
|
||||||
for FocusOut, so it is safely ignored there.
|
for FocusOut, so it is safely ignored there.
|
||||||
*/
|
*/
|
||||||
if (e->xfocus.detail == NotifyInferior ||
|
if (INVALID_FOCUSIN(e) ||
|
||||||
e->xfocus.detail > NotifyNonlinearVirtual ||
|
|
||||||
client == NULL) {
|
client == NULL) {
|
||||||
|
#ifdef DEBUG_FOCUS
|
||||||
|
g_message("FocusIn on %lx mode %d detail %d IGNORED", e->xfocus.window,
|
||||||
|
e->xfocus.mode, e->xfocus.detail);
|
||||||
|
#endif
|
||||||
/* says a client was not found for the event (or a valid FocusIn
|
/* says a client was not found for the event (or a valid FocusIn
|
||||||
event was not found.
|
event was not found.
|
||||||
*/
|
*/
|
||||||
|
@ -260,45 +266,67 @@ static gboolean event_ignore(XEvent *e, Client *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FOCUS
|
#ifdef DEBUG_FOCUS
|
||||||
g_message("FocusIn on %lx", window);
|
g_message("FocusIn on %lx mode %d detail %d", e->xfocus.window,
|
||||||
|
e->xfocus.mode, e->xfocus.detail);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
|
if (INVALID_FOCUSOUT(e)) {
|
||||||
#ifdef DEBUG_FOCUS
|
#ifdef DEBUG_FOCUS
|
||||||
g_message("FocusOut on %lx mode %d detail %d", window,
|
g_message("FocusOut on %lx mode %d detail %d IGNORED",
|
||||||
e->xfocus.mode, e->xfocus.detail);
|
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
|
||||||
#endif
|
#endif
|
||||||
if (e->xfocus.mode == NotifyGrab ||
|
return TRUE;
|
||||||
e->xfocus.detail == NotifyInferior ||
|
}
|
||||||
e->xfocus.detail == NotifyAncestor ||
|
|
||||||
e->xfocus.detail > NotifyNonlinearVirtual) return TRUE;
|
|
||||||
|
|
||||||
#ifdef DEBUG_FOCUS
|
#ifdef DEBUG_FOCUS
|
||||||
g_message("FocusOut on %lx", window);
|
g_message("FocusOut on %lx mode %d detail %d",
|
||||||
|
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Try process a FocusIn first, and if a legit one isn't found, then
|
/* Try process a FocusIn first, and if a legit one isn't found, then
|
||||||
do the fallback shiznit. */
|
do the fallback shiznit. */
|
||||||
{
|
{
|
||||||
XEvent fi, fo;
|
XEvent fe;
|
||||||
gboolean isfo = FALSE;
|
gboolean fallback = TRUE;
|
||||||
|
|
||||||
if (XCheckTypedEvent(ob_display, FocusIn, &fi)) {
|
while (TRUE) {
|
||||||
event_process(&fi);
|
if (!XCheckTypedEvent(ob_display, FocusOut, &fe))
|
||||||
|
if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
|
||||||
/* when we have gotten a fi/fo pair, then see if there are any
|
break;
|
||||||
more fo's coming. if there are, then don't fallback just yet
|
if (fe.type == FocusOut) {
|
||||||
*/
|
#ifdef DEBUG_FOCUS
|
||||||
if ((isfo = XCheckTypedEvent(ob_display, FocusOut, &fo)))
|
g_message("found pending FocusOut");
|
||||||
XPutBackEvent(ob_display, &fo);
|
#endif
|
||||||
|
if (!INVALID_FOCUSOUT(&fe)) {
|
||||||
/* secret magic way of event_process telling us that no client
|
/* if there is a VALID FocusOut still coming, don't
|
||||||
was found for the FocusIn event. ^_^ */
|
fallback focus yet, we'll deal with it then */
|
||||||
if (!isfo && fi.xfocus.window == None)
|
XPutBackEvent(ob_display, &fe);
|
||||||
focus_fallback(Fallback_NoFocus);
|
fallback = FALSE;
|
||||||
if (fi.xfocus.window == e->xfocus.window)
|
break;
|
||||||
return TRUE;
|
}
|
||||||
} else
|
} else {
|
||||||
|
#ifdef DEBUG_FOCUS
|
||||||
|
g_message("found pending FocusIn");
|
||||||
|
#endif
|
||||||
|
/* once all the FocusOut's have been dealt with, if there
|
||||||
|
is a FocusIn still left and it is valid, then use it */
|
||||||
|
event_process(&fe);
|
||||||
|
/* secret magic way of event_process telling us that no
|
||||||
|
client was found for the FocusIn event. ^_^ */
|
||||||
|
if (fe.xfocus.window != None) {
|
||||||
|
fallback = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fallback) {
|
||||||
|
#ifdef DEBUG_FOCUS
|
||||||
|
g_message("no valid FocusIn and no FocusOut events found, "
|
||||||
|
"falling back");
|
||||||
|
#endif
|
||||||
focus_fallback(Fallback_NoFocus);
|
focus_fallback(Fallback_NoFocus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EnterNotify:
|
case EnterNotify:
|
||||||
|
|
Loading…
Reference in a new issue