area_t: make it smaller, use arrays instead of lists.
Make area_t smaller so that it fits in an uint64_t using 4 {u,}int16_t's for it. Note that xcb uses the very same structure, so we aren't loosing any information while remaining very small. This is better to use arrays in term of: * memory access when iterating over area_t's; * allocation because area_t's have no *next/*prev members anymore, which makes it a tiny structure (8 octets); * allocation because we allocate area_t's by vector of'em rather than one by one. Signed-off-by: Pierre Habouzit <madcoder@debian.org>
This commit is contained in:
parent
dc6373488f
commit
46f03fd6a6
|
@ -923,7 +923,7 @@ draw_image(draw_context_t *ctx, int x, int y, int wanted_h, draw_image_t *image)
|
|||
area_t
|
||||
draw_get_image_size(const char *filename)
|
||||
{
|
||||
area_t size = { -1, -1, -1, -1, NULL, NULL };
|
||||
area_t size = { 0, 0, 0, 0 };
|
||||
Imlib_Image image;
|
||||
Imlib_Load_Error e = IMLIB_LOAD_ERROR_NONE;
|
||||
|
||||
|
@ -997,7 +997,7 @@ draw_text_extents(xcb_connection_t *conn, int phys_screen, font_t *font, const c
|
|||
PangoLayout *layout;
|
||||
PangoRectangle ext;
|
||||
xcb_screen_t *s = xutil_screen_get(conn, phys_screen);
|
||||
area_t geom = { 0, 0, 0, 0, NULL, NULL };
|
||||
area_t geom = { 0, 0, 0, 0 };
|
||||
ssize_t len;
|
||||
draw_parser_data_t parser_data;
|
||||
|
||||
|
@ -1160,66 +1160,67 @@ xcolor_new(xcb_connection_t *conn, int phys_screen, const char *colstr, xcolor_t
|
|||
|
||||
/** Remove a area from a list of them,
|
||||
* spliting the space between several area that can overlap
|
||||
* \param head list head
|
||||
* \param elem area to remove
|
||||
* \param areas array of areas.
|
||||
* \param elem area to remove
|
||||
*/
|
||||
void
|
||||
area_list_remove(area_t **head, area_t *elem)
|
||||
area_array_remove(area_array_t *areas, area_t elem)
|
||||
{
|
||||
area_t *r, inter, *extra, *rnext;
|
||||
|
||||
for(r = *head; r; r = rnext)
|
||||
/* loop from the end because:
|
||||
* (1) we remove elements ;
|
||||
* (2) the one we add to the end are okay wrt the invariants
|
||||
*/
|
||||
for (int i = areas->len - 1; i >= 0; i--)
|
||||
{
|
||||
rnext = r->next;
|
||||
if(area_intersect_area(*r, *elem))
|
||||
if(area_intersect_area(areas->tab[i], elem))
|
||||
{
|
||||
/* remove it from the list */
|
||||
area_list_detach(head, r);
|
||||
area_t r = area_array_take(areas, i);
|
||||
area_t inter = area_get_intersect_area(r, elem);
|
||||
|
||||
inter = area_get_intersect_area(*r, *elem);
|
||||
|
||||
if(AREA_LEFT(inter) > AREA_LEFT(*r))
|
||||
if(AREA_LEFT(inter) > AREA_LEFT(r))
|
||||
{
|
||||
extra = p_new(area_t, 1);
|
||||
extra->x = r->x;
|
||||
extra->y = r->y;
|
||||
extra->width = AREA_LEFT(inter) - r->x;
|
||||
extra->height = r->height;
|
||||
area_list_append(head, extra);
|
||||
area_t extra = {
|
||||
.x = r.x,
|
||||
.y = r.y,
|
||||
.width = AREA_LEFT(inter) - r.x,
|
||||
.height = r.height,
|
||||
};
|
||||
area_array_append(areas, extra);
|
||||
}
|
||||
|
||||
if(AREA_TOP(inter) > AREA_TOP(*r))
|
||||
if(AREA_TOP(inter) > AREA_TOP(r))
|
||||
{
|
||||
extra = p_new(area_t, 1);
|
||||
extra->x = r->x;
|
||||
extra->y = r->y;
|
||||
extra->width = r->width;
|
||||
extra->height = AREA_TOP(inter) - r->y;
|
||||
area_list_append(head, extra);
|
||||
area_t extra = {
|
||||
.x = r.x,
|
||||
.y = r.y,
|
||||
.width = r.width,
|
||||
.height = AREA_TOP(inter) - r.y,
|
||||
};
|
||||
area_array_append(areas, extra);
|
||||
}
|
||||
|
||||
if(AREA_RIGHT(inter) < AREA_RIGHT(*r))
|
||||
if(AREA_RIGHT(inter) < AREA_RIGHT(r))
|
||||
{
|
||||
extra = p_new(area_t, 1);
|
||||
extra->x = AREA_RIGHT(inter);
|
||||
extra->y = r->y;
|
||||
extra->width = AREA_RIGHT(*r) - AREA_RIGHT(inter);
|
||||
extra->height = r->height;
|
||||
area_list_append(head, extra);
|
||||
area_t extra = {
|
||||
.x = AREA_RIGHT(inter),
|
||||
.y = r.y,
|
||||
.width = AREA_RIGHT(r) - AREA_RIGHT(inter),
|
||||
.height = r.height,
|
||||
};
|
||||
area_array_append(areas, extra);
|
||||
}
|
||||
|
||||
if(AREA_BOTTOM(inter) < AREA_BOTTOM(*r))
|
||||
if(AREA_BOTTOM(inter) < AREA_BOTTOM(r))
|
||||
{
|
||||
extra = p_new(area_t, 1);
|
||||
extra->x = r->x;
|
||||
extra->y = AREA_BOTTOM(inter);
|
||||
extra->width = r->width;
|
||||
extra->height = AREA_BOTTOM(*r) - AREA_BOTTOM(inter);
|
||||
area_list_append(head, extra);
|
||||
area_t extra = {
|
||||
.x = r.x,
|
||||
.y = AREA_BOTTOM(inter),
|
||||
.width = r.width,
|
||||
.height = AREA_BOTTOM(r) - AREA_BOTTOM(inter),
|
||||
};
|
||||
area_array_append(areas, extra);
|
||||
}
|
||||
|
||||
/* delete the elem since we removed it from the list */
|
||||
p_delete(&r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "common/array.h"
|
||||
#include "common/list.h"
|
||||
|
||||
typedef struct
|
||||
|
@ -52,14 +52,13 @@ typedef struct area_t area_t;
|
|||
struct area_t
|
||||
{
|
||||
/** Co-ords of upper left corner */
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
area_t *prev, *next;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
};
|
||||
|
||||
DO_SLIST(area_t, area, p_delete)
|
||||
DO_ARRAY(area_t, area, DO_NOTHING);
|
||||
|
||||
#define AREA_LEFT(a) ((a).x)
|
||||
#define AREA_TOP(a) ((a).y)
|
||||
|
@ -171,7 +170,7 @@ area_t draw_text_extents(xcb_connection_t *, int, font_t *, const char *);
|
|||
alignment_t draw_align_get_from_str(const char *);
|
||||
bool xcolor_new(xcb_connection_t *, int, const char *, xcolor_t *);
|
||||
|
||||
void area_list_remove(area_t **, area_t *);
|
||||
void area_array_remove(area_array_t *, area_t);
|
||||
|
||||
#endif
|
||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
||||
|
|
|
@ -58,6 +58,8 @@ typedef struct
|
|||
/** \brief replace \c NULL strings with emtpy strings */
|
||||
#define NONULL(x) (x ? x : "")
|
||||
|
||||
#define DO_NOTHING(...)
|
||||
|
||||
#undef MAX
|
||||
#undef MIN
|
||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
|
|
|
@ -59,7 +59,6 @@ screen_xsitoarea(xcb_xinerama_screen_info_t si)
|
|||
a.y = si.y_org;
|
||||
a.width = si.width;
|
||||
a.height = si.height;
|
||||
a.next = a.prev = NULL;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ _tile(int screen, const position_t position)
|
|||
unsigned int mw = 0, mh = 0;
|
||||
int n, i, masterwin = 0, otherwin = 0;
|
||||
int real_ncol = 1, win_by_col = 1, current_col = 0;
|
||||
area_t area, geometry = { 0, 0, 0, 0, NULL, NULL };
|
||||
area_t area, geometry = { 0, 0, 0, 0 };
|
||||
client_t *c;
|
||||
tag_t **curtags = tags_get_current(screen);
|
||||
|
||||
|
|
2
mouse.c
2
mouse.c
|
@ -243,7 +243,7 @@ mouse_infobox_draw(draw_context_t *ctx,
|
|||
simple_window_t *sw,
|
||||
area_t geometry, int border)
|
||||
{
|
||||
area_t draw_geometry = { 0, 0, ctx->width, ctx->height, NULL, NULL };
|
||||
area_t draw_geometry = { 0, 0, ctx->width, ctx->height };
|
||||
char size[64];
|
||||
|
||||
snprintf(size, sizeof(size), "<text align=\"center\"/>%dx%d+%d+%d",
|
||||
|
|
38
placement.c
38
placement.c
|
@ -68,20 +68,18 @@ area_t
|
|||
placement_smart(client_t *c)
|
||||
{
|
||||
client_t *client;
|
||||
area_t newgeometry = { 0, 0, 0, 0, NULL, NULL };
|
||||
area_t *screen_geometry, *arealist = NULL, *r;
|
||||
area_t newgeometry = { 0, 0, 0, 0 };
|
||||
area_t screen_geometry;
|
||||
area_array_t areas;
|
||||
bool found = false;
|
||||
layout_t *layout;
|
||||
|
||||
screen_geometry = p_new(area_t, 1);
|
||||
|
||||
*screen_geometry = screen_area_get(c->screen,
|
||||
globalconf.screens[c->screen].statusbar,
|
||||
&globalconf.screens[c->screen].padding);
|
||||
screen_geometry = screen_area_get(c->screen,
|
||||
globalconf.screens[c->screen].statusbar,
|
||||
&globalconf.screens[c->screen].padding);
|
||||
|
||||
layout = layout_get_current(c->screen);
|
||||
|
||||
area_list_push(&arealist, screen_geometry);
|
||||
area_array_append(&areas, screen_geometry);
|
||||
|
||||
for(client = globalconf.clients; client; client = client->next)
|
||||
if((client->isfloating || layout == layout_floating)
|
||||
|
@ -91,7 +89,7 @@ placement_smart(client_t *c)
|
|||
newgeometry.width += 2 * client->border;
|
||||
newgeometry.height += 2 * client->border;
|
||||
newgeometry = titlebar_geometry_add(c->titlebar, c->border, newgeometry);
|
||||
area_list_remove(&arealist, &newgeometry);
|
||||
area_array_remove(&areas, newgeometry);
|
||||
}
|
||||
|
||||
newgeometry.x = c->f_geometry.x;
|
||||
|
@ -99,20 +97,29 @@ placement_smart(client_t *c)
|
|||
newgeometry.width = 0;
|
||||
newgeometry.height = 0;
|
||||
|
||||
for(r = arealist; r; r = r->next)
|
||||
for(int i = 0; i < areas.len; i++)
|
||||
{
|
||||
area_t *r = &areas.tab[i];
|
||||
|
||||
if(r->width >= c->f_geometry.width && r->height >= c->f_geometry.height
|
||||
&& r->width * r->height > newgeometry.width * newgeometry.height)
|
||||
{
|
||||
found = true;
|
||||
newgeometry = *r;
|
||||
}
|
||||
}
|
||||
|
||||
/* we did not found a space with enough space for our size:
|
||||
* just take the biggest available and go in */
|
||||
if(!found)
|
||||
for(r = arealist; r; r = r->next)
|
||||
if(r->width * r->height > newgeometry.width * newgeometry.height)
|
||||
newgeometry = *r;
|
||||
{
|
||||
for(int i = 0; i < areas.len; i++)
|
||||
{
|
||||
area_t *r = &areas.tab[i];
|
||||
if(r->width * r->height > newgeometry.width * newgeometry.height)
|
||||
newgeometry = *r;
|
||||
}
|
||||
}
|
||||
|
||||
/* restore height and width */
|
||||
newgeometry.width = c->f_geometry.width;
|
||||
|
@ -122,8 +129,7 @@ placement_smart(client_t *c)
|
|||
newgeometry = placement_fix_offscreen(newgeometry, c->screen, c->border);
|
||||
newgeometry = titlebar_geometry_remove(c->titlebar, c->border, newgeometry);
|
||||
|
||||
area_list_wipe(&arealist);
|
||||
|
||||
area_array_wipe(&areas);
|
||||
return newgeometry;
|
||||
}
|
||||
|
||||
|
|
2
screen.c
2
screen.c
|
@ -82,7 +82,7 @@ screen_area_get(int screen, statusbar_t *statusbar, padding_t *padding)
|
|||
area_t
|
||||
display_area_get(int phys_screen, statusbar_t *statusbar, padding_t *padding)
|
||||
{
|
||||
area_t area = { 0, 0, 0, 0, NULL, NULL };
|
||||
area_t area = { 0, 0, 0, 0 };
|
||||
statusbar_t *sb;
|
||||
xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
|
||||
|
||||
|
|
2
widget.c
2
widget.c
|
@ -143,7 +143,7 @@ widget_render(widget_node_t *wnode, draw_context_t *ctx, xcb_gcontext_t gc, xcb_
|
|||
char *data;
|
||||
xcb_get_property_reply_t *prop_r;
|
||||
xcb_get_property_cookie_t prop_c;
|
||||
area_t rectangle = { 0, 0, 0, 0, NULL, NULL };
|
||||
area_t rectangle = { 0, 0, 0, 0 };
|
||||
xcb_atom_t rootpix_atom;
|
||||
xutil_intern_atom_request_t rootpix_atom_req;
|
||||
|
||||
|
|
|
@ -33,14 +33,14 @@ typedef struct taglist_drawn_area_t taglist_drawn_area_t;
|
|||
struct taglist_drawn_area_t
|
||||
{
|
||||
void *object;
|
||||
area_t *area;
|
||||
area_array_t areas;
|
||||
taglist_drawn_area_t *next, *prev;
|
||||
};
|
||||
|
||||
static void
|
||||
taglist_drawn_area_delete(taglist_drawn_area_t **a)
|
||||
{
|
||||
area_list_wipe(&(*a)->area);
|
||||
area_array_wipe(&(*a)->areas);
|
||||
p_delete(a);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
|
|||
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, NULL, NULL };
|
||||
area_t area, rectangle = { 0, 0, 0, 0 };
|
||||
char **text = NULL;
|
||||
taglist_drawn_area_t *tda;
|
||||
|
||||
|
@ -157,48 +157,47 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
|
|||
taglist_drawn_area_list_push(&data->drawn_area, tda);
|
||||
}
|
||||
|
||||
area_list_wipe(&tda->area);
|
||||
tda->areas.len = 0;
|
||||
|
||||
/* First compute text and widget width */
|
||||
for(tag = vscreen->tags; tag; tag = tag->next, i++)
|
||||
{
|
||||
p_realloc(&text, i + 1);
|
||||
area = p_new(area_t, 1);
|
||||
text[i] = taglist_text_get(tag, data);
|
||||
text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i]));
|
||||
*area = draw_text_extents(ctx->connection, ctx->phys_screen,
|
||||
area = draw_text_extents(ctx->connection, ctx->phys_screen,
|
||||
globalconf.font, text[i]);
|
||||
|
||||
if (data->show_empty || tag->selected || tag_isoccupied(tag))
|
||||
w->area.width += area->width;
|
||||
w->area.width += area.width;
|
||||
|
||||
area_list_append(&tda->area, area);
|
||||
area_array_append(&tda->areas, area);
|
||||
}
|
||||
|
||||
/* Now that we have widget width we can compute widget x coordinate */
|
||||
w->area.x = widget_calculate_offset(ctx->width, w->area.width,
|
||||
offset, w->widget->align);
|
||||
|
||||
for(area = tda->area, tag = vscreen->tags, i = 0;
|
||||
tag && area;
|
||||
tag = tag->next, area = area->next, i++)
|
||||
for(i = 0, tag = vscreen->tags; tag && i < tda->areas.len; i++, tag = tag->next)
|
||||
{
|
||||
area_t *r = &tda->areas.tab[i];
|
||||
|
||||
if (!data->show_empty && !tag->selected && !tag_isoccupied(tag))
|
||||
{
|
||||
p_delete(&text[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
area->x = w->area.x + prev_width;
|
||||
prev_width += area->width;
|
||||
draw_text(ctx, globalconf.font, *area, text[i]);
|
||||
r->x = w->area.x + prev_width;
|
||||
prev_width += r->width;
|
||||
draw_text(ctx, globalconf.font, *r, text[i]);
|
||||
p_delete(&text[i]);
|
||||
|
||||
if(tag_isoccupied(tag))
|
||||
{
|
||||
rectangle.width = rectangle.height = (globalconf.font->height + 2) / 3;
|
||||
rectangle.x = area->x;
|
||||
rectangle.y = area->y;
|
||||
rectangle.x = r->x;
|
||||
rectangle.y = r->y;
|
||||
draw_rectangle(ctx, rectangle, 1.0,
|
||||
sel && is_client_tagged(sel, tag), ctx->fg);
|
||||
}
|
||||
|
@ -228,16 +227,17 @@ taglist_button_press(widget_node_t *w,
|
|||
button_t *b;
|
||||
taglist_data_t *data = w->widget->data;
|
||||
taglist_drawn_area_t *tda;
|
||||
area_t *area;
|
||||
tag_t *tag;
|
||||
int i;
|
||||
|
||||
/* Find the good drawn area list */
|
||||
for(tda = data->drawn_area; tda && tda->object != object; tda = tda->next);
|
||||
area = tda->area;
|
||||
|
||||
for(b = w->widget->buttons; b; b = b->next)
|
||||
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
|
||||
for(tag = vscreen->tags; tag && area; tag = tag->next, area = area->next)
|
||||
for(i = 0, tag = vscreen->tags; tag && i < tda->areas.len; tag = tag->next, i++)
|
||||
{
|
||||
area_t *area = &tda->areas.tab[i];
|
||||
if(ev->event_x >= AREA_LEFT(*area)
|
||||
&& ev->event_x < AREA_RIGHT(*area)
|
||||
&& (data->show_empty || tag->selected || tag_isoccupied(tag)) )
|
||||
|
@ -247,6 +247,7 @@ taglist_button_press(widget_node_t *w,
|
|||
luaA_dofunction(globalconf.L, b->fct, 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static widget_tell_status_t
|
||||
|
|
Loading…
Reference in New Issue