Hi,

don't you miss the good old times? Where men where men and awesome upgrades were
awful? Where the config broke every time you sneezed? Where there was a land
flowing with milk and honey?

Fear no more, the breakage is back!

In August 2010, I made git/master use oocairo. That brought us a new widget
system (again...) and gave people all of cairo's power for drawing stuff!

That was back then. Now, the new kid in town is lgi[0] and attached are the
patches which make awesome us that instead of oocairo/oopango. People might
wonder why this switch should happen. "Why not?" is what I reply. :-P

Also, lgi uses GObject introspection for most of its magic. This means that it
is way easier to add bindings, because most of the stuff is done automagically.
Currently, lgi provides bindings for cairo, pango, gtk, clutter and gstreamer
(but others might work without any magic and out-of-the-box).

Yet another reason is that oocairo and lgi.cairo do the same thing. Why would we
want two lua bindings for cairo? That just duplicates effort!

And finally, the upstream dev for oocairo and oopango is a lazy bastard who lets
it slowly bitrot away. oopango never was in a good state and adding cairo 1.12's
new function to oocairo needs way more work/lines than with lgi.

Now the downside: Current lgi.cairo's user_to_device() binding is broken. This
function is needed for my hacky widget system and thus awesome doesn't work. One
of the patch 0001's that I attached are for lgi and should fix this (already
sent upstream, but upstream is offline for a week).

The other patch 0001 and patch 0002 port over awesome. However, one more
downside: No configs should break and no config changes are needed (unless you
do weird things in your config, e.g. I had to change something!).

Once the lgi patch is upstream (and perhaps even got into some release), I
intend to push this.

So now that I talked so much nonsense:

What do others think about these patches? Any major objections which I will have
to ignore when I push? :-P

Cheers,
Uli

P.S.: Yes, I did exaggerate when I said "breakage". This just changes some
dependencies.

[0]: https://github.com/pavouk/lgi
-- 
- He made himself, me nothing, you nothing out of the dust
- Er machte sich mir nichts, dir nichts aus dem Staub
>From d0612cfd5bf71d7c331d7c9db9230f085b4b19f5 Mon Sep 17 00:00:00 2001
From: Uli Schlachter <[email protected]>
Date: Sat, 26 May 2012 23:24:32 +0200
Subject: [PATCH 1/1] cairo: Fix cr:user_to_device() and friends

All of these functions have inout params, not just out. Also,
user_to_device_distance was missing.

Signed-off-by: Uli Schlachter <[email protected]>
---
 lgi/override/cairo.lua |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/lgi/override/cairo.lua b/lgi/override/cairo.lua
