revert my commit of d3th, it fucked up focus badly

This commit is contained in:
Dana Jansens 2003-09-15 11:29:17 +00:00
parent ebf24d5224
commit 3a607fad9d
6 changed files with 124 additions and 90 deletions

View file

@ -1647,9 +1647,7 @@ static ObStackingLayer calc_layer(ObClient *self)
{ {
ObStackingLayer l; ObStackingLayer l;
if (self->fullscreen && if (self->fullscreen) l = OB_STACKING_LAYER_FULLSCREEN;
(client_focused(self) || client_search_focus_tree(self)))
l = OB_STACKING_LAYER_FULLSCREEN;
else if (self->type == OB_CLIENT_TYPE_DESKTOP) else if (self->type == OB_CLIENT_TYPE_DESKTOP)
l = OB_STACKING_LAYER_DESKTOP; l = OB_STACKING_LAYER_DESKTOP;
else if (self->type == OB_CLIENT_TYPE_DOCK) { else if (self->type == OB_CLIENT_TYPE_DOCK) {
@ -1671,9 +1669,7 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
old = self->layer; old = self->layer;
own = calc_layer(self); own = calc_layer(self);
self->layer = MAX(l, own); self->layer = l > own ? l : own;
g_message("calc for 0x%x %d %d", self->window, old, self->layer);
for (it = self->transients; it; it = it->next) for (it = self->transients; it; it = it->next)
client_calc_layer_recursive(it->data, orig, client_calc_layer_recursive(it->data, orig,
@ -1681,6 +1677,7 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
if (!raised && l != old) if (!raised && l != old)
if (orig->frame) { /* only restack if the original window is managed */ if (orig->frame) { /* only restack if the original window is managed */
/* XXX add_non_intrusive ever? */
stacking_remove(CLIENT_AS_WINDOW(self)); stacking_remove(CLIENT_AS_WINDOW(self));
stacking_add(CLIENT_AS_WINDOW(self)); stacking_add(CLIENT_AS_WINDOW(self));
} }
@ -2529,15 +2526,14 @@ gboolean client_focus(ObClient *self)
/* choose the correct target */ /* choose the correct target */
self = client_focus_target(self); self = client_focus_target(self);
if (!self->frame->visible) { if (!client_can_focus(self)) {
/* update the focus lists */ if (!self->frame->visible) {
focus_order_to_top(self); /* update the focus lists */
focus_order_to_top(self);
}
return FALSE; return FALSE;
} }
if (!client_can_focus(self))
return FALSE;
if (self->can_focus) { if (self->can_focus) {
/* RevertToPointerRoot causes much more headache than RevertToNone, so /* RevertToPointerRoot causes much more headache than RevertToNone, so
I choose to use it always, hopefully to find errors quicker, if any I choose to use it always, hopefully to find errors quicker, if any
@ -2565,8 +2561,6 @@ gboolean client_focus(ObClient *self)
XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce); XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
} }
focus_set_client(self);
#ifdef DEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("%sively focusing %lx at %d\n", ob_debug("%sively focusing %lx at %d\n",
(self->can_focus ? "act" : "pass"), (self->can_focus ? "act" : "pass"),

View file

@ -42,7 +42,6 @@ typedef struct
} ObEventData; } ObEventData;
static void event_process(const XEvent *e, gpointer data); static void event_process(const XEvent *e, gpointer data);
static void event_done(gpointer data);
static void event_handle_root(XEvent *e); static void event_handle_root(XEvent *e);
static void event_handle_menu(XEvent *e); static void event_handle_menu(XEvent *e);
static void event_handle_dock(ObDock *s, XEvent *e); static void event_handle_dock(ObDock *s, XEvent *e);
@ -133,7 +132,7 @@ void event_startup(gboolean reconfig)
} }
} }
ob_main_loop_x_add(ob_main_loop, event_process, event_done, NULL, NULL); ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
#ifdef USE_SM #ifdef USE_SM
IceAddConnectionWatch(ice_watch, NULL); IceAddConnectionWatch(ice_watch, NULL);
@ -284,32 +283,24 @@ static void event_hack_mods(XEvent *e)
static gboolean event_ignore(XEvent *e, ObClient *client) static gboolean event_ignore(XEvent *e, ObClient *client)
{ {
gboolean ignore = FALSE;
XEvent ce;
switch(e->type) { switch(e->type) {
case FocusIn: case FocusIn:
while (XCheckTypedWindowEvent(ob_display, e->xfocus.window,
FocusIn, &ce))
{
if (!INVALID_FOCUSIN(&ce)) {
XPutBackEvent(ob_display, &ce);
ignore = TRUE;
break;
}
}
/* 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 (ignore || INVALID_FOCUSIN(e) || client == NULL) { if (INVALID_FOCUSIN(e) ||
client == NULL) {
#ifdef DEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n", ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail); e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif #endif
/* says a client was not found for the event (or a valid FocusIn
event was not found.
*/
e->xfocus.window = None;
return TRUE; return TRUE;
} }
@ -319,20 +310,10 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
#endif #endif
break; break;
case FocusOut: case FocusOut:
while (XCheckTypedWindowEvent(ob_display, e->xfocus.window, if (INVALID_FOCUSOUT(e)) {
FocusOut, &ce))
{
if (!INVALID_FOCUSOUT(&ce)) {
XPutBackEvent(ob_display, &ce);
ignore = TRUE;
break;
}
}
if (ignore || INVALID_FOCUSOUT(e)) {
#ifdef DEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n", ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail); e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif #endif
return TRUE; return TRUE;
} }
@ -341,6 +322,84 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
ob_debug("FocusOut on %lx mode %d detail %d\n", ob_debug("FocusOut on %lx mode %d detail %d\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail); e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif #endif
{
XEvent fe;
gboolean fallback = TRUE;
while (TRUE) {
if (!XCheckTypedWindowEvent(ob_display, e->xfocus.window,
FocusOut, &fe))
if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
break;
if (fe.type == FocusOut) {
#ifdef DEBUG_FOCUS
ob_debug("found pending FocusOut\n");
#endif
if (!INVALID_FOCUSOUT(&fe)) {
/* if there is a VALID FocusOut still coming, don't
fallback focus yet, we'll deal with it then */
XPutBackEvent(ob_display, &fe);
fallback = FALSE;
break;
}
} else {
#ifdef DEBUG_FOCUS
ob_debug("found pending FocusIn\n");
#endif
/* is the focused window getting a FocusOut/In back to
itself?
*/
if (fe.xfocus.window == e->xfocus.window &&
!event_ignore(&fe, client)) {
/*
if focus_client is not set, then we can't do
this. we need the FocusIn. This happens in the
case when the set_focus_client(NULL) in the
focus_fallback function fires and then
focus_fallback picks the currently focused
window (such as on a SendToDesktop-esque action.
*/
if (focus_client) {
#ifdef DEBUG_FOCUS
ob_debug("focused window got an Out/In back to "
"itself IGNORED both\n");
#endif
return TRUE;
} else {
event_process(&fe, NULL);
#ifdef DEBUG_FOCUS
ob_debug("focused window got an Out/In back to "
"itself but focus_client was null "
"IGNORED just the Out\n");
#endif
return TRUE;
}
}
{
ObEventData d;
/* 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, &d);
if (!d.ignored) {
ob_debug("FocusIn was OK, so don't fallback\n");
fallback = FALSE;
break;
}
}
}
}
if (fallback) {
#ifdef DEBUG_FOCUS
ob_debug("no valid FocusIn and no FocusOut events found, "
"falling back\n");
#endif
focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
}
}
break; break;
case EnterNotify: case EnterNotify:
case LeaveNotify: case LeaveNotify:
@ -354,7 +413,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
(e->xcrossing.detail == NotifyAncestor || (e->xcrossing.detail == NotifyAncestor ||
e->xcrossing.detail == NotifyNonlinearVirtual || e->xcrossing.detail == NotifyNonlinearVirtual ||
e->xcrossing.detail == NotifyVirtual))) { e->xcrossing.detail == NotifyVirtual))) {
#ifdef aDEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n", ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n",
(e->type == EnterNotify ? "Enter" : "Leave"), (e->type == EnterNotify ? "Enter" : "Leave"),
e->xcrossing.mode, e->xcrossing.mode,
@ -362,7 +421,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
#endif #endif
return TRUE; return TRUE;
} }
#ifdef aDEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("%sNotify mode %d detail %d on %lx\n", ob_debug("%sNotify mode %d detail %d on %lx\n",
(e->type == EnterNotify ? "Enter" : "Leave"), (e->type == EnterNotify ? "Enter" : "Leave"),
e->xcrossing.mode, e->xcrossing.mode,
@ -486,12 +545,6 @@ static void event_process(const XEvent *ec, gpointer data)
} }
} }
static void event_done(gpointer data)
{
if (!focus_client)
focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
}
static void event_handle_root(XEvent *e) static void event_handle_root(XEvent *e)
{ {
Atom msgtype; Atom msgtype;
@ -597,22 +650,27 @@ static void event_handle_client(ObClient *client, XEvent *e)
break; break;
case FocusIn: case FocusIn:
#ifdef DEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"), ob_debug("FocusIn on client for %lx\n", client->window);
client->window);
#endif #endif
if (client != focus_client) if (client != focus_client) {
focus_set_client(client); focus_set_client(client);
frame_adjust_focus(client->frame, e->type == FocusIn); frame_adjust_focus(client->frame, TRUE);
}
break; break;
case FocusOut: case FocusOut:
#ifdef DEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"), ob_debug("FocusOut on client for %lx\n", client->window);
client->window);
#endif #endif
if (client == focus_client) /* are we a fullscreen window or a transient of one? (checks layer)
focus_client = NULL; if we are then we need to be iconified since we are losing focus
frame_adjust_focus(client->frame, e->type == FocusIn); */
break; if (client->layer == OB_STACKING_LAYER_FULLSCREEN && !client->iconic &&
!client_search_focus_tree_full(client))
/* iconify fullscreen windows when they and their transients
aren't focused */
client_iconify(client, TRUE, TRUE);
frame_adjust_focus(client->frame, FALSE);
break;
case LeaveNotify: case LeaveNotify:
con = frame_context(client, e->xcrossing.window); con = frame_context(client, e->xcrossing.window);
switch (con) { switch (con) {
@ -675,7 +733,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
case OB_FRAME_CONTEXT_FRAME: case OB_FRAME_CONTEXT_FRAME:
if (client_normal(client)) { if (client_normal(client)) {
if (config_focus_follow) { if (config_focus_follow) {
#ifdef aDEBUG_FOCUS #ifdef DEBUG_FOCUS
ob_debug("EnterNotify on %lx, focusing window\n", ob_debug("EnterNotify on %lx, focusing window\n",
client->window); client->window);
#endif #endif

View file

@ -73,7 +73,7 @@ void focus_set_client(ObClient *client)
screen_install_colormap(focus_client, FALSE); screen_install_colormap(focus_client, FALSE);
screen_install_colormap(client, TRUE); screen_install_colormap(client, TRUE);
if (!client) { if (client == NULL) {
/* when nothing will be focused, send focus to the backup target */ /* when nothing will be focused, send focus to the backup target */
XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot, XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
event_lasttime); event_lasttime);
@ -87,22 +87,16 @@ void focus_set_client(ObClient *client)
old = focus_client; old = focus_client;
focus_client = client; focus_client = client;
if (old) { /* move to the top of the list */
/* focus state can affect the stacking layer */ if (client != NULL)
client_calc_layer(old);
}
if (client) {
/* focus state can affect the stacking layer */
client_calc_layer(client);
/* move to the top of the list */
push_to_top(client); push_to_top(client);
}
/* set the NET_ACTIVE_WINDOW hint */ /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
active = client ? client->window : None; if (ob_state() != OB_STATE_EXITING) {
PROP_SET32(RootWindow(ob_display, ob_screen), active = client ? client->window : None;
net_active_window, window, active); PROP_SET32(RootWindow(ob_display, ob_screen),
net_active_window, window, active);
}
} }
static gboolean focus_under_pointer() static gboolean focus_under_pointer()

View file

@ -1,5 +1,4 @@
#include "mainloop.h" #include "mainloop.h"
#include "focus.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -100,7 +99,6 @@ struct _ObMainLoopXHandlerType
ObMainLoop *loop; ObMainLoop *loop;
gpointer data; gpointer data;
ObMainLoopXHandler func; ObMainLoopXHandler func;
ObMainLoopXDoneHandler done_func;
GDestroyNotify destroy; GDestroyNotify destroy;
}; };
@ -265,12 +263,6 @@ void ob_main_loop_run(ObMainLoop *loop)
h->func(&e, h->data); h->func(&e, h->data);
} }
} while (XPending(loop->display)); } while (XPending(loop->display));
for (it = loop->x_handlers; it; it = g_slist_next(it)) {
ObMainLoopXHandlerType *h = it->data;
if (h->done_func)
h->done_func(h->data);
}
} else { } else {
/* this only runs if there were no x events received */ /* this only runs if there were no x events received */
@ -305,7 +297,6 @@ void ob_main_loop_exit(ObMainLoop *loop)
void ob_main_loop_x_add(ObMainLoop *loop, void ob_main_loop_x_add(ObMainLoop *loop,
ObMainLoopXHandler handler, ObMainLoopXHandler handler,
ObMainLoopXDoneHandler done_handler,
gpointer data, gpointer data,
GDestroyNotify notify) GDestroyNotify notify)
{ {
@ -314,7 +305,6 @@ void ob_main_loop_x_add(ObMainLoop *loop,
h = g_new(ObMainLoopXHandlerType, 1); h = g_new(ObMainLoopXHandlerType, 1);
h->loop = loop; h->loop = loop;
h->func = handler; h->func = handler;
h->done_func = done_handler;
h->data = data; h->data = data;
h->destroy = notify; h->destroy = notify;
loop->x_handlers = g_slist_prepend(loop->x_handlers, h); loop->x_handlers = g_slist_prepend(loop->x_handlers, h);

View file

@ -10,11 +10,9 @@ ObMainLoop *ob_main_loop_new(Display *display);
void ob_main_loop_destroy(ObMainLoop *loop); void ob_main_loop_destroy(ObMainLoop *loop);
typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data); typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data);
typedef void (*ObMainLoopXDoneHandler) (gpointer data);
void ob_main_loop_x_add(ObMainLoop *loop, void ob_main_loop_x_add(ObMainLoop *loop,
ObMainLoopXHandler handler, ObMainLoopXHandler handler,
ObMainLoopXDoneHandler done_handler,
gpointer data, gpointer data,
GDestroyNotify notify); GDestroyNotify notify);
void ob_main_loop_x_remove(ObMainLoop *loop, void ob_main_loop_x_remove(ObMainLoop *loop,

View file

@ -41,7 +41,7 @@ void sn_startup(gboolean reconfig)
sn_context = sn_monitor_context_new(sn_display, ob_screen, sn_context = sn_monitor_context_new(sn_display, ob_screen,
sn_event_func, NULL, NULL); sn_event_func, NULL, NULL);
ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL, NULL); ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL);
} }
void sn_shutdown(gboolean reconfig) void sn_shutdown(gboolean reconfig)