2 * luaa.c - Lua configuration management
4 * Copyright © 2008-2009 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.
28 #include <basedir_fs.h>
30 #include <xcb/xcb_atom.h>
34 #include "objects/timer.h"
35 #include "awesome-version-internal.h"
39 #include "objects/tag.h"
40 #include "objects/client.h"
41 #include "objects/drawin.h"
42 #include "objects/drawable.h"
46 #include "selection.h"
48 #include "common/xcursor.h"
49 #include "common/buffer.h"
50 #include "common/backtrace.h"
53 extern const struct luaL_Reg awesome_dbus_lib
[];
55 extern const struct luaL_Reg awesome_keygrabber_lib
[];
56 extern const struct luaL_Reg awesome_mousegrabber_lib
[];
57 extern const struct luaL_Reg awesome_root_lib
[];
58 extern const struct luaL_Reg awesome_mouse_methods
[];
59 extern const struct luaL_Reg awesome_mouse_meta
[];
60 extern const struct luaL_Reg awesome_screen_methods
[];
61 extern const struct luaL_Reg awesome_screen_meta
[];
63 /** Path to config file */
64 static char *conffile
;
66 /** Check whether a composite manager is running.
67 * \return True if such a manager is running.
70 composite_manager_running(void)
72 xcb_intern_atom_reply_t
*atom_r
;
73 xcb_get_selection_owner_reply_t
*selection_r
;
77 if(!(atom_name
= xcb_atom_name_by_screen("_NET_WM_CM", globalconf
.default_screen
)))
79 warn("error getting composite manager atom");
83 atom_r
= xcb_intern_atom_reply(globalconf
.connection
,
84 xcb_intern_atom_unchecked(globalconf
.connection
, false,
85 a_strlen(atom_name
), atom_name
),
91 selection_r
= xcb_get_selection_owner_reply(globalconf
.connection
,
92 xcb_get_selection_owner_unchecked(globalconf
.connection
,
97 result
= selection_r
!= NULL
&& selection_r
->owner
!= XCB_NONE
;
98 p_delete(&selection_r
);
104 * \param L The Lua VM state.
105 * \return The number of elements pushed on stack.
108 luaA_quit(lua_State
*L
)
110 g_main_loop_quit(globalconf
.loop
);
114 /** Execute another application, probably a window manager, to replace
116 * \param L The Lua VM state.
117 * \return The number of elements pushed on stack.
119 * \lparam The command line to execute.
122 luaA_exec(lua_State
*L
)
124 const char *cmd
= luaL_checkstring(L
, 1);
126 awesome_atexit(false);
135 luaA_restart(lua_State
*L
)
141 /** Load an image from a given path.
142 * \param L The Lua VM state.
143 * \return The number of elements pushed on stack.
145 * \lparam The command line to execute.
148 luaA_load_image(lua_State
*L
)
150 const char *filename
= luaL_checkstring(L
, 1);
151 cairo_surface_t
*surface
= draw_load_image(L
, filename
);
154 /* lua has to make sure to free the ref or we have a leak */
155 lua_pushlightuserdata(L
, surface
);
159 /** UTF-8 aware string length computing.
160 * \param L The Lua VM state.
161 * \return The number of elements pushed on stack.
164 luaA_mbstrlen(lua_State
*L
)
166 const char *cmd
= luaL_checkstring(L
, 1);
167 lua_pushnumber(L
, (ssize_t
) mbstowcs(NULL
, NONULL(cmd
), 0));
171 /** Enhanced type() function which recognize awesome objects.
172 * \param L The Lua VM state.
173 * \return The number of arguments pushed on the stack.
176 luaAe_type(lua_State
*L
)
179 lua_pushstring(L
, luaA_typename(L
, 1));
183 /** Replace various standards Lua functions with our own.
184 * \param L The Lua VM state.
187 luaA_fixups(lua_State
*L
)
189 /* export string.wlen */
190 lua_getglobal(L
, "string");
191 lua_pushcfunction(L
, luaA_mbstrlen
);
192 lua_setfield(L
, -2, "wlen");
195 lua_pushcfunction(L
, luaAe_type
);
196 lua_setglobal(L
, "type");
198 lua_pushcfunction(L
, luaA_selection_get
);
199 lua_setglobal(L
, "selection");
202 /** awesome global table.
203 * \param L The Lua VM state.
204 * \return The number of elements pushed on stack.
206 * \lfield conffile The configuration file which has been loaded.
207 * \lfield version The version of awesome.
208 * \lfield release The release name of awesome.
209 * \lfield startup True if we are still in startup, false otherwise.
210 * \lfield startup_errors Error message for errors that occured during startup.
211 * \lfield composite_manager_running True if a composite manager is running.
214 luaA_awesome_index(lua_State
*L
)
216 if(luaA_usemetatable(L
, 1, 2))
219 const char *buf
= luaL_checkstring(L
, 2);
221 if(A_STREQ(buf
, "conffile"))
223 lua_pushstring(L
, conffile
);
227 if(A_STREQ(buf
, "version"))
229 lua_pushliteral(L
, AWESOME_VERSION
);
233 if(A_STREQ(buf
, "release"))
235 lua_pushliteral(L
, AWESOME_RELEASE
);
239 if(A_STREQ(buf
, "startup"))
241 lua_pushboolean(L
, globalconf
.loop
== NULL
);
245 if(A_STREQ(buf
, "startup_errors") && globalconf
.startup_errors
.len
!= 0)
247 lua_pushstring(L
, globalconf
.startup_errors
.s
);
251 if(A_STREQ(buf
, "composite_manager_running"))
253 lua_pushboolean(L
, composite_manager_running());
260 /** Add a global signal.
261 * \param L The Lua VM state.
262 * \return The number of elements pushed on stack.
264 * \lparam A string with the event name.
265 * \lparam The function to call.
268 luaA_awesome_connect_signal(lua_State
*L
)
270 const char *name
= luaL_checkstring(L
, 1);
271 luaA_checkfunction(L
, 2);
272 signal_connect(&global_signals
, name
, luaA_object_ref(L
, 2));
276 /** Remove a global signal.
277 * \param L The Lua VM state.
278 * \return The number of elements pushed on stack.
280 * \lparam A string with the event name.
281 * \lparam The function to call.
284 luaA_awesome_disconnect_signal(lua_State
*L
)
286 const char *name
= luaL_checkstring(L
, 1);
287 luaA_checkfunction(L
, 2);
288 const void *func
= lua_topointer(L
, 2);
289 signal_disconnect(&global_signals
, name
, func
);
290 luaA_object_unref(L
, (void *) func
);
294 /** Emit a global signal.
295 * \param L The Lua VM state.
296 * \return The number of elements pushed on stack.
298 * \lparam A string with the event name.
299 * \lparam The function to call.
302 luaA_awesome_emit_signal(lua_State
*L
)
304 signal_object_emit(L
, &global_signals
, luaL_checkstring(L
, 1), lua_gettop(L
) - 1);
309 luaA_panic(lua_State
*L
)
311 warn("unprotected error in call to Lua API (%s)",
312 lua_tostring(L
, -1));
315 warn("dumping backtrace\n%s", buf
.s
);
316 warn("restarting awesome");
322 luaA_dofunction_on_error(lua_State
*L
)
324 /* duplicate string error */
325 lua_pushvalue(L
, -1);
326 /* emit error signal */
327 signal_object_emit(L
, &global_signals
, "debug::error", 1);
329 if(!luaL_dostring(L
, "return debug.traceback(\"error while running function\", 3)"))
331 /* Move traceback before error */
333 /* Insert sentence */
334 lua_pushliteral(L
, "\nerror: ");
335 /* Move it before error */
342 /** Initialize the Lua VM
343 * \param xdg An xdg handle to use to get XDG basedir.
346 luaA_init(xdgHandle
* xdg
)
349 static const struct luaL_Reg awesome_lib
[] =
351 { "quit", luaA_quit
},
352 { "exec", luaA_exec
},
353 { "spawn", luaA_spawn
},
354 { "restart", luaA_restart
},
355 { "connect_signal", luaA_awesome_connect_signal
},
356 { "disconnect_signal", luaA_awesome_disconnect_signal
},
357 { "emit_signal", luaA_awesome_emit_signal
},
358 { "systray", luaA_systray
},
359 { "load_image", luaA_load_image
},
360 { "register_xproperty", luaA_register_xproperty
},
361 { "set_xproperty", luaA_set_xproperty
},
362 { "get_xproperty", luaA_get_xproperty
},
363 { "__index", luaA_awesome_index
},
367 L
= globalconf
.L
= luaL_newstate();
369 /* Set panic function */
370 lua_atpanic(L
, luaA_panic
);
372 /* Set error handling function */
373 lualib_dofunction_on_error
= luaA_dofunction_on_error
;
379 luaA_object_setup(L
);
381 /* Export awesome lib */
382 luaA_openlib(L
, "awesome", awesome_lib
, awesome_lib
);
384 /* Export root lib */
385 luaA_registerlib(L
, "root", awesome_root_lib
);
386 lua_pop(L
, 1); /* luaA_registerlib() leaves the table on stack */
389 /* Export D-Bus lib */
390 luaA_registerlib(L
, "dbus", awesome_dbus_lib
);
391 lua_pop(L
, 1); /* luaA_registerlib() leaves the table on stack */
394 /* Export keygrabber lib */
395 luaA_registerlib(L
, "keygrabber", awesome_keygrabber_lib
);
396 lua_pop(L
, 1); /* luaA_registerlib() leaves the table on stack */
398 /* Export mousegrabber lib */
399 luaA_registerlib(L
, "mousegrabber", awesome_mousegrabber_lib
);
400 lua_pop(L
, 1); /* luaA_registerlib() leaves the table on stack */
403 luaA_openlib(L
, "screen", awesome_screen_methods
, awesome_screen_meta
);
406 luaA_openlib(L
, "mouse", awesome_mouse_methods
, awesome_mouse_meta
);
409 button_class_setup(L
);
415 window_class_setup(L
);
417 /* Export drawable */
418 drawable_class_setup(L
);
421 drawin_class_setup(L
);
424 client_class_setup(L
);
430 timer_class_setup(L
);
432 /* add Lua search paths */
433 lua_getglobal(L
, "package");
434 if (LUA_TTABLE
!= lua_type(L
, 1))
436 warn("package is not a table");
439 lua_getfield(L
, 1, "path");
440 if (LUA_TSTRING
!= lua_type(L
, 2))
442 warn("package.path is not a string");
447 /* add XDG_CONFIG_DIR as include path */
448 const char * const *xdgconfigdirs
= xdgSearchableConfigDirectories(xdg
);
449 for(; *xdgconfigdirs
; xdgconfigdirs
++)
451 size_t len
= a_strlen(*xdgconfigdirs
);
452 lua_pushliteral(L
, ";");
453 lua_pushlstring(L
, *xdgconfigdirs
, len
);
454 lua_pushliteral(L
, "/awesome/?.lua");
457 lua_pushliteral(L
, ";");
458 lua_pushlstring(L
, *xdgconfigdirs
, len
);
459 lua_pushliteral(L
, "/awesome/?/init.lua");
462 lua_concat(L
, 3); /* concatenate with package.path */
465 /* add Lua lib path (/usr/share/awesome/lib by default) */
466 lua_pushliteral(L
, ";" AWESOME_LUA_LIB_PATH
"/?.lua");
467 lua_pushliteral(L
, ";" AWESOME_LUA_LIB_PATH
"/?/init.lua");
468 lua_concat(L
, 3); /* concatenate with package.path */
469 lua_setfield(L
, 1, "path"); /* package.path = "concatenated string" */
471 lua_getfield(L
, 1, "loaded");
473 lua_pop(L
, 2); /* pop "package" and "package.loaded" */
475 signal_add(&global_signals
, "debug::error");
476 signal_add(&global_signals
, "debug::deprecation");
477 signal_add(&global_signals
, "debug::index::miss");
478 signal_add(&global_signals
, "debug::newindex::miss");
479 signal_add(&global_signals
, "systray::update");
480 signal_add(&global_signals
, "wallpaper_changed");
481 signal_add(&global_signals
, "refresh");
482 signal_add(&global_signals
, "exit");
486 luaA_startup_error(const char *err
)
488 if (globalconf
.startup_errors
.len
> 0)
489 buffer_addsl(&globalconf
.startup_errors
, "\n\n");
490 buffer_adds(&globalconf
.startup_errors
, err
);
494 luaA_loadrc(const char *confpath
, bool run
)
496 if(!luaL_loadfile(globalconf
.L
, confpath
))
500 /* Set the conffile right now so it can be used inside the
501 * configuration file. */
502 conffile
= a_strdup(confpath
);
503 /* Move error handling function before function */
504 lua_pushcfunction(globalconf
.L
, luaA_dofunction_on_error
);
505 lua_insert(globalconf
.L
, -2);
506 if(lua_pcall(globalconf
.L
, 0, LUA_MULTRET
, -2))
508 const char *err
= lua_tostring(globalconf
.L
, -1);
509 luaA_startup_error(err
);
510 fprintf(stderr
, "%s\n", err
);
511 /* An error happened, so reset this. */
519 lua_pop(globalconf
.L
, 1);
525 const char *err
= lua_tostring(globalconf
.L
, -1);
526 luaA_startup_error(err
);
527 fprintf(stderr
, "%s\n", err
);
533 /** Load a configuration file.
534 * \param xdg An xdg handle to use to get XDG basedir.
535 * \param confpatharg The configuration file to load.
536 * \param run Run the configuration file.
539 luaA_parserc(xdgHandle
* xdg
, const char *confpatharg
, bool run
)
541 char *confpath
= NULL
;
544 /* try to load, return if it's ok */
547 if(luaA_loadrc(confpatharg
, run
))
556 confpath
= xdgConfigFind("awesome/rc.lua", xdg
);
558 char *tmp
= confpath
;
560 /* confpath is "string1\0string2\0string3\0\0" */
563 if(luaA_loadrc(tmp
, run
))
570 tmp
+= a_strlen(tmp
) + 1;
581 luaA_class_index_miss_property(lua_State
*L
, lua_object_t
*obj
)
583 signal_object_emit(L
, &global_signals
, "debug::index::miss", 2);
588 luaA_class_newindex_miss_property(lua_State
*L
, lua_object_t
*obj
)
590 signal_object_emit(L
, &global_signals
, "debug::newindex::miss", 3);
597 signal_object_emit(globalconf
.L
, &global_signals
, "refresh", 0);
600 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80