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.
This commit is contained in:
Dana Jansens 2007-03-14 21:07:30 +00:00
parent 496c769fce
commit c80b496bf4
6 changed files with 86 additions and 194 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
static void to_top(ObClient *c, guint d)
{
focus_order[d] = g_list_remove(focus_order[d], c);
if (!c->iconic) {
focus_order[d] = g_list_prepend(focus_order[d], c);
} else {
GList *it;
/* insert before first iconic window */
for (it = focus_order[d];
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_remove(focus_order, 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)
{
focus_order[d] = g_list_remove(focus_order[d], c);
if (c->iconic) {
focus_order[d] = g_list_append(focus_order[d], c);
focus_order = g_list_remove(focus_order, c);
if (!c->iconic) {
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_bottom(ObClient *c)
{
guint d, i;
focus_order = g_list_remove(focus_order, c);
if (c->iconic) {
focus_order = g_list_append(focus_order, c);
} else {
GList *it;
d = c->desktop;
if (d == DESKTOP_ALL) {
for (i = 0; i < screen_num_desktops; ++i)
to_bottom(c, i);
} else
to_bottom(c, d);
/* insert before first iconic window */
for (it = focus_order;
it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
focus_order = g_list_insert_before(focus_order, it, c);
}
}
ObClient *focus_order_find_first(guint desktop)
{
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;
}

View file

@ -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

View file

@ -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;

View file

@ -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);
}