From bfb800c032e1dd50f5d1c37d1ce8ac9239947b01 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 22 Apr 2007 19:13:38 +0000 Subject: [PATCH] a) remove focus_hilite, it is not needed and complicated things b) set focus_client to null when nothing is actually focused, but still allow focus to go to black holes c) allow the focus action to be performed without a client, this will focus the openbox instance (i.e. the screen in multihead setups) big thanks to syscrash for the ideas on how to go about this --- openbox/action.c | 30 +++++++++++++++++++++--------- openbox/event.c | 46 +++++----------------------------------------- openbox/focus.c | 45 +++++++++++++++++++++++---------------------- openbox/focus.h | 11 +++-------- openbox/screen.c | 35 +++++++++-------------------------- 5 files changed, 61 insertions(+), 106 deletions(-) diff --git a/openbox/action.c b/openbox/action.c index 5e42b68b..db49f56c 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -434,6 +434,11 @@ void setup_action_showmenu(ObAction **a, ObUserAction uact) } } +void setup_action_focus(ObAction **a, ObUserAction uact) +{ + (*a)->data.any.client_action = OB_CLIENT_ACTION_OPTIONAL; +} + void setup_client_action(ObAction **a, ObUserAction uact) { (*a)->data.any.client_action = OB_CLIENT_ACTION_ALWAYS; @@ -494,7 +499,7 @@ ActionString actionstrings[] = { "focus", action_focus, - setup_client_action + setup_action_focus }, { "unfocus", @@ -1159,15 +1164,22 @@ void action_activate(union ActionData *data) void action_focus(union ActionData *data) { - /* similar to the openbox dock for dockapps, don't let user actions give - focus to 3rd-party docks (panels) either (unless they ask for it - themselves). */ - if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) { - /* if using focus_delay, stop the timer now so that focus doesn't go - moving on us */ - event_halt_focus_delay(); + if (data->client.any.c) { + /* similar to the openbox dock for dockapps, don't let user actions + give focus to 3rd-party docks (panels) either (unless they ask for + it themselves). */ + if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) { + /* if using focus_delay, stop the timer now so that focus doesn't + go moving on us */ + event_halt_focus_delay(); - client_focus(data->client.any.c); + client_focus(data->client.any.c); + } + } else { + /* focus action on something other than a client, make keybindings + work for this openbox instance, but don't focus any specific client + */ + focus_nothing(); } } diff --git a/openbox/event.c b/openbox/event.c index 6f819cc1..65b94980 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -71,7 +71,6 @@ typedef struct } ObFocusDelayData; static void event_process(const XEvent *e, gpointer data); -static void event_client_dest(ObClient *client, 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); @@ -164,7 +163,6 @@ void event_startup(gboolean reconfig) #endif client_add_destructor(focus_delay_client_dest, NULL); - client_add_destructor(event_client_dest, NULL); } void event_shutdown(gboolean reconfig) @@ -176,7 +174,6 @@ void event_shutdown(gboolean reconfig) #endif client_remove_destructor(focus_delay_client_dest); - client_remove_destructor(event_client_dest); XFreeModifiermap(modmap); } @@ -395,11 +392,8 @@ static gboolean event_ignore(XEvent *e, ObClient *client) switch(e->type) { case FocusIn: case FocusOut: - if (!wanted_focusevent(e)) { - ob_debug_type(OB_DEBUG_FOCUS, "focus event ignored\n"); + if (!wanted_focusevent(e)) return TRUE; - } - ob_debug_type(OB_DEBUG_FOCUS, "focus event used;\n"); break; } return FALSE; @@ -442,29 +436,6 @@ static void event_process(const XEvent *ec, gpointer data) } } - if (e->type == FocusIn || e->type == FocusOut) { - gint mode = e->xfocus.mode; - gint detail = e->xfocus.detail; - Window window = e->xfocus.window; - if (detail == NotifyVirtual) { - ob_debug_type(OB_DEBUG_FOCUS, - "FOCUS %s NOTIFY VIRTUAL window 0x%x\n", - (e->type == FocusIn ? "IN" : "OUT"), window); - } - - else if (detail == NotifyNonlinearVirtual) { - ob_debug_type(OB_DEBUG_FOCUS, - "FOCUS %s NOTIFY NONLINVIRTUAL window 0x%x\n", - (e->type == FocusIn ? "IN" : "OUT"), window); - } - - else - ob_debug_type(OB_DEBUG_FOCUS, - "UNKNOWN FOCUS %s (d %d, m %d) window 0x%x\n", - (e->type == FocusIn ? "IN" : "OUT"), - detail, mode, window); - } - event_set_curtime(e); event_hack_mods(e); if (event_ignore(e, client)) { @@ -495,9 +466,9 @@ static void event_process(const XEvent *ec, gpointer data) window which had it. */ focus_fallback(FALSE); } else if (client && client != focus_client) { - focus_set_client(client); frame_adjust_focus(client->frame, TRUE); client_calc_layer(client); + focus_set_client(client); } } else if (e->type == FocusOut) { gboolean nomove = FALSE; @@ -510,6 +481,8 @@ static void event_process(const XEvent *ec, gpointer data) /* There is no FocusIn, this means focus went to a window that is not being managed, or a window on another screen. */ ob_debug_type(OB_DEBUG_FOCUS, "Focus went to a black hole !\n"); + /* nothing is focused */ + focus_set_client(NULL); } else if (ce.xany.window == e->xany.window) { /* If focus didn't actually move anywhere, there is nothing to do*/ nomove = TRUE; @@ -528,8 +501,6 @@ static void event_process(const XEvent *ec, gpointer data) } if (client && !nomove) { - /* This client is no longer focused, so show that */ - focus_hilite = NULL; frame_adjust_focus(client->frame, FALSE); client_calc_layer(client); } @@ -594,8 +565,7 @@ static void event_process(const XEvent *ec, gpointer data) mouse_event(client, e); } else if (e->type == KeyPress) { keyboard_event((focus_cycle_target ? focus_cycle_target : - (focus_hilite ? focus_hilite : client)), - e); + client), e); } } } @@ -1376,12 +1346,6 @@ static void focus_delay_client_dest(ObClient *client, gpointer data) client, FALSE); } -static void event_client_dest(ObClient *client, gpointer data) -{ - if (client == focus_hilite) - focus_hilite = NULL; -} - void event_halt_focus_delay() { ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func); diff --git a/openbox/focus.c b/openbox/focus.c index ea3d4fab..7a686800 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -37,9 +37,9 @@ #include #include -ObClient *focus_client, *focus_hilite; -GList *focus_order; -ObClient *focus_cycle_target; +ObClient *focus_client = NULL; +GList *focus_order = NULL; +ObClient *focus_cycle_target = NULL; struct { InternalWindow top; @@ -81,7 +81,7 @@ void focus_startup(gboolean reconfig) client_add_destructor(focus_cycle_destructor, NULL); /* start with nothing focused */ - focus_set_client(NULL); + focus_nothing(); focus_indicator.top.obwin.type = Window_Internal; focus_indicator.left.obwin.type = Window_Internal; @@ -156,7 +156,6 @@ static void push_to_top(ObClient *client) void focus_set_client(ObClient *client) { Window active; - ObClient *old; ob_debug_type(OB_DEBUG_FOCUS, "focus_set_client 0x%lx\n", client ? client->window : 0); @@ -165,37 +164,26 @@ void focus_set_client(ObClient *client) screen_install_colormap(focus_client, FALSE); screen_install_colormap(client, TRUE); - if (client == NULL) { - ob_debug_type(OB_DEBUG_FOCUS, "actively focusing NONWINDOW\n"); - - /* when nothing will be focused, send focus to the backup target */ - XSetInputFocus(ob_display, screen_support_win, RevertToNone, - event_curtime); - XSync(ob_display, FALSE); - } - /* in the middle of cycling..? kill it. CurrentTime is fine, time won't be used. */ if (focus_cycle_target) focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); - old = focus_client; focus_client = client; - /* move to the top of the list */ - if (client != NULL) + if (client != NULL) { + /* move to the top of the list */ push_to_top(client); + /* remove hiliting from the window when it gets focused */ + client_hilite(client, FALSE); + } /* 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); - - /* remove hiliting from the window when it gets focused */ - if (client != NULL) - client_hilite(client, FALSE); } } @@ -280,12 +268,25 @@ void focus_fallback(gboolean allow_refocus) and such, and then when I try focus them, I won't get a FocusIn event at all for them. */ - focus_set_client(NULL); + focus_nothing(); if ((new = focus_fallback_target(allow_refocus, old))) client_focus(new); } +void focus_nothing() +{ + /* Install our own colormap */ + if (focus_client != NULL) { + screen_install_colormap(focus_client, FALSE); + screen_install_colormap(NULL, TRUE); + } + + /* when nothing will be focused, send focus to the backup target */ + XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot, + event_curtime); +} + static void popup_cycle(ObClient *c, gboolean show) { if (!show) { diff --git a/openbox/focus.h b/openbox/focus.h index 1366cd08..5ed9977c 100644 --- a/openbox/focus.h +++ b/openbox/focus.h @@ -29,14 +29,6 @@ struct _ObClient; /*! The client which is currently focused */ extern struct _ObClient *focus_client; -/*! The client which is being decorated as focused, not always matching the - real focus, but this is used to track it so that it can be resolved to match. - - This is for when you change desktops. We know which window is *going to be* - focused, so we hilight it. But since it's hilighted, we also want - keybindings to go to it, which is really what this is for. -*/ -extern struct _ObClient *focus_hilite; /*! The client which appears focused during a focus cycle operation */ extern struct _ObClient *focus_cycle_target; @@ -50,6 +42,9 @@ void focus_shutdown(gboolean reconfig); send focus anywhere, its called by the Focus event handlers */ void focus_set_client(struct _ObClient *client); +/*! Focus nothing, but let keyboard events be caught. */ +void focus_nothing(); + struct _ObClient* focus_fallback_target(gboolean allow_refocus, struct _ObClient *old); diff --git a/openbox/screen.c b/openbox/screen.c index c6a6b0e5..a54b2b56 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -422,6 +422,7 @@ void screen_set_num_desktops(guint num) void screen_set_desktop(guint num) { + ObClient *c; GList *it; guint old; @@ -459,19 +460,10 @@ void screen_set_desktop(guint num) } } - focus_hilite = focus_fallback_target(TRUE, focus_client); - if (focus_hilite) { - frame_adjust_focus(focus_hilite->frame, TRUE); - - /*! - When this focus_client check is not used, you can end up with - races, as demonstrated with gnome-panel, sometimes the window - you click on another desktop ends up losing focus cuz of the - focus change here. - */ - /*if (!focus_client)*/ - client_focus(focus_hilite); - } + /* reduce flicker by hiliting now rather than waiting for the server + FocusIn event */ + if ((c = focus_fallback_target(TRUE, focus_client))) + frame_adjust_focus(c->frame, TRUE); event_ignore_queued_enters(); } @@ -895,21 +887,12 @@ void screen_show_desktop(gboolean show) break; } } else { + ObClient *c; + /* use NULL for the "old" argument because the desktop was focused and we don't want to fallback to the desktop by default */ - focus_hilite = focus_fallback_target(TRUE, NULL); - if (focus_hilite) { - frame_adjust_focus(focus_hilite->frame, TRUE); - - /*! - When this focus_client check is not used, you can end up with - races, as demonstrated with gnome-panel, sometimes the window - you click on another desktop ends up losing focus cuz of the - focus change here. - */ - /*if (!focus_client)*/ - client_focus(focus_hilite); - } + if ((c = focus_fallback_target(TRUE, NULL))) + client_focus(c); } show = !!show; /* make it boolean */ -- 2.45.2