build: fix theme installation (FS#263)
[awesome.git] / lua.c
blobb00acd202a0c2aac4886bebf4b6dd31f26dfe183
1 /*
2 * lua.c - Lua configuration management
4 * Copyright © 2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <errno.h>
23 #include <stdio.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <unistd.h>
28 #include <ev.h>
30 #include <lua.h>
31 #include <lauxlib.h>
32 #include <lualib.h>
34 #include <xcb/xcb.h>
35 #include <xcb/xcb_aux.h>
37 #include "awesome-version-internal.h"
38 #include "ewmh.h"
39 #include "config.h"
40 #include "lua.h"
41 #include "tag.h"
42 #include "client.h"
43 #include "statusbar.h"
44 #include "titlebar.h"
45 #include "screen.h"
46 #include "layouts/tile.h"
47 #include "common/socket.h"
49 extern awesome_t globalconf;
51 extern const struct luaL_reg awesome_keygrabber_lib[];
52 extern const struct luaL_reg awesome_mouse_methods[];
53 extern const struct luaL_reg awesome_mouse_meta[];
54 extern const struct luaL_reg awesome_screen_methods[];
55 extern const struct luaL_reg awesome_screen_meta[];
56 extern const struct luaL_reg awesome_client_methods[];
57 extern const struct luaL_reg awesome_client_meta[];
58 extern const struct luaL_reg awesome_titlebar_methods[];
59 extern const struct luaL_reg awesome_titlebar_meta[];
60 extern const struct luaL_reg awesome_tag_methods[];
61 extern const struct luaL_reg awesome_tag_meta[];
62 extern const struct luaL_reg awesome_widget_methods[];
63 extern const struct luaL_reg awesome_widget_meta[];
64 extern const struct luaL_reg awesome_statusbar_methods[];
65 extern const struct luaL_reg awesome_statusbar_meta[];
66 extern const struct luaL_reg awesome_keybinding_methods[];
67 extern const struct luaL_reg awesome_keybinding_meta[];
69 static struct sockaddr_un *addr;
70 static ev_io csio = { .fd = -1 };
72 /** Add a global mouse binding. This binding will be available when you'll
73 * click on root window.
74 * \param L The Lua VM state.
76 * \luastack
77 * \lparam A mouse button binding.
79 static int
80 luaA_mouse_add(lua_State *L)
82 button_t **button = luaA_checkudata(L, 1, "mouse");
84 button_list_push(&globalconf.buttons.root, *button);
85 button_ref(button);
87 return 0;
90 /** Quit awesome.
92 static int
93 luaA_quit(lua_State *L __attribute__ ((unused)))
95 ev_unloop(globalconf.loop, 1);
96 return 0;
99 /** Execute another application, probably a window manager, to replace
100 * awesome.
101 * \param L The Lua VM state.
103 * \luastack
104 * \lparam The command line to execute.
106 static int
107 luaA_exec(lua_State *L)
109 client_t *c;
110 const char *cmd = luaL_checkstring(L, 1);
112 for(c = globalconf.clients; c; c = c->next)
113 client_unban(c);
115 xcb_aux_sync(globalconf.connection);
116 xcb_disconnect(globalconf.connection);
118 a_exec(cmd);
119 return 0;
122 /** Restart awesome.
124 static int
125 luaA_restart(lua_State *L __attribute__ ((unused)))
127 ewmh_restart();
128 return 0;
131 /** Set the function called each time a client gets focus. This function is
132 * called with the client object as argument.
133 * \param L The Lua VM state.
134 * \return The number of elements pushed on stack.
136 * \luastack
137 * \lparam A function to call each time a client gets focus.
139 static int
140 luaA_hooks_focus(lua_State *L)
142 return luaA_registerfct(L, &globalconf.hooks.focus);
145 /** Set the function called each time a client loses focus. This function is
146 * called with the client object as argument.
147 * \param L The Lua VM state.
149 * \luastack
150 * \lparam A function to call each time a client loses focus.
152 static int
153 luaA_hooks_unfocus(lua_State *L)
155 return luaA_registerfct(L, &globalconf.hooks.unfocus);
158 /** Set the function called each time a new client appears. This function is
159 * called with the client object as argument.
160 * \param L The Lua VM state.
162 * \luastack
163 * \lparam A function to call on each new client.
165 static int
166 luaA_hooks_manage(lua_State *L)
168 return luaA_registerfct(L, &globalconf.hooks.manage);
171 /** Set the function called each time a client goes away. This function is
172 * called with the client object as argument.
173 * \param L The Lua VM state.
175 * \luastack
176 * \lparam A function to call when a client goes away.
178 static int
179 luaA_hooks_unmanage(lua_State *L)
181 return luaA_registerfct(L, &globalconf.hooks.unmanage);
184 /** Set the function called each time the mouse enter a new window. This
185 * function is called with the client object as argument.
186 * \param L The Lua VM state.
188 * \luastack
189 * \lparam A function to call each time a client gets mouse over it.
191 static int
192 luaA_hooks_mouseover(lua_State *L)
194 return luaA_registerfct(L, &globalconf.hooks.mouseover);
197 /** Set the function called on each screen arrange. This function is called
198 * with the screen number as argument.
199 * \param L The Lua VM state.
201 * \luastack
202 * \lparam A function to call on each screen arrange.
204 static int
205 luaA_hooks_arrange(lua_State *L)
207 return luaA_registerfct(L, &globalconf.hooks.arrange);
210 /** Set the function called on each title update. This function is called with
211 * the client object as argument.
212 * \param L The Lua VM state.
214 * \luastack
215 * \lparam A function to call on each title update of each client.
217 static int
218 luaA_hooks_titleupdate(lua_State *L)
220 return luaA_registerfct(L, &globalconf.hooks.titleupdate);
223 /** Set the function called when a client get urgency flag. This function is called with
224 * the client object as argument.
225 * \param L The Lua VM state.
227 * \luastack
228 * \lparam A function to call when a client get the urgent flag.
230 static int
231 luaA_hooks_urgent(lua_State *L)
233 return luaA_registerfct(L, &globalconf.hooks.urgent);
236 /** Set the function to be called every N seconds.
237 * \param L The Lua VM state.
239 * \luastack
240 * \lparam The number of seconds to run function every. Set 0 to disable.
241 * \lparam A function to call every N seconds (optional).
243 static int
244 luaA_hooks_timer(lua_State *L)
246 globalconf.timer.repeat = luaL_checknumber(L, 1);
248 if(lua_gettop(L) == 2 && !lua_isnil(L, 2))
249 luaA_registerfct(L, &globalconf.hooks.timer);
251 ev_timer_again(globalconf.loop, &globalconf.timer);
252 return 0;
255 /** Set default font.
256 * \param L The Lua VM state.
258 * \luastack
259 * \lparam A string with a font name in Pango format.
261 static int
262 luaA_font_set(lua_State *L)
264 const char *font = luaL_checkstring(L, 1);
265 draw_font_delete(&globalconf.font);
266 globalconf.font = draw_font_new(globalconf.connection,
267 globalconf.default_screen, font);
268 return 0;
271 /** Set default colors.
272 * \param L The Lua VM state.
274 * \luastack
275 * \lparam A table with `fg' and `bg' elements, containing colors.
277 static int
278 luaA_colors_set(lua_State *L)
280 const char *buf;
281 size_t len;
282 int8_t colors_nbr = -1, i;
283 xcolor_init_request_t reqs[2];
285 luaA_checktable(L, 1);
287 if((buf = luaA_getopt_lstring(L, 1, "fg", NULL, &len)))
288 reqs[++colors_nbr] = xcolor_init_unchecked(globalconf.connection,
289 &globalconf.colors.fg,
290 globalconf.default_screen,
291 buf, len);
293 if((buf = luaA_getopt_lstring(L, 1, "bg", NULL, &len)))
294 reqs[++colors_nbr] = xcolor_init_unchecked(globalconf.connection,
295 &globalconf.colors.bg,
296 globalconf.default_screen,
297 buf, len);
299 for(i = 0; i <= colors_nbr; i++)
300 xcolor_init_reply(globalconf.connection, reqs[i]);
302 return 0;
305 /** Push a pointer onto the stack according to its type.
306 * \param p The pointer.
307 * \param type Its type.
309 void
310 luaA_pushpointer(lua_State *L, void *p, awesome_type_t type)
312 switch(type)
314 case AWESOME_TYPE_STATUSBAR:
315 luaA_statusbar_userdata_new(L, p);
316 break;
317 case AWESOME_TYPE_TITLEBAR:
318 luaA_titlebar_userdata_new(L, p);
319 break;
323 static void
324 luaA_openlib(lua_State *L, const char *name,
325 const struct luaL_reg methods[],
326 const struct luaL_reg meta[])
328 luaL_newmetatable(L, name); /* 1 */
329 lua_pushvalue(L, -1); /* dup metatable 2 */
330 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable 1 */
332 luaL_register(L, NULL, meta); /* 1 */
333 luaL_register(L, name, methods); /* 2 */
334 lua_pushvalue(L, -1); /* dup self as metatable 3 */
335 lua_setmetatable(L, -2); /* set self as metatable 2 */
336 lua_pop(L, 2);
339 static int
340 luaA_mbstrlen(lua_State *L)
342 const char *cmd = luaL_checkstring(L, 1);
343 lua_pushnumber(L, mbstowcs(NULL, NONULL(cmd), 0));
344 return 1;
347 static int
348 luaA_next(lua_State *L)
350 if(luaL_getmetafield(L, 1, "__next"))
352 lua_insert(L, 1);
353 lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
354 return lua_gettop(L);
357 luaL_checktype(L, 1, LUA_TTABLE);
358 lua_settop(L, 2);
359 if(lua_next(L, 1))
360 return 2;
361 lua_pushnil(L);
362 return 1;
365 static int
366 luaA_pairs(lua_State *L)
368 if(luaL_getmetafield(L, 1, "__pairs"))
370 lua_insert(L, 1);
371 lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
372 return lua_gettop(L);
375 luaL_checktype(L, 1, LUA_TTABLE);
376 return luaA_generic_pairs(L);
379 static void
380 luaA_fixups(lua_State *L)
382 lua_getglobal(L, "string");
383 lua_pushcfunction(L, luaA_mbstrlen);
384 lua_setfield(L, -2, "len");
385 lua_pop(L, 1);
386 lua_pushliteral(L, "next");
387 lua_pushcfunction(L, luaA_next);
388 lua_settable(L, LUA_GLOBALSINDEX);
389 lua_pushliteral(L, "pairs");
390 lua_pushcfunction(L, luaA_next);
391 lua_pushcclosure(L, luaA_pairs, 1); /* pairs get next as upvalue */
392 lua_settable(L, LUA_GLOBALSINDEX);
395 /** Object table.
396 * This table can use safely object as key.
397 * \param L The Lua VM state.
398 * \return The number of elements pushed on stack.
401 luaA_otable_index(lua_State *L)
403 void **obj, **v;
405 if((obj = lua_touserdata(L, 2)))
407 /* begins at nil */
408 lua_pushnil(L);
409 while(lua_next(L, 1))
411 if((v = lua_touserdata(L, -2))
412 && *v == *obj)
413 return 1;
414 /* removes 'value'; keeps 'key' for next iteration */
415 lua_pop(L, 1);
417 return 0;
420 lua_rawget(L, 1);
421 return 1;
424 /** Object table.
425 * This table can use safely object as key.
426 * \param L The Lua VM state.
427 * \return The number of elements pushed on stack.
429 static int
430 luaA_otable_newindex(lua_State *L)
432 void **obj, **v;
434 if((obj = lua_touserdata(L, 2)))
436 /* begins at nil */
437 lua_pushnil(L);
438 while(lua_next(L, 1))
440 if((v = lua_touserdata(L, -2))
441 && *v == *obj)
443 /* remove value */
444 lua_pop(L, 1);
445 /* push new value on top */
446 lua_pushvalue(L, 3);
447 /* set in table key = value */
448 lua_rawset(L, 1);
449 return 0;
451 /* removes 'value'; keeps 'key' for next iteration */
452 lua_pop(L, 1);
456 lua_rawset(L, 1);
457 return 0;
460 /** Initialize the Lua VM
462 void
463 luaA_init(void)
465 lua_State *L;
467 static const struct luaL_reg otable_methods[] =
469 { "__call", luaA_otable_new },
470 { NULL, NULL }
472 static const struct luaL_reg otable_meta[] =
474 { "__index", luaA_otable_index },
475 { "__newindex", luaA_otable_newindex },
476 { NULL, NULL }
478 static const struct luaL_reg awesome_lib[] =
480 { "quit", luaA_quit },
481 { "exec", luaA_exec },
482 { "restart", luaA_restart },
483 { "mouse_add", luaA_mouse_add },
484 { "font_set", luaA_font_set },
485 { "colors_set", luaA_colors_set },
486 { NULL, NULL }
488 static const struct luaL_reg awesome_hooks_lib[] =
490 { "focus", luaA_hooks_focus },
491 { "unfocus", luaA_hooks_unfocus },
492 { "manage", luaA_hooks_manage },
493 { "unmanage", luaA_hooks_unmanage },
494 { "mouseover", luaA_hooks_mouseover },
495 { "arrange", luaA_hooks_arrange },
496 { "titleupdate", luaA_hooks_titleupdate },
497 { "urgent", luaA_hooks_urgent },
498 { "timer", luaA_hooks_timer },
499 { NULL, NULL }
502 L = globalconf.L = luaL_newstate();
504 luaL_openlibs(L);
506 luaA_fixups(L);
508 /* Export awesome lib */
509 luaL_register(L, "awesome", awesome_lib);
511 /* Export hooks lib */
512 luaL_register(L, "hooks", awesome_hooks_lib);
514 /* Export keygrabber lib */
515 luaL_register(L, "keygrabber", awesome_keygrabber_lib);
517 /* Export otable lib */
518 luaA_openlib(L, "otable", otable_methods, otable_meta);
520 /* Export screen */
521 luaA_openlib(L, "screen", awesome_screen_methods, awesome_screen_meta);
523 /* Export mouse */
524 luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta);
526 /* Export tag */
527 luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta);
529 /* Export statusbar */
530 luaA_openlib(L, "statusbar", awesome_statusbar_methods, awesome_statusbar_meta);
532 /* Export widget */
533 luaA_openlib(L, "widget", awesome_widget_methods, awesome_widget_meta);
535 /* Export client */
536 luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta);
538 /* Export titlebar */
539 luaA_openlib(L, "titlebar", awesome_titlebar_methods, awesome_titlebar_meta);
541 /* Export keys */
542 luaA_openlib(L, "keybinding", awesome_keybinding_methods, awesome_keybinding_meta);
544 lua_pushliteral(L, "AWESOME_VERSION");
545 lua_pushstring(L, AWESOME_VERSION);
546 lua_settable(L, LUA_GLOBALSINDEX);
548 luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?.lua\"");
549 luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?/init.lua\"");
551 /* init hooks */
552 globalconf.hooks.manage = LUA_REFNIL;
553 globalconf.hooks.unmanage = LUA_REFNIL;
554 globalconf.hooks.focus = LUA_REFNIL;
555 globalconf.hooks.unfocus = LUA_REFNIL;
556 globalconf.hooks.mouseover = LUA_REFNIL;
557 globalconf.hooks.arrange = LUA_REFNIL;
558 globalconf.hooks.titleupdate = LUA_REFNIL;
559 globalconf.hooks.urgent = LUA_REFNIL;
560 globalconf.hooks.timer = LUA_REFNIL;
563 #define XDG_CONFIG_HOME_DEFAULT "/.config"
565 #define AWESOME_CONFIG_FILE "/awesome/rc.lua"
567 /** Load a configuration file.
568 * \param rcfile The configuration file to load.
570 void
571 luaA_parserc(const char *confpatharg)
573 int screen;
574 const char *confdir, *xdg_config_dirs;
575 char *confpath = NULL, **xdg_files, **buf, path[1024];
576 ssize_t len;
578 if(confpatharg)
580 if(luaL_dofile(globalconf.L, confpatharg))
581 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
582 else
583 goto bailout;
586 confdir = getenv("XDG_CONFIG_HOME");
588 if((len = a_strlen(confdir)))
590 len += sizeof(AWESOME_CONFIG_FILE);
591 confpath = p_new(char, len);
592 a_strcpy(confpath, len, confdir);
593 /* update package.path */
594 snprintf(path, sizeof(path) - 1, "package.path = package.path .. \";%s/awesome/?.lua\"", confdir);
595 luaA_dostring(globalconf.L, path);
597 else
599 confdir = getenv("HOME");
600 len = a_strlen(confdir) + sizeof(AWESOME_CONFIG_FILE)-1 + sizeof(XDG_CONFIG_HOME_DEFAULT);
601 confpath = p_new(char, len);
602 a_strcpy(confpath, len, confdir);
603 a_strcat(confpath, len, XDG_CONFIG_HOME_DEFAULT);
604 /* update package.path */
605 snprintf(path, sizeof(path) - 1, "package.path = package.path .. \";%s" XDG_CONFIG_HOME_DEFAULT "/awesome/?.lua\"", confdir);
606 luaA_dostring(globalconf.L, path);
608 a_strcat(confpath, len, AWESOME_CONFIG_FILE);
610 if(luaL_dofile(globalconf.L, confpath))
611 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
612 else
613 goto bailout;
615 xdg_config_dirs = getenv("XDG_CONFIG_DIRS");
617 if(!(len = a_strlen(xdg_config_dirs)))
619 xdg_config_dirs = XDG_CONFIG_DIR;
620 len = sizeof(XDG_CONFIG_DIR) - 1;
623 xdg_files = a_strsplit(xdg_config_dirs, len, ':');
625 for(buf = xdg_files; *buf; buf++)
627 p_delete(&confpath);
628 len = a_strlen(*buf) + sizeof("AWESOME_CONFIG_FILE");
629 confpath = p_new(char, len);
630 a_strcpy(confpath, len, *buf);
631 a_strcat(confpath, len, AWESOME_CONFIG_FILE);
632 snprintf(path, sizeof(path) - 1, "package.path = package.path .. \";%s/awesome/?.lua\"", *buf);
633 luaA_dostring(globalconf.L, path);
634 if(luaL_dofile(globalconf.L, confpath))
635 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
636 else
637 break;
640 for(buf = xdg_files; *buf; buf++)
641 p_delete(buf);
642 p_delete(&xdg_files);
644 bailout:
645 /* Assure there's at least one tag */
646 for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
647 if(!globalconf.screens[screen].tags.len)
648 tag_append_to_screen(tag_new("default", sizeof("default")-1, layout_tile, 0.5, 1, 0), screen);
650 p_delete(&confpath);
653 /** Parse a command.
654 * \param cmd The buffer to parse.
655 * \return true on succes, false on failure.
657 static void
658 luaA_docmd(const char *cmd)
660 char *p;
662 while((p = strchr(cmd, '\n')))
664 *p = '\0';
665 luaA_dostring(globalconf.L, cmd);
666 cmd = p + 1;
670 static void
671 luaA_cb(EV_P_ ev_io *w, int revents)
673 char buf[1024];
674 int r;
676 switch(r = recv(w->fd, buf, sizeof(buf)-1, MSG_TRUNC))
678 case -1:
679 warn("error reading UNIX domain socket: %s", strerror(errno));
680 luaA_cs_cleanup();
681 break;
682 case 0:
683 break;
684 default:
685 if(r >= ssizeof(buf))
686 break;
687 buf[r] = '\0';
688 luaA_docmd(buf);
690 layout_refresh();
691 statusbar_refresh();
692 titlebar_refresh();
695 void
696 luaA_cs_init(void)
698 int csfd = socket_getclient();
700 if (csfd < 0)
701 return;
702 addr = socket_getaddr(getenv("DISPLAY"));
704 if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
706 if(errno == EADDRINUSE)
708 if(unlink(addr->sun_path))
709 warn("error unlinking existing file: %s", strerror(errno));
710 if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
711 warn("error binding UNIX domain socket: %s", strerror(errno));
713 else
714 warn("error binding UNIX domain socket: %s", strerror(errno));
716 ev_io_init(&csio, &luaA_cb, csfd, EV_READ);
717 ev_io_start(EV_DEFAULT_UC_ &csio);
718 ev_unref(EV_DEFAULT_UC);
721 void
722 luaA_cs_cleanup(void)
724 if(csio.fd < 0)
725 return;
726 ev_ref(EV_DEFAULT_UC);
727 ev_io_stop(EV_DEFAULT_UC_ &csio);
728 if (close(csio.fd))
729 warn("error closing UNIX domain socket: %s", strerror(errno));
730 if(unlink(addr->sun_path))
731 warn("error unlinking UNIX domain socket: %s", strerror(errno));
732 p_delete(&addr);
733 csio.fd = -1;
736 void
737 luaA_on_timer(EV_P_ ev_timer *w, int revents)
739 luaA_dofunction(globalconf.L, globalconf.hooks.timer, 0, 0);
740 layout_refresh();
741 statusbar_refresh();
742 titlebar_refresh();
745 void
746 luaA_pushcolor(lua_State *L, const xcolor_t *c)
748 uint8_t r = (unsigned)c->red * 0xff / 0xffff;
749 uint8_t g = (unsigned)c->green * 0xff / 0xffff;
750 uint8_t b = (unsigned)c->blue * 0xff / 0xffff;
751 uint8_t a = (unsigned)c->alpha * 0xff / 0xffff;
752 char s[10];
753 snprintf(s, sizeof(s), "#%02x%02x%02x%02x", r, g, b, a);
754 lua_pushlstring(L, s, sizeof(s));