From 14f4e02e6686c327511184f3bdfc33c24a9b2ccc Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 23 Jun 2008 17:37:19 +0200 Subject: [PATCH] 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 --- client.c | 88 +++++++++++++++++---------------------- ewmh.c | 103 +++++++++++++++++++++------------------------- lua.c | 2 +- screen.c | 6 +-- structs.h | 5 +-- tag.c | 85 ++++++++++++++++++-------------------- tag.h | 6 +-- widgets/taglist.c | 29 ++++++------- 8 files changed, 145 insertions(+), 179 deletions(-) diff --git a/client.c b/client.c index e8279dab..b48577d6 100644 --- a/client.c +++ b/client.c @@ -61,7 +61,6 @@ DO_LUA_EQ(client_t, client, "client") /** Load windows properties, restoring client's tag * 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 screen A virtual screen. * \return True if client had property, false otherwise. @@ -69,38 +68,32 @@ DO_LUA_EQ(client_t, client, "client") static bool client_loadprops(client_t * c, screen_t *screen) { - int i, ntags = 0; - tag_t *tag; + tag_array_t *tags = &screen->tags; char *prop = NULL; - bool result = false; - for(tag = screen->tags; tag; tag = tag->next) - ntags++; - - if(xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms, + if(!xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms, xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms, xutil_intern_atom(globalconf.connection, &globalconf.atoms, "_AWESOME_PROPERTIES")), &prop)) - { - 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); + return false; - 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); + return false; } - p_delete(&prop); + 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]); - return result; + 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. @@ -139,12 +132,13 @@ window_isprotodel(xcb_window_t win) bool client_isvisible(client_t *c, int screen) { - tag_t *tag; - 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 false; } @@ -345,7 +339,6 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) client_t *c, *t = NULL; xcb_window_t trans; bool rettrans, retloadprops; - tag_t *tag; xcb_size_hints_t *u_size_hints; const uint32_t select_input_val[] = { 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 */ if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans)) && (t = client_getbywin(trans))) - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - if(is_client_tagged(t, tag)) - tag_client(c, tag); + { + tag_array_t *tags = &globalconf.screens[c->screen].tags; + 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 */ if(rettrans || c->isfixed) @@ -600,32 +596,22 @@ client_setfloating(client_t *c, bool floating, layer_t layer) void client_saveprops(client_t *c) { - int i = 0, ntags = 0; - char *prop; - tag_t *tag; + tag_array_t *tags = &globalconf.screens[c->screen].tags; + unsigned char *prop = p_alloca(unsigned char, tags->len + 3); xutil_intern_atom_request_t atom_q; + int i; atom_q = xutil_intern_atom(globalconf.connection, &globalconf.atoms, "_AWESOME_PROPERTIES"); - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - ntags++; + for(i = 0; i < tags->len; i++) + prop[i] = is_client_tagged(c, tags->tab[i]) ? '1' : '0'; - prop = p_new(char, ntags + 3); - - 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'; + prop[i++] = c->isfloating ? '1' : '0'; + prop[i++] = '0' + c->layer; xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, c->win, xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms, atom_q), - STRING, 8, i, (unsigned char *) prop); - - p_delete(&prop); + STRING, 8, i, prop); } /** Unban a client. @@ -646,7 +632,7 @@ client_unban(client_t *c) void client_unmanage(client_t *c) { - tag_t *tag; + tag_array_t *tags = &globalconf.screens[c->screen].tags; /* call hook */ luaA_client_userdata_new(globalconf.L, c); @@ -663,8 +649,8 @@ client_unmanage(client_t *c) client_list_detach(&globalconf.clients, c); focus_client_delete(c); stack_client_delete(c); - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - untag_client(c, tag); + for(int i = 0; i < tags->len; i++) + untag_client(c, tags->tab[i]); if(globalconf.focus->client == c) client_focus(NULL, c->screen); diff --git a/ewmh.c b/ewmh.c index dbf6d1e7..14f51764 100644 --- a/ewmh.c +++ b/ewmh.c @@ -273,11 +273,7 @@ ewmh_update_net_client_list_stacking(int phys_screen) void ewmh_update_net_numbers_of_desktop(int phys_screen) { - uint32_t count = 0; - tag_t *tag; - - for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next) - count++; + uint32_t count = globalconf.screens[phys_screen].tags.len; xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xutil_screen_get(globalconf.connection, phys_screen)->root, @@ -287,11 +283,11 @@ ewmh_update_net_numbers_of_desktop(int phys_screen) void ewmh_update_net_current_desktop(int phys_screen) { + tag_array_t *tags = &globalconf.screens[phys_screen].tags; 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) - count++; + for(count = 0; tags->tab[count] != curtags[0]; count++); xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xutil_screen_get(globalconf.connection, phys_screen)->root, @@ -303,23 +299,21 @@ ewmh_update_net_current_desktop(int phys_screen) void ewmh_update_net_desktop_names(int phys_screen) { - char buf[1024], *pos; - ssize_t len, curr_size; - tag_t *tag; + tag_array_t *tags = &globalconf.screens[phys_screen].tags; + buffer_t buf; - pos = buf; - len = 0; - for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next) + buffer_inita(&buf, BUFSIZ); + + for(int i = 0; i < tags->len; i++) { - curr_size = a_strlen(tag->name); - a_strcpy(pos, sizeof(buf), tag->name); - pos += curr_size + 1; - len += curr_size + 1; + buffer_adds(&buf, tags->tab[i]->name); + buffer_addc(&buf, '\0'); } xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, 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. @@ -328,29 +322,24 @@ ewmh_update_net_desktop_names(int phys_screen) void ewmh_update_workarea(int phys_screen) { - uint32_t *area; - tag_t *tag; - int count = 0; + tag_array_t *tags = &globalconf.screens[phys_screen].tags; + uint32_t *area = p_alloca(uint32_t, tags->len * 4); area_t geom = screen_area_get(phys_screen, globalconf.screens[phys_screen].statusbar, &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(tag = globalconf.screens[phys_screen].tags, count = 0; tag; tag = tag->next, count++) + for(int i = 0; i < tags->len; i++) { - area[4 * count + 0] = geom.x; - area[4 * count + 1] = geom.y; - area[4 * count + 2] = geom.width; - area[4 * count + 3] = geom.height; + area[4 * i + 0] = geom.x; + area[4 * i + 1] = geom.y; + area[4 * i + 2] = geom.width; + area[4 * i + 3] = geom.height; } xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, xutil_screen_get(globalconf.connection, phys_screen)->root, - net_workarea, CARDINAL, 32, count * 4, area); - p_delete(&area); + net_workarea, CARDINAL, 32, tags->len * 4, area); } void @@ -369,13 +358,13 @@ ewmh_update_net_active_window(int phys_screen) static void 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) { - tag_t *tag; - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - tag_client(c, tag); + tag_array_t *tags = &globalconf.screens[c->screen].tags; + for(int i = 0; i < tags->len; i++) + tag_client(c, tags->tab[i]); } 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 ewmh_process_window_type_atom(client_t *c, xcb_atom_t state) { - tag_t *tag; - if(state == net_wm_window_type_normal) { /* 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); else if(state == net_wm_window_type_desktop) { + tag_array_t *tags = &globalconf.screens[c->screen].tags; c->noborder = true; c->isfixed = true; c->skip = true; c->layer = LAYER_DESKTOP; - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - tag_client(c, tag); + for(int i = 0; i < tags->len; i++) + tag_client(c, tags->tab[i]); } } @@ -520,9 +508,7 @@ int ewmh_process_client_message(xcb_client_message_event_t *ev) { client_t *c; - tag_t *tag; int screen; - unsigned int i; if(ev->type == net_current_desktop) for(screen = 0; @@ -541,15 +527,17 @@ ewmh_process_client_message(xcb_client_message_event_t *ev) { if((c = client_getbywin(ev->window))) { + tag_array_t *tags = &globalconf.screens[c->screen].tags; + if(ev->data.data32[0] == 0xffffffff) - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - tag_client(c, tag); + for(int i = 0; i < tags->len; i++) + tag_client(c, tags->tab[i]); else - for(i = 0, tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++) - if(ev->data.data32[0] == i) - tag_client(c, tag); + for(int i = 0; i < tags->len; i++) + if((int)ev->data.data32[0] == i) + tag_client(c, tags->tab[i]); else - untag_client(c, tag); + untag_client(c, tags->tab[i]); } } else if(ev->type == net_wm_state) @@ -571,10 +559,9 @@ ewmh_check_client_hints(client_t *c) { xcb_atom_t *state; void *data = NULL; - int i, desktop; + int desktop; xcb_get_property_cookie_t c0, c1, c2; xcb_get_property_reply_t *reply; - tag_t *tag; /* Send the GetProperty requests which will be processed later */ 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); if(reply && reply->value_len && (data = xcb_get_property_value(reply))) { + tag_array_t *tags = &globalconf.screens[c->screen].tags; + desktop = *(uint32_t *) data; if(desktop == -1) - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - tag_client(c, tag); + for(int i = 0; i < tags->len; i++) + tag_client(c, tags->tab[i]); 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) - tag_client(c, tag); + tag_client(c, tags->tab[i]); else - untag_client(c, tag); + untag_client(c, tags->tab[i]); } p_delete(&reply); @@ -607,7 +596,7 @@ ewmh_check_client_hints(client_t *c) if(reply && (data = xcb_get_property_value(reply))) { 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); } @@ -617,7 +606,7 @@ ewmh_check_client_hints(client_t *c) if(reply && (data = xcb_get_property_value(reply))) { 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]); } diff --git a/lua.c b/lua.c index f44a27e9..c41e91bd 100644 --- a/lua.c +++ b/lua.c @@ -547,7 +547,7 @@ luaA_parserc(const char* rcfile) /* Assure there's at least one tag */ 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); return true; diff --git a/screen.c b/screen.c index 9ca45181..9c856334 100644 --- a/screen.c +++ b/screen.c @@ -128,12 +128,12 @@ screen_virttophys(int screen) void screen_client_moveto(client_t *c, int new_screen, bool doresize) { - tag_t *tag; int old_screen = c->screen; + tag_array_t *tags = &globalconf.screens[old_screen].tags; area_t from, to; - for(tag = globalconf.screens[old_screen].tags; tag; tag = tag->next) - untag_client(c, tag); + for(int i = 0; i < tags->len; i++) + untag_client(c, tags->tab[i]); c->screen = new_screen; diff --git a/structs.h b/structs.h index 787e323b..211641b8 100644 --- a/structs.h +++ b/structs.h @@ -346,9 +346,8 @@ struct _tag_t int nmaster; /** Number of columns in tile layout */ int ncol; - /** Next and previous tags */ - tag_t *prev, *next; }; +ARRAY_TYPE(tag_t *, tag); /** Tag client link type */ struct tag_client_node_t @@ -377,7 +376,7 @@ typedef struct /** true if we need to arrange() */ bool need_arrange; /** Tag list */ - tag_t *tags; + tag_array_t tags; /** Status bar */ statusbar_t *statusbar; /** Padding */ diff --git a/tag.c b/tag.c index 9db1215a..fb2c49e4 100644 --- a/tag.c +++ b/tag.c @@ -95,8 +95,7 @@ tag_append_to_screen(tag_t *tag, int screen) int phys_screen = screen_virttophys(screen); tag->screen = screen; - tag_list_append(&globalconf.screens[screen].tags, tag); - tag_ref(&tag); + tag_array_append(&globalconf.screens[screen].tags, tag_ref(&tag)); ewmh_update_net_numbers_of_desktop(phys_screen); ewmh_update_net_desktop_names(phys_screen); ewmh_update_workarea(phys_screen); @@ -173,14 +172,13 @@ is_client_tagged(client_t *c, tag_t *t) void tag_client_with_current_selected(client_t *c) { - tag_t *tag; - screen_t vscreen = globalconf.screens[c->screen]; + tag_array_t *tags = &globalconf.screens[c->screen].tags; - for(tag = vscreen.tags; tag; tag = tag->next) - if(tag->selected) - tag_client(c, tag); + for(int i = 0; i < tags->len; i++) + if(tags->tab[i]->selected) + tag_client(c, tags->tab[i]); else - untag_client(c, tag); + untag_client(c, tags->tab[i]); } /** Get the current tags for the specified screen. @@ -191,21 +189,15 @@ tag_client_with_current_selected(client_t *c) tag_t ** tags_get_current(int screen) { - tag_t *tag, **tags = NULL; - int n = 1; + tag_array_t *tags = &globalconf.screens[screen].tags; + tag_t **out = p_new(tag_t *, tags->len + 1); + int n = 0; - tags = p_new(tag_t *, n); - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - if(tag->selected) - { - p_realloc(&tags, ++n); - tags[n - 2] = tag; - } + for(int i = 0; i < tags->len; i++) + if(tags->tab[i]->selected) + out[n++] = tags->tab[i]; - /* finish with null */ - tags[n - 1] = NULL; - - return tags; + return out; } @@ -215,12 +207,12 @@ tags_get_current(int screen) static void tag_view_only(tag_t *target) { - tag_t *tag; + if (target) { + tag_array_t *tags = &globalconf.screens[target->screen].tags; - if(!target) return; - - for(tag = globalconf.screens[target->screen].tags; tag; tag = tag->next) - tag_view(tag, tag == target); + for(int i = 0; i < tags->len; i++) + tag_view(tags->tab[i], tags->tab[i] == target); + } } /** View only a tag, selected by its index. @@ -230,14 +222,11 @@ tag_view_only(tag_t *target) void 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; - - for(tag = globalconf.screens[screen].tags; tag && dindex > 0; - tag = tag->next, dindex--); - tag_view_only(tag); + tag_view_only(tags->tab[dindex]); } /** Convert a tag to a printable string. @@ -265,16 +254,22 @@ luaA_tag_tostring(lua_State *L) static int luaA_tag_add(lua_State *L) { - tag_t *t, **tag = luaA_checkudata(L, 1, "tag"); - int i, screen = luaL_checknumber(L, 2) - 1; + tag_t **tag = luaA_checkudata(L, 1, "tag"); + int screen = luaL_checknumber(L, 2) - 1; luaA_checkscreen(screen); - for(i = 0; i < globalconf.screens_info->nscreen; i++) - for(t = globalconf.screens[i].tags; t; t = t->next) + for(int i = 0; i < globalconf.screens_info->nscreen; i++) + { + 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) luaL_error(L, "tag already on screen %d", i + 1); 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); + } + } (*tag)->screen = screen; tag_append_to_screen(*tag, screen); @@ -292,16 +287,16 @@ static int luaA_tag_get(lua_State *L) { int screen = luaL_checknumber(L, 1) - 1; - tag_t *tag; + tag_array_t *tags = &globalconf.screens[screen].tags; luaA_checkscreen(screen); 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); - lua_setfield(L, -2, tag->name); + luaA_tag_userdata_new(L, tags->tab[i]); + lua_setfield(L, -2, tags->tab[i]->name); } return 1; @@ -318,17 +313,17 @@ luaA_tag_get(lua_State *L) static int luaA_tag_geti(lua_State *L) { - int i = 1, screen = luaL_checknumber(L, 1) - 1; - tag_t *tag; + int screen = luaL_checknumber(L, 1) - 1; + tag_array_t *tags = &globalconf.screens[screen].tags; luaA_checkscreen(screen); 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); - lua_rawseti(L, -2, i++); + luaA_tag_userdata_new(L, tags->tab[i]); + lua_rawseti(L, -2, i + 1); } return 1; diff --git a/tag.h b/tag.h index 0f6bd8cc..1d74820d 100644 --- a/tag.h +++ b/tag.h @@ -29,7 +29,7 @@ #define IS_TILED(client, screen) (client && !client->isfloating && !client->ismax && client_isvisible(client, screen)) /* Contructor, destructor and referencors */ -tag_t * tag_new(const char *, layout_t *, double, int, int); +tag_t *tag_new(const char *, layout_t *, double, int, int); static inline void tag_delete(tag_t **tag) @@ -38,7 +38,7 @@ tag_delete(tag_t **tag) p_delete(tag); } -tag_t ** tags_get_current(int); +tag_t **tags_get_current(int); void tag_client(client_t *, tag_t *); void untag_client(client_t *, tag_t *); bool is_client_tagged(client_t *, tag_t *); @@ -48,7 +48,7 @@ void tag_append_to_screen(tag_t *, int); int luaA_tag_userdata_new(lua_State *, tag_t *); 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) diff --git a/widgets/taglist.c b/widgets/taglist.c index 46f72a38..14425f47 100644 --- a/widgets/taglist.c +++ b/widgets/taglist.c @@ -134,15 +134,15 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w, int used __attribute__ ((unused)), void *object) { - tag_t *tag; taglist_data_t *data = w->widget->data; 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 }; - char **text = NULL; 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; @@ -162,10 +162,10 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w, tda->areas.len = 0; /* 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); - p_realloc(&pdata, i + 1); + tag_t *tag = tags->tab[i]; + text[i] = taglist_text_get(tag, data); text[i] = tag_markup_parse(tag, text[i], a_strlen(text[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, 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]; 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; return w->area.width; } @@ -230,20 +228,19 @@ taglist_button_press(widget_node_t *w, void *object, awesome_type_t type) { - screen_t *vscreen = &globalconf.screens[screen]; + tag_array_t *tags = &globalconf.screens[screen].tags; button_t *b; taglist_data_t *data = w->widget->data; taglist_drawn_area_t *tda; - tag_t *tag; - int i; /* Find the good drawn area list */ for(tda = data->drawn_area; tda && tda->object != object; tda = tda->next); for(b = w->widget->buttons; b; b = b->next) 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]; if(ev->event_x >= AREA_LEFT(*area) && ev->event_x < AREA_RIGHT(*area)