widgets: use a geometry callback

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-10-22 17:32:17 +02:00
parent 4a6885e0eb
commit 25bf12868a
11 changed files with 218 additions and 185 deletions

View file

@ -112,8 +112,8 @@ widget_getbycoords(position_t position, widget_node_array_t *widgets, int width,
{
widget_node_t *w = &widgets->tab[i];
if(w->widget->isvisible &&
*x >= w->area.x && *x < w->area.x + w->area.width
&& *y >= w->area.y && *y < w->area.y + w->area.height)
*x >= w->geometry.x && *x < w->geometry.x + w->geometry.width
&& *y >= w->geometry.y && *y < w->geometry.y + w->geometry.height)
return w;
}

View file

@ -238,9 +238,14 @@ function tasklist.new(label, buttons)
end
w[k + 1].text, w[k].bg = label(clients[(k + 1) / 2])
if w[k + 1].text then
w[k].visible = true
w[k + 1].visible = true
-- Set icon
w[k].image = clients[(k + 1) / 2].icon
if w[k].image then
w[k].visible = true
else
w[k].visible = false
end
w[k + 1].visible = true
else
w[k].visible = false
w[k + 1].visible = false

View file

@ -129,8 +129,10 @@ struct widget_t
widget_constructor_t *type;
/** Widget destructor */
widget_destructor_t *destructor;
/** Geometry function */
area_t (*geometry)(widget_t *, int, int, int);
/** Draw function */
int (*draw)(draw_context_t *, int, widget_node_t *, int, int, wibox_t *);
void (*draw)(widget_t *, draw_context_t *, area_t, int, wibox_t *);
/** Index function */
int (*index)(lua_State *, awesome_token_t);
/** Newindex function */

32
wibox.c
View file

