diff --git a/event.c b/event.c index d5f4228a..a16a4ba9 100644 --- a/event.c +++ b/event.c @@ -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; } diff --git a/lib/awful/widget.lua.in b/lib/awful/widget.lua.in index a0c241c8..ff56722d 100644 --- a/lib/awful/widget.lua.in +++ b/lib/awful/widget.lua.in @@ -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 diff --git a/structs.h b/structs.h index a50cff31..8fbab0fb 100644 --- a/structs.h +++ b/structs.h @@ -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 */ diff --git a/wibox.c b/wibox.c index 91d17709..b6c837f1 100644 --- a/wibox.c +++ b/wibox.c @@ -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, diff --git a/widget.c b/widget.c index 166a6381..8b8d2aa1 100644 --- a/widget.c +++ b/widget.c @@ -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: diff --git a/widget.h b/widget.h index 966c9143..78430c2d 100644 --- a/widget.h +++ b/widget.h @@ -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. diff --git a/widgets/graph.c b/widgets/graph.c index 1300a405..d0cbc5c0 100644 --- a/widgets/graph.c +++ b/widgets/graph.c @@ -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; diff --git a/widgets/imagebox.c b/widgets/imagebox.c index a2826007..4ebe1b09 100644 --- a/widgets/imagebox.c +++ b/widgets/imagebox.c @@ -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; diff --git a/widgets/progressbar.c b/widgets/progressbar.c index 42a5436a..3a5546f6 100644 --- a/widgets/progressbar.c +++ b/widgets/progressbar.c @@ -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; diff --git a/widgets/systray.c b/widgets/systray.c index 073373d6..324eef5d 100644 --- a/widgets/systray.c +++ b/widgets/systray.c @@ -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; diff --git a/widgets/textbox.c b/widgets/textbox.c index a2ccb6de..86559a2c 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -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;