summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2007-03-14 21:07:30 +0000
committerDana Jansens <danakj@orodu.net>2007-03-14 21:07:30 +0000
commitc80b496bf407d73bea169058abfcda44effad0dd (patch)
treefca8985046322baf23147257a0b325bfa30e1d34
parent496c769fcec42dc3092a9f128d270ff1a4f2e64b (diff)
make focus_order into one long list instead of having one per desktop. this actually fixes bugs with omnipresent windows and adding desktops. it is just overall a little nicer i think.
also this is not tested. sorry if it breaks everything.
-rw-r--r--openbox/client_list_combined_menu.c6
-rw-r--r--openbox/client_list_menu.c6
-rw-r--r--openbox/focus.c223
-rw-r--r--openbox/focus.h4
-rw-r--r--openbox/place.c6
-rw-r--r--openbox/screen.c19
6 files changed, 78 insertions, 186 deletions
diff --git a/openbox/client_list_combined_menu.c b/openbox/client_list_combined_menu.c
index f590dc10..39a8e60b 100644
--- a/openbox/client_list_combined_menu.c
+++ b/openbox/client_list_combined_menu.c
@@ -55,9 +55,11 @@ static void self_update(ObMenuFrame *frame, gpointer data)
e->data.normal.label = g_strdup(screen_desktop_names[desktop]);
/* The one at the bottom will always have entries below it though */
menu_add_separator(menu, -1);
- for (it = focus_order[desktop], i = 0; it; it = g_list_next(it), ++i) {
+ for (it = focus_order, i = 0; it; it = g_list_next(it), ++i) {
ObClient *c = it->data;
- if (client_normal(c) && (!c->skip_taskbar || c->iconic)) {
+ if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&
+ (c->desktop == desktop || c->desktop == DESKTOP_ALL))
+ {
GSList *acts = NULL;
ObAction* act;
const ObClientIcon *icon;
diff --git a/openbox/client_list_menu.c b/openbox/client_list_menu.c
index d703babd..f49f623b 100644
--- a/openbox/client_list_menu.c
+++ b/openbox/client_list_menu.c
@@ -49,9 +49,11 @@ static void desk_menu_update(ObMenuFrame *frame, gpointer data)
menu_clear_entries(menu);
- for (it = focus_order[d->desktop], i = 0; it; it = g_list_next(it), ++i) {
+ for (it = focus_order, i = 0; it; it = g_list_next(it), ++i) {
ObClient *c = it->data;
- if (client_normal(c) && (!c->skip_taskbar || c->iconic)) {
+ if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&
+ (c->desktop == d->desktop || c->desktop == DESKTOP_ALL))
+ {
GSList *acts = NULL;
ObAction* act;
ObMenuEntry *e;
diff --git a/openbox/focus.c b/openbox/focus.c
index d18b3a1f..4be187b9 100644
--- a/openbox/focus.c
+++ b/openbox/focus.c
@@ -38,8 +38,7 @@
#include <assert.h>
ObClient *focus_client, *focus_hilite;
-GList **focus_order; /* these lists are created when screen_startup
- sets the number of desktops */
+GList *focus_order;
ObClient *focus_cycle_target;
struct {
@@ -129,17 +128,11 @@ void focus_startup(gboolean reconfig)
void focus_shutdown(gboolean reconfig)
{
- guint i;
-
icon_popup_free(focus_cycle_popup);
if (!reconfig) {
client_remove_destructor(focus_cycle_destructor);
- for (i = 0; i < screen_num_desktops; ++i)
- g_list_free(focus_order[i]);
- g_free(focus_order);
-
/* reset focus to root */
XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
@@ -156,12 +149,8 @@ void focus_shutdown(gboolean reconfig)
static void push_to_top(ObClient *client)
{
- guint desktop;
-
- desktop = client->desktop;
- if (desktop == DESKTOP_ALL) desktop = screen_desktop;
- focus_order[desktop] = g_list_remove(focus_order[desktop], client);
- focus_order[desktop] = g_list_prepend(focus_order[desktop], client);
+ focus_order = g_list_remove(focus_order, client);
+ focus_order = g_list_prepend(focus_order, client);
}
void focus_set_client(ObClient *client)
@@ -212,87 +201,11 @@ void focus_set_client(ObClient *client)
}
}
-/* finds the first transient that isn't 'skip' and ensure's that client_normal
- is true for it */
-static ObClient *find_transient_recursive(ObClient *c, ObClient *top,
- ObClient *skip)
-{
- GSList *it;
- ObClient *ret;
-
- for (it = c->transients; it; it = g_slist_next(it)) {
- if (it->data == top) return NULL;
- ret = find_transient_recursive(it->data, top, skip);
- if (ret && ret != skip && client_normal(ret) &&
- client_can_focus(ret) && client_validate(ret))
- return ret;
- if (it->data != skip && client_normal(it->data) &&
- client_can_focus(it->data) && client_validate(it->data))
- return it->data;
- }
- return NULL;
-}
-
-static ObClient* focus_fallback_transient(ObClient *top, ObClient *old)
-{
- ObClient *target = find_transient_recursive(top, top, old);
- if (!target) {
- /* make sure client_normal is true always */
- if (!client_normal(top))
- return NULL;
- target = top; /* no transient, keep the top */
- }
- if (client_can_focus(target))
- return target;
- else
- return NULL;
-}
-
ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old)
{
GList *it;
ObClient *target = NULL;
-
- if (!allow_refocus && old && old->transient_for) {
- gboolean trans = FALSE;
-
- if (!config_focus_follow || config_focus_last)
- trans = TRUE;
- else if ((target = client_under_pointer()) &&
- client_search_transient
- (client_search_top_parent(target), old))
- trans = TRUE;
-
- /* try for transient relations */
- if (trans) {
- if (old->transient_for == OB_TRAN_GROUP) {
- for (it = focus_order[screen_desktop]; it;
- it = g_list_next(it))
- {
- GSList *sit;
-
- for (sit = old->group->members; sit;
- sit = g_slist_next(sit))
- {
- if (sit->data == it->data)
- if ((target =
- focus_fallback_transient(sit->data, old)))
- {
- ob_debug("found in transient #1\n");
- return target;
- }
- }
- }
- } else {
- if ((target =
- focus_fallback_transient(old->transient_for, old)))
- {
- ob_debug("found in transient #2\n");
- return target;
- }
- }
- }
- }
+ ObClient *desktop = NULL;
ob_debug("trying pointer stuff\n");
if (config_focus_follow && !config_focus_last)
@@ -321,21 +234,34 @@ ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old)
#endif
ob_debug("trying the focus order\n");
- for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
- if (allow_refocus || it->data != old)
- if (client_normal(it->data) && client_can_focus(it->data) &&
- client_validate(it->data))
+ for (it = focus_order; it; it = g_list_next(it))
+ if (allow_refocus || it->data != old) {
+ ObClient *c = it->data;
+ /* fallback focus to a window if:
+ 1. it is actually focusable, cuz if it's not then we're sending
+ focus off to nothing
+ 2. it is validated. if the window is about to disappear, then
+ don't try focus it.
+ 3. it is visible on the screen right now.
+ 4. it is a normal type window, don't fall back onto a dock or
+ a splashscreen or a desktop window (save the desktop as a
+ backup fallback though)
+ */
+ if (client_can_focus(c) && client_validate(c) &&
+ client_should_show(c))
{
- ob_debug("found in focus order\n");
- return it->data;
+ if (client_normal(c)) {
+ ob_debug("found in focus order\n");
+ return it->data;
+ } else if (c->type == OB_CLIENT_TYPE_DESKTOP && !desktop)
+ desktop = c;
}
+ }
- /* XXX fallback to the "desktop window" if one exists ?
- could store it while going through all the windows in the loop right
- above this..
+ /* as a last resort fallback to the desktop window if there is one.
+ (if there's more than one, then the one last focused.)
*/
-
- return NULL;
+ return desktop;
}
void focus_fallback(gboolean allow_refocus)
@@ -579,15 +505,15 @@ void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
} else if (done)
goto done_cycle;
- if (!focus_order[screen_desktop])
+ if (!focus_order)
goto done_cycle;
if (!first) first = focus_client;
if (linear) list = client_list;
- else list = focus_order[screen_desktop];
+ else list = focus_order;
} else {
- if (!focus_order[screen_desktop])
+ if (!focus_order)
goto done_cycle;
list = client_list;
}
@@ -657,7 +583,7 @@ void focus_directional_cycle(ObDirection dir, gboolean interactive,
} else if (done)
goto done_cycle;
- if (!focus_order[screen_desktop])
+ if (!focus_order)
goto done_cycle;
if (!first) first = focus_client;
@@ -668,7 +594,7 @@ void focus_directional_cycle(ObDirection dir, gboolean interactive,
else {
GList *it;
- for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
+ for (it = focus_order; it; it = g_list_next(it))
if (valid_focus_target(it->data))
ft = it->data;
}
@@ -701,92 +627,61 @@ done_cycle:
void focus_order_add_new(ObClient *c)
{
- guint d, i;
-
if (c->iconic)
focus_order_to_top(c);
else {
- d = c->desktop;
- if (d == DESKTOP_ALL) {
- for (i = 0; i < screen_num_desktops; ++i) {
- g_assert(!g_list_find(focus_order[i], c));
- if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic)
- focus_order[i] = g_list_insert(focus_order[i], c, 0);
- else
- focus_order[i] = g_list_insert(focus_order[i], c, 1);
- }
- } else {
- g_assert(!g_list_find(focus_order[d], c));
- if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
- focus_order[d] = g_list_insert(focus_order[d], c, 0);
- else
- focus_order[d] = g_list_insert(focus_order[d], c, 1);
- }
+ g_assert(!g_list_find(focus_order, c));
+ /* if there are any iconic windows, put this above them in the order,
+ but if there are not, then put it under the currently focused one */
+ if (focus_order && ((ObClient*)focus_order->data)->iconic)
+ focus_order = g_list_insert(focus_order, c, 0);
+ else
+ focus_order = g_list_insert(focus_order, c, 1);
}
}
void focus_order_remove(ObClient *c)
{
- guint d, i;
-
- d = c->desktop;
- if (d == DESKTOP_ALL) {
- for (i = 0; i < screen_num_desktops; ++i)
- focus_order[i] = g_list_remove(focus_order[i], c);
- } else
- focus_order[d] = g_list_remove(focus_order[d], c);
+ focus_order = g_list_remove(focus_order, c);
}
-static void to_top(ObClient *c, guint d)
+void focus_order_to_top(ObClient *c)
{
- focus_order[d] = g_list_remove(focus_order[d], c);
+ focus_order = g_list_remove(focus_order, c);
if (!c->iconic) {
- focus_order[d] = g_list_prepend(focus_order[d], c);
+ focus_order = g_list_prepend(focus_order, c);
} else {
GList *it;
/* insert before first iconic window */
- for (it = focus_order[d];
+ for (it = focus_order;
it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
- focus_order[d] = g_list_insert_before(focus_order[d], it, c);
+ focus_order = g_list_insert_before(focus_order, it, c);
}
}
-void focus_order_to_top(ObClient *c)
-{
- guint d, i;
-
- d = c->desktop;
- if (d == DESKTOP_ALL) {
- for (i = 0; i < screen_num_desktops; ++i)
- to_top(c, i);
- } else
- to_top(c, d);
-}
-
-static void to_bottom(ObClient *c, guint d)
+void focus_order_to_bottom(ObClient *c)
{
- focus_order[d] = g_list_remove(focus_order[d], c);
+ focus_order = g_list_remove(focus_order, c);
if (c->iconic) {
- focus_order[d] = g_list_append(focus_order[d], c);
+ focus_order = g_list_append(focus_order, c);
} else {
GList *it;
/* insert before first iconic window */
- for (it = focus_order[d];
+ for (it = focus_order;
it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
- focus_order[d] = g_list_insert_before(focus_order[d], it, c);
+ focus_order = g_list_insert_before(focus_order, it, c);
}
}
-void focus_order_to_bottom(ObClient *c)
+ObClient *focus_order_find_first(guint desktop)
{
- guint d, i;
-
- d = c->desktop;
- if (d == DESKTOP_ALL) {
- for (i = 0; i < screen_num_desktops; ++i)
- to_bottom(c, i);
- } else
- to_bottom(c, d);
+ GList *it;
+ for (it = focus_order; it; it = g_list_next(it)) {
+ ObClient *c = it->data;
+ if (c->desktop == desktop || c->desktop == DESKTOP_ALL)
+ return c;
+ }
+ return NULL;
}
diff --git a/openbox/focus.h b/openbox/focus.h
index 200d96a5..e1d6a6c4 100644
--- a/openbox/focus.h
+++ b/openbox/focus.h
@@ -41,7 +41,7 @@ extern struct _ObClient *focus_hilite;
extern struct _ObClient *focus_cycle_target;
/*! The recent focus order on each desktop */
-extern GList **focus_order;
+extern GList *focus_order;
void focus_startup(gboolean reconfig);
void focus_shutdown(gboolean reconfig);
@@ -77,4 +77,6 @@ void focus_order_to_top(struct _ObClient *c);
very bottom always though). */
void focus_order_to_bottom(struct _ObClient *c);
+struct _ObClient *focus_order_find_first(guint desktop);
+
#endif
diff --git a/openbox/place.c b/openbox/place.c
index 260299b3..ada0d7c3 100644
--- a/openbox/place.c
+++ b/openbox/place.c
@@ -297,11 +297,9 @@ static gboolean place_smart(ObClient *client, gint *x, gint *y,
if (type == SMART_FULL || type == SMART_FOCUSED) {
gboolean found_foc = FALSE, stop = FALSE;
ObClient *foc;
- GList *list;
- list = focus_order[client->desktop == DESKTOP_ALL ?
- screen_desktop : client->desktop];
- foc = list ? list->data : NULL;
+ foc = focus_order_find_first(client->desktop == DESKTOP_ALL ?
+ screen_desktop : client->desktop);
for (; it && !stop; it = g_list_next(it)) {
ObClient *c;
diff --git a/openbox/screen.c b/openbox/screen.c
index 70de299d..8f1f9396 100644
--- a/openbox/screen.c
+++ b/openbox/screen.c
@@ -372,7 +372,7 @@ void screen_resize()
void screen_set_num_desktops(guint num)
{
- guint i, old;
+ guint old;
gulong *viewport;
GList *it;
@@ -410,16 +410,6 @@ void screen_set_num_desktops(guint num)
/* change our desktop if we're on one that no longer exists! */
if (screen_desktop >= screen_num_desktops)
screen_set_desktop(num - 1);
-
- /* update the focus lists */
- /* free our lists for the desktops which have disappeared */
- for (i = num; i < old; ++i)
- g_list_free(focus_order[i]);
- /* realloc the array */
- focus_order = g_renew(GList*, focus_order, num);
- /* set the new lists to be empty */
- for (i = old; i < num; ++i)
- focus_order[i] = NULL;
}
void screen_set_desktop(guint num)
@@ -888,10 +878,13 @@ void screen_show_desktop(gboolean show)
if (show) {
/* focus desktop */
- for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
- if (((ObClient*)it->data)->type == OB_CLIENT_TYPE_DESKTOP &&
+ for (it = focus_order; it; it = g_list_next(it)) {
+ ObClient *c = it->data;
+ if (c->type == OB_CLIENT_TYPE_DESKTOP &&
+ (c->desktop == screen_desktop || c->desktop == DESKTOP_ALL) &&
client_validate(it->data) && client_focus(it->data))
break;
+ }
} else {
focus_fallback(TRUE);
}