index 4b9e2a8..32e9c75 100644
--- a/lgi/override/cairo.lua
+++ b/lgi/override/cairo.lua
@@ -245,12 +245,14 @@ for _, info in ipairs {
 	 set_matrix = { cairo.Matrix },
 	 get_matrix = { cairo.Matrix },
 	 identity_matrix = {},
-	 user_to_device = { { ti.double, dir = 'out' },
-			    { ti.double, dir = 'out' } },
-	 device_to_user = { { ti.double, dir = 'out' },
-			    { ti.double, dir = 'out' } },
-	 device_to_user_distance = { { ti.double, dir = 'out' },
-				     { ti.double, dir = 'out' } },
+	 user_to_device = { { ti.double, dir = 'inout' },
+			    { ti.double, dir = 'inout' } },
+	 user_to_device_distance = { { ti.double, dir = 'inout' },
+				     { ti.double, dir = 'inout' } },
+	 device_to_user = { { ti.double, dir = 'inout' },
+			    { ti.double, dir = 'inout' } },
+	 device_to_user_distance = { { ti.double, dir = 'inout' },
+				     { ti.double, dir = 'inout' } },
 
 	 select_font_face = { ti.utf8, cairo.FontSlant, cairo.FontWeight },
 	 set_font_size = { ti.double },
-- 
1.7.10

>From 4f30dfd198cacd08df062813e705ebb687b3d9a4 Mon Sep 17 00:00:00 2001
From: Uli Schlachter <[email protected]>
Date: Sun, 27 May 2012 19:20:34 +0200
Subject: [PATCH 1/2] Switch from oocairo to lgi.cairo

Signed-off-by: Uli Schlachter <[email protected]>
---
 awesomeConfig.cmake                |    2 -
 draw.c                             |    8 ++--
 draw.h                             |    2 +-
 lib/awful/menu.lua.in              |   18 ++++----
 lib/awful/widget/button.lua.in     |   21 +++------
 lib/awful/widget/layoutbox.lua.in  |    1 -
 lib/awful/widget/taglist.lua.in    |    7 +--
 lib/beautiful.lua.in               |   22 ++++------
 lib/gears/color.lua.in             |   20 ++++-----
 lib/gears/init.lua.in              |    1 +
 lib/gears/surface.lua.in           |   35 +++++++++++++++
 lib/naughty.lua.in                 |   21 ++++-----
 lib/wibox/init.lua.in              |   15 ++++---
 lib/wibox/widget/background.lua.in |   14 ++----
 lib/wibox/widget/imagebox.lua.in   |   12 +++---
 lib/wibox/widget/textbox.lua.in    |   82 ++++++++++++------------------------
 luaa.c                             |   17 --------
 luadoc/awesome.lua                 |    2 +-
 luadoc/drawin.lua                  |    2 +-
 objects/client.c                   |   24 +++++------
 objects/drawin.c                   |    4 +-
 root.c                             |    8 ++--
 22 files changed, 151 insertions(+), 187 deletions(-)
 create mode 100644 lib/gears/surface.lua.in

diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake
index c50295e..fc8492d 100644
--- a/awesomeConfig.cmake
+++ b/awesomeConfig.cmake
@@ -132,8 +132,6 @@ pkg_check_modules(AWESOME_REQUIRED REQUIRED
     glib-2.0
     cairo
     x11
-    oocairo
-    oopango
     xcb-randr
     xcb-xtest
     xcb-xinerama
diff --git a/draw.c b/draw.c
index a2dd511..dc8a60d 100644
--- a/draw.c
+++ b/draw.c
@@ -133,12 +133,10 @@ luaA_surface_from_data(lua_State *L, int width, int height, uint32_t *data)
     /* This makes sure that buffer will be freed */
     cairo_surface_set_user_data(surface, &data_key, buffer, &free_data);
 
-    /* This will increase the reference count of the surface */
-    int ret = oocairo_surface_push(globalconf.L, surface);
-    /* So we have to drop our own reference */
-    cairo_surface_destroy(surface);
+    /* lua has to make sure to free the ref or we have a leak */
+    lua_pushlightuserdata(L, surface);
 
-    return ret;
+    return 1;
 }
 
 /** Duplicate the specified image surface.
diff --git a/draw.h b/draw.h
index c039d55..c87db2d 100644
--- a/draw.h
+++ b/draw.h
@@ -23,7 +23,7 @@
 #define AWESOME_COMMON_DRAW_H
 
 #include <xcb/xcb.h>
-#include <oocairo.h>
+#include <cairo.h>
 
 #include "common/util.h"
 
diff --git a/lib/awful/menu.lua.in b/lib/awful/menu.lua.in
index 76e5278..07a4953 100644
--- a/lib/awful/menu.lua.in
+++ b/lib/awful/menu.lua.in
@@ -13,6 +13,8 @@ local tags = require("awful.tag")
 local keygrabber = require("awful.keygrabber")
 local beautiful = require("beautiful")
 local object = require("gears.object")
+local surface = require("gears.surface")
+local cairo = require("lgi").cairo
 local setmetatable = setmetatable
 local tonumber = tonumber
 local string = string
@@ -27,9 +29,7 @@ local capi = {
     timer = timer,
     screen = screen,
     mouse = mouse,
-    client = client,
-    awesome = awesome,
-    oocairo = oocairo }
+    client = client }
 
 
 module("awful.menu")
@@ -515,7 +515,7 @@ function entry(parent, args)
     if args.icon then
         icon = args.icon
         if type(icon) == "string" then
-            icon = capi.awesome.load_image(icon)
+            icon = surface.load(icon)
         end
     end
     if icon then
@@ -529,10 +529,10 @@ function entry(parent, args)
                 w, h = (args.theme.height / ih) * iw, args.theme.height
             end
             -- We need to scale the image to size w x h
-            local img = capi.oocairo.image_surface_create("argb32", w, h)
-            local cr = capi.oocairo.context_create(img)
+            local img = cairo.ImageSurface(cairo.Format.ARGB32, w, h)
+            local cr = cairo.Context(img)
             cr:scale(w / iw, h / ih)
-            cr:set_source(icon, 0, 0)
+            cr:set_source_surface(icon, 0, 0)
             cr:paint()
             icon = img
         end
@@ -551,9 +551,7 @@ function entry(parent, args)
     if type(args.cmd) == "table" then
         if args.theme.submenu_icon then
             submenu = wibox.widget.imagebox()
-            submenu:set_image(
-                capi.awesome.load_image(
-                args.theme.submenu_icon))
+            submenu:set_image(surface.load(args.theme.submenu_icon))
         else
             submenu = wibox.widget.textbox()
             submenu:set_font(args.theme.font)
diff --git a/lib/awful/widget/button.lua.in b/lib/awful/widget/button.lua.in
index 7647cd0..29c5aeb 100644
--- a/lib/awful/widget/button.lua.in
+++ b/lib/awful/widget/button.lua.in
@@ -8,9 +8,9 @@ local setmetatable = setmetatable
 local type = type
 local button = require("awful.button")
 local imagebox = require("wibox.widget.imagebox")
-local capi = { mouse = mouse,
-               awesome = awesome,
-               oocairo = oocairo }
+local surface = require("gears.surface")
+local cairo = require("lgi").cairo
+local capi = { mouse = mouse }
 
 module("awful.widget.button")
 
@@ -20,17 +20,10 @@ module("awful.widget.button")
 -- @return A textbox widget configured as a button.
 function new(args)
     if not args or not args.image then return end
-    local img_release
-    if type(args.image) == "string" then
-        img_release = capi.awesome.load_image(args.image)
-    elseif type(args.image) == "userdata" and args.image.type and args.image:type() == "cairo_surface_t" then
-        img_release = args.image
-    elseif type(args.image) == "userdata" and args.image._NAME and args.image._NAME == "cairo surface object" then
-        img_release = args.image
-    end
-    local img_press = capi.oocairo.image_surface_create("argb32", img_release:get_width(), img_release:get_height())
-    local cr = capi.oocairo.context_create(img_press)
-    cr:set_source(img_release, 2, 2)
+    local img_release = surface.load(args.image)
+    local img_press = cairo.ImageSurface(cairo.Format.ARGB32, img_release.width, img_release.height)
+    local cr = cairo.Context(img_press)
+    cr:set_source_surface(img_release, 2, 2)
     cr:paint()
 
     local w = imagebox()
diff --git a/lib/awful/widget/layoutbox.lua.in b/lib/awful/widget/layoutbox.lua.in
index 1723ee5..43e98ba 100644
--- a/lib/awful/widget/layoutbox.lua.in
+++ b/lib/awful/widget/layoutbox.lua.in
@@ -11,7 +11,6 @@ local layout = require("awful.layout")
 local tag = require("awful.tag")
 local beautiful = require("beautiful")
 local imagebox = require("wibox.widget.imagebox")
-local capi = { oocairo = oocairo }
 
 --- Layoutbox widget.
 module("awful.widget.layoutbox")
diff --git a/lib/awful/widget/taglist.lua.in b/lib/awful/widget/taglist.lua.in
index a6ec7f6..13f50fb 100644
--- a/lib/awful/widget/taglist.lua.in
+++ b/lib/awful/widget/taglist.lua.in
@@ -18,6 +18,7 @@ local util = require("awful.util")
 local tag = require("awful.tag")
 local beautiful = require("beautiful")
 local fixed = require("wibox.layout.fixed")
+local surface = require("gears.surface")
 
 --- Taglist widget module for awful
 module("awful.widget.taglist")
@@ -55,7 +56,7 @@ function taglist_label(t, args)
             local seltags = sel:tags()
             for _, v in ipairs(seltags) do
                 if v == t then
-                    bg_image = capi.awesome.load_image(taglist_squares_sel)
+                    bg_image = surface.load(taglist_squares_sel)
                     bg_resize = taglist_squares_resize == "true"
                     is_selected = true
                     break
@@ -67,7 +68,7 @@ function taglist_label(t, args)
         local cls = t:clients()
         if #cls > 0 then
             if taglist_squares_unsel then
-                bg_image = capi.awesome.load_image(taglist_squares_unsel)
+                bg_image = surface.load(taglist_squares_unsel)
                 bg_resize = taglist_squares_resize == "true"
             end
             if bg_occupied then bg_color = bg_occupied end
@@ -93,7 +94,7 @@ function taglist_label(t, args)
     if tag.geticon(t) and type(tag.geticon(t)) == "image" then
         icon = tag.geticon(t)
     elseif tag.geticon(t) then
-        icon = capi.awesome.load_image(tag.geticon(t))
+        icon = surface.load(tag.geticon(t))
     end
 
     return text, bg_color, bg_image, icon
diff --git a/lib/beautiful.lua.in b/lib/beautiful.lua.in
index d67dcd3..8b7ddd5 100644
--- a/lib/beautiful.lua.in
+++ b/lib/beautiful.lua.in
@@ -14,12 +14,14 @@ local type = type
 local dofile = dofile
 local setmetatable = setmetatable
 local util = require("awful.util")
+local lgi = require("lgi")
+local cairo = lgi.cairo
+local Pango = lgi.Pango
+local PangoCairo = lgi.PangoCairo
 local capi =
 {
     screen = screen,
-    awesome = awesome,
-    oocairo = oocairo,
-    oopango = oopango
+    awesome = awesome
 }
 
 --- Theme library.
@@ -40,19 +42,11 @@ local function load_font(name)
         return fonts[name]
     end
     -- load new font
-    local desc = capi.oopango.font_description_from_string(name)
+    local desc = Pango.FontDescription.from_string(name)
 
     -- Create a temporary surface that we need for computing the size :(
-    local surface = capi.oocairo.image_surface_create("argb32", 1, 1)
-    local cr = capi.oocairo.context_create(surface)
-    local layout
-    -- Api breakage in oopango
-    if capi.oopango.cairo_layout_create then
-        layout = capi.oopango.cairo_layout_create(cr)
-    else
-        layout = capi.oopango.cairo.layout_create(cr)
-    end
-
+    local surface = cairo.ImageSurface(cairo.Format.ARGB32, 1, 1)
+    local layout = PangoCairo.create_layout(cairo.Context(surface))
     layout:set_font_description(desc)
 
     local width, height = layout:get_pixel_size()
diff --git a/lib/gears/color.lua.in b/lib/gears/color.lua.in
index 1299ff6..14d1aa4 100644
--- a/lib/gears/color.lua.in
+++ b/lib/gears/color.lua.in
@@ -12,10 +12,8 @@ local unpack = unpack
 local ipairs = ipairs
 local pairs = pairs
 local type = type
-local capi = {
-    awesome = awesome,
-    oocairo = oocairo
-}
+local cairo = require("lgi").cairo
+local surface = require("gears.surface")
 
 module("gears.color")
 
@@ -60,7 +58,7 @@ function create_solid_pattern(col)
     elseif type(col) == "table" then
         col = col.color
     end
-    return capi.oocairo.pattern_create_rgba(parse_color(col))
+    return cairo.Pattern.create_rgba(parse_color(col))
 end
 
 --- Create an image pattern from a png file
@@ -71,8 +69,8 @@ function create_png_pattern(file)
     if type(file) == "table" then
         file = file.file
     end
-    local image = capi.awesome.load_image(file)
-    return capi.oocairo.pattern_create_for_surface(image)
+    local image = surface.load(file)
+    return cairo.Pattern.create_for_surface(image)
 end
 
 -- Add stops to the given pattern.
@@ -125,12 +123,12 @@ function create_linear_pattern(arg)
     local pat
 
     if type(arg) == "string" then
-        return string_pattern(capi.oocairo.pattern_create_linear, arg)
+        return string_pattern(cairo.Pattern.create_linear, arg)
     elseif type(arg) ~= "table" then
         error("Wrong argument type: " .. type(arg))
     end
 
-    pat = capi.oocairo.pattern_create_linear(arg.from[1], arg.from[2], arg.to[1], arg.to[2])
+    pat = cairo.Pattern.create_linear(arg.from[1], arg.from[2], arg.to[1], arg.to[2])
     add_stops_table(pat, arg.stops)
     return pat
 end
@@ -150,12 +148,12 @@ function create_radial_pattern(arg)
     local pat
 
     if type(arg) == "string" then
-        return string_pattern(capi.oocairo.pattern_create_radial, arg)
+        return string_pattern(cairo.Pattern.create_radial, arg)
     elseif type(arg) ~= "table" then
         error("Wrong argument type: " .. type(arg))
     end
 
-    pat = capi.oocairo.pattern_create_radial(arg.from[1], arg.from[2], arg.from[3],
+    pat = cairo.Pattern.create_radial(arg.from[1], arg.from[2], arg.from[3],
             arg.to[1], arg.to[2], arg.to[3])
     add_stops_table(pat, arg.stops)
     return pat
diff --git a/lib/gears/init.lua.in b/lib/gears/init.lua.in
index dcc4c27..f8864a1 100644
--- a/lib/gears/init.lua.in
+++ b/lib/gears/init.lua.in
@@ -8,6 +8,7 @@ require("gears.color")
 require("gears.debug")
 require("gears.object")
 require("gears.sort")
+require("gears.surface")
 
 module("gears")
 
diff --git a/lib/gears/surface.lua.in b/lib/gears/surface.lua.in
new file mode 100644
index 0000000..df38db8
--- /dev/null
+++ b/lib/gears/surface.lua.in
@@ -0,0 +1,35 @@
+---------------------------------------------------------------------------
+-- @author Uli Schlachter
+-- @copyright 2012 Uli Schlachter
+-- @release @AWESOME_VERSION@
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local type = type
+local capi = { awesome = awesome }
+local cairo = require("lgi").cairo
+
+module("gears.surface")
+
+--- Try to convert the argument into an lgi cairo surface.
+-- This is usually needed for loading images by file name.
+function load(surface)
+    -- Nil is not changed
+    if not surface then
+        return nil
+    end
+    -- lgi cairo surfaces don't get changed either
+    if cairo.Surface:is_type_of(surface) then
+        return surface
+    end
+    -- Strings are assumed to be file names and get loaded
+    if type(surface) == "string" then
+        surface = capi.awesome.load_image(surface)
+    end
+    -- Everything else gets forced into a surface
+    return cairo.Surface(surface, true)
+end
+
+setmetatable(_M, { __call = function(_, ...) return load(...) end })
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/naughty.lua.in b/lib/naughty.lua.in
index cc6a374..7906638 100644
--- a/lib/naughty.lua.in
+++ b/lib/naughty.lua.in
@@ -14,12 +14,13 @@ local capi = { screen = screen,
                awesome = awesome,
                dbus = dbus,
                timer = timer,
-               awesome = awesome,
-               oocairo = oocairo }
+               awesome = awesome }
 local button = require("awful.button")
 local util = require("awful.util")
 local bt = require("beautiful")
 local wibox = require("wibox")
+local surface = require("gears.surface")
+local cairo = require("lgi").cairo
 
 --- Notification library
 module("naughty")
@@ -399,17 +400,12 @@ function notify(args)
         if icon then
             iconbox = wibox.widget.imagebox()
             iconmargin = wibox.layout.margin(iconbox, margin, margin, margin, margin)
-            local img = icon
-            if type(icon) == "string" then
-                img = capi.awesome.load_image(icon)
-            else
-                img = icon
-            end
+            local img = surface.load(icon)
             if icon_size then
-                local scaled = capi.oocairo.image_surface_create("argb32", icon_size, icon_size)
-                local cr = capi.oocairo.context_create(scaled)
+                local scaled = cairo.ImageSurface(cairo.Format.ARGB32, icon_size, icon_size)
+                local cr = cairo.Context(scaled)
                 cr:scale(icon_size / img:get_height(), icon_size / img:get_width())
-                cr:set_source(img, 0, 0)
+                cr:set_source_surface(img, 0, 0)
                 cr:paint()
                 img = scaled
             end
@@ -543,7 +539,8 @@ if capi.dbus then
                     end
                 end
                 if imgdata then
-                    args.icon = capi.oocairo.image_surface_create_from_data(imgdata, "argb32", hints.icon_data[1], hints.icon_data[2], hints.icon_data[1] * 4)
+                    args.icon = cairo.ImageSurface.create_for_data(imgdata,
+                        cairo.Format.ARGB32, hints.icon_data[1], hints.icon_data[2], hints.icon_data[1] * 4)
                 end
             end
             if replaces_id and replaces_id ~= "" and replaces_id ~= 0 then
diff --git a/lib/wibox/init.lua.in b/lib/wibox/init.lua.in
index 02d7401..e02aa35 100644
--- a/lib/wibox/init.lua.in
+++ b/lib/wibox/init.lua.in
@@ -9,7 +9,6 @@ require("wibox.widget")
 
 local capi = {
     drawin = drawin,
-    oocairo = oocairo,
     root = root,
     awesome = awesome
 }
@@ -17,11 +16,13 @@ local setmetatable = setmetatable
 local pairs = pairs
 local type = type
 local table = table
+local string_format = string.format
 local color = require("gears.color")
 local object = require("gears.object")
 local sort = require("gears.sort")
 local beautiful = require("beautiful")
-local string_format = string.format
+local surface = require("gears.surface")
+local cairo = require("lgi").cairo
 
 --- This provides widget box windows. Every wibox can also be used as if it were
 -- a drawin. All drawin functions and properties are also available on wiboxes!
@@ -33,19 +34,19 @@ local function do_redraw(wibox)
     end
 
     local geom = wibox.drawin:geometry()
-    local cr = capi.oocairo.context_create(wibox.drawin.surface)
+    local cr = cairo.Context(surface(wibox.drawin.surface))
 
     -- Draw the background
     cr:save()
     -- This is pseudo-transparency: We draw the wallpaper in the background
-    local wallpaper = capi.root.wallpaper()
+    local wallpaper = surface(capi.root.wallpaper())
     if wallpaper then
-        cr:set_operator("source")
-        cr:set_source(wallpaper, -wibox.drawin.x, -wibox.drawin.y)
+        cr.operator = cairo.Operator.SOURCE
+        cr:set_source_surface(wallpaper, -wibox.drawin.x, -wibox.drawin.y)
         cr:paint()
     end
 
-    cr:set_operator("over")
+    cr.operator = cairo.Operator.OVER
     cr:set_source(wibox.background_color)
     cr:paint()
     cr:restore()
diff --git a/lib/wibox/widget/background.lua.in b/lib/wibox/widget/background.lua.in
index 89f9aa3..09ded3e 100644
--- a/lib/wibox/widget/background.lua.in
+++ b/lib/wibox/widget/background.lua.in
@@ -4,14 +4,14 @@
 -- @release @AWESOME_VERSION@
 ---------------------------------------------------------------------------
 
-local oocairo = require("oocairo")
 local base = require("wibox.widget.base")
 local color = require("gears.color")
 local layout_base = require("wibox.layout.base")
+local surface = require("gears.surface")
+local cairo = require("lgi").cairo
 local setmetatable = setmetatable
 local pairs = pairs
 local type = type
-local awesome = awesome
 
 module("wibox.widget.background")
 
@@ -28,7 +28,7 @@ function draw(box, wibox, cr, width, height)
         cr:paint()
     end
     if box.bgimage then
-        local pattern = oocairo.pattern_create_for_surface(box.bgimage)
+        local pattern = cairo.Pattern.create_for_surface(box.bgimage)
         cr:set_source(pattern)
         cr:paint()
     end
@@ -89,13 +89,7 @@ end
 
 --- Set the background image to use
 function set_bgimage(box, image)
-    local image = image
-
-    if type(image) == "string" then
-        image = awesome.load_image(image)
-    end
-
-    box.bgimage = image
+    box.bgimage = surface.load(image)
     box._emit_updated()
 end
 
diff --git a/lib/wibox/widget/imagebox.lua.in b/lib/wibox/widget/imagebox.lua.in
index 2e35ccb..14acb8a 100644
--- a/lib/wibox/widget/imagebox.lua.in
+++ b/lib/wibox/widget/imagebox.lua.in
@@ -5,12 +5,12 @@
 ---------------------------------------------------------------------------
 
 local base = require("wibox.widget.base")
+local surface = require("gears.surface")
 local setmetatable = setmetatable
 local pairs = pairs
 local type = type
 local pcall = pcall
 local print = print
-local awesome = awesome
 
 module("wibox.widget.imagebox")
 
@@ -30,7 +30,7 @@ function draw(box, wibox, cr, width, height)
 
         cr:scale(aspect, aspect)
     end
-    cr:set_source(box.image)
+    cr:set_source_surface(box.image, 0, 0)
     cr:paint()
 
     cr:restore()
@@ -74,7 +74,7 @@ function set_image(box, image)
     local image = image
 
     if type(image) == "string" then
-        local success, result = pcall(awesome.load_image, image)
+        local success, result = pcall(surface.load, image)
         if not success then
             print("Error while reading '" .. image .. "': " .. result)
             return false
@@ -82,9 +82,11 @@ function set_image(box, image)
         image = result
     end
 
+    image = surface.load(image)
+
     if image then
-        local w = image:get_width()
-        local h = image:get_height()
+        local w = image.width
+        local h = image.height
         if w <= 0 or h <= 0 then
             return false
         end
diff --git a/lib/wibox/widget/textbox.lua.in b/lib/wibox/widget/textbox.lua.in
index 49f3958..e33bd4b 100644
--- a/lib/wibox/widget/textbox.lua.in
+++ b/lib/wibox/widget/textbox.lua.in
@@ -5,50 +5,30 @@
 -- @release @AWESOME_VERSION@
 ---------------------------------------------------------------------------
 
-local oopango = require("oopango")
-local oocairo = require("oocairo")
 local base = require("wibox.widget.base")
 local beautiful = require("beautiful")
+local lgi = require("lgi")
+local cairo = lgi.cairo
+local Pango = lgi.Pango
+local PangoCairo = lgi.PangoCairo
 local type = type
 local unpack = unpack
 local setmetatable = setmetatable
 local pairs = pairs
+local error = error
 
 module("wibox.widget.textbox")
 
-local function layout_create(cr)
-    if oopango.cairo_layout_create then
-        return oopango.cairo_layout_create(cr)
-    end
-    return oopango.cairo.layout_create(cr)
-end
-
-local function layout_update(cr, layout)
-    if oopango.cairo_update_layout then
-        oopango.cairo_update_layout(cr, layout)
-    else
-        oopango.cairo.update_layout(cr, layout)
-    end
-end
-
-local function layout_show(cr, layout)
-    if oopango.cairo_show_layout then
-        oopango.cairo_show_layout(cr, layout)
-    else
-        oopango.cairo.show_layout(cr, layout)
-    end
-end
-
 -- Setup a pango layout for the given textbox and cairo context
 local function setup_layout(box, width, height)
     local layout = box._layout
-    layout:set_width(oopango.units_from_number(width))
-    layout:set_height(oopango.units_from_number(height))
+    layout.width = Pango.units_from_double(width)
+    layout.height = Pango.units_from_double(height)
 end
 
 --- Draw the given textbox on the given cairo context in the given geometry
 function draw(box, wibox, cr, width, height)
-    layout_update(cr, box._layout)
+    cr:update_layout(box._layout)
     setup_layout(box, width, height)
     local ink, logical = box._layout:get_pixel_extents()
     local offset = 0
@@ -58,7 +38,7 @@ function draw(box, wibox, cr, width, height)
         offset = height - logical.height
     end
     cr:move_to(0, offset)
-    layout_show(cr, box._layout)
+    cr:show_layout(box._layout)
 end
 
 --- Fit the given textbox
@@ -70,47 +50,37 @@ end
 
 -- Return a pango layout which can be used if no cairo context is available
 local function get_temp_layout()
-    local surface = oocairo.image_surface_create("argb32", 0, 0)
-    local cr = oocairo.context_create(surface)
-    return layout_create(cr)
-end
-
-local temp_layout
--- Test if a text is valid for a textbox. If it isn't, a lua error will be thrown.
-local function check_text(text, markup)
-    if not temp_layout then
-        temp_layout = get_temp_layout()
-    end
-
-    if markup then
-        temp_layout:set_markup(text)
-    else
-        temp_layout:set_text(text)
-    end
+    local surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
+    local cr = cairo.Context(surface)
+    return PangoCairo.create_layout(cr)
 end
 
 --- Set a textbox' text.
 -- @param text The text to set. This can contain pango markup (e.g. <b>bold</b>)
 function set_markup(box, text)
-    check_text(text, true)
-    box._layout:set_markup(text)
+    local attr, parsed = Pango.parse_markup(text, -1, 0)
+    -- In case of error, attr is false and parsed is an error message
+    if not attr then error(parsed) end
+
+    box._layout.text = parsed
+    box._layout.attributes = attr
     box:emit_signal("widget::updated")
 end
 
 --- Set a textbox' text.
 -- @param text The text to display. Pango markup is ignored and shown as-is.
 function set_text(box, text)
-    check_text(text, false)
-    box._layout:set_text(text)
+    box._layout.text = text
+    box._layout.attributes = nil
     box:emit_signal("widget::updated")
 end
 
 --- Set a textbox' ellipsize mode.
 -- @param mode Where should long lines be shortened? "start", "middle" or "end"
 function set_ellipsize(box, mode)
-    local allowed = { none = true, start = true, middle = true, ["end"] = true }
+    local allowed = { none = "NONE", start = "START", middle = "MIDDLE", ["end"] = "END" }
     if allowed[mode] then
-        box._layout:set_ellipsize(mode)
+        box._layout:set_ellipsize(allowed[mode])
         box:emit_signal("widget::updated")
     end
 end
@@ -118,9 +88,9 @@ end
 --- Set a textbox' wrap mode.
 -- @param mode Where to wrap? After "word", "char" or "word_char"
 function set_wrap(box, mode)
-    local allowed = { word = true, char = true, word_char = true }
+    local allowed = { word = "WORD", char = "CHAR", word_char = "WORD_CHAR" }
     if allowed[mode] then
-        box._layout:set_wrap(mode)
+        box._layout:set_wrap(allowed[mode])
         box:emit_signal("widget::updated")
     end
 end
@@ -138,9 +108,9 @@ end
 --- Set a textbox' horizontal alignment
 -- @param mode Where should the textbox be drawn? "left", "center" or "right"
 function set_align(box, mode)
-    local allowed = { left = true, center = true, right = true }
+    local allowed = { left = "LEFT", center = "CENTER", right = "RIGHT" }
     if allowed[mode] then
-        box._layout:set_alignment(mode)
+        box._layout:set_alignment(allowed[mode])
         box:emit_signal("widget::updated")
     end
 end
diff --git a/luaa.c b/luaa.c
index 2b61289..6fe8c1c 100644
--- a/luaa.c
+++ b/luaa.c
@@ -29,9 +29,6 @@
 
 #include <basedir_fs.h>
 
-#include <oopango.h>
-#include <oocairo.h>
-
 #include "awesome.h"
 #include "config.h"
 #include "objects/timer.h"
@@ -637,20 +634,6 @@ luaA_init(xdgHandle* xdg)
 
     lua_getfield(L, 1, "loaded");
 
-    /* Load oocairo */
-    if (luaopen_oocairo(L) != 1)
-        fatal("Loading oocairo failed");
-    lua_pushvalue(L, 3); /* Copy the module */
-    lua_setglobal(L, "oocairo"); /* Set the global entry */
-    lua_setfield(L, 2, "oocairo"); /* Make it require()able */
-
-    /* Load oopango */
-    if (luaopen_oopango(L) != 1)
-        fatal("Loading oopango failed");
-    lua_pushvalue(L, 3); /* Copy the module */
-    lua_setglobal(L, "oopango"); /* Set the global entry */
-    lua_setfield(L, 2, "oopango"); /* Make it require()able */
-
     lua_pop(L, 2); /* pop "package" and "package.loaded" */
 
     signal_add(&global_signals, "debug::error");
diff --git a/luadoc/awesome.lua b/luadoc/awesome.lua
index 2e509c9..667cb52 100644
--- a/luadoc/awesome.lua
+++ b/luadoc/awesome.lua
@@ -37,7 +37,7 @@ module("awesome")
 
 --- Load an image
 -- @param name The file name
--- @return An oocairo image surface
+-- @return A cairo image surface as light user datum
 -- @name load_image
 -- @class function
 
diff --git a/luadoc/drawin.lua b/luadoc/drawin.lua
index e8e71cb..8c527fa 100644
--- a/luadoc/drawin.lua
+++ b/luadoc/drawin.lua
@@ -15,7 +15,7 @@ module("drawin")
 -- @field y The y coordinates.
 -- @field width The width of the drawin.
 -- @field height The height of the drawin.
--- @field surface A oocairo surface that can be used for drawing.
+-- @field surface A cairo surface as light user datum that can be used for drawing.
 -- @class table
 -- @name drawin
 
diff --git a/objects/client.c b/objects/client.c
index 0bb0a51..237ce24 100644
--- a/objects/client.c
+++ b/objects/client.c
@@ -1043,17 +1043,15 @@ void
 client_set_icon(lua_State *L, int cidx, int iidx)
 {
     client_t *c = luaA_checkudata(L, cidx, &client_class);
-    if(lua_isnil(L, iidx))
+    cairo_surface_t *surf = NULL;
+    if(!lua_isnil(L, iidx))
     {
-        if(c->icon)
-            cairo_surface_destroy(c->icon);
-        c->icon = NULL;
-    } else {
-        cairo_surface_t **cairo_surface = (cairo_surface_t **)luaL_checkudata(L, iidx, OOCAIRO_MT_NAME_SURFACE);
-        if(c->icon)
-            cairo_surface_destroy(c->icon);
-        c->icon = draw_dup_image_surface(*cairo_surface);
+        cairo_surface_t **cairo_surface = (cairo_surface_t **)lua_touserdata(L, iidx);
+        surf = draw_dup_image_surface(*cairo_surface);
     }
+    if(c->icon)
+        cairo_surface_destroy(c->icon);
+    c->icon = surf;
     luaA_object_emit_signal(L, cidx < iidx ? cidx : cidx - 1, "property::icon", 0);
 }
 
@@ -1431,9 +1429,11 @@ luaA_client_get_screen(lua_State *L, client_t *c)
 static int
 luaA_client_get_icon(lua_State *L, client_t *c)
 {
-    if(c->icon)
-        return oocairo_surface_push(L, c->icon);
-    return 0;
+    if(!c->icon)
+        return 0;
+    /* lua gets its own reference which it will have to destroy */
+    lua_pushlightuserdata(L, cairo_surface_reference(c->icon));
+    return 1;
 }
 
 static int
diff --git a/objects/drawin.c b/objects/drawin.c
index 69178ff..d4770bd 100644
--- a/objects/drawin.c
+++ b/objects/drawin.c
@@ -532,7 +532,9 @@ luaA_drawin_set_visible(lua_State *L, drawin_t *drawin)
 static int
 luaA_drawin_get_surface(lua_State *L, drawin_t *drawin)
 {
-    return oocairo_surface_push(L, drawin->surface);
+    /* Lua gets its own reference which it will have to destroy */
+    lua_pushlightuserdata(L, cairo_surface_reference(drawin->surface));
+    return 1;
 }
 
 /** Refresh a drawin's content. This has to be called whenever some drawing to
diff --git a/root.c b/root.c
index c6f5704..a1aeb2b 100644
--- a/root.c
+++ b/root.c
@@ -263,7 +263,6 @@ luaA_root_wallpaper(lua_State *L)
     xcb_get_property_reply_t *prop_r;
     xcb_pixmap_t *rootpix;
     cairo_surface_t *surface;
-    int ret;
 
     prop_c = xcb_get_property_unchecked(globalconf.connection, false,
             globalconf.screen->root, _XROOTPMAP_ID, XCB_ATOM_PIXMAP, 0, 1);
@@ -282,9 +281,10 @@ luaA_root_wallpaper(lua_State *L)
      */
     surface = cairo_xcb_surface_create(globalconf.connection, *rootpix, globalconf.default_visual,
             globalconf.screen->width_in_pixels, globalconf.screen->height_in_pixels);
-    ret = oocairo_surface_push(globalconf.L, surface);
-    cairo_surface_destroy(surface);
-    return ret;
+
+    /* lua has to make sure this surface gets destroyed */
+    lua_pushlightuserdata(L, surface);
+    return 1;
 }
 
 const struct luaL_reg awesome_root_lib[] =
