X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Ffocus_cycle.c;h=07cc2e83d4e5a8cf1b0fc9d65df9f9bc6ceecc1a;hb=b8e994e837d260860a4dc0a1ee3a680e2cdfc75a;hp=2697820433260f848ecd81a76323c08593fac467;hpb=aac72915273dcd4bfeb606d04ff794304c4e1332;p=chaz%2Fopenbox diff --git a/openbox/focus_cycle.c b/openbox/focus_cycle.c index 26978204..07cc2e83 100644 --- a/openbox/focus_cycle.c +++ b/openbox/focus_cycle.c @@ -26,24 +26,21 @@ #include "screen.h" #include "openbox.h" #include "debug.h" -#include "group.h" #include #include ObClient *focus_cycle_target = NULL; +static gboolean focus_cycle_directional = FALSE; static gboolean focus_cycle_iconic_windows; static gboolean focus_cycle_all_desktops; static gboolean focus_cycle_dock_windows; static gboolean focus_cycle_desktop_windows; -static gboolean focus_target_has_siblings (ObClient *ft, - gboolean iconic_windows, - gboolean all_desktops); -static ObClient *focus_find_directional (ObClient *c, - ObDirection dir, - gboolean dock_windows, - gboolean desktop_windows); +static ObClient *focus_find_directional(ObClient *c, + ObDirection dir, + gboolean dock_windows, + gboolean desktop_windows); void focus_cycle_startup(gboolean reconfig) { @@ -55,124 +52,81 @@ void focus_cycle_shutdown(gboolean reconfig) if (reconfig) return; } -void focus_cycle_stop(ObClient *ifclient) +void focus_cycle_add(ObClient *ifclient) { - /* stop focus cycling if the given client is a valid focus target, - and so the cycling is being disrupted */ - if (focus_cycle_target && ifclient && - focus_cycle_target_valid(ifclient, - focus_cycle_iconic_windows, - focus_cycle_all_desktops, - focus_cycle_dock_windows, - focus_cycle_desktop_windows)) - { - focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); - focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); - } + if (!(focus_cycle_target && ifclient && !focus_cycle_directional)) + return; + + if (focus_valid_target(ifclient, TRUE, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows, + FALSE)) + focus_cycle_popup_refresh(focus_cycle_target, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows); } -/*! Returns if a focus target has valid group siblings that can be cycled - to in its place */ -static gboolean focus_target_has_siblings(ObClient *ft, - gboolean iconic_windows, - gboolean all_desktops) - +void focus_cycle_remove(ObClient *ifclient) { - GSList *it; - - if (!ft->group) return FALSE; + if (!(focus_cycle_target && ifclient)) + return; - for (it = ft->group->members; it; it = g_slist_next(it)) { - ObClient *c = it->data; - /* check that it's not a helper window to avoid infinite recursion */ - if (c != ft && !client_helper(c) && - focus_cycle_target_valid(c, iconic_windows, all_desktops, FALSE, - FALSE)) - { - return TRUE; + if (focus_cycle_directional) { + if (focus_cycle_target == ifclient) { + focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE); + } + } + else { + if (!focus_valid_target(ifclient, TRUE, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows, + FALSE)) { + if (focus_cycle_target == ifclient) { + focus_cycle_target = + focus_cycle_popup_revert(focus_cycle_target); + focus_cycle_update_indicator(focus_cycle_target); + } + focus_cycle_popup_refresh(focus_cycle_target, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows); } } - return FALSE; } -gboolean focus_cycle_target_valid(ObClient *ft, - gboolean iconic_windows, - gboolean all_desktops, - gboolean dock_windows, - gboolean desktop_windows) +void focus_cycle_reorder() { - gboolean ok = FALSE; - - /* it's on this desktop unless you want all desktops. - - do this check first because it will usually filter out the most - windows */ - ok = (all_desktops || ft->desktop == screen_desktop || - ft->desktop == DESKTOP_ALL); - - /* the window can receive focus somehow */ - ok = ok && (ft->can_focus || ft->focus_notify); - - /* the window is not iconic, or we're allowed to go to iconic ones */ - ok = ok && (iconic_windows || !ft->iconic); - - /* it's the right type of window */ - if (dock_windows || desktop_windows) - ok = ok && ((dock_windows && ft->type == OB_CLIENT_TYPE_DOCK) || - (desktop_windows && ft->type == OB_CLIENT_TYPE_DESKTOP)); - /* modal windows are important and can always get focus if they are - visible and stuff, so don't change 'ok' based on their type */ - else if (!ft->modal) - /* normal non-helper windows are valid targets */ - ok = ok && - ((client_normal(ft) && !client_helper(ft)) - || - /* helper windows are valid targets it... */ - (client_helper(ft) && - /* ...a window in its group already has focus ... */ - ((focus_client && ft->group == focus_client->group) || - /* ... or if there are no other windows in its group - that can be cycled to instead */ - !focus_target_has_siblings(ft, iconic_windows, all_desktops)))); - - /* it's not set to skip the taskbar (unless it is a type that would be - expected to set this hint, or modal) */ - ok = ok && ((ft->type == OB_CLIENT_TYPE_DOCK || - ft->type == OB_CLIENT_TYPE_DESKTOP || - ft->type == OB_CLIENT_TYPE_TOOLBAR || - ft->type == OB_CLIENT_TYPE_MENU || - ft->type == OB_CLIENT_TYPE_UTILITY) || - ft->modal || - !ft->skip_taskbar); - - /* it's not going to just send focus off somewhere else (modal window), - unless that modal window is not one of our valid targets, then let - you choose this window and bring the modal one here */ - { - ObClient *cft = client_focus_target(ft); - ok = ok && (ft == cft || !focus_cycle_target_valid(cft, - iconic_windows, - all_desktops, - dock_windows, - desktop_windows)); - } - - return ok; + if (focus_cycle_target && !focus_cycle_directional) + focus_cycle_popup_refresh(focus_cycle_target, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows); } -void focus_cycle(gboolean forward, gboolean all_desktops, - gboolean dock_windows, gboolean desktop_windows, - gboolean linear, gboolean interactive, - gboolean dialog, gboolean done, gboolean cancel) +ObClient* focus_cycle(gboolean forward, gboolean all_desktops, + gboolean dock_windows, gboolean desktop_windows, + gboolean linear, gboolean interactive, + gboolean showbar, gboolean dialog, + gboolean done, gboolean cancel) { - static ObClient *t = NULL; static GList *order = NULL; GList *it, *start, *list; ObClient *ft = NULL; + ObClient *ret = NULL; if (interactive) { if (cancel) { focus_cycle_target = NULL; + focus_cycle_directional = FALSE; goto done_cycle; } else if (done) goto done_cycle; @@ -188,7 +142,6 @@ void focus_cycle(gboolean forward, gboolean all_desktops, list = client_list; } - if (focus_cycle_target == NULL) { focus_cycle_iconic_windows = TRUE; focus_cycle_all_desktops = all_desktops; @@ -211,16 +164,18 @@ void focus_cycle(gboolean forward, gboolean all_desktops, if (it == NULL) it = g_list_last(list); } ft = it->data; - if (focus_cycle_target_valid(ft, - focus_cycle_iconic_windows, - focus_cycle_all_desktops, - focus_cycle_dock_windows, - focus_cycle_desktop_windows)) + if (focus_valid_target(ft, TRUE, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows, + FALSE)) { if (interactive) { if (ft != focus_cycle_target) { /* prevents flicker */ focus_cycle_target = ft; - focus_cycle_draw_indicator(ft); + focus_cycle_directional = FALSE; + focus_cycle_draw_indicator(showbar ? ft : NULL); } if (dialog) /* same arguments as focus_target_valid */ @@ -229,9 +184,10 @@ void focus_cycle(gboolean forward, gboolean all_desktops, focus_cycle_all_desktops, focus_cycle_dock_windows, focus_cycle_desktop_windows); - return; + return focus_cycle_target; } else if (ft != focus_cycle_target) { focus_cycle_target = ft; + focus_cycle_directional = FALSE; done = TRUE; break; } @@ -239,11 +195,10 @@ void focus_cycle(gboolean forward, gboolean all_desktops, } while (it != start); done_cycle: - if (done && focus_cycle_target) - client_activate(focus_cycle_target, FALSE, TRUE); + if (done && !cancel) ret = focus_cycle_target; - t = NULL; focus_cycle_target = NULL; + focus_cycle_directional = FALSE; g_list_free(order); order = NULL; @@ -252,13 +207,13 @@ done_cycle: focus_cycle_popup_hide(); } - return; + return ret; } /* this be mostly ripped from fvwm */ static ObClient *focus_find_directional(ObClient *c, ObDirection dir, gboolean dock_windows, - gboolean desktop_windows) + gboolean desktop_windows) { gint my_cx, my_cy, his_cx, his_cy; gint offset = 0; @@ -283,8 +238,8 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir, /* the currently selected window isn't interesting */ if (cur == c) continue; - if (!focus_cycle_target_valid(it->data, FALSE, FALSE, dock_windows, - desktop_windows)) + if (!focus_valid_target(it->data, TRUE, FALSE, FALSE, dock_windows, + desktop_windows, FALSE)) continue; /* find the centre coords of this window, from the @@ -351,20 +306,21 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir, return best_client; } -void focus_directional_cycle(ObDirection dir, gboolean dock_windows, - gboolean desktop_windows, gboolean interactive, - gboolean dialog, gboolean done, gboolean cancel) +ObClient* focus_directional_cycle(ObDirection dir, gboolean dock_windows, + gboolean desktop_windows, + gboolean interactive, + gboolean showbar, gboolean dialog, + gboolean done, gboolean cancel) { static ObClient *first = NULL; ObClient *ft = NULL; - - if (!interactive) - return; + ObClient *ret = NULL; if (cancel) { focus_cycle_target = NULL; + focus_cycle_directional = FALSE; goto done_cycle; - } else if (done) + } else if (done && interactive) goto done_cycle; if (!focus_order) @@ -388,39 +344,39 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows, GList *it; for (it = focus_order; it; it = g_list_next(it)) - if (focus_cycle_target_valid(it->data, - focus_cycle_iconic_windows, - focus_cycle_all_desktops, - focus_cycle_dock_windows, - focus_cycle_desktop_windows)) + if (focus_valid_target(it->data, TRUE, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows, FALSE)) ft = it->data; } - - if (ft) { - if (ft != focus_cycle_target) {/* prevents flicker */ - focus_cycle_target = ft; - focus_cycle_draw_indicator(ft); - } + + if (ft && ft != focus_cycle_target) {/* prevents flicker */ + focus_cycle_target = ft; + focus_cycle_directional = TRUE; + if (!interactive) + goto done_cycle; + focus_cycle_draw_indicator(showbar ? ft : NULL); } - if (focus_cycle_target && dialog) { + if (focus_cycle_target && dialog) /* same arguments as focus_target_valid */ focus_cycle_popup_single_show(focus_cycle_target, focus_cycle_iconic_windows, focus_cycle_all_desktops, focus_cycle_dock_windows, focus_cycle_desktop_windows); - } - return; + return focus_cycle_target; done_cycle: - if (done && focus_cycle_target) - client_activate(focus_cycle_target, FALSE, TRUE); + if (done && !cancel) ret = focus_cycle_target; first = NULL; focus_cycle_target = NULL; + focus_cycle_directional = FALSE; focus_cycle_draw_indicator(NULL); focus_cycle_popup_single_hide(); - return; + return ret; }