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:
parent
496c769fce
commit
c80b496bf4
6 changed files with 86 additions and 194 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
239
openbox/focus.c
239
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue