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

Attachment: signature.asc
Description: PGP signature

Reply via email to