Replace tag_t lists with arrays.

This improves lots of code efficiency (we *know* how many tags we have
now, YA'RLY).

Also fix a \todo in client.c: since knowing the number of tags is cheap,
ignore props that don't match it.

Use many p_alloca for things that depends on the number of tags (no sane
user will have *thousands* of tags. This saves a few more mallocs.

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
This commit is contained in:
Pierre Habouzit 2008-06-23 17:37:19 +02:00
parent 236ccc165c
commit 14f4e02e66
8 changed files with 145 additions and 179 deletions

View File

@ -61,7 +61,6 @@ DO_LUA_EQ(client_t, client, "client")
/** Load windows properties, restoring client's tag /** Load windows properties, restoring client's tag
* and floating state before awesome was restarted if any. * and floating state before awesome was restarted if any.
* \todo This may bug if number of tags is != than before.
* \param c A client pointer. * \param c A client pointer.
* \param screen A virtual screen. * \param screen A virtual screen.
* \return True if client had property, false otherwise. * \return True if client had property, false otherwise.
@ -69,38 +68,32 @@ DO_LUA_EQ(client_t, client, "client")
static bool static bool
client_loadprops(client_t * c, screen_t *screen) client_loadprops(client_t * c, screen_t *screen)
{ {
int i, ntags = 0; tag_array_t *tags = &screen->tags;
tag_t *tag;
char *prop = NULL; char *prop = NULL;
bool result = false;
for(tag = screen->tags; tag; tag = tag->next) if(!xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
ntags++;
if(xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms, xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
xutil_intern_atom(globalconf.connection, xutil_intern_atom(globalconf.connection,
&globalconf.atoms, &globalconf.atoms,
"_AWESOME_PROPERTIES")), "_AWESOME_PROPERTIES")),
&prop)) &prop))
{ return false;
for(i = 0, tag = screen->tags; tag && i < ntags && prop[i]; i++, tag = tag->next)
if(prop[i] == '1')
{
tag_client(c, tag);
result = true;
}
else
untag_client(c, tag);
if(prop[i])
client_setfloating(c, prop[i] == '1',
(prop[i + 1] >= 0 && prop[i + 1] <= LAYER_FULLSCREEN) ? atoi(&prop[i + 1]) : prop[i] == '1' ? LAYER_FLOAT : LAYER_TILE);
}
if (strlen(prop) != tags->len + 2) {
/* ignore property if the tag count isn't matching */
p_delete(&prop); p_delete(&prop);
return false;
}
return result; for(int i = 0; i < tags->len; i++)
if(prop[i] == '1')
tag_client(c, tags->tab[i]);
else
untag_client(c, tags->tab[i]);
client_setfloating(c, prop[tags->len] == '1', prop[tags->len + 1] - '0');
p_delete(&prop);
return true;
} }
/** Check if client supports protocol WM_DELETE_WINDOW. /** Check if client supports protocol WM_DELETE_WINDOW.
@ -139,12 +132,13 @@ window_isprotodel(xcb_window_t win)
bool bool
client_isvisible(client_t *c, int screen) client_isvisible(client_t *c, int screen)
{ {
tag_t *tag;
if(c && !c->ishidden && c->screen == screen) if(c && !c->ishidden && c->screen == screen)
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) {
if(tag->selected && is_client_tagged(c, tag)) tag_array_t *tags = &globalconf.screens[screen].tags;
for(int i = 0; i < tags->len; i++)
if(tags->tab[i]->selected && is_client_tagged(c, tags->tab[i]))
return true; return true;
}
return false; return false;
} }
@ -345,7 +339,6 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
client_t *c, *t = NULL; client_t *c, *t = NULL;
xcb_window_t trans; xcb_window_t trans;
bool rettrans, retloadprops; bool rettrans, retloadprops;
tag_t *tag;
xcb_size_hints_t *u_size_hints; xcb_size_hints_t *u_size_hints;
const uint32_t select_input_val[] = { const uint32_t select_input_val[] = {
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE |
@ -383,9 +376,12 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
/* check for transient and set tags like its parent */ /* check for transient and set tags like its parent */
if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans)) if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans))
&& (t = client_getbywin(trans))) && (t = client_getbywin(trans)))
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) {
if(is_client_tagged(t, tag)) tag_array_t *tags = &globalconf.screens[c->screen].tags;
tag_client(c, tag); for(int i = 0; i < tags->len; i++)
if(is_client_tagged(t, tags->tab[i]))
tag_client(c, tags->tab[i]);
}
/* should be floating if transsient or fixed */ /* should be floating if transsient or fixed */
if(rettrans || c->isfixed) if(rettrans || c->isfixed)
@ -600,32 +596,22 @@ client_setfloating(client_t *c, bool floating, layer_t layer)
void void
client_saveprops(client_t *c) client_saveprops(client_t *c)
{ {
int i = 0, ntags = 0; tag_array_t *tags = &globalconf.screens[c->screen].tags;
char *prop; unsigned char *prop = p_alloca(unsigned char, tags->len + 3);
tag_t *tag;
xutil_intern_atom_request_t atom_q; xutil_intern_atom_request_t atom_q;
int i;
atom_q = xutil_intern_atom(globalconf.connection, &globalconf.atoms, "_AWESOME_PROPERTIES"); atom_q = xutil_intern_atom(globalconf.connection, &globalconf.atoms, "_AWESOME_PROPERTIES");
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) for(i = 0; i < tags->len; i++)
ntags++; prop[i] = is_client_tagged(c, tags->tab[i]) ? '1' : '0';
prop = p_new(char, ntags + 3); prop[i++] = c->isfloating ? '1' : '0';
prop[i++] = '0' + c->layer;
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++)
prop[i] = is_client_tagged(c, tag) ? '1' : '0';
prop[i] = c->isfloating ? '1' : '0';
sprintf(&prop[++i], "%d", c->layer);
prop[++i] = '\0';
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, c->win, xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, c->win,
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms, atom_q), xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms, atom_q),
STRING, 8, i, (unsigned char *) prop); STRING, 8, i, prop);
p_delete(&prop);
} }
/** Unban a client. /** Unban a client.
@ -646,7 +632,7 @@ client_unban(client_t *c)
void void
client_unmanage(client_t *c) client_unmanage(client_t *c)
{ {
tag_t *tag; tag_array_t *tags = &globalconf.screens[c->screen].tags;
/* call hook */ /* call hook */
luaA_client_userdata_new(globalconf.L, c); luaA_client_userdata_new(globalconf.L, c);
@ -663,8 +649,8 @@ client_unmanage(client_t *c)
client_list_detach(&globalconf.clients, c); client_list_detach(&globalconf.clients, c);
focus_client_delete(c); focus_client_delete(c);
stack_client_delete(c); stack_client_delete(c);
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
untag_client(c, tag); untag_client(c, tags->tab[i]);
if(globalconf.focus->client == c) if(globalconf.focus->client == c)
client_focus(NULL, c->screen); client_focus(NULL, c->screen);

