static int internal_prepare_rendering(CustomCellRendererFlexi *cr) { if (cr->rendered_type!=RENDER_NONE) return cr->rendered_type; if (cr->is_raw) { internal_format(cr, cr->raw_value, 65536); } else { if (a_strlen(cr->mime_type)>2) { if (strstr(a_strval(cr->mime_type)+2,"image/")!=NULL) { internal_load_image(cr,a_strval(cr->raw_value),a_strval(cr->mime_type)+2); } else { internal_render_error(cr,"Unrecognized mime-type"); } } else { if (a_strlen(cr->alt_text)>0) { internal_format(cr, cr->alt_text,65536); } else if (a_strlen(cr->raw_value)>0) { internal_format(cr, cr->raw_value,256); } } } return cr->rendered_type; }
/** Register a new xproperty. * \param L The Lua VM state. * \return The number of elements pushed on stack. * \luastack * \lparam The name of the X11 property * \lparam One of "string", "number" or "boolean" */ int luaA_register_xproperty(lua_State *L) { const char *name; struct xproperty property; struct xproperty *found; const char *const args[] = { "string", "number", "boolean" }; xcb_intern_atom_reply_t *atom_r; int type; name = luaL_checkstring(L, 1); type = luaL_checkoption(L, 2, NULL, args); if (type == 0) property.type = PROP_STRING; else if (type == 1) property.type = PROP_NUMBER; else property.type = PROP_BOOLEAN; atom_r = xcb_intern_atom_reply(globalconf.connection, xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(name), name), NULL); if(!atom_r) return 0; property.atom = atom_r->atom; p_delete(&atom_r); found = xproperty_array_lookup(&globalconf.xproperties, &property); if(found) { /* Property already registered */ if(found->type != property.type) return luaL_error(L, "xproperty '%s' already registered with different type", name); } else { buffer_t buf; buffer_inita(&buf, a_strlen(name) + a_strlen("xproperty::") + 1); buffer_addf(&buf, "xproperty::%s", name); property.name = a_strdup(name); xproperty_array_insert(&globalconf.xproperties, property); signal_add(&window_class.signals, buf.s); signal_add(&global_signals, buf.s); buffer_wipe(&buf); } return 0; }
/** Remove systray information in X. */ void systray_cleanup(void) { xcb_intern_atom_reply_t *atom_systray_r; char *atom_name; if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", globalconf.default_screen)) || !(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(atom_name), atom_name), NULL))) { warn("error getting systray atom"); p_delete(&atom_name); return; } p_delete(&atom_name); xcb_set_selection_owner(globalconf.connection, XCB_NONE, atom_systray_r->atom, XCB_CURRENT_TIME); p_delete(&atom_systray_r); xcb_unmap_window(globalconf.connection, globalconf.systray.window); }
/** Check whether a composite manager is running. * \return True if such a manager is running. */ static bool composite_manager_running(void) { xcb_intern_atom_reply_t *atom_r; xcb_get_selection_owner_reply_t *selection_r; char *atom_name; bool result; if(!(atom_name = xcb_atom_name_by_screen("_NET_WM_CM", globalconf.default_screen))) { warn("error getting composite manager atom"); return false; } atom_r = xcb_intern_atom_reply(globalconf.connection, xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(atom_name), atom_name), NULL); p_delete(&atom_name); if(!atom_r) return false; selection_r = xcb_get_selection_owner_reply(globalconf.connection, xcb_get_selection_owner_unchecked(globalconf.connection, atom_r->atom), NULL); p_delete(&atom_r); result = selection_r != NULL && selection_r->owner != XCB_NONE; p_delete(&selection_r); return result; }
void atoms_init(xcb_connection_t *conn) { unsigned int i; xcb_intern_atom_cookie_t cs[countof(ATOM_LIST)]; xcb_intern_atom_reply_t *r; /* Create the atom and get the reply in a XCB way (e.g. send all * the requests at the same time and then get the replies) */ for(i = 0; i < countof(ATOM_LIST); i++) cs[i] = xcb_intern_atom_unchecked(conn, false, a_strlen(ATOM_LIST[i].name), ATOM_LIST[i].name); for(i = 0; i < countof(ATOM_LIST); i++) { if(!(r = xcb_intern_atom_reply(conn, cs[i], NULL))) /* An error occured, get reply for next atom */ continue; *ATOM_LIST[i].atom = r->atom; p_delete(&r); } }
/** Initialize systray information in X. */ void systray_init(void) { xcb_intern_atom_cookie_t atom_systray_q; xcb_intern_atom_reply_t *atom_systray_r; char *atom_name; xcb_screen_t *xscreen = globalconf.screen; globalconf.systray.window = xcb_generate_id(globalconf.connection); xcb_create_window(globalconf.connection, xscreen->root_depth, globalconf.systray.window, xscreen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL); atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", globalconf.default_screen); if(!atom_name) fatal("error getting systray atom name"); atom_systray_q = xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(atom_name), atom_name); p_delete(&atom_name); atom_systray_r = xcb_intern_atom_reply(globalconf.connection, atom_systray_q, NULL); if(!atom_systray_r) fatal("error getting systray atom"); globalconf.systray.atom = atom_systray_r->atom; p_delete(&atom_systray_r); }
/** Remove systray information in X. * \param phys_screen Physical screen. */ void systray_cleanup(int phys_screen) { xcb_intern_atom_reply_t *atom_systray_r; char *atom_name; if(!globalconf.screens.tab[phys_screen].systray.registered) return; globalconf.screens.tab[phys_screen].systray.registered = false; if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen)) || !(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(atom_name), atom_name), NULL))) { warn("error getting systray atom"); p_delete(&atom_name); return; } p_delete(&atom_name); xcb_set_selection_owner(globalconf.connection, XCB_NONE, atom_systray_r->atom, XCB_CURRENT_TIME); p_delete(&atom_systray_r); }
static gboolean internal_format(CustomCellRendererFlexi *cr, const a_string_t *a_src, int limit) { int len_src = a_strlen(a_src); const char *src = a_strval(a_src); cr->rendered_type = RENDER_TEXT; cr->rendered_value = a_strnew(NULL); if (src==NULL || len_src<2) return FALSE; switch (src[0]) { case '8': case '4': case '1': internal_format_raw(cr->rendered_value,len_src,src,limit); break; case 't': internal_format_alt(cr->rendered_value,len_src,src); break; default: return internal_render_error(cr,"Internal format error."); } return TRUE; }
/** Initialize systray information in X. * \param phys_screen Physical screen. */ void systray_init(int phys_screen) { xcb_client_message_event_t ev; xcb_screen_t *xscreen = xutil_screen_get(globalconf.connection, phys_screen); char *atom_name; xcb_intern_atom_cookie_t atom_systray_q; xcb_intern_atom_reply_t *atom_systray_r; xcb_atom_t atom_systray; /* Send requests */ if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen))) { warn("error getting systray atom"); return; } atom_systray_q = xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(atom_name), atom_name); p_delete(&atom_name); globalconf.screens[phys_screen].systray.window = xcb_generate_id(globalconf.connection); xcb_create_window(globalconf.connection, xscreen->root_depth, globalconf.screens[phys_screen].systray.window, xscreen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL); /* Fill event */ p_clear(&ev, 1); ev.response_type = XCB_CLIENT_MESSAGE; ev.window = xscreen->root; ev.format = 32; ev.type = MANAGER; ev.data.data32[0] = XCB_CURRENT_TIME; ev.data.data32[2] = globalconf.screens[phys_screen].systray.window; ev.data.data32[3] = ev.data.data32[4] = 0; if(!(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, atom_systray_q, NULL))) { warn("error getting systray atom"); return; } ev.data.data32[1] = atom_systray = atom_systray_r->atom; p_delete(&atom_systray_r); xcb_set_selection_owner(globalconf.connection, globalconf.screens[phys_screen].systray.window, atom_systray, XCB_CURRENT_TIME); xcb_send_event(globalconf.connection, false, xscreen->root, 0xFFFFFF, (char *) &ev); }
/** Register systray in X. * \param phys_screen Physical screen. */ void systray_register(int phys_screen) { xcb_client_message_event_t ev; xcb_screen_t *xscreen = xutil_screen_get(globalconf.connection, phys_screen); char *atom_name; xcb_intern_atom_cookie_t atom_systray_q; xcb_intern_atom_reply_t *atom_systray_r; xcb_atom_t atom_systray; /* Set registered even if it fails to don't try again unless forced */ if(globalconf.screens.tab[phys_screen].systray.registered) return; globalconf.screens.tab[phys_screen].systray.registered = true; /* Send requests */ if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen))) { warn("error getting systray atom"); return; } atom_systray_q = xcb_intern_atom_unchecked(globalconf.connection, false, a_strlen(atom_name), atom_name); p_delete(&atom_name); /* Fill event */ p_clear(&ev, 1); ev.response_type = XCB_CLIENT_MESSAGE; ev.window = xscreen->root; ev.format = 32; ev.type = MANAGER; ev.data.data32[0] = XCB_CURRENT_TIME; ev.data.data32[2] = globalconf.screens.tab[phys_screen].systray.window; ev.data.data32[3] = ev.data.data32[4] = 0; if(!(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, atom_systray_q, NULL))) { warn("error getting systray atom"); return; } ev.data.data32[1] = atom_systray = atom_systray_r->atom; p_delete(&atom_systray_r); xcb_set_selection_owner(globalconf.connection, globalconf.screens.tab[phys_screen].systray.window, atom_systray, XCB_CURRENT_TIME); xcb_send_event(globalconf.connection, false, xscreen->root, 0xFFFFFF, (char *) &ev); }
static gboolean internal_render_error(CustomCellRendererFlexi *cr, const char *msg) { cr->rendered_type = RENDER_TEXT; cr->rendered_value = a_strnew("<span foreground='#7F0000'>Error: "); a_strcat(cr->rendered_value,msg); a_strcat(cr->rendered_value,"</span>"); if (a_strlen(cr->mime_type)>2) log_printf(LOG_WARNING,"Rendering error for '%s' mime-type: %s",a_strval(cr->mime_type)+2,msg); else log_printf(LOG_WARNING,"Rendering error: %s",msg); return FALSE; }
/** \brief safe strcpy. * * Copies at most <tt>n-1</tt> characters from \c src into \c dst, always * adding a final \c \\0 in \c dst. * * \param[in] dst destination buffer. * \param[in] n size of the buffer. Negative sizes are allowed. * \param[in] src source string. * \return \c src \e length. If this value is \>= \c n then the copy was * truncated. */ ssize_t a_strcpy(char *dst, ssize_t n, const char *src) { ssize_t len = a_strlen(src); if (n > 0) { ssize_t dlen = MIN(n - 1, len); memcpy(dst, src, dlen); dst[dlen] = '\0'; } return len; }
/** Load a configuration file. * \param xdg An xdg handle to use to get XDG basedir. * \param confpatharg The configuration file to load. * \param run Run the configuration file. */ bool luaA_parserc(xdgHandle* xdg, const char *confpatharg, bool run) { char *confpath = NULL; bool ret = false; /* try to load, return if it's ok */ if(confpatharg) { if(luaA_loadrc(confpatharg, run)) { ret = true; goto bailout; } else if(!run) goto bailout; } confpath = xdgConfigFind("awesome/rc.lua", xdg); char *tmp = confpath; /* confpath is "string1\0string2\0string3\0\0" */ while(*tmp) { if(luaA_loadrc(tmp, run)) { ret = true; goto bailout; } else if(!run) goto bailout; tmp += a_strlen(tmp) + 1; } bailout: p_delete(&confpath); return ret; }
/** Hello, this is main. * \param argc Who knows. * \param argv Who knows. * \return EXIT_SUCCESS I hope. */ int main(int argc, char **argv) { char *confpath = NULL; int xfd, i, opt; ssize_t cmdlen = 1; xdgHandle xdg; bool no_argb = false; xcb_generic_event_t *event; xcb_query_tree_cookie_t tree_c; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "check", 0, NULL, 'k' }, { "no-argb", 0, NULL, 'a' }, { NULL, 0, NULL, 0 } }; /* event loop watchers */ ev_io xio = { .fd = -1 }; ev_check xcheck; ev_prepare a_refresh; ev_signal sigint; ev_signal sigterm; ev_signal sighup; /* clear the globalconf structure */ p_clear(&globalconf, 1); globalconf.keygrabber = LUA_REFNIL; globalconf.mousegrabber = LUA_REFNIL; buffer_init(&globalconf.startup_errors); /* save argv */ for(i = 0; i < argc; i++) cmdlen += a_strlen(argv[i]) + 1; awesome_argv = p_new(char, cmdlen); a_strcpy(awesome_argv, cmdlen, argv[0]); for(i = 1; i < argc; i++) { a_strcat(awesome_argv, cmdlen, " "); a_strcat(awesome_argv, cmdlen, argv[i]); } /* Text won't be printed correctly otherwise */ setlocale(LC_CTYPE, ""); /* Get XDG basedir data */ xdgInitHandle(&xdg); /* init lua */ luaA_init(&xdg); /* check args */ while((opt = getopt_long(argc, argv, "vhkc:a", long_options, NULL)) != -1) switch(opt) { case 'v': eprint_version(); break; case 'h': exit_help(EXIT_SUCCESS); break; case 'k': if(!luaA_parserc(&xdg, confpath, false)) { fprintf(stderr, "✘ Configuration file syntax error.\n"); return EXIT_FAILURE; } else { fprintf(stderr, "✔ Configuration file syntax OK.\n"); return EXIT_SUCCESS; } case 'c': if(a_strlen(optarg)) confpath = a_strdup(optarg); else fatal("-c option requires a file name"); break; case 'a': no_argb = true; break; } globalconf.loop = ev_default_loop(EVFLAG_NOSIGFD); /* register function for signals */ ev_signal_init(&sigint, exit_on_signal, SIGINT); ev_signal_init(&sigterm, exit_on_signal, SIGTERM); ev_signal_init(&sighup, restart_on_signal, SIGHUP); ev_signal_start(globalconf.loop, &sigint); ev_signal_start(globalconf.loop, &sigterm); ev_signal_start(globalconf.loop, &sighup); ev_unref(globalconf.loop); ev_unref(globalconf.loop); ev_unref(globalconf.loop); struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 }; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0); /* X stuff */ globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display"); globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen); /* FIXME The following two assignments were swapped on purpose */ if(!no_argb) globalconf.visual = a_default_visual(globalconf.screen); if(!globalconf.visual) globalconf.visual = a_argb_visual(globalconf.screen); globalconf.default_depth = a_visual_depth(globalconf.screen, globalconf.visual->visual_id); globalconf.default_cmap = globalconf.screen->default_colormap; if(globalconf.default_depth != globalconf.screen->root_depth) { // We need our own color map if we aren't using the default depth globalconf.default_cmap = xcb_generate_id(globalconf.connection); xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE, globalconf.default_cmap, globalconf.screen->root, globalconf.visual->visual_id); } /* Prefetch all the extensions we might need */ xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_xinerama_id); /* initialize dbus */ a_dbus_init(); /* Get the file descriptor corresponding to the X connection */ xfd = xcb_get_file_descriptor(globalconf.connection); ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ); ev_io_start(globalconf.loop, &xio); ev_check_init(&xcheck, &a_xcb_check_cb); ev_check_start(globalconf.loop, &xcheck); ev_unref(globalconf.loop); ev_prepare_init(&a_refresh, &a_refresh_cb); ev_prepare_start(globalconf.loop, &a_refresh); ev_unref(globalconf.loop); /* Grab server */ xcb_grab_server(globalconf.connection); /* Make sure there are no pending events. Since we didn't really do anything * at all yet, we will just discard all events which we received so far. * The above GrabServer should make sure no new events are generated. */ xcb_aux_sync(globalconf.connection); while ((event = xcb_poll_for_event(globalconf.connection)) != NULL) { /* Make sure errors are printed */ uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event); if(response_type == 0) event_handle(event); p_delete(&event); } { const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; /* This causes an error if some other window manager is running */ xcb_change_window_attributes(globalconf.connection, globalconf.screen->root, XCB_CW_EVENT_MASK, &select_input_val); } /* Need to xcb_flush to validate error handler */ xcb_aux_sync(globalconf.connection); /* Process all errors in the queue if any. There can be no events yet, so if * this function returns something, it must be an error. */ if (xcb_poll_for_event(globalconf.connection) != NULL) fatal("another window manager is already running"); /* Prefetch the maximum request length */ xcb_prefetch_maximum_request_length(globalconf.connection); /* check for xtest extension */ const xcb_query_extension_reply_t *xtest_query; xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id); globalconf.have_xtest = xtest_query->present; /* Allocate the key symbols */ globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); xcb_get_modifier_mapping_cookie_t xmapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection); /* init atom cache */ atoms_init(globalconf.connection); /* init screens information */ screen_scan(); xutil_lock_mask_get(globalconf.connection, xmapping_cookie, globalconf.keysyms, &globalconf.numlockmask, &globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.modeswitchmask); /* do this only for real screen */ ewmh_init(); systray_init(); /* init spawn (sn) */ spawn_init(); /* The default GC is just a newly created associated with a window with * depth globalconf.default_depth */ xcb_window_t tmp_win = xcb_generate_id(globalconf.connection); globalconf.gc = xcb_generate_id(globalconf.connection); xcb_create_window(globalconf.connection, globalconf.default_depth, tmp_win, globalconf.screen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, (const uint32_t []) { globalconf.screen->black_pixel, globalconf.screen->black_pixel, globalconf.default_cmap }); xcb_create_gc(globalconf.connection, globalconf.gc, tmp_win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t[]) { globalconf.screen->black_pixel, globalconf.screen->white_pixel }); xcb_destroy_window(globalconf.connection, tmp_win); /* Get the window tree associated to this screen */ tree_c = xcb_query_tree_unchecked(globalconf.connection, globalconf.screen->root); xcb_change_window_attributes(globalconf.connection, globalconf.screen->root, XCB_CW_EVENT_MASK, ROOT_WINDOW_EVENT_MASK); /* we will receive events, stop grabbing server */ xcb_ungrab_server(globalconf.connection); /* Parse and run configuration file */ if (!luaA_parserc(&xdg, confpath, true)) fatal("couldn't find any rc file"); p_delete(&confpath); xdgWipeHandle(&xdg); /* scan existing windows */ scan(tree_c); xcb_flush(globalconf.connection); /* main event loop */ ev_loop(globalconf.loop, 0); /* cleanup event loop */ ev_ref(globalconf.loop); ev_check_stop(globalconf.loop, &xcheck); ev_ref(globalconf.loop); ev_prepare_stop(globalconf.loop, &a_refresh); ev_ref(globalconf.loop); ev_io_stop(globalconf.loop, &xio); awesome_atexit(false); return EXIT_SUCCESS; }
/** Initialize the Lua VM * \param xdg An xdg handle to use to get XDG basedir. */ void luaA_init(xdgHandle* xdg) { lua_State *L; static const struct luaL_reg awesome_lib[] = { { "quit", luaA_quit }, { "exec", luaA_exec }, { "spawn", luaA_spawn }, { "restart", luaA_restart }, { "add_signal", luaA_awesome_add_signal }, { "remove_signal", luaA_awesome_remove_signal }, { "emit_signal", luaA_awesome_emit_signal }, { "__index", luaA_awesome_index }, { "__newindex", luaA_awesome_newindex }, { NULL, NULL } }; L = globalconf.L = luaL_newstate(); /* Set panic function */ lua_atpanic(L, luaA_panic); /* Set error handling function */ lualib_dofunction_on_error = luaA_dofunction_on_error; luaL_openlibs(L); luaA_fixups(L); luaA_object_setup(L); /* Export awesome lib */ luaA_openlib(L, "awesome", awesome_lib, awesome_lib); /* Export root lib */ luaL_register(L, "root", awesome_root_lib); lua_pop(L, 1); /* luaL_register() leaves the table on stack */ /* Export hooks lib */ luaL_register(L, "hooks", awesome_hooks_lib); lua_pop(L, 1); /* luaL_register() leaves the table on stack */ #ifdef WITH_DBUS /* Export D-Bus lib */ luaL_register(L, "dbus", awesome_dbus_lib); lua_pop(L, 1); /* luaL_register() leaves the table on stack */ #endif /* Export keygrabber lib */ luaL_register(L, "keygrabber", awesome_keygrabber_lib); lua_pop(L, 1); /* luaL_register() leaves the table on stack */ /* Export mousegrabber lib */ luaL_register(L, "mousegrabber", awesome_mousegrabber_lib); lua_pop(L, 1); /* luaL_register() leaves the table on stack */ /* Export screen */ luaA_openlib(L, "screen", awesome_screen_methods, awesome_screen_meta); /* Export mouse */ luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta); /* Export button */ button_class_setup(L); /* Export image */ image_class_setup(L); /* Export tag */ tag_class_setup(L); /* Export wibox */ wibox_class_setup(L); /* Export widget */ widget_class_setup(L); /* Export client */ client_class_setup(L); /* Export keys */ key_class_setup(L); /* Export timer */ timer_class_setup(L); /* init hooks */ globalconf.hooks.manage = LUA_REFNIL; globalconf.hooks.unmanage = LUA_REFNIL; globalconf.hooks.focus = LUA_REFNIL; globalconf.hooks.unfocus = LUA_REFNIL; globalconf.hooks.mouse_enter = LUA_REFNIL; globalconf.hooks.mouse_leave = LUA_REFNIL; globalconf.hooks.clients = LUA_REFNIL; globalconf.hooks.tags = LUA_REFNIL; globalconf.hooks.tagged = LUA_REFNIL; globalconf.hooks.property = LUA_REFNIL; globalconf.hooks.timer = LUA_REFNIL; globalconf.hooks.exit = LUA_REFNIL; /* add Lua search paths */ lua_getglobal(L, "package"); if (LUA_TTABLE != lua_type(L, 1)) { warn("package is not a table"); return; } lua_getfield(L, 1, "path"); if (LUA_TSTRING != lua_type(L, 2)) { warn("package.path is not a string"); lua_pop(L, 1); return; } /* add XDG_CONFIG_DIR as include path */ const char * const *xdgconfigdirs = xdgSearchableConfigDirectories(xdg); for(; *xdgconfigdirs; xdgconfigdirs++) { size_t len = a_strlen(*xdgconfigdirs); lua_pushliteral(L, ";"); lua_pushlstring(L, *xdgconfigdirs, len); lua_pushliteral(L, "/awesome/?.lua"); lua_concat(L, 3); lua_pushliteral(L, ";"); lua_pushlstring(L, *xdgconfigdirs, len); lua_pushliteral(L, "/awesome/?/init.lua"); lua_concat(L, 3); lua_concat(L, 3); /* concatenate with package.path */ } /* add Lua lib path (/usr/share/awesome/lib by default) */ lua_pushliteral(L, ";" AWESOME_LUA_LIB_PATH "/?.lua"); lua_pushliteral(L, ";" AWESOME_LUA_LIB_PATH "/?/init.lua"); lua_concat(L, 3); /* concatenate with package.path */ lua_setfield(L, 1, "path"); /* package.path = "concatenated string" */ }
/** Initialize the Lua VM * \param xdg An xdg handle to use to get XDG basedir. */ void luaA_init(xdgHandle* xdg) { lua_State *L; static const struct luaL_Reg awesome_lib[] = { { "quit", luaA_quit }, { "exec", luaA_exec }, { "spawn", luaA_spawn }, { "restart", luaA_restart }, { "connect_signal", luaA_awesome_connect_signal }, { "disconnect_signal", luaA_awesome_disconnect_signal }, { "emit_signal", luaA_awesome_emit_signal }, { "systray", luaA_systray }, { "load_image", luaA_load_image }, { "__index", luaA_awesome_index }, { NULL, NULL } }; L = globalconf.L = luaL_newstate(); /* Set panic function */ lua_atpanic(L, luaA_panic); /* Set error handling function */ lualib_dofunction_on_error = luaA_dofunction_on_error; luaL_openlibs(L); luaA_fixups(L); luaA_object_setup(L); /* Export awesome lib */ luaA_openlib(L, "awesome", awesome_lib, awesome_lib); /* Export root lib */ luaA_registerlib(L, "root", awesome_root_lib); lua_pop(L, 1); /* luaA_registerlib() leaves the table on stack */ #ifdef WITH_DBUS /* Export D-Bus lib */ luaA_registerlib(L, "dbus", awesome_dbus_lib); lua_pop(L, 1); /* luaA_registerlib() leaves the table on stack */ #endif /* Export keygrabber lib */ luaA_registerlib(L, "keygrabber", awesome_keygrabber_lib); lua_pop(L, 1); /* luaA_registerlib() leaves the table on stack */ /* Export mousegrabber lib */ luaA_registerlib(L, "mousegrabber", awesome_mousegrabber_lib); lua_pop(L, 1); /* luaA_registerlib() leaves the table on stack */ /* Export screen */ luaA_openlib(L, "screen", awesome_screen_methods, awesome_screen_meta); /* Export mouse */ luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta); /* Export button */ button_class_setup(L); /* Export tag */ tag_class_setup(L); /* Export window */ window_class_setup(L); /* Export drawable */ drawable_class_setup(L); /* Export drawin */ drawin_class_setup(L); /* Export client */ client_class_setup(L); /* Export keys */ key_class_setup(L); /* Export timer */ timer_class_setup(L); /* add Lua search paths */ lua_getglobal(L, "package"); if (LUA_TTABLE != lua_type(L, 1)) { warn("package is not a table"); return; } lua_getfield(L, 1, "path"); if (LUA_TSTRING != lua_type(L, 2)) { warn("package.path is not a string"); lua_pop(L, 1); return; } /* add XDG_CONFIG_DIR as include path */ const char * const *xdgconfigdirs = xdgSearchableConfigDirectories(xdg); for(; *xdgconfigdirs; xdgconfigdirs++) { size_t len = a_strlen(*xdgconfigdirs); lua_pushliteral(L, ";"); lua_pushlstring(L, *xdgconfigdirs, len); lua_pushliteral(L, "/awesome/?.lua"); lua_concat(L, 3); lua_pushliteral(L, ";"); lua_pushlstring(L, *xdgconfigdirs, len); lua_pushliteral(L, "/awesome/?/init.lua"); lua_concat(L, 3); lua_concat(L, 3); /* concatenate with package.path */ } /* add Lua lib path (/usr/share/awesome/lib by default) */ lua_pushliteral(L, ";" AWESOME_LUA_LIB_PATH "/?.lua"); lua_pushliteral(L, ";" AWESOME_LUA_LIB_PATH "/?/init.lua"); lua_concat(L, 3); /* concatenate with package.path */ lua_setfield(L, 1, "path"); /* package.path = "concatenated string" */ lua_getfield(L, 1, "loaded"); lua_pop(L, 2); /* pop "package" and "package.loaded" */ signal_add(&global_signals, "debug::error"); signal_add(&global_signals, "debug::deprecation"); signal_add(&global_signals, "debug::index::miss"); signal_add(&global_signals, "debug::newindex::miss"); signal_add(&global_signals, "systray::update"); signal_add(&global_signals, "wallpaper_changed"); signal_add(&global_signals, "refresh"); signal_add(&global_signals, "exit"); }
/** Hello, this is main. * \param argc Who knows. * \param argv Who knows. * \return EXIT_SUCCESS I hope. */ int main(int argc, char **argv) { char *confpath = NULL; int xfd, i, screen_nbr, opt, colors_nbr; xcolor_init_request_t colors_reqs[2]; ssize_t cmdlen = 1; xdgHandle xdg; xcb_generic_event_t *event; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "check", 0, NULL, 'k' }, { NULL, 0, NULL, 0 } }; /* event loop watchers */ ev_io xio = { .fd = -1 }; ev_check xcheck; ev_prepare a_refresh; ev_signal sigint; ev_signal sigterm; ev_signal sighup; /* clear the globalconf structure */ p_clear(&globalconf, 1); globalconf.keygrabber = LUA_REFNIL; globalconf.mousegrabber = LUA_REFNIL; buffer_init(&globalconf.startup_errors); /* save argv */ for(i = 0; i < argc; i++) cmdlen += a_strlen(argv[i]) + 1; globalconf.argv = p_new(char, cmdlen); a_strcpy(globalconf.argv, cmdlen, argv[0]); for(i = 1; i < argc; i++) { a_strcat(globalconf.argv, cmdlen, " "); a_strcat(globalconf.argv, cmdlen, argv[i]); } /* Text won't be printed correctly otherwise */ setlocale(LC_CTYPE, ""); /* Get XDG basedir data */ xdgInitHandle(&xdg); /* init lua */ luaA_init(&xdg); /* check args */ while((opt = getopt_long(argc, argv, "vhkc:", long_options, NULL)) != -1) switch(opt) { case 'v': eprint_version(); break; case 'h': exit_help(EXIT_SUCCESS); break; case 'k': if(!luaA_parserc(&xdg, confpath, false)) { fprintf(stderr, "✘ Configuration file syntax error.\n"); return EXIT_FAILURE; } else { fprintf(stderr, "✔ Configuration file syntax OK.\n"); return EXIT_SUCCESS; } case 'c': if(a_strlen(optarg)) confpath = a_strdup(optarg); else fatal("-c option requires a file name"); break; } globalconf.loop = ev_default_loop(0); ev_timer_init(&globalconf.timer, &luaA_on_timer, 0., 0.); /* register function for signals */ ev_signal_init(&sigint, exit_on_signal, SIGINT); ev_signal_init(&sigterm, exit_on_signal, SIGTERM); ev_signal_init(&sighup, restart_on_signal, SIGHUP); ev_signal_start(globalconf.loop, &sigint); ev_signal_start(globalconf.loop, &sigterm); ev_signal_start(globalconf.loop, &sighup); ev_unref(globalconf.loop); ev_unref(globalconf.loop); ev_unref(globalconf.loop); struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 }; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0); /* XLib sucks */ XkbIgnoreExtension(True); /* X stuff */ globalconf.display = XOpenDisplay(NULL); if (globalconf.display == NULL) fatal("cannot open display"); globalconf.default_screen = XDefaultScreen(globalconf.display); globalconf.connection = XGetXCBConnection(globalconf.display); /* Double checking then everything is OK. */ if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display"); /* Prefetch all the extensions we might need */ xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_shape_id); /* initialize dbus */ a_dbus_init(); /* Get the file descriptor corresponding to the X connection */ xfd = xcb_get_file_descriptor(globalconf.connection); ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ); ev_io_start(globalconf.loop, &xio); ev_check_init(&xcheck, &a_xcb_check_cb); ev_check_start(globalconf.loop, &xcheck); ev_unref(globalconf.loop); ev_prepare_init(&a_refresh, &a_refresh_cb); ev_prepare_start(globalconf.loop, &a_refresh); ev_unref(globalconf.loop); /* Grab server */ xcb_grab_server(globalconf.connection); /* Make sure there are no pending events. Since we didn't really do anything * at all yet, we will just discard all events which we received so far. * The above GrabServer should make sure no new events are generated. */ xcb_aux_sync(globalconf.connection); while ((event = xcb_poll_for_event(globalconf.connection)) != NULL) { /* Make sure errors are printed */ uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event); if(response_type == 0) event_handle(event); p_delete(&event); } for(screen_nbr = 0; screen_nbr < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); screen_nbr++) { const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; /* This causes an error if some other window manager is running */ xcb_change_window_attributes(globalconf.connection, xutil_screen_get(globalconf.connection, screen_nbr)->root, XCB_CW_EVENT_MASK, &select_input_val); } /* Need to xcb_flush to validate error handler */ xcb_aux_sync(globalconf.connection); /* Process all errors in the queue if any. There can be no events yet, so if * this function returns something, it must be an error. */ if (xcb_poll_for_event(globalconf.connection) != NULL) fatal("another window manager is already running"); /* Prefetch the maximum request length */ xcb_prefetch_maximum_request_length(globalconf.connection); /* check for xtest extension */ const xcb_query_extension_reply_t *xtest_query; xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id); globalconf.have_xtest = xtest_query->present; /* Allocate the key symbols */ globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); xcb_get_modifier_mapping_cookie_t xmapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection); /* init atom cache */ atoms_init(globalconf.connection); /* init screens information */ screen_scan(); /* init default font and colors */ colors_reqs[0] = xcolor_init_unchecked(&globalconf.colors.fg, "black", sizeof("black") - 1); colors_reqs[1] = xcolor_init_unchecked(&globalconf.colors.bg, "white", sizeof("white") - 1); globalconf.font = draw_font_new("sans 8"); for(colors_nbr = 0; colors_nbr < 2; colors_nbr++) xcolor_init_reply(colors_reqs[colors_nbr]); xutil_lock_mask_get(globalconf.connection, xmapping_cookie, globalconf.keysyms, &globalconf.numlockmask, &globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.modeswitchmask); /* Get the window tree associated to this screen */ const int screen_max = xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); xcb_query_tree_cookie_t tree_c[screen_max]; /* do this only for real screen */ for(screen_nbr = 0; screen_nbr < screen_max; screen_nbr++) { /* select for events */ const uint32_t change_win_vals[] = { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_FOCUS_CHANGE }; tree_c[screen_nbr] = xcb_query_tree_unchecked(globalconf.connection, xutil_screen_get(globalconf.connection, screen_nbr)->root); xcb_change_window_attributes(globalconf.connection, xutil_screen_get(globalconf.connection, screen_nbr)->root, XCB_CW_EVENT_MASK, change_win_vals); ewmh_init(screen_nbr); systray_init(screen_nbr); } /* init spawn (sn) */ spawn_init(); /* we will receive events, stop grabbing server */ xcb_ungrab_server(globalconf.connection); /* Parse and run configuration file */ if (!luaA_parserc(&xdg, confpath, true)) fatal("couldn't find any rc file"); scan(tree_c); xcb_flush(globalconf.connection); /* main event loop */ ev_loop(globalconf.loop, 0); /* cleanup event loop */ ev_ref(globalconf.loop); ev_check_stop(globalconf.loop, &xcheck); ev_ref(globalconf.loop); ev_prepare_stop(globalconf.loop, &a_refresh); ev_ref(globalconf.loop); ev_io_stop(globalconf.loop, &xio); awesome_atexit(false); return EXIT_SUCCESS; }
int cardpeek_update_perform(void) { const char* cardpeek_update_file = path_config_get_string(PATH_CONFIG_FILE_CARDPEEK_UPDATE); a_string_t *contents; update_t *update; int remove; update_item_t *item; time_t now = time(NULL); int updated = 0; char *url = NULL; char *local_file; char *local_dnld; unsigned char digest[SHA256_DIGEST_LENGTH]; a_string_t *url_request; unsigned first_update; first_update = (unsigned)luax_variable_get_integer("cardpeek.updates.first_update"); /* STEP 1: get cardpeek.update file */ url=luax_variable_get_strdup("cardpeek.updates.url"); if (url==NULL) url = g_strdup(DEFAULT_UPDATE_URL); log_printf(LOG_INFO,"Fetching '%s'",url); url_request = a_strnew(NULL); a_sprintf(url_request,"%s?u=%x&v=%s",url,first_update,VERSION); if (http_download(a_strval(url_request),cardpeek_update_file)==0) { g_free(url); return 0; } g_free(url); a_strfree(url_request); /* STEP 2: parse file */ if ((contents=file_get_contents(cardpeek_update_file))==NULL) { log_printf(LOG_ERROR,"failed to read update file information."); unlink(cardpeek_update_file); return 0; } update = update_new(); if ((update_load(update,a_strval(contents),a_strlen(contents)))==0) { unlink(cardpeek_update_file); a_strfree(contents); update_free(update); return 0; } a_strfree(contents); /* log_printf(LOG_DEBUG,"Updates correctly loaded from '%s'",cardpeek_update_file); */ if ((remove = update_filter_version(update,VERSION))>0) log_printf(LOG_WARNING,"%d updates will not be installed because they require a newer version of Cardpeek."); remove = update_filter_files(update); if (update->item_count) log_printf(LOG_INFO,"A total of %d files will be updated, %d files are kept unchanged.",update->item_count,remove); else log_printf(LOG_INFO,"No files will be updated, %d files are kept unchanged.",remove); item = update->items; while (item) { local_dnld = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,".download"); local_file = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,NULL); if (http_download(item->url,local_dnld)!=0) { if (sha256sum(local_dnld,digest)) { if (memcmp(digest,bytestring_get_data(&item->digest),SHA256_DIGEST_LENGTH)==0) { unlink(local_file); if (rename(local_dnld,local_file)==0) { log_printf(LOG_INFO,"Successfuly updated %s", local_file); updated++; } else { log_printf(LOG_ERROR,"Failed to copy %s to %s: %s", local_dnld, local_file, strerror(errno)); } } else { log_printf(LOG_WARNING,"File %s was not updated: authentication failed.",local_file); } } unlink(local_dnld); } g_free(local_dnld); g_free(local_file); item = item->next; } if (updated == update->item_count) { luax_variable_set_integer("cardpeek.updates.next_update",(int)(now+7*(24*3600))); luax_config_table_save(); } unlink(cardpeek_update_file); update_free(update); /* STEP 3: finish */ return 1; }
/** The property notify event handler handling xproperties. * \param ev The event. */ static void property_handle_propertynotify_xproperty(xcb_property_notify_event_t *ev) { xproperty_t *prop; xproperty_t lookup = { .atom = ev->atom }; buffer_t buf; void *obj; prop = xproperty_array_lookup(&globalconf.xproperties, &lookup); if(!prop) /* Property is not registered */ return; if (ev->window != globalconf.screen->root) { obj = client_getbywin(ev->window); if(!obj) obj = drawin_getbywin(ev->window); if(!obj) return; } else obj = NULL; /* Get us the name of the property */ buffer_inita(&buf, a_strlen(prop->name) + a_strlen("xproperty::") + 1); buffer_addf(&buf, "xproperty::%s", prop->name); /* And emit the right signal */ if (obj) { luaA_object_push(globalconf.L, obj); luaA_object_emit_signal(globalconf.L, -1, buf.s, 0); lua_pop(globalconf.L, 1); } else signal_object_emit(globalconf.L, &global_signals, buf.s, 0); buffer_wipe(&buf); } /** The property notify event handler. * \param ev The event. */ void property_handle_propertynotify(xcb_property_notify_event_t *ev) { int (*handler)(uint8_t state, xcb_window_t window) = NULL; globalconf.timestamp = ev->time; property_handle_propertynotify_xproperty(ev); /* Find the correct event handler */ #define HANDLE(atom_, cb) \ if (ev->atom == atom_) \ { \ handler = cb; \ } else #define END return /* Xembed stuff */ HANDLE(_XEMBED_INFO, property_handle_xembed_info) /* ICCCM stuff */ HANDLE(XCB_ATOM_WM_TRANSIENT_FOR, property_handle_wm_transient_for) HANDLE(WM_CLIENT_LEADER, property_handle_wm_client_leader) HANDLE(XCB_ATOM_WM_NORMAL_HINTS, property_handle_wm_normal_hints) HANDLE(XCB_ATOM_WM_HINTS, property_handle_wm_hints) HANDLE(XCB_ATOM_WM_NAME, property_handle_wm_name) HANDLE(XCB_ATOM_WM_ICON_NAME, property_handle_wm_icon_name) HANDLE(XCB_ATOM_WM_CLASS, property_handle_wm_class) HANDLE(WM_PROTOCOLS, property_handle_wm_protocols) HANDLE(XCB_ATOM_WM_CLIENT_MACHINE, property_handle_wm_client_machine) HANDLE(WM_WINDOW_ROLE, property_handle_wm_window_role) /* EWMH stuff */ HANDLE(_NET_WM_NAME, property_handle_net_wm_name) HANDLE(_NET_WM_ICON_NAME, property_handle_net_wm_icon_name) HANDLE(_NET_WM_STRUT_PARTIAL, property_handle_net_wm_strut_partial) HANDLE(_NET_WM_ICON, property_handle_net_wm_icon) HANDLE(_NET_WM_PID, property_handle_net_wm_pid) HANDLE(_NET_WM_WINDOW_OPACITY, property_handle_net_wm_opacity) /* background change */ HANDLE(_XROOTPMAP_ID, property_handle_xrootpmap_id) /* If nothing was found, return */ END; #undef HANDLE #undef END (*handler)(ev->state, ev->window); }