Blog-like notes

Real fullscreen with Awesome

There is no built-in method in Awesome to make a client span on all screens. In the provided “full screen” mode (Mod4-F in default configuration), a client will only occupy a single screen. I implemented a kind of “real fullscreen” mode to force a client window to occupy the whole X display, regardless of the number of actual screens

Obtain the display size

I didn’t find any way to obtain the display size (all screens combined) directly from Awesome, so I wrote a C extension to query the X server and return the width and height of the display to the Lua environment. The function is in a C module called chelpers, whose code follows:

#include <stdlib.h>
#include <lauxlib.h>   /* Lua */
#include <X11/Xlib.h>  /* X functions */

static int
l_get_display_size(lua_State *L)
{
    Display *dpy;
    int screen, width, height;

    if ( (dpy = XOpenDisplay(NULL)) == NULL )
        return 0; /* This should never happen. */

    screen = DefaultScreen(dpy);
    width  = DisplayWidth (dpy, screen);
    height = DisplayHeight(dpy, screen);

    XCloseDisplay(dpy);

    lua_pushinteger(L, width);
    lua_pushinteger(L, height);

    return 2;
}

static const struct luaL_Reg chelpers[] = {
    { “get_display_size”, l_get_display_size },
    { NULL,               NULL }
}

int
luaopen_chelpers(lua_State *L)
{
    luaL_newlib(L, chelpers);
    return 1;
}

I compiled this code into a shared library:

$ gcc -c -fPIC -o chelpers.o chelpers.c
$ gcc -shared -o chelpers.so chelpers.o -lX11

And I wrote an auxiliary Lua module chelpers.lua to easily load that shared library:

chelpers_lib = package.loadlib(“chelpers.so”, “luaopen_chelpers”)
chelpers = chelpers_lib()

return chelpers

Then a single require instruction is enough to access the C helper functions from Awesome’s configuration file:

chelpers = require(‘chelpers’)

Setting a client in “real fullscreen” mode

Now that the extension function is in place and callable from Awesome, I added the following function somewhere in Awesome’s configuration file:

function realfullscreen(c)
    awful.client.floating.set(c, true)

    local geometry = c:geometry()
    local width, height = chelpers.get_display_size()
    geometry[“x”] = 0
    geometry[“y”] = 0
    geometry[“width”] = width
    geometry[“height”] = height
    c:geometry(geometry)
end

Finally, I added the highlighted line below to bind the Mod4-G combination to that function:

clientkeys = awful.util.table.join(
    awful.key({ modkey,         }, “f”, function(c) c.fullscreen = not c.fullscreen end),
    awful.key({ modkey,         }, “g”, function(c) reallfullscreen(c) end),
    awful.key({ modkey, “Shift” }, “c”, function(c) c:kill() end),
    […]
)

That’s it. Now Mod4-G forces the current client window to span the available space on all screens.