103
ewmh.c
View File

@ -273,11 +273,7 @@ ewmh_update_net_client_list_stacking(int phys_screen)
void void
ewmh_update_net_numbers_of_desktop(int phys_screen) ewmh_update_net_numbers_of_desktop(int phys_screen)
{ {
uint32_t count = 0; uint32_t count = globalconf.screens[phys_screen].tags.len;
tag_t *tag;
for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next)
count++;
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
xutil_screen_get(globalconf.connection, phys_screen)->root, xutil_screen_get(globalconf.connection, phys_screen)->root,
@ -287,11 +283,11 @@ ewmh_update_net_numbers_of_desktop(int phys_screen)
void void
ewmh_update_net_current_desktop(int phys_screen) ewmh_update_net_current_desktop(int phys_screen)
{ {
tag_array_t *tags = &globalconf.screens[phys_screen].tags;
uint32_t count = 0; uint32_t count = 0;
tag_t *tag, **curtags = tags_get_current(phys_screen); tag_t **curtags = tags_get_current(phys_screen);
for(tag = globalconf.screens[phys_screen].tags; tag != curtags[0]; tag = tag->next) for(count = 0; tags->tab[count] != curtags[0]; count++);
count++;
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
xutil_screen_get(globalconf.connection, phys_screen)->root, xutil_screen_get(globalconf.connection, phys_screen)->root,
@ -303,23 +299,21 @@ ewmh_update_net_current_desktop(int phys_screen)
void void
ewmh_update_net_desktop_names(int phys_screen) ewmh_update_net_desktop_names(int phys_screen)
{ {
char buf[1024], *pos; tag_array_t *tags = &globalconf.screens[phys_screen].tags;
ssize_t len, curr_size; buffer_t buf;
tag_t *tag;
pos = buf; buffer_inita(&buf, BUFSIZ);
len = 0;
for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
{ {
curr_size = a_strlen(tag->name); buffer_adds(&buf, tags->tab[i]->name);
a_strcpy(pos, sizeof(buf), tag->name); buffer_addc(&buf, '\0');
pos += curr_size + 1;
len += curr_size + 1;
} }
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
xutil_screen_get(globalconf.connection, phys_screen)->root, xutil_screen_get(globalconf.connection, phys_screen)->root,
net_desktop_names, utf8_string, 8, len, buf); net_desktop_names, utf8_string, 8, buf.len, buf.s);
buffer_wipe(&buf);
} }
/** Update the work area space for each physical screen and each desktop. /** Update the work area space for each physical screen and each desktop.
@ -328,29 +322,24 @@ ewmh_update_net_desktop_names(int phys_screen)
void void
ewmh_update_workarea(int phys_screen) ewmh_update_workarea(int phys_screen)
{ {
uint32_t *area; tag_array_t *tags = &globalconf.screens[phys_screen].tags;
tag_t *tag; uint32_t *area = p_alloca(uint32_t, tags->len * 4);
int count = 0;
area_t geom = screen_area_get(phys_screen, area_t geom = screen_area_get(phys_screen,
globalconf.screens[phys_screen].statusbar, globalconf.screens[phys_screen].statusbar,
&globalconf.screens[phys_screen].padding); &globalconf.screens[phys_screen].padding);
for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next)
count++;
area = p_new(uint32_t, count * 4); for(int i = 0; i < tags->len; i++)
for(tag = globalconf.screens[phys_screen].tags, count = 0; tag; tag = tag->next, count++)
{ {
area[4 * count + 0] = geom.x; area[4 * i + 0] = geom.x;
area[4 * count + 1] = geom.y; area[4 * i + 1] = geom.y;
area[4 * count + 2] = geom.width; area[4 * i + 2] = geom.width;
area[4 * count + 3] = geom.height; area[4 * i + 3] = geom.height;
} }
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
xutil_screen_get(globalconf.connection, phys_screen)->root, xutil_screen_get(globalconf.connection, phys_screen)->root,
net_workarea, CARDINAL, 32, count * 4, area); net_workarea, CARDINAL, 32, tags->len * 4, area);
p_delete(&area);
} }
void void
@ -369,13 +358,13 @@ ewmh_update_net_active_window(int phys_screen)
static void static void
ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set) ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
{ {
const uint32_t raise_window_val = XCB_STACK_MODE_ABOVE; static uint32_t const raise_window_val = XCB_STACK_MODE_ABOVE;
if(state == net_wm_state_sticky) if(state == net_wm_state_sticky)
{ {
tag_t *tag; tag_array_t *tags = &globalconf.screens[c->screen].tags;
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
tag_client(c, tag); tag_client(c, tags->tab[i]);
} }
else if(state == net_wm_state_skip_taskbar) else if(state == net_wm_state_skip_taskbar)
{ {
@ -483,8 +472,6 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
static void static void
ewmh_process_window_type_atom(client_t *c, xcb_atom_t state) ewmh_process_window_type_atom(client_t *c, xcb_atom_t state)
{ {
tag_t *tag;
if(state == net_wm_window_type_normal) if(state == net_wm_window_type_normal)
{ {
/* do nothing. this is REALLY IMPORTANT */ /* do nothing. this is REALLY IMPORTANT */
@ -507,12 +494,13 @@ ewmh_process_window_type_atom(client_t *c, xcb_atom_t state)
client_setfloating(c, true, LAYER_MODAL); client_setfloating(c, true, LAYER_MODAL);
else if(state == net_wm_window_type_desktop) else if(state == net_wm_window_type_desktop)
{ {
tag_array_t *tags = &globalconf.screens[c->screen].tags;
c->noborder = true; c->noborder = true;
c->isfixed = true; c->isfixed = true;
c->skip = true; c->skip = true;
c->layer = LAYER_DESKTOP; c->layer = LAYER_DESKTOP;
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
tag_client(c, tag); tag_client(c, tags->tab[i]);
} }
} }
@ -520,9 +508,7 @@ int
ewmh_process_client_message(xcb_client_message_event_t *ev) ewmh_process_client_message(xcb_client_message_event_t *ev)
{ {
client_t *c; client_t *c;
tag_t *tag;
int screen; int screen;
unsigned int i;
if(ev->type == net_current_desktop) if(ev->type == net_current_desktop)
for(screen = 0; for(screen = 0;
@ -541,15 +527,17 @@ ewmh_process_client_message(xcb_client_message_event_t *ev)
{ {
if((c = client_getbywin(ev->window))) if((c = client_getbywin(ev->window)))
{ {
tag_array_t *tags = &globalconf.screens[c->screen].tags;
if(ev->data.data32[0] == 0xffffffff) if(ev->data.data32[0] == 0xffffffff)
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
tag_client(c, tag); tag_client(c, tags->tab[i]);
else else
for(i = 0, tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++) for(int i = 0; i < tags->len; i++)
if(ev->data.data32[0] == i) if((int)ev->data.data32[0] == i)
tag_client(c, tag); tag_client(c, tags->tab[i]);
else else
untag_client(c, tag); untag_client(c, tags->tab[i]);
} }
} }
else if(ev->type == net_wm_state) else if(ev->type == net_wm_state)
@ -571,10 +559,9 @@ ewmh_check_client_hints(client_t *c)
{ {
xcb_atom_t *state; xcb_atom_t *state;
void *data = NULL; void *data = NULL;
int i, desktop; int desktop;
xcb_get_property_cookie_t c0, c1, c2; xcb_get_property_cookie_t c0, c1, c2;
xcb_get_property_reply_t *reply; xcb_get_property_reply_t *reply;
tag_t *tag;
/* Send the GetProperty requests which will be processed later */ /* Send the GetProperty requests which will be processed later */
c0 = xcb_get_property_unchecked(globalconf.connection, false, c->win, c0 = xcb_get_property_unchecked(globalconf.connection, false, c->win,
@ -589,16 +576,18 @@ ewmh_check_client_hints(client_t *c)
reply = xcb_get_property_reply(globalconf.connection, c0, NULL); reply = xcb_get_property_reply(globalconf.connection, c0, NULL);
if(reply && reply->value_len && (data = xcb_get_property_value(reply))) if(reply && reply->value_len && (data = xcb_get_property_value(reply)))
{ {
tag_array_t *tags = &globalconf.screens[c->screen].tags;
desktop = *(uint32_t *) data; desktop = *(uint32_t *) data;
if(desktop == -1) if(desktop == -1)
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
tag_client(c, tag); tag_client(c, tags->tab[i]);
else else
for(i = 0, tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++) for(int i = 0; i < tags->len; i++)
if(desktop == i) if(desktop == i)
tag_client(c, tag); tag_client(c, tags->tab[i]);
else else
untag_client(c, tag); untag_client(c, tags->tab[i]);
} }
p_delete(&reply); p_delete(&reply);
@ -607,7 +596,7 @@ ewmh_check_client_hints(client_t *c)
if(reply && (data = xcb_get_property_value(reply))) if(reply && (data = xcb_get_property_value(reply)))
{ {
state = (xcb_atom_t *) data; state = (xcb_atom_t *) data;
for(i = 0; i < xcb_get_property_value_length(reply); i++) for(int i = 0; i < xcb_get_property_value_length(reply); i++)
ewmh_process_state_atom(c, state[i], _NET_WM_STATE_ADD); ewmh_process_state_atom(c, state[i], _NET_WM_STATE_ADD);
} }
@ -617,7 +606,7 @@ ewmh_check_client_hints(client_t *c)
if(reply && (data = xcb_get_property_value(reply))) if(reply && (data = xcb_get_property_value(reply)))
{ {
state = (xcb_atom_t *) data; state = (xcb_atom_t *) data;
for(i = 0; i < xcb_get_property_value_length(reply); i++) for(int i = 0; i < xcb_get_property_value_length(reply); i++)
ewmh_process_window_type_atom(c, state[i]); ewmh_process_window_type_atom(c, state[i]);
} }

2
lua.c
View File

@ -547,7 +547,7 @@ luaA_parserc(const char* rcfile)
/* Assure there's at least one tag */ /* Assure there's at least one tag */
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
if(!globalconf.screens[screen].tags) if(!globalconf.screens[screen].tags.len)
tag_append_to_screen(tag_new("default", layout_tile, 0.5, 1, 0), screen); tag_append_to_screen(tag_new("default", layout_tile, 0.5, 1, 0), screen);
return true; return true;

View File

@ -128,12 +128,12 @@ screen_virttophys(int screen)
void void
screen_client_moveto(client_t *c, int new_screen, bool doresize) screen_client_moveto(client_t *c, int new_screen, bool doresize)
{ {
tag_t *tag;
int old_screen = c->screen; int old_screen = c->screen;
tag_array_t *tags = &globalconf.screens[old_screen].tags;
area_t from, to; area_t from, to;
for(tag = globalconf.screens[old_screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
untag_client(c, tag); untag_client(c, tags->tab[i]);
c->screen = new_screen; c->screen = new_screen;

View File

@ -346,9 +346,8 @@ struct _tag_t
int nmaster; int nmaster;
/** Number of columns in tile layout */ /** Number of columns in tile layout */
int ncol; int ncol;
/** Next and previous tags */
tag_t *prev, *next;
}; };
ARRAY_TYPE(tag_t *, tag);
/** Tag client link type */ /** Tag client link type */
struct tag_client_node_t struct tag_client_node_t
@ -377,7 +376,7 @@ typedef struct
/** true if we need to arrange() */ /** true if we need to arrange() */
bool need_arrange; bool need_arrange;
/** Tag list */ /** Tag list */
tag_t *tags; tag_array_t tags;
/** Status bar */ /** Status bar */
statusbar_t *statusbar; statusbar_t *statusbar;
/** Padding */ /** Padding */

85
tag.c
View File

@ -95,8 +95,7 @@ tag_append_to_screen(tag_t *tag, int screen)
int phys_screen = screen_virttophys(screen); int phys_screen = screen_virttophys(screen);
tag->screen = screen; tag->screen = screen;
tag_list_append(&globalconf.screens[screen].tags, tag); tag_array_append(&globalconf.screens[screen].tags, tag_ref(&tag));
tag_ref(&tag);
ewmh_update_net_numbers_of_desktop(phys_screen); ewmh_update_net_numbers_of_desktop(phys_screen);
ewmh_update_net_desktop_names(phys_screen); ewmh_update_net_desktop_names(phys_screen);
ewmh_update_workarea(phys_screen); ewmh_update_workarea(phys_screen);
@ -173,14 +172,13 @@ is_client_tagged(client_t *c, tag_t *t)
void void
tag_client_with_current_selected(client_t *c) tag_client_with_current_selected(client_t *c)
{ {
tag_t *tag; tag_array_t *tags = &globalconf.screens[c->screen].tags;
screen_t vscreen = globalconf.screens[c->screen];
for(tag = vscreen.tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
if(tag->selected) if(tags->tab[i]->selected)
tag_client(c, tag); tag_client(c, tags->tab[i]);
else else
untag_client(c, tag); untag_client(c, tags->tab[i]);
} }
/** Get the current tags for the specified screen. /** Get the current tags for the specified screen.
@ -191,21 +189,15 @@ tag_client_with_current_selected(client_t *c)
tag_t ** tag_t **
tags_get_current(int screen) tags_get_current(int screen)
{ {
tag_t *tag, **tags = NULL; tag_array_t *tags = &globalconf.screens[screen].tags;
int n = 1; tag_t **out = p_new(tag_t *, tags->len + 1);
int n = 0;
tags = p_new(tag_t *, n); for(int i = 0; i < tags->len; i++)
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) if(tags->tab[i]->selected)
if(tag->selected) out[n++] = tags->tab[i];
{
p_realloc(&tags, ++n);
tags[n - 2] = tag;
}
/* finish with null */ return out;
tags[n - 1] = NULL;
return tags;
} }
@ -215,12 +207,12 @@ tags_get_current(int screen)
static void static void
tag_view_only(tag_t *target) tag_view_only(tag_t *target)
{ {
tag_t *tag; if (target) {
tag_array_t *tags = &globalconf.screens[target->screen].tags;
if(!target) return; for(int i = 0; i < tags->len; i++)
tag_view(tags->tab[i], tags->tab[i] == target);
for(tag = globalconf.screens[target->screen].tags; tag; tag = tag->next) }
tag_view(tag, tag == target);
} }
/** View only a tag, selected by its index. /** View only a tag, selected by its index.
@ -230,14 +222,11 @@ tag_view_only(tag_t *target)
void void
tag_view_only_byindex(int screen, int dindex) tag_view_only_byindex(int screen, int dindex)
{ {
tag_t *tag; tag_array_t *tags = &globalconf.screens[screen].tags;
if(dindex < 0) if(dindex < 0 || dindex >= tags->len)
return; return;
tag_view_only(tags->tab[dindex]);
for(tag = globalconf.screens[screen].tags; tag && dindex > 0;
tag = tag->next, dindex--);
tag_view_only(tag);
} }
/** Convert a tag to a printable string. /** Convert a tag to a printable string.
@ -265,16 +254,22 @@ luaA_tag_tostring(lua_State *L)
static int static int
luaA_tag_add(lua_State *L) luaA_tag_add(lua_State *L)
{ {
tag_t *t, **tag = luaA_checkudata(L, 1, "tag"); tag_t **tag = luaA_checkudata(L, 1, "tag");
int i, screen = luaL_checknumber(L, 2) - 1; int screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen); luaA_checkscreen(screen);
for(i = 0; i < globalconf.screens_info->nscreen; i++) for(int i = 0; i < globalconf.screens_info->nscreen; i++)
for(t = globalconf.screens[i].tags; t; t = t->next) {
tag_array_t *tags = &globalconf.screens[i].tags;
for(int j = 0; j < tags->len; j++)
{
tag_t *t = tags->tab[j];
if(*tag == t) if(*tag == t)
luaL_error(L, "tag already on screen %d", i + 1); luaL_error(L, "tag already on screen %d", i + 1);
else if(t->screen == screen && !a_strcmp((*tag)->name, t->name)) else if(t->screen == screen && !a_strcmp((*tag)->name, t->name))
luaL_error(L, "a tag with the name `%s' is already on screen %d", t->name, i + 1); luaL_error(L, "a tag with the name `%s' is already on screen %d", t->name, i + 1);
}
}
(*tag)->screen = screen; (*tag)->screen = screen;
tag_append_to_screen(*tag, screen); tag_append_to_screen(*tag, screen);
@ -292,16 +287,16 @@ static int
luaA_tag_get(lua_State *L) luaA_tag_get(lua_State *L)
{ {
int screen = luaL_checknumber(L, 1) - 1; int screen = luaL_checknumber(L, 1) - 1;
tag_t *tag; tag_array_t *tags = &globalconf.screens[screen].tags;
luaA_checkscreen(screen); luaA_checkscreen(screen);
lua_newtable(L); lua_newtable(L);
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
{ {
luaA_tag_userdata_new(L, tag); luaA_tag_userdata_new(L, tags->tab[i]);
lua_setfield(L, -2, tag->name); lua_setfield(L, -2, tags->tab[i]->name);
} }
return 1; return 1;
@ -318,17 +313,17 @@ luaA_tag_get(lua_State *L)
static int static int
luaA_tag_geti(lua_State *L) luaA_tag_geti(lua_State *L)
{ {
int i = 1, screen = luaL_checknumber(L, 1) - 1; int screen = luaL_checknumber(L, 1) - 1;
tag_t *tag; tag_array_t *tags = &globalconf.screens[screen].tags;
luaA_checkscreen(screen); luaA_checkscreen(screen);
lua_newtable(L); lua_newtable(L);
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) for(int i = 0; i < tags->len; i++)
{ {
luaA_tag_userdata_new(L, tag); luaA_tag_userdata_new(L, tags->tab[i]);
lua_rawseti(L, -2, i++); lua_rawseti(L, -2, i + 1);
} }
return 1; return 1;

2
tag.h
View File

@ -48,7 +48,7 @@ void tag_append_to_screen(tag_t *, int);
int luaA_tag_userdata_new(lua_State *, tag_t *); int luaA_tag_userdata_new(lua_State *, tag_t *);
DO_RCNT(tag_t, tag, tag_delete) DO_RCNT(tag_t, tag, tag_delete)
DO_SLIST(tag_t, tag, tag_delete) ARRAY_FUNCS(tag_t *, tag, tag_unref);
DO_SLIST(tag_client_node_t, tag_client_node, p_delete) DO_SLIST(tag_client_node_t, tag_client_node, p_delete)

View File

@ -134,15 +134,15 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
int used __attribute__ ((unused)), int used __attribute__ ((unused)),
void *object) void *object)
{ {
tag_t *tag;
taglist_data_t *data = w->widget->data; taglist_data_t *data = w->widget->data;
client_t *sel = globalconf.focus->client; client_t *sel = globalconf.focus->client;
screen_t *vscreen = &globalconf.screens[screen];
int i = 0, prev_width = 0;
area_t area, rectangle = { 0, 0, 0, 0 }; area_t area, rectangle = { 0, 0, 0, 0 };
char **text = NULL;
taglist_drawn_area_t *tda; taglist_drawn_area_t *tda;
draw_parser_data_t *pdata = NULL; int prev_width = 0;
tag_array_t *tags = &globalconf.screens[screen].tags;
char **text = p_alloca(char *, tags->len);
draw_parser_data_t *pdata = p_alloca(draw_parser_data_t, tags->len);
w->area.width = w->area.y = 0; w->area.width = w->area.y = 0;
@ -162,10 +162,10 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
tda->areas.len = 0; tda->areas.len = 0;
/* First compute text and widget width */ /* First compute text and widget width */
for(tag = vscreen->tags; tag; tag = tag->next, i++) for(int i = 0; i < tags->len; i++)
{ {
p_realloc(&text, i + 1); tag_t *tag = tags->tab[i];
p_realloc(&pdata, i + 1);
text[i] = taglist_text_get(tag, data); text[i] = taglist_text_get(tag, data);
text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i])); text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i]));
draw_parser_data_init(&pdata[i]); draw_parser_data_init(&pdata[i]);
@ -182,8 +182,9 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
w->area.x = widget_calculate_offset(ctx->width, w->area.width, w->area.x = widget_calculate_offset(ctx->width, w->area.width,
offset, w->widget->align); offset, w->widget->align);
for(i = 0, tag = vscreen->tags; tag && i < tda->areas.len; i++, tag = tag->next) for(int i = 0; i < tags->len; i++)
{ {
tag_t *tag = tags->tab[i];
area_t *r = &tda->areas.tab[i]; area_t *r = &tda->areas.tab[i];
if(!data->show_empty && !tag->selected && !tag_isoccupied(tag)) if(!data->show_empty && !tag->selected && !tag_isoccupied(tag))
@ -209,9 +210,6 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
} }
} }
p_delete(&text);
p_delete(&pdata);
w->area.height = ctx->height; w->area.height = ctx->height;
return w->area.width; return w->area.width;
} }
@ -230,20 +228,19 @@ taglist_button_press(widget_node_t *w,
void *object, void *object,
awesome_type_t type) awesome_type_t type)
{ {
screen_t *vscreen = &globalconf.screens[screen]; tag_array_t *tags = &globalconf.screens[screen].tags;
button_t *b; button_t *b;
taglist_data_t *data = w->widget->data; taglist_data_t *data = w->widget->data;
taglist_drawn_area_t *tda; taglist_drawn_area_t *tda;
tag_t *tag;
int i;
/* Find the good drawn area list */ /* Find the good drawn area list */
for(tda = data->drawn_area; tda && tda->object != object; tda = tda->next); for(tda = data->drawn_area; tda && tda->object != object; tda = tda->next);
for(b = w->widget->buttons; b; b = b->next) for(b = w->widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct) if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
for(i = 0, tag = vscreen->tags; tag && i < tda->areas.len; tag = tag->next, i++) for(int i = 0; i < MIN(tags->len, tda->areas.len); i++)
{ {
tag_t *tag = tags->tab[i];
area_t *area = &tda->areas.tab[i]; area_t *area = &tda->areas.tab[i];
if(ev->event_x >= AREA_LEFT(*area) if(ev->event_x >= AREA_LEFT(*area)
&& ev->event_x < AREA_RIGHT(*area) && ev->event_x < AREA_RIGHT(*area)