build: any target need cmake first
[awesome.git] / lua.c
blob3ebf5a23f0b7e503872cf9027408de9bdb1df53b
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_client_methods[];
55 extern const struct luaL_reg awesome_client_meta[];
56 extern const struct luaL_reg awesome_titlebar_methods[];
57 extern const struct luaL_reg awesome_titlebar_meta[];
58 extern const struct luaL_reg awesome_tag_methods[];
59 extern const struct luaL_reg awesome_tag_meta[];
60 extern const struct luaL_reg awesome_widget_methods[];
61 extern const struct luaL_reg awesome_widget_meta[];
62 extern const struct luaL_reg awesome_statusbar_methods[];
63 extern const struct luaL_reg awesome_statusbar_meta[];
64 extern const struct luaL_reg awesome_keybinding_methods[];
65 extern const struct luaL_reg awesome_keybinding_meta[];
67 static struct sockaddr_un *addr;
68 static ev_io csio = { .fd = -1 };
70 /** Add a global mouse binding. This binding will be available when you'll
71 * click on root window.
72 * \param L The Lua VM state.
74 * \luastack
75 * \lparam A mouse button binding.
77 static int
78 luaA_mouse_add(lua_State *L)
80 button_t **button = luaA_checkudata(L, 1, "mouse");
82 button_list_push(&globalconf.buttons.root, *button);
83 button_ref(button);
85 return 0;
88 /** Quit awesome.
90 static int
91 luaA_quit(lua_State *L __attribute__ ((unused)))
93 ev_unloop(globalconf.loop, 1);
94 return 0;
97 /** Execute another application, probably a window manager, to replace
98 * awesome.
99 * \param L The Lua VM state.
101 * \luastack
102 * \lparam The command line to execute.
104 static int
105 luaA_exec(lua_State *L)
107 client_t *c;
108 const char *cmd = luaL_checkstring(L, 1);
110 for(c = globalconf.clients; c; c = c->next)
111 client_unban(c);
113 xcb_aux_sync(globalconf.connection);
114 xcb_disconnect(globalconf.connection);
116 a_exec(cmd);
117 return 0;
120 /** Restart awesome.
122 static int
123 luaA_restart(lua_State *L __attribute__ ((unused)))
125 ewmh_restart();
126 return 0;
129 /** Set the screen padding. This can be used to define margin around the
130 * screen. awesome will not use this area.
131 * \param L The Lua VM state.
132 * \return The number of elements pushed on stack.
134 * \luastack
135 * \lparam A screen number.
136 * \lparam A table with a list of margin for `right', `left', `top' and
137 * `bottom'.
139 static int
140 luaA_screen_padding_set(lua_State *L)
142 int screen = luaL_checknumber(L, 1) - 1;
144 luaA_checkscreen(screen);
146 luaA_checktable(L, 2);
148 globalconf.screens[screen].padding.right = luaA_getopt_number(L, 2, "right", 0);
149 globalconf.screens[screen].padding.left = luaA_getopt_number(L, 2, "left", 0);
150 globalconf.screens[screen].padding.top = luaA_getopt_number(L, 2, "top", 0);
151 globalconf.screens[screen].padding.bottom = luaA_getopt_number(L, 2, "bottom", 0);
153 ewmh_update_workarea(screen_virttophys(screen));
155 return 0;
158 /** Get the screen count.
159 * \param L The Lua VM state.
160 * \return The number of elements pushed on stack.
162 * \luastack
163 * \lreturn The screen count, at least 1.
165 static int
166 luaA_screen_count(lua_State *L)
168 lua_pushnumber(L, globalconf.screens_info->nscreen);
169 return 1;
172 /** Return screen coordinates.
173 * \param L The Lua VM state.
174 * \return The number of elements pushed on stack.
175 * \luastack
176 * \lparam A screen number.
177 * \lreturn A table with the screen geometry: x, y, width and height.
179 static int
180 luaA_screen_coords_get(lua_State *L)
182 int screen = luaL_checknumber(L, 1) - 1;
183 luaA_checkscreen(screen);
184 lua_newtable(L);
185 lua_pushnumber(L, globalconf.screens_info->geometry[screen].x);
186 lua_setfield(L, -2, "x");
187 lua_pushnumber(L, globalconf.screens_info->geometry[screen].y);
188 lua_setfield(L, -2, "y");
189 lua_pushnumber(L, globalconf.screens_info->geometry[screen].width);
190 lua_setfield(L, -2, "width");
191 lua_pushnumber(L, globalconf.screens_info->geometry[screen].height);
192 lua_setfield(L, -2, "height");
193 return 1;
196 /** Return the geometry of the workspace, i.e. where applications live.
197 * \param L The Lua VM state.
198 * \return The number of elements pushed on stack.
199 * \luastack
200 * \lparam A screen number.
201 * \lreturn A table with the workspace geometry.
203 static int
204 luaA_screen_workspace_get(lua_State *L)
206 area_t g;
207 int screen = luaL_checknumber(L, 1) - 1;
208 luaA_checkscreen(screen);
209 g = screen_area_get(screen,
210 globalconf.screens[screen].statusbar,
211 &globalconf.screens[screen].padding);
212 lua_newtable(L);
213 lua_pushnumber(L, g.x);
214 lua_setfield(L, -2, "x");
215 lua_pushnumber(L, g.y);
216 lua_setfield(L, -2, "y");
217 lua_pushnumber(L, g.width);
218 lua_setfield(L, -2, "width");
219 lua_pushnumber(L, g.height);
220 lua_setfield(L, -2, "height");
221 return 1;
224 /** Set the function called each time a client gets focus. This function is
225 * called with the client object as argument.
226 * \param L The Lua VM state.
227 * \return The number of elements pushed on stack.
229 * \luastack
230 * \lparam A function to call each time a client gets focus.
232 static int
233 luaA_hooks_focus(lua_State *L)
235 return luaA_registerfct(L, &globalconf.hooks.focus);
238 /** Set the function called each time a client loses focus. This function is
239 * called with the client object as argument.
240 * \param L The Lua VM state.
242 * \luastack
243 * \lparam A function to call each time a client loses focus.
245 static int
246 luaA_hooks_unfocus(lua_State *L)
248 return luaA_registerfct(L, &globalconf.hooks.unfocus);
251 /** Set the function called each time a new client appears. This function is
252 * called with the client object as argument.
253 * \param L The Lua VM state.
255 * \luastack
256 * \lparam A function to call on each new client.
258 static int
259 luaA_hooks_manage(lua_State *L)
261 return luaA_registerfct(L, &globalconf.hooks.manage);
264 /** Set the function called each time a client goes away. This function is
265 * called with the client object as argument.
266 * \param L The Lua VM state.
268 * \luastack
269 * \lparam A function to call when a client goes away.
271 static int
272 luaA_hooks_unmanage(lua_State *L)
274 return luaA_registerfct(L, &globalconf.hooks.unmanage);
277 /** Set the function called each time the mouse enter a new window. This
278 * function is called with the client object as argument.
279 * \param L The Lua VM state.
281 * \luastack
282 * \lparam A function to call each time a client gets mouse over it.
284 static int
285 luaA_hooks_mouseover(lua_State *L)
287 return luaA_registerfct(L, &globalconf.hooks.mouseover);
290 /** Set the function called on each screen arrange. This function is called
291 * with the screen number as argument.
292 * \param L The Lua VM state.
294 * \luastack
295 * \lparam A function to call on each screen arrange.
297 static int
298 luaA_hooks_arrange(lua_State *L)
300 return luaA_registerfct(L, &globalconf.hooks.arrange);
303 /** Set the function called on each title update. This function is called with
304 * the client object as argument.
305 * \param L The Lua VM state.
307 * \luastack
308 * \lparam A function to call on each title update of each client.
310 static int
311 luaA_hooks_titleupdate(lua_State *L)
313 return luaA_registerfct(L, &globalconf.hooks.titleupdate);
316 /** Set the function called when a client get urgency flag. This function is called with
317 * the client object as argument.
318 * \param L The Lua VM state.
320 * \luastack
321 * \lparam A function to call when a client get the urgent flag.
323 static int
324 luaA_hooks_urgent(lua_State *L)
326 return luaA_registerfct(L, &globalconf.hooks.urgent);
329 /** Set the function to be called every N seconds.
330 * \param L The Lua VM state.
332 * \luastack
333 * \lparam The number of seconds to run function every. Set 0 to disable.
334 * \lparam A function to call every N seconds (optional).
336 static int
337 luaA_hooks_timer(lua_State *L)
339 globalconf.timer.repeat = luaL_checknumber(L, 1);
341 if(lua_gettop(L) == 2 && !lua_isnil(L, 2))
342 luaA_registerfct(L, &globalconf.hooks.timer);
344 ev_timer_again(globalconf.loop, &globalconf.timer);
345 return 0;
348 /** Set default font.
349 * \param L The Lua VM state.
351 * \luastack
352 * \lparam A string with a font name in Pango format.
354 static int
355 luaA_font_set(lua_State *L)
357 const char *font = luaL_checkstring(L, 1);
358 draw_font_delete(&globalconf.font);
359 globalconf.font = draw_font_new(globalconf.connection,
360 globalconf.default_screen, font);
361 return 0;
364 /** Set default colors.
365 * \param L The Lua VM state.
367 * \luastack
368 * \lparam A table with `fg' and `bg' elements, containing colors.
370 static int
371 luaA_colors_set(lua_State *L)
373 const char *buf;
374 size_t len;
376 luaA_checktable(L, 1);
378 if((buf = luaA_getopt_lstring(L, 1, "fg", NULL, &len)))
379 xcolor_init(&globalconf.colors.fg, globalconf.connection,
380 globalconf.default_screen, buf, len);
382 if((buf = luaA_getopt_lstring(L, 1, "bg", NULL, &len)))
383 xcolor_init(&globalconf.colors.bg, globalconf.connection,
384 globalconf.default_screen, buf, len);
385 return 0;
388 /** Push a pointer onto the stack according to its type.
389 * \param p The pointer.
390 * \param type Its type.
392 void
393 luaA_pushpointer(lua_State *L, void *p, awesome_type_t type)
395 switch(type)
397 case AWESOME_TYPE_STATUSBAR:
398 luaA_statusbar_userdata_new(L, p);
399 break;
400 case AWESOME_TYPE_TITLEBAR:
401 luaA_titlebar_userdata_new(L, p);
402 break;
406 static void
407 luaA_openlib(lua_State *L, const char *name,
408 const struct luaL_reg methods[],
409 const struct luaL_reg meta[])
411 luaL_newmetatable(L, name); /* 1 */
412 lua_pushvalue(L, -1); /* dup metatable 2 */
413 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable 1 */
415 luaL_register(L, NULL, meta); /* 1 */
416 luaL_register(L, name, methods); /* 2 */
417 lua_pushvalue(L, -1); /* dup self as metatable 3 */
418 lua_setmetatable(L, -2); /* set self as metatable 2 */
419 lua_pop(L, 2);
422 static int
423 luaA_mbstrlen(lua_State *L)
425 const char *cmd = luaL_checkstring(L, 1);
426 lua_pushnumber(L, mbstowcs(NULL, NONULL(cmd), 0));
427 return 1;
430 static void
431 luaA_fixups(lua_State *L)
433 lua_getglobal(L, "string");
434 lua_pushcfunction(L, luaA_mbstrlen);
435 lua_setfield(L, -2, "len");
436 lua_pop(L, 1);
439 /** Initialize the Lua VM
441 void
442 luaA_init(void)
444 lua_State *L;
446 static const struct luaL_reg awesome_lib[] =
448 { "quit", luaA_quit },
449 { "exec", luaA_exec },
450 { "restart", luaA_restart },
451 { "mouse_add", luaA_mouse_add },
452 { "font_set", luaA_font_set },
453 { "colors_set", luaA_colors_set },
454 { NULL, NULL }
456 static const struct luaL_reg awesome_screen_lib[] =
458 { "padding_set", luaA_screen_padding_set },
459 { "coords_get", luaA_screen_coords_get },
460 { "workspace_get", luaA_screen_workspace_get },
461 { "count", luaA_screen_count },
462 { NULL, NULL }
464 static const struct luaL_reg awesome_hooks_lib[] =
466 { "focus", luaA_hooks_focus },
467 { "unfocus", luaA_hooks_unfocus },
468 { "manage", luaA_hooks_manage },
469 { "unmanage", luaA_hooks_unmanage },
470 { "mouseover", luaA_hooks_mouseover },
471 { "arrange", luaA_hooks_arrange },
472 { "titleupdate", luaA_hooks_titleupdate },
473 { "urgent", luaA_hooks_urgent },
474 { "timer", luaA_hooks_timer },
475 { NULL, NULL }
478 L = globalconf.L = luaL_newstate();
480 luaL_openlibs(L);
482 luaA_fixups(L);
484 /* Export awesome lib */
485 luaL_register(L, "awesome", awesome_lib);
487 /* Export screen lib */
488 luaL_register(L, "screen", awesome_screen_lib);
490 /* Export hooks lib */
491 luaL_register(L, "hooks", awesome_hooks_lib);
493 /* Export keygrabber lib */
494 luaL_register(L, "keygrabber", awesome_keygrabber_lib);
496 /* Export mouse */
497 luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta);
499 /* Export tag */
500 luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta);
502 /* Export statusbar */
503 luaA_openlib(L, "statusbar", awesome_statusbar_methods, awesome_statusbar_meta);
505 /* Export widget */
506 luaA_openlib(L, "widget", awesome_widget_methods, awesome_widget_meta);
508 /* Export client */
509 luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta);
511 /* Export titlebar */
512 luaA_openlib(L, "titlebar", awesome_titlebar_methods, awesome_titlebar_meta);
514 /* Export keys */
515 luaA_openlib(L, "keybinding", awesome_keybinding_methods, awesome_keybinding_meta);
517 lua_pushliteral(L, "AWESOME_VERSION");
518 lua_pushstring(L, AWESOME_VERSION);
519 lua_settable(L, LUA_GLOBALSINDEX);
521 luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?.lua\"");
522 luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?/init.lua\"");
524 /* init hooks */
525 globalconf.hooks.manage = LUA_REFNIL;
526 globalconf.hooks.unmanage = LUA_REFNIL;
527 globalconf.hooks.focus = LUA_REFNIL;
528 globalconf.hooks.unfocus = LUA_REFNIL;
529 globalconf.hooks.mouseover = LUA_REFNIL;
530 globalconf.hooks.arrange = LUA_REFNIL;
531 globalconf.hooks.titleupdate = LUA_REFNIL;
532 globalconf.hooks.urgent = LUA_REFNIL;
533 globalconf.hooks.timer = LUA_REFNIL;
536 #define XDG_CONFIG_HOME_DEFAULT "/.config"
538 #define AWESOME_CONFIG_FILE "/awesome/rc.lua"
540 /** Load a configuration file.
541 * \param rcfile The configuration file to load.
543 void
544 luaA_parserc(const char *confpatharg)
546 int screen;
547 const char *confdir, *xdg_config_dirs;
548 char *confpath = NULL, **xdg_files, **buf, path[1024];
549 ssize_t len;
551 if(confpatharg)
553 if(luaL_dofile(globalconf.L, confpatharg))
554 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
555 else
556 goto bailout;
559 confdir = getenv("XDG_CONFIG_HOME");
561 if((len = a_strlen(confdir)))
563 len += sizeof(AWESOME_CONFIG_FILE);
564 confpath = p_new(char, len);
565 a_strcpy(confpath, len, confdir);
566 /* update package.path */
567 snprintf(path, sizeof(path) - 1, "package.path = package.path .. \";%s/awesome/?.lua\"", confdir);
568 luaA_dostring(globalconf.L, path);
570 else
572 confdir = getenv("HOME");
573 len = a_strlen(confdir) + sizeof(AWESOME_CONFIG_FILE)-1 + sizeof(XDG_CONFIG_HOME_DEFAULT);
574 confpath = p_new(char, len);
575 a_strcpy(confpath, len, confdir);
576 a_strcat(confpath, len, XDG_CONFIG_HOME_DEFAULT);
577 /* update package.path */
578 snprintf(path, sizeof(path) - 1, "package.path = package.path .. \";%s" XDG_CONFIG_HOME_DEFAULT "/awesome/?.lua\"", confdir);
579 luaA_dostring(globalconf.L, path);
581 a_strcat(confpath, len, AWESOME_CONFIG_FILE);
583 if(luaL_dofile(globalconf.L, confpath))
584 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
585 else
586 goto bailout;
588 xdg_config_dirs = getenv("XDG_CONFIG_DIRS");
590 if(!(len = a_strlen(xdg_config_dirs)))
592 xdg_config_dirs = XDG_CONFIG_DIR;
593 len = sizeof(XDG_CONFIG_DIR) - 1;
596 xdg_files = a_strsplit(xdg_config_dirs, len, ':');
598 for(buf = xdg_files; *buf; buf++)
600 p_delete(&confpath);
601 len = a_strlen(*buf) + sizeof("AWESOME_CONFIG_FILE");
602 confpath = p_new(char, len);
603 a_strcpy(confpath, len, *buf);
604 a_strcat(confpath, len, AWESOME_CONFIG_FILE);
605 snprintf(path, sizeof(path) - 1, "package.path = package.path .. \";%s/awesome/?.lua\"", *buf);
606 luaA_dostring(globalconf.L, path);
607 if(luaL_dofile(globalconf.L, confpath))
608 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
609 else
610 break;
613 for(buf = xdg_files; *buf; buf++)
614 p_delete(buf);
615 p_delete(&xdg_files);
617 bailout:
618 /* Assure there's at least one tag */
619 for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
620 if(!globalconf.screens[screen].tags.len)
621 tag_append_to_screen(tag_new("default", sizeof("default")-1, layout_tile, 0.5, 1, 0), screen);
623 p_delete(&confpath);
626 /** Parse a command.
627 * \param cmd The buffer to parse.
628 * \return true on succes, false on failure.
630 static void
631 luaA_docmd(const char *cmd)
633 char *p;
635 while((p = strchr(cmd, '\n')))
637 *p = '\0';
638 luaA_dostring(globalconf.L, cmd);
639 cmd = p + 1;
643 static void
644 luaA_cb(EV_P_ ev_io *w, int revents)
646 char buf[1024];
647 int r;
649 switch(r = recv(w->fd, buf, sizeof(buf)-1, MSG_TRUNC))
651 case -1:
652 warn("error reading UNIX domain socket: %s", strerror(errno));
653 luaA_cs_cleanup();
654 break;
655 case 0:
656 break;
657 default:
658 if(r >= ssizeof(buf))
659 break;
660 buf[r] = '\0';
661 luaA_docmd(buf);
665 void
666 luaA_cs_init(void)
668 int csfd = socket_getclient();
670 if (csfd < 0)
671 return;
672 addr = socket_getaddr(getenv("DISPLAY"));
674 if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
676 if(errno == EADDRINUSE)
678 if(unlink(addr->sun_path))
679 warn("error unlinking existing file: %s", strerror(errno));
680 if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
681 warn("error binding UNIX domain socket: %s", strerror(errno));
683 else
684 warn("error binding UNIX domain socket: %s", strerror(errno));
686 ev_io_init(&csio, &luaA_cb, csfd, EV_READ);
687 ev_io_start(EV_DEFAULT_UC_ &csio);
688 ev_unref(EV_DEFAULT_UC);
691 void
692 luaA_cs_cleanup(void)
694 if(csio.fd < 0)
695 return;
696 ev_ref(EV_DEFAULT_UC);
697 ev_io_stop(EV_DEFAULT_UC_ &csio);
698 if (close(csio.fd))
699 warn("error closing UNIX domain socket: %s", strerror(errno));
700 if(unlink(addr->sun_path))
701 warn("error unlinking UNIX domain socket: %s", strerror(errno));
702 p_delete(&addr);
703 csio.fd = -1;
706 void
707 luaA_on_timer(EV_P_ ev_timer *w, int revents)
709 luaA_dofunction(globalconf.L, globalconf.hooks.timer, 0, 0);
712 void
713 luaA_pushcolor(lua_State *L, const xcolor_t *c)
715 uint8_t r = (unsigned)c->red * 0xff / 0xffff;
716 uint8_t g = (unsigned)c->green * 0xff / 0xffff;
717 uint8_t b = (unsigned)c->blue * 0xff / 0xffff;
718 uint8_t a = (unsigned)c->alpha * 0xff / 0xffff;
719 char s[10];
720 snprintf(s, sizeof(s), "#%02x%02x%02x%02x", r, g, b, a);
721 lua_pushlstring(L, s, sizeof(s));