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:
Dana Jansens 2003-04-18 08:45:49 +00:00
parent b426f7667d
commit 01debc76b9

View file

@ -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: