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.
24 #include <sys/socket.h>
34 #include <xcb/xcb_aux.h>
43 #include "statusbar.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.
78 * \lparam A mouse button binding.
81 luaA_mouse_add(lua_State
*L
)
83 button_t
**button
= luaA_checkudata(L
, 1, "mouse");
85 button_list_push(&globalconf
.buttons
.root
, *button
);
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.
96 * \lparam An algorith name, either `none', `smart' or `mouse'.
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
);
109 luaA_quit(lua_State
*L
__attribute__ ((unused
)))
111 ev_unloop(globalconf
.loop
, 1);
115 /** Execute another application, probably a window manager, to replace
117 * \param L The Lua VM state.
120 * \lparam The command line to execute.
123 luaA_exec(lua_State
*L
)
126 const char *cmd
= luaL_checkstring(L
, 1);
128 for(c
= globalconf
.clients
; c
; c
= c
->next
)
131 xcb_aux_sync(globalconf
.connection
);
132 xcb_disconnect(globalconf
.connection
);
141 luaA_restart(lua_State
*L
__attribute__ ((unused
)))
143 a_exec(globalconf
.argv
);
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.
152 * \lparam A screen number.
153 * \lparam A table with a list of margin for `right', `left', `top' and
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
));
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.
182 * \lparam A boolean value, true to enable, false to disable.
185 luaA_resizehints_set(lua_State
*L
)
187 globalconf
.resize_hints
= luaA_checkboolean(L
, 1);
191 /** Get the screen count.
192 * \param L The Lua VM state.
195 * \lreturn The screen count, at least 1.
198 luaA_screen_count(lua_State
*L
)
200 lua_pushnumber(L
, globalconf
.screens_info
->nscreen
);
204 /** Give the focus to a screen.
205 * \param L The Lua VM state.
208 * \lparam A screen number
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
);
221 luaA_screen_coords_get(lua_State
*L
)
223 int screen
= luaL_checknumber(L
, 1) - 1;
224 luaA_checkscreen(screen
);
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");
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.
242 * \lparam A function to call each time a client gets focus.
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
);
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.
259 * \lparam A function to call each time a client loses focus.
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
);
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.
276 * \lparam A function to call on each new client.
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
);
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.
293 * \lparam A function to call when a client goes away.
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
);
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.
310 * \lparam A function to call each time a client gets mouse over it.
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
);
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.
327 * \lparam A function to call on each screen arrange.
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
);
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.
344 * \lparam A function to call on each title update of each client.
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
);
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.
361 * \lparam A function to call when a client get the urgent flag.
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
);
373 /** Set the function to be called every N seconds.
374 * \param L The Lua VM state.
377 * \lparam The number of seconds to run function every. Set 0 to disable.
378 * \lparam A function to call every N seconds (optional).
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
);
397 /** Set default font.
398 * \param L The Lua VM state.
401 * \lparam A string with a font name in Pango format.
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
);
413 /** Set default colors.
414 * \param L The Lua VM state.
417 * \lparam A table with `fg' and `bg' elements, containing colors.
420 luaA_colors_set(lua_State
*L
)
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
);
433 /** Push a pointer onto the stack according to its type.
434 * \param p The pointer.
435 * \param type Its type.
438 luaA_pushpointer(lua_State
*L
, void *p
, awesome_type_t type
)
442 case AWESOME_TYPE_STATUSBAR
:
443 luaA_statusbar_userdata_new(L
, p
);
445 case AWESOME_TYPE_TITLEBAR
:
446 luaA_titlebar_userdata_new(L
, p
);
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
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
},
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
},
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
},
506 L
= globalconf
.L
= lua_open();
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
);
523 luaA_openlib(L
, "mouse", awesome_mouse_methods
, awesome_mouse_meta
);
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
);
532 luaA_openlib(L
, "widget", awesome_widget_methods
, awesome_widget_meta
);
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
);
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.
556 luaA_parserc(const char* rcfile
)
560 if(luaL_dofile(globalconf
.L
, rcfile
))
562 fprintf(stderr
, "%s\n", lua_tostring(globalconf
.L
, -1));
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
);
575 * \param cmd The buffer to parse.
576 * \return true on succes, false on failure.
579 luaA_docmd(char *cmd
)
581 char *p
, *curcmd
= cmd
;
584 while((p
= strchr(curcmd
, '\n')))
587 luaA_dostring(globalconf
.L
, curcmd
);
593 luaA_cb(EV_P_ ev_io
*w
, int revents
)
598 switch(r
= recv(w
->fd
, buf
, sizeof(buf
)-1, MSG_TRUNC
))
601 warn("error reading UNIX domain socket: %s", strerror(errno
));
607 if(r
>= ssizeof(buf
))
617 int csfd
= socket_getclient();
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
));
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
);
641 luaA_cs_cleanup(void)
645 ev_ref(EV_DEFAULT_UC
);
646 ev_io_stop(EV_DEFAULT_UC_
&csio
);
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
));
656 luaA_on_timer(EV_P_ ev_timer
*w
, int revents
)
658 luaA_dofunction(globalconf
.L
, globalconf
.hooks
.timer
, 0);