Hi people, I finally found some time to hack around awesome again, so here i present a backport of :extents() from the widget-layouts branch to the master branch and a little addition to naughty which makes it behave much more friendly to screen space by automagically resizing naughtyfications so they take exactly as much space as they need.
The first patch export a function called :extents() for each widget which takes
a screen number as its argument. This is only used for systrays to correctly
calculate their geometries, for all other widgets it is ignored. If it's
omitted for a systray, 1 is assumed. It returns the geometry the widget wants
to be drawn at, which doesn't take later resizing into account (i.e. if you
have a square 64x64 imagebox with resize enabled on a wibox with 16 px
height, :extents().height will still be 64 although the widget is actually
drawn 16 pixels high).
The second patch adds support for resizing to naughty. See the commit message
for additional details on how it works.
--
GCS/IT/M d- s+:- a--- C++ UL+++ US UB++ P+++ L+++ E--- W+ N+ o--
K- w--- O M-- V PS+ PE- Y+ PGP+++ t+ 5 X+ R tv+ b++ DI+++ D+++ G+
e- h! r y+
Gregor Best
From b3d219ee638f76f9ecd97b0eeb0cace437c0cf64 Mon Sep 17 00:00:00 2001 From: Gregor Best <[email protected]> Date: Tue, 5 May 2009 19:55:29 +0200 Subject: [PATCH 1/2] widgets: export extents() function This commit adds a function called extents() to widgets. In the case of a systray, it takes the systray's screen as its argument to correctly calculate the width. By default, 1 is assumed. For all other widgets, the argument can be ommitted. The function doesn't return the geometry as drawn, instead it returns the geometry the widget _wants_ to be drawn at, for example an imagebox always has (image width, image height) as the return values even if it's drawn with a smaller width and height on a smaller wibox. Signed-off-by: Gregor Best <[email protected]> --- widget.c | 24 ++++++++++++++++++++++++ widget.h | 4 +++- widgets/graph.c | 11 +++++++++++ widgets/imagebox.c | 21 +++++++++++++++++++++ widgets/progressbar.c | 29 +++++++++++++++++++++++++++++ widgets/systray.c | 28 ++++++++++++++++++++++++++++ widgets/textbox.c | 25 +++++++++++++++++++++++++ 7 files changed, 141 insertions(+), 1 deletions(-) diff --git a/widget.c b/widget.c index f8c00e3..d6372bb 100644 --- a/widget.c +++ b/widget.c @@ -494,6 +494,29 @@ luaA_widget_newindex(lua_State *L) return 0; } +static int +luaA_widget_extents(lua_State *L) +{ + widget_t *widget = luaL_checkudata(L, 1, "widget"); + area_t g = { + .x = 0, + .y = 0, + .width = 0, + .height = 0 + }; + + if(widget->extents) + g = widget->extents(L, widget); + + lua_newtable(L); + lua_pushnumber(L, g.width); + lua_setfield(L, -2, "width"); + lua_pushnumber(L, g.height); + lua_setfield(L, -2, "height"); + + return 1; +} + const struct luaL_reg awesome_widget_methods[] = { { "__call", luaA_widget_new }, @@ -502,6 +525,7 @@ const struct luaL_reg awesome_widget_methods[] = const struct luaL_reg awesome_widget_meta[] = { { "buttons", luaA_widget_buttons }, + { "extents", luaA_widget_extents }, { "__index", luaA_widget_index }, { "__newindex", luaA_widget_newindex }, { "__gc", luaA_widget_gc }, diff --git a/widget.h b/widget.h index 97c792e..02fbc9a 100644 --- a/widget.h +++ b/widget.h @@ -37,8 +37,10 @@ struct widget_t widget_constructor_t *type; /** Widget destructor */ widget_destructor_t *destructor; - /** Geometry function */ + /** Geometry function for drawing */ area_t (*geometry)(widget_t *, screen_t *, int, int); + /** Extents function */ + area_t (*extents)(lua_State *, widget_t *); /** Draw function */ void (*draw)(widget_t *, draw_context_t *, area_t, wibox_t *); /** Index function */ diff --git a/widgets/graph.c b/widgets/graph.c index 675239b..44f8f0e 100644 --- a/widgets/graph.c +++ b/widgets/graph.c @@ -159,6 +159,16 @@ graph_geometry(widget_t *widget, screen_t *screen, int height, int width) return geometry; } +static area_t +graph_extents(lua_State *L, widget_t *widget) +{ + area_t geometry; + graph_data_t *d = widget->data; + geometry.width = geometry.height = d->width; + + return geometry; +} + /** Draw a graph widget. * \param ctx The draw context. * \param w The widget node we are called from. @@ -592,6 +602,7 @@ widget_graph(widget_t *w) w->newindex = luaA_graph_newindex; w->destructor = graph_destructor; w->geometry = graph_geometry; + w->extents = graph_extents; graph_data_t *d = w->data = p_new(graph_data_t, 1); diff --git a/widgets/imagebox.c b/widgets/imagebox.c index de8b5f0..ddcd131 100644 --- a/widgets/imagebox.c +++ b/widgets/imagebox.c @@ -72,6 +72,26 @@ imagebox_geometry(widget_t *widget, screen_t *screen, int height, int width) return geometry; } +static area_t +imagebox_extents(lua_State *L, widget_t *widget) +{ + area_t geometry = { + .x = 0, + .y = 0, + .width = 0, + .height = 0 + }; + imagebox_data_t *d = widget->data; + + if (d->image) + { + geometry.height = d->image->height; + geometry.width = d->image->width; + } + + return geometry; +} + /** Draw an image. * \param widget The widget. * \param ctx The draw context. @@ -210,6 +230,7 @@ widget_imagebox(widget_t *w) w->newindex = luaA_imagebox_newindex; w->destructor = imagebox_destructor; w->geometry = imagebox_geometry; + w->extents = imagebox_extents; w->data = d = p_new(imagebox_data_t, 1); d->resize = true; d->valign = AlignTop; diff --git a/widgets/progressbar.c b/widgets/progressbar.c index 940c058..1f93237 100644 --- a/widgets/progressbar.c +++ b/widgets/progressbar.c @@ -161,6 +161,34 @@ progressbar_geometry(widget_t *widget, screen_t *screen, int height, int width) return geometry; } +static area_t +progressbar_extents(lua_State *L, widget_t *widget) +{ + area_t geometry; + progressbar_data_t *d = widget->data; + + 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); + } + + geometry.height = geometry.width; + + return geometry; +} + /** Draw a progressbar. * \param ctx The draw context. * \param w The widget node we're drawing for. @@ -646,6 +674,7 @@ widget_progressbar(widget_t *w) w->newindex = luaA_progressbar_newindex; w->destructor = progressbar_destructor; w->geometry = progressbar_geometry; + w->extents = progressbar_extents; progressbar_data_t *d = w->data = p_new(progressbar_data_t, 1); diff --git a/widgets/systray.c b/widgets/systray.c index 2c277f7..109d2b3 100644 --- a/widgets/systray.c +++ b/widgets/systray.c @@ -48,6 +48,33 @@ systray_geometry(widget_t *widget, screen_t *screen, int height, int width) return geometry; } +static area_t +systray_extents(lua_State *L, widget_t *widget) +{ + area_t geometry; + int screen = screen_virttophys(luaL_optnumber(L, -1, 1)), n = 0; + + geometry.height = 0; + int width = 0; + + for(int i = 0; i < globalconf.embedded.len; i++) + if(globalconf.embedded.tab[i].phys_screen == screen) + { + xcb_get_geometry_cookie_t geo = xcb_get_geometry(globalconf.connection, globalconf.embedded.tab[i].win); + xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(globalconf.connection, geo, NULL); + + n++; + if(g->height > geometry.height) + geometry.height = g->height; + if(g->width > width) + width = g->width; + } + + geometry.width = width * n; + + return geometry; +} + static void systray_draw(widget_t *widget, draw_context_t *ctx, area_t geometry, wibox_t *p) @@ -81,6 +108,7 @@ widget_systray(widget_t *w) { w->draw = systray_draw; w->geometry = systray_geometry; + w->extents = systray_extents; return w; } diff --git a/widgets/textbox.c b/widgets/textbox.c index 6848108..5abea21 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -75,6 +75,30 @@ textbox_geometry(widget_t *widget, screen_t *screen, int height, int width) return geometry; } +static area_t +textbox_extents(lua_State *L, widget_t *widget) +{ + textbox_data_t *d = widget->data; + area_t geometry = d->extents; + + geometry.width += d->margin.left + d->margin.left; + geometry.height += d->margin.bottom + d->margin.top; + + if(d->bg_image) + { + double ratio = d->bg_resize ? (double) geometry.height / d->bg_image->height : 1; + geometry.width = MAX(d->extents.width + d->margin.left + d->margin.right, MAX(d->width, d->bg_image->width * ratio)); + } + + if (d->data.len == 0) + { + geometry.width = 0; + geometry.height = 0; + } + + return geometry; +} + /** Draw a textbox widget. * \param widget The widget. * \param ctx The draw context. @@ -370,6 +394,7 @@ widget_textbox(widget_t *w) w->newindex = luaA_textbox_newindex; w->destructor = textbox_destructor; w->geometry = textbox_geometry; + w->extents = textbox_extents; textbox_data_t *d = w->data = p_new(textbox_data_t, 1); d->ellip = PANGO_ELLIPSIZE_END; -- 1.6.2.3
From 3ec6319e4a5a6ffbe2546eba444b8af2c0353020 Mon Sep 17 00:00:00 2001 From: Gregor Best <[email protected]> Date: Tue, 5 May 2009 20:38:15 +0200 Subject: [PATCH 2/2] naughty: resize naughtifications to the minimum needed space This commits adds support for :extents() to naughty. It changes the behaviour of naughty.config.presets.*.width so that if it's set to nil, the notification gets resized automagically. Else the value of width is used for the notification's width. The meaning of naughty.config.presets.*.height changed similarly, now, if set, it means the literal height of the notifications. If unset, the notification gets resized automagically as well. Signed-off-by: Gregor Best <[email protected]> --- lib/naughty.lua.in | 35 +++++++++++++++++++++++++++-------- 1 files changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/naughty.lua.in b/lib/naughty.lua.in index 45ec3b5..6d042dc 100644 --- a/lib/naughty.lua.in +++ b/lib/naughty.lua.in @@ -91,8 +91,8 @@ config.presets = { hover_timeout = nil, position = "top_right", screen = 1, - width = 300, - height = 16, + width = nil, + height = nil, icon = nil, icon_size = nil }, @@ -271,6 +271,7 @@ function notify(args) local screen = args.screen or (args.preset and args.preset.screen) or config.presets.normal.screen local ontop = args.ontop or config.ontop local width = args.width or (args.preset and args.preset.width) or config.presets.normal.width + local height = args.preset and args.preset.height or config.presets.normal.height local hover_timeout = args.hover_timeout or (args.preset and args.preset.hover_timeout) or config.presets.normal.hover_timeout local opacity = args.opacity or (args.preset and args.preset.opacity) or config.presets.normal.opacity @@ -369,13 +370,31 @@ function notify(args) border_width = config.border_width }) -- position the wibox - local lines = 1; for i in string.gmatch(title..text, "\n") do lines = lines + 1 end - local height = args.preset and args.preset.height or config.presets.normal.height - if iconbox and iconbox.image.height > lines * height then - notification.height = iconbox.image.height + if height then + if iconbox and iconbox.image.height > height then + notification.height = iconbox.image.height + else + notification.height = height + end + else + if iconbox and iconbox:extents().height > textbox:extents().height then + notification.height = iconbox:extents().height + else + notification.height = textbox:extents().height + end + end + if width then + notification.width = width else - notification.height = lines * height end - notification.width = width + notification.width = textbox:extents().width + (iconbox and iconbox:extents().width or 0) + (2 * (config.border_width or 0)) + end + if notification.width > capi.screen[screen].workarea.width - 2 * (config.border_width or 0) then + notification.width = capi.screen[screen].workarea.width - 2 * (config.border_width or 0) + end + if notification.height > capi.screen[screen].workarea.height - 2 * (config.border_width or 0) - 2 * (config.padding or 0) then + notification.height = capi.screen[screen].workarea.height - 2 * (config.border_width or 0) - 2 * (config.padding or 0) + end + local offset = get_offset(screen, notification.position, notification.idx, notification.width, notification.height) notification.box:geometry({ width = notification.width, height = notification.height, -- 1.6.2.3
signature.asc
Description: PGP signature
