Using Cairo within Awesome

Note
The following is only needed for Awesome 3.2.1 and earlier. The upcoming 3.3 release will contain functions to draw on images without the need of external modules. The functions are called

img:draw_pixel(x, y, color) img:draw_line(x1, y1, x2, y2, color) img:draw_rectangle(x, y, width, height, fill, color) img:draw_circle(x, y, width, height, fill, color)

x{1, 2}?, y{1, 2}?, width and height are integer values, fill is a boolean value indicating whether the drawn object should be filled and color is the color to draw and is either 3 (RGB) or 4 (RGBA) bytes long (i.e. "#FF0020" and "#FF0020BB" are valid colors). Images can be initialized like this: local img = image(nil, width, height) which returns an empty image with width and height set to the respective values.

Introduction
This guide will explain how to use Awesome3's support for Cairo to create widgets. First, you need a recent version of Awesome3, or the latest one from git. Obtain it via git clone git://git.naquadah.org/awesome then compile and install it.

After installing the latest version of Awesome3, you need to get oocairo, which is a library containing Lua bindings to Cairo. Grab it from http://luaforge.net/frs/download.php/3884/lua-oocairo-1.2.tar.gz

Before compiling, you may need to edit the Makefile (Other patches from arch linux AUR)

LIBTOOL := libtool --quiet

to

LIBTOOL := libtool --quiet --tag CC

Integrating oocairo with Awesome3
Integrating oocairo with Awesome3 is pretty straightforward. Just include oocairo into your widget module rc.lua like this:

Cairo = require "oocairo"

For your widget, you first need to create an imagebox to hold your widgets image. Then use oocairo to create an image surface which has its color-mode set to "argb32" like this:

cs = Cairo.image_surface_create("argb32", w, h)

Then you need a graphics context, which can be created from the image surface as follows:

cr = Cairo.context_create(cs)

Now draw onto that surface as you please. The drawing functions for oocairo are the same as for using Cairo with C/C++, except their first parameter, the graphics context, gets discarded and the functions are called as methods of the context like this:

cr:new_path cr:move_to(10, 10) cr:line_to(40, 40) cr:set_source_rgb(0, 0, 0) cr:set_line_width(3) cr:stroke

The above code will draw a 3 pixel wide line from (10, 10) to (40, 40) on the drawing context cr.

When you are done drawing, it's time to transfer the content of your image surface to the imagebox. This works by calling the function image.argb32(w, h, sd), which returns a valid image for imageboxes. The code looks similar to this:

ib.image = image.argb32(w, h, cs:get_data)

That is basically all.

Please note that for widgets which update regularly, it is most of the time easier and faster to not create a new drawing context for each redrawing step but to clear the context with the following code which will reset the color of a w x h pixel drawing context to white:

cr:new_sub_path cr:move_to(0, 0) cr:line_to(w, 0) cr:line_to(w, h) cr:line_to(0, h)  cr:close_path cr:set_source_rgb(1, 1, 1) cr:fill