build: set minimal cmake version to 2.4.7
[awesome.git] / lua.c
blob47786622ab3ebc46f966481761db9a157e72409c
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>
29 #include <lua.h>
30 #include <lauxlib.h>
31 #include <lualib.h>
33 #include <xcb/xcb.h>
34 #include <xcb/xcb_aux.h>
36 #include "ewmh.h"
37 #include "config.h"
38 #include "structs.h"
39 #include "lua.h"
40 #include "tag.h"
41 #include "client.h"
42 #include "window.h"
43 #include "statusbar.h"
44 #include "titlebar.h"
45 #include "screen.h"
46 #include "layouts/tile.h"
47 #include "common/socket.h"
48 #include "common/version.h"
50 extern awesome_t globalconf;
52 extern const name_func_link_t FloatingPlacementList[];
54 extern const struct luaL_reg awesome_keygrabber_lib[];
55 extern const struct luaL_reg awesome_mouse_methods[];
56 extern const struct luaL_reg awesome_mouse_meta[];
57 extern const struct luaL_reg awesome_client_methods[];
58 extern const struct luaL_reg awesome_client_meta[];
59 extern const struct luaL_reg awesome_titlebar_methods[];
60 extern const struct luaL_reg awesome_titlebar_meta[];
61 extern const struct luaL_reg awesome_tag_methods[];
62 extern const struct luaL_reg awesome_tag_meta[];
63 extern const struct luaL_reg awesome_widget_methods[];
64 extern const struct luaL_reg awesome_widget_meta[];
65 extern const struct luaL_reg awesome_statusbar_methods[];
66 extern const struct luaL_reg awesome_statusbar_meta[];
67 extern const struct luaL_reg awesome_keybinding_methods[];
68 extern const struct luaL_reg awesome_keybinding_meta[];
70 static struct sockaddr_un *addr;
71 static ev_io csio = { .fd = -1 };
73 /** Add a global mouse binding. This binding will be available when you'll
74 * click on root window.
75 * \param L The Lua VM state.
77 * \luastack
78 * \lparam A mouse button binding.
80 static int
81 luaA_mouse_add(lua_State *L)
83 button_t **button = luaA_checkudata(L, 1, "mouse");
85 button_list_push(&globalconf.buttons.root, *button);
86 button_ref(button);
88 return 0;
91 /** Set the floating placement algorithm. This will be used to compute the
92 * initial floating position of floating windows.
93 * \param L The Lua VM state.
95 * \luastack
96 * \lparam An algorith name, either `none', `smart' or `mouse'.
98 static int
99 luaA_floating_placement_set(lua_State *L)
101 const char *pl = luaL_checkstring(L, 1);
102 globalconf.floating_placement = name_func_lookup(pl, FloatingPlacementList);
103 return 0;
106 /** Quit awesome.
108 static int
109 luaA_quit(lua_State *L __attribute__ ((unused)))
111 ev_unloop(globalconf.loop, 1);
112 return 0;
115 /** Execute another application, probably a window manager, to replace
116 * awesome.
117 * \param L The Lua VM state.
119 * \luastack
120 * \lparam The command line to execute.
122 static int
123 luaA_exec(lua_State *L)
125 client_t *c;
126 const char *cmd = luaL_checkstring(L, 1);
128 for(c = globalconf.clients; c; c = c->next)
129 client_unban(c);
131 xcb_aux_sync(globalconf.connection);
132 xcb_disconnect(globalconf.connection);
134 a_exec(cmd);
135 return 0;
138 /** Restart awesome.
140 static int
141 luaA_restart(lua_State *L __attribute__ ((unused)))
143 a_exec(globalconf.argv);
144 return 0;
147 /** Set the screen padding. This can be used to define margin around the
148 * screen. awesome will not use this area.
149 * \param L The Lua VM state.
151 * \luastack
152 * \lparam A screen number.
153 * \lparam A table with a list of margin for `right', `left', `top' and
154 * `bottom'.
156 static int
157 luaA_padding_set(lua_State *L)
159 int screen = luaL_checknumber(L, 1) - 1;
161 if(screen >= 0 && screen < globalconf.screens_info->nscreen)
163 luaA_checktable(L, 2);
165 globalconf.screens[screen].padding.right = luaA_getopt_number(L, 2, "right", 0);
166 globalconf.screens[screen].padding.left = luaA_getopt_number(L, 2, "left", 0);
167 globalconf.screens[screen].padding.top = luaA_getopt_number(L, 2, "top", 0);
168 globalconf.screens[screen].padding.bottom = luaA_getopt_number(L, 2, "bottom", 0);
171 ewmh_update_workarea(screen_virttophys(screen));
173 return 0;
176 /** Define if awesome should respect applications size hints when resizing
177 * windows in tiled mode. If you set this to true, you will experience gaps
178 * between windows, but they will have the best size they can have.
179 * \param L The Lua VM state.
181 * \luastack
182 * \lparam A boolean value, true to enable, false to disable.
184 static int
185 luaA_resizehints_set(lua_State *L)
187 globalconf.resize_hints = luaA_checkboolean(L, 1);
188 return 0;
191 /** Get the screen count.
192 * \param L The Lua VM state.
194 * \luastack
195 * \lreturn The screen count, at least 1.
197 static int
198 luaA_screen_count(lua_State *L)
200 lua_pushnumber(L, globalconf.screens_info->nscreen);
201 return 1;
204 /** Give the focus to a screen.
205 * \param L The Lua VM state.
207 * \luastack
208 * \lparam A screen number
210 static int
211 luaA_screen_focus(lua_State *L)
213 /* Our table begin at 0, Lua begins at 1 */
214 int screen = luaL_checknumber(L, 1) - 1;
215 luaA_checkscreen(screen);
216 client_focus(NULL, screen);
217 return 0;
220 static int
221 luaA_screen_coords_get(lua_State *L)
223 int screen = luaL_checknumber(L, 1) - 1;
224 luaA_checkscreen(screen);
225 lua_newtable(L);
226 lua_pushnumber(L, globalconf.screens_info->geometry[screen].x);
227 lua_setfield(L, -2, "x");
228 lua_pushnumber(L, globalconf.screens_info->geometry[screen].y);
229 lua_setfield(L, -2, "y");
230 lua_pushnumber(L, globalconf.screens_info->geometry[screen].width);
231 lua_setfield(L, -2, "width");
232 lua_pushnumber(L, globalconf.screens_info->geometry[screen].height);
233 lua_setfield(L, -2, "height");
234 return 1;
237 /** Set the function called each time a client gets focus. This function is
238 * called with the client object as argument.
239 * \param L The Lua VM state.
241 * \luastack
242 * \lparam A function to call each time a client gets focus.
244 static int
245 luaA_hooks_focus(lua_State *L)
247 luaA_checkfunction(L, 1);
248 if(globalconf.hooks.focus)
249 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.focus);
250 globalconf.hooks.focus = luaL_ref(L, LUA_REGISTRYINDEX);
251 return 0;
254 /** Set the function called each time a client loses focus. This function is
255 * called with the client object as argument.
256 * \param L The Lua VM state.
258 * \luastack
259 * \lparam A function to call each time a client loses focus.
261 static int
262 luaA_hooks_unfocus(lua_State *L)
264 luaA_checkfunction(L, 1);
265 if(globalconf.hooks.unfocus)
266 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.unfocus);
267 globalconf.hooks.unfocus = luaL_ref(L, LUA_REGISTRYINDEX);
268 return 0;
271 /** Set the function called each time a new client appears. This function is
272 * called with the client object as argument.
273 * \param L The Lua VM state.
275 * \luastack
276 * \lparam A function to call on each new client.
278 static int
279 luaA_hooks_manage(lua_State *L)
281 luaA_checkfunction(L, 1);
282 if(globalconf.hooks.manage)
283 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.manage);
284 globalconf.hooks.manage = luaL_ref(L, LUA_REGISTRYINDEX);
285 return 0;
288 /** Set the function called each time a client goes away. This function is
289 * called with the client object as argument.
290 * \param L The Lua VM state.
292 * \luastack
293 * \lparam A function to call when a client goes away.
295 static int
296 luaA_hooks_unmanage(lua_State *L)
298 luaA_checkfunction(L, 1);
299 if(globalconf.hooks.unmanage)
300 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.unmanage);
301 globalconf.hooks.unmanage = luaL_ref(L, LUA_REGISTRYINDEX);
302 return 0;
305 /** Set the function called each time the mouse enter a new window. This
306 * function is called with the client object as argument.
307 * \param L The Lua VM state.
309 * \luastack
310 * \lparam A function to call each time a client gets mouse over it.
312 static int
313 luaA_hooks_mouseover(lua_State *L)
315 luaA_checkfunction(L, 1);
316 if(globalconf.hooks.mouseover)
317 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.mouseover);
318 globalconf.hooks.mouseover = luaL_ref(L, LUA_REGISTRYINDEX);
319 return 0;
322 /** Set the function called on each screen arrange. This function is called
323 * with the screen number as argument.
324 * \param L The Lua VM state.
326 * \luastack
327 * \lparam A function to call on each screen arrange.
329 static int
330 luaA_hooks_arrange(lua_State *L)
332 luaA_checkfunction(L, 1);
333 if(globalconf.hooks.arrange)
334 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.arrange);
335 globalconf.hooks.arrange = luaL_ref(L, LUA_REGISTRYINDEX);
336 return 0;
339 /** Set the function called on each title update. This function is called with
340 * the client object as argument.
341 * \param L The Lua VM state.
343 * \luastack
344 * \lparam A function to call on each title update of each client.
346 static int
347 luaA_hooks_titleupdate(lua_State *L)
349 luaA_checkfunction(L, 1);
350 if(globalconf.hooks.titleupdate)
351 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.titleupdate);
352 globalconf.hooks.titleupdate = luaL_ref(L, LUA_REGISTRYINDEX);
353 return 0;
356 /** Set the function called when a client get urgency flag. This function is called with
357 * the client object as argument.
358 * \param L The Lua VM state.
360 * \luastack
361 * \lparam A function to call when a client get the urgent flag.
363 static int
364 luaA_hooks_urgent(lua_State *L)
366 luaA_checkfunction(L, 1);
367 if(globalconf.hooks.urgent)
368 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.urgent);
369 globalconf.hooks.urgent = luaL_ref(L, LUA_REGISTRYINDEX);
370 return 0;
373 /** Set the function to be called every N seconds.
374 * \param L The Lua VM state.
376 * \luastack
377 * \lparam The number of seconds to run function every. Set 0 to disable.
378 * \lparam A function to call every N seconds (optional).
380 static int
381 luaA_hooks_timer(lua_State *L)
383 globalconf.timer.repeat = luaL_checknumber(L, 1);
385 if(lua_gettop(L) == 2 && !lua_isnil(L, 2))
387 luaA_checkfunction(L, 2);
388 if(globalconf.hooks.timer)
389 luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.timer);
390 globalconf.hooks.timer = luaL_ref(L, LUA_REGISTRYINDEX);
393 ev_timer_again(globalconf.loop, &globalconf.timer);
394 return 0;
397 /** Set default font.
398 * \param L The Lua VM state.
400 * \luastack
401 * \lparam A string with a font name in Pango format.
403 static int
404 luaA_font_set(lua_State *L)
406 const char *font = luaL_checkstring(L, 1);
407 draw_font_delete(&globalconf.font);
408 globalconf.font = draw_font_new(globalconf.connection,
409 globalconf.default_screen, font);
410 return 0;
413 /** Set default colors.
414 * \param L The Lua VM state.
416 * \luastack
417 * \lparam A table with `fg' and `bg' elements, containing colors.
419 static int
420 luaA_colors_set(lua_State *L)
422 const char *fg, *bg;
423 luaA_checktable(L, 1);
424 if((fg = luaA_getopt_string(L, 1, "fg", NULL)))
425 xcolor_new(globalconf.connection, globalconf.default_screen,
426 fg, &globalconf.colors.fg);
427 if((bg = luaA_getopt_string(L, 1, "bg",NULL)))
428 xcolor_new(globalconf.connection, globalconf.default_screen,
429 bg, &globalconf.colors.bg);
430 return 0;
433 /** Push a pointer onto the stack according to its type.
434 * \param p The pointer.
435 * \param type Its type.
437 void
438 luaA_pushpointer(lua_State *L, void *p, awesome_type_t type)
440 switch(type)
442 case AWESOME_TYPE_STATUSBAR:
443 luaA_statusbar_userdata_new(L, p);
444 break;
445 case AWESOME_TYPE_TITLEBAR:
446 luaA_titlebar_userdata_new(L, p);
447 break;
451 static void
452 luaA_openlib(lua_State *L, const char *name,
453 const struct luaL_reg methods[],
454 const struct luaL_reg meta[])
456 luaL_newmetatable(L, name);
457 lua_pushliteral(L, "__index");
458 lua_pushvalue(L, -2); /* dup metatable*/
459 lua_settable(L, -3); /* metatable.__index = metatable */
461 luaL_register(L, NULL, meta);
462 luaL_register(L, name, methods);
465 /** Initialize the Lua VM
467 void
468 luaA_init(void)
470 lua_State *L;
472 static const struct luaL_reg awesome_lib[] =
474 { "quit", luaA_quit },
475 { "exec", luaA_exec },
476 { "restart", luaA_restart },
477 { "floating_placement_set", luaA_floating_placement_set },
478 { "padding_set", luaA_padding_set },
479 { "mouse_add", luaA_mouse_add },
480 { "resizehints_set", luaA_resizehints_set },
481 { "font_set", luaA_font_set },
482 { "colors_set", luaA_colors_set },
483 { NULL, NULL }
485 static const struct luaL_reg awesome_screen_lib[] =
487 { "coords_get", luaA_screen_coords_get },
488 { "count", luaA_screen_count },
489 { "focus", luaA_screen_focus },
490 { NULL, NULL }
492 static const struct luaL_reg awesome_hooks_lib[] =
494 { "focus", luaA_hooks_focus },
495 { "unfocus", luaA_hooks_unfocus },
496 { "manage", luaA_hooks_manage },
497 { "unmanage", luaA_hooks_unmanage },
498 { "mouseover", luaA_hooks_mouseover },
499 { "arrange", luaA_hooks_arrange },
500 { "titleupdate", luaA_hooks_titleupdate },
501 { "urgent", luaA_hooks_urgent },
502 { "timer", luaA_hooks_timer },
503 { NULL, NULL }
506 L = globalconf.L = lua_open();
508 luaL_openlibs(L);
510 /* Export awesome lib */
511 luaL_register(L, "awesome", awesome_lib);
513 /* Export screen lib */
514 luaL_register(L, "screen", awesome_screen_lib);
516 /* Export hooks lib */
517 luaL_register(L, "hooks", awesome_hooks_lib);
519 /* Export keygrabber lib */
520 luaL_register(L, "keygrabber", awesome_keygrabber_lib);
522 /* Export mouse */
523 luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta);
525 /* Export tag */
526 luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta);
528 /* Export statusbar */
529 luaA_openlib(L, "statusbar", awesome_statusbar_methods, awesome_statusbar_meta);
531 /* Export widget */
532 luaA_openlib(L, "widget", awesome_widget_methods, awesome_widget_meta);
534 /* Export client */
535 luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta);
537 /* Export titlebar */
538 luaA_openlib(L, "titlebar", awesome_titlebar_methods, awesome_titlebar_meta);
540 /* Export keys */
541 luaA_openlib(L, "keybinding", awesome_keybinding_methods, awesome_keybinding_meta);
543 lua_pushliteral(L, "AWESOME_VERSION");
544 lua_pushstring(L, version_string());
545 lua_settable(L, LUA_GLOBALSINDEX);
547 luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?.lua\"");
550 /** Load a configuration file
552 * \param rcfile The configuration file to load.
553 * \return True on succes, false on failure.
555 bool
556 luaA_parserc(const char* rcfile)
558 int screen;
560 if(luaL_dofile(globalconf.L, rcfile))
562 fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
563 return false;
566 /* Assure there's at least one tag */
567 for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
568 if(!globalconf.screens[screen].tags)
569 tag_append_to_screen(tag_new("default", layout_tile, 0.5, 1, 0), screen);
571 return true;
574 /** Parse a command.
575 * \param cmd The buffer to parse.
576 * \return true on succes, false on failure.
578 static void
579 luaA_docmd(char *cmd)
581 char *p, *curcmd = cmd;
583 if(a_strlen(cmd))
584 while((p = strchr(curcmd, '\n')))
586 *p = '\0';
587 luaA_dostring(globalconf.L, curcmd);
588 curcmd = p + 1;
592 static void
593 luaA_cb(EV_P_ ev_io *w, int revents)
595 char buf[1024];
596 int r;
598 switch(r = recv(w->fd, buf, sizeof(buf)-1, MSG_TRUNC))
600 case -1:
601 warn("error reading UNIX domain socket: %s", strerror(errno));
602 luaA_cs_cleanup();
603 break;
604 case 0:
605 break;
606 default:
607 if(r >= ssizeof(buf))
608 break;
609 buf[r] = '\0';
610 luaA_docmd(buf);
614 void
615 luaA_cs_init(void)
617 int csfd = socket_getclient();
619 if (csfd < 0)
620 return;
621 addr = socket_getaddr(getenv("DISPLAY"));
623 if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
625 if(errno == EADDRINUSE)
627 if(unlink(addr->sun_path))
628 warn("error unlinking existing file: %s", strerror(errno));
629 if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
630 warn("error binding UNIX domain socket: %s", strerror(errno));
632 else
633 warn("error binding UNIX domain socket: %s", strerror(errno));
635 ev_io_init(&csio, &luaA_cb, csfd, EV_READ);
636 ev_io_start(EV_DEFAULT_UC_ &csio);
637 ev_unref(EV_DEFAULT_UC);
640 void
641 luaA_cs_cleanup(void)
643 if(csio.fd < 0)
644 return;
645 ev_ref(EV_DEFAULT_UC);
646 ev_io_stop(EV_DEFAULT_UC_ &csio);
647 if (close(csio.fd))
648 warn("error closing UNIX domain socket: %s", strerror(errno));
649 if(unlink(addr->sun_path))
650 warn("error unlinking UNIX domain socket: %s", strerror(errno));
651 p_delete(&addr);
652 csio.fd = -1;
655 void
656 luaA_on_timer(EV_P_ ev_timer *w, int revents)
658 luaA_dofunction(globalconf.L, globalconf.hooks.timer, 0);