@ -131,7 +131,7 @@ wibox_systray_refresh(wibox_t *wibox)
if(wibox->isvisible
&& systray->widget->isvisible
&& systray->area.width)
&& systray->geometry.width)
{
pos = wibox->position;
@ -145,22 +145,22 @@ wibox_systray_refresh(wibox_t *wibox)
switch(wibox->position)
{
case Left:
config_win_vals[0] = systray->area.y;
config_win_vals[1] = wibox->sw.geometry.height - systray->area.x - systray->area.width;
config_win_vals[2] = systray->area.height;
config_win_vals[3] = systray->area.width;
config_win_vals[0] = systray->geometry.y;
config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
config_win_vals[2] = systray->geometry.height;
config_win_vals[3] = systray->geometry.width;
break;
case Right:
config_win_vals[0] = systray->area.y;
config_win_vals[1] = systray->area.x;
config_win_vals[2] = systray->area.height;
config_win_vals[3] = systray->area.width;
config_win_vals[0] = systray->geometry.y;
config_win_vals[1] = systray->geometry.x;
config_win_vals[2] = systray->geometry.height;
config_win_vals[3] = systray->geometry.width;
break;
default:
config_win_vals[0] = systray->area.x;
config_win_vals[1] = systray->area.y;
config_win_vals[2] = systray->area.width;
config_win_vals[3] = systray->area.height;
config_win_vals[0] = systray->geometry.x;
config_win_vals[1] = systray->geometry.y;
config_win_vals[2] = systray->geometry.width;
config_win_vals[3] = systray->geometry.height;
break;
}
/* reparent */
@ -180,7 +180,7 @@ wibox_systray_refresh(wibox_t *wibox)
| XCB_CONFIG_WINDOW_HEIGHT,
config_win_vals);
/* width = height = systray height */
config_win_vals[2] = config_win_vals[3] = systray->area.height;
config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
config_win_vals[0] = 0;
}
else
@ -189,7 +189,7 @@ wibox_systray_refresh(wibox_t *wibox)
switch(pos)
{
case Left:
config_win_vals[1] = systray->area.width - config_win_vals[3];
config_win_vals[1] = systray->geometry.width - config_win_vals[3];
for(em = globalconf.embedded; em; em = em->next)
if(em->phys_screen == phys_screen)
{
@ -242,7 +242,7 @@ wibox_systray_refresh(wibox_t *wibox)
if(em->phys_screen == phys_screen)
{
/* if(x + width < systray.x + systray.width) */
if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->area) + wibox->sw.geometry.x)
if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
{
xcb_map_window(globalconf.connection, em->win);
xcb_configure_window(globalconf.connection, em->win,

View file

@ -128,12 +128,7 @@ widget_render(widget_node_array_t *widgets, draw_context_t *ctx, xcb_gcontext_t
int screen, orientation_t orientation,
int x, int y, wibox_t *wibox)
{
xcb_pixmap_t rootpix;
xcb_screen_t *s;
int left = 0, right = 0;
char *data;
xcb_get_property_reply_t *prop_r;
xcb_get_property_cookie_t prop_c;
area_t rectangle = { 0, 0, 0, 0 };
rectangle.width = ctx->width;
@ -141,7 +136,11 @@ widget_render(widget_node_array_t *widgets, draw_context_t *ctx, xcb_gcontext_t
if(ctx->bg.alpha != 0xffff)
{
s = xutil_screen_get(globalconf.connection, ctx->phys_screen);
xcb_get_property_reply_t *prop_r;
char *data;
xcb_pixmap_t rootpix;
xcb_get_property_cookie_t prop_c;
xcb_screen_t *s = xutil_screen_get(globalconf.connection, ctx->phys_screen);
prop_c = xcb_get_property_unchecked(globalconf.connection, false, s->root, _XROOTPMAP_ID,
PIXMAP, 0, 1);
if((prop_r = xcb_get_property_reply(globalconf.connection, prop_c, NULL)))
@ -181,18 +180,27 @@ widget_render(widget_node_array_t *widgets, draw_context_t *ctx, xcb_gcontext_t
}
}
draw_rectangle(ctx, rectangle, 1.0, true, &ctx->bg);
/* compute geometry */
for(int i = 0; i < widgets->len; i++)
if(widgets->tab[i].widget->align == AlignLeft && widgets->tab[i].widget->isvisible)
left += widgets->tab[i].widget->draw(ctx, screen, &widgets->tab[i], left, (left + right), wibox);
{
widgets->tab[i].geometry = widgets->tab[i].widget->geometry(widgets->tab[i].widget,
screen, ctx->height,
ctx->width - (left + right));
widgets->tab[i].geometry.x = left;
left += widgets->tab[i].geometry.width;
}
/* renders right widget from last to first */
for(int i = widgets->len - 1; i >= 0; i--)
if(widgets->tab[i].widget->align == AlignRight && widgets->tab[i].widget->isvisible)
right += widgets->tab[i].widget->draw(ctx, screen, &widgets->tab[i], right, (left + right), wibox);
{
widgets->tab[i].geometry = widgets->tab[i].widget->geometry(widgets->tab[i].widget,
screen, ctx->height,
ctx->width - (left + right));
right += widgets->tab[i].geometry.width;
widgets->tab[i].geometry.x = ctx->width - right;
}
/* \todo rewrite this */
int flex = 0;
for(int i = 0; i < widgets->len; i++)
if(widgets->tab[i].widget->align == AlignFlex && widgets->tab[i].widget->isvisible)
@ -204,9 +212,27 @@ widget_render(widget_node_array_t *widgets, draw_context_t *ctx, xcb_gcontext_t
for(int i = 0; i < widgets->len; i++)
if(widgets->tab[i].widget->align == AlignFlex && widgets->tab[i].widget->isvisible)
left += widgets->tab[i].widget->draw(ctx, screen, &widgets->tab[i], left, (left + right) + length * --flex , wibox);
{
widgets->tab[i].geometry = widgets->tab[i].widget->geometry(widgets->tab[i].widget,
screen, ctx->height,
length);
widgets->tab[i].geometry.x = left;
left += widgets->tab[i].geometry.width;
}
}
/* draw everything! */
draw_rectangle(ctx, rectangle, 1.0, true, &ctx->bg);
for(int i = 0; i < widgets->len; i++)
if(widgets->tab[i].widget->isvisible)
{
widgets->tab[i].geometry.y = 0;
widgets->tab[i].widget->draw(widgets->tab[i].widget,
ctx, widgets->tab[i].geometry,
screen, wibox);
}
switch(orientation)
{
case South:

View file

@ -30,8 +30,8 @@ struct widget_node_t
{
/** The widget */
widget_t *widget;
/** The area where the widget was drawn */
area_t area;
/** The geometry where the widget was drawn */
area_t geometry;
};
/** Delete a widget structure.

View file

@ -148,6 +148,18 @@ graph_plot_get(graph_data_t *d, const char *title)
return graph_plot_add(d, title);
}
static area_t
graph_geometry(widget_t *widget, int screen, int height, int width)
{
area_t geometry;
graph_data_t *d = widget->data;
geometry.height = height;
geometry.width = d->width;
return geometry;
}
/** Draw a graph widget.
* \param ctx The draw context.
* \param screen The screen number.
@ -157,35 +169,26 @@ graph_plot_get(graph_data_t *d, const char *title)
* \param p A pointer to the object we're drawing onto.
* \return The widget width.
*/
static int
graph_draw(draw_context_t *ctx,
int screen __attribute__ ((unused)),
widget_node_t *w,
int offset,
int used __attribute__ ((unused)),
wibox_t *p __attribute__ ((unused)))
static void
graph_draw(widget_t *widget, draw_context_t *ctx,
area_t geometry, int screen, wibox_t *p)
{
int margin_top, y;
graph_data_t *d = w->widget->data;
graph_data_t *d = widget->data;
area_t rectangle;
vector_t color_gradient;
if(!d->plots.len)
return 0;
w->area.x = widget_calculate_offset(ctx->width,
d->width, offset,
w->widget->align);
w->area.y = 0;
return;
/* box = the plot inside the rectangle */
if(!d->box_height)
d->box_height = round(ctx->height * d->height) - 2;
margin_top = round((ctx->height - (d->box_height + 2)) / 2) + w->area.y;
margin_top = round((ctx->height - (d->box_height + 2)) / 2) + geometry.y;
/* draw background */
rectangle.x = w->area.x + 1;
rectangle.x = geometry.x + 1;
rectangle.y = margin_top + 1;
rectangle.width = d->size;
rectangle.height = d->box_height;
@ -279,15 +282,11 @@ graph_draw(draw_context_t *ctx,
}
/* draw border (after line-drawing, what paints 0-values to the border) */
rectangle.x = w->area.x;
rectangle.x = geometry.x;
rectangle.y = margin_top;
rectangle.width = d->size + 2;
rectangle.height = d->box_height + 2;
draw_rectangle(ctx, rectangle, 1.0, false, &d->border_color);
w->area.width = d->width;
w->area.height = ctx->height;
return w->area.width;
}
/** Set various plot graph properties.
@ -596,6 +595,7 @@ graph_new(alignment_t align)
w->newindex = luaA_graph_newindex;
w->destructor = graph_destructor;
w->align = align;
w->geometry = graph_geometry;
d = w->data = p_new(graph_data_t, 1);
d->width = 80;

View file

@ -32,45 +32,45 @@ typedef struct
xcolor_t bg;
} imagebox_data_t;
/** Draw an image.
* \param ctx The draw context.
* \param screen The screen.
* \param w The widget node we are linked from.
* \param offset Offset to draw at.
* \param used The size used on the element.
* \param p A pointer to the object we're draw onto.
* \return The width used.
*/
static int
imagebox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)),
widget_node_t *w,
int offset, int used,
wibox_t *p)
static area_t
imagebox_geometry(widget_t *widget, int screen, int height, int width)
{
imagebox_data_t *d = w->widget->data;
w->area.y = 0;
area_t geometry;
imagebox_data_t *d = widget->data;
if(d->image)
{
w->area.height = ctx->height;
w->area.width = ((double) ctx->height / (double) d->image->height) * d->image->width;
w->area.x = widget_calculate_offset(ctx->width,
w->area.width,
offset,
w->widget->align);
if(d->bg.initialized)
draw_rectangle(ctx, w->area, 1.0, true, &d->bg);
draw_image(ctx, w->area.x, w->area.y, ctx->height, d->image);
geometry.height = height;
geometry.width = ((double) height / (double) d->image->height) * d->image->width;
}
else
{
w->area.width = 0;
w->area.height = 0;
geometry.width = 0;
geometry.height = 0;
}
return w->area.width;
return geometry;
}
/** Draw an image.
* \param widget The widget.
* \param ctx The draw context.
* \param geometry The geometry we draw in.
* \param screen The screen.
* \param p A pointer to the object we're draw onto.
*/
static void
imagebox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
int screen, wibox_t *p)
{
imagebox_data_t *d = widget->data;
if(d->image)
{
if(d->bg.initialized)
draw_rectangle(ctx, geometry, 1.0, true, &d->bg);
draw_image(ctx, geometry.x, geometry.y, ctx->height, d->image);
}
}
/** Delete a imagebox widget.
@ -171,6 +171,7 @@ imagebox_new(alignment_t align)
w->index = luaA_imagebox_index;
w->newindex = luaA_imagebox_newindex;
w->destructor = imagebox_destructor;
w->geometry = imagebox_geometry;
w->data = p_new(imagebox_data_t, 1);
return w;

View file

@ -133,6 +133,35 @@ progressbar_bar_get(bar_array_t *bars, const char *title)
return progressbar_bar_add(bars, title);
}
static area_t
progressbar_geometry(widget_t *widget, int screen, int height, int width)
{
area_t geometry;
progressbar_data_t *d = widget->data;
geometry.height = height;
if(d->vertical)
{
int pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->bars.len
- d->gap * (d->bars.len - 1)) / d->bars.len);
geometry.width = d->bars.len * (pb_width + 2 * (d->border_width + d->border_padding)
+ d->gap) - d->gap;
}
else
{
int pb_width = d->width - 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap)
{
int unit = (pb_width + d->ticks_gap) / d->ticks_count;
pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */
}
geometry.width = pb_width + 2 * (d->border_width + d->border_padding);
}
return geometry;
}
/** Draw a progressbar.
* \param ctx The draw context.
* \param screen The screen we're drawing for.
@ -142,47 +171,19 @@ progressbar_bar_get(bar_array_t *bars, const char *title)
* \param object The object pointer we're drawing onto.
* \return The width used.
*/
static int
progressbar_draw(draw_context_t *ctx,
int screen __attribute__ ((unused)),
widget_node_t *w,
int offset,
int used __attribute__ ((unused)),
wibox_t *p __attribute__ ((unused)))
static void
progressbar_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
int screen, wibox_t *p)
{
/* pb_.. values points to the widget inside a potential border */
int values_ticks, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset;
int unit = 0; /* tick + gap */
area_t rectangle;
vector_t color_gradient;
progressbar_data_t *d = w->widget->data;
progressbar_data_t *d = widget->data;
if(!d->bars.len)
return 0;
if(d->vertical)
{
pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->bars.len
- d->gap * (d->bars.len - 1)) / d->bars.len);
w->area.width = d->bars.len * (pb_width + 2 * (d->border_width + d->border_padding)
+ d->gap) - d->gap;
}
else
{
pb_width = d->width - 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap)
{
unit = (pb_width + d->ticks_gap) / d->ticks_count;
pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */
}
w->area.width = pb_width + 2 * (d->border_width + d->border_padding);
}
w->area.x = widget_calculate_offset(ctx->width,
w->area.width,
offset,
w->widget->align);
w->area.y = 0;
return;
/* for a 'reversed' progressbar:
* basic progressbar:
@ -195,11 +196,14 @@ progressbar_draw(draw_context_t *ctx,
* 2. finally draw the gaps
*/
pb_x = w->area.x + d->border_width + d->border_padding;
pb_x = geometry.x + d->border_width + d->border_padding;
pb_offset = 0;
if(d->vertical)
{
pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->bars.len
- d->gap * (d->bars.len - 1)) / d->bars.len);
/** \todo maybe prevent to calculate that stuff below over and over again
* (->use static-values) */
pb_height = (int) (ctx->height * d->height + 0.5)
@ -211,7 +215,7 @@ progressbar_draw(draw_context_t *ctx,
pb_height = unit * d->ticks_count - d->ticks_gap;
}
pb_y = w->area.y + ((int) (ctx->height * (1 - d->height)) / 2)
pb_y = geometry.y + ((int) (ctx->height * (1 - d->height)) / 2)
+ d->border_width + d->border_padding;
for(int i = 0; i < d->bars.len; i++)
@ -312,10 +316,18 @@ progressbar_draw(draw_context_t *ctx,
}
else /* a horizontal progressbar */
{
pb_width = d->width - 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap)
{
unit = (pb_width + d->ticks_gap) / d->ticks_count;
pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */
}
pb_height = (int) ((ctx->height * d->height
- d->bars.len * 2 * (d->border_width + d->border_padding)
- (d->gap * (d->bars.len - 1))) / d->bars.len + 0.5);
pb_y = w->area.y + ((int) (ctx->height * (1 - d->height)) / 2)
pb_y = geometry.y + ((int) (ctx->height * (1 - d->height)) / 2)
+ d->border_width + d->border_padding;
for(int i = 0; i < d->bars.len; i++)
@ -410,9 +422,6 @@ progressbar_draw(draw_context_t *ctx,
pb_offset += pb_height + d->gap + 2 * (d->border_width + d->border_padding);
}
}
w->area.height = ctx->height;
return w->area.width;
}
/** Set various progressbar bars properties:
@ -643,6 +652,7 @@ progressbar_new(alignment_t align)
w->index = luaA_progressbar_index;
w->newindex = luaA_progressbar_newindex;
w->destructor = progressbar_destructor;
w->geometry = progressbar_geometry;
d = w->data = p_new(progressbar_data_t, 1);
d->height = 0.80;

View file

@ -32,36 +32,30 @@
extern awesome_t globalconf;
static int
systray_draw(draw_context_t *ctx,
int screen __attribute__ ((unused)),
widget_node_t *w,
int offset, int used __attribute__ ((unused)),
wibox_t *p)
static area_t
systray_geometry(widget_t *widget, int screen, int height, int width)
{
area_t geometry;
int phys_screen = screen_virttophys(screen), i = 0;
geometry.height = height;
for(xembed_window_t *em = globalconf.embedded; em; em = em->next)
if(em->phys_screen == phys_screen)
i++;
/** \todo use class hints */
geometry.width = MIN(i * height, width);
return geometry;
}
static void
systray_draw(widget_t *widget, draw_context_t *ctx,
area_t geometry, int screen, wibox_t *p)
{
uint32_t orient;
w->area.height = ctx->height;
if(ctx->width - used > 0)
{
int i = 0;
xembed_window_t *em;
for(em = globalconf.embedded; em; em = em->next)
if(em->phys_screen == p->sw.ctx.phys_screen)
i++;
/** \todo use clas hints */
w->area.width = MIN(i * ctx->height, ctx->width - used);
}
else
w->area.width = 0;
w->area.x = widget_calculate_offset(ctx->width,
w->area.width,
offset,
w->widget->align);
w->area.y = 0;
switch(p->position)
{
case Right:
@ -78,8 +72,6 @@ systray_draw(draw_context_t *ctx,
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
globalconf.screens[p->sw.ctx.phys_screen].systray.window,
_NET_SYSTEM_TRAY_ORIENTATION, CARDINAL, 32, 1, &orient);
return w->area.width;
}
widget_t *
@ -91,6 +83,7 @@ systray_new(alignment_t align)
widget_common_new(w);
w->align = align;
w->draw = systray_draw;
w->geometry = systray_geometry;
w->cache_flags = WIDGET_CACHE_EMBEDDED;
return w;

View file

@ -39,47 +39,42 @@ typedef struct
draw_parser_data_t pdata;
} textbox_data_t;
/** Draw a textbox widget.
* \param ctx The draw context.
* \param screen The screen.
* \param w The widget node we are linked from.
* \param offset Offset to draw at.
* \param used The size used on the element.
* \param p A pointer to the object we're draw onto.
* \return The width used.
*/
static int
textbox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)),
widget_node_t *w,
int offset, int used,
wibox_t *p __attribute__ ((unused)))
static area_t
textbox_geometry(widget_t *widget, int screen, int height, int width)
{
textbox_data_t *d = w->widget->data;
area_t geometry;
textbox_data_t *d = widget->data;
w->area.height = ctx->height;
geometry.height = height;
if(d->width)
w->area.width = d->width;
else if(w->widget->align == AlignFlex)
w->area.width = ctx->width - used;
geometry.width = d->width;
else if(widget->align == AlignFlex)
geometry.width = width;
else
{
w->area.width = MIN(d->extents, ctx->width - used);
geometry.width = MIN(d->extents, width);
if(d->pdata.bg_image)
w->area.width = MAX(w->area.width,
d->pdata.bg_resize ? ((double) d->pdata.bg_image->width / (double) d->pdata.bg_image->height) * w->area.height : d->pdata.bg_image->width);
geometry.width = MAX(geometry.width,
d->pdata.bg_resize ? ((double) d->pdata.bg_image->width / (double) d->pdata.bg_image->height) * geometry.height : d->pdata.bg_image->width);
}
w->area.x = widget_calculate_offset(ctx->width,
w->area.width,
offset,
w->widget->align);
w->area.y = 0;
return geometry;
}
draw_text(ctx, globalconf.font, w->area, d->text, d->len, &d->pdata);
return w->area.width;
/** Draw a textbox widget.
* \param widget The widget.
* \param ctx The draw context.
* \param screen The screen.
* \param p A pointer to the object we're draw onto.
*/
static void
textbox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
int screen, wibox_t *p)
{
textbox_data_t *d = widget->data;
draw_text(ctx, globalconf.font, geometry, d->text, d->len, &d->pdata);
}
/** Delete a textbox widget.
@ -187,6 +182,7 @@ textbox_new(alignment_t align)
w->index = luaA_textbox_index;
w->newindex = luaA_textbox_newindex;
w->destructor = textbox_destructor;
w->geometry = textbox_geometry;
w->data = d = p_new(textbox_data_t, 1);
return w;