-- 
1.7.10

>From 68d630c32a98061a907d5ba290cd388e051c6ab2 Mon Sep 17 00:00:00 2001
From: Uli Schlachter <[email protected]>
Date: Sun, 27 May 2012 20:14:56 +0200
Subject: [PATCH 2/2] Remove a pango hack

Instead of creating unused cairo image surfaces, we create our temporary layouts
now via the (PangoCairo) font map. Way less ugly.

Signed-off-by: Uli Schlachter <[email protected]>
---
 lib/beautiful.lua.in            |    5 ++---
 lib/wibox/widget/textbox.lua.in |   12 +++---------
 2 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/lib/beautiful.lua.in b/lib/beautiful.lua.in
index 8b7ddd5..cf512fd 100644
--- a/lib/beautiful.lua.in
+++ b/lib/beautiful.lua.in
@@ -44,9 +44,8 @@ local function load_font(name)
     -- load new font
     local desc = Pango.FontDescription.from_string(name)
 
-    -- Create a temporary surface that we need for computing the size :(
-    local surface = cairo.ImageSurface(cairo.Format.ARGB32, 1, 1)
-    local layout = PangoCairo.create_layout(cairo.Context(surface))
+    local ctx = PangoCairo.font_map_get_default():create_context()
+    local layout = Pango.Layout.new(ctx)
     layout:set_font_description(desc)
 
     local width, height = layout:get_pixel_size()
diff --git a/lib/wibox/widget/textbox.lua.in b/lib/wibox/widget/textbox.lua.in
index e33bd4b..b09987f 100644
--- a/lib/wibox/widget/textbox.lua.in
+++ b/lib/wibox/widget/textbox.lua.in
@@ -48,13 +48,6 @@ function fit(box, width, height)
     return logical.width, logical.height
 end
 
--- Return a pango layout which can be used if no cairo context is available
-local function get_temp_layout()
-    local surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
-    local cr = cairo.Context(surface)
-    return PangoCairo.create_layout(cr)
-end
-
 --- Set a textbox' text.
 -- @param text The text to set. This can contain pango markup (e.g. <b>bold</b>)
 function set_markup(box, text)
@@ -131,8 +124,9 @@ local function new()
         end
     end
 
-    -- Spot the hack: Temporary surface to make pango happy
-    ret._layout = get_temp_layout()
+    local ctx = PangoCairo.font_map_get_default():create_context()
+    ret._layout = Pango.Layout.new(ctx)
+
     ret:set_ellipsize("end")
     ret:set_wrap("word_char")
     ret:set_valign("center")
-- 
1.7.10

Reply via email to