From 3a607fad9df628ab16e0f7436dfbfc9b22634003 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 15 Sep 2003 11:29:17 +0000 Subject: [PATCH] revert my commit of d3th, it fucked up focus badly --- openbox/client.c | 22 +++--- openbox/event.c | 154 +++++++++++++++++++++++++++------------- openbox/focus.c | 24 +++---- openbox/mainloop.c | 10 --- openbox/mainloop.h | 2 - openbox/startupnotify.c | 2 +- 6 files changed, 124 insertions(+), 90 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index 83291132..59af202a 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1647,9 +1647,7 @@ static ObStackingLayer calc_layer(ObClient *self) { ObStackingLayer l; - if (self->fullscreen && - (client_focused(self) || client_search_focus_tree(self))) - l = OB_STACKING_LAYER_FULLSCREEN; + if (self->fullscreen) l = OB_STACKING_LAYER_FULLSCREEN; else if (self->type == OB_CLIENT_TYPE_DESKTOP) l = OB_STACKING_LAYER_DESKTOP; 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; own = calc_layer(self); - self->layer = MAX(l, own); - - g_message("calc for 0x%x %d %d", self->window, old, self->layer); + self->layer = l > own ? l : own; for (it = self->transients; it; it = it->next) 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 (orig->frame) { /* only restack if the original window is managed */ + /* XXX add_non_intrusive ever? */ stacking_remove(CLIENT_AS_WINDOW(self)); stacking_add(CLIENT_AS_WINDOW(self)); } @@ -2529,15 +2526,14 @@ gboolean client_focus(ObClient *self) /* choose the correct target */ self = client_focus_target(self); - if (!self->frame->visible) { - /* update the focus lists */ - focus_order_to_top(self); + if (!client_can_focus(self)) { + if (!self->frame->visible) { + /* update the focus lists */ + focus_order_to_top(self); + } return FALSE; } - if (!client_can_focus(self)) - return FALSE; - if (self->can_focus) { /* RevertToPointerRoot causes much more headache than RevertToNone, so 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); } - focus_set_client(self); - #ifdef DEBUG_FOCUS ob_debug("%sively focusing %lx at %d\n", (self->can_focus ? "act" : "pass"), diff --git a/openbox/event.c b/openbox/event.c index 68d51135..483050fa 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -42,7 +42,6 @@ typedef struct } ObEventData; 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_menu(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 IceAddConnectionWatch(ice_watch, NULL); @@ -284,32 +283,24 @@ static void event_hack_mods(XEvent *e) static gboolean event_ignore(XEvent *e, ObClient *client) { - gboolean ignore = FALSE; - XEvent ce; - switch(e->type) { 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 because of RevertToPointerRoot. If the focus ends up reverting to pointer root on a workspace change, then the FocusIn event that we want will be of type NotifyAncestor. This situation does not occur for FocusOut, so it is safely ignored there. */ - if (ignore || INVALID_FOCUSIN(e) || client == NULL) { + if (INVALID_FOCUSIN(e) || + client == NULL) { #ifdef DEBUG_FOCUS ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n", e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif + /* says a client was not found for the event (or a valid FocusIn + event was not found. + */ + e->xfocus.window = None; return TRUE; } @@ -319,20 +310,10 @@ static gboolean event_ignore(XEvent *e, ObClient *client) #endif break; case FocusOut: - while (XCheckTypedWindowEvent(ob_display, e->xfocus.window, - FocusOut, &ce)) - { - if (!INVALID_FOCUSOUT(&ce)) { - XPutBackEvent(ob_display, &ce); - ignore = TRUE; - break; - } - } - - if (ignore || INVALID_FOCUSOUT(e)) { + if (INVALID_FOCUSOUT(e)) { #ifdef DEBUG_FOCUS - ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n", - e->xfocus.window, e->xfocus.mode, e->xfocus.detail); + ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n", + e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif return TRUE; } @@ -341,6 +322,84 @@ static gboolean event_ignore(XEvent *e, ObClient *client) ob_debug("FocusOut on %lx mode %d detail %d\n", e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #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; case EnterNotify: case LeaveNotify: @@ -354,7 +413,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client) (e->xcrossing.detail == NotifyAncestor || e->xcrossing.detail == NotifyNonlinearVirtual || e->xcrossing.detail == NotifyVirtual))) { -#ifdef aDEBUG_FOCUS +#ifdef DEBUG_FOCUS ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, @@ -362,7 +421,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client) #endif return TRUE; } -#ifdef aDEBUG_FOCUS +#ifdef DEBUG_FOCUS ob_debug("%sNotify mode %d detail %d on %lx\n", (e->type == EnterNotify ? "Enter" : "Leave"), 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) { Atom msgtype; @@ -597,22 +650,27 @@ static void event_handle_client(ObClient *client, XEvent *e) break; case FocusIn: #ifdef DEBUG_FOCUS - ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"), - client->window); + ob_debug("FocusIn on client for %lx\n", client->window); #endif - if (client != focus_client) + if (client != focus_client) { focus_set_client(client); - frame_adjust_focus(client->frame, e->type == FocusIn); + frame_adjust_focus(client->frame, TRUE); + } break; case FocusOut: #ifdef DEBUG_FOCUS - ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"), - client->window); + ob_debug("FocusOut on client for %lx\n", client->window); #endif - if (client == focus_client) - focus_client = NULL; - frame_adjust_focus(client->frame, e->type == FocusIn); - break; + /* are we a fullscreen window or a transient of one? (checks layer) + if we are then we need to be iconified since we are losing focus + */ + 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: con = frame_context(client, e->xcrossing.window); switch (con) { @@ -675,7 +733,7 @@ static void event_handle_client(ObClient *client, XEvent *e) case OB_FRAME_CONTEXT_FRAME: if (client_normal(client)) { if (config_focus_follow) { -#ifdef aDEBUG_FOCUS +#ifdef DEBUG_FOCUS ob_debug("EnterNotify on %lx, focusing window\n", client->window); #endif diff --git a/openbox/focus.c b/openbox/focus.c index 2582736b..a7904910 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -73,7 +73,7 @@ void focus_set_client(ObClient *client) screen_install_colormap(focus_client, FALSE); screen_install_colormap(client, TRUE); - if (!client) { + if (client == NULL) { /* when nothing will be focused, send focus to the backup target */ XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot, event_lasttime); @@ -87,22 +87,16 @@ void focus_set_client(ObClient *client) old = focus_client; focus_client = client; - if (old) { - /* focus state can affect the stacking layer */ - client_calc_layer(old); - } - if (client) { - /* focus state can affect the stacking layer */ - client_calc_layer(client); - - /* move to the top of the list */ + /* move to the top of the list */ + if (client != NULL) push_to_top(client); - } - /* set the NET_ACTIVE_WINDOW hint */ - active = client ? client->window : None; - PROP_SET32(RootWindow(ob_display, ob_screen), - net_active_window, window, active); + /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */ + if (ob_state() != OB_STATE_EXITING) { + active = client ? client->window : None; + PROP_SET32(RootWindow(ob_display, ob_screen), + net_active_window, window, active); + } } static gboolean focus_under_pointer() diff --git a/openbox/mainloop.c b/openbox/mainloop.c index a50a48fb..9ee20757 100644 --- a/openbox/mainloop.c +++ b/openbox/mainloop.c @@ -1,5 +1,4 @@ #include "mainloop.h" -#include "focus.h" #include #include @@ -100,7 +99,6 @@ struct _ObMainLoopXHandlerType ObMainLoop *loop; gpointer data; ObMainLoopXHandler func; - ObMainLoopXDoneHandler done_func; GDestroyNotify destroy; }; @@ -265,12 +263,6 @@ void ob_main_loop_run(ObMainLoop *loop) h->func(&e, h->data); } } 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 { /* 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, ObMainLoopXHandler handler, - ObMainLoopXDoneHandler done_handler, gpointer data, GDestroyNotify notify) { @@ -314,7 +305,6 @@ void ob_main_loop_x_add(ObMainLoop *loop, h = g_new(ObMainLoopXHandlerType, 1); h->loop = loop; h->func = handler; - h->done_func = done_handler; h->data = data; h->destroy = notify; loop->x_handlers = g_slist_prepend(loop->x_handlers, h); diff --git a/openbox/mainloop.h b/openbox/mainloop.h index f3377316..8e0e5ed6 100644 --- a/openbox/mainloop.h +++ b/openbox/mainloop.h @@ -10,11 +10,9 @@ ObMainLoop *ob_main_loop_new(Display *display); void ob_main_loop_destroy(ObMainLoop *loop); typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data); -typedef void (*ObMainLoopXDoneHandler) (gpointer data); void ob_main_loop_x_add(ObMainLoop *loop, ObMainLoopXHandler handler, - ObMainLoopXDoneHandler done_handler, gpointer data, GDestroyNotify notify); void ob_main_loop_x_remove(ObMainLoop *loop, diff --git a/openbox/startupnotify.c b/openbox/startupnotify.c index d7591f7b..ebe6e6b3 100644 --- a/openbox/startupnotify.c +++ b/openbox/startupnotify.c @@ -41,7 +41,7 @@ void sn_startup(gboolean reconfig) sn_context = sn_monitor_context_new(sn_display, ob_screen, 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) -- 2.39.2