diff --git a/.gitignore b/.gitignore index fa167b7a..6dc2fb44 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ awesome awesome-client doc *.swp -defconfig.h .deps .dirstamp configure @@ -16,16 +15,10 @@ aclocal.m4 autom4te.cache awesome.doxygen awesome-client.1 -awesome-message.1 awesome-menu.1 awesome.1 awesomerc.5 -awesomerc +awesomerc.lua widgetgen.h layoutgen.h awesome-version-internal.h -awesome-message -awesome-menu -uicbdocgen.txt -optsdocgen.txt -rcskeletongen.txt diff --git a/Makefile.am b/Makefile.am index 1bda0c11..18869dc0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,6 +9,8 @@ iconsdir = $(pkgdatadir)/icons dist_icons_DATA = iconslayoutsdir = $(iconsdir)/layouts dist_iconslayouts_DATA = +awfuldir = $(pkgdatadir)/lib +dist_awful_DATA = LAYOUTS = @@ -27,10 +29,8 @@ LAYOUTS += layouts/fibonacci.h WIDGETS = WIDGETS += widgets/taglist.c -WIDGETS += widgets/layoutinfo.c WIDGETS += widgets/textbox.c WIDGETS += widgets/iconbox.c -WIDGETS += widgets/focusicon.c WIDGETS += widgets/progressbar.c WIDGETS += widgets/tasklist.c WIDGETS += widgets/graph.c @@ -39,32 +39,22 @@ WIDGETS += widgets/common.c widgets/common.h doc_DATA += README -doc_DATA += UPGRADE -EXTRA_DIST += UPGRADE - EXTRA_DIST += LICENSE -EXTRA_DIST += UPGRADE EXTRA_DIST += STYLE doc_DATA += STYLE -EXTRA_DIST += awesomerc.in -CLEANFILES += awesomerc -BUILT_SOURCES += awesomerc -doc_DATA += awesomerc -awesomerc: $(srcdir)/awesomerc.in - $(SED) -e "s|[@]iconslayoutsdir@|$(iconslayoutsdir)|;s|[@]iconsdir@|$(iconsdir)|" \ - < $(srcdir)/awesomerc.in > awesomerc +EXTRA_DIST += awful.lua +dist_awful_DATA += awful.lua -CLEANFILES += defconfig.h -BUILT_SOURCES += defconfig.h -defconfig.h: awesomerc - @echo "generating defconfig.h from awesomerc" - @echo "static const char *AWESOME_DEFAULT_CONFIG = " > defconfig.h - @echo -n "\"" >> defconfig.h - @$(SED) 's,\\,\\\\,g;s/$$/\\n\\/;s/"/\\"/g' "awesomerc" >> defconfig.h - @echo "\";" >> defconfig.h +EXTRA_DIST += awesomerc.lua.in +CLEANFILES += awesomerc.lua +BUILT_SOURCES += awesomerc.lua +doc_DATA += awesomerc.lua +awesomerc.lua: $(srcdir)/awesomerc.lua.in + $(SED) -e "s|[@]iconslayoutsdir@|$(iconslayoutsdir)|;s|[@]iconsdir@|$(iconsdir)|" \ + < $(srcdir)/awesomerc.lua.in > awesomerc.lua CLEANFILES += layoutgen.h BUILT_SOURCES += layoutgen.h @@ -102,12 +92,12 @@ AWESOME_CFLAGS = -std=gnu99 -pipe \ -Wunused -Winit-self -Wpointer-arith -Wredundant-decls \ -Wmissing-prototypes -Wmissing-format-attribute -Wmissing-noreturn endif -AM_CPPFLAGS = $(pangocairo_CFLAGS) $(confuse_CFLAGS) $(AWESOME_CFLAGS) \ +AM_CPPFLAGS = $(pangocairo_CFLAGS) $(AWESOME_CFLAGS) \ $(GTK_CFLAGS) $(imlib2_CFLAGS) \ $(xcb_CFLAGS) $(xcb_event_CFLAGS) \ $(xcb_randr_CFLAGS) $(xcb_xinerama_CFLAGS) $(xcb_shape_CFLAGS) \ $(xcb_aux_CFLAGS) $(xcb_atom_CFLAGS) $(xcb_keysyms_CFLAGS) \ - $(xcb_icccm_CFLAGS) $(dbus_CFLAGS) + $(xcb_icccm_CFLAGS) $(dbus_CFLAGS) $(Lua_CFLAGS) bin_PROGRAMS += awesome awesome_SOURCES = \ @@ -120,7 +110,7 @@ awesome_SOURCES = \ common/xscreen.h common/xscreen.c \ common/draw.c common/draw.h \ common/markup.c common/markup.h \ - common/list.h \ + common/list.h common/refcount.h \ structs.h \ client.c client.h \ titlebar.c titlebar.h \ @@ -128,24 +118,22 @@ awesome_SOURCES = \ focus.c focus.h \ event.c event.h \ layout.c layout.h \ - awesome.c awesome.h \ + awesome.c \ tag.c tag.h \ - config.c config.h \ + lua.c lua.h \ screen.c screen.h \ statusbar.c statusbar.h \ - uicb.c uicb.h \ window.c window.h \ - rules.c rules.h \ mouse.c mouse.h \ widget.c widget.h \ ewmh.c ewmh.h \ dbus.c dbus.h awesome_SOURCES += $(LAYOUTS) awesome_SOURCES += $(WIDGETS) -awesome_LDADD = $(pangocairo_LIBS) $(confuse_LIBS) $(xcb_LIBS) $(xcb_event_LIBS) \ +awesome_LDADD = $(pangocairo_LIBS) $(xcb_LIBS) $(xcb_event_LIBS) \ $(xcb_randr_LIBS) $(xcb_xinerama_LIBS) $(xcb_shape_LIBS) $(xcb_aux_LIBS) \ $(xcb_atom_LIBS) $(xcb_keysyms_LIBS) $(xcb_icccm_LIBS) $(dbus_LIBS)\ - $(imlib2_LIBS) $(GTK_LIBS) + $(imlib2_LIBS) $(GTK_LIBS) $(Lua_LIBS) bin_PROGRAMS += awesome-client awesome_client_SOURCES = \ @@ -153,41 +141,13 @@ awesome_client_SOURCES = \ common/socket.c common/socket.h \ common/version.c common/version.h \ common/util.c common/util.h - -bin_PROGRAMS += awesome-message -awesome_message_SOURCES = \ - common/swindow.c common/swindow.h \ - common/draw.c common/draw.h \ - common/markup.c common/markup.h \ - common/util.h common/util.c \ - common/version.h common/version.c \ - common/configopts.h common/configopts.c \ - common/xscreen.h common/xscreen.c \ - common/xutil.h common/xutil.c \ - awesome-message.c -awesome_message_LDADD = $(xcb_LIBS) $(xcb_atom_LIBS) $(xcb_keysyms_LIBS) $(xcb_aux_LIBS) \ - $(pangocairo_LIBS) $(confuse_LIBS) $(xcb_xinerama_LIBS) $(xcb_event_LIBS) $(imlib2_LIBS) $(GTK_LIBS) - -bin_PROGRAMS += awesome-menu -awesome_menu_SOURCES = \ - common/swindow.c common/swindow.h \ - common/draw.c common/draw.h \ - common/markup.c common/markup.h \ - common/util.h common/util.c \ - common/version.h common/version.c \ - common/configopts.h common/configopts.c \ - common/xutil.h common/xutil.c \ - awesome-menu.c -awesome_menu_LDADD = $(xcb_LIBS) $(xcb_atom_LIBS) $(xcb_keysyms_LIBS) $(xcb_aux_LIBS) \ - $(pangocairo_LIBS) $(confuse_LIBS) $(xcb_xinerama_LIBS) $(xcb_event_LIBS) $(imlib2_LIBS) $(GTK_LIBS) +awesome_client_LDADD = -lreadline if HAVE_XMLTO if HAVE_ASCIIDOC if XMLTO_MAN_WORKS man_MANS += awesome.1 man_MANS += awesome-client.1 -man_MANS += awesome-message.1 -man_MANS += awesome-menu.1 man_MANS += awesomerc.5 endif endif @@ -195,8 +155,6 @@ endif EXTRA_DIST += awesome.1.txt EXTRA_DIST += awesome-client.1.txt -EXTRA_DIST += awesome-message.1.txt -EXTRA_DIST += awesome-menu.1.txt EXTRA_DIST += awesomerc.5.txt dist_icons_DATA += icons/awesome16.png @@ -221,13 +179,10 @@ dist_iconslayouts_DATA += icons/layouts/tiletopw.png dist_iconslayouts_DATA += icons/layouts/tilew.png clean-local: - rm -f awesome*.1 awesome*.1.xml awesome*.5 awesome*.5.xml optsdocgen.txt uicbdocgen.txt + rm -f awesome*.1 awesome*.1.xml awesome*.5 awesome*.5.xml SUFFIXES += .1.xml .1 SUFFIXES += .5.xml .5 -EXTRA_DIST += build-utils/extractuicbdoc.py -EXTRA_DIST += build-utils/extractoptsdoc.py -EXTRA_DIST += build-utils/extractrcskeleton.py if HAVE_XMLTO .1.xml.1: $(XMLTO) man $< @@ -238,26 +193,12 @@ endif SUFFIXES += .1.txt .1.xml SUFFIXES += .5.txt .5.xml if HAVE_ASCIIDOC -if HAVE_PYTHON -CLEANFILES += optsdocgen.txt -CLEANFILES += rcskeletongen.txt -CLEANFILES += uicbdocgen.txt -optsdocgen.txt: common/configopts.c - $(PYTHON) $(top_srcdir)/build-utils/extractoptsdoc.py \ - $(top_srcdir)/common/configopts.c > optsdocgen.txt -rcskeletongen.txt: common/configopts.c - $(PYTHON) $(top_srcdir)/build-utils/extractrcskeleton.py \ - $(top_srcdir)/common/configopts.c > rcskeletongen.txt -uicbdocgen.txt: $(awesome_SOURCES) - $(PYTHON) $(top_srcdir)/build-utils/extractuicbdoc.py \ - $(top_srcdir)/*.c > uicbdocgen.txt .1.txt.1.xml: $(ASCIIDOC) -d manpage -b docbook -o $@ $< -awesomerc.5.xml: optsdocgen.txt rcskeletongen.txt uicbdocgen.txt +awesomerc.5.xml: .5.txt.5.xml: $(ASCIIDOC) -d manpage -b docbook -o $@ $< endif -endif # Check that package version matches git version before creating dist tarballs diff --git a/README b/README index c0cec605..5af4d353 100644 --- a/README +++ b/README @@ -5,8 +5,8 @@ awesome is an extremely fast, small, and dynamic window manager for X. Requirements ------------ In order to build awesome itself, you need header files and libs of: - - Xlib, Xinerama, Xrandr - - libconfuse >= 2.6 + - Xlib, xcb and xcb-util. + - Lua 5.1 - cairo - pango and pangocairo - glib @@ -57,5 +57,5 @@ the DISPLAY environment variable is set correctly, e.g.: Configuration ------------- -The configuration of awesome is done by creating a ~/.awesomerc file. +The configuration of awesome is done by creating a ~/.awesomerc.lua file. An example is provided in the sources. diff --git a/UPGRADE b/UPGRADE deleted file mode 100644 index 2cca3ade..00000000 --- a/UPGRADE +++ /dev/null @@ -1 +0,0 @@ -Run awesome -k to check your configuration file syntax. diff --git a/as_ac_expand.m4 b/as_ac_expand.m4 new file mode 100644 index 00000000..7355c7d7 --- /dev/null +++ b/as_ac_expand.m4 @@ -0,0 +1,44 @@ +dnl as-ac-expand.m4 0.2.0 +dnl dnl autostars m4 macro for expanding directories using configure's prefix +dnl dnl thomas@apestaart.org +dnl +dnl dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) +dnl dnl example +dnl dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +dnl dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local +dnl +AC_DEFUN([AS_AC_EXPAND], +[ + EXP_VAR=[$1] + FROM_VAR=[$2] + + dnl first expand prefix and exec_prefix if necessary + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + dnl if no prefix given, then use /usr/local, the default prefix + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + dnl if no exec_prefix given, then use prefix + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + dnl loop until it doesn't change anymore + while true; do + new_full_var="`eval echo $full_var`" + if test "x$new_full_var" = "x$full_var"; then break; fi + full_var=$new_full_var + done + + dnl clean up + full_var=$new_full_var + AC_SUBST([$1], "$full_var") + + dnl restore prefix and exec_prefix + prefix=$prefix_save + exec_prefix=$exec_prefix_save +]) + diff --git a/awesome-client.c b/awesome-client.c index 31601cf2..80de4d42 100644 --- a/awesome-client.c +++ b/awesome-client.c @@ -20,12 +20,18 @@ * */ +#define _GNU_SOURCE + #include #include #include #include #include +#include +#include +#include + #include "common/socket.h" #include "common/version.h" #include "common/util.h" @@ -41,7 +47,7 @@ * \return errno of sendto() */ static int -send_msg(char *msg, ssize_t msg_len) +send_msg(const char *msg, ssize_t msg_len) { struct sockaddr_un *addr; int csfd, ret_value = EXIT_SUCCESS; @@ -94,52 +100,59 @@ exit_help(int exit_code) int main(int argc, char **argv) { - char buf[1024], *msg; + char buf[1024], *msg, *prompt; int ret_value = EXIT_SUCCESS; ssize_t len, msg_len = 1; - if (argc < 2) - { - /* no args to parse, nothing to do */ - } - else if (argc == 2) + if(argc == 2) { if(!a_strcmp("-v", argv[1]) || !a_strcmp("--version", argv[1])) eprint_version("awesome-client"); else if(!a_strcmp("-h", argv[1]) || !a_strcmp("--help", argv[1])) exit_help(EXIT_SUCCESS); } + else if(argc > 2) + exit_help(EXIT_SUCCESS); + + if(isatty(STDIN_FILENO)) + { + asprintf(&prompt, "awesome@%s%% ", getenv("DISPLAY")); + while((msg = readline(prompt))) + if((msg_len = a_strlen(msg))) + { + p_realloc(&msg, msg_len + 2); + msg[msg_len] = '\n'; + msg[msg_len + 1] = '\0'; + send_msg(msg, msg_len + 2); + } + } else { - exit_help(EXIT_SUCCESS); - } - - msg = p_new(char, 1); - while(fgets(buf, sizeof(buf), stdin)) - { - len = a_strlen(buf); - if (len < 2 && msg_len > 1) + msg = p_new(char, 1); + while(fgets(buf, sizeof(buf), stdin)) { + len = a_strlen(buf); + if(len < 2 && msg_len > 1) + { + ret_value = send_msg(msg, msg_len); + p_delete(&msg); + if (ret_value != EXIT_SUCCESS) + return ret_value; + msg = p_new(char, 1); + msg_len = 1; + } + else if (len > 1) + { + msg_len += len; + p_realloc(&msg, msg_len); + a_strncat(msg, msg_len, buf, len); + } + } + if(msg_len > 1) ret_value = send_msg(msg, msg_len); - p_delete(&msg); - if (ret_value != EXIT_SUCCESS) - return ret_value; - msg = p_new(char, 1); - msg_len = 1; - } - else if (len > 1) - { - msg_len += len; - p_realloc(&msg, msg_len); - a_strncat(msg, msg_len, buf, len); - } + p_delete(&msg); } - if (msg_len > 1) - ret_value = send_msg(msg, msg_len); - - p_delete(&msg); - return ret_value; } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/awesome-menu.1.txt b/awesome-menu.1.txt deleted file mode 100644 index 15085d7d..00000000 --- a/awesome-menu.1.txt +++ /dev/null @@ -1,62 +0,0 @@ -awesome-menu(1) -================= - -NAME ----- - -awesome-menu - awesome menu system - -SYNOPSIS --------- - -awesome-menu [-c config] [-e command] - -DESCRIPTION ------------ - -awesome-menu is a tool which will pop up a menu on your screen, grabbing -keyboard and allowing you to search through an initial completion list, or -using your files as completion. - -USAGE ------ -By default, awesome-menu reads completion from standard input. If nothing is -read, the completion list is built from the current working directory files. - -To build a menu with all the executable files of /usr/bin: - - ls /usr/bin | awesome-menu -e 'exec ' 'Execute' - -To build the same menu and run the programs in a terminal window: - - ls /usr/bin | awesome-menu -e 'xterm -e exec ' 'Execute in terminal' - -To build an ssh connection prompt: - - cut -d' ' -f1 ~/.ssh/known_hosts | cut -d, -f1 | awesome-menu -e 'xterm -e ssh ' 'ssh to:' - -If you do not specify the -e option, the result will be sent to standard output. -You can do things like that: - - gzip "$(awesome-menu '"File to gzip')" - -OPTIONS -------- --c config:: - Use an alternate configuration file instead of $HOME/.awesomerc. --e command:: - Command to execute. The result is appended to the end of this command (like xargs). -<title>:: - Print this title. This is also used to identify the menu section in the awesomerc file. - -SEE ALSO --------- -awesome(1) awesomerc(5) - -AUTHORS -------- -Julien Danjou <julien@danjou.info> - -WWW ---- -http://awesome.naquadah.org diff --git a/awesome-menu.c b/awesome-menu.c deleted file mode 100644 index 2daa6671..00000000 --- a/awesome-menu.c +++ /dev/null @@ -1,1411 +0,0 @@ -/* - * awesome-menu.c - menu window for awesome - * - * Copyright © 2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/* asprintf() */ -#define _GNU_SOURCE - -#define CHUNK_SIZE 4096 - -#include <getopt.h> - -#include <signal.h> -#include <unistd.h> -#include <stdlib.h> -#include <dirent.h> -#include <pwd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <string.h> -#include <errno.h> - -#include <xcb/xcb.h> -#include <xcb/xcb_atom.h> -#include <xcb/xcb_keysyms.h> - -#include "common/swindow.h" -#include "common/util.h" -#include "common/version.h" -#include "common/configopts.h" -#include "common/xutil.h" -#include "common/xscreen.c" - -#define PROGNAME "awesome-menu" - -#define CLEANMASK(mask) (mask & ~(globalconf.numlockmask | XCB_MOD_MASK_LOCK)) - -/** awesome-menu run status */ -typedef enum -{ - /** Stop awesome-menu */ - STOP = 0, - /** Run awesome-menu */ - RUN = 1, - /** Stop awesome-menu and cancel any operation */ - CANCEL = 2 -} status_t; - -/** Is awesome-menu running ? */ -static status_t status = RUN; - -/** Import awesome config file format */ -extern cfg_opt_t awesome_opts[]; - -/** Item_t typedef */ -typedef struct item_t item_t; -/** Item_t structure */ -struct item_t -{ - /** Data */ - char *data; - /** Previous and next elems in item_t list */ - item_t *prev, *next; - /** True if the item currently matches */ - bool match; -}; - -/** Destructor for item structure - * \param item item pointer - */ -static void -item_delete(item_t **item) -{ - p_delete(&(*item)->data); - p_delete(item); -} - -DO_SLIST(item_t, item, item_delete) - -/** awesome-run global configuration structure */ -typedef struct -{ - /** Connection ref */ - xcb_connection_t *connection; - /** Default screen number */ - int default_screen; - /** The window */ - simple_window_t *sw; - /** The draw contet */ - draw_context_t *ctx; - /** Colors */ - struct - { - style_t normal; - style_t focus; - } styles; - /** Key symbols */ - xcb_key_symbols_t *keysyms; - /** Numlock mask */ - unsigned int numlockmask; - /** Shiftlock mask */ - unsigned int shiftlockmask; - /** Capslock mask */ - unsigned int capslockmask; - /** The text */ - char *text; - /** The text when we asked to complete */ - char *text_complete; - /** The text length */ - size_t text_size; - /** Item list */ - item_t *items; - /** Selected item */ - item_t *item_selected; - /** What to do with the result text */ - char *exec; - /** Prompt */ - char *prompt; -} AwesomeMenuConf; - -static AwesomeMenuConf globalconf; - -/** Exit with given exit code - * \param exit_code exit code - * \return never returns - */ -static void __attribute__ ((noreturn)) -exit_help(int exit_code) -{ - FILE *outfile = (exit_code == EXIT_SUCCESS) ? stdout : stderr; - fprintf(outfile, "Usage: %s [-c config] [-e command] <message>\n", - PROGNAME); - exit(exit_code); -} - -/** Parse configuration file and fill up AwesomeMenuConf - * data structures with configuration directives. - * \param screen screen number - * \param confpatharg configuration file pathname, or NULL if auto - * \param menu_title menu title - * \param geometry geometry to fill up with supplied information from - * configuration file - * \return cfg_parse status - */ -static int -config_parse(int screen, const char *confpatharg, - const char *menu_title, area_t *geometry) -{ - int ret, i; - char *confpath; - cfg_t *cfg, *cfg_menu = NULL, *cfg_screen = NULL, - *cfg_styles, *cfg_menu_styles = NULL; - - if(!confpatharg) - confpath = config_file(); - else - confpath = a_strdup(confpatharg); - - cfg = cfg_new(); - - switch((ret = cfg_parse(cfg, confpath))) - { - case CFG_FILE_ERROR: - warn("parsing configuration file failed: %s\n", strerror(errno)); - break; - case CFG_PARSE_ERROR: - cfg_error(cfg, "W: awesome: parsing configuration file %s failed.\n", confpath); - break; - } - - if(ret) - return ret; - - if(menu_title && !(cfg_menu = cfg_gettsec(cfg, "menu", menu_title))) - warn("no definition for menu %s in configuration file: using default\n", - menu_title); - - /* get global screen section */ - if(!(cfg_screen = cfg_getnsec(cfg, "screen", screen))) - cfg_screen = cfg_getsec(cfg, "screen"); - - if(cfg_menu) - { - cfg_menu_styles = cfg_getsec(cfg_menu, "styles"); - if((i = cfg_getint(cfg_menu, "x")) != (int) 0xffffffff) - geometry->x = i; - if((i = cfg_getint(cfg_menu, "y")) != (int) 0xffffffff) - geometry->y = i; - if((i = cfg_getint(cfg_menu, "width")) > 0) - geometry->width = i; - if((i = cfg_getint(cfg_menu, "height")) > 0) - geometry->height = i; - } - - if(cfg_screen - && (cfg_styles = cfg_getsec(cfg_screen, "styles"))) - { - /* Grab default styles */ - draw_style_init(globalconf.connection, globalconf.default_screen, - cfg_getsec(cfg_styles, "normal"), - &globalconf.styles.normal, NULL); - - draw_style_init(globalconf.connection, globalconf.default_screen, - cfg_getsec(cfg_styles, "focus"), - &globalconf.styles.focus, &globalconf.styles.normal); - } - - /* Now grab menu styles if any */ - if(cfg_menu_styles) - { - draw_style_init(globalconf.connection, globalconf.default_screen, - cfg_getsec(cfg_menu_styles, "normal"), - &globalconf.styles.normal, NULL); - - draw_style_init(globalconf.connection, globalconf.default_screen, - cfg_getsec(cfg_menu_styles, "focus"), - &globalconf.styles.focus, &globalconf.styles.normal); - } - - if(!globalconf.styles.normal.font) - eprint("no default font available\n"); - - p_delete(&confpath); - - return ret; -} - -/** Return the last word for a text. - * \param text the text to look into - * \return a pointer to the last word position in text - */ -static char * -get_last_word(char *text) -{ - char *last_word; - - if((last_word = strrchr(text, ' '))) - last_word++; - else - last_word = text; - - return last_word; -} - -/** Fill the completion list for awesome-menu with file list. - * \param directory directory to look into - * \return always true - */ -static bool -item_list_fill_file(const char *directory) -{ - char *cwd, *home, *user, *filename; - const char *file; - DIR *dir; - struct dirent *dirinfo; - item_t *item; - ssize_t len, lenfile; - struct passwd *passwd = NULL; - struct stat st; - - item_list_wipe(&globalconf.items); - - if(!directory) - cwd = a_strdup("./"); - else if(a_strlen(directory) > 1 && directory[0] == '~') - { - if(directory[1] == '/') - { - home = getenv("HOME"); - asprintf(&cwd, "%s%s", (home ? home : ""), directory + 1); - } - else - { - if(!(file = strchr(directory, '/'))) - file = directory + a_strlen(directory); - len = (file - directory) + 1; - user = p_new(char, len); - a_strncpy(user, len, directory + 1, (file - directory) - 1); - if((passwd = getpwnam(user))) - { - asprintf(&cwd, "%s%s", passwd->pw_dir, file); - p_delete(&user); - } - else - { - p_delete(&user); - return false; - } - } - } - else - cwd = a_strdup(directory); - - if(!(dir = opendir(cwd))) - { - p_delete(&cwd); - return false; - } - - while((dirinfo = readdir(dir))) - { - item = p_new(item_t, 1); - - /* + 1 for \0 + 1 for / if directory */ - len = a_strlen(directory) + a_strlen(dirinfo->d_name) + 2; - - item->data = p_new(char, len); - if(a_strlen(directory)) - a_strcpy(item->data, len, directory); - a_strcat(item->data, len, dirinfo->d_name); - - lenfile = a_strlen(cwd) + a_strlen(dirinfo->d_name) + 2; - - filename = p_new(char, lenfile); - a_strcpy(filename, lenfile, cwd); - a_strcat(filename, lenfile, dirinfo->d_name); - - if(!stat(filename, &st) && S_ISDIR(st.st_mode)) - a_strcat(item->data, len, "/"); - - p_delete(&filename); - - item_list_push(&globalconf.items, item); - } - - closedir(dir); - p_delete(&cwd); - - return true; -} - -static void -complete(bool reverse) -{ - int loop = 2; - item_t *item = NULL; - item_t *(*item_iter)(item_t **, item_t *) = item_list_next_cycle; - - if(reverse) - item_iter = item_list_prev_cycle; - - if(globalconf.item_selected) - item = item_iter(&globalconf.items, globalconf.item_selected); - else - item = globalconf.items; - - for(; item && loop; item = item_iter(&globalconf.items, item)) - { - if(item->match) - { - a_strcpy(globalconf.text_complete, - globalconf.text_size - (globalconf.text_complete - globalconf.text), - item->data); - globalconf.item_selected = item; - return; - } - /* Since loop is 2, it will be 1 at first iter, and then 0 if we - * get back before matching an item (i.e. no items match) to the - * first elem: so it will break the loop, otherwise it loops for - * ever - */ - if(item == globalconf.items) - loop--; - } -} - -/** Compute a match from completion list for word. - * \param word the word to match - */ -static void -compute_match(const char *word) -{ - ssize_t len = a_strlen(word); - item_t *item; - - /* reset the selected item to NULL */ - globalconf.item_selected = NULL; - - if(len) - { - if(word[len - 1] == '/' - || word[len - 1] == ' ') - item_list_fill_file(word); - - for(item = globalconf.items; item; item = item->next) - if(!a_strncmp(word, item->data, a_strlen(word))) - item->match = true; - else - item->match = false; - } - else - { - if(a_strlen(globalconf.text)) - item_list_fill_file(NULL); - for(item = globalconf.items; item; item = item->next) - item->match = true; - } -} - -/* Why not? */ -#define MARGIN 10 - -/** Redraw the menu. */ -static void -redraw(void) -{ - item_t *item; - area_t geometry = { 0, 0, 0, 0, NULL, NULL }; - bool selected_item_is_drawn = false; - int len, prompt_len, x_of_previous_item; - style_t style; - - geometry.width = globalconf.sw->geometry.width; - geometry.height = globalconf.sw->geometry.height; - - if(a_strlen(globalconf.prompt)) - { - draw_text(globalconf.ctx, geometry, globalconf.prompt, &globalconf.styles.focus); - - len = MARGIN * 2 + draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.styles.focus.font, globalconf.prompt).width; - geometry.x += len; - geometry.width -= len; - } - - draw_text(globalconf.ctx, geometry, globalconf.text, &globalconf.styles.normal); - - len = MARGIN * 2 + MAX(draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.styles.normal.font, globalconf.text).width, - geometry.width / 20); - geometry.x += len; - geometry.width -= len; - prompt_len = geometry.x; - - for(item = globalconf.items; item && geometry.width > 0; item = item->next) - if(item->match) - { - style = item == globalconf.item_selected ? globalconf.styles.focus : globalconf.styles.normal; - len = MARGIN + draw_text_extents(globalconf.connection, globalconf.default_screen, - style.font, item->data).width; - if(item == globalconf.item_selected) - { - if(len > geometry.width) - break; - else - selected_item_is_drawn = true; - } - draw_text(globalconf.ctx, geometry, item->data, &style); - geometry.x += len; - geometry.width -= len; - } - - /* we have an item selected but not drawn, so redraw in the other side */ - if(globalconf.item_selected && !selected_item_is_drawn) - { - geometry.x = globalconf.sw->geometry.width; - - for(item = globalconf.item_selected; item; item = item_list_prev(&globalconf.items, item)) - if(item->match) - { - style = item == globalconf.item_selected ? globalconf.styles.focus : globalconf.styles.normal; - x_of_previous_item = geometry.x; - geometry.width = MARGIN + draw_text_extents(globalconf.connection, globalconf.default_screen, - style.font, item->data).width; - geometry.x -= geometry.width; - - if(geometry.x < prompt_len) - break; - - draw_text(globalconf.ctx, geometry, item->data, &style); - } - - if(item) - { - geometry.x = prompt_len; - geometry.width = x_of_previous_item - prompt_len; - draw_rectangle(globalconf.ctx, geometry, 1.0, true, globalconf.styles.normal.bg); - } - } - else if(geometry.width) - draw_rectangle(globalconf.ctx, geometry, 1.0, true, globalconf.styles.normal.bg); - - simplewindow_refresh_drawable(globalconf.sw); - xcb_aux_sync(globalconf.connection); -} - -/** XCB equivalent of XLookupString which translate the keycode given - * by PressEvent to a KeySym and a string - * \todo use XKB! - */ -static unsigned short const -keysym_to_unicode_1a1_1ff[] = -{ - 0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */ - 0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */ - 0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */ - 0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */ - 0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */ - 0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */ - 0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */ - 0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */ - 0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */ - 0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */ - 0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */ - 0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9 /* 0x01f8-0x01ff */ -}; - -static unsigned short const -keysym_to_unicode_2a1_2fe[] = -{ - 0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */ - 0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */ - 0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */ - 0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */ - 0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */ - 0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d /* 0x02f8-0x02ff */ -}; - -static unsigned short const -keysym_to_unicode_3a2_3fe[] = -{ - 0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */ - 0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */ - 0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */ - 0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */ - 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */ - 0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */ - 0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */ - 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */ - 0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */ - 0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b /* 0x03f8-0x03ff */ -}; - -static unsigned short const -keysym_to_unicode_4a1_4df[] = -{ - 0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */ - 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */ - 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */ - 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */ - 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */ - 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */ - 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */ - 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c /* 0x04d8-0x04df */ -}; - -static unsigned short const -keysym_to_unicode_590_5fe[] = -{ - 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */ - 0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */ - - 0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */ - 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */ - 0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */ - 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */ - 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */ - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */ - 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */ - 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */ - 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */ - 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */ - 0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1 /* 0x05f8-0x05fe */ -}; - -static unsigned short const -keysym_to_unicode_680_6ff[] = -{ - 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */ - 0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */ - 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */ - 0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */ - 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */ - 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */ - 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */ - 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */ - 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */ - 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */ - 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */ - 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */ - 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */ - 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */ - 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */ - 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a /* 0x06f8-0x06ff */ -}; - -static unsigned short const -keysym_to_unicode_7a1_7f9[] = -{ - 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */ - 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */ - 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */ - 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */ - 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */ - 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */ - 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */ - 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */ - 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */ - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */ - 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */ - 0x03c8, 0x03c9 /* 0x07f8-0x07ff */ -}; - -static unsigned short const -keysym_to_unicode_8a4_8fe[] = -{ - 0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */ - 0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */ - 0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */ - 0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x22a2, 0x0000, /* 0x08c8-0x08cf */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */ - 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e8-0x08ef */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */ - 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193 /* 0x08f8-0x08ff */ -}; - -static unsigned short const -keysym_to_unicode_9df_9f8[] = -{ - 0x2422, /* 0x09d8-0x09df */ - 0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */ - 0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */ - 0x2502 /* 0x09f8-0x09ff */ -}; - -static unsigned short const -keysym_to_unicode_aa1_afe[] = -{ - 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */ - 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */ - 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */ - 0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */ - 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */ - 0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */ - 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */ - 0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */ - 0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */ - 0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */ - 0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */ - 0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e /* 0x0af8-0x0aff */ -}; - -/* none of the APL keysyms match the Unicode characters */ -static unsigned short const -keysym_to_unicode_cdf_cfa[] = -{ - 0x2017, /* 0x0cd8-0x0cdf */ - 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */ - 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */ - 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */ - 0x05e8, 0x05e9, 0x05ea /* 0x0cf8-0x0cff */ -}; - -static unsigned short const -keysym_to_unicode_da1_df9[] = -{ - 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */ - 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */ - 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */ - 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */ - 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */ - 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */ - 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */ - 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */ - 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */ - 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */ - 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */ - 0x0e58, 0x0e59 /* 0x0df8-0x0dff */ -}; - -static unsigned short const -keysym_to_unicode_ea0_eff[] = -{ - 0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */ - 0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */ - 0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */ - 0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */ - 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */ - 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */ - 0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */ - 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */ - 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */ - 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */ - 0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */ - 0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */ -}; - -static unsigned short const -keysym_to_unicode_12a1_12fe[] = -{ - 0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */ - 0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */ - 0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */ - 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */ - 0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */ - 0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177 /* 0x12f0-0x12ff */ -}; - -static unsigned short const -keysym_to_unicode_13bc_13be[] = -{ - 0x0152, 0x0153, 0x0178 /* 0x13b8-0x13bf */ -}; - -static unsigned short const -keysym_to_unicode_14a1_14ff[] = -{ - 0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */ - 0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */ - 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */ - 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */ - 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */ - 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */ - 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */ - 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */ - 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */ - 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */ - 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */ - 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */ -}; - -static unsigned short const -keysym_to_unicode_15d0_15f6[] = -{ - 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */ - 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */ - 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */ - 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */ - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6 /* 0x15f0-0x15f7 */ -}; - -static unsigned short const -keysym_to_unicode_16a0_16f6[] = -{ - 0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */ - 0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */ - 0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */ - 0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */ - 0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */ - 0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259 /* 0x16f0-0x16f6 */ -}; - -static unsigned short const -keysym_to_unicode_1e9f_1eff[] = -{ - 0x0303, - 0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */ - 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */ - 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */ - 0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */ - 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */ - 0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */ - 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */ - 0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */ - 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */ - 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */ - 0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */ - 0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323 /* 0x1ef8-0x1eff */ -}; - -static unsigned short const -keysym_to_unicode_20a0_20ac[] = -{ - 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */ - 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */ -}; - -static char * -keysym_to_utf8(const xcb_keysym_t ksym) -{ - unsigned int ksym_conv; - int count; - char *buf; - - /* Unicode keysym */ - if((ksym & 0xff000000) == 0x01000000) - ksym_conv = ksym & 0x00ffffff; - else if(ksym > 0 && ksym < 0x100) - ksym_conv = ksym; - else if(ksym > 0x1a0 && ksym < 0x200) - ksym_conv = keysym_to_unicode_1a1_1ff[ksym - 0x1a1]; - else if(ksym > 0x2a0 && ksym < 0x2ff) - ksym_conv = keysym_to_unicode_2a1_2fe[ksym - 0x2a1]; - else if(ksym > 0x3a1 && ksym < 0x3ff) - ksym_conv = keysym_to_unicode_3a2_3fe[ksym - 0x3a2]; - else if(ksym > 0x4a0 && ksym < 0x4e0) - ksym_conv = keysym_to_unicode_4a1_4df[ksym - 0x4a1]; - else if(ksym > 0x589 && ksym < 0x5ff) - ksym_conv = keysym_to_unicode_590_5fe[ksym - 0x590]; - else if(ksym > 0x67f && ksym < 0x700) - ksym_conv = keysym_to_unicode_680_6ff[ksym - 0x680]; - else if(ksym > 0x7a0 && ksym < 0x7fa) - ksym_conv = keysym_to_unicode_7a1_7f9[ksym - 0x7a1]; - else if(ksym > 0x8a3 && ksym < 0x8ff) - ksym_conv = keysym_to_unicode_8a4_8fe[ksym - 0x8a4]; - else if(ksym > 0x9de && ksym < 0x9f9) - ksym_conv = keysym_to_unicode_9df_9f8[ksym - 0x9df]; - else if(ksym > 0xaa0 && ksym < 0xaff) - ksym_conv = keysym_to_unicode_aa1_afe[ksym - 0xaa1]; - else if(ksym > 0xcde && ksym < 0xcfb) - ksym_conv = keysym_to_unicode_cdf_cfa[ksym - 0xcdf]; - else if(ksym > 0xda0 && ksym < 0xdfa) - ksym_conv = keysym_to_unicode_da1_df9[ksym - 0xda1]; - else if(ksym > 0xe9f && ksym < 0xf00) - ksym_conv = keysym_to_unicode_ea0_eff[ksym - 0xea0]; - else if(ksym > 0x12a0 && ksym < 0x12ff) - ksym_conv = keysym_to_unicode_12a1_12fe[ksym - 0x12a1]; - else if(ksym > 0x13bb && ksym < 0x13bf) - ksym_conv = keysym_to_unicode_13bc_13be[ksym - 0x13bc]; - else if(ksym > 0x14a0 && ksym < 0x1500) - ksym_conv = keysym_to_unicode_14a1_14ff[ksym - 0x14a1]; - else if(ksym > 0x15cf && ksym < 0x15f7) - ksym_conv = keysym_to_unicode_15d0_15f6[ksym - 0x15d0]; - else if(ksym > 0x169f && ksym < 0x16f7) - ksym_conv = keysym_to_unicode_16a0_16f6[ksym - 0x16a0]; - else if(ksym > 0x1e9e && ksym < 0x1f00) - ksym_conv = keysym_to_unicode_1e9f_1eff[ksym - 0x1e9f]; - else if(ksym > 0x209f && ksym < 0x20ad) - ksym_conv = keysym_to_unicode_20a0_20ac[ksym - 0x20a0]; - else - return NULL; - - if(ksym_conv < 0x80) - count = 1; - else if(ksym_conv < 0x800) - count = 2; - else if(ksym_conv < 0x10000) - count = 3; - else if(ksym_conv < 0x200000) - count = 4; - else if(ksym_conv < 0x4000000) - count = 5; - else if(ksym_conv <= 0x7fffffff) - count = 6; - else - return NULL; - - buf = p_new(char, count + 1); - - switch (count) - { - case 6: - buf[5] = 0x80 | (ksym_conv & 0x3f); - ksym_conv = ksym_conv >> 6; - ksym_conv |= 0x4000000; - case 5: - buf[4] = 0x80 | (ksym_conv & 0x3f); - ksym_conv = ksym_conv >> 6; - ksym_conv |= 0x200000; - case 4: - buf[3] = 0x80 | (ksym_conv & 0x3f); - ksym_conv = ksym_conv >> 6; - ksym_conv |= 0x10000; - case 3: - buf[2] = 0x80 | (ksym_conv & 0x3f); - ksym_conv = ksym_conv >> 6; - ksym_conv |= 0x800; - case 2: - buf[1] = 0x80 | (ksym_conv & 0x3f); - ksym_conv = ksym_conv >> 6; - ksym_conv |= 0xc0; - case 1: - buf[0] = ksym_conv; - } - - buf[count] = '\0'; - return buf; -} - -static char * -keysym_to_str(const xcb_keysym_t ksym) -{ - char *buf; - - /* Try to convert to Latin-1, handling ctrl */ - if(!(((ksym >= XK_BackSpace) && (ksym <= XK_Clear)) || - (ksym == XK_Return) || (ksym == XK_Escape) || - (ksym == XK_KP_Space) || (ksym == XK_KP_Tab) || - (ksym == XK_KP_Enter) || - ((ksym >= XK_KP_Multiply) && (ksym <= XK_KP_9)) || - (ksym == XK_KP_Equal) || - (ksym == XK_Delete))) - return NULL; - - buf = p_new(char, 2); - - /* If X KeySym, convert to ascii by grabbing low 7 bits */ - if(ksym == XK_KP_Space) - /* Patch encoding botch */ - buf[0] = XK_space & 0x7F; - else if(ksym == XK_hyphen) - /* Map to equivalent character */ - buf[0] = (char)(XK_minus & 0xFF); - else - buf[0] = (char)(ksym & 0x7F); - - buf[1] = '\0'; - return buf; -} - -static void -key_press_lookup_string(xcb_key_press_event_t *e, - char **buf, size_t *buf_len, - xcb_keysym_t *ksym) -{ - xcb_keysym_t k0, k1; - - /* 'col' (third parameter) is used to get the proper KeySym - * according to modifier (XCB doesn't provide an equivalent to - * XLookupString()) */ - k0 = xcb_key_press_lookup_keysym(globalconf.keysyms, e, 0); - k1 = xcb_key_press_lookup_keysym(globalconf.keysyms, e, 1); - - /* The numlock modifier is on and the second KeySym is a keypad - * KeySym */ - if((e->state & globalconf.numlockmask) && xcb_is_keypad_key(k1)) - { - /* The Shift modifier is on, or if the Lock modifier is on and - * is interpreted as ShiftLock, use the first KeySym */ - if((e->state & XCB_MOD_MASK_SHIFT) || - (e->state & XCB_MOD_MASK_LOCK && (e->state & globalconf.shiftlockmask))) - *ksym = k0; - else - *ksym = k1; - } - - /* The Shift and Lock modifers are both off, use the first - * KeySym */ - else if(!(e->state & XCB_MOD_MASK_SHIFT) && !(e->state & XCB_MOD_MASK_LOCK)) - *ksym = k0; - - /* The Shift modifier is off and the Lock modifier is on and is - * interpreted as CapsLock */ - else if(!(e->state & XCB_MOD_MASK_SHIFT) && - (e->state & XCB_MOD_MASK_LOCK && (e->state & globalconf.capslockmask))) - /* The first Keysym is used but if that KeySym is lowercase - * alphabetic, then the corresponding uppercase KeySym is used - * instead */ - *ksym = k1; - - /* The Shift modifier is on, and the Lock modifier is on and is - * interpreted as CapsLock */ - else if((e->state & XCB_MOD_MASK_SHIFT) && - (e->state & XCB_MOD_MASK_LOCK && (e->state & globalconf.capslockmask))) - /* The second Keysym is used but if that KeySym is lowercase - * alphabetic, then the corresponding uppercase KeySym is used - * instead */ - *ksym = k1; - - /* The Shift modifer is on, or the Lock modifier is on and is - * interpreted as ShiftLock, or both */ - else if((e->state & XCB_MOD_MASK_SHIFT) || - (e->state & XCB_MOD_MASK_LOCK && (e->state & globalconf.shiftlockmask))) - *ksym = k1; - - if(xcb_is_modifier_key(*ksym) || xcb_is_function_key(*ksym) || - xcb_is_pf_key(*ksym) || xcb_is_cursor_key(*ksym) || - xcb_is_misc_function_key(*ksym)) - { - *buf_len = 0; - return; - } - - /* Handle special KeySym (Tab, Newline...) */ - if((*ksym & 0xffffff00) == 0xff00) - *buf = keysym_to_str(*ksym); - /* Handle other KeySym (like unicode...) */ - else - *buf = keysym_to_utf8(*ksym); - - *buf_len = a_strlen(*buf); -} - -/** Handle keypress event in awesome-menu. - * \param e received XKeyEvent - */ -static void -handle_kpress(xcb_key_press_event_t *e) -{ - char *buf; - xcb_keysym_t ksym = 0; - ssize_t len; - size_t text_dst_len, num; - - len = a_strlen(globalconf.text); - - key_press_lookup_string(e, &buf, &num, &ksym); - /* Got a special key, see x_lookup_string() */ - if(!num) - return; - - if(e->state & XCB_MOD_MASK_CONTROL) - switch(ksym) - { - default: - p_delete(&buf); - return; - case XK_bracketleft: - ksym = XK_Escape; - break; - case XK_h: - case XK_H: - ksym = XK_BackSpace; - break; - case XK_i: - case XK_I: - ksym = XK_Tab; - break; - case XK_j: - case XK_J: - ksym = XK_Return; - break; - case XK_c: - case XK_C: - status = CANCEL; - break; - case XK_w: - case XK_W: - /* erase word */ - if(len) - { - int i = len - 1; - while(i >= 0 && globalconf.text[i] == ' ') - globalconf.text[i--] = '\0'; - while(i >= 0 && globalconf.text[i] != ' ') - globalconf.text[i--] = '\0'; - compute_match(get_last_word(globalconf.text)); - redraw(); - } - p_delete(&buf); - return; - } - else if(CLEANMASK(e->state) & XCB_MOD_MASK_1) - switch(ksym) - { - default: - p_delete(&buf); - return; - case XK_h: - ksym = XK_Left; - break; - case XK_l: - ksym = XK_Right; - break; - } - - switch(ksym) - { - case XK_space: - globalconf.text_complete = globalconf.text + a_strlen(globalconf.text) + 1; - default: - if(num && !iscntrl((int) buf[0])) - { - if(buf[0] != '/' || globalconf.text[len - 1] != '/') - { - /* Reallocate text string if needed to hold - * concatenation of text and buf */ - if((text_dst_len = (a_strlen(globalconf.text) + num - 1)) > globalconf.text_size) - { - globalconf.text_size += ((int) (text_dst_len / globalconf.text_size)) * CHUNK_SIZE; - p_realloc(&globalconf.text, globalconf.text_size); - } - a_strncat(globalconf.text, globalconf.text_size, buf, num); - } - compute_match(get_last_word(globalconf.text)); - redraw(); - } - - p_delete(&buf); - break; - case XK_BackSpace: - if(len) - { - globalconf.text[--len] = '\0'; - compute_match(get_last_word(globalconf.text)); - redraw(); - } - break; - case XK_ISO_Left_Tab: - case XK_Left: - complete(true); - redraw(); - break; - case XK_Right: - case XK_Tab: - complete(false); - redraw(); - break; - case XK_Escape: - status = CANCEL; - break; - case XK_Return: - status = STOP; - break; - } - - p_delete(&buf); -} - -#ifndef HAVE_GETLINE -static ssize_t -my_getline(char **lineptr, size_t *n, FILE *stream) -{ - char *ret = NULL; - - if(lineptr == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } - - if(*n == 0) - { - *lineptr = p_new(char, CHUNK_SIZE); - *n = CHUNK_SIZE; - } - - ret = fgets(*lineptr, *n, stream); - while(ret != NULL && (*lineptr)[a_strlen (*lineptr) - 1] != '\n') - { - *n += CHUNK_SIZE; - *lineptr = realloc(*lineptr, *n); - - ret = fgets(*lineptr + a_strlen(*lineptr), CHUNK_SIZE, stream); - } - - if (ret == NULL) - return -1; - - return a_strlen(*lineptr); -} -#endif - -/** Fill the completion by reading on stdin. - * \return true if something has been filled up, false otherwise. - */ -static bool -item_list_fill_stdin(void) -{ - char *buf = NULL; - size_t len = 0; - ssize_t line_len; - - item_t *newitem; - bool has_entry = false; - - item_list_init(&globalconf.items); - - if((line_len = getline(&buf, &len, stdin)) != -1) - has_entry = true; - - if(has_entry) - do - { - buf[line_len - 1] = '\0'; - newitem = p_new(item_t, 1); - newitem->data = a_strdup(buf); - newitem->match = true; - item_list_append(&globalconf.items, newitem); - } - while((line_len = getline(&buf, &len, stdin)) != -1); - - p_delete(&buf); - - return has_entry; -} - -/** Grab the keyboard. - */ -static void -keyboard_grab(void) -{ - int i; - xcb_grab_keyboard_reply_t *xgb = NULL; - for(i = 1000; i; i--) - { - if((xgb = xcb_grab_keyboard_reply(globalconf.connection, - xcb_grab_keyboard(globalconf.connection, true, - xcb_aux_get_screen(globalconf.connection, globalconf.default_screen)->root, - XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_ASYNC), - NULL)) != NULL) - { - p_delete(&xgb); - break; - } - usleep(1000); - } - if(!i) - eprint("cannot grab keyboard"); -} - -/** Main function of awesome-menu. - * \param argc number of elements in argv - * \param argv arguments array - * \return EXIT_SUCCESS - */ -int -main(int argc, char **argv) -{ - xcb_generic_event_t *ev; - int opt, ret, screen = 0; - xcb_query_pointer_reply_t *xqp = NULL; - char *configfile = NULL, *cmd; - ssize_t len; - const char *shell = getenv("SHELL"); - area_t geometry = { 0, 0, 0, 0, NULL, NULL }; - screens_info_t *si; - static struct option long_options[] = - { - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 'v'}, - {"exec", 0, NULL, 'e'}, - {NULL, 0, NULL, 0} - }; - - while((opt = getopt_long(argc, argv, "vhf:b:x:y:n:c:e:", - long_options, NULL)) != -1) - switch(opt) - { - case 'v': - eprint_version(PROGNAME); - break; - case 'h': - exit_help(EXIT_SUCCESS); - break; - case 'c': - configfile = a_strdup(optarg); - break; - case 'e': - globalconf.exec = a_strdup(optarg); - break; - } - - if(argc - optind >= 1) - globalconf.prompt = a_strdup(argv[optind]); - - globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); - if(xcb_connection_has_error(globalconf.connection)) - eprint("unable to open display"); - - si = screensinfo_new(globalconf.connection); - if(si->xinerama_is_active) - { - if((xqp = xcb_query_pointer_reply(globalconf.connection, - xcb_query_pointer(globalconf.connection, - xcb_aux_get_screen(globalconf.connection, - globalconf.default_screen)->root), - NULL)) != NULL) - { - screen = screen_get_bycoord(si, 0, xqp->root_x, xqp->root_y); - p_delete(&xqp); - - geometry.x = si->geometry[screen].x; - geometry.y = si->geometry[screen].y; - geometry.width = si->geometry[screen].width; - } - } - else - { - screen = globalconf.default_screen; - if(!geometry.width) - geometry.width = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen)->width_in_pixels; - } - - if((ret = config_parse(screen, configfile, globalconf.prompt, &geometry))) - return ret; - - /* Init the geometry */ - if(!geometry.height) - geometry.height = 1.5 * MAX(globalconf.styles.normal.font->height, - globalconf.styles.focus.font->height); - - screensinfo_delete(&si); - - /* Create the window */ - globalconf.sw = simplewindow_new(globalconf.connection, globalconf.default_screen, - geometry.x, geometry.y, geometry.width, geometry.height, 0); - - xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, - globalconf.sw->window, WM_NAME, STRING, 8, - strlen(PROGNAME), PROGNAME); - - /* Create the drawing context */ - globalconf.ctx = draw_context_new(globalconf.connection, globalconf.default_screen, - geometry.width, geometry.height, - globalconf.sw->drawable); - - /* Allocate a default size for the text on the heap instead of - * using stack allocation with PATH_MAX (may not been defined - * according to POSIX). This string size may be increased if - * needed */ - globalconf.text_complete = globalconf.text = p_new(char, CHUNK_SIZE); - globalconf.text_size = CHUNK_SIZE; - - if(isatty(STDIN_FILENO)) - { - if(!item_list_fill_stdin()) - item_list_fill_file(NULL); - keyboard_grab(); - } - else - { - keyboard_grab(); - if(!item_list_fill_stdin()) - item_list_fill_file(NULL); - } - - compute_match(NULL); - - globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); - - /* Get the numlock, capslock and shiftlock mask */ - xutil_getlockmask(globalconf.connection, globalconf.keysyms, &globalconf.numlockmask, - &globalconf.shiftlockmask, &globalconf.capslockmask); - - xcb_map_window(globalconf.connection, globalconf.sw->window); - redraw(); - - while(status == RUN) - { - ev = xcb_wait_for_event(globalconf.connection); - /* Skip errors */ - if(ev->response_type == 0) - continue; - - switch(ev->response_type & 0x7f) - { - case XCB_BUTTON_PRESS: - status = CANCEL; - break; - case XCB_KEY_PRESS: - handle_kpress((xcb_key_press_event_t *) ev); - break; - case XCB_EXPOSE: - if(!((xcb_expose_event_t *) ev)->count) - simplewindow_refresh_drawable(globalconf.sw); - break; - default: - break; - } - p_delete(&ev); - } - - if(status != CANCEL) - { - if(!globalconf.exec) - printf("%s\n", globalconf.text); - else - { - if(!shell) - shell = a_strdup("/bin/sh"); - len = a_strlen(globalconf.exec) + a_strlen(globalconf.text) + 1; - cmd = p_new(char, len); - a_strcpy(cmd, len, globalconf.exec); - a_strcat(cmd, len, globalconf.text); - execl(shell, shell, "-c", cmd, NULL); - } - } - - xcb_key_symbols_free(globalconf.keysyms); - p_delete(&globalconf.text); - draw_context_delete(&globalconf.ctx); - simplewindow_delete(&globalconf.sw); - xcb_disconnect(globalconf.connection); - - return EXIT_SUCCESS; -} - -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/awesome-message.1.txt b/awesome-message.1.txt deleted file mode 100644 index 2b471f80..00000000 --- a/awesome-message.1.txt +++ /dev/null @@ -1,49 +0,0 @@ -awesome-message(1) -================= - -NAME ----- - -awesome-message - awesome message window - -SYNOPSIS --------- - -awesome-message [-x xcoord] [-y ycoord] [-d delay] <message> <icon> - -DESCRIPTION ------------ - -awesome-message is a tool which will pop up a simple X window with a message -and optionally an icon in front of it. - -USAGE ------ -To have a popup when you have new mail, you can do something like that: - - awesome-message "You have new mails!" ~/.awesome/icons/newmail.png - -OPTIONS -------- --x xcoord:: - Set x coordinate of the window. --y ycoord:: - Set y coordinate of the window. --d delay:: - Close the window after <delay> seconds. Must be an integer greater than 0. -<message>:: - Print this message in the window. -<icon>:: - Draw this icon file in the window. - -SEE ALSO --------- -awesome(1) - -AUTHORS -------- -Julien Danjou <julien@danjou.info> - -WWW ---- -http://awesome.naquadah.org diff --git a/awesome-message.c b/awesome-message.c deleted file mode 100644 index 16b0ba58..00000000 --- a/awesome-message.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * awesome-message.c - message window for awesome - * - * Copyright © 2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#define _GNU_SOURCE -#include <getopt.h> - -#include <signal.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> - -#include <xcb/xcb.h> -#include <xcb/xcb_aux.h> -#include <xcb/xcb_atom.h> - -#include "common/swindow.h" -#include "common/util.h" -#include "common/version.h" -#include "common/configopts.h" -#include "common/xscreen.h" - -#define PROGNAME "awesome-message" - -static bool running = true; - -/** Import awesome config file format */ -extern cfg_opt_t awesome_opts[]; - -/** awesome-run global configuration structure */ -typedef struct -{ - /** Display ref */ - xcb_connection_t *connection; - /** Default screen number */ - int default_screen; - /** Style */ - style_t style; -} AwesomeMsgConf; - -static AwesomeMsgConf globalconf; - -static void __attribute__ ((noreturn)) -exit_help(int exit_code) -{ - FILE *outfile = (exit_code == EXIT_SUCCESS) ? stdout : stderr; - fprintf(outfile, "Usage: %s [-x xcoord] [-y ycoord] [-d delay] <message> <icon>\n", - PROGNAME); - exit(exit_code); -} - -static int -config_parse(int screen, const char *confpatharg) -{ - int ret; - char *confpath; - cfg_t *cfg, *cfg_screen; - - if(!confpatharg) - confpath = config_file(); - else - confpath = a_strdup(confpatharg); - - cfg = cfg_new(); - - switch((ret = cfg_parse(cfg, confpath))) - { - case CFG_FILE_ERROR: - warn("parsing configuration file failed: %s\n", strerror(errno)); - break; - case CFG_PARSE_ERROR: - cfg_error(cfg, "awesome: parsing configuration file %s failed.\n", confpath); - break; - } - - if(ret) - return ret; - - /* get global screen section */ - if(!(cfg_screen = cfg_getnsec(cfg, "screen", screen))) - if(!(cfg_screen = cfg_getsec(cfg, "screen"))) - eprint("parsing configuration file failed, no screen section found\n"); - - /* style */ - draw_style_init(globalconf.connection, globalconf.default_screen, - cfg_getsec(cfg_getsec(cfg_screen, "styles"), "normal"), - &globalconf.style, NULL); - - if(!globalconf.style.font) - eprint("no default font available\n"); - - p_delete(&confpath); - - return ret; -} - -static void -exit_on_signal(int sig __attribute__ ((unused))) -{ - running = false; -} - -int -main(int argc, char **argv) -{ - simple_window_t *sw; - draw_context_t *ctx; - xcb_generic_event_t *ev; - area_t geometry = { 0, 0, 200, 50, NULL, NULL }, - icon_geometry = { -1, -1, -1, -1, NULL, NULL }; - int opt, ret, screen = 0, delay = 0; - xcb_query_pointer_reply_t *xqp = NULL; - char *configfile = NULL; - screens_info_t *si; - static struct option long_options[] = - { - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 'v'}, - {NULL, 0, NULL, 0} - }; - - while((opt = getopt_long(argc, argv, "vhf:b:x:y:n:c:d:", - long_options, NULL)) != -1) - switch(opt) - { - case 'd': - if((delay = atoi(optarg)) <= 0) - delay = 1; - break; - case 'v': - eprint_version(PROGNAME); - break; - case 'x': - geometry.x = atoi(optarg); - break; - case 'y': - geometry.y = atoi(optarg); - break; - case 'h': - exit_help(EXIT_SUCCESS); - break; - case 'c': - configfile = a_strdup(optarg); - break; - } - - if(argc - optind < 1) - exit_help(EXIT_FAILURE); - - globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); - if(xcb_connection_has_error(globalconf.connection)) - eprint("unable to open display"); - - si = screensinfo_new(globalconf.connection); - if(si->xinerama_is_active) - { - if((xqp = xcb_query_pointer_reply(globalconf.connection, - xcb_query_pointer(globalconf.connection, - xcb_aux_get_screen(globalconf.connection, - globalconf.default_screen)->root), - NULL)) != NULL) - { - screen = screen_get_bycoord(si, 0, xqp->root_x, xqp->root_y); - p_delete(&xqp); - } - } - else - screen = globalconf.default_screen; - - if((ret = config_parse(screen, configfile))) - return ret; - - geometry.width = draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.style.font, argv[optind]).width; - geometry.height = globalconf.style.font->height * 1.5; - - if(argc - optind >= 2) - { - icon_geometry = draw_get_image_size(argv[optind + 1]); - if(icon_geometry.width <= 0 || icon_geometry.height <= 0) - eprint("invalid image\n"); - else - geometry.width += icon_geometry.width - * ((double) globalconf.style.font->height / (double) icon_geometry.height); - } - - sw = simplewindow_new(globalconf.connection, globalconf.default_screen, - geometry.x, geometry.y, geometry.width, geometry.height, 0); - - xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, sw->window, - WM_NAME, STRING, 8, strlen(PROGNAME), PROGNAME); - - ctx = draw_context_new(globalconf.connection, globalconf.default_screen, - geometry.width, geometry.height, sw->drawable); - - geometry.x = geometry.y = 0; - draw_text(ctx, geometry, argv[optind], &globalconf.style); - - if(icon_geometry.width > 0 && icon_geometry.height > 0) - draw_image(ctx, 0, (geometry.height / 2) - (globalconf.style.font->height / 2), - globalconf.style.font->height, argv[optind + 1]); - - p_delete(&ctx); - - xcb_map_window(globalconf.connection, sw->window); - simplewindow_refresh_drawable(sw); - xcb_aux_sync(globalconf.connection); - - signal(SIGALRM, &exit_on_signal); - alarm(delay); - - while(running) - { - while((ev = xcb_poll_for_event(globalconf.connection))) - { - /* Skip errors */ - if(ev->response_type == 0) - continue; - - switch(ev->response_type & 0x7f) - { - case XCB_BUTTON_PRESS: - case XCB_KEY_PRESS: - running = false; - case XCB_EXPOSE: - simplewindow_refresh_drawable(sw); - break; - default: - break; - } - - p_delete(&ev); - } - usleep(100000); - } - - simplewindow_delete(&sw); - xcb_disconnect(globalconf.connection); - - return EXIT_SUCCESS; -} - -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/awesome.1.txt b/awesome.1.txt index 2b213bee..4126019a 100644 --- a/awesome.1.txt +++ b/awesome.1.txt @@ -9,7 +9,7 @@ awesome - awesome window manager SYNOPSIS -------- -awesome [ -v | --version ] [ -h | --help ] [ -k | --check ] [ --config | -c configuration file ] +awesome [ -v | --version ] [ -h | --help ] [ --config | -c configuration file ] DESCRIPTION ----------- @@ -47,8 +47,6 @@ OPTIONS Print help information, then exit. --config | -c:: Use an alternate configuration file instead of $HOME/.awesomerc. ---check | -k:: - Check configuration file syntax. DEFAULTS MOUSE BINDINGS ----------------------- diff --git a/awesome.c b/awesome.c index c4892f29..9b780870 100644 --- a/awesome.c +++ b/awesome.c @@ -41,8 +41,7 @@ #include <xcb/xcb_atom.h> #include <xcb/xcb_icccm.h> -#include "config.h" -#include "awesome.h" +#include "lua.h" #include "event.h" #include "layout.h" #include "screen.h" @@ -58,7 +57,7 @@ #include "common/configopts.h" #include "common/xutil.h" -static bool running = true; +bool running = true; AwesomeConf globalconf; @@ -200,17 +199,6 @@ xerrorstart(void * data __attribute__ ((unused)), eprint("another window manager is already running\n"); } -/** Quit awesome. - * \param screen Screen ID - * \param arg nothing - * \ingroup ui_callback - */ -void -uicb_quit(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused))) -{ - running = false; -} - /** Function to exit on some signals. * \param sig the signal received, unused */ @@ -292,21 +280,21 @@ main(int argc, char **argv) int r, xfd, csfd, dbusfd, i, screen_nbr, opt; ssize_t cmdlen = 1; const xcb_query_extension_reply_t *shape_query, *randr_query; - statusbar_t *statusbar; fd_set rd; xcb_generic_event_t *ev; struct sockaddr_un *addr; client_t *c; - bool confcheck = false; static struct option long_options[] = { {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'v'}, - {"check", 0, NULL, 'k'}, {"config", 1, NULL, 'c'}, {NULL, 0, NULL, 0} }; + /* clear the globalconf structure */ + p_clear(&globalconf, 1); + /* save argv */ for(i = 0; i < argc; i++) cmdlen += a_strlen(argv[i]) + 1; @@ -337,17 +325,11 @@ main(int argc, char **argv) else eprint("-c option requires a file name\n"); break; - case 'k': - confcheck = true; - break; } /* Text won't be printed correctly otherwise */ setlocale(LC_CTYPE, ""); - if(confcheck) - return config_check(confpath); - /* X stuff */ globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); if(xcb_connection_has_error(globalconf.connection)) @@ -396,23 +378,15 @@ main(int argc, char **argv) focus_add_client(NULL); /* parse config */ - config_parse(confpath); + if(!confpath) + confpath = config_file(); + luaA_parserc(confpath); /* init cursors */ globalconf.cursor[CurNormal] = create_font_cursor(CURSOR_LEFT_PTR); globalconf.cursor[CurResize] = create_font_cursor(CURSOR_SIZING); globalconf.cursor[CurMove] = create_font_cursor(CURSOR_FLEUR); - /* for each virtual screen */ - for(screen_nbr = 0; screen_nbr < globalconf.screens_info->nscreen; screen_nbr++) - { - /* view at least one tag */ - tag_view(globalconf.screens[screen_nbr].tags, true); - for(statusbar = globalconf.screens[screen_nbr].statusbar; - statusbar; statusbar = statusbar->next) - statusbar_init(statusbar); - } - /* select for events */ const uint32_t change_win_vals[] = { @@ -433,8 +407,7 @@ main(int argc, char **argv) change_win_vals); ewmh_set_supported_hints(screen_nbr); /* call this to at least grab root window clicks */ - window_root_grabbuttons(screen_nbr); - window_root_grabkeys(screen_nbr); + window_root_grabbuttons(); } /* scan existing windows */ @@ -450,7 +423,6 @@ main(int argc, char **argv) set_enter_notify_event_handler(globalconf.evenths, event_handle_enternotify, NULL); set_expose_event_handler(globalconf.evenths, event_handle_expose, NULL); set_key_press_event_handler(globalconf.evenths, event_handle_keypress, NULL); - set_mapping_notify_event_handler(globalconf.evenths, event_handle_mappingnotify, NULL); set_map_request_event_handler(globalconf.evenths, event_handle_maprequest, NULL); set_property_notify_event_handler(globalconf.evenths, event_handle_propertynotify, NULL); set_unmap_notify_event_handler(globalconf.evenths, event_handle_unmapnotify, NULL); @@ -490,7 +462,7 @@ main(int argc, char **argv) else warn("error binding UNIX domain socket: %s\n", strerror(errno)); } - + if(!a_dbus_init(&dbusfd)) dbusfd = -1; @@ -519,7 +491,7 @@ main(int argc, char **argv) eprint("select failed\n"); } if(csfd >= 0 && FD_ISSET(csfd, &rd)) - switch (r = recv(csfd, buf, sizeof(buf)-1, MSG_TRUNC)) + switch(r = recv(csfd, buf, sizeof(buf)-1, MSG_TRUNC)) { case -1: warn("error reading UNIX domain socket: %s\n", strerror(errno)); @@ -531,7 +503,7 @@ main(int argc, char **argv) if(r >= ssizeof(buf)) break; buf[r] = '\0'; - __uicb_parsecmd(buf); + luaA_docmd(buf); statusbar_refresh(); layout_refresh(); } diff --git a/awesome.h b/awesome.h deleted file mode 100644 index 85cc528a..00000000 --- a/awesome.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * awesome.h - awesome main header - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef AWESOME_AWESOME_H -#define AWESOME_AWESOME_H - -#include "uicb.h" - -uicb_t uicb_quit; - -#endif -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/awesomerc.5.txt b/awesomerc.5.txt index 3e9b761d..cd488bd9 100644 --- a/awesomerc.5.txt +++ b/awesomerc.5.txt @@ -8,23 +8,7 @@ awesomerc - Configuration file for the 'awesome window manager' SYNOPSIS -------- -.......................... -<section> [title] -{ - <option> = <value> - - <section> [title] - { - <option> = <value> - ... - } - ... -} - -<option> = <value> - -include(file.conf) -.......................... +None. DESCRIPTION ----------- @@ -34,182 +18,14 @@ be used to configure the behaviour and look of awesome in a variety of ways. It is read at startup. -OPTIONS --------- -*awesomerc* contains 5 global sections: *screen*, *rules*, *keys*, *mouse* and *menu* which -are described here. - -All these sections contain options which may be strings, integers, floats, or -even sections again. - -include::optsdocgen.txt[] - -UICB FUNCTIONS --------------- - -In awesome, a lot of *functions* are available. These functions are called -uicb (User Interface Call Backs). Each function can be bound to a key shortcut -or a mouse button. - -include::uicbdocgen.txt[] - -EXAMPLES --------- - -More examples are available on awesome's wiki: -http://awesome.naquadah.org/wiki/ - -Simple textbox example -~~~~~~~~~~~~~~~~~~~~~~ -.............................................. -1. Add an include directive into ~/.awesomerc - - screen 0 { include(~/.awesome/bottom-status-bar) } - -2. Create ~/.awesome/bottom-status-bar - - statusbar "bottom" - { - position = "bottom" - textbox "clock" { } - } - -3. Check the configuration file for errors - - $ awesome -k - Configuration file OK. - - Note: If you see anything other than "Configuration file OK." you have a - typo somewhere. - -4. Create ~/bin/awesome-clock - - #!/bin/sh - while true - do - # if you start this from .xinitrc, the script will start before - # awesome, and will fail. - if [ -S ~/.awesome_ctl.0 ]; then - while true - do - echo "0 widget_tell bottom clock text `date`" - echo "" # an empty line flushes data inside awesome - sleep 1 - done | awesome-client - else - sleep 1 - fi - done - - Note: What we are saying is "awesome-client, tell the bottom status bar's - widget named 'clock' to set it's 'text' property to date's output". - -5. Make your ~/bin/awesome-clock executable - - $ chmod a+x ~/bin/awesome-clock - -6. Modify ~/.xinitrc - - ~/bin/awesome-clock & - exec awesome - -7. Restart awesome - -8. If you did not get what you were expecting, take a look at - ~/.xsession-errors or the terminal where X got started. -.............................................. - -Simple progressbar example -~~~~~~~~~~~~~~~~~~~~~~~~~~ -.............................................. - -1. Add an include directive into ~/.awesomerc - - screen 0 { include(~/.awesome/bottom-status-bar) } - -2. Create ~/.awesome/bottom-status-bar - - statusbar "bottom" - { - position = "bottom" - progressbar "diskusage" - { - data "disk" - { - bordercolor = "#006e96" - bg = "#000000" - fg = "#ff0000" - fg_center = "#daaf0a" - fg_end = "#00ff00" - } - width = 100 - align = "left" - } - } - -3. Check the configuration file for errors - - $ awesome -k - Configuration file OK. - - Note: If you see anything other than "Configuration file OK," you have a - typo somewhere. - -4. Create ~/bin/awesome-diskusage - - #!/bin/sh - while true - do - # if you start this from .xinitrc, the script will start before - # awesome, and will fail. - if [ -S ~/.awesome_ctl.0 ]; then - while true; do - usage = `df /dev/sda5 | awk '/\/dev\/sda5/ { print 100-$5 }'` - echo "0 widget_tell bottom diskusage data disk ${usage}" - echo "" # an empty line flushes data inside awesome - sleep 600; - done | awesome-client - else - sleep 1 - fi - done - - - Note: What we are saying is "awesome-client, tell the bottom status bar's - widget named 'diskusage' to set it's 'data' property named 'disk' to - ${usage}." - -5. Make ~/bin/awesome-diskusage executable - -$ chmod a+x ~/bin/awesome-diskusage - -6. Modify ~/.xinitrc - - ~/bin/awesome-diskusage & - exec awesome - -7. Restart awesome - -8. If you did not get what you were expecting, take a look at - ~/.xsession-errors or the terminal where X got started. -.............................................. - -AWESOMERC SKELETON ------------------- -The following skeleton lists all available configuration options in *awesomerc*. - -.......................... -include::rcskeletongen.txt[] -.......................... SEE ALSO -------- -awesome(1) awesome-client(1) awesome-menu(1) awesome-message(1) +awesome(1) awesome-client(1) AUTHORS ------- -This man page was written by Julien Danjou <julien@danjou.info>, Marco Candrian <mac@calmar.ws> -and Chris Ciulla <chris.ciulla@gmail.com> (Simple Examples). +This man page was written by Julien Danjou <julien@danjou.info>. WWW --- diff --git a/awesomerc.in b/awesomerc.in deleted file mode 100644 index 812c95b6..00000000 --- a/awesomerc.in +++ /dev/null @@ -1,183 +0,0 @@ -screen 0 -{ - styles - { - normal - { - font = "sans 8" - fg = "#dddddd" - bg = "#444444" - border = "#555555" - } - focus - { - fg = "#000000" - bg = "#535d6c" - border = "#535d6c" - } - urgent - { - fg = "#111111" - bg = "#ff4500" - } - } - tags - { - tag one { } - tag two { } - tag three { } - tag four { } - tag five { } - tag six { } - tag seven { } - tag eight { } - tag nine { } - } - layouts - { - layout tile { image = "@iconslayoutsdir@/tilew.png" } - layout tileleft { image = "@iconslayoutsdir@/tileleftw.png" } - layout tilebottom { image = "@iconslayoutsdir@/tilebottomw.png" } - layout tiletop { image = "@iconslayoutsdir@/tiletopw.png" } - layout max { image = "@iconslayoutsdir@/maxw.png" } - layout spiral { image = "@iconslayoutsdir@/spiralw.png" } - layout dwindle { image = "@iconslayoutsdir@/dwindlew.png" } - layout floating { image = "@iconslayoutsdir@/floatingw.png" } - } - statusbar mystatusbar - { - position = "top" - - taglist mytaglist - { - mouse { button = "1" command = "tag_view" } - mouse { button = "1" modkey = {"Mod4"} command = "client_tag" } - mouse { button = "3" command = "tag_toggleview" } - mouse { button = "3" modkey = {"Mod4"} command = "client_toggletag" } - mouse { button = "4" command = "tag_viewnext" } - mouse { button = "5" command = "tag_viewprev" } - } - layoutinfo mylayoutinfo - { - mouse { button = "1" command = "tag_setlayout" args = {"+1"} } - mouse { button = "4" command = "tag_setlayout" args = {"+1"} } - mouse { button = "3" command = "tag_setlayout" args = {"-1"} } - mouse { button = "5" command = "tag_setlayout" args = {"-1"} } - } - tasklist mytasklist - { - mouse { button = "4" command = "client_focus" args = {"+1"} } - mouse { button = "5" command = "client_focus" args = {"-1"} } - mouse { modkey = {"Mod4"} button = "4" command = "client_swap" args = {"+1"} } - mouse { modkey = {"Mod4"} button = "5" command = "client_swap" args = {"-1"} } - } - iconbox logo - { - image = "@iconsdir@/awesome16.png" - mouse { button = "1" command = "spawn" args = {"exec xterm -e man awesome"} } - } - } -} - -rules -{ - rule { name = "Gimp" float = true } - rule { name = "MPlayer" float = true } - rule { name = "Acroread" float = true } - rule { name = "pinentry" float = true } -} - -mouse -{ - root { button = "3" command = "spawn" args = {"exec xterm"} } - root { button = "4" command = "tag_viewnext" } - root { button = "5" command = "tag_viewprev" } - client { modkey = {"Mod4"} button = "1" command = "client_movemouse" } - client { modkey = {"Mod4"} button = "2" command = "client_swap" args = {"0"} } - client { modkey = {"Mod4"} button = "3" command = "client_resizemouse" } - titlebar { button = "1" command = "client_movemouse" } - titlebar { button = "3" command = "client_resizemouse" } -} - -keys -{ - key { modkey = {"Mod4"} key = "F1" command = "spawn" args = {"for i in /usr/share/man/man?;do ls $i; done | cut -d. -f1 | awesome-menu -e 'xterm -e man ' 'See manual page for:'"} } - key { modkey = {"Mod4"} key = "F2" command = "spawn" args = {"find /usr/bin -type f -executable ! -empty | awesome-menu -e 'exec ' Execute:"} } - key { modkey = {"Mod4"} key = "F3" command = "spawn" args = {"cut -d' ' -f1 ~/.ssh/known_hosts | cut -d, -f1 | awesome-menu -e 'xterm -e ssh ' 'ssh to:'"} } - key { modkey = {"Mod4"} key = "Return" command = "spawn" args = {"exec xterm"} } - key { modkey = {"Mod4"} key = "space" command = "tag_setlayout" args = {"+1"} } - key { modkey = {"Mod4", "Shift"} key = "space" command = "tag_setlayout" args = {"-1"} } - key { modkey = {"Mod4"} key = "b" command = "statusbar_toggle" } - key { modkey = {"Mod4"} key = "j" command = "client_focus" args = {"+1"} } - key { modkey = {"Mod4"} key = "k" command = "client_focus" args = {"-1"} } - key { modkey = {"Mod4"} key = "Tab" command = "focus_history" args = {"-1"} } - key { modkey = {"Mod4", "Shift"} key = "j" command = "client_swap" args = {"+1"} } - key { modkey = {"Mod4", "Shift"} key = "k" command = "client_swap" args = {"-1"} } - key { modkey = {"Mod4", "Control"} key = "j" command = "screen_focus" args = {"+1"} } - key { modkey = {"Mod4", "Control"} key = "k" command = "screen_focus" args = {"-1"} } - key { modkey = {"Mod4"} key = "h" command = "tag_setmwfact" args = {"-0.05"} } - key { modkey = {"Mod4"} key = "l" command = "tag_setmwfact" args = {"+0.05"} } - key { modkey = {"Mod4", "Shift"} key = "h" command = "tag_setnmaster" args = {"+1"} } - key { modkey = {"Mod4", "Shift"} key = "l" command = "tag_setnmaster" args = {"-1"} } - key { modkey = {"Mod4", "Control"} key = "h" command = "tag_setncol" args = {"+1"} } - key { modkey = {"Mod4", "Control"} key = "l" command = "tag_setncol" args = {"-1"} } - key { modkey = {"Mod4"} key = "Escape" command = "tag_prev_selected" } - key { modkey = {"Mod4"} key = "Left" command = "tag_viewprev" } - key { modkey = {"Mod4"} key = "Right" command = "tag_viewnext" } - key { modkey = {"Mod4"} key = "m" command = "client_togglemax" } - key { modkey = {"Mod4", "Control"} key = "Return" command = "client_swap" args = {"0"} } - key { modkey = {"Mod4", "Control"} key = "space" command = "client_setfloating" } - key { modkey = {"Mod4"} key = "s" command = "client_togglescratch" } - key { modkey = {"Mod4", "Control"} key = "s" command = "client_setscratch" } - key { modkey = {"Mod4"} key = "r" command = "client_redraw" } - key { modkey = {"Mod4", "Shift"} key = "c" command = "client_kill" } - key { modkey = {"Mod4", "Shift"} key = "q" command = "quit" } - key { modkey = {"Mod4", "Control"} key = "r" command = "restart" } - - key { modkey = {"Mod4"} key = "0" command = "tag_view" } - key { modkey = {"Mod4"} key = "0" command = "tag_view" } - key { modkey = {"Mod4"} key = "1" command = "tag_view" args = {"1"} } - key { modkey = {"Mod4"} key = "2" command = "tag_view" args = {"2"} } - key { modkey = {"Mod4"} key = "3" command = "tag_view" args = {"3"} } - key { modkey = {"Mod4"} key = "4" command = "tag_view" args = {"4"} } - key { modkey = {"Mod4"} key = "5" command = "tag_view" args = {"5"} } - key { modkey = {"Mod4"} key = "6" command = "tag_view" args = {"6"} } - key { modkey = {"Mod4"} key = "7" command = "tag_view" args = {"7"} } - key { modkey = {"Mod4"} key = "8" command = "tag_view" args = {"8"} } - key { modkey = {"Mod4"} key = "9" command = "tag_view" args = {"9"} } - - key { modkey = {"Mod4"} key = "0" command = "tag_toggleview" } - key { modkey = {"Mod4", "Control"} key = "0" command = "tag_toggleview" } - key { modkey = {"Mod4", "Control"} key = "1" command = "tag_toggleview" args = {"1"} } - key { modkey = {"Mod4", "Control"} key = "2" command = "tag_toggleview" args = {"2"} } - key { modkey = {"Mod4", "Control"} key = "3" command = "tag_toggleview" args = {"3"} } - key { modkey = {"Mod4", "Control"} key = "4" command = "tag_toggleview" args = {"4"} } - key { modkey = {"Mod4", "Control"} key = "5" command = "tag_toggleview" args = {"5"} } - key { modkey = {"Mod4", "Control"} key = "6" command = "tag_toggleview" args = {"6"} } - key { modkey = {"Mod4", "Control"} key = "7" command = "tag_toggleview" args = {"7"} } - key { modkey = {"Mod4", "Control"} key = "8" command = "tag_toggleview" args = {"8"} } - key { modkey = {"Mod4", "Control"} key = "9" command = "tag_toggleview" args = {"9"} } - - key { modkey = {"Mod4", "Shift"} key = "0" command = "client_tag" } - key { modkey = {"Mod4", "Shift"} key = "1" command = "client_tag" args = {"1"} } - key { modkey = {"Mod4", "Shift"} key = "2" command = "client_tag" args = {"2"} } - key { modkey = {"Mod4", "Shift"} key = "3" command = "client_tag" args = {"3"} } - key { modkey = {"Mod4", "Shift"} key = "4" command = "client_tag" args = {"4"} } - key { modkey = {"Mod4", "Shift"} key = "5" command = "client_tag" args = {"5"} } - key { modkey = {"Mod4", "Shift"} key = "6" command = "client_tag" args = {"6"} } - key { modkey = {"Mod4", "Shift"} key = "7" command = "client_tag" args = {"7"} } - key { modkey = {"Mod4", "Shift"} key = "8" command = "client_tag" args = {"8"} } - key { modkey = {"Mod4", "Shift"} key = "9" command = "client_tag" args = {"9"} } - - key { modkey = {"Mod4", "Shift", "Control"} key = "0" command = "client_toggletag" } - key { modkey = {"Mod4", "Shift", "Control"} key = "1" command = "client_toggletag" args = {"1"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "2" command = "client_toggletag" args = {"2"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "3" command = "client_toggletag" args = {"3"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "4" command = "client_toggletag" args = {"4"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "5" command = "client_toggletag" args = {"5"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "6" command = "client_toggletag" args = {"6"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "7" command = "client_toggletag" args = {"7"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "8" command = "client_toggletag" args = {"8"} } - key { modkey = {"Mod4", "Shift", "Control"} key = "9" command = "client_toggletag" args = {"9"} } -} -# vim: filetype=conf diff --git a/awesomerc.lua.in b/awesomerc.lua.in new file mode 100644 index 00000000..da445739 --- /dev/null +++ b/awesomerc.lua.in @@ -0,0 +1,191 @@ +-- awesome 3 configuration file + +-- Include awesome library, with lots of useful function! +require("awful") + +-- {{{ Variables definitions +-- This is used later as the default terminal to run. +terminal = "xterm" +-- Default modkey. +-- Usually, Mod4 is the key with a logo between Control and Alt. +-- If you do not like this or do not have such a key, +-- I suggest you to remap Mod4 to another key using xmodmap or other tools. +-- However, you can use another modifier like Mod1, but it may interact with others. +modkey = "Mod4" +-- }}} + +-- {{{ Tags +-- Define tags +tags = {} +for s = 1, awesome.screen_count() do + tags[s] = + { + tag.new({ name = "1" }), + tag.new({ name = "2" }), + tag.new({ name = "3" }), + tag.new({ name = "4" }), + tag.new({ name = "5" }), + tag.new({ name = "6" }), + tag.new({ name = "7" }), + tag.new({ name = "8" }), + tag.new({ name = "9" }) + } + -- Add tags to screen 0 one by one + for index, tag in ipairs(tags[s]) do + tag:add(s) + end + -- I'm sure you want to see at least one tag. + tags[s][1]:view(true) +end +-- }}} + +-- {{{ Statusbar +-- Create a taglist widget +mytaglist = widget.new({ type = "taglist", name = "mytaglist" }) +mytaglist:mouse({}, 1, awful.tag.viewonly) +mytaglist:mouse({ modkey }, 1, awful.client.toggletag) +mytaglist:mouse({}, 3, + function (tag) + tag:view(not tag:isselected()) + end) +mytaglist:mouse({ modkey }, 3, awful.client.toggletag) +mytaglist:mouse({ }, 4, awful.tag.viewprev) +mytaglist:mouse({ }, 5, awful.tag.viewnext) +mytaglist:set("text_focus", "<bg color=\"#555555\"/> <title/> ") + +-- Create a tasklist widget +mytasklist = widget.new({ type = "tasklist", name = "mytasklist" }) +mytasklist:mouse({ }, 1, function (c) c:focus_set() end) +mytasklist:mouse({ }, 4, function () awful.client.focus(1) end) +mytasklist:mouse({ }, 5, function () awful.client.focus(-1) end) +mytasklist:set("text_focus", "<bg color=\"#555555\"/> <title/> ") + +-- Create a textbox widget +mytextbox = widget.new({ type = "textbox", name = "mytextbox", align = "right" }) +-- Set the default text in textbox +mytextbox:set("text", "<i><small>awesome " .. AWESOME_VERSION .. "</small></i>") + +-- Create an iconbox widget +myiconbox = widget.new({ type = "iconbox", name = "myiconbox", align = "right" }) +myiconbox:set("image", "@iconsdir@/awesome16.png") + +-- Create a statusbar for each screen and add it +for s = 1, awesome.screen_count() do + mystatusbar = statusbar.new({ position = "top", name = "mystatusbar" .. s, + fg = "lightblue", bg = "black" }) + -- Add widgets to the statusbar - order matters + mystatusbar:widget_add(mytaglist) + mystatusbar:widget_add(mytasklist) + mystatusbar:widget_add(mytextbox) + mystatusbar:add(s) +end +-- }}} + +-- {{{ Mouse bindings +awesome.mouse({ }, 3, function () awful.spawn(terminal) end) +client.mouse({ modkey }, 1, mouse.client_move) +client.mouse({ modkey }, 3, mouse.client_resize) +-- }}} + +-- {{{ Key bindings + +-- Bind keyboard digits +-- Compute the maximum number of digit we need, limited to 9 +keynumber = 0 +for s = 1, awesome.screen_count() do + keynumber = math.min(9, math.max(#tags[s], keynumber)); +end + +for i = 1, keynumber do + awesome.key({ modkey }, i, + function () + local screen = mouse.screen_get() + if tags[screen][i] then + awful.tag.viewonly(tags[screen][i]) + end + end) + awesome.key({ modkey, "Control" }, i, + function () + local screen = mouse.screen_get() + if tags[screen][i] then + tags[i]:view(not tags[screen][i]:isselected()) + end + end) + awesome.key({ modkey, "Shift" }, i, + function () + local screen = mouse.screen_get() + if tags[screen][i] then + awful.client.movetotag(tags[screen][i]) + end + end) + awesome.key({ modkey, "Control", "Shift" }, i, + function () + local screen = mouse.screen_get() + if tags[screen][i] then + awful.client.toggletag(tags[screen][i]) + end + end) +end + +awesome.key({ modkey }, "Left", awful.tag.viewprev) +awesome.key({ modkey }, "Right", awful.tag.viewnext) + +-- Standard program +awesome.key({ modkey }, "Return", function () awful.spawn(terminal) end) + +awesome.key({ modkey, "Control" }, "r", awesome.restart) +awesome.key({ modkey, "Shift" }, "q", awesome.quit) + +-- Client manipulation +awesome.key({ modkey, "Shift" }, "c", function () client.focus_get():kill() end) +awesome.key({ modkey }, "j", function () awful.client.focus(1) end) +awesome.key({ modkey }, "k", function () awful.client.focus(-1) end) +awesome.key({ modkey, "Shift" }, "j", function () awful.client.swap(1) end) +awesome.key({ modkey, "Shift" }, "k", function () awful.client.swap(-1) end) +awesome.key({ modkey, "Control" }, "j", function () awful.screen.focus(1) end) +awesome.key({ modkey, "Control" }, "k", function () awful.screen.focus(-1) end) +awesome.key({ modkey, "Control" }, "space", function () awful.client.togglefloating() end) + +-- Statubar manipulation +awesome.key({ modkey }, "b", function () mystatusbar:position_set("off") end) + +-- Layout manipulation +awesome.key({ modkey }, "l", function () awful.tag.incmwfact(0.05) end) +awesome.key({ modkey }, "h", function () awful.tag.incmwfact(-0.05) end) +awesome.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(1) end) +awesome.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end) +awesome.key({ modkey, "Control" }, "h", function () awful.tag.incncol(1) end) +awesome.key({ modkey, "Control" }, "l", function () awful.tag.incncol(1) end) +-- }}} + +-- {{{ Hooks +-- Hook function to execute when focusing a client. +function hook_focus(c) + c:border_set({ width = 1, color = "white" }) +end + +-- Hook function to execute when unfocusing a client. +function hook_unfocus(c) + c:border_set({ width = 1, color = "black" }) +end + +-- Hook function to exeucte when the mouse is over a client. +function hook_mouseover(c) + -- Sloppy focus + c:focus_set() +end + +-- Hook function to execute when a new client appears. +function hook_newclient(c) + c:focus_set() +end + +-- Set up some hooks +hooks.focus(hook_focus) +hooks.unfocus(hook_unfocus) +hooks.newclient(hook_newclient) +hooks.mouseover(hook_mouseover) +-- }}} + +-- Respect size hints +awesome.resizehints_set(true) diff --git a/awful.lua b/awful.lua new file mode 100644 index 00000000..36eb1690 --- /dev/null +++ b/awful.lua @@ -0,0 +1,223 @@ +----------------------------------------------- +-- awful: AWesome Function very UsefuL -- +-- Common useful awesome functions -- +-- -- +-- © 2008 Julien Danjou <julien@danjou.info> -- +----------------------------------------------- + +-- We usually are required as 'awful' +-- But that can be changed. +local P = {} -- package +if _REQUIREDNAME == nil then + awful = P +else + _G[_REQUIREDNAME] = P +end + +-- Grab environment we need +local ipairs = ipairs +local awesome = awesome +local client = client +local tag = tag +local mouse = mouse +local os = os + +-- Reset env +setfenv(1, P) + +-- Function to the good value in table, cycling +function array_boundandcycle(t, i) + if i > #t then + i = 1 + elseif i < 1 then + i = #t + end + return i +end + + +-- Function to get a client by its relative index: +-- set i to 1 to get next, -1 to get previous. +function client_next(i) + -- Get all visible clients + local cls = client.visible_get(mouse.screen_get(), ".*") + -- Get currently focused client + local sel = client.focus_get() + if not sel then return end + -- Loop upon each client + for idx, c in ipairs(cls) do + if c == sel then + return cls[array_boundandcycle(cls, idx +i)] + end + end +end + +-- Focus a client by its relative index. +function client_focus(i) + local c = client_next(i) + if c then + c:focus_set() + end +end + +-- Swap a client by its relative index. +function client_swap(i) + local c = client_next(i) + local sel = client.focus_get() + if c and sel then + sel:swap(c) + end +end + +-- Focus a client relative to current focused client +function screen_focus(i) + local sel = client.focus_get() + local s + if sel then + s = sel:screen_get() + else + s = mouse.screen_get() + end + local count = awesome.screen_count() + s = s + i + if s < 1 then + s = count + elseif s > count then + s = 1 + end + awesome.screen_focus(s) +end + +-- Return a table with all visible tags +function getselectedtags() + local idx = 1 + local screen = mouse.screen_get() + local tags = tag.get(screen, ".*") + local vtags = {} + for i, t in ipairs(tags) do + if t:isselected() then + vtags[idx] = t + idx = idx + 1 + end + end + return vtags +end + +-- Return only the first element of all visible tags, +-- so that's the first visible tags. +local function getselectedtag() + return getselectedtags()[1] +end + +-- Increase master width factor +function tag_incmwfact(i) + local t = getselectedtag() + if t then + t:mwfact_set(t:mwfact_get() + i) + end +end + +-- Increase number of master windows +function tag_incnmaster(i) + local t = getselectedtag() + if t then + t:nmaster_set(t:nmaster_get() + i) + end +end + +-- Increase number of column windows +function tag_incncol(i) + local t = getselectedtag() + if t then + t:ncol_set(t:ncol_get() + i) + end +end + +-- View no tag +function tag_viewnone() + local tags = tag.get(mouse.screen_get(), ".*") + for i, t in ipairs(tags) do + t:view(false) + end +end + +function tag_viewidx(r) + local tags = tag.get(mouse.screen_get(), ".*") + local sel = getselectedtag() + tag_viewnone() + for i, t in ipairs(tags) do + if t == sel then + tags[array_boundandcycle(tags, i - r)]:view(true) + end + end +end + +-- View next tag +function tag_viewnext() + return tag_viewidx(1) +end + +-- View previous tag +function tag_viewprev() + return tag_viewidx(-1) +end + +function tag_viewonly(t) + tag_viewnone() + t:view(true) +end + +function client_movetotag(target, c) + local sel = c or client.focus_get(); + local tags = tag.get(mouse.screen_get(), ".*") + for i, t in ipairs(tags) do + sel:tag(t, false) + end + sel:tag(target, true) +end + +function client_toggletag(target, c) + local sel = c or client.focus_get(); + if sel then + sel:tag(target, not sel:istagged(target)) + end +end + +function client_togglefloating(c) + local sel = c or client.focus_get(); + if sel then + sel:floating_set(not sel:floating_get()) + end +end + +function spawn(cmd) + return os.execute(cmd .. "&") +end + +-- Export tags function +P.tag = +{ + viewnone = tag_viewnone; + viewprev = tag_viewprev; + viewnext = tag_viewnext; + viewonly = tag_viewonly; + incmwfact = tag_incmwfact; + incncol = tag_incncol; + incnmaster = tag_incnmaster; +} +P.client = +{ + next = client_next; + focus = client_focus; + swap = client_swap; + movetotag = client_movetotag; + toggletag = client_toggletag; + togglefloating = client_togglefloating; +} +P.screen = +{ + focus = screen_focus; +} +P.spawn = spawn + +return P diff --git a/build-utils/extractoptsdoc.py b/build-utils/extractoptsdoc.py deleted file mode 100755 index cabd10fe..00000000 --- a/build-utils/extractoptsdoc.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# -# extractoptsdoc.py - extract options documentation from awesome sour code -# Copyright (C) 2008 Julien Danjou <julien@danjou.info> -# -# This indeed crappy. Any better version, even with awk, would be welcome. -# - -import sys - -def section_print(section, options): - print section - i = 0 - underline = "" - while i < len(section): - underline += "~" - i += 1 - print underline - if options.has_key("comments"): - print "%s\n" % options.pop("comments") - for option, format in options.items(): - print "%s::" % option - print " %s" % format - print - -def sections_print(sections): - section_print("Base sections", sections.pop("awesome")) - keylist = sections.keys() - keylist.sort() - for key in keylist: - section_print(key, sections[key]) - -def sections_get(file): - sections = {} - section_doc = {} - section_begin = False - for line in file.readlines(): - if line.startswith("cfg_opt_t"): - section_name = (line.split(" ", 1)[1]).split("_opts")[0] - section_doc['comments'] = lastline[4:-3] - section_begin = True - elif section_begin and line.startswith("};"): - section_begin = False - sections[section_name] = section_doc - section_doc = {} - elif section_begin and line.startswith(" CFG_"): - if line.startswith(" CFG_AWESOME_END"): - continue - option_title = line.split("\"")[1].split("\"")[0] - if lastline.startswith(" /**"): - section_doc[option_title] = lastline[8:-3] - else: - section_doc[option_title] = "Undocumented option. " - if line.startswith(" CFG_INT"): - section_doc[option_title] += "This option must be an integer value." - elif line.startswith(" CFG_BOOL"): - section_doc[option_title] += "This option must be a boolean value." - elif line.startswith(" CFG_FLOAT"): - section_doc[option_title] += "This option must be a float value." - elif line.startswith(" CFG_ALIGNMENT"): - section_doc[option_title] += "This option must be an alignment value." - elif line.startswith(" CFG_POSITION"): - section_doc[option_title] += "This option must be a position value." - elif line.startswith(" CFG_STR_LIST"): - section_doc[option_title] += "This option must be string list." - elif line.startswith(" CFG_STR"): - section_doc[option_title] += "This option must be string value." - elif line.startswith(" CFG_SEC"): - secname = (line.split(", ")[1]).split("_opts", 1)[0] - section_doc[option_title] += "This option must be a section `%s'" % secname - if line.find("CFGF_MULTI") != -1: - section_doc[option_title] += ", can be specified multiple times" - if line.find("CFGF_NO_TITLE_DUPES") != -1: - section_doc[option_title] += ", must have a unique title" - elif line.find("CFGF_TITLE") != -1: - section_doc[option_title] += ", must have a title" - section_doc[option_title] += "." - - lastline = line - - return sections - -sections_print(sections_get(file(sys.argv[1]))) diff --git a/build-utils/extractrcskeleton.py b/build-utils/extractrcskeleton.py deleted file mode 100755 index a4589a38..00000000 --- a/build-utils/extractrcskeleton.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# -# extractuicbdoc.py - extract uicb documentation from awesome source code -# Copyright (C) 2008 Julien Danjou <julien@danjou.info> -# Copyright (C) 2008 Marco Candrian <mac@calmar.ws> -# -# This is indeed crappy. Any better version, would be welcome. - -import sys - -sections = {} # [section_name] -> options infos (packed in option_doc's {}) -option_order = {} # [section_name] -> options in [] (ordered like found) -section_desc = {} # [section_name] -> description of section itself - -def sections_print(sec, indent): - global sections, section_desc, option_order - for opt in option_order[sec]: - if sections[sec][opt][:9] == "<SECTION>": - print indent + opt + section_desc[sections[sec][opt][9:]] - print indent + "{" - indent += " " - if sections[sec][opt][9:] == "style_opts": - print indent + "<style section>" - else: - sections_print(sections[sec][opt][9:], indent) - indent = indent[0:-4] - print indent + "}" - else: - if opt in ["fg", "bg", "fg_center", "fg_end", "fg_off", "bordercolor", - "tab_border","normal_fg","normal_bg","normal_border","focus_fg", - "focus_bg","focus_border","urgent_fg","urgent_bg"]: - print indent + opt + " = <color>" - elif opt in ["font"]: - print indent + opt + " = <font>" - elif opt in ["image"]: - print indent + opt + " = <image>" - elif opt in ["name", "xproperty_value", "tags"]: - print indent + opt + " = <regex>" - elif opt in ["key"]: - print indent + opt + " = <key>" - elif opt in ["keylist"]: - print indent + opt + " = <key, ...>" - elif opt in ["modkey"]: - print indent + opt + " = <mod>" - elif opt in ["align"]: - print indent + opt + " = <{auto, left, right}>" - elif opt in ["draw_style"]: - print indent + opt + " = <{bottom, top, line}>" - elif opt in ["text_align"]: - print indent + opt + " = <{left, center, right}>" - elif opt in ["grow"]: - print indent + opt + " = <{left, right}>" - elif opt in ["arg"]: - print indent + opt + " = <uicb-arg>" - elif opt in ["command"]: - print indent + opt + " = <uicb-cmd>" - elif opt in ["float", "master"]: - print indent + opt + " = <{auto,true,false}>" - elif opt in ["show"]: - print indent + opt + " = <{all,tags,focus}>" - elif opt in ["floating_placement"]: - print indent + opt + " = <{smart,under_mouse}>" - else: - print indent + opt + " = " + sections[sec][opt] - -def sections_get(file): - global sections, section_desc, option_order - option_doc = {} # holds all items from a section - section_begin = False - for line in file.readlines(): - if line.startswith("cfg_opt_t"): - section_name = (line.split(" ", 1)[1]).split("[]")[0] - section_begin = True - option_order[section_name] = [] - elif section_begin and line.startswith("};"): - section_begin = False - sections[section_name] = option_doc - option_doc = {} - elif section_begin and line.startswith(" CFG_"): - if line.startswith(" CFG_AWESOME_END"): - continue - option_title = line.split("\"")[1].split("\"")[0] - - if line.startswith(" CFG_INT"): - option_doc[option_title] = "<integer>" - elif line.startswith(" CFG_BOOL"): - option_doc[option_title] = "<boolean>" - elif line.startswith(" CFG_FLOAT"): - option_doc[option_title] = "<float>" - elif line.startswith(" CFG_ALIGNMENT"): - option_doc[option_title] = "<{left, center, right, flex, auto}>" - elif line.startswith(" CFG_POSITION"): - option_doc[option_title] = "<{top, bottom, left, right, auto, off}>" - elif line.startswith(" CFG_STR_LIST"): - option_doc[option_title] = "<string-list>" - elif line.startswith(" CFG_STR"): - option_doc[option_title] = "<string>" - elif line.startswith(" CFG_SEC"): - secname = (line.split(", ")[1]).split(",", 1)[0] - str = "" - if line.find("CFGF_NO_TITLE_DUPES") != -1: - str += " <identifier>" - elif line.find("CFGF_TITLE") != -1: - str += " <title>" - if line.find("CFGF_MULTI") != -1: - str += " [MULTI]" - section_desc[secname] = str - option_doc[option_title] = "<SECTION>" + secname - option_order[section_name].append(option_title) - - lastline = line - -def print_defines(): - print """Note: when there is no whitespace, quotes are optional. - - <boolean> -> true or false - <color> -> Color in X format or hexadecimal (e.g. #aabbcc) - <float> -> Floating numbers (e.g 0.2) - <font> -> Pango font: [FAMILY-LIST] [STYLE-OPTIONS] [SIZE] (e.g Sans Italic 12) - <identifier> -> A name used to identify (e.g foobar) - <image> -> A path to an image (e.g. /home/user/image.jpg) - <integer> -> A signed integer - <key> -> A KeySym (e.g. F10) or a KeyCodea (e.g #120) - <mod> -> A key modifier list (e.g. Mod1) - <regex> -> Regular expression - <string> -> A string - <string-list> -> A string list (e.g. {a, b, c, ...}) - <uicb-arg> -> Argument to an uicb function - <uicb-cmd> -> Uicb function, see UICB FUNCTIONS - <style section> -> A style section: {fg= bg= border= font= shadow= shadow_offset= } - <{.., ...}> -> List of available options - [MULTI] -> This item can be defined multiple times - """ -sections_get(file(sys.argv[1])) - -print_defines() -sections_print("awesome_opts", "") - -# vim: filetype=python:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/build-utils/extractuicbdoc.py b/build-utils/extractuicbdoc.py deleted file mode 100755 index 7978df8f..00000000 --- a/build-utils/extractuicbdoc.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# extractuicbdoc.py - extract uicb documentation from awesome sour code -# Copyright (C) 2008 Julien Danjou <julien@danjou.info> -# -# This indeed crappy. Any better version, even with awk, would be welcome. -# - -import sys -import os.path - -def extract_doc(file): - function_doc = {} - doc = [] - doc_begin = False - catch_name = 0 - - for line in file.readlines(): - if catch_name == 1: - catch_name = 2 - continue - if catch_name > 1: - # We only want functions with uicb - if line.startswith("uicb_"): - if line.endswith("arg __attribute__ ((unused)))\n"): - doc.append("No argument needed.") - uicb_name = line.split('_', 1)[1] - uicb_name = uicb_name.split('(', 1)[0] - function_doc[uicb_name] = doc - catch_name = False - else: - catch_name = 0 - doc = [] - if line.startswith("/**"): - doc_begin = True - doc.append(line[4:].replace("\n", "")) - if doc_begin and line.startswith(" * ") and not line.startswith(" * \\"): - doc.append(line[3:].replace("\n", "")) - if line.startswith(" */"): - doc_begin = False - catch_name = 1 - - return function_doc - -def doc_print(function_doc, filename): - if not len(function_doc): - return - filename = os.path.basename(filename) - # Special case - if filename == "uicb.c": - filename = "general.c" - # Print header - tmptitle = filename.replace(".c", "") - title = tmptitle[0].upper() + tmptitle[1:] - print title - i = 0 - underline = "" - while i < len(title): - underline += "~" - i += 1 - print underline - # Print documentation - for uicb, doc in function_doc.items(): - # Special case - print "*%s*::" % uicb - print " %s" % " ".join(doc) - print - -for f in sys.argv[1:]: - doc_print(extract_doc(file(f)), f) diff --git a/client.c b/client.c index 984b3c27..0da82236 100644 --- a/client.c +++ b/client.c @@ -28,13 +28,13 @@ #include "client.h" #include "tag.h" -#include "rules.h" #include "window.h" #include "focus.h" #include "ewmh.h" #include "widget.h" #include "screen.h" #include "titlebar.h" +#include "lua.h" #include "layouts/floating.h" #include "common/markup.h" #include "common/xutil.h" @@ -221,13 +221,13 @@ client_updatetitle(client_t *c) static void client_unfocus(client_t *c) { - if(globalconf.screens[c->screen].opacity_unfocused != -1) - window_settrans(c->win, globalconf.screens[c->screen].opacity_unfocused); - else if(globalconf.screens[c->screen].opacity_focused != -1) - window_settrans(c->win, -1); + /* Call hook */ + client_t **lc = lua_newuserdata(globalconf.L, sizeof(client_t *)); + *lc = c; + luaA_settype(globalconf.L, "client"); + luaA_dofunction(globalconf.L, globalconf.hooks.unfocus, 1); + focus_add_client(NULL); - xcb_change_window_attributes(globalconf.connection, c->win, XCB_CW_BORDER_PIXEL, - &globalconf.screens[c->screen].styles.normal.border.pixel); widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); titlebar_draw(c); } @@ -242,8 +242,8 @@ client_ban(client_t *c) client_unfocus(c); xcb_unmap_window(globalconf.connection, c->win); window_setstate(c->win, XCB_WM_ICONIC_STATE); - if(c->titlebar.position && c->titlebar.sw) - xcb_unmap_window(globalconf.connection, c->titlebar.sw->window); + if(c->titlebar.position && c->titlebar_sw) + xcb_unmap_window(globalconf.connection, c->titlebar_sw->window); } /** Give focus to client, or to first client if c is NULL @@ -255,6 +255,7 @@ client_ban(client_t *c) bool client_focus(client_t *c, int screen, bool raise) { + client_t **lc; int phys_screen; /* if c is NULL or invisible, take next client in the focus history */ @@ -277,12 +278,6 @@ client_focus(client_t *c, int screen, bool raise) client_unban(c); /* save sel in focus history */ focus_add_client(c); - if(globalconf.screens[c->screen].opacity_focused != -1) - window_settrans(c->win, globalconf.screens[c->screen].opacity_focused); - else if(globalconf.screens[c->screen].opacity_unfocused != -1) - window_settrans(c->win, -1); - xcb_change_window_attributes(globalconf.connection, c->win, XCB_CW_BORDER_PIXEL, - &globalconf.screens[screen].styles.focus.border.pixel); titlebar_draw(c); xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT, c->win, XCB_CURRENT_TIME); @@ -305,6 +300,11 @@ client_focus(client_t *c, int screen, bool raise) ewmh_update_net_active_window(phys_screen); widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS); + lc = lua_newuserdata(globalconf.L, sizeof(client_t *)); + *lc = c; + luaA_settype(globalconf.L, "client"); + luaA_dofunction(globalconf.L, globalconf.hooks.focus, 1); + return true; } @@ -326,13 +326,13 @@ client_stack(client_t *c) if(client->layer == layer && client != c && client_isvisible_anyscreen(client)) { - if(client->titlebar.position && client->titlebar.sw) + if(client->titlebar.position && client->titlebar_sw) { xcb_configure_window(globalconf.connection, - client->titlebar.sw->window, + client->titlebar_sw->window, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, config_win_vals); - config_win_vals[0] = client->titlebar.sw->window; + config_win_vals[0] = client->titlebar_sw->window; } xcb_configure_window(globalconf.connection, client->win, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, @@ -342,12 +342,12 @@ client_stack(client_t *c) } if(c->layer == layer) { - if(c->titlebar.position && c->titlebar.sw) + if(c->titlebar.position && c->titlebar_sw) { - xcb_configure_window(globalconf.connection, c->titlebar.sw->window, + xcb_configure_window(globalconf.connection, c->titlebar_sw->window, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, config_win_vals); - config_win_vals[0] = c->titlebar.sw->window; + config_win_vals[0] = c->titlebar_sw->window; } xcb_configure_window(globalconf.connection, c->win, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, @@ -365,12 +365,10 @@ client_stack(client_t *c) void client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) { - client_t *c, *t = NULL; + client_t **lc, *c, *t = NULL; xcb_window_t trans; bool rettrans, retloadprops; - uint32_t config_win_val; tag_t *tag; - rule_t *rule; xcb_size_hints_t *u_size_hints; c = p_new(client_t, 1); @@ -392,13 +390,6 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) c->newcomer = true; c->layer = c->oldlayer = LAYER_TILE; - /* Set windows borders */ - config_win_val = c->border = globalconf.screens[screen].borderpx; - xcb_configure_window(globalconf.connection, w, XCB_CONFIG_WINDOW_BORDER_WIDTH, - &config_win_val); - /* propagates border_width, if size doesn't change */ - window_configure(c->win, c->geometry, c->border); - /* update window title */ client_updatetitle(c); @@ -413,35 +404,6 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) /* Then check clients hints */ ewmh_check_client_hints(c); - /* default titlebar position */ - c->titlebar = globalconf.screens[screen].titlebar_default; - - /* get the matching rule if any */ - rule = rule_matching_client(c); - - /* Then apply rules if no props */ - if(!retloadprops && rule) - { - if(rule->screen != RULE_NOSCREEN) - move_client_to_screen(c, rule->screen, true); - tag_client_with_rule(c, rule); - - switch(rule->isfloating) - { - case Maybe: - break; - case Yes: - client_setfloating(c, true, c->layer != LAYER_TILE ? c->layer : LAYER_FLOAT); - break; - case No: - client_setfloating(c, false, LAYER_TILE); - break; - } - - if(rule->opacity >= 0.0f) - window_settrans(c->win, rule->opacity); - } - /* check for transient and set tags like its parent */ if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans)) && (t = client_get_bywin(globalconf.clients, trans))) @@ -453,28 +415,20 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) if(rettrans || c->isfixed) client_setfloating(c, true, c->layer != LAYER_TILE ? c->layer : LAYER_FLOAT); - /* titlebar init */ - if(rule && rule->titlebar.position != Auto) - c->titlebar = rule->titlebar; - - titlebar_init(c); - - if(!retloadprops + if(globalconf.floating_placement + && !retloadprops && u_size_hints && !(xcb_size_hints_get_flags(u_size_hints) & (XCB_SIZE_US_POSITION_HINT | XCB_SIZE_P_POSITION_HINT))) { if(c->isfloating && !c->ismax) - client_resize(c, globalconf.screens[c->screen].floating_placement(c), false); + client_resize(c, globalconf.floating_placement(c), false); else - c->f_geometry = globalconf.screens[c->screen].floating_placement(c); + c->f_geometry = globalconf.floating_placement(c); xcb_free_size_hints(u_size_hints); } - /* update titlebar with real floating info now */ - titlebar_update_geometry_floating(c); - const uint32_t select_input_val[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_ENTER_WINDOW }; @@ -489,31 +443,16 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) window_setshape(c->win, c->phys_screen); } - /* attach to the stack */ - if(rule) - switch(rule->ismaster) - { - case Yes: - client_list_push(&globalconf.clients, c); - break; - case No: - client_list_append(&globalconf.clients, c); - break; - case Maybe: - rule = NULL; - break; - } - - if(!rule) - { - if(globalconf.screens[c->screen].new_become_master) - client_list_push(&globalconf.clients, c); - else - client_list_append(&globalconf.clients, c); - } + client_list_push(&globalconf.clients, c); widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); ewmh_update_net_client_list(c->phys_screen); + + /* call hook */ + lc = lua_newuserdata(globalconf.L, sizeof(client_t *)); + *lc = c; + luaA_settype(globalconf.L, "client"); + luaA_dofunction(globalconf.L, globalconf.hooks.newclient, 1); } static area_t @@ -574,10 +513,10 @@ client_resize(client_t *c, area_t geometry, bool hints) { int new_screen; area_t area; - Layout *layout = layout_get_current(c->screen); + LayoutArrange *layout = layout_get_current(c->screen); bool resized = false; - if(!c->ismoving && !c->isfloating && layout->arrange != layout_floating) + if(!c->ismoving && !c->isfloating && layout != layout_floating) { titlebar_update_geometry(c, geometry); geometry = titlebar_geometry_remove(&c->titlebar, geometry); @@ -621,7 +560,7 @@ client_resize(client_t *c, area_t geometry, bool hints) /* save the floating geometry if the window is floating but not * maximized */ if(c->ismoving || c->isfloating - || layout_get_current(new_screen)->arrange == layout_floating) + || layout_get_current(new_screen) == layout_floating) { if(!c->ismax) c->f_geometry = geometry; @@ -643,7 +582,7 @@ client_resize(client_t *c, area_t geometry, bool hints) /* call it again like it was floating, * we want it to be sticked to the window */ - if(!c->ismoving && !c->isfloating && layout->arrange != layout_floating) + if(!c->ismoving && !c->isfloating && layout != layout_floating) titlebar_update_geometry_floating(c); return resized; @@ -717,8 +656,8 @@ client_unban(client_t *c) { xcb_map_window(globalconf.connection, c->win); window_setstate(c->win, XCB_WM_NORMAL_STATE); - if(c->titlebar.sw && c->titlebar.position != Off) - xcb_map_window(globalconf.connection, c->titlebar.sw->window); + if(c->titlebar_sw && c->titlebar.position != Off) + xcb_map_window(globalconf.connection, c->titlebar_sw->window); } void @@ -750,7 +689,7 @@ client_unmanage(client_t *c) xcb_aux_sync(globalconf.connection); xcb_ungrab_server(globalconf.connection); - simplewindow_delete(&c->titlebar.sw); + simplewindow_delete(&c->titlebar_sw); p_delete(&c); } @@ -828,21 +767,6 @@ client_updatesizehints(client_t *c) return size; } -/** Get the style related to a client: focus, urgent, normal. - * \param c The client. - * \return The style to apply for this client. - */ -style_t * -client_style_get(client_t *c) -{ - if(globalconf.focus->client == c) - return &globalconf.screens[c->screen].styles.focus; - else if(c->isurgent) - return &globalconf.screens[c->screen].styles.urgent; - - return &globalconf.screens[c->screen].styles.normal; -} - char * client_markup_parse(client_t *c, const char *str, ssize_t len) { @@ -868,192 +792,6 @@ client_markup_parse(client_t *c, const char *str, ssize_t len) return ret; } -/** Set the transparency of the selected client. - * Argument should be an absolut or relativ floating between 0.0 and 1.0 - * \param screen Screen ID - * \param arg unused arg - * \ingroup ui_callback - */ -void -uicb_client_settrans(int screen __attribute__ ((unused)), char *arg) -{ - double delta = 1.0, current_opacity = 100.0; - unsigned int current_opacity_raw = 0; - int set_prop = 0; - client_t *sel = globalconf.focus->client; - xcb_get_property_reply_t *prop_r; - - if(!sel) - return; - - prop_r = xcb_get_property_reply(globalconf.connection, - xcb_get_property_unchecked(globalconf.connection, - false, sel->win, - xutil_intern_atom_reply(globalconf.connection, - &globalconf.atoms, - xutil_intern_atom(globalconf.connection, - &globalconf.atoms, - "_NET_WM_WINDOW_OPACITY")), - CARDINAL, - 0, 1), - NULL); - - if(prop_r) - { - memcpy(¤t_opacity_raw, xcb_get_property_value(prop_r), sizeof(unsigned int)); - current_opacity = (double) current_opacity_raw / 0xffffffff; - p_delete(&prop_r); - } - else - set_prop = 1; - - delta = compute_new_value_from_arg(arg, current_opacity); - - if(delta <= 0.0) - delta = 0.0; - else if(delta > 1.0) - { - delta = 1.0; - set_prop = 1; - } - - if(delta == 1.0 && !set_prop) - window_settrans(sel->win, -1); - else - window_settrans(sel->win, delta); -} - -/** Find a visible client on screen. Return next client or previous client if - * nindex is less than 0. If nindex is 0, then sel itself can be returned if - * visible. - * \param sel Current selected client. - * \param nindex Number of windows to match before returning. - * \return Next or previous visible client. - */ -static client_t * -client_find_visible(client_t *sel, int nindex) -{ - int i = 0, screen; - client_t *next; - client_t *(*client_iter)(client_t **, client_t *) = client_list_next_cycle; - - if(!sel) - return NULL; - - screen = sel->screen; - - if(nindex < 0) - client_iter = client_list_prev_cycle; - else if(nindex == 0) - sel = client_list_prev_cycle(&globalconf.clients, sel); - - nindex = abs(nindex); - - /* look for previous or next starting at sel */ - for(next = client_iter(&globalconf.clients, sel); - next && next != sel; - next = client_iter(&globalconf.clients, next)) - { - if(!next->skip && client_isvisible(next, screen)) - i++; - if(i >= nindex) - return next; - } - - return NULL; -} - -/** Swap the currently focused client with another one. - * The argument must be an integer 1 for next, 2 for next of next, -1 for - * previous, etc. 0 will swap with the visible master window. - * \param screen Virtual screen number. - * \param arg Relative number in the client stack. - * \ingroup ui_callback - */ -void -uicb_client_swap(int screen, char *arg) -{ - client_t *swap = NULL; - int i; - - if(arg && (i = atoi(arg))) - swap = client_find_visible(globalconf.focus->client, i); - else if(globalconf.focus->client == globalconf.clients) - swap = client_find_visible(globalconf.focus->client, 1); - else - swap = globalconf.clients; - - if(swap) - { - client_list_swap(&globalconf.clients, swap, globalconf.focus->client); - globalconf.screens[screen].need_arrange = true; - widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS); - } -} - -/** Move and resize a client. Argument should be in format "x y w h" with - * absolute (1, 20, 300, ...) or relative (+10, -200, ...) values. - * \param screen Screen ID - * \param arg x y w h - * \ingroup ui_callback - */ -void -uicb_client_moveresize(int screen, char *arg) -{ - int ox, oy, ow, oh; /* old geometry */ - char x[8], y[8], w[8], h[8]; - int nmx, nmy; - area_t geometry; - client_t *sel = globalconf.focus->client; - xcb_query_pointer_cookie_t xqc; - xcb_query_pointer_reply_t *xqr; - Layout *curlay = layout_get_current(screen); - - if(!sel || sel->isfixed || !arg || - (curlay->arrange != layout_floating && !sel->isfloating)) - return; - - if(sscanf(arg, "%s %s %s %s", x, y, w, h) != 4) - return; - - xqc = xcb_query_pointer_unchecked(globalconf.connection, - xcb_aux_get_screen(globalconf.connection, sel->phys_screen)->root); - - geometry.x = (int) compute_new_value_from_arg(x, sel->geometry.x); - geometry.y = (int) compute_new_value_from_arg(y, sel->geometry.y); - geometry.width = (int) compute_new_value_from_arg(w, sel->geometry.width); - geometry.height = (int) compute_new_value_from_arg(h, sel->geometry.height); - - ox = sel->geometry.x; - oy = sel->geometry.y; - ow = sel->geometry.width; - oh = sel->geometry.height; - - if(globalconf.screens[sel->screen].resize_hints) - geometry = client_geometry_hints(sel, geometry); - client_resize(sel, geometry, false); - if ((xqr = xcb_query_pointer_reply(globalconf.connection, xqc, NULL))) - { - if(ox <= xqr->root_x && (ox + 2 * sel->border + ow) >= xqr->root_x && - oy <= xqr->root_y && (oy + 2 * sel->border + oh) >= xqr->root_y) - { - nmx = xqr->root_x - (ox + sel->border) + sel->geometry.width - ow; - nmy = xqr->root_y - (oy + sel->border) + sel->geometry.height - oh; - - if(nmx < -sel->border) /* can happen on a resize */ - nmx = -sel->border; - if(nmy < -sel->border) - nmy = -sel->border; - - xcb_warp_pointer(globalconf.connection, - XCB_NONE, sel->win, - 0, 0, 0, 0, nmx, nmy); - } - - p_delete(&xqr); - } -} - /** Kill a client via a WM_DELETE_WINDOW request or XKillClient if not * supported. * \param c the client to kill @@ -1089,189 +827,343 @@ client_kill(client_t *c) xcb_kill_client(globalconf.connection, c->win); } -/** Kill the currently focused client. - * \param screen Screen ID - * \param arg unused - * \ingroup ui_callback - */ -void -uicb_client_kill(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused))) +static int +luaA_client_get(lua_State *L) { - client_t *sel = globalconf.focus->client; + int ret, i = 1; + regex_t r; + regmatch_t match; + client_t *c, **cobj; + const char *name = luaL_checkstring(L, 1); + char error[512]; - if(sel) - client_kill(sel); -} - -/** Maximize the client to the given geometry. - * \param c the client to maximize - * \param geometry the geometry to use for maximizing - */ -static void -client_maximize(client_t *c, area_t geometry) -{ - if((c->ismax = !c->ismax)) + if((ret = regcomp(&r, name, REG_EXTENDED))) { - /* disable titlebar */ - c->titlebar.position = Off; - c->wasfloating = c->isfloating; - c->m_geometry = c->geometry; - if(layout_get_current(c->screen)->arrange != layout_floating) - client_setfloating(c, true, LAYER_FULLSCREEN); - client_focus(c, c->screen, true); - client_resize(c, geometry, false); + regerror(ret, &r, error, sizeof(error)); + luaL_error(L, "regex compilation error: %s\n", error); } - else if(c->wasfloating) - { - c->titlebar.position = c->titlebar.dposition; - client_setfloating(c, true, LAYER_FULLSCREEN); - client_resize(c, c->m_geometry, false); - widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); - } - else if(layout_get_current(c->screen)->arrange == layout_floating) - { - c->titlebar.position = c->titlebar.dposition; - client_resize(c, c->m_geometry, false); - } - else - { - c->titlebar.position = c->titlebar.dposition; - client_setfloating(c, false, LAYER_TILE); - } - widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); -} -/** Toggle maximization state for the focused client. - * \param screen Virtual screen number. - * \param arg Either "vertical", "horizontal" or nothing for both. - * \ingroup ui_callback - */ -void -uicb_client_togglemax(int screen, char *arg) -{ - area_t area; - - if(!globalconf.focus->client) - return; + lua_newtable(L); - area = screen_get_area(screen, - globalconf.screens[screen].statusbar, - &globalconf.screens[screen].padding); - if(arg && arg[0] == 'v') - { - area.x = globalconf.focus->client->geometry.x; - area.width = globalconf.focus->client->geometry.width; - area.height -= 2 * globalconf.focus->client->border; - } - else if(arg && arg[0] == 'h') - { - area.y = globalconf.focus->client->geometry.y; - area.height = globalconf.focus->client->geometry.height; - area.width -= 2 * globalconf.focus->client->border; - } - else - { - area.width -= 2 * globalconf.focus->client->border; - area.height -= 2 * globalconf.focus->client->border; - } - client_maximize(globalconf.focus->client, area); -} - -/** Give focus to the next or previous visible client in the stack. - * Argument mus be a relative number of windows to give focus after current one. - * Giving 1 as argument will focus next visible window, -2 will focus previous - * of previous visible window. Giving 0 as argument will focus master window. - * \param screen Virtual screen number. - * \param arg Relative number in the client stack. - * \ingroup ui_callback - */ -void -uicb_client_focus(int screen, char *arg) -{ - client_t *next = NULL; - int i; - - if(arg && (i = atoi(arg))) - next = client_find_visible(globalconf.focus->client, i); - else if(globalconf.clients) - next = client_find_visible(globalconf.clients, 0); - - if(next) - client_focus(next, screen, true); -} - -/** Set or toggle the floating state of the focused client. - * Argument must be none to toggle, or a boolean value to set. - * \param screen Virtual screen number. - * \param arg - * \ingroup ui_callback - */ -void -uicb_client_setfloating(int screen __attribute__ ((unused)), char *arg) -{ - bool floating; - - if(!globalconf.focus->client) - return; + for(c = globalconf.clients; c; c = c->next) + if(!regexec(&r, c->name, 1, &match, 0)) + { + cobj = lua_newuserdata(L, sizeof(client_t *)); + *cobj = c; + luaA_settype(L, "client"); + lua_rawseti(L, -2, i++); + } - if(!arg) - floating = !globalconf.focus->client->isfloating; - else - floating = a_strtobool(arg); - - client_setfloating(globalconf.focus->client, !globalconf.focus->client->isfloating, - globalconf.focus->client->layer == LAYER_FLOAT ? LAYER_TILE : LAYER_FLOAT); + return 1; } -/** Toggle the scratch client attribute on the focused client. - * \param screen screen number - * \param arg unused argument - * \ingroup ui_callback - */ -void -uicb_client_setscratch(int screen, char *arg __attribute__ ((unused))) +static int +luaA_client_mouse(lua_State *L) { - if(!globalconf.focus->client) - return; + size_t i, len; + int b; + Button *button; - if(globalconf.scratch.client == globalconf.focus->client) - globalconf.scratch.client = NULL; - else - globalconf.scratch.client = globalconf.focus->client; + /* arg 2 is modkey table */ + luaA_checktable(L, 1); + /* arg 3 is mouse button */ + b = luaL_checknumber(L, 2); + /* arg 4 is cmd to run */ + luaA_checkfunction(L, 3); - widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS | WIDGET_CACHE_TAGS); - globalconf.screens[screen].need_arrange = true; -} + button = p_new(Button, 1); + button->button = xutil_button_fromint(b); + button->fct = luaL_ref(L, LUA_REGISTRYINDEX); -void -uicb_client_redraw(int screen __attribute__ ((unused)), - char *arg __attribute__ ((unused))) -{ - if(!globalconf.focus->client) - return; - - /* Use unmap/map ATM but it would be better to used SendEvent, - * however the client doesn't seem to handle it... */ - xcb_unmap_window(globalconf.connection, globalconf.focus->client->win); - xcb_map_window(globalconf.connection, globalconf.focus->client->win); -} - -/** Toggle the scratch client's visibility. - * \param screen screen number - * \param arg unused argument - * \ingroup ui_callback - */ -void -uicb_client_togglescratch(int screen, char *arg __attribute__ ((unused))) -{ - if(globalconf.scratch.client) + len = lua_objlen(L, 1); + for(i = 1; i <= len; i++) { - globalconf.scratch.isvisible = !globalconf.scratch.isvisible; - if(globalconf.scratch.isvisible) - client_focus(globalconf.scratch.client, screen, true); - globalconf.screens[globalconf.scratch.client->screen].need_arrange = true; - widget_invalidate_cache(globalconf.scratch.client->screen, WIDGET_CACHE_CLIENTS); + lua_rawgeti(L, 1, i); + button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); } + + button_list_push(&globalconf.buttons.client, button); + + return 0; } +static int +luaA_client_visible_get(lua_State *L) +{ + int ret, i = 1; + regex_t r; + regmatch_t match; + client_t *c, **cobj; + char error[512]; + int screen = luaL_checknumber(L, 1) - 1; + const char *name = luaL_checkstring(L, 2); + + luaA_checkscreen(screen); + + if((ret = regcomp(&r, name, REG_EXTENDED))) + { + regerror(ret, &r, error, sizeof(error)); + luaL_error(L, "regex compilation error: %s\n", error); + } + + lua_newtable(L); + + for(c = globalconf.clients; c; c = c->next) + if(!c->skip && client_isvisible(c, screen) + && !regexec(&r, c->name, 1, &match, 0)) + { + cobj = lua_newuserdata(L, sizeof(client_t *)); + *cobj = c; + luaA_settype(L, "client"); + lua_rawseti(L, -2, i++); + } + + return 1; +} + +static int +luaA_client_focus_get(lua_State *L) +{ + client_t **cobj; + + if(!globalconf.focus->client) + return 0; + + cobj = lua_newuserdata(L, sizeof(client_t *)); + *cobj = globalconf.focus->client; + luaA_settype(L, "client"); + return 1; +} + +static int +luaA_client_border_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + int width = luaA_getopt_number(L, 2, "width", -1); + const char *colorstr = luaA_getopt_string(L, 2, "color", NULL); + xcolor_t color; + + if(width >= 0) + { + (*c)->border = width; + globalconf.screens[(*c)->screen].need_arrange = true; + xcb_configure_window(globalconf.connection, (*c)->win, + XCB_CONFIG_WINDOW_BORDER_WIDTH, (uint32_t *) &width); + } + + if(colorstr + && draw_color_new(globalconf.connection, (*c)->phys_screen, colorstr, &color)) + xcb_change_window_attributes(globalconf.connection, (*c)->win, XCB_CW_BORDER_PIXEL, + &color.pixel); + + return 0; +} + +static int +luaA_client_titlebar_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + titlebar_t **t = luaL_checkudata(L, 2, "titlebar"); + + /* Copy titlebar info */ + (*c)->titlebar = **t; + titlebar_init(*c); + + if((*c)->isfloating || layout_get_current((*c)->screen) == layout_floating) + titlebar_update_geometry_floating(*c); + else + globalconf.screens[(*c)->screen].need_arrange = true; + + return 0; +} + +static int +luaA_client_screen_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + int screen = luaL_checknumber(L, 2) - 1; + luaA_checkscreen(screen); + move_client_to_screen(*c, screen, true); + return 0; +} + +static int +luaA_client_screen_get(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + lua_pushnumber(L, 1 + (*c)->screen); + return 1; +} + + +static int +luaA_client_tag(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + tag_t **tag = luaL_checkudata(L, 2, "tag"); + bool tag_the_client = luaA_checkboolean(L, 3); + if(tag_the_client) + tag_client(*c, *tag); + else + untag_client(*c, *tag); + return 0; +} + +static int +luaA_client_istagged(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + tag_t **tag = luaL_checkudata(L, 2, "tag"); + lua_pushboolean(L, is_client_tagged(*c, *tag)); + return 1; +} + +static int +luaA_client_coords_get(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + lua_newtable(L); + lua_pushnumber(L, (*c)->geometry.width); + lua_setfield(L, -2, "width"); + lua_pushnumber(L, (*c)->geometry.height); + lua_setfield(L, -2, "height"); + lua_pushnumber(L, (*c)->geometry.x); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, (*c)->geometry.y); + lua_setfield(L, -2, "y"); + return 1; +} + +static int +luaA_client_coords_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + area_t geometry; + + if((*c)->isfloating || layout_get_current((*c)->screen) == layout_floating) + { + luaA_checktable(L, 2); + geometry.x = luaA_getopt_number(L, 2, "x", (*c)->geometry.x); + geometry.y = luaA_getopt_number(L, 2, "y", (*c)->geometry.y); + geometry.width = luaA_getopt_number(L, 2, "width", (*c)->geometry.width); + geometry.height = luaA_getopt_number(L, 2, "height", (*c)->geometry.height); + client_resize(*c, geometry, false); + } + + return 0; +} + +static int +luaA_client_opacity_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + double opacity = luaL_checknumber(L, 2); + + if(opacity == -1 || (opacity >= 0 && opacity <= 100)) + window_settrans((*c)->win, opacity); + return 0; +} + +static int +luaA_client_kill(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + client_kill(*c); + return 0; +} + +static int +luaA_client_swap(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + client_t **swap = luaL_checkudata(L, 2, "client"); + client_list_swap(&globalconf.clients, *swap, *c); + globalconf.screens[(*c)->screen].need_arrange = true; + globalconf.screens[(*swap)->screen].need_arrange = true; + widget_invalidate_cache((*c)->screen, WIDGET_CACHE_CLIENTS); + widget_invalidate_cache((*swap)->screen, WIDGET_CACHE_CLIENTS); + return 0; +} + +static int +luaA_client_focus_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + client_focus(*c, (*c)->screen, false); + return 0; +} + +static int +luaA_client_floating_set(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + bool f = luaA_checkboolean(L, 2); + client_setfloating(*c, f, (*c)->layer == LAYER_FLOAT ? LAYER_TILE : LAYER_FLOAT); + return 0; +} + +static int +luaA_client_floating_get(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + lua_pushboolean(L, (*c)->isfloating); + return 1; +} + +static int +luaA_client_eq(lua_State *L) +{ + client_t **c1 = luaL_checkudata(L, 1, "client"); + client_t **c2 = luaL_checkudata(L, 2, "client"); + lua_pushboolean(L, (*c1 == *c2)); + return 1; +} + +static int +luaA_client_redraw(lua_State *L) +{ + client_t **c = luaL_checkudata(L, 1, "client"); + xcb_unmap_window(globalconf.connection, (*c)->win); + xcb_map_window(globalconf.connection, (*c)->win); + return 0; +} + +static int +luaA_client_tostring(lua_State *L) +{ + client_t **p = luaL_checkudata(L, 1, "client"); + lua_pushfstring(L, "[client udata(%p) name(%s)]", *p, (*p)->name); + return 1; +} + +const struct luaL_reg awesome_client_methods[] = +{ + { "get", luaA_client_get }, + { "focus_get", luaA_client_focus_get }, + { "visible_get", luaA_client_visible_get }, + { "mouse", luaA_client_mouse }, + { NULL, NULL } +}; +const struct luaL_reg awesome_client_meta[] = +{ + { "titlebar_set", luaA_client_titlebar_set }, + { "screen_set", luaA_client_screen_set }, + { "screen_get", luaA_client_screen_get }, + { "border_set", luaA_client_border_set }, + { "tag", luaA_client_tag }, + { "istagged", luaA_client_istagged }, + { "coords_get", luaA_client_coords_get }, + { "coords_set", luaA_client_coords_set }, + { "opacity_set", luaA_client_opacity_set }, + { "kill", luaA_client_kill }, + { "swap", luaA_client_swap }, + { "focus_set", luaA_client_focus_set }, + { "redraw", luaA_client_redraw }, + { "floating_set", luaA_client_floating_set }, + { "floating_get", luaA_client_floating_get }, + { "__eq", luaA_client_eq }, + { "__tostring", luaA_client_tostring }, + { NULL, NULL } +}; + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/client.h b/client.h index 47352a96..d8592925 100644 --- a/client.h +++ b/client.h @@ -43,18 +43,6 @@ void client_saveprops(client_t *); void client_kill(client_t *); void client_setfloating(client_t *, bool, layer_t); char * client_markup_parse(client_t *, const char *, ssize_t); -style_t * client_style_get(client_t *); - -uicb_t uicb_client_kill; -uicb_t uicb_client_moveresize; -uicb_t uicb_client_settrans; -uicb_t uicb_client_swap; -uicb_t uicb_client_togglemax; -uicb_t uicb_client_focus; -uicb_t uicb_client_setfloating; -uicb_t uicb_client_togglescratch; -uicb_t uicb_client_setscratch; -uicb_t uicb_client_redraw; DO_SLIST(client_t, client, p_delete) diff --git a/common/configopts.c b/common/configopts.c index 11062c3b..68b7c24d 100644 --- a/common/configopts.c +++ b/common/configopts.c @@ -24,601 +24,10 @@ #include <sys/stat.h> #include <unistd.h> -#include "rules.h" #include "common/configopts.h" +#include "common/util.h" -#define AWESOME_CONFIG_FILE ".awesomerc" - -#define CFG_AWESOME_END() \ - CFG_FUNC((char *) "include", cfg_awesome_include), \ - CFG_END() - -#define CFG_POSITION(name, value, flags) \ - CFG_PTR_CB(name, value, flags, \ - cfg_position_parse, cfg_value_free) - -#define CFG_ALIGNMENT(name, value, flags) \ - CFG_PTR_CB(name, value, flags, \ - cfg_alignment_parse, cfg_value_free) - -/** This is a better writing of cfg_include coming from libconfuse. - * With this one, we do not treat errors as fatal. - */ -static int -cfg_awesome_include(cfg_t *cfg, cfg_opt_t *opt, - int argc, const char **argv) -{ - char *filename; - FILE *fp; - - if(argc != 1 || !a_strlen(argv[0])) - { - cfg_error(cfg, "wrong number of arguments to cfg_awesome_include()"); - return 0; - } - - filename = cfg_tilde_expand(argv[0]); - - if(!(fp = fopen(filename, "r"))) - { - cfg_error(cfg, "cannot include configuration file %s: %s", - filename, strerror(errno)); - return 0; - } - - p_delete(&filename); - fclose(fp); - - return cfg_include(cfg, opt, argc, argv); -} - -static int -cfg_position_parse(cfg_t *cfg, cfg_opt_t *opt, - const char *value, void *result) -{ - position_t *p = p_new(position_t, 1); - - if((*p = position_get_from_str(value)) == Off - && a_strcmp(value, "off")) - { - cfg_error(cfg, - "position option '%s' must be top, bottom, right, left, auto or off in section '%s'", - opt->name, cfg->name); - p_delete(&p); - return -1; - } - *(void **) result = p; - return 0; -} - -static int -cfg_alignment_parse(cfg_t *cfg, cfg_opt_t *opt, - const char *value, void *result) -{ - alignment_t *p = p_new(alignment_t, 1); - - if((*p = draw_align_get_from_str(value)) == Auto - && a_strcmp(value, "auto")) - { - cfg_error(cfg, - "alignment option '%s' must be left, center, right, flex or auto in section '%s'", - opt->name, cfg->name); - p_delete(&p); - return -1; - } - *(void **) result = p; - return 0; -} - -static void -cfg_value_free(void *value) -{ - p_delete(&value); -} - -alignment_t -cfg_opt_getnalignment(cfg_opt_t *opt, unsigned int oindex) -{ - return * (alignment_t *) cfg_opt_getnptr(opt, oindex); -} - -alignment_t -cfg_getnalignment(cfg_t *cfg, const char *name, unsigned int oindex) -{ - return cfg_opt_getnalignment(cfg_getopt(cfg, name), oindex); -} - -alignment_t -cfg_getalignment(cfg_t *cfg, const char *name) -{ - return cfg_getnalignment(cfg, name, 0); -} - -position_t -cfg_opt_getnposition(cfg_opt_t *opt, unsigned int oindex) -{ - return * (position_t *) cfg_opt_getnptr(opt, oindex); -} - -position_t -cfg_getnposition(cfg_t *cfg, const char *name, unsigned int oindex) -{ - return cfg_opt_getnposition(cfg_getopt(cfg, name), oindex); -} - -position_t -cfg_getposition(cfg_t *cfg, const char *name) -{ - return cfg_getnposition(cfg, name, 0); -} - -/** This section defines a style. */ -cfg_opt_t style_opts[] = -{ - /** Windows border color. */ - CFG_STR((char *) "border", NULL, CFGF_NONE), - /** Background color. */ - CFG_STR((char *) "bg", NULL, CFGF_NONE), - /** Foreground color. */ - CFG_STR((char *) "fg", NULL, CFGF_NONE), - /** Shadow color. */ - CFG_STR((char *) "shadow_color", NULL, CFGF_NONE), - /** Shadow offset in pixels. */ - CFG_INT((char *) "shadow_offset", 0xffffffff, CFGF_NONE), - /** Font to use. */ - CFG_STR((char *) "font", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines several styles in a row. */ -cfg_opt_t styles_opts[] = -{ - /** Normal style. */ - CFG_SEC((char *) "normal", style_opts, CFGF_NONE), - /** Style used for the focused window. */ - CFG_SEC((char *) "focus", style_opts, CFGF_NONE), - /** Style used for windows with urgency hint. */ - CFG_SEC((char *) "urgent", style_opts, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines a titlebar. */ -cfg_opt_t titlebar_opts[] = -{ - /** Titlebar position. */ - CFG_POSITION((char *) "position", (char *) "auto", CFGF_NONE), - /** Titlebar alignment around window. */ - CFG_ALIGNMENT((char *) "align", (char *) "left", CFGF_NONE), - /** Titlebar width. Set to 0 for auto. */ - CFG_INT((char *) "width", 0, CFGF_NONE), - /** Titlebar height. Set to 0 for auto. */ - CFG_INT((char *) "height", 0, CFGF_NONE), - /** Titlebar markup string for normal windows. */ - CFG_STR((char *) "text_normal", (char *) "<title/>", CFGF_NONE), - /** Titlebar markup string for focused windows. */ - CFG_STR((char *) "text_focus", (char *) "<title/>", CFGF_NONE), - /** Titlebar markup string for urgent windows. */ - CFG_STR((char *) "text_urgent", (char *) "<title/>", CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines general options. */ -cfg_opt_t general_opts[] = -{ - /** The border size of windows in pixels. */ - CFG_INT((char *) "border", 1, CFGF_NONE), - /** The number of pixels to snap when moving floating windows. */ - CFG_INT((char *) "snap", 8, CFGF_NONE), - /** Use resize hints when resizing tiled windows. Can produce gaps between windows. */ - CFG_BOOL((char *) "resize_hints", cfg_true, CFGF_NONE), - /** Enable sloppy focus, also known as focus follows mouse. */ - CFG_BOOL((char *) "sloppy_focus", cfg_true, CFGF_NONE), - /** Raise the window if it is given focus with the mouse. */ - CFG_BOOL((char *) "sloppy_focus_raise", cfg_false, CFGF_NONE), - /** New windows become master windows. */ - CFG_BOOL((char *) "new_become_master", cfg_true, CFGF_NONE), - /** New windows get focus. */ - CFG_BOOL((char *) "new_get_focus", cfg_true, CFGF_NONE), - /** Opacity of windows when unfocused. */ - CFG_FLOAT((char *) "opacity_unfocused", -1, CFGF_NONE), - /** Opacity of windows when focused. */ - CFG_FLOAT((char *) "opacity_focused", -1, CFGF_NONE), - /** How to dispose floating windows. Can be smart or under_mouse. */ - CFG_STR((char *) "floating_placement", (char *) "smart", CFGF_NONE), - /** Lower limit for the master window size factor. */ - CFG_FLOAT((char *) "mwfact_lower_limit", 0.1, CFGF_NONE), - /** Upper limit for the master window size factor. */ - CFG_FLOAT((char *) "mwfact_upper_limit", 0.9, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines mouse bindings or the taglist widget. */ -cfg_opt_t mouse_taglist_opts[] = -{ - /** Modifier keys. */ - CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE), - /** Mouse button. */ - CFG_STR((char *) "button", (char *) "XCB_NONE", CFGF_NONE), - /** Uicb command to run. */ - CFG_STR((char *) "command", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines generic mouse bindings. */ -cfg_opt_t mouse_generic_opts[] = -{ - /** Modifier keys. */ - CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE), - /** Mouse button. */ - CFG_STR((char *) "button", (char *) "XCB_NONE", CFGF_NONE), - /** Uicb command to run. */ - CFG_STR((char *) "command", NULL, CFGF_NONE), - /** Arguments to use for command. */ - CFG_STR_LIST((char *) "args", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines common widgets options. */ -cfg_opt_t widget_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Widget alignment. */ - CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), - CFG_AWESOME_END() -}; -/** This section defines taglist widget options. */ -cfg_opt_t widget_taglist_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Widget alignment. */ - CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_taglist_opts, CFGF_MULTI), - /** Markup title string for normal tags */ - CFG_STR((char *) "text_normal", (char *) " <text align=\"center\"/><title/> ", CFGF_NONE), - /** Markup title string for selected tags. */ - CFG_STR((char *) "text_focus", (char *) " <text align=\"center\"/><title/> ", CFGF_NONE), - /** Markup title string for tags with urgent windows. */ - CFG_STR((char *) "text_urgent", (char *) " <text align=\"center\"/><title/> ", CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines iconbox widget options. */ -cfg_opt_t widget_iconbox_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Widget alignment. */ - CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), - /** Image to draw. */ - CFG_STR((char *) "image", NULL, CFGF_NONE), - /** Enable automatic resize of the image. */ - CFG_BOOL((char *) "resize", cfg_true, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines textbox widget options. */ -cfg_opt_t widget_textbox_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Widget alignment. */ - CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), - /** Widget width. Set to 0 for auto. */ - CFG_INT((char *) "width", 0, CFGF_NONE), - /** Default printed text. */ - CFG_STR((char *) "text", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines tasklist widget options */ -cfg_opt_t widget_tasklist_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), - /** Markup title string for normal window. */ - CFG_STR((char *) "text_normal", (char *) "<title/>", CFGF_NONE), - /** Markup title string for focused windows. */ - CFG_STR((char *) "text_focus", (char *) "<title/>", CFGF_NONE), - /** Markup title string for urgent windows. */ - CFG_STR((char *) "text_urgent", (char *) "<title/>", CFGF_NONE), - /** Which windows to show: tags, all or focus. */ - CFG_STR((char *) "show", (char *) "tags", CFGF_NONE), - /** Show icons of windows. */ - CFG_BOOL((char *) "show_icons", cfg_true, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines graph data widget options. */ -cfg_opt_t widget_graph_data_opts[] = -{ - /** Value of a full graph. */ - CFG_FLOAT((char *) "max", 100.0f, CFGF_NONE), - /** Scale graph when values are bigger than 'max'. */ - CFG_BOOL((char *) "scale", cfg_false, CFGF_NONE), - /** Foreground color. */ - CFG_STR((char *) "fg", NULL, CFGF_NONE), - /** Foreground color in the center of the bar (as gradient). */ - CFG_STR((char *) "fg_center", NULL, CFGF_NONE), - /** Foreground color at the end of a bar (as gradient). */ - CFG_STR((char *) "fg_end", NULL, CFGF_NONE), - /** fg, fg_center and fg_end define a vertical gradient. */ - CFG_BOOL((char *) "vertical_gradient", cfg_false, CFGF_NONE), - /** Draw style. */ - CFG_STR((char *) "draw_style", (char *) "bottom", CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines graph widget options. */ -cfg_opt_t widget_graph_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Widget alignment. */ - CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), - /** Data stream. */ - CFG_SEC((char *) "data", widget_graph_data_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Widget width. Set to 0 for auto. */ - CFG_INT((char *) "width", 100, CFGF_NONE), - /** Put new values onto the 'left' or 'right'. */ - CFG_POSITION((char *) "grow", (char *) "left", CFGF_NONE), - /** Set height (i.e. 0.9 = 90%). */ - CFG_FLOAT((char *) "height", 0.67, CFGF_NONE), - /** Background color. */ - CFG_STR((char *) "bg", NULL, CFGF_NONE), - /** Border color. */ - CFG_STR((char *) "bordercolor", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines graph widget options. */ -cfg_opt_t widget_progressbar_data_opts[] = -{ - /** Foreground color. */ - CFG_STR((char *) "fg", NULL, CFGF_NONE), - /** Foreground color in the center of the bar (as gradient). */ - CFG_STR((char *) "fg_center", NULL, CFGF_NONE), - /** Foreground color at the end of a bar (as gradient). */ - CFG_STR((char *) "fg_end", NULL, CFGF_NONE), - /** Foreground color of not filled bar/ticks. */ - CFG_STR((char *) "fg_off", NULL, CFGF_NONE), - /** Background color. */ - CFG_STR((char *) "bg", NULL, CFGF_NONE), - /** Border color. */ - CFG_STR((char *) "bordercolor", NULL, CFGF_NONE), - /** Reverse/mirror the bar. */ - CFG_BOOL((char *) "reverse", cfg_false, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines progressbar widget options. */ -cfg_opt_t widget_progressbar_opts[] = -{ - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Widget alignment. */ - CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), - /** Draws a bar for each data section. */ - CFG_SEC((char *) "data", widget_progressbar_data_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Widget width. */ - CFG_INT((char *) "width", 100, CFGF_NONE), - /** Distance between individual bars. */ - CFG_INT((char *) "gap", 2, CFGF_NONE), - /** Border width in pixels. */ - CFG_INT((char *) "border_width", 1, CFGF_NONE), - /** Padding between border and ticks/bar. */ - CFG_INT((char *) "border_padding", 0, CFGF_NONE), - /** Distance between the ticks. */ - CFG_INT((char *) "ticks_gap", 1, CFGF_NONE), - /** Number of 'ticks' to draw. */ - CFG_INT((char *) "ticks_count", 0, CFGF_NONE), - /** Set height (i.e. 0.9 = 90%). */ - CFG_FLOAT((char *) "height", 0.67, CFGF_NONE), - /** Draw the bar(s) vertically. */ - CFG_BOOL((char *) "vertical", cfg_false, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines statusbar options. */ -cfg_opt_t statusbar_opts[] = -{ - /** Statusbar position. */ - CFG_POSITION((char *) "position", (char *) "top", CFGF_NONE), - /** Statusbar height. Set to 0 for auto. */ - CFG_INT((char *) "height", 0, CFGF_NONE), - /** Statusbar width. Set to 0 for auto. */ - CFG_INT((char *) "width", 0, CFGF_NONE), - /** Textbox widget(s). */ - CFG_SEC((char *) "textbox", widget_textbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Taglist widget(s). */ - CFG_SEC((char *) "taglist", widget_taglist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Layoutinfo widget(s). */ - CFG_SEC((char *) "layoutinfo", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Iconbox widget(s). */ - CFG_SEC((char *) "iconbox", widget_iconbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Focusicon widget(s). */ - CFG_SEC((char *) "focusicon", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Progressbar widget(s). */ - CFG_SEC((char *) "progressbar", widget_progressbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Graph(s) widget(s). */ - CFG_SEC((char *) "graph", widget_graph_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Tasklist(s) widget(s). */ - CFG_SEC((char *) "tasklist", widget_tasklist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - CFG_AWESOME_END() -}; -/** This section defines tag options. */ -cfg_opt_t tag_opts[] = -{ - /** Default layout for this tag. */ - CFG_STR((char *) "layout", (char *) "tile", CFGF_NONE), - /** Default master width factor for this tag. */ - CFG_FLOAT((char *) "mwfact", 0.61803398874989484820, CFGF_NONE), - /** Default number of master windows for this tag. */ - CFG_INT((char *) "nmaster", 1, CFGF_NONE), - /** Default number of window columns for this tag. */ - CFG_INT((char *) "ncol", 1, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines tags options. */ -cfg_opt_t tags_opts[] = -{ - /** Available tag(s). */ - CFG_SEC((char *) "tag", tag_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - CFG_AWESOME_END() -}; -/** This section defines layout options. */ -cfg_opt_t layout_opts[] = -{ - /** Image to represent layout in layoutinfo widget. */ - CFG_STR((char *) "image", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines layouts options. */ -cfg_opt_t layouts_opts[] = -{ - /** Available layout(s). */ - CFG_SEC((char *) "layout", layout_opts, CFGF_TITLE | CFGF_MULTI), - CFG_AWESOME_END() -}; -/** This section defines padding options. */ -cfg_opt_t padding_opts[] = -{ - /** Top padding in pixels. */ - CFG_INT((char *) "top", 0, CFGF_NONE), - /** Bottom padding in pixels. */ - CFG_INT((char *) "bottom", 0, CFGF_NONE), - /** Right padding in pixels. */ - CFG_INT((char *) "right", 0, CFGF_NONE), - /** Left padding in pixels. */ - CFG_INT((char *) "left", 0, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines screen options. */ -cfg_opt_t screen_opts[] = -{ - /** General options. */ - CFG_SEC((char *) "general", general_opts, CFGF_NONE), - /** Titlebar definitions. */ - CFG_SEC((char *) "titlebar", titlebar_opts, CFGF_NONE), - /** Statubar(s) definitions. */ - CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** Tags definitions. */ - CFG_SEC((char *) "tags", tags_opts, CFGF_NONE), - /** Styles definitions. */ - CFG_SEC((char *) "styles", styles_opts, CFGF_NONE), - /** Layouts definitions. */ - CFG_SEC((char *) "layouts", layouts_opts, CFGF_NONE), - /** Paddings definitions. */ - CFG_SEC((char *) "padding", padding_opts, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines rule options. */ -cfg_opt_t rule_opts[] = -{ - /** Name of the xproperty to match. */ - CFG_STR((char *) "xproperty_name", NULL, CFGF_NONE), - /** Regexp value of the xproperty above to match. */ - CFG_STR((char *) "xproperty_value", NULL, CFGF_NONE), - /** Regexp to match the window against a string formatted like: class:name:title. */ - CFG_STR((char *) "name", NULL, CFGF_NONE), - /** Tags matching that regexp to tag windows with. */ - CFG_STR((char *) "tags", NULL, CFGF_NONE), - /** Icon to use for that window. */ - CFG_STR((char *) "icon", NULL, CFGF_NONE), - /** Set this window floating. */ - CFG_STR((char *) "float", (char *) "auto", CFGF_NONE), - /** Set this window as master. */ - CFG_STR((char *) "master", (char *) "auto", CFGF_NONE), - /** Titlebar for this window. */ - CFG_SEC((char *) "titlebar", titlebar_opts, CFGF_NONE), - /** Screen to start this window on. */ - CFG_INT((char *) "screen", RULE_NOSCREEN, CFGF_NONE), - /** Opacity for this window. */ - CFG_FLOAT((char *) "opacity", -1, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines rules options. */ -cfg_opt_t rules_opts[] = -{ - /** A rule. A window can match one rule. */ - CFG_SEC((char *) "rule", rule_opts, CFGF_MULTI), - CFG_AWESOME_END() -}; -/** This section defines a global key binding. */ -cfg_opt_t key_opts[] = -{ - /** Modifier keys. */ - CFG_STR_LIST((char *) "modkey", (char *) "", CFGF_NONE), - /** Key to press. */ - CFG_STR((char *) "key", (char *) "XCB_NONE", CFGF_NONE), - /** Uicb command to run. */ - CFG_STR((char *) "command", (char *) "", CFGF_NONE), - /** Argument to use for command. */ - CFG_STR_LIST((char *) "args", NULL, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines keys options. */ -cfg_opt_t keys_opts[] = -{ - /** A key binding. */ - CFG_SEC((char *) "key", key_opts, CFGF_MULTI), - CFG_AWESOME_END() -}; -/** This section defines mouse options. */ -cfg_opt_t mouse_opts[] = -{ - /** Mouse bindings for the root window. */ - CFG_SEC((char *) "root", mouse_generic_opts, CFGF_MULTI), - /** Mouse bindings for the clients' window. */ - CFG_SEC((char *) "client", mouse_generic_opts, CFGF_MULTI), - /** Mouse bindings for the clients' titlebar. */ - CFG_SEC((char *) "titlebar", mouse_generic_opts, CFGF_MULTI), - CFG_AWESOME_END() -}; -/** This section defines menu options. */ -cfg_opt_t menu_opts[] = -{ - /** Width of the menu. Set to 0 for auto. */ - CFG_INT((char *) "width", 0, CFGF_NONE), - /** Height of the menu. Set to 0 for auto. */ - CFG_INT((char *) "height", 0, CFGF_NONE), - /** X coordinate, do not set for auto. */ - CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), - /** Y coordinate, do not set for auto. */ - CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), - /** Styles to use for this menu. */ - CFG_SEC((char *) "styles", styles_opts, CFGF_NONE), - CFG_AWESOME_END() -}; -/** This section defines global awesome options. */ -cfg_opt_t awesome_opts[] = -{ - /** The screens section. Make one for each of your screens. */ - CFG_SEC((char *) "screen", screen_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - /** The rules section. This allows specific options for specific windows. */ - CFG_SEC((char *) "rules", rules_opts, CFGF_NONE), - /** Key bindings. */ - CFG_SEC((char *) "keys", keys_opts, CFGF_NONE), - /** Mouse bindings. */ - CFG_SEC((char *) "mouse", mouse_opts, CFGF_NONE), - /** Menu options. */ - CFG_SEC((char *) "menu", menu_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - CFG_AWESOME_END() -}; +#define AWESOME_CONFIG_FILE ".awesomerc.lua" /** Return default configuration file path * \return path to the default configuration file @@ -640,144 +49,4 @@ config_file(void) return confpath; } -static int -config_validate_unsigned_int(cfg_t *cfg, cfg_opt_t *opt) -{ - int value = cfg_opt_getnint(opt, cfg_opt_size(opt) - 1); - - if(value < 0) - { - cfg_error(cfg, "integer option '%s' must be positive in section '%s'", - opt->name, cfg->name); - return -1; - } - return 0; -} - -static int -config_validate_supone_int(cfg_t *cfg, cfg_opt_t *opt) -{ - int value = cfg_opt_getnint(opt, cfg_opt_size(opt) - 1); - - if(value < 1) - { - cfg_error(cfg, "integer option '%s' must be at least 1 in section '%s'", - opt->name, cfg->name); - return -1; - } - return 0; -} - -static int -config_validate_zero_one_float(cfg_t *cfg, cfg_opt_t *opt) -{ - float value = cfg_opt_getnfloat(opt, cfg_opt_size(opt) - 1); - - if(value < 0.0 || value > 1.0) - { - cfg_error(cfg, "float option '%s' must be at least 0.0 and less than 1.0 in section '%s'", - opt->name, cfg->name); - return -1; - } - return 0; -} - -static int -config_validate_supzero_float(cfg_t *cfg, cfg_opt_t *opt) -{ - float value = cfg_opt_getnfloat(opt, cfg_opt_size(opt) - 1); - - if(value <= 0.0) - { - cfg_error(cfg, "float option '%s' must be greater than 0.0 section '%s'", - opt->name, cfg->name); - return -1; - } - return 0; -} - -cfg_t * -cfg_new(void) -{ - cfg_t *cfg; - - cfg = cfg_init(awesome_opts, CFGF_NONE); - - /* Check integers values */ - cfg_set_validate_func(cfg, "screen|general|snap", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|general|border", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|height", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|tags|tag|nmaster", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|titlebar|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|titlebar|height", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "rules|rule|titlebar|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "rules|rule|titlebar|height", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "rules|rule|screen", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|textbox|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|graph|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|progressbar|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|progressbar|border_width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|progressbar|border_padding", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|progressbar|ticks_gap", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "screen|statusbar|progressbar|ticks_count", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "menu|width", config_validate_unsigned_int); - cfg_set_validate_func(cfg, "menu|height", config_validate_unsigned_int); - - /* Check integers values > 1 */ - cfg_set_validate_func(cfg, "screen|tags|tag|ncol", config_validate_supone_int); - - /* Check float values */ - cfg_set_validate_func(cfg, "screen|general|mwfact_lower_limit", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "screen|general|mwfact_upper_limit", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "screen|tags|tag|mwfact", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "screen|general|opacity_unfocused", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "screen|general|opacity_focused", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "rules|rule|opacity", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "screen|statusbar|graph|height", config_validate_zero_one_float); - cfg_set_validate_func(cfg, "screen|statusbar|progressbar|height", config_validate_zero_one_float); - - /* Check float values > 0.0 */ - cfg_set_validate_func(cfg, "screen|statusbar|graph|data|max", config_validate_supzero_float); - - return cfg; -} - -/** Check configuration file syntax in regard of libconfuse parsing - * \param path to config file - * \return status returned by cfg_parse() - */ -int -config_check(const char *confpatharg) -{ - cfg_t *cfg; - int ret; - char *confpath; - - cfg = cfg_new(); - - if(confpatharg) - confpath = a_strdup(confpatharg); - else - confpath = config_file(); - - switch((ret = cfg_parse(cfg, confpath))) - { - case CFG_FILE_ERROR: - warn("parsing configuration file failed: %s\n", strerror(errno)); - break; - case CFG_PARSE_ERROR: - cfg_error(cfg, "awesome: parsing configuration file %s failed.\n", confpath); - break; - case CFG_SUCCESS: - printf("Configuration file OK.\n"); - break; - } - - p_delete(&confpath); - cfg_free(cfg); - - return ret; -} - // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/common/configopts.h b/common/configopts.h index 75055f58..be567edc 100644 --- a/common/configopts.h +++ b/common/configopts.h @@ -22,19 +22,7 @@ #ifndef AWESOME_COMMON_CONFIGOPTS_H #define AWESOME_COMMON_CONFIGOPTS_H -#include <confuse.h> - -cfg_t * cfg_new(void); char * config_file(void); -int config_check(const char *); - -alignment_t cfg_opt_getnalignment(cfg_opt_t *, unsigned int); -alignment_t cfg_getnalignment(cfg_t *, const char *, unsigned int); -alignment_t cfg_getalignment(cfg_t *, const char *); - -position_t cfg_opt_getnposition(cfg_opt_t *, unsigned int); -position_t cfg_getnposition(cfg_t *, const char *, unsigned int); -position_t cfg_getposition(cfg_t *, const char *); #endif diff --git a/common/draw.c b/common/draw.c index f85814a1..b7e4ae44 100644 --- a/common/draw.c +++ b/common/draw.c @@ -141,7 +141,7 @@ draw_context_new(xcb_connection_t *conn, int phys_screen, int width, int height, * \return a new font */ font_t * -draw_font_new(xcb_connection_t *conn, int phys_screen, char *fontname) +draw_font_new(xcb_connection_t *conn, int phys_screen, const char *fontname) { cairo_surface_t *surface; xcb_screen_t *s = xcb_aux_get_screen(conn, phys_screen); @@ -213,7 +213,11 @@ typedef struct } margin; bool has_bg_color; xcolor_t bg_color; - shadow_t shadow; + struct + { + int offset; + xcolor_t color; + } shadow; } draw_parser_data_t; static bool @@ -278,13 +282,13 @@ draw_text_markup_expand(draw_parser_data_t *data, * \param style A pointer to the style to use. */ void -draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *style) +draw_text(draw_context_t *ctx, font_t *font, + xcolor_t *fg, area_t area, const char *text) { int x, y; ssize_t len, olen; char *buf = NULL, *utf8 = NULL; PangoRectangle ext; - shadow_t shadow; draw_parser_data_t parser_data; if(!(len = a_strlen(text))) @@ -311,8 +315,6 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty if(parser_data.has_bg_color) draw_rectangle(ctx, area, 1.0, true, parser_data.bg_color); - else - draw_rectangle(ctx, area, 1.0, true, style->bg); pango_layout_set_width(ctx->layout, pango_units_from_double(area.width @@ -320,14 +322,14 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty + parser_data.margin.right))); pango_layout_set_ellipsize(ctx->layout, PANGO_ELLIPSIZE_END); pango_layout_set_markup(ctx->layout, buf, len); - pango_layout_set_font_description(ctx->layout, style->font->desc); + pango_layout_set_font_description(ctx->layout, font->desc); pango_layout_get_pixel_extents(ctx->layout, NULL, &ext); x = area.x + parser_data.margin.left; /* + 1 is added for rounding, so that in any case of doubt we rather draw * the text 1px lower than too high which usually results in a better type * face */ - y = area.y + (ctx->height - style->font->height + 1) / 2; + y = area.y + (ctx->height - font->height + 1) / 2; switch(parser_data.align) { @@ -341,20 +343,13 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty break; } - - p_clear(&shadow, 1); if(parser_data.shadow.offset) - shadow = parser_data.shadow; - else if(style->shadow.offset) - shadow = style->shadow; - - if(shadow.offset) { cairo_set_source_rgb(ctx->cr, - shadow.color.red / 65535.0, - shadow.color.green / 65535.0, - shadow.color.blue / 65535.0); - cairo_move_to(ctx->cr, x + shadow.offset, y + shadow.offset); + parser_data.shadow.color.red / 65535.0, + parser_data.shadow.color.green / 65535.0, + parser_data.shadow.color.blue / 65535.0); + cairo_move_to(ctx->cr, x + parser_data.shadow.offset, y + parser_data.shadow.offset); pango_cairo_update_layout(ctx->cr, ctx->layout); pango_cairo_show_layout(ctx->cr, ctx->layout); } @@ -362,9 +357,9 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty cairo_move_to(ctx->cr, x, y); cairo_set_source_rgb(ctx->cr, - style->fg.red / 65535.0, - style->fg.green / 65535.0, - style->fg.blue / 65535.0); + fg->red / 65535.0, + fg->green / 65535.0, + fg->blue / 65535.0); pango_cairo_update_layout(ctx->cr, ctx->layout); pango_cairo_show_layout(ctx->cr, ctx->layout); @@ -1078,48 +1073,6 @@ draw_color_new(xcb_connection_t *conn, int phys_screen, const char *colstr, xcol return false; } -/** Init a style struct. Every value will be inherited from m - * if they are not set in the configuration section cfg. - * \param disp Display ref - * \param phys_screen Physical screen number - * \param cfg style configuration section - * \param c style to fill - * \param m style to use as template - */ -void -draw_style_init(xcb_connection_t *conn, int phys_screen, cfg_t *cfg, - style_t *c, style_t *m) -{ - char *buf; - int shadow; - - if(m) - *c = *m; - - if(!cfg) - return; - - if((buf = cfg_getstr(cfg, "font"))) - c->font = draw_font_new(conn, phys_screen, buf); - - draw_color_new(conn, phys_screen, - cfg_getstr(cfg, "fg"), &c->fg); - - draw_color_new(conn, phys_screen, - cfg_getstr(cfg, "bg"), &c->bg); - - draw_color_new(conn, phys_screen, - cfg_getstr(cfg, "border"), &c->border); - - draw_color_new(conn, phys_screen, - cfg_getstr(cfg, "shadow_color"), &c->shadow.color); - - if((shadow = cfg_getint(cfg, "shadow_offset")) != (int) 0xffffffff) - c->shadow.offset = shadow; - else if(!m) - c->shadow.offset = 0; -} - /** Remove a area from a list of them, * spliting the space between several area that can overlap * \param head list head diff --git a/common/draw.h b/common/draw.h index a3c6b8db..fcfa5dda 100644 --- a/common/draw.h +++ b/common/draw.h @@ -35,7 +35,7 @@ typedef enum { - AlignLeft, + AlignLeft = 0, AlignRight, AlignCenter, AlignFlex, @@ -88,27 +88,6 @@ typedef struct int height; } font_t; -typedef struct -{ - int offset; - xcolor_t color; -} shadow_t; - -/** Style structure */ -typedef struct -{ - /** Foreground color */ - xcolor_t fg; - /** Background color */ - xcolor_t bg; - /** Shadow color */ - shadow_t shadow; - /** Border color */ - xcolor_t border; - /** Font */ - font_t *font; -} style_t; - typedef struct { xcb_connection_t *connection; @@ -132,17 +111,20 @@ draw_context_delete(draw_context_t **ctx) { if(*ctx) { - g_object_unref((*ctx)->layout); - cairo_surface_destroy((*ctx)->surface); - cairo_destroy((*ctx)->cr); + if((*ctx)->layout) + g_object_unref((*ctx)->layout); + if((*ctx)->surface) + cairo_surface_destroy((*ctx)->surface); + if((*ctx)->cr) + cairo_destroy((*ctx)->cr); p_delete(ctx); } } -font_t *draw_font_new(xcb_connection_t *, int, char *); +font_t *draw_font_new(xcb_connection_t *, int, const char *); void draw_font_delete(font_t **); -void draw_text(draw_context_t *, area_t, const char *, const style_t *); +void draw_text(draw_context_t *, font_t *, xcolor_t *, area_t, const char *); void draw_rectangle(draw_context_t *, area_t, float, bool, xcolor_t); void draw_rectangle_gradient(draw_context_t *, area_t, float, bool, area_t, xcolor_t *, xcolor_t *, xcolor_t *); @@ -157,7 +139,6 @@ void draw_rotate(draw_context_t *, xcb_drawable_t, int, int, double, int, int); area_t draw_text_extents(xcb_connection_t *, int, font_t *, const char *); alignment_t draw_align_get_from_str(const char *); bool draw_color_new(xcb_connection_t *, int, const char *, xcolor_t *); -void draw_style_init(xcb_connection_t *, int, cfg_t *, style_t *, style_t *); void area_list_remove(area_t **, area_t *); diff --git a/common/list.h b/common/list.h index 8589e9e2..c59355f2 100644 --- a/common/list.h +++ b/common/list.h @@ -159,7 +159,7 @@ return NULL; \ } \ \ - static inline void prefix##_list_detach(type **list, type *item) \ + static inline type *prefix##_list_detach(type **list, type *item) \ { \ if(item == *list) \ *list = item->next; \ @@ -169,7 +169,27 @@ item->next->prev = item->prev; \ item->next = NULL; \ item->prev = NULL; \ - } \ + return item; \ + } + +#define DO_SLIST_UNREF(type, prefix, dtor) \ + static inline void prefix##_list_unref(type **list) \ + { \ + type *next, *item = *list; \ + printf("list_unref\n");\ + while(item) \ + { \ + printf(" item %p refcount %d", item, item->refcount);\ + next = item->next; \ + if(--(item->refcount) <= 0) \ + { \ + prefix##_list_detach(list, item); \ + dtor(&item); \ + } \ + item = next; \ + } \ + printf("end list_unref\n");\ + } #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/common/refcount.h b/common/refcount.h new file mode 100644 index 00000000..1eb56c79 --- /dev/null +++ b/common/refcount.h @@ -0,0 +1,39 @@ +/* + * refcount.h - useful reference counter handling header + * + * Copyright © 2008 Julien Danjou <julien@danjou.info> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef AWESOME_COMMON_REFCOUNT_H +#define AWESOME_COMMON_REFCOUNT_H + +#include <assert.h> + +#define DO_RCNT(type, prefix, dtor) \ + static inline void prefix##_unref(type **item) \ + { \ + if(--(*item)->refcount <= 0) \ + dtor(item); \ + } \ + \ + static inline void prefix##_ref(type **item) \ + { \ + (*item)->refcount++; \ + } + +#endif +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/common/util.c b/common/util.c index edacee93..983f7141 100644 --- a/common/util.c +++ b/common/util.c @@ -175,7 +175,8 @@ fuzzy_get_from_str(const char *str) * * \return minimum of \c src \e length and \c l. */ -ssize_t a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l) +ssize_t +a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l) { ssize_t len = MIN(a_strlen(src), l); @@ -200,7 +201,8 @@ ssize_t a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l) * \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 +a_strcpy(char *dst, ssize_t n, const char *src) { ssize_t len = a_strlen(src); @@ -213,4 +215,28 @@ ssize_t a_strcpy(char *dst, ssize_t n, const char *src) return len; } + +/** Execute a command and replace the current process. + * \param cmd The command to execute. + */ +void +a_exec(const char *cmd) +{ + char *args, *path; + + /* Ignore the leading spaces if any */ + while(cmd[0] && cmd[0] == ' ') cmd++; + + /* Get the beginning of the arguments */ + args = strchr(cmd, ' '); + if(args) + path = a_strndup(cmd, args - cmd); + else + path = a_strndup(cmd, a_strlen(cmd)); + + execlp(path, cmd, NULL); + + p_delete(&path); +} + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/common/util.h b/common/util.h index cf44f0c9..af0bc9a5 100644 --- a/common/util.h +++ b/common/util.h @@ -284,6 +284,7 @@ char * position_to_str(position_t); fuzzy_t fuzzy_get_from_str(const char *); double compute_new_value_from_arg(const char *, double); void *name_func_lookup(const char *, const name_func_link_t *); +void a_exec(const char *); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/common/xutil.c b/common/xutil.c index 0ca4f0cf..c7f2354a 100644 --- a/common/xutil.c +++ b/common/xutil.c @@ -505,4 +505,79 @@ xutil_delete_error(xutil_error_t *err) p_delete(&err); } +/** Link a name to a key symbol */ +typedef struct +{ + const char *name; + xcb_keysym_t keysym; +} keymod_t; + +xcb_keysym_t +xutil_keymask_fromstr(const char *keyname) +{ + /** List of keyname and corresponding X11 mask codes */ + static const keymod_t KeyModList[] = + { + { "Shift", XCB_MOD_MASK_SHIFT }, + { "Lock", XCB_MOD_MASK_LOCK }, + { "Control", XCB_MOD_MASK_CONTROL }, + { "Ctrl", XCB_MOD_MASK_CONTROL }, + { "Mod1", XCB_MOD_MASK_1 }, + { "Mod2", XCB_MOD_MASK_2 }, + { "Mod3", XCB_MOD_MASK_3 }, + { "Mod4", XCB_MOD_MASK_4 }, + { "Mod5", XCB_MOD_MASK_5 }, + { NULL, XCB_NO_SYMBOL } + }; + int i; + + if(keyname) + for(i = 0; KeyModList[i].name; i++) + if(!a_strcmp(keyname, KeyModList[i].name)) + return KeyModList[i].keysym; + + return XCB_NO_SYMBOL; + +} + +/** Permit to use mouse with many more buttons */ +#ifndef XCB_BUTTON_INDEX_6 +#define XCB_BUTTON_INDEX_6 6 +#endif +#ifndef XCB_BUTTON_INDEX_7 +#define XCB_BUTTON_INDEX_7 7 +#endif + +/** Link a name to a mouse button symbol */ +typedef struct +{ + int id; + unsigned int button; +} mouse_button_t; + +/** Lookup for a mouse button from its index. + * \param button Mouse button index. + * \return Mouse button or 0 if not found. + */ +unsigned int +xutil_button_fromint(int button) +{ + /** List of button name and corresponding X11 mask codes */ + static const mouse_button_t mouse_button_list[] = + { + { 1, XCB_BUTTON_INDEX_1 }, + { 2, XCB_BUTTON_INDEX_2 }, + { 3, XCB_BUTTON_INDEX_3 }, + { 4, XCB_BUTTON_INDEX_4 }, + { 5, XCB_BUTTON_INDEX_5 }, + { 6, XCB_BUTTON_INDEX_6 }, + { 7, XCB_BUTTON_INDEX_7 } + }; + + if(button >= 1 && button <= countof(mouse_button_list)) + return mouse_button_list[button - 1].button; + + return 0; +} + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/common/xutil.h b/common/xutil.h index d06fff27..1e7e6eec 100644 --- a/common/xutil.h +++ b/common/xutil.h @@ -158,6 +158,8 @@ typedef struct xutil_error_t *xutil_get_error(const xcb_generic_error_t *); void xutil_delete_error(xutil_error_t *); +xcb_keysym_t xutil_keymask_fromstr(const char *); +unsigned int xutil_button_fromint(int); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/config.c b/config.c deleted file mode 100644 index 0fb1bf21..00000000 --- a/config.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * config.c - configuration management - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/* XStringToKeysym() */ -#include <X11/Xlib.h> - -#include <errno.h> - -#include "config.h" -#include "statusbar.h" -#include "tag.h" -#include "rules.h" -#include "screen.h" -#include "widget.h" -#include "defconfig.h" -#include "layouts/tile.h" -#include "common/configopts.h" -#include "common/xutil.h" - -/* Permit to use mouse with many more buttons */ -#ifndef XCB_BUTTON_INDEX_6 -#define XCB_BUTTON_INDEX_6 6 -#endif -#ifndef XCB_BUTTON_INDEX_7 -#define XCB_BUTTON_INDEX_7 7 -#endif - -extern AwesomeConf globalconf; -extern cfg_opt_t awesome_opts[]; - -/** Link a name to a key symbol */ -typedef struct -{ - const char *name; - xcb_keysym_t keysym; -} keymod_t; - -/** Link a name to a mouse button symbol */ -typedef struct -{ - const char *name; - unsigned int button; -} mouse_button_t; - -extern const name_func_link_t UicbList[]; -extern const name_func_link_t WidgetList[]; -extern const name_func_link_t LayoutList[]; -extern const name_func_link_t FloatingPlacementList[]; - -/** Lookup for a key mask from its name - * \param keyname Key name - * \return Key mask or 0 if not found - */ -static xcb_keysym_t -key_mask_lookup(const char *keyname) -{ - /** List of keyname and corresponding X11 mask codes */ - static const keymod_t KeyModList[] = - { - {"Shift", XCB_MOD_MASK_SHIFT}, - {"Lock", XCB_MOD_MASK_LOCK}, - {"Control", XCB_MOD_MASK_CONTROL}, - {"Mod1", XCB_MOD_MASK_1}, - {"Mod2", XCB_MOD_MASK_2}, - {"Mod3", XCB_MOD_MASK_3}, - {"Mod4", XCB_MOD_MASK_4}, - {"Mod5", XCB_MOD_MASK_5}, - {NULL, XCB_NO_SYMBOL} - }; - int i; - - if(keyname) - for(i = 0; KeyModList[i].name; i++) - if(!a_strcmp(keyname, KeyModList[i].name)) - return KeyModList[i].keysym; - - return 0; -} - -/** Lookup for a mouse button from its name - * \param button Mouse button name - * \return Mouse button or 0 if not found - */ -static unsigned int -mouse_button_lookup(const char *button) -{ - /** List of button name and corresponding X11 mask codes */ - static const mouse_button_t mouse_button_tList[] = - { - {"1", XCB_BUTTON_INDEX_1}, - {"2", XCB_BUTTON_INDEX_2}, - {"3", XCB_BUTTON_INDEX_3}, - {"4", XCB_BUTTON_INDEX_4}, - {"5", XCB_BUTTON_INDEX_5}, - {"6", XCB_BUTTON_INDEX_6}, - {"7", XCB_BUTTON_INDEX_7}, - {NULL, 0} - }; - int i; - - if(button) - for(i = 0; mouse_button_tList[i].name; i++) - if(!a_strcmp(button, mouse_button_tList[i].name)) - return mouse_button_tList[i].button; - - return 0; -} - -static Button * -parse_mouse_bindings(cfg_t * cfg, const char *secname, bool handle_arg) -{ - int i, j; - cfg_t *cfgsectmp; - Button *b = NULL, *head = NULL; - - /* Mouse: layout click bindings */ - for(i = cfg_size(cfg, secname) - 1; i >= 0; i--) - { - b = p_new(Button, 1); - - cfgsectmp = cfg_getnsec(cfg, secname, i); - for(j = cfg_size(cfgsectmp, "modkey") - 1; j >= 0; j--) - b->mod |= key_mask_lookup(cfg_getnstr(cfgsectmp, "modkey", j)); - b->button = mouse_button_lookup(cfg_getstr(cfgsectmp, "button")); - b->func = name_func_lookup(cfg_getstr(cfgsectmp, "command"), UicbList); - if(!b->func) - warn("unknown command %s\n", cfg_getstr(cfgsectmp, "command")); - if(handle_arg) - b->arg = a_strdup(cfg_getnstr(cfgsectmp, "args", 0)); - else - b->arg = NULL; - - button_list_push(&head, b); - } - - return head; -} - -static void -config_key_store(keybinding_t *key, char *str) -{ - xcb_keycode_t kc; - int ikc; - - if(!a_strlen(str)) - return; - else if(a_strncmp(str, "#", 1)) - key->keysym = XStringToKeysym(str); - else - { - ikc = atoi(str + 1); - memcpy(&kc, &ikc, sizeof(KeyCode)); - key->keycode = kc; - } -} - -static int -cmp_widget_cfg(const void *a, const void *b) -{ - if (((cfg_t*)a)->line < ((cfg_t*)b)->line) - return -1; - - if (((cfg_t*)a)->line > ((cfg_t*)b)->line) - return 1; - - return 0; -} - -static void -statusbar_widgets_create(cfg_t *cfg_statusbar, statusbar_t *statusbar) -{ - cfg_t* widgets, *wptr; - widget_t *widget = NULL; - unsigned int i, j, numwidgets = 0; - WidgetConstructor *widget_new; - - for(i = 0; WidgetList[i].name; i++) - numwidgets += cfg_size(cfg_statusbar, WidgetList[i].name); - - wptr = widgets = p_new(cfg_t, numwidgets); - - for(i = 0; WidgetList[i].name; i++) - for (j = 0; j < cfg_size(cfg_statusbar, WidgetList[i].name); j++) - { - memcpy(wptr, - cfg_getnsec(cfg_statusbar, WidgetList[i].name, j), - sizeof(cfg_t)); - wptr++; - } - - qsort(widgets, numwidgets, sizeof(cfg_t), cmp_widget_cfg); - - for(i = 0; i < numwidgets; i++) - { - wptr = &widgets[i]; - widget_new = name_func_lookup(cfg_name(wptr), WidgetList); - if(widget_new) - { - widget = widget_new(statusbar, wptr); - widget_list_append(&statusbar->widgets, widget); - widget->buttons = parse_mouse_bindings(wptr, "mouse", - a_strcmp(cfg_name(wptr), "taglist") ? true : false); - } - else - warn("ignoring unknown widget: %s.\n", cfg_name(widgets + i)); - } - p_delete(&widgets); -} - -static void -config_section_titlebar_init(cfg_t *cfg_titlebar, titlebar_t *tb) -{ - tb->position = tb->dposition = cfg_getposition(cfg_titlebar, "position"); - tb->align = cfg_getalignment(cfg_titlebar, "align"); - tb->width = cfg_getint(cfg_titlebar, "width"); - tb->height = cfg_getint(cfg_titlebar, "height"); - tb->text_normal = a_strdup(cfg_getstr(cfg_titlebar, "text_normal")); - tb->text_focus = a_strdup(cfg_getstr(cfg_titlebar, "text_focus")); - tb->text_urgent = a_strdup(cfg_getstr(cfg_titlebar, "text_urgent")); -} - -static void -config_parse_screen(cfg_t *cfg, int screen) -{ - char buf[2]; - const char *tmp; - FloatingPlacement flpl; - Layout *layout = NULL; - tag_t *tag = NULL; - statusbar_t *statusbar = NULL; - cfg_t *cfg_general, *cfg_styles, *cfg_screen, *cfg_tags, - *cfg_layouts, *cfg_padding, *cfgsectmp, *cfg_titlebar, - *cfg_styles_normal, *cfg_styles_focus, *cfg_styles_urgent; - VirtScreen *virtscreen = &globalconf.screens[screen]; - int i, phys_screen = screen_virttophys(screen); - - snprintf(buf, sizeof(buf), "%d", screen); - cfg_screen = cfg_gettsec(cfg, "screen", buf); - if(!cfg_screen) - cfg_screen = cfg_getsec(cfg, "screen"); - - if(!cfg_screen) - { - warn("parsing configuration file failed, no screen section found\n"); - cfg_parse_buf(cfg, AWESOME_DEFAULT_CONFIG); - cfg_screen = cfg_getsec(cfg, "screen"); - } - - /* get screen specific sections */ - cfg_tags = cfg_getsec(cfg_screen, "tags"); - cfg_styles = cfg_getsec(cfg_screen, "styles"); - cfg_general = cfg_getsec(cfg_screen, "general"); - cfg_titlebar = cfg_getsec(cfg_screen, "titlebar"); - cfg_layouts = cfg_getsec(cfg_screen, "layouts"); - cfg_padding = cfg_getsec(cfg_screen, "padding"); - - - /* General section */ - virtscreen->borderpx = cfg_getint(cfg_general, "border"); - virtscreen->snap = cfg_getint(cfg_general, "snap"); - virtscreen->resize_hints = cfg_getbool(cfg_general, "resize_hints"); - virtscreen->sloppy_focus = cfg_getbool(cfg_general, "sloppy_focus"); - virtscreen->sloppy_focus_raise = cfg_getbool(cfg_general, "sloppy_focus_raise"); - virtscreen->new_become_master = cfg_getbool(cfg_general, "new_become_master"); - virtscreen->new_get_focus = cfg_getbool(cfg_general, "new_get_focus"); - virtscreen->opacity_unfocused = cfg_getfloat(cfg_general, "opacity_unfocused"); - virtscreen->opacity_focused = cfg_getfloat(cfg_general, "opacity_focused"); - virtscreen->floating_placement = - name_func_lookup(cfg_getstr(cfg_general, "floating_placement"), - FloatingPlacementList); - virtscreen->mwfact_lower_limit = cfg_getfloat(cfg_general, "mwfact_lower_limit"); - virtscreen->mwfact_upper_limit = cfg_getfloat(cfg_general, "mwfact_upper_limit"); - - if(virtscreen->mwfact_upper_limit < virtscreen->mwfact_lower_limit) - { - warn("mwfact_upper_limit must be greater than mwfact_lower_limit\n"); - virtscreen->mwfact_upper_limit = 0.9; - virtscreen->mwfact_lower_limit = 0.1; - } - - if(!virtscreen->floating_placement) - { - warn("unknown floating placement: %s\n", cfg_getstr(cfg_general, "floating_placement")); - virtscreen->floating_placement = FloatingPlacementList[0].func; - } - - /* Colors */ - if(!cfg_styles) - eprint("no colors section found"); - - if(!(cfg_styles_normal = cfg_getsec(cfg_styles, "normal"))) - eprint("no normal colors section found\n"); - if(!(cfg_styles_focus = cfg_getsec(cfg_styles, "focus"))) - eprint("no focus colors section found\n"); - if(!(cfg_styles_urgent = cfg_getsec(cfg_styles, "urgent"))) - eprint("no urgent colors section found\n"); - - draw_style_init(globalconf.connection, phys_screen, - cfg_styles_normal, &virtscreen->styles.normal, NULL); - draw_style_init(globalconf.connection, phys_screen, - cfg_styles_focus, &virtscreen->styles.focus, &virtscreen->styles.normal); - draw_style_init(globalconf.connection, phys_screen, - cfg_styles_urgent, &virtscreen->styles.urgent, &virtscreen->styles.normal); - - if(!virtscreen->styles.normal.font) - eprint("no font available\n"); - - /* Titlebar */ - config_section_titlebar_init(cfg_titlebar, &virtscreen->titlebar_default); - - /* statusbar_t */ - statusbar_list_init(&virtscreen->statusbar); - for(i = cfg_size(cfg_screen, "statusbar") - 1; i >= 0; i--) - { - statusbar = p_new(statusbar_t, 1); - cfgsectmp = cfg_getnsec(cfg_screen, "statusbar", i); - statusbar->position = statusbar->dposition = - cfg_getposition(cfgsectmp, "position"); - statusbar->height = cfg_getint(cfgsectmp, "height"); - statusbar->width = cfg_getint(cfgsectmp, "width"); - statusbar->name = a_strdup(cfg_title(cfgsectmp)); - statusbar->screen = screen; - statusbar_preinit(statusbar); - statusbar_widgets_create(cfgsectmp, statusbar); - statusbar_list_push(&virtscreen->statusbar, statusbar); - } - - /* Layouts */ - layout_list_init(&virtscreen->layouts); - if((i = cfg_size(cfg_layouts, "layout"))) - for(--i; i >= 0; i--) - { - layout = p_new(Layout, 1); - cfgsectmp = cfg_getnsec(cfg_layouts, "layout", i); - layout->arrange = name_func_lookup(cfg_title(cfgsectmp), LayoutList); - if(!layout->arrange) - { - warn("unknown layout %s in configuration file\n", cfg_title(cfgsectmp)); - layout->image = NULL; - continue; - } - layout->image = a_strdup(cfg_getstr(cfgsectmp, "image")); - - layout_list_push(&virtscreen->layouts, layout); - } - else - { - warn("no default layout available\n"); - layout = p_new(Layout, 1); - layout->arrange = layout_tile; - layout_list_push(&virtscreen->layouts, layout); - } - - /* Tags */ - tag_list_init(&virtscreen->tags); - if((i = cfg_size(cfg_tags, "tag"))) - for(--i; i >= 0; i--) - { - cfgsectmp = cfg_getnsec(cfg_tags, "tag", i); - - tmp = cfg_getstr(cfgsectmp, "layout"); - for(layout = virtscreen->layouts; - layout && layout->arrange != name_func_lookup(tmp, LayoutList); - layout = layout->next); - if(!layout) - layout = virtscreen->layouts; - - tag = tag_new(cfg_title(cfgsectmp), - layout, - cfg_getfloat(cfgsectmp, "mwfact"), - cfg_getint(cfgsectmp, "nmaster"), - cfg_getint(cfgsectmp, "ncol")); - - tag_push_to_screen(tag, screen); - } - else - { - warn("fatal: no tags found in configuration file\n"); - tag = tag_new("default", virtscreen->layouts, 0.5, 1, 1); - tag_push_to_screen(tag, screen); - } - - /* select first tag by default */ - virtscreen->tags[0].selected = true; - virtscreen->tags[0].was_selected = true; - - /* padding */ - virtscreen->padding.top = cfg_getint(cfg_padding, "top"); - virtscreen->padding.bottom = cfg_getint(cfg_padding, "bottom"); - virtscreen->padding.left = cfg_getint(cfg_padding, "left"); - virtscreen->padding.right = cfg_getint(cfg_padding, "right"); -} - -/** Parse configuration file and initialize some stuff - * \param confpatharg Path to configuration file - */ -void -config_parse(const char *confpatharg) -{ - cfg_t *cfg, *cfg_rules, *cfg_keys, *cfg_mouse, *cfgsectmp; - int ret, screen, i; - unsigned int j; - char *confpath; - rule_t *rule = NULL; - keybinding_t *key; - FILE *defconfig = NULL; - - if(confpatharg) - confpath = a_strdup(confpatharg); - else - confpath = config_file(); - - globalconf.configpath = a_strdup(confpath); - - cfg = cfg_new(); - - ret = cfg_parse(cfg, confpath); - - switch(ret) - { - case CFG_FILE_ERROR: - warn("parsing configuration file failed: %s\n", strerror(errno)); - if(!(defconfig = fopen(confpath, "w"))) - warn("unable to create default configuration file: %s\n", strerror(errno)); - break; - case CFG_PARSE_ERROR: - cfg_error(cfg, "W: awesome: parsing configuration file %s failed.\n", confpath); - break; - } - - if(ret != CFG_SUCCESS) - { - warn("using default compile-time configuration\n"); - cfg_free(cfg); - cfg = cfg_init(awesome_opts, CFGF_NONE); - cfg_parse_buf(cfg, AWESOME_DEFAULT_CONFIG); - } - - /* get the right screen section */ - for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) - config_parse_screen(cfg, screen); - - /* get general sections */ - cfg_rules = cfg_getsec(cfg, "rules"); - cfg_keys = cfg_getsec(cfg, "keys"); - cfg_mouse = cfg_getsec(cfg, "mouse"); - - /* Rules */ - rule_list_init(&globalconf.rules); - for(i = cfg_size(cfg_rules, "rule") - 1; i >= 0; i--) - { - rule = p_new(rule_t, 1); - cfgsectmp = cfg_getnsec(cfg_rules, "rule", i); - rule->prop_r = rules_compile_regex(cfg_getstr(cfgsectmp, "name")); - rule->tags_r = rules_compile_regex(cfg_getstr(cfgsectmp, "tags")); - rule->xprop = a_strdup(cfg_getstr(cfgsectmp, "xproperty_name")); - rule->xpropval_r = rules_compile_regex(cfg_getstr(cfgsectmp, "xproperty_value")); - rule->icon = a_strdup(cfg_getstr(cfgsectmp, "icon")); - rule->isfloating = fuzzy_get_from_str(cfg_getstr(cfgsectmp, "float")); - rule->screen = cfg_getint(cfgsectmp, "screen"); - rule->ismaster = fuzzy_get_from_str(cfg_getstr(cfgsectmp, "master")); - rule->opacity = cfg_getfloat(cfgsectmp, "opacity"); - config_section_titlebar_init(cfg_getsec(cfgsectmp, "titlebar"), &rule->titlebar); - if(rule->screen >= globalconf.screens_info->nscreen) - rule->screen = 0; - - rule_list_push(&globalconf.rules, rule); - } - - /* Key bindings */ - keybinding_list_init(&globalconf.keys); - for(i = cfg_size(cfg_keys, "key") - 1; i >= 0; i--) - { - key = p_new(keybinding_t, 1); - cfgsectmp = cfg_getnsec(cfg_keys, "key", i); - config_key_store(key, cfg_getstr(cfgsectmp, "key")); - for(j = 0; j < cfg_size(cfgsectmp, "modkey"); j++) - key->mod |= key_mask_lookup(cfg_getnstr(cfgsectmp, "modkey", j)); - if(!(key->func = name_func_lookup(cfg_getstr(cfgsectmp, "command"), UicbList))) - warn("unknown command %s\n", cfg_getstr(cfgsectmp, "command")); - key->arg = a_strdup(cfg_getnstr(cfgsectmp, "args", 0)); - printf("key %s %s %d\n", cfg_getstr(cfgsectmp, "command"), key->arg, key->keysym); - keybinding_list_push(&globalconf.keys, key); - } - - /* Mouse: root window click bindings */ - globalconf.buttons.root = parse_mouse_bindings(cfg_mouse, "root", true); - - /* Mouse: client windows click bindings */ - globalconf.buttons.client = parse_mouse_bindings(cfg_mouse, "client", true); - - /* Mouse: titlebar windows click bindings */ - globalconf.buttons.titlebar = parse_mouse_bindings(cfg_mouse, "titlebar", true); - - if(defconfig) - { - fwrite(AWESOME_DEFAULT_CONFIG, a_strlen(AWESOME_DEFAULT_CONFIG), 1, defconfig); - fclose(defconfig); - } - - /* Free! Like a river! */ - cfg_free(cfg); - p_delete(&confpath); -} - -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/config.h b/config.h deleted file mode 100644 index c53339d2..00000000 --- a/config.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * config.h - configuration management header - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef AWESOME_CONFIG_H -#define AWESOME_CONFIG_H - -#include "structs.h" - -DO_SLIST(keybinding_t, keybinding, p_delete) -DO_SLIST(Button, button, p_delete) - -void config_parse(const char *); - -#endif -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/configure.ac b/configure.ac index fe2c756d..9500b759 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,8 @@ # -*- Autoconf -*- # Process this file with autoreconf to produce a configure script. +m4_include(as_ac_expand.m4) + AC_PREREQ(2.61) dnl Each time you want an updated version number for your build, you need to dnl (re-)run autoreconf. @@ -44,17 +46,14 @@ AC_ARG_VAR([DOXYGEN], [doxygen source documentation system]) test "x$ASCIIDOC" = "x" && AC_PATH_PROG([ASCIIDOC], [asciidoc], [:]) test "x$XMLTO" = "x" && AC_PATH_PROG([XMLTO], [xmlto], [:]) -test "x$DOXYGEN" = "x" && AC_PATH_PROG([PYTHON], [python], [:]) test "x$DOXYGEN" = "x" && AC_PATH_PROG([DOXYGEN], [doxygen], [:]) test "x$ASCIIDOC" = "x:" && AC_MSG_WARN([awesome man page generation requires asciidoc]) test "x$XMLTO" = "x:" && AC_MSG_WARN([awesome man page generation requires xmlto]) -test "x$PYTHON" = "x:" && AC_MSG_WARN([awesome man page generation requires python]) test "x$DOXYGEN" = "x:" && AC_MSG_WARN([awesome developer doc generation requires doxygen]) AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$ASCIIDOC" != "x:"]) AM_CONDITIONAL([HAVE_XMLTO], [test "x$XMLTO" != "x:"]) -AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != "x:"]) AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != "x:"]) xmlto_man_works=no @@ -107,12 +106,15 @@ AC_PATH_PROG([WHOAMI], [whoami], [false]) AS_IF([test "x$WHOAMI" = "xfalse"], [aw_whoami="???"], [aw_whoami=`$WHOAMI`]) AC_DEFINE_UNQUOTED([AWESOME_COMPILE_BY], ["$aw_whoami"], [build user]) +AS_AC_EXPAND(awesomelibdir, "$datarootdir/awesome/lib") +AC_DEFINE_UNQUOTED([AWESOME_LIB_PATH], "${awesomelibdir}", [awesome lib path]) + # Checks for libraries. AC_PATH_XTRA PKG_CHECK_MODULES([pangocairo], [pangocairo],, [AC_MSG_ERROR([awesome requires pangocairo.])]) -PKG_CHECK_MODULES([confuse], [libconfuse >= 2.6],, - [AC_MSG_ERROR([awesome requires libconfuse >= 2.6.])]) +PKG_CHECK_MODULES([Lua], [lua5.1],, + [AC_MSG_ERROR([awesome requires Lua >= 5.1.])]) PKG_CHECK_MODULES([glib], [glib-2.0],, [AC_MSG_ERROR([awesome requires glib-2.0.])]) PKG_CHECK_MODULES([dbus], [dbus-1],, diff --git a/event.c b/event.c index 4b7d4c60..2c0d6000 100644 --- a/event.c +++ b/event.c @@ -32,8 +32,8 @@ #include "ewmh.h" #include "client.h" #include "widget.h" -#include "rules.h" #include "titlebar.h" +#include "lua.h" #include "layouts/tile.h" #include "layouts/floating.h" #include "common/xscreen.h" @@ -46,18 +46,17 @@ extern AwesomeConf globalconf; * \param button button number * \param state modkeys state * \param buttons buttons list to check for - * \param arg optional arg passed to uicb, otherwise buttons' arg are used */ static void -event_handle_mouse_button_press(int screen, unsigned int button, +event_handle_mouse_button_press(unsigned int button, unsigned int state, Button *buttons) { Button *b; for(b = buttons; b; b = b->next) - if(button == b->button && CLEANMASK(state) == b->mod && b->func) - b->func(screen, b->arg); + if(button == b->button && CLEANMASK(state) == b->mod && b->fct) + luaA_dofunction(globalconf.L, b->fct, 0); } /** Handle XButtonPressed events @@ -70,12 +69,8 @@ event_handle_buttonpress(void *data __attribute__ ((unused)), { int screen; client_t *c; - widget_t *widget; + widget_node_t *w; statusbar_t *statusbar; - xcb_query_pointer_cookie_t qc; - xcb_query_pointer_reply_t *qr; - - qc = xcb_query_pointer(connection, ev->event); for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next) @@ -85,34 +80,34 @@ event_handle_buttonpress(void *data __attribute__ ((unused)), { case Top: case Bottom: - for(widget = statusbar->widgets; widget; widget = widget->next) - if(ev->event_x >= widget->area.x && ev->event_x < widget->area.x + widget->area.width - && ev->event_y >= widget->area.y && ev->event_y < widget->area.y + widget->area.height) + for(w = statusbar->widgets; w; w = w->next) + if(ev->event_x >= w->area.x && ev->event_x < w->area.x + w->area.width + && ev->event_y >= w->area.y && ev->event_y < w->area.y + w->area.height) { - widget->button_press(widget, ev); + w->widget->button_press(w, statusbar, ev); return 0; } break; case Right: - for(widget = statusbar->widgets; widget; widget = widget->next) - if(ev->event_y >= widget->area.x && ev->event_y < widget->area.x + widget->area.width - && statusbar->sw->geometry.width - ev->event_x >= widget->area.y + for(w = statusbar->widgets; w; w = w->next) + if(ev->event_y > w->area.x && ev->event_y < w->area.x + w->area.width + && statusbar->sw->geometry.width - ev->event_x >= w->area.y && statusbar->sw->geometry.width - ev->event_x - < widget->area.y + widget->area.height) + < w->area.y + w->area.height) { - widget->button_press(widget, ev); + w->widget->button_press(w, statusbar, ev); return 0; } break; case Left: - for(widget = statusbar->widgets; widget; widget = widget->next) - if(statusbar->sw->geometry.height - ev->event_y >= widget->area.x + for(w = statusbar->widgets; w; w = w->next) + if(statusbar->sw->geometry.height - ev->event_y >= w->area.x && statusbar->sw->geometry.height - ev->event_y - < widget->area.x + widget->area.width - && ev->event_x >= widget->area.y - && ev->event_x < widget->area.y + widget->area.height) + < w->area.x + w->area.width + && ev->event_x >= w->area.y + && ev->event_x < w->area.y + w->area.height) { - widget->button_press(widget, ev); + w->widget->button_press(w, statusbar, ev); return 0; } break; @@ -125,14 +120,14 @@ event_handle_buttonpress(void *data __attribute__ ((unused)), /* Check for titlebar first */ for(c = globalconf.clients; c; c = c->next) - if(c->titlebar.sw && c->titlebar.sw->window == ev->event) + if(c->titlebar_sw && c->titlebar_sw->window == ev->event) { if(!client_focus(c, c->screen, true)) client_stack(c); if(CLEANMASK(ev->state) == XCB_NO_SYMBOL && ev->detail == XCB_BUTTON_INDEX_1) window_grabbuttons(c->win, c->phys_screen); - event_handle_mouse_button_press(c->screen, ev->detail, ev->state, + event_handle_mouse_button_press(ev->detail, ev->state, globalconf.buttons.titlebar); return 0; } @@ -148,18 +143,14 @@ event_handle_buttonpress(void *data __attribute__ ((unused)), window_grabbuttons(c->win, c->phys_screen); } else - event_handle_mouse_button_press(c->screen, ev->detail, ev->state, globalconf.buttons.client); + event_handle_mouse_button_press(ev->detail, ev->state, globalconf.buttons.client); } else for(screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(connection)); screen++) - if(xcb_aux_get_screen(connection, screen)->root == ev->event - && (qr = xcb_query_pointer_reply(connection, qc, NULL))) + if(xcb_aux_get_screen(connection, screen)->root == ev->event) { - screen = screen_get_bycoord(globalconf.screens_info, screen, qr->root_x, qr->root_y); - event_handle_mouse_button_press(screen, ev->detail, ev->state, + event_handle_mouse_button_press(ev->detail, ev->state, globalconf.buttons.root); - - p_delete(&qr); return 0; } @@ -193,7 +184,7 @@ event_handle_configurerequest(void *data __attribute__ ((unused)), if(geometry.x != c->geometry.x || geometry.y != c->geometry.y || geometry.width != c->geometry.width || geometry.height != c->geometry.height) { - if(c->isfloating || layout_get_current(c->screen)->arrange == layout_floating) + if(c->isfloating || layout_get_current(c->screen) == layout_floating) client_resize(c, geometry, false); else { @@ -275,7 +266,7 @@ event_handle_configurenotify(void *data __attribute__ ((unused)), && (ev->width != screen->width_in_pixels || ev->height != screen->height_in_pixels)) /* it's not that we panic, but restart */ - uicb_restart(0, NULL); + a_exec(globalconf.argv); return 0; } @@ -303,10 +294,10 @@ event_handle_destroynotify(void *data __attribute__ ((unused)), */ int event_handle_enternotify(void *data __attribute__ ((unused)), - xcb_connection_t *connection, xcb_enter_notify_event_t *ev) + xcb_connection_t *connection __attribute__ ((unused)), + xcb_enter_notify_event_t *ev) { - client_t *c; - int screen; + client_t *c, **lc; if(ev->mode != XCB_NOTIFY_MODE_NORMAL || (ev->root_x == globalconf.pointer_x @@ -314,7 +305,7 @@ event_handle_enternotify(void *data __attribute__ ((unused)), return 0; for(c = globalconf.clients; c; c = c->next) - if(c->titlebar.sw && c->titlebar.sw->window == ev->event) + if(c->titlebar_sw && c->titlebar_sw->window == ev->event) break; if(c || (c = client_get_bywin(globalconf.clients, ev->event))) @@ -326,17 +317,13 @@ event_handle_enternotify(void *data __attribute__ ((unused)), globalconf.pointer_x = ev->root_x; globalconf.pointer_y = ev->root_y; - if(globalconf.screens[c->screen].sloppy_focus) - client_focus(c, c->screen, - globalconf.screens[c->screen].sloppy_focus_raise); + lc = lua_newuserdata(globalconf.L, sizeof(client_t *)); + *lc = c; + luaA_settype(globalconf.L, "client"); + luaA_dofunction(globalconf.L, globalconf.hooks.mouseover, 1); } else - for(screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(connection)); screen++) - if(ev->event == xcb_aux_get_screen(connection, screen)->root) - { - window_root_grabbuttons(screen); - return 0; - } + window_root_grabbuttons(); return 0; } @@ -365,9 +352,9 @@ event_handle_expose(void *data __attribute__ ((unused)), } for(c = globalconf.clients; c; c = c->next) - if(c->titlebar.sw && c->titlebar.sw->window == ev->window) + if(c->titlebar_sw && c->titlebar_sw->window == ev->window) { - simplewindow_refresh_drawable(c->titlebar.sw); + simplewindow_refresh_drawable(c->titlebar_sw); return 0; } } @@ -381,53 +368,18 @@ event_handle_expose(void *data __attribute__ ((unused)), */ int event_handle_keypress(void *data __attribute__ ((unused)), - xcb_connection_t *connection, xcb_key_press_event_t *ev) + xcb_connection_t *connection __attribute__ ((unused)), + xcb_key_press_event_t *ev) { - int screen; - xcb_query_pointer_reply_t *qpr = NULL; xcb_keysym_t keysym; keybinding_t *k; - /* find the right screen for this event */ - for(screen = 0; screen < xcb_setup_roots_length (xcb_get_setup (connection)); screen++) - if((qpr = xcb_query_pointer_reply(connection, - xcb_query_pointer(connection, - xcb_aux_get_screen(connection, screen)->root), - NULL)) != NULL) - { - /* if screen is 0, we are on first Zaphod screen or on the - * only screen in Xinerama, so we can ask for a better screen - * number with screen_get_bycoord: we'll get 0 in Zaphod mode - * so it's the same, or maybe the real Xinerama screen */ - screen = screen_get_bycoord(globalconf.screens_info, screen, qpr->root_x, qpr->root_y); - p_delete(&qpr); - break; - } - keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, ev->detail, 0); for(k = globalconf.keys; k; k = k->next) if(((k->keycode && ev->detail == k->keycode) || (k->keysym && keysym == k->keysym)) - && k->func && CLEANMASK(k->mod) == CLEANMASK(ev->state)) - k->func(screen, k->arg); - - return 0; -} - -/** Handle XMapping events - * \param connection connection to the X server - * \param ev MappingNotify event - */ -int -event_handle_mappingnotify(void *data __attribute__ ((unused)), - xcb_connection_t *connection, xcb_mapping_notify_event_t *ev) -{ - int screen; - - xcb_refresh_keyboard_mapping(globalconf.keysyms, ev); - if(ev->request == XCB_MAPPING_KEYBOARD) - for(screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(connection)); screen++) - window_root_grabkeys(screen); + && k->fct && CLEANMASK(k->mod) == CLEANMASK(ev->state)) + luaA_dofunction(globalconf.L, k->fct, 0); return 0; } @@ -594,7 +546,7 @@ event_handle_randr_screen_change_notify(void *data __attribute__ ((unused)), * XRenderSetSubpixelOrder(dpy, snum, scevent->subpixel_order); */ - uicb_restart(0, NULL); + a_exec(globalconf.argv); return 0; } diff --git a/event.h b/event.h index 7dd997da..e3cb56cc 100644 --- a/event.h +++ b/event.h @@ -35,7 +35,6 @@ int event_handle_destroynotify(void *, xcb_connection_t *, xcb_destroy_notify_ev int event_handle_enternotify(void *, xcb_connection_t *, xcb_enter_notify_event_t *); int event_handle_expose(void *, xcb_connection_t *, xcb_expose_event_t *); int event_handle_keypress(void *, xcb_connection_t *, xcb_key_press_event_t *); -int event_handle_mappingnotify(void *, xcb_connection_t *, xcb_mapping_notify_event_t *); int event_handle_maprequest(void *, xcb_connection_t *, xcb_map_request_event_t *); int event_handle_propertynotify(void *, xcb_connection_t *, xcb_property_notify_event_t *); int event_handle_unmapnotify(void *, xcb_connection_t *, xcb_unmap_notify_event_t *); diff --git a/ewmh.c b/ewmh.c index 40866fdf..17a4a997 100644 --- a/ewmh.c +++ b/ewmh.c @@ -281,7 +281,11 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set) /* restore geometry */ geometry = c->m_geometry; /* restore borders and titlebar */ - titlebar_position_set(&c->titlebar, c->titlebar.dposition); + if((c->titlebar.position = c->titlebar_oldposition)) + { + c->titlebar.position = c->titlebar_oldposition; + xcb_map_window(globalconf.connection, c->titlebar_sw->window); + } c->border = c->oldborder; c->ismax = false; client_setfloating(c, c->wasfloating, c->oldlayer); @@ -293,7 +297,11 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set) c->m_geometry = c->geometry; c->wasfloating = c->isfloating; /* disable titlebar and borders */ - titlebar_position_set(&c->titlebar, Off); + if((c->titlebar_oldposition = c->titlebar.position)) + { + xcb_unmap_window(globalconf.connection, c->titlebar_sw->window); + c->titlebar.position = Off; + } c->oldborder = c->border; c->border = 0; c->ismax = true; @@ -343,7 +351,11 @@ ewmh_process_window_type_atom(client_t *c, xcb_atom_t state) c->border = 0; c->skip = true; c->isfixed = true; - titlebar_position_set(&c->titlebar, Off); + if(c->titlebar.position) + { + xcb_unmap_window(globalconf.connection, c->titlebar_sw->window); + c->titlebar.position = Off; + } client_setfloating(c, true, LAYER_ABOVE); } else if (state == net_wm_window_type_dialog) diff --git a/focus.c b/focus.c index 0af7659e..f9f34b3d 100644 --- a/focus.c +++ b/focus.c @@ -99,54 +99,4 @@ focus_get_current_client(int screen) return sel; } -/** Jump back in the focus history stack. - * Set arg to 0 for previous, -1 for previous of previous, etc. - * \param screen Screen ID - * \param arg Integer argument - * \ingroup ui_callback - */ -void -uicb_focus_history(int screen, char *arg) -{ - int i; - tag_t **curtags; - client_t *c; - - if(arg) - { - i = atoi(arg); - - if(i < 0) - { - curtags = tags_get_current(screen); - c = focus_get_latest_client_for_tags(curtags, i); - p_delete(&curtags); - if(c) - client_focus(c, screen, true); - } - } -} - -/** Focus one of the visible clients by its name. - * \param screen screen id - * \param arg client's name - * \ingroup ui_callback - */ -void -uicb_focus_client_byname(int screen, char *arg) -{ - client_t *c; - tag_t **curtags, **tag; - - if(arg) - { - curtags = tags_get_current(screen); - if((c = client_get_byname(globalconf.clients, arg))) - for(tag = curtags; *tag; tag++) - if(is_client_tagged(c, *tag)) - client_focus(c, screen, true); - p_delete(&curtags); - } -} - // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/focus.h b/focus.h index a8bdb665..2da6e6dc 100644 --- a/focus.h +++ b/focus.h @@ -28,9 +28,6 @@ void focus_add_client(client_t *); void focus_delete_client(client_t *); client_t * focus_get_current_client(int); -uicb_t uicb_focus_history; -uicb_t uicb_focus_client_byname; - DO_SLIST(client_node_t, client_node, p_delete) #endif diff --git a/layout.c b/layout.c index 0f3e2c94..344ac001 100644 --- a/layout.c +++ b/layout.c @@ -36,8 +36,6 @@ extern AwesomeConf globalconf; -#include "layoutgen.h" - /** Arrange windows following current selected layout * \param screen the screen to arrange */ @@ -45,7 +43,7 @@ static void arrange(int screen) { client_t *c; - Layout *curlay = layout_get_current(screen); + LayoutArrange *curlay = layout_get_current(screen); int phys_screen = screen_virttophys(screen); xcb_query_pointer_cookie_t qp_c; xcb_query_pointer_reply_t *qp_r; @@ -59,24 +57,19 @@ arrange(int screen) client_ban(c); } - curlay->arrange(screen); + if(curlay) + curlay(screen); for(c = globalconf.clients; c; c = c->next) if(c->newcomer && client_isvisible(c, screen)) { c->newcomer = false; client_unban(c); - if(globalconf.screens[screen].new_get_focus - && !c->skip - && (!globalconf.focus->client || !globalconf.focus->client->ismax)) - client_focus(c, screen, true); - else if(globalconf.focus->client && globalconf.focus->client->ismax) - client_stack(globalconf.focus->client); } /* if we have a valid client that could be focused but currently no window * are focused, then set the focus on this window */ - if((c = focus_get_current_client(screen)) && globalconf.focus->client != c) + if((c = focus_get_current_client(screen)) && !globalconf.focus->client) client_focus(c, screen, true); qp_c = xcb_query_pointer_unchecked(globalconf.connection, @@ -87,7 +80,7 @@ arrange(int screen) if((qp_r = xcb_query_pointer_reply(globalconf.connection, qp_c, NULL))) { if(qp_r->root == XCB_NONE || qp_r->child == XCB_NONE || qp_r->root == qp_r->child) - window_root_grabbuttons(phys_screen); + window_root_grabbuttons(); globalconf.pointer_x = qp_r->root_x; globalconf.pointer_y = qp_r->root_y; @@ -117,62 +110,21 @@ layout_refresh(void) return arranged; } -/** Get current layout used on screen - * \param screen screen id +/** Get current layout used on screen. + * \param screen Virtual screen number. * \return layout used on that screen */ -Layout * +LayoutArrange * layout_get_current(int screen) { + LayoutArrange *l = NULL; tag_t **curtags = tags_get_current(screen); - Layout *l = curtags[0]->layout; + + if(curtags[0]) + l = curtags[0]->layout; p_delete(&curtags); + return l; } -/** Set the layout of the current tag. - * Argument must be a relative or absolute integer of available layouts. - * \param screen Screen ID - * \param arg Layout specifier - * \ingroup ui_callback - */ -void -uicb_tag_setlayout(int screen, char *arg) -{ - Layout *l = globalconf.screens[screen].layouts; - tag_t *tag, **curtags; - int i; - - if(arg) - { - curtags = tags_get_current(screen); - for(i = 0; l && l != curtags[0]->layout; i++, l = l->next); - p_delete(&curtags); - - if(!l) - i = 0; - - i = compute_new_value_from_arg(arg, (double) i); - - if(i >= 0) - for(l = globalconf.screens[screen].layouts; l && i > 0; i--) - l = l->next; - else - for(l = globalconf.screens[screen].layouts; l && i < 0; i++) - l = layout_list_prev_cycle(&globalconf.screens[screen].layouts, l); - - if(!l) - l = globalconf.screens[screen].layouts; - } - - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - if(tag->selected) - tag->layout = l; - - if(globalconf.focus->client) - arrange(screen); - - widget_invalidate_cache(screen, WIDGET_CACHE_LAYOUTS); -} - // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/layout.h b/layout.h index 427d2cec..c3e7a6ed 100644 --- a/layout.h +++ b/layout.h @@ -22,26 +22,13 @@ #ifndef AWESOME_LAYOUT_H #define AWESOME_LAYOUT_H -#include "uicb.h" #include "common/list.h" #include "common/util.h" typedef void (LayoutArrange)(int); -typedef struct Layout Layout; -struct Layout -{ - char *image; - LayoutArrange *arrange; - Layout *prev, *next; -}; - -DO_SLIST(Layout, layout, p_delete) - +LayoutArrange * layout_get_current(int); int layout_refresh(void); -Layout * layout_get_current(int); - -uicb_t uicb_tag_setlayout; #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/layouts/fibonacci.c b/layouts/fibonacci.c index 61478fcd..9b712f50 100644 --- a/layouts/fibonacci.c +++ b/layouts/fibonacci.c @@ -81,7 +81,7 @@ layout_fibonacci(int screen, int shape) } geometry.width -= 2 * c->border; geometry.height -= 2 * c->border; - client_resize(c, geometry, globalconf.screens[screen].resize_hints); + client_resize(c, geometry, globalconf.resize_hints); geometry.width += 2 * c->border; geometry.height += 2 * c->border; } diff --git a/layouts/tile.c b/layouts/tile.c index 6738504c..a52d4266 100644 --- a/layouts/tile.c +++ b/layouts/tile.c @@ -22,7 +22,6 @@ #include <stdio.h> #include "screen.h" -#include "awesome.h" #include "tag.h" #include "client.h" #include "layouts/tile.h" @@ -30,99 +29,6 @@ extern AwesomeConf globalconf; -void -uicb_tag_setnmaster(int screen, char * arg) -{ - tag_t **curtags = tags_get_current(screen); - Layout *curlay = curtags[0]->layout; - client_t *c; - int n; - - if(!arg || (curlay->arrange != layout_tile - && curlay->arrange != layout_tileleft - && curlay->arrange != layout_tilebottom - && curlay->arrange != layout_tiletop)) - return; - - if((curtags[0]->nmaster = (int) compute_new_value_from_arg(arg, (double) curtags[0]->nmaster)) < 0) - curtags[0]->nmaster = 0; - - for(n = 0, c = globalconf.clients; c; c = c->next) - if(IS_TILED(c, screen)) - n++; - - if(curtags[0]->nmaster > n - 1) - curtags[0]->nmaster = n; - - p_delete(&curtags); - - globalconf.screens[screen].need_arrange = true; -} - -void -uicb_tag_setncol(int screen, char * arg) -{ - tag_t **curtags = tags_get_current(screen); - Layout *curlay = curtags[0]->layout; - client_t *c; - int n; - - if(!arg || (curlay->arrange != layout_tile - && curlay->arrange != layout_tileleft - && curlay->arrange != layout_tilebottom - && curlay->arrange != layout_tiletop)) - return; - - - if((curtags[0]->ncol = (int) compute_new_value_from_arg(arg, (double) curtags[0]->ncol)) < 1) - curtags[0]->ncol = 1; - - for(n = 0, c = globalconf.clients; c; c = c->next) - if(IS_TILED(c, screen)) - n++; - - if(curtags[0]->ncol > n - 1) - curtags[0]->ncol = n - 1; - - p_delete(&curtags); - - globalconf.screens[screen].need_arrange = true; -} - -void -uicb_tag_setmwfact(int screen, char *arg) -{ - char *newarg; - tag_t **curtags = tags_get_current(screen); - Layout *curlay = curtags[0]->layout; - - if(!arg || (curlay->arrange != layout_tile - && curlay->arrange != layout_tileleft - && curlay->arrange != layout_tilebottom - && curlay->arrange != layout_tiletop)) - return; - - newarg = a_strdup(arg); - if(curlay->arrange == layout_tileleft || curlay->arrange == layout_tiletop) - { - if(newarg[0] == '+') - newarg[0] = '-'; - else if(arg[0] == '-') - newarg[0] = '+'; - } - - curtags[0]->mwfact = compute_new_value_from_arg(newarg, curtags[0]->mwfact); - - if(curtags[0]->mwfact < globalconf.screens[screen].mwfact_lower_limit) - curtags[0]->mwfact = globalconf.screens[screen].mwfact_lower_limit; - else if(curtags[0]->mwfact > globalconf.screens[screen].mwfact_upper_limit) - curtags[0]->mwfact = globalconf.screens[screen].mwfact_upper_limit; - - p_delete(&newarg); - p_delete(&curtags); - globalconf.screens[screen].need_arrange = true; -} - static void _tile(int screen, const position_t position) { @@ -206,7 +112,7 @@ _tile(int screen, const position_t position) geometry.width = mw - 2 * c->border; geometry.height = mh - 2 * c->border; - client_resize(c, geometry, globalconf.screens[screen].resize_hints); + client_resize(c, geometry, globalconf.resize_hints); } else { @@ -257,7 +163,7 @@ _tile(int screen, const position_t position) if(position == Bottom) geometry.y += mh; } - client_resize(c, geometry, globalconf.screens[screen].resize_hints); + client_resize(c, geometry, globalconf.resize_hints); } i++; } diff --git a/layouts/tile.h b/layouts/tile.h index 6280f56c..a7f3e169 100644 --- a/layouts/tile.h +++ b/layouts/tile.h @@ -30,9 +30,5 @@ LayoutArrange layout_tileleft; LayoutArrange layout_tilebottom; LayoutArrange layout_tiletop; -uicb_t uicb_tag_setnmaster; -uicb_t uicb_tag_setncol; -uicb_t uicb_tag_setmwfact; - #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/lua.c b/lua.c new file mode 100644 index 00000000..c11da31c --- /dev/null +++ b/lua.c @@ -0,0 +1,383 @@ +#include <stdio.h> +#include <unistd.h> + +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> + +#include <xcb/xcb.h> +#include <xcb/xcb_aux.h> + +/* XStringToKeysym() */ +#include <X11/Xlib.h> + +#include "structs.h" +#include "lua.h" +#include "tag.h" +#include "statusbar.h" +#include "widget.h" +#include "placement.h" +#include "client.h" +#include "window.h" +#include "mouse.h" +#include "statusbar.h" +#include "screen.h" +#include "titlebar.h" +#include "layouts/tile.h" +#include "layouts/floating.h" +#include "common/util.h" +#include "common/xutil.h" + +extern AwesomeConf globalconf; +extern bool running; +extern const name_func_link_t WidgetList[]; +extern const name_func_link_t FloatingPlacementList[]; + +extern const struct luaL_reg awesome_mouse_lib[]; +extern const struct luaL_reg awesome_client_methods[]; +extern const struct luaL_reg awesome_client_meta[]; +extern const struct luaL_reg awesome_titlebar_methods[]; +extern const struct luaL_reg awesome_titlebar_meta[]; +extern const struct luaL_reg awesome_tag_methods[]; +extern const struct luaL_reg awesome_tag_meta[]; +extern const struct luaL_reg awesome_widget_methods[]; +extern const struct luaL_reg awesome_widget_meta[]; +extern const struct luaL_reg awesome_statusbar_methods[]; +extern const struct luaL_reg awesome_statusbar_meta[]; + +/* Static */ +static void +__luaA_keystore(keybinding_t *key, const char *str) +{ + xcb_keycode_t kc; + int ikc; + + if(!a_strlen(str)) + return; + else if(a_strncmp(str, "#", 1)) + key->keysym = XStringToKeysym(str); + else + { + ikc = atoi(str + 1); + memcpy(&kc, &ikc, sizeof(KeyCode)); + key->keycode = kc; + } +} + +static int +luaA_mouse(lua_State *L) +{ + size_t i, len; + int b; + Button *button; + + /* arg 1 is modkey table */ + luaA_checktable(L, 1); + /* arg 2 is mouse button */ + b = luaL_checknumber(L, 2); + /* arg 3 is cmd to run */ + luaA_checkfunction(L, 3); + + button = p_new(Button, 1); + button->button = xutil_button_fromint(b); + button->fct = luaL_ref(L, LUA_REGISTRYINDEX); + + len = lua_objlen(L, 1); + for(i = 1; i <= len; i++) + { + lua_rawgeti(L, 1, i); + button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); + } + + button_list_push(&globalconf.buttons.root, button); + + window_root_grabbutton(button); + + return 0; +} + +static int +luaA_key(lua_State *L) +{ + size_t i, len; + keybinding_t *k; + const char *key; + + /* arg 1 is key mod table */ + luaA_checktable(L, 1); + /* arg 2 is key */ + key = luaL_checkstring(L, 2); + /* arg 3 is cmd to run */ + luaA_checkfunction(L, 3); + + /* get the last arg as function */ + k = p_new(keybinding_t, 1); + __luaA_keystore(k, key); + k->fct = luaL_ref(L, LUA_REGISTRYINDEX); + + len = lua_objlen(L, 1); + for(i = 1; i <= len; i++) + { + lua_rawgeti(L, 1, i); + k->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); + } + + keybinding_list_push(&globalconf.keys, k); + + window_root_grabkey(k); + + return 0; +} + +static int +luaA_floating_placement_set(lua_State *L) +{ + const char *pl = luaL_checkstring(L, 1); + globalconf.floating_placement = name_func_lookup(pl, FloatingPlacementList); + return 0; +} + +static int +luaA_quit(lua_State *L __attribute__ ((unused))) +{ + running = false; + return 0; +} + +static int +luaA_exec(lua_State *L) +{ + client_t *c; + const char *cmd = luaL_checkstring(L, 1); + + for(c = globalconf.clients; c; c = c->next) + client_unban(c); + + xcb_aux_sync(globalconf.connection); + xcb_disconnect(globalconf.connection); + + a_exec(cmd); + return 0; +} + +static int +luaA_restart(lua_State *L __attribute__ ((unused))) +{ + a_exec(globalconf.argv); + return 0; +} + +static int +luaA_padding_set(lua_State *L) +{ + int screen = luaL_checknumber(L, 1) - 1; + + if(screen >= 0 && screen < globalconf.screens_info->nscreen) + { + luaA_checktable(L, 2); + + globalconf.screens[screen].padding.right = luaA_getopt_number(L, 2, "right", 0); + globalconf.screens[screen].padding.left = luaA_getopt_number(L, 2, "left", 0); + globalconf.screens[screen].padding.top = luaA_getopt_number(L, 2, "top", 0); + globalconf.screens[screen].padding.bottom = luaA_getopt_number(L, 2, "bottom", 0); + } + + return 0; +} + +static int +luaA_resizehints_set(lua_State *L) +{ + globalconf.resize_hints = luaA_checkboolean(L, 1); + return 0; +} + +static int +luaA_screen_count(lua_State *L) +{ + lua_pushnumber(L, globalconf.screens_info->nscreen); + return 1; +} + +static int +luaA_screen_focus(lua_State *L) +{ + /* Our table begin at 0, Lua begins at 1 */ + int screen = luaL_checknumber(L, 1) - 1; + luaA_checkscreen(screen); + client_focus(NULL, screen, true); + return 0; +} + +static int +luaA_screen_coords_get(lua_State *L) +{ + int screen = luaL_checknumber(L, 1) - 1; + luaA_checkscreen(screen); + lua_newtable(L); + lua_pushnumber(L, globalconf.screens_info->geometry[screen].x); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, globalconf.screens_info->geometry[screen].y); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, globalconf.screens_info->geometry[screen].width); + lua_setfield(L, -2, "width"); + lua_pushnumber(L, globalconf.screens_info->geometry[screen].height); + lua_setfield(L, -2, "height"); + return 1; +} + +/* Hooks */ +static int +luaA_hooks_focus(lua_State *L) +{ + luaA_checkfunction(L, 1); + if(globalconf.hooks.focus) + luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.focus); + globalconf.hooks.focus = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; +} + +static int +luaA_hooks_unfocus(lua_State *L) +{ + luaA_checkfunction(L, 1); + if(globalconf.hooks.unfocus) + luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.unfocus); + globalconf.hooks.unfocus = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; +} + +static int +luaA_hooks_newclient(lua_State *L) +{ + luaA_checkfunction(L, 1); + if(globalconf.hooks.newclient) + luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.newclient); + globalconf.hooks.newclient = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; +} + +static int +luaA_hooks_mouseover(lua_State *L) +{ + luaA_checkfunction(L, 1); + if(globalconf.hooks.mouseover) + luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.mouseover); + globalconf.hooks.mouseover = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; +} + +static void +luaA_openlib(lua_State *L, const char *name, + const struct luaL_reg methods[], + const struct luaL_reg meta[]) +{ + luaL_newmetatable(L, name); + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* dup metatable*/ + lua_settable(L, -3); /* metatable.__index = metatable */ + + luaL_openlib(L, NULL, meta, 0); + luaL_openlib(L, name, methods, 0); +} + +bool +luaA_parserc(const char *rcfile) +{ + lua_State *L; + int screen; + + static const struct luaL_reg awesome_lib[] = + { + { "quit", luaA_quit }, + { "exec", luaA_exec }, + { "restart", luaA_restart }, + { "floating_placement_set", luaA_floating_placement_set }, + { "padding_set", luaA_padding_set }, + { "screen_coords_get", luaA_screen_coords_get }, + { "screen_count", luaA_screen_count }, + { "screen_focus", luaA_screen_focus }, + { "key", luaA_key }, + { "mouse", luaA_mouse }, + { "resizehints_set", luaA_resizehints_set }, + { NULL, NULL } + }; + static const struct luaL_reg awesome_hooks_lib[] = + { + { "focus", luaA_hooks_focus }, + { "unfocus", luaA_hooks_unfocus }, + { "newclient", luaA_hooks_newclient }, + { "mouseover", luaA_hooks_mouseover }, + { NULL, NULL } + }; + + L = globalconf.L = lua_open(); + + luaL_openlibs(L); + + /* Export awesome lib */ + luaL_openlib(L, "awesome", awesome_lib, 0); + + /* Export hooks lib */ + luaL_openlib(L, "hooks", awesome_hooks_lib, 0); + + /* Export hooks lib */ + luaL_openlib(L, "mouse", awesome_mouse_lib, 0); + + /* Export tag */ + luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta); + + /* Export statusbar */ + luaA_openlib(L, "statusbar", awesome_statusbar_methods, awesome_statusbar_meta); + + /* Export widget */ + luaA_openlib(L, "widget", awesome_widget_methods, awesome_widget_meta); + + /* Export client */ + luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta); + + /* Export titlebar */ + luaA_openlib(L, "titlebar", awesome_titlebar_methods, awesome_titlebar_meta); + + lua_pushliteral(L, "AWESOME_VERSION"); + lua_pushliteral(L, VERSION); + lua_settable(L, LUA_GLOBALSINDEX); + + /* \todo move this */ + globalconf.font = draw_font_new(globalconf.connection, globalconf.default_screen, "sans 8"); + draw_color_new(globalconf.connection, globalconf.default_screen, "black", &globalconf.colors.fg); + draw_color_new(globalconf.connection, globalconf.default_screen, "white", &globalconf.colors.bg); + + luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LIB_PATH "?.lua\""); + + if(luaL_dofile(L, rcfile)) + { + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + return false; + } + + /* Assure there's at least one tag */ + for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) + if(!globalconf.screens[screen].tags) + tag_append_to_screen(tag_new("default", layout_tile, 0.5, 1, 0), screen); + + return true; +} + +/** Parse a command. + * \param cmd The buffer to parse. + * \return true on succes, false on failure. + */ +void +luaA_docmd(char *cmd) +{ + char *p, *curcmd = cmd; + + if(a_strlen(cmd)) + while((p = strchr(curcmd, '\n'))) + { + *p = '\0'; + luaA_dostring(globalconf.L, curcmd); + curcmd = p + 1; + } +} diff --git a/lua.h b/lua.h new file mode 100644 index 00000000..fb4f2c06 --- /dev/null +++ b/lua.h @@ -0,0 +1,117 @@ +/* + * lua.h - Lua configuration management header + * + * Copyright © 2008 Julien Danjou <julien@danjou.info> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef AWESOME_LUA_H +#define AWESOME_LUA_H + +#include <lua5.1/lua.h> +#include <lua5.1/lauxlib.h> + +#include "common/util.h" + +/** Type for Lua function */ +typedef int luaA_function; + +#define luaA_dostring(L, cmd) \ + do { \ + if(cmd) \ + if(luaL_dostring(L, cmd)) \ + warn("error executing Lua code: %s\n", \ + lua_tostring(L, -1)); \ + } while(0) + +#define luaA_dofunction(L, f, n) \ + do { \ + if(f) \ + { \ + lua_rawgeti(L, LUA_REGISTRYINDEX, f); \ + if(n) \ + lua_insert(L, - (n + 1)); \ + if(lua_pcall(L, n, 0, 0)) \ + warn("error running function: %s\n", \ + lua_tostring(L, -1)); \ + } \ + } while(0) + +#define luaA_checktable(L, n) \ + do { \ + if(!lua_istable(L, n)) \ + luaL_typerror(L, n, "table"); \ + } while(0) + +#define luaA_checkfunction(L, n) \ + do { \ + if(!lua_isfunction(L, n)) \ + luaL_typerror(L, n, "function"); \ + } while(0) + +#define luaA_checkscreen(screen) \ + do { \ + if(screen < 0 || screen >= globalconf.screens_info->nscreen) \ + luaL_error(L, "invalid screen number: %d\n", screen); \ + } while(0) + +static inline lua_Number +luaA_getopt_number(lua_State *L, int idx, const char *name, lua_Number def) +{ + /* assume that table is first on stack */ + lua_getfield(L, idx, name); + /* return luaL_optnumber result */ + return luaL_optnumber(L, -1, def); +} + +static inline const char * +luaA_getopt_string(lua_State *L, int idx, const char *name, const char *def) +{ + /* assume that table is first on stack */ + lua_getfield(L, idx, name); + /* return luaL_optnumber result */ + return luaL_optstring(L, -1, def); +} + +static inline int +luaA_settype(lua_State *L, const char *type) +{ + luaL_getmetatable(L, type); + lua_setmetatable(L, -2); + return 1; +} + +static inline char * +luaA_name_init(lua_State *L) +{ + lua_getfield(L, 1, "name"); + return a_strdup(luaL_checkstring(L, -1)); +} + +static inline bool +luaA_checkboolean(lua_State *L, int n) +{ + if(!lua_isboolean(L, n)) + luaL_typerror(L, n, "boolean"); + return lua_toboolean(L, n); +} + + +bool luaA_parserc(const char *); +void luaA_docmd(char *); +#endif +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/mouse.c b/mouse.c index 44e35d33..b05d0a37 100644 --- a/mouse.c +++ b/mouse.c @@ -94,10 +94,9 @@ mouse_snapclienttogeometry_inside(area_t geometry, area_t snap_geometry, int sna * \return geometry to set to the client */ static area_t -mouse_snapclient(client_t *c, area_t geometry) +mouse_snapclient(client_t *c, area_t geometry, int snap) { client_t *snapper; - int snap = globalconf.screens[c->screen].snap; area_t snapper_geometry; area_t screen_geometry = screen_get_area(c->screen, @@ -117,8 +116,7 @@ mouse_snapclient(client_t *c, area_t geometry) snapper_geometry = snapper->geometry; snapper_geometry.width += 2 * c->border; snapper_geometry.height += 2 * c->border; - snapper_geometry = titlebar_geometry_add(&snapper->titlebar, - snapper_geometry); + snapper_geometry = titlebar_geometry_add(&snapper->titlebar, snapper_geometry); geometry = mouse_snapclienttogeometry_outside(geometry, snapper_geometry, @@ -137,15 +135,17 @@ mouse_snapclient(client_t *c, area_t geometry) * \param border The client border size. */ static void -mouse_resizebar_draw(draw_context_t *ctx, style_t *style, - simple_window_t *sw, area_t geometry, int border) +mouse_resizebar_draw(draw_context_t *ctx, + simple_window_t *sw, + area_t geometry, int border) { area_t draw_geometry = { 0, 0, ctx->width, ctx->height, NULL, NULL }; char size[64]; snprintf(size, sizeof(size), "<text align=\"center\"/>%dx%d+%d+%d", geometry.x, geometry.y, geometry.width, geometry.height); - draw_text(ctx, draw_geometry, size, style); + draw_rectangle(ctx, draw_geometry, 1.0, true, globalconf.colors.bg); + draw_text(ctx, globalconf.font, &globalconf.colors.fg, draw_geometry, size); simplewindow_move(sw, geometry.x + ((2 * border + geometry.width) - sw->geometry.width) / 2, geometry.y + ((2 * border + geometry.height) - sw->geometry.height) / 2); @@ -162,14 +162,14 @@ mouse_resizebar_draw(draw_context_t *ctx, style_t *style, */ static simple_window_t * mouse_resizebar_new(int phys_screen, int border, area_t geometry, - style_t *style, draw_context_t **ctx) + draw_context_t **ctx) { simple_window_t *sw; area_t geom; geom = draw_text_extents(globalconf.connection, globalconf.default_screen, - style->font, + globalconf.font, "0000x0000+0000+0000"); geom.x = geometry.x + ((2 * border + geometry.width) - geom.width) / 2; geom.y = geometry.y + ((2 * border + geometry.height) - geom.height) / 2; @@ -183,37 +183,36 @@ mouse_resizebar_new(int phys_screen, int border, area_t geometry, sw->drawable); xcb_map_window(globalconf.connection, sw->window); - mouse_resizebar_draw(*ctx, style, sw, geometry, border); + mouse_resizebar_draw(*ctx, sw, geometry, border); return sw; } /** Move the focused window with the mouse. - * \param screen Screen ID - * \param arg Unused - * \ingroup ui_callback */ void -uicb_client_movemouse(int screen, char *arg __attribute__ ((unused))) +mouse_client_move(int snap) { int ocx, ocy, newscreen; area_t geometry; client_t *c = globalconf.focus->client, *target; - Layout *layout = layout_get_current(screen); + LayoutArrange *layout; simple_window_t *sw = NULL; draw_context_t *ctx; - style_t *style; xcb_generic_event_t *ev = NULL; xcb_motion_notify_event_t *ev_motion = NULL; xcb_grab_pointer_reply_t *grab_pointer_r = NULL; xcb_grab_pointer_cookie_t grab_pointer_c; xcb_query_pointer_reply_t *query_pointer_r = NULL, *mquery_pointer_r = NULL; xcb_query_pointer_cookie_t query_pointer_c; - xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, c->phys_screen); + xcb_screen_t *s; if(!c) return; + layout = layout_get_current(c->screen); + s = xcb_aux_get_screen(globalconf.connection, c->phys_screen); + /* Send pointer requests */ grab_pointer_c = xcb_grab_pointer(globalconf.connection, false, s->root, MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, @@ -224,7 +223,6 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused))) geometry = c->geometry; ocx = geometry.x; ocy = geometry.y; - style = &globalconf.screens[c->screen].styles.focus; /* Get responses */ if(!(grab_pointer_r = xcb_grab_pointer_reply(globalconf.connection, grab_pointer_c, NULL))) @@ -236,9 +234,9 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused))) query_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL); - if(c->isfloating || layout->arrange == layout_floating) + if(c->isfloating || layout == layout_floating) { - sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, style, &ctx); + sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, &ctx); xcb_aux_sync(globalconf.connection); } @@ -261,20 +259,20 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused))) p_delete(&ev); return; case XCB_MOTION_NOTIFY: - if(c->isfloating || layout->arrange == layout_floating) + if(c->isfloating || layout == layout_floating) { ev_motion = (xcb_motion_notify_event_t *) ev; geometry.x = ocx + (ev_motion->event_x - query_pointer_r->root_x); geometry.y = ocy + (ev_motion->event_y - query_pointer_r->root_y); - geometry = mouse_snapclient(c, geometry); + geometry = mouse_snapclient(c, geometry, snap); c->ismoving = true; client_resize(c, geometry, false); c->ismoving = false; if(sw) - mouse_resizebar_draw(ctx, style, sw, c->geometry, c->border); + mouse_resizebar_draw(ctx, sw, c->geometry, c->border); xcb_aux_sync(globalconf.connection); } @@ -317,53 +315,53 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused))) /** Resize the focused window with the mouse. * \param screen Screen ID * \param arg Unused - * \ingroup ui_callback */ void -uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused))) +mouse_client_resize(void) { int ocx = 0, ocy = 0, n; xcb_generic_event_t *ev = NULL; xcb_motion_notify_event_t *ev_motion = NULL; client_t *c = globalconf.focus->client; - tag_t **curtags = tags_get_current(screen); - Layout *layout = curtags[0]->layout; + tag_t **curtags; + LayoutArrange *layout; area_t area = { 0, 0, 0, 0, NULL, NULL }, geometry = { 0, 0, 0, 0, NULL, NULL }; double mwfact; simple_window_t *sw = NULL; draw_context_t *ctx = NULL; - style_t *style; xcb_grab_pointer_cookie_t grab_pointer_c; xcb_grab_pointer_reply_t *grab_pointer_r = NULL; - xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, c->phys_screen); + xcb_screen_t *s; /* only handle floating and tiled layouts */ if(!c || c->isfixed) return; - style = &globalconf.screens[c->screen].styles.focus; + curtags = tags_get_current(c->screen); + layout = curtags[0]->layout; + s = xcb_aux_get_screen(globalconf.connection, c->phys_screen); - if(layout->arrange == layout_floating || c->isfloating) + if(layout == layout_floating || c->isfloating) { ocx = c->geometry.x; ocy = c->geometry.y; c->ismax = false; - sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, style, &ctx); + sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, &ctx); } - else if (layout->arrange == layout_tile || layout->arrange == layout_tileleft - || layout->arrange == layout_tilebottom || layout->arrange == layout_tiletop) + else if (layout == layout_tile || layout == layout_tileleft + || layout == layout_tilebottom || layout == layout_tiletop) { for(n = 0, c = globalconf.clients; c; c = c->next) - if(IS_TILED(c, screen)) + if(IS_TILED(c, c->screen)) n++; if(n <= curtags[0]->nmaster) return; - for(c = globalconf.clients; c && !IS_TILED(c, screen); c = c->next); + for(c = globalconf.clients; c && !IS_TILED(c, c->screen); c = c->next); if(!c) return; - area = screen_get_area(screen, + area = screen_get_area(c->screen, globalconf.screens[c->screen].statusbar, &globalconf.screens[c->screen].padding); } @@ -380,10 +378,10 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused))) p_delete(&grab_pointer_r); - if(curtags[0]->layout->arrange == layout_tileleft) + if(curtags[0]->layout == layout_tileleft) xcb_warp_pointer(globalconf.connection, XCB_NONE, c->win, 0, 0, 0, 0, 0, c->geometry.height + c->border - 1); - else if(curtags[0]->layout->arrange == layout_tiletop) + else if(curtags[0]->layout == layout_tiletop) xcb_warp_pointer(globalconf.connection, XCB_NONE, c->win, 0, 0, 0, 0, c->geometry.width + c->border - 1, 0); else @@ -414,7 +412,7 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused))) case XCB_MOTION_NOTIFY: ev_motion = (xcb_motion_notify_event_t *) ev; - if(layout->arrange == layout_floating || c->isfloating) + if(layout == layout_floating || c->isfloating) { if((geometry.width = ev_motion->event_x - ocx - 2 * c->border + 1) <= 0) geometry.width = 1; @@ -424,26 +422,24 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused))) geometry.y = c->geometry.y; client_resize(c, geometry, true); if(sw) - mouse_resizebar_draw(ctx, style, sw, c->geometry, c->border); + mouse_resizebar_draw(ctx, sw, c->geometry, c->border); xcb_aux_sync(globalconf.connection); } - else if(layout->arrange == layout_tile || layout->arrange == layout_tileleft - || layout->arrange == layout_tiletop || layout->arrange == layout_tilebottom) + else if(layout == layout_tile || layout == layout_tileleft + || layout == layout_tiletop || layout == layout_tilebottom) { - if(layout->arrange == layout_tile) + if(layout == layout_tile) mwfact = (double) (ev_motion->event_x - area.x) / area.width; - else if(curtags[0]->layout->arrange == layout_tileleft) + else if(curtags[0]->layout == layout_tileleft) mwfact = 1 - (double) (ev_motion->event_x - area.x) / area.width; - else if(curtags[0]->layout->arrange == layout_tilebottom) + else if(curtags[0]->layout == layout_tilebottom) mwfact = (double) (ev_motion->event_y - area.y) / area.height; else mwfact = 1 - (double) (ev_motion->event_y - area.y) / area.height; - mwfact = MAX(globalconf.screens[screen].mwfact_lower_limit, - MIN(globalconf.screens[screen].mwfact_upper_limit, mwfact)); if(fabs(curtags[0]->mwfact - mwfact) >= 0.01) { curtags[0]->mwfact = mwfact; - globalconf.screens[screen].need_arrange = true; + globalconf.screens[c->screen].need_arrange = true; layout_refresh(); } } @@ -461,4 +457,63 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused))) } } +static int +luaA_mouse_coords_set(lua_State *L) +{ + int x, y; + x = luaL_checknumber(L, 1); + y = luaL_checknumber(L, 2); + xcb_warp_pointer(globalconf.connection, XCB_NONE, + xcb_aux_get_screen(globalconf.connection, globalconf.default_screen)->root, + 0, 0, 0, 0, x, y); + return 0; +} + +static int +luaA_mouse_client_resize(lua_State *L __attribute__ ((unused))) +{ + mouse_client_resize(); + return 0; +} + +static int +luaA_mouse_client_move(lua_State *L) +{ + int snap = luaL_optnumber(L, 1, 8); + mouse_client_move(snap); + return 0; +} + +static int +luaA_mouse_screen_get(lua_State *L) +{ + int screen; + xcb_query_pointer_cookie_t qc; + xcb_query_pointer_reply_t *qr; + + qc = xcb_query_pointer(globalconf.connection, + xcb_aux_get_screen(globalconf.connection, + globalconf.default_screen)->root); + + if(!(qr = xcb_query_pointer_reply(globalconf.connection, qc, NULL))) + return 0; + + screen = screen_get_bycoord(globalconf.screens_info, + globalconf.default_screen, + qr->root_x, qr->root_y); + p_delete(&qr); + lua_pushnumber(L, screen + 1); + + return 1; +} + +const struct luaL_reg awesome_mouse_lib[] = +{ + { "screen_get", luaA_mouse_screen_get }, + { "coords_set", luaA_mouse_coords_set }, + { "client_resize", luaA_mouse_client_resize }, + { "client_move", luaA_mouse_client_move }, + { NULL, NULL } +}; + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/mouse.h b/mouse.h index 95a11b90..04e43335 100644 --- a/mouse.h +++ b/mouse.h @@ -22,10 +22,8 @@ #ifndef AWESOME_MOUSE_H #define AWESOME_MOUSE_H -#include "uicb.h" - -uicb_t uicb_client_movemouse; -uicb_t uicb_client_resizemouse; +void mouse_client_move(int); +void mouse_client_resize(void); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/placement.c b/placement.c index e97f77b6..88c86711 100644 --- a/placement.c +++ b/placement.c @@ -72,7 +72,7 @@ placement_smart(client_t *c) area_t newgeometry = { 0, 0, 0, 0, NULL, NULL }; area_t *screen_geometry, *arealist = NULL, *r; bool found = false; - Layout *layout; + LayoutArrange *layout; screen_geometry = p_new(area_t, 1); @@ -85,7 +85,7 @@ placement_smart(client_t *c) area_list_push(&arealist, screen_geometry); for(client = globalconf.clients; client; client = client->next) - if((client->isfloating || layout->arrange == layout_floating) + if((client->isfloating || layout == layout_floating) && client_isvisible(client, c->screen)) { newgeometry = client->f_geometry; diff --git a/rules.c b/rules.c deleted file mode 100644 index 19c3dbc9..00000000 --- a/rules.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * rules.c - rules management - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "rules.h" -#include "common/xutil.h" - -extern AwesomeConf globalconf; - -regex_t * -rules_compile_regex(char *val) -{ - regex_t *reg; - - if(val) - { - reg = p_new(regex_t, 1); - if(regcomp(reg, val, REG_EXTENDED)) - p_delete(®); - else - return reg; - } - - return NULL; -} - -bool -tag_match_rule(tag_t *t, rule_t *r) -{ - regmatch_t tmp; - - if(r->tags_r && !regexec(r->tags_r, t->name, 1, &tmp, 0)) - return true; - - return false; -} - -rule_t * -rule_matching_client(client_t *c) -{ - rule_t *r; - char *prop = NULL, *buf = NULL; - regmatch_t tmp; - ssize_t len; - class_hint_t *ch = NULL; - bool ret = false; - - if(!(ch = xutil_get_class_hint(globalconf.connection, c->win))) - return NULL; - - len = a_strlen(ch->res_class) + a_strlen(ch->res_name) + a_strlen(c->name) + 3; - prop = p_new(char, len); - - snprintf(prop, len, "%s:%s:%s", - ch->res_class ? ch->res_class : "", ch->res_name ? ch->res_name : "", c->name); - - p_delete(&ch->res_class); - p_delete(&ch->res_name); - p_delete(&ch); - - for(r = globalconf.rules; r; r = r->next) - { - if(r->prop_r && prop) - ret = !regexec(r->prop_r, prop, 1, &tmp, 0); - - if(!ret - && r->xprop - && r->xpropval_r - && xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms, - xutil_intern_atom_reply(globalconf.connection, - &globalconf.atoms, - xutil_intern_atom(globalconf.connection, - &globalconf.atoms, - r->xprop)), - &buf)) - ret = !regexec(r->xpropval_r, buf, 1, &tmp, 0); - - p_delete(&buf); - - if(ret) - { - p_delete(&prop); - return r; - } - } - - p_delete(&prop); - - return NULL; -} - -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/rules.h b/rules.h deleted file mode 100644 index 14739a6e..00000000 --- a/rules.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * rules.h - rules management header - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef AWESOME_RULES_H -#define AWESOME_RULES_H - -#include "structs.h" - -#define RULE_NOSCREEN -1 - -regex_t * rules_compile_regex(char *); -bool tag_match_rule(tag_t *, rule_t *); -rule_t * rule_matching_client(client_t *); - -DO_SLIST(rule_t, rule, p_delete) - -#endif -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/screen.c b/screen.c index 47243556..1ad852a8 100644 --- a/screen.c +++ b/screen.c @@ -210,82 +210,4 @@ move_client_to_screen(client_t *c, int new_screen, bool doresize) } } -/** Move mouse pointer to x_org and y_xorg of specified screen - * \param screen screen number - */ -static void -move_mouse_pointer_to_screen(int phys_screen) -{ - if(globalconf.screens_info->xinerama_is_active) - { - area_t area = screen_get_area(phys_screen, NULL, NULL); - xcb_warp_pointer(globalconf.connection, - XCB_NONE, - xcb_aux_get_screen(globalconf.connection, globalconf.default_screen)->root, - 0, 0, 0, 0, area.x, area.y); - } - else - xcb_warp_pointer(globalconf.connection, - XCB_NONE, - xcb_aux_get_screen(globalconf.connection, phys_screen)->root, - 0, 0, 0, 0, 0, 0); -} - - -/** Switch focus to a specified screen. - * Argument must be an absolute or relative screen number. - * \param screen Screen ID - * \param arg screen number - * \ingroup ui_callback - */ -void -uicb_screen_focus(int screen, char *arg) -{ - int new_screen; - - if(arg) - new_screen = compute_new_value_from_arg(arg, screen); - else - new_screen = screen + 1; - - if (new_screen < 0) - new_screen = globalconf.screens_info->nscreen - 1; - if (new_screen > (globalconf.screens_info->nscreen - 1)) - new_screen = 0; - - client_focus(NULL, new_screen, true); - - move_mouse_pointer_to_screen(new_screen); -} - -/** Move client to a screen. - * Argument must be an absolute or relative screen number. - * \param screen Screen ID - * \param arg screen number - * \ingroup ui_callback - */ -void -uicb_client_movetoscreen(int screen __attribute__ ((unused)), char *arg) -{ - int new_screen, prev_screen; - client_t *sel = globalconf.focus->client; - - if(!sel || !globalconf.screens_info->xinerama_is_active) - return; - - if(arg) - new_screen = compute_new_value_from_arg(arg, sel->screen); - else - new_screen = sel->screen + 1; - - if(new_screen >= globalconf.screens_info->nscreen) - new_screen = 0; - else if(new_screen < 0) - new_screen = globalconf.screens_info->nscreen - 1; - - prev_screen = sel->screen; - move_client_to_screen(sel, new_screen, true); - move_mouse_pointer_to_screen(new_screen); - client_focus(sel, sel->screen, true); -} // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/screen.h b/screen.h index c85ef632..70bfea59 100644 --- a/screen.h +++ b/screen.h @@ -29,8 +29,5 @@ area_t get_display_area(int, statusbar_t *, Padding *); int screen_virttophys(int); void move_client_to_screen(client_t *, int, bool); -uicb_t uicb_screen_focus; -uicb_t uicb_client_movetoscreen; - #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/statusbar.c b/statusbar.c index 0ffa9f40..fc5182ec 100644 --- a/statusbar.c +++ b/statusbar.c @@ -32,84 +32,10 @@ extern AwesomeConf globalconf; -static void -statusbar_position_update(statusbar_t *statusbar) -{ - statusbar_t *sb; - area_t area; - - if(statusbar->position == Off) - { - xcb_unmap_window(globalconf.connection, statusbar->sw->window); - return; - } - - xcb_map_window(globalconf.connection, statusbar->sw->window); - - /* Top and Bottom statusbar_t have prio */ - if(statusbar->position == Top || statusbar->position == Bottom) - area = screen_get_area(statusbar->screen, - NULL, - &globalconf.screens[statusbar->screen].padding); - else - area = screen_get_area(statusbar->screen, - globalconf.screens[statusbar->screen].statusbar, - &globalconf.screens[statusbar->screen].padding); - - for(sb = globalconf.screens[statusbar->screen].statusbar; sb && sb != statusbar; sb = sb->next) - switch(sb->position) - { - case Top: - if(sb->position == statusbar->position) - area.y += sb->height; - break; - case Bottom: - if(sb->position == statusbar->position) - area.height -= sb->height; - break; - case Left: - /* we need to re-add our own value removed in the - * screen_get_area computation */ - if(statusbar->position == Left - || statusbar->position == Right) - { - area.x -= statusbar->sw->geometry.width; - area.width += statusbar->sw->geometry.width; - } - break; - case Right: - if(statusbar->position == Left - || statusbar->position == Right) - area.width += statusbar->sw->geometry.width; - break; - default: - break; - } - - switch(statusbar->position) - { - case Top: - simplewindow_move(statusbar->sw, area.x, area.y); - break; - case Bottom: - simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->sw->geometry.height); - break; - case Left: - simplewindow_move(statusbar->sw, area.x - statusbar->sw->geometry.width, - (area.y + area.height) - statusbar->sw->geometry.height); - break; - case Right: - simplewindow_move(statusbar->sw, area.x + area.width, area.y); - break; - default: - break; - } -} - static void statusbar_draw(statusbar_t *statusbar) { - widget_t *widget; + widget_node_t *w; int left = 0, right = 0; area_t rectangle = { 0, 0, 0, 0, NULL, NULL }; @@ -121,22 +47,20 @@ statusbar_draw(statusbar_t *statusbar) rectangle.width = statusbar->width; rectangle.height = statusbar->height; draw_rectangle(statusbar->ctx, rectangle, 1.0, true, - globalconf.screens[statusbar->screen].styles.normal.bg); + statusbar->colors.bg); - for(widget = statusbar->widgets; widget; widget = widget->next) - if (widget->alignment == AlignLeft) - left += widget->draw(widget, statusbar->ctx, left, (left + right)); + for(w = statusbar->widgets; w; w = w->next) + if(w->widget->align == AlignLeft) + left += w->widget->draw(w, statusbar, left, (left + right)); /* renders right widget from last to first */ - for(widget = *widget_list_last(&statusbar->widgets); - widget; - widget = widget_list_prev(&statusbar->widgets, widget)) - if (widget->alignment == AlignRight) - right += widget->draw(widget, statusbar->ctx, right, (left + right)); + for(w = *widget_node_list_last(&statusbar->widgets); w; w = w->prev) + if(w->widget->align == AlignRight) + right += w->widget->draw(w, statusbar, right, (left + right)); - for(widget = statusbar->widgets; widget; widget = widget->next) - if (widget->alignment == AlignFlex) - left += widget->draw(widget, statusbar->ctx, left, (left + right)); + for(w = statusbar->widgets; w; w = w->next) + if(w->widget->align == AlignFlex) + left += w->widget->draw(w, statusbar, left, (left + right)); switch(statusbar->position) { @@ -158,96 +82,145 @@ statusbar_draw(statusbar_t *statusbar) } void -statusbar_preinit(statusbar_t *statusbar) -{ - if(statusbar->height <= 0) - /* 1.5 as default factor, it fits nice but no one knows why */ - statusbar->height = 1.5 * MAX(globalconf.screens[statusbar->screen].styles.normal.font->height, - MAX(globalconf.screens[statusbar->screen].styles.focus.font->height, - globalconf.screens[statusbar->screen].styles.urgent.font->height)); -} - -void -statusbar_init(statusbar_t *statusbar) +statusbar_position_update(statusbar_t *statusbar, position_t position) { statusbar_t *sb; + area_t area; xcb_drawable_t dw; xcb_screen_t *s = NULL; - int phys_screen = screen_virttophys(statusbar->screen); - area_t area = screen_get_area(statusbar->screen, - globalconf.screens[statusbar->screen].statusbar, - &globalconf.screens[statusbar->screen].padding); + bool ignore = false; - statusbar->phys_screen = phys_screen; + simplewindow_delete(&statusbar->sw); + draw_context_delete(&statusbar->ctx); + + if((statusbar->position = position) == Off) + return; + + area = screen_get_area(statusbar->screen, + NULL, + &globalconf.screens[statusbar->screen].padding); /* Top and Bottom statusbar_t have prio */ for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next) + { + /* Ignore every statusbar after me that is in the same position */ + if(statusbar == sb) + { + ignore = true; + continue; + } + else if(ignore && statusbar->position == sb->position) + continue; switch(sb->position) { case Left: + switch(statusbar->position) + { + case Left: + area.x += statusbar->height; + break; + default: + break; + } + break; case Right: - area.width += sb->height; + switch(statusbar->position) + { + case Right: + area.x -= statusbar->height; + break; + default: + break; + } + break; + case Top: + switch(statusbar->position) + { + case Top: + area.y += sb->height; + break; + case Left: + case Right: + area.height -= sb->height; + area.y += sb->height; + break; + default: + break; + } + break; + case Bottom: + switch(statusbar->position) + { + case Bottom: + area.y -= sb->height; + break; + case Left: + case Right: + area.height -= sb->height; + break; + default: + break; + } break; default: break; } - - if(statusbar->width <= 0) - { - if(statusbar->position == Right || statusbar->position == Left) - statusbar->width = area.height; - else - statusbar->width = area.width; } switch(statusbar->position) { case Right: case Left: - statusbar->sw = - simplewindow_new(globalconf.connection, phys_screen, 0, 0, - statusbar->height, statusbar->width, 0); - break; - default: - statusbar->sw = - simplewindow_new(globalconf.connection, phys_screen, 0, 0, - statusbar->width, statusbar->height, 0); - break; - } - - widget_calculate_alignments(statusbar->widgets); - - statusbar_position_update(statusbar); - - switch(statusbar->position) - { - case Off: - return; - case Right: - case Left: - s = xcb_aux_get_screen(globalconf.connection, phys_screen); - + statusbar->width = area.height; + statusbar->sw = + simplewindow_new(globalconf.connection, statusbar->phys_screen, 0, 0, + statusbar->height, statusbar->width, 0); + s = xcb_aux_get_screen(globalconf.connection, statusbar->phys_screen); /* we need a new pixmap this way [ ] to render */ dw = xcb_generate_id(globalconf.connection); xcb_create_pixmap(globalconf.connection, s->root_depth, dw, s->root, statusbar->width, statusbar->height); statusbar->ctx = draw_context_new(globalconf.connection, - phys_screen, + statusbar->phys_screen, statusbar->width, statusbar->height, dw); break; default: + statusbar->width = area.width; + statusbar->sw = + simplewindow_new(globalconf.connection, statusbar->phys_screen, 0, 0, + statusbar->width, statusbar->height, 0); statusbar->ctx = draw_context_new(globalconf.connection, - phys_screen, + statusbar->phys_screen, statusbar->width, statusbar->height, statusbar->sw->drawable); break; } - + switch(statusbar->position) + { + case Top: + simplewindow_move(statusbar->sw, area.x, area.y); + break; + case Bottom: + simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->height); + break; + case Left: + simplewindow_move(statusbar->sw, area.x, + (area.y + area.height) - statusbar->sw->geometry.height); + break; + case Right: + simplewindow_move(statusbar->sw, area.x + area.width - statusbar->height, area.y); + break; + default: + break; + } + + globalconf.screens[statusbar->screen].need_arrange = true; + xcb_map_window(globalconf.connection, statusbar->sw->window); statusbar_draw(statusbar); } @@ -262,10 +235,7 @@ statusbar_refresh() statusbar; statusbar = statusbar->next) if(statusbar->need_update) - { statusbar_draw(statusbar); - break; - } } statusbar_t * @@ -280,36 +250,140 @@ statusbar_getbyname(int screen, const char *name) return NULL; } -static void -statusbar_toggle(statusbar_t *statusbar) +static int +luaA_statusbar_eq(lua_State *L) { - if(statusbar->position == Off) - statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition; - else - statusbar->position = Off; - - globalconf.screens[statusbar->screen].need_arrange = true; + statusbar_t **t1 = luaL_checkudata(L, 1, "statusbar"); + statusbar_t **t2 = luaL_checkudata(L, 2, "statusbar"); + lua_pushboolean(L, (*t1 == *t2)); + return 1; } -/** Toggle the statusbar on or off. - * Argument must be a statusbar name, or no argument for all statusbars. - * \param screen Screen ID - * \param arg statusbar name - * \ingroup ui_callback - */ -void -uicb_statusbar_toggle(int screen, char *arg) +static int +luaA_statusbar_position_set(lua_State *L) { - statusbar_t *sb = statusbar_getbyname(screen, arg); + statusbar_t *s, **sb = luaL_checkudata(L, 1, "statusbar"); + const char *pos = luaL_checkstring(L, 2); + position_t position = position_get_from_str(pos); - if(sb) - statusbar_toggle(sb); - else - for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next) - statusbar_toggle(sb); + if(position != (*sb)->position) + { + (*sb)->position = position; + for(s = globalconf.screens[(*sb)->screen].statusbar; s; s = s->next) + statusbar_position_update(s, s->position); + } - for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next) - statusbar_position_update(sb); + return 0; } +static int +luaA_statusbar_tostring(lua_State *L) +{ + statusbar_t **p = luaL_checkudata(L, 1, "statusbar"); + lua_pushfstring(L, "[statusbar udata(%p) name(%s)]", *p, (*p)->name); + return 1; +} + +static int +luaA_statusbar_widget_add(lua_State *L) +{ + statusbar_t **sb = luaL_checkudata(L, 1, "statusbar"); + widget_t **widget = luaL_checkudata(L, 2, "widget"); + widget_node_t *w = p_new(widget_node_t, 1); + + (*sb)->need_update = true; + w->widget = *widget; + widget_node_list_append(&(*sb)->widgets, w); + widget_ref(widget); + + return 0; +} + +static int +luaA_statusbar_add(lua_State *L) +{ + statusbar_t *s, **sb = luaL_checkudata(L, 1, "statusbar"); + int screen = luaL_checknumber(L, 2) - 1; + + luaA_checkscreen(screen); + + (*sb)->screen = screen; + + /* \todo check for uniq name */ + statusbar_list_append(&globalconf.screens[screen].statusbar, *sb); + for(s = globalconf.screens[(*sb)->screen].statusbar; s; s = s->next) + statusbar_position_update(s, s->position); + statusbar_ref(sb); + (*sb)->screen = screen; + (*sb)->phys_screen = screen_virttophys(screen); + + return 0; +} + +static int +luaA_statusbar_new(lua_State *L) +{ + statusbar_t **sb = lua_newuserdata(L, sizeof(statusbar_t *)); + int objpos = lua_gettop(L); + const char *color; + + luaA_checktable(L, 1); + + *sb = p_new(statusbar_t, 1); + + /* \todo check that the name is unique */ + (*sb)->name = luaA_name_init(L); + + lua_getfield(L, 1, "fg"); + if((color = luaL_optstring(L, -1, NULL))) + draw_color_new(globalconf.connection, globalconf.default_screen, + color, &(*sb)->colors.fg); + else + (*sb)->colors.fg = globalconf.colors.fg; + + lua_getfield(L, 1, "bg"); + if((color = luaL_optstring(L, -1, NULL))) + draw_color_new(globalconf.connection, globalconf.default_screen, + color, &(*sb)->colors.bg); + else + (*sb)->colors.bg = globalconf.colors.bg; + + (*sb)->width = luaA_getopt_number(L, 1, "width", 0); + (*sb)->height = luaA_getopt_number(L, 1, "height", 0); + if((*sb)->height <= 0) + /* 1.5 as default factor, it fits nice but no one knows why */ + (*sb)->height = 1.5 * globalconf.font->height; + + (*sb)->position = position_get_from_str(luaA_getopt_string(L, 1, "position", "top")); + + statusbar_ref(sb); + + lua_pushvalue(L, objpos); + return luaA_settype(L, "statusbar"); +} + +static int +luaA_statusbar_gc(lua_State *L) +{ + statusbar_t **sb = luaL_checkudata(L, 1, "statusbar"); + statusbar_unref(sb); + return 0; +} + +const struct luaL_reg awesome_statusbar_methods[] = +{ + { "new", luaA_statusbar_new }, + { NULL, NULL } +}; +const struct luaL_reg awesome_statusbar_meta[] = +{ + { "widget_add", luaA_statusbar_widget_add }, + { "position_set", luaA_statusbar_position_set }, + { "add", luaA_statusbar_add }, + { "__gc", luaA_statusbar_gc }, + { "__eq", luaA_statusbar_eq }, + { "__tostring", luaA_statusbar_tostring }, + { NULL, NULL }, +}; + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/statusbar.h b/statusbar.h index 6cdee9c6..8b88a7cc 100644 --- a/statusbar.h +++ b/statusbar.h @@ -23,15 +23,26 @@ #define AWESOME_STATUSBAR_H #include "structs.h" +#include "widget.h" +#include "common/refcount.h" +#include "common/swindow.h" +static inline void +statusbar_delete(statusbar_t **statusbar) +{ + simplewindow_delete(&(*statusbar)->sw); + widget_node_list_wipe(&(*statusbar)->widgets); + p_delete(&(*statusbar)->name); + p_delete(statusbar); +} + +void statusbar_position_update(statusbar_t *, position_t); void statusbar_refresh(void); -void statusbar_preinit(statusbar_t *); -void statusbar_init(statusbar_t *); statusbar_t * statusbar_getbyname(int, const char *); -uicb_t uicb_statusbar_toggle; - -DO_SLIST(statusbar_t, statusbar, p_delete) +DO_RCNT(statusbar_t, statusbar, statusbar_delete) +DO_SLIST(statusbar_t, statusbar, statusbar_delete) +DO_SLIST_UNREF(statusbar_t, statusbar, statusbar_delete) #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/structs.h b/structs.h index ba918875..223e3ea5 100644 --- a/structs.h +++ b/structs.h @@ -25,10 +25,13 @@ #include <xcb/xcb_event.h> #include <regex.h> + +#include "lua.h" #include "layout.h" #include "common/draw.h" #include "common/swindow.h" #include "common/xscreen.h" +#include "common/refcount.h" /** stacking layout */ typedef enum @@ -47,58 +50,60 @@ enum typedef struct { - simple_window_t *sw; + /** Ref count */ + int refcount; position_t position; - position_t dposition; alignment_t align; int width, height; char *text_normal, *text_focus, *text_urgent; } titlebar_t; -/** Rule type */ -typedef struct rule_t rule_t; -struct rule_t +static inline void +titlebar_delete(titlebar_t **t) { - char *icon; - char *xprop; - int screen; - fuzzy_t isfloating; - fuzzy_t ismaster; - titlebar_t titlebar; - double opacity; - regex_t *prop_r; - regex_t *tags_r; - regex_t *xpropval_r; - /** Next and previous rules */ - rule_t *prev, *next; -}; + p_delete(&(*t)->text_normal); + p_delete(&(*t)->text_focus); + p_delete(&(*t)->text_urgent); + p_delete(t); +} + +DO_RCNT(titlebar_t, titlebar, titlebar_delete) /** Keys bindings */ typedef struct keybinding_t keybinding_t; struct keybinding_t { + /** Key modifier */ unsigned long mod; + /** Keysym */ xcb_keysym_t keysym; + /** Keycode */ xcb_keycode_t keycode; - uicb_t *func; - char *arg; + /** Lua function to execute. */ + luaA_function fct; /** Next and previous keys */ keybinding_t *prev, *next; }; +DO_SLIST(keybinding_t, keybinding, p_delete) + /** Mouse buttons bindings */ typedef struct Button Button; struct Button { + /** Key modifiers */ unsigned long mod; + /** Mouse button number */ unsigned int button; - uicb_t *func; - char *arg; + /** Lua function to execute. */ + luaA_function fct; /** Next and previous buttons */ Button *prev, *next; }; -/** widget_t tell status code */ +DO_SLIST(Button, button, p_delete) + +/** Widget tell status code */ typedef enum { WIDGET_NOERROR = 0, @@ -110,41 +115,67 @@ typedef enum WIDGET_ERROR_FORMAT_SECTION } widget_tell_status_t; -/** widget_t */ +/** Widget */ typedef struct widget_t widget_t; +typedef struct widget_node_t widget_node_t; typedef struct statusbar_t statusbar_t; struct widget_t { + /** Ref count */ + int refcount; /** widget_t name */ char *name; /** Draw function */ - int (*draw)(widget_t *, draw_context_t *, int, int); + int (*draw)(widget_node_t *, statusbar_t *, int, int); /** Update function */ - widget_tell_status_t (*tell)(widget_t *, char *, char *); + widget_tell_status_t (*tell)(widget_t *, const char *, const char *); /** ButtonPressedEvent handler */ - void (*button_press)(widget_t *, xcb_button_press_event_t *); - /** statusbar_t */ - statusbar_t *statusbar; + void (*button_press)(widget_node_t *, statusbar_t *, xcb_button_press_event_t *); /** Alignement */ - alignment_t alignment; + alignment_t align; /** Misc private data */ void *data; - /** true if user supplied coords */ - bool user_supplied_x; - bool user_supplied_y; - /** area_t */ - area_t area; /** Buttons bindings */ Button *buttons; /** Cache flags */ int cache_flags; - /** Next and previous widgets */ - widget_t *prev, *next; }; +struct widget_node_t +{ + /** The widget */ + widget_t *widget; + /** The area where the widget was drawn */ + area_t area; + /** Next and previous widget in the list */ + widget_node_t *prev, *next; +}; + +static inline void +widget_delete(widget_t **widget) +{ + button_list_wipe(&(*widget)->buttons); + p_delete(&(*widget)->data); + p_delete(&(*widget)->name); + p_delete(widget); +} + +DO_RCNT(widget_t, widget, widget_delete) + +static inline void +widget_node_delete(widget_node_t **node) +{ + widget_unref(&(*node)->widget); + p_delete(node); +} + +DO_SLIST(widget_node_t, widget_node, widget_node_delete) + /** Status bar */ struct statusbar_t { + /** Ref count */ + int refcount; /** Window */ simple_window_t *sw; /** statusbar_t name */ @@ -153,20 +184,23 @@ struct statusbar_t int width; /** Bar height */ int height; - /** Default position */ - position_t dposition; /** Bar position */ position_t position; /** Screen */ int screen; /** Physical screen id */ int phys_screen; - /** widget_t list */ - widget_t *widgets; + /** Widget list */ + widget_node_t *widgets; /** Draw context */ draw_context_t *ctx; /** Need update */ bool need_update; + /** Default colors */ + struct + { + xcolor_t fg, bg; + } colors; /** Next and previous statusbars */ statusbar_t *prev, *next; }; @@ -212,11 +246,14 @@ struct client_t int phys_screen; /** True if the client is a new one */ bool newcomer; - /** titlebar_t */ + /** Titlebar */ titlebar_t titlebar; - /** layer in the stacking order */ - layer_t layer; - layer_t oldlayer; + /** Titlebar window */ + simple_window_t *titlebar_sw; + /** Old position */ + position_t titlebar_oldposition; + /** Layer in the stacking order */ + layer_t layer, oldlayer; }; typedef struct client_node_t client_node_t; @@ -231,16 +268,16 @@ struct client_node_t typedef struct _tag_t tag_t; struct _tag_t { + /** Ref count */ + int refcount; /** Tag name */ char *name; /** Screen */ int screen; /** true if selected */ bool selected; - /** true if was selected before selecting others tags */ - bool was_selected; /** Current tag layout */ - Layout *layout; + LayoutArrange *layout; /** Master width factor */ double mwfact; /** Number of master windows */ @@ -277,43 +314,10 @@ typedef struct typedef area_t (FloatingPlacement)(client_t *); typedef struct { - /** titlebar_t default parameters */ - titlebar_t titlebar_default; - /** Number of pixels to snap windows */ - int snap; - /** Border size */ - int borderpx; - /** Mwfact limits */ - float mwfact_upper_limit, mwfact_lower_limit; - /** Floating window placement algo */ - FloatingPlacement *floating_placement; - /** Respect resize hints */ - bool resize_hints; - /** Sloppy focus: focus follow mouse */ - bool sloppy_focus; - /** true if we should raise windows on focus */ - bool sloppy_focus_raise; - /** Focus new clients */ - bool new_get_focus; - /** true if new clients should become master */ - bool new_become_master; /** true if we need to arrange() */ bool need_arrange; - /** Colors */ - struct - { - style_t normal; - style_t focus; - style_t urgent; - } styles; - /** Transparency of unfocused clients */ - double opacity_unfocused; - /** Transparency of focused clients */ - double opacity_focused; /** Tag list */ tag_t *tags; - /** Layout list */ - Layout *layouts; /** Status bar */ statusbar_t *statusbar; /** Padding */ @@ -336,8 +340,6 @@ struct AwesomeConf VirtScreen *screens; /** Screens info */ screens_info_t *screens_info; - /** Rules list */ - rule_t *rules; /** Keys bindings list */ keybinding_t *keys; /** Mouse bindings list */ @@ -369,6 +371,8 @@ struct AwesomeConf } scratch; /** Path to config file */ char *configpath; + /** Floating window placement algo */ + FloatingPlacement *floating_placement; /** Selected clients history */ client_node_t *focus; /** Link between tags and clients */ @@ -379,6 +383,28 @@ struct AwesomeConf int pointer_x, pointer_y; /** Atoms cache */ xutil_atom_cache_t *atoms; + /** Lua VM state */ + lua_State *L; + /** Default colors */ + struct + { + xcolor_t fg, bg; + } colors; + /** Default font */ + font_t *font; + /** Respect resize hints */ + bool resize_hints; + struct + { + /** Command to execute when spawning a new client */ + luaA_function newclient; + /** Command to execute when giving focus to a client */ + luaA_function focus; + /** Command to execute when removing focus to a client */ + luaA_function unfocus; + /** Command to run when mouse is over */ + luaA_function mouseover; + } hooks; }; #endif diff --git a/tag.c b/tag.c index 675f668b..1423b32c 100644 --- a/tag.c +++ b/tag.c @@ -24,11 +24,17 @@ #include "screen.h" #include "tag.h" -#include "rules.h" #include "client.h" #include "ewmh.h" #include "widget.h" +#include "layouts/tile.h" +#include "layouts/max.h" +#include "layouts/floating.h" +#include "layouts/fibonacci.h" + +#include "layoutgen.h" + extern AwesomeConf globalconf; /** Create a new tag. Parameteres values are checked. @@ -40,7 +46,7 @@ extern AwesomeConf globalconf; * \return a new tag with all these parameters */ tag_t * -tag_new(const char *name, Layout *layout, double mwfact, int nmaster, int ncol) +tag_new(const char *name, LayoutArrange *layout, double mwfact, int nmaster, int ncol) { tag_t *tag; @@ -58,6 +64,8 @@ tag_new(const char *name, Layout *layout, double mwfact, int nmaster, int ncol) if((tag->ncol = ncol) < 1) tag->ncol = 1; + tag_ref(&tag); + return tag; } @@ -72,22 +80,7 @@ tag_append_to_screen(tag_t *tag, int screen) tag->screen = screen; tag_list_append(&globalconf.screens[screen].tags, tag); - ewmh_update_net_numbers_of_desktop(phys_screen); - ewmh_update_net_desktop_names(phys_screen); - widget_invalidate_cache(screen, WIDGET_CACHE_TAGS); -} - -/** Push a tag to a screen tag list. - * \param tag the tag to push - * \param screen the screen - */ -void -tag_push_to_screen(tag_t *tag, int screen) -{ - int phys_screen = screen_virttophys(screen); - - tag->screen = screen; - tag_list_push(&globalconf.screens[screen].tags, tag); + tag_ref(&tag); ewmh_update_net_numbers_of_desktop(phys_screen); ewmh_update_net_desktop_names(phys_screen); widget_invalidate_cache(screen, WIDGET_CACHE_TAGS); @@ -173,34 +166,6 @@ tag_client_with_current_selected(client_t *c) untag_client(c, tag); } -/** Tag the client according to a rule. - * \param c the client - * \param r the rule - */ -void -tag_client_with_rule(client_t *c, rule_t *r) -{ - tag_t *tag; - bool matched = false; - - if(!r) return; - - /* check if at least one tag match */ - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - if(tag_match_rule(tag, r)) - { - matched = true; - break; - } - - if(matched) - for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) - if(tag_match_rule(tag, r)) - tag_client(c, tag); - else - untag_client(c, tag); -} - /** Get the current tags for the specified screen. * Returned pointer must be p_delete'd after. * \param screen screen id @@ -226,123 +191,6 @@ tags_get_current(int screen) return tags; } -/** Tag the focused client with the given tag. - * \param screen Screen ID - * \param arg tag name - * \ingroup ui_callback - */ -void -uicb_client_tag(int screen, char *arg) -{ - int tag_id = -1; - tag_t *tag, *target_tag; - client_t *sel = globalconf.focus->client; - - if(!sel) - return; - - if(arg) - { - tag_id = atoi(arg) - 1; - if(tag_id != -1) - { - for(target_tag = globalconf.screens[screen].tags; target_tag && tag_id > 0; - target_tag = target_tag->next, tag_id--); - if(target_tag) - { - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - untag_client(sel, tag); - tag_client(sel, target_tag); - } - } - } - else - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - tag_client(sel, tag); -} - -/** Toggle a tag on the focused client. - * \param screen virtual screen id - * \param arg tag number - * \ingroup ui_callback - */ -void -uicb_client_toggletag(int screen, char *arg) -{ - client_t *sel = globalconf.focus->client; - int i; - Bool is_sticky = True; - tag_t *tag, *target_tag; - - if(!sel) - return; - - if(arg) - { - i = atoi(arg) - 1; - for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0; - target_tag = target_tag->next, i--); - if(target_tag) - { - if(is_client_tagged(sel, target_tag)) - untag_client(sel, target_tag); - else - tag_client(sel, target_tag); - } - - /* check that there's at least one tag selected for this client*/ - for(tag = globalconf.screens[screen].tags; tag - && !is_client_tagged(sel, tag); tag = tag->next); - - if(!tag) - tag_client(sel, target_tag); - } - else - { - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - if(!is_client_tagged(sel, tag)) - { - is_sticky = False; - tag_client(sel, tag); - } - if(is_sticky) - tag_client_with_current_selected(sel); - } -} - -/** Toggle the visibility of a tag. - * \param screen Screen ID - * \param arg tag_t name - * \ingroup ui_callback - */ -void -uicb_tag_toggleview(int screen, char *arg) -{ - int i; - tag_t *tag, *target_tag, - **backtag, **curtags = tags_get_current(screen); - - if(arg) - { - i = atoi(arg) - 1; - for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0; - target_tag = target_tag->next, i--); - - if(target_tag) - tag_view(target_tag, !target_tag->selected); - } - else - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - tag_view(tag, !tag->selected); - - /* check that there's at least one tag selected */ - for(tag = globalconf.screens[screen].tags; tag && !tag->selected; tag = tag->next); - if(!tag) - for(backtag = curtags; *backtag; backtag++) - tag_view(*backtag, True); - - p_delete(&curtags); -} /** Set a tag to be the only one viewed. * \param target the tag to see @@ -400,94 +248,226 @@ tag_view_only_byindex(int screen, int dindex) void tag_view(tag_t *tag, bool view) { - tag->was_selected = tag->selected; tag->selected = view; ewmh_update_net_current_desktop(screen_virttophys(tag->screen)); widget_invalidate_cache(tag->screen, WIDGET_CACHE_TAGS); globalconf.screens[tag->screen].need_arrange = true; } -/** View only this tag. - * \param screen Screen ID - * \param arg tag to view - * \ingroup ui_callback - */ -void -uicb_tag_view(int screen, char *arg) +static int +luaA_tag_eq(lua_State *L) { - tag_t *tag; - - if(arg) - tag_view_only_byindex(screen, atoi(arg) - 1); - else - for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - tag_view(tag, true); + tag_t **t1 = luaL_checkudata(L, 1, "tag"); + tag_t **t2 = luaL_checkudata(L, 2, "tag"); + lua_pushboolean(L, (*t1 == *t2)); + return 1; } -/** View the previously selected tags. - * \param screen Screen ID - * \param arg unused - * \ingroup ui_callback - */ -void -uicb_tag_prev_selected(int screen, char *arg __attribute__ ((unused))) +static int +luaA_tag_tostring(lua_State *L) { - tag_t *tag; + tag_t **p = luaL_checkudata(L, 1, "tag"); + lua_pushfstring(L, "[tag udata(%p) name(%s)]", *p, (*p)->name); + return 1; +} + +static int +luaA_tag_add(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + int screen = luaL_checknumber(L, 2) - 1; + luaA_checkscreen(screen); + /* \todo check tag is not already in another screen */ + tag_append_to_screen(*tag, screen); + return 0; +} + +static int +luaA_tag_get(lua_State *L) +{ + int screen = luaL_checknumber(L, 1) - 1; + const char *name = luaL_checkstring(L, 2); + tag_t *tag, **tobj; + int ret, i = 1; + regex_t r; + regmatch_t match; + char error[512]; + + luaA_checkscreen(screen); + + if((ret = regcomp(&r, name, REG_EXTENDED))) + { + regerror(ret, &r, error, sizeof(error)); + luaL_error(L, "regex compilation error: %s\n", error); + } + + lua_newtable(L); for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) - tag_view(tag, tag->was_selected); + if(!regexec(&r, tag->name, 1, &match, 0)) + { + tobj = lua_newuserdata(L, sizeof(tag_t *)); + *tobj = tag; + tag_ref(&tag); + luaA_settype(L, "tag"); + lua_rawseti(L, -2, i++); + } + + return 1; } -/** View the next tag. - * \param screen Screen ID - * \param arg unused - * \ingroup ui_callback +/** Create a new tag. + * \param L Lua state. + * \return One because there's one element, a user data. */ -void -uicb_tag_viewnext(int screen, char *arg __attribute__ ((unused))) +static int +luaA_tag_new(lua_State *L) { - tag_t *tag, **curtags = tags_get_current(screen); + tag_t **tag; + int ncol, nmaster; + const char *name, *lay; + double mwfact; + LayoutArrange *layout; - tag = tag_list_next_cycle(&globalconf.screens[screen].tags, curtags[0]); + luaA_checktable(L, 1); - tag_view(curtags[0], false); - tag_view(tag, true); + name = luaA_name_init(L); + mwfact = luaA_getopt_number(L, 1, "mwfact", 0.5); + ncol = luaA_getopt_number(L, 1, "ncol", 1); + nmaster = luaA_getopt_number(L, 1, "nmaster", 1); + lay = luaA_getopt_string(L, 1, "layout", "tile"); - p_delete(&curtags); + layout = name_func_lookup(lay, LayoutList); + + tag = lua_newuserdata(L, sizeof(tag_t *)); + + *tag = tag_new(name, + layout, + mwfact, nmaster, ncol); + + return luaA_settype(L, "tag"); } -/** View the previous tag. - * \param screen Screen ID - * \param arg unused - * \ingroup ui_callback - */ -void -uicb_tag_viewprev(int screen, char *arg __attribute__ ((unused))) +static int +luaA_tag_view(lua_State *L) { - tag_t *tag, **curtags = tags_get_current(screen); - - tag = tag_list_prev_cycle(&globalconf.screens[screen].tags, curtags[0]); - - tag_view(curtags[0], false); - tag_view(tag, true); - - p_delete(&curtags); + tag_t **tag = luaL_checkudata(L, 1, "tag"); + bool view = luaA_checkboolean(L, 2); + tag_view(*tag, view); + return 0; } -/** Create a new tag. Argument must be the tag name. - * \param screen the screen id - * \param arg the tag name - */ -void -uicb_tag_create(int screen, char *arg) +static int +luaA_tag_isselected(lua_State *L) { - tag_t *tag; - - if(!a_strlen(arg)) - return; - - tag = tag_new(arg, globalconf.screens[screen].layouts, 0.5, 1, 1); - tag_append_to_screen(tag, screen); + tag_t **tag = luaL_checkudata(L, 1, "tag"); + lua_pushboolean(L, (*tag)->selected); + return 1; } +static int +luaA_tag_mwfact_set(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + double mwfact = luaL_checknumber(L, 2); + + if(mwfact < 1 && mwfact > 0) + { + (*tag)->mwfact = mwfact; + globalconf.screens[(*tag)->screen].need_arrange = true; + } + else + luaL_error(L, "bad value, must be between 0 and 1"); + + return 0; +} + +static int +luaA_tag_mwfact_get(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + lua_pushnumber(L, (*tag)->mwfact); + return 1; +} + +static int +luaA_tag_ncol_set(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + int ncol = luaL_checknumber(L, 2); + + if(ncol >= 1) + { + (*tag)->ncol = ncol; + globalconf.screens[(*tag)->screen].need_arrange = true; + } + else + luaL_error(L, "bad value, must be greater than 1"); + + return 0; +} + +static int +luaA_tag_ncol_get(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + lua_pushnumber(L, (*tag)->ncol); + return 1; +} + +static int +luaA_tag_nmaster_set(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + int nmaster = luaL_checknumber(L, 2); + + if(nmaster >= 0) + { + (*tag)->nmaster = nmaster; + globalconf.screens[(*tag)->screen].need_arrange = true; + } + else + luaL_error(L, "bad value, must be greater than 0"); + + return 0; +} + +static int +luaA_tag_nmaster_get(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + lua_pushnumber(L, (*tag)->nmaster); + return 1; +} + +static int +luaA_tag_gc(lua_State *L) +{ + tag_t **tag = luaL_checkudata(L, 1, "tag"); + tag_unref(tag); + return 0; +} + +const struct luaL_reg awesome_tag_methods[] = +{ + { "new", luaA_tag_new }, + { "get", luaA_tag_get}, + { NULL, NULL } +}; +const struct luaL_reg awesome_tag_meta[] = +{ + { "add", luaA_tag_add }, + { "view", luaA_tag_view }, + { "isselected", luaA_tag_isselected }, + { "mwfact_set", luaA_tag_mwfact_set }, + { "mwfact_get", luaA_tag_mwfact_get }, + { "ncol_set", luaA_tag_ncol_set }, + { "ncol_get", luaA_tag_ncol_get }, + { "nmaster_set", luaA_tag_nmaster_set }, + { "nmaster_get", luaA_tag_nmaster_get }, + { "__eq", luaA_tag_eq }, + { "__gc", luaA_tag_gc }, + { "__tostring", luaA_tag_tostring }, + { NULL, NULL }, +}; // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/tag.h b/tag.h index 12d4cca8..502fa5cc 100644 --- a/tag.h +++ b/tag.h @@ -23,33 +23,35 @@ #define AWESOME_TAG_H #include "structs.h" +#include "common/refcount.h" /** Check if a client is tiled */ #define IS_TILED(client, screen) (client && !client->isfloating && !client->ismax && client_isvisible(client, screen)) -tag_t * tag_new(const char *, Layout *, double, int, int); +/* Contructor, destructor and referencors */ +tag_t * tag_new(const char *, LayoutArrange *, double, int, int); + +static inline void +tag_delete(tag_t **tag) +{ + p_delete(&(*tag)->name); + p_delete(tag); +} + void tag_view(tag_t *, bool); void tag_view_byindex(int, int, bool); -void tag_push_to_screen(tag_t *, int); tag_t ** tags_get_current(int); void tag_client(client_t *, tag_t *); void untag_client(client_t *, tag_t *); bool is_client_tagged(client_t *, tag_t *); -void tag_client_with_rule(client_t *, rule_t *r); void tag_client_with_current_selected(client_t *); void tag_view_only_byindex(int, int); void tag_append_to_screen(tag_t *, int); -uicb_t uicb_client_tag; -uicb_t uicb_client_toggletag; -uicb_t uicb_tag_toggleview; -uicb_t uicb_tag_view; -uicb_t uicb_tag_prev_selected; -uicb_t uicb_tag_viewnext; -uicb_t uicb_tag_viewprev; -uicb_t uicb_tag_create; +DO_RCNT(tag_t, tag, tag_delete) +DO_SLIST(tag_t, tag, tag_delete) +DO_SLIST_UNREF(tag_t, tag, tag_delete) -DO_SLIST(tag_t, tag, p_delete) DO_SLIST(tag_client_node_t, tag_client_node, p_delete) #endif diff --git a/titlebar.c b/titlebar.c index d2f8508d..1421e67d 100644 --- a/titlebar.c +++ b/titlebar.c @@ -50,35 +50,327 @@ static inline area_t titlebar_size(client_t *c) { return draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.screens[c->screen].styles.normal.font, titlebar_text(c)); + globalconf.font, titlebar_text(c)); } -/** Initialize a titlebar: create the simple_window_t. - * We still need to update its geometry to have it placed correctly. +/** Draw the titlebar content. * \param c the client */ void +titlebar_draw(client_t *c) +{ + xcb_drawable_t dw = 0; + draw_context_t *ctx; + area_t geometry; + xcb_screen_t *s; + char *text; + + if(!c->titlebar_sw) + return; + + s = xcb_aux_get_screen(globalconf.connection, + c->titlebar_sw->phys_screen); + + switch(c->titlebar.position) + { + case Off: + return; + case Right: + case Left: + dw = xcb_generate_id(globalconf.connection); + xcb_create_pixmap(globalconf.connection, s->root_depth, + dw, + s->root, + c->titlebar_sw->geometry.height, + c->titlebar_sw->geometry.width); + ctx = draw_context_new(globalconf.connection, c->titlebar_sw->phys_screen, + c->titlebar_sw->geometry.height, + c->titlebar_sw->geometry.width, + dw); + geometry.width = c->titlebar_sw->geometry.height; + geometry.height = c->titlebar_sw->geometry.width; + break; + default: + ctx = draw_context_new(globalconf.connection, c->titlebar_sw->phys_screen, + c->titlebar_sw->geometry.width, + c->titlebar_sw->geometry.height, + c->titlebar_sw->drawable); + geometry = c->titlebar_sw->geometry; + break; + } + + text = titlebar_text(c); + geometry.x = geometry.y = 0; + draw_rectangle(ctx, geometry, 1.0, true, globalconf.colors.bg); + draw_text(ctx, globalconf.font, &globalconf.colors.fg, geometry, text); + p_delete(&text); + + switch(c->titlebar.position) + { + case Left: + draw_rotate(ctx, c->titlebar_sw->drawable, ctx->height, ctx->width, + - M_PI_2, 0, c->titlebar_sw->geometry.height); + xcb_free_pixmap(globalconf.connection, dw); + break; + case Right: + draw_rotate(ctx, c->titlebar_sw->drawable, ctx->height, ctx->width, + M_PI_2, c->titlebar_sw->geometry.width, 0); + xcb_free_pixmap(globalconf.connection, dw); + default: + break; + } + + simplewindow_refresh_drawable(c->titlebar_sw); + + draw_context_delete(&ctx); +} + +/** Update the titlebar geometry for a floating client. + * \param c the client + */ +void +titlebar_update_geometry_floating(client_t *c) +{ + int width, x_offset = 0, y_offset = 0; + + if(!c->titlebar_sw) + return; + + switch(c->titlebar.position) + { + default: + return; + case Off: + return; + case Top: + if(!c->titlebar.width) + width = c->geometry.width + 2 * c->border; + else + width = MIN(c->titlebar.width, c->geometry.width); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + x_offset = 2 * c->border + c->geometry.width - width; + break; + case AlignCenter: + x_offset = (c->geometry.width - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + c->geometry.x + x_offset, + c->geometry.y - c->titlebar_sw->geometry.height, + width, + c->titlebar_sw->geometry.height); + break; + case Bottom: + if(!c->titlebar.width) + width = c->geometry.width + 2 * c->border; + else + width = MIN(c->titlebar.width, c->geometry.width); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + x_offset = 2 * c->border + c->geometry.width - width; + break; + case AlignCenter: + x_offset = (c->geometry.width - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + c->geometry.x + x_offset, + c->geometry.y + c->geometry.height + 2 * c->border, + width, + c->titlebar_sw->geometry.height); + break; + case Left: + if(!c->titlebar.width) + width = c->geometry.height + 2 * c->border; + else + width = MIN(c->titlebar.width, c->geometry.height); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + y_offset = 2 * c->border + c->geometry.height - width; + break; + case AlignCenter: + y_offset = (c->geometry.height - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + c->geometry.x - c->titlebar_sw->geometry.width, + c->geometry.y + y_offset, + c->titlebar_sw->geometry.width, + width); + break; + case Right: + if(!c->titlebar.width) + width = c->geometry.height + 2 * c->border; + else + width = MIN(c->titlebar.width, c->geometry.height); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + y_offset = 2 * c->border + c->geometry.height - width; + break; + case AlignCenter: + y_offset = (c->geometry.height - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + c->geometry.x + c->geometry.width + 2 * c->border, + c->geometry.y + y_offset, + c->titlebar_sw->geometry.width, + width); + break; + } + + titlebar_draw(c); +} + + +/** Update the titlebar geometry for a tiled client. + * \param c the client + * \param geometry the geometry the client will receive + */ +void +titlebar_update_geometry(client_t *c, area_t geometry) +{ + int width, x_offset = 0 , y_offset = 0; + + if(!c->titlebar_sw) + return; + + switch(c->titlebar.position) + { + default: + return; + case Off: + return; + case Top: + if(!c->titlebar.width) + width = geometry.width + 2 * c->border; + else + width = MIN(c->titlebar.width, geometry.width); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + x_offset = 2 * c->border + geometry.width - width; + break; + case AlignCenter: + x_offset = (geometry.width - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + geometry.x + x_offset, + geometry.y, + width, + c->titlebar_sw->geometry.height); + break; + case Bottom: + if(!c->titlebar.width) + width = geometry.width + 2 * c->border; + else + width = MIN(c->titlebar.width, geometry.width); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + x_offset = 2 * c->border + geometry.width - width; + break; + case AlignCenter: + x_offset = (geometry.width - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + geometry.x + x_offset, + geometry.y + geometry.height + - c->titlebar_sw->geometry.height + 2 * c->border, + width, + c->titlebar_sw->geometry.height); + break; + case Left: + if(!c->titlebar.width) + width = geometry.height + 2 * c->border; + else + width = MIN(c->titlebar.width, geometry.height); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + y_offset = 2 * c->border + geometry.height - width; + break; + case AlignCenter: + y_offset = (geometry.height - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + geometry.x, + geometry.y + y_offset, + c->titlebar_sw->geometry.width, + width); + break; + case Right: + if(!c->titlebar.width) + width = geometry.height + 2 * c->border; + else + width = MIN(c->titlebar.width, geometry.height); + switch(c->titlebar.align) + { + default: + break; + case AlignRight: + y_offset = 2 * c->border + geometry.height - width; + break; + case AlignCenter: + y_offset = (geometry.height - width) / 2; + break; + } + simplewindow_move_resize(c->titlebar_sw, + geometry.x + geometry.width + - c->titlebar_sw->geometry.width + 2 * c->border, + geometry.y + y_offset, + c->titlebar_sw->geometry.width, + width); + break; + } + + titlebar_draw(c); +} + +/** Set client titlebar position. + * \param c The client. + * \param p The position. + */ +void titlebar_init(client_t *c) { int width = 0, height = 0; if(!c->titlebar.height) - c->titlebar.height = MAX(MAX(draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.screens[c->screen].styles.focus.font, - client_markup_parse(c, c->titlebar.text_focus, a_strlen(c->titlebar.text_focus))).height, - draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.screens[c->screen].styles.normal.font, - client_markup_parse(c, c->titlebar.text_normal, a_strlen(c->titlebar.text_normal))).height), - draw_text_extents(globalconf.connection, globalconf.default_screen, - globalconf.screens[c->screen].styles.urgent.font, - client_markup_parse(c, c->titlebar.text_urgent, a_strlen(c->titlebar.text_urgent))).height); - + c->titlebar.height = draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.font, + client_markup_parse(c, + c->titlebar.text_focus, + a_strlen(c->titlebar.text_focus))).height; switch(c->titlebar.position) { - case Off: - return; default: c->titlebar.position = Off; + if(c->titlebar_sw) + xcb_unmap_window(globalconf.connection, c->titlebar_sw->window); + return; return; case Top: case Bottom: @@ -97,411 +389,116 @@ titlebar_init(client_t *c) width = c->titlebar.height; break; } - c->titlebar.sw = simplewindow_new(globalconf.connection, + + /* Delete old statusbar */ + simplewindow_delete(&c->titlebar_sw); + + c->titlebar_sw = simplewindow_new(globalconf.connection, c->phys_screen, 0, 0, width, height, 0); - xcb_map_window(globalconf.connection, c->titlebar.sw->window); -} - -/** Add the titlebar geometry to a geometry. - * \param t the titlebar - * \param geometry the geometry - * \return a new geometry bigger if the titlebar is visible - */ -area_t -titlebar_geometry_add(titlebar_t *t, area_t geometry) -{ - if(!t->sw) - return geometry; - - switch(t->position) - { - case Top: - geometry.y -= t->sw->geometry.height; - geometry.height += t->sw->geometry.height; - break; - case Bottom: - geometry.height += t->sw->geometry.height; - break; - case Left: - geometry.x -= t->sw->geometry.width; - geometry.width += t->sw->geometry.width; - break; - case Right: - geometry.width += t->sw->geometry.width; - break; - default: - break; - } - - return geometry; -} - -/** Remove the titlebar geometry to a geometry. - * \param t the titlebar - * \param geometry the geometry - * \return a new geometry smaller if the titlebar is visible - */ -area_t -titlebar_geometry_remove(titlebar_t *t, area_t geometry) -{ - if(!t->sw) - return geometry; - - switch(t->position) - { - case Top: - geometry.y += t->sw->geometry.height; - geometry.height -= t->sw->geometry.height; - break; - case Bottom: - geometry.height -= t->sw->geometry.height; - break; - case Left: - geometry.x += t->sw->geometry.width; - geometry.width -= t->sw->geometry.width; - break; - case Right: - geometry.width -= t->sw->geometry.width; - break; - default: - break; - } - - return geometry; -} - -/** Draw the titlebar content. - * \param c the client - */ -void -titlebar_draw(client_t *c) -{ - xcb_drawable_t dw = 0; - draw_context_t *ctx; - area_t geometry; - xcb_screen_t *s; - char *text; - style_t *style; - - if(!c->titlebar.sw) - return; - - s = xcb_aux_get_screen(globalconf.connection, - c->titlebar.sw->phys_screen); - - switch(c->titlebar.position) - { - case Off: - return; - case Right: - case Left: - dw = xcb_generate_id(globalconf.connection); - xcb_create_pixmap(globalconf.connection, s->root_depth, - dw, - s->root, - c->titlebar.sw->geometry.height, - c->titlebar.sw->geometry.width); - ctx = draw_context_new(globalconf.connection, c->titlebar.sw->phys_screen, - c->titlebar.sw->geometry.height, - c->titlebar.sw->geometry.width, - dw); - geometry.width = c->titlebar.sw->geometry.height; - geometry.height = c->titlebar.sw->geometry.width; - break; - default: - ctx = draw_context_new(globalconf.connection, c->titlebar.sw->phys_screen, - c->titlebar.sw->geometry.width, - c->titlebar.sw->geometry.height, - c->titlebar.sw->drawable); - geometry = c->titlebar.sw->geometry; - break; - } - - text = titlebar_text(c); - geometry.x = geometry.y = 0; - style = client_style_get(c); - draw_text(ctx, geometry, text, style); - p_delete(&text); - - switch(c->titlebar.position) - { - case Left: - draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width, - - M_PI_2, 0, c->titlebar.sw->geometry.height); - xcb_free_pixmap(globalconf.connection, dw); - break; - case Right: - draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width, - M_PI_2, c->titlebar.sw->geometry.width, 0); - xcb_free_pixmap(globalconf.connection, dw); - default: - break; - } - - simplewindow_refresh_drawable(c->titlebar.sw); - - draw_context_delete(&ctx); -} - -/** Update the titlebar geometry for a floating client. - * \param c the client - */ -void -titlebar_update_geometry_floating(client_t *c) -{ - int width, x_offset = 0, y_offset = 0; - - if(!c->titlebar.sw) - return; - - switch(c->titlebar.position) - { - default: - return; - case Off: - return; - case Top: - if(!c->titlebar.width) - width = c->geometry.width + 2 * c->border; - else - width = MIN(c->titlebar.width, c->geometry.width); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - x_offset = 2 * c->border + c->geometry.width - width; - break; - case AlignCenter: - x_offset = (c->geometry.width - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - c->geometry.x + x_offset, - c->geometry.y - c->titlebar.sw->geometry.height, - width, - c->titlebar.sw->geometry.height); - break; - case Bottom: - if(!c->titlebar.width) - width = c->geometry.width + 2 * c->border; - else - width = MIN(c->titlebar.width, c->geometry.width); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - x_offset = 2 * c->border + c->geometry.width - width; - break; - case AlignCenter: - x_offset = (c->geometry.width - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - c->geometry.x + x_offset, - c->geometry.y + c->geometry.height + 2 * c->border, - width, - c->titlebar.sw->geometry.height); - break; - case Left: - if(!c->titlebar.width) - width = c->geometry.height + 2 * c->border; - else - width = MIN(c->titlebar.width, c->geometry.height); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - y_offset = 2 * c->border + c->geometry.height - width; - break; - case AlignCenter: - y_offset = (c->geometry.height - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - c->geometry.x - c->titlebar.sw->geometry.width, - c->geometry.y + y_offset, - c->titlebar.sw->geometry.width, - width); - break; - case Right: - if(!c->titlebar.width) - width = c->geometry.height + 2 * c->border; - else - width = MIN(c->titlebar.width, c->geometry.height); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - y_offset = 2 * c->border + c->geometry.height - width; - break; - case AlignCenter: - y_offset = (c->geometry.height - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - c->geometry.x + c->geometry.width + 2 * c->border, - c->geometry.y + y_offset, - c->titlebar.sw->geometry.width, - width); - break; - } - titlebar_draw(c); + xcb_map_window(globalconf.connection, c->titlebar_sw->window); } - -/** Update the titlebar geometry for a tiled client. - * \param c the client - * \param geometry the geometry the client will receive - */ -void -titlebar_update_geometry(client_t *c, area_t geometry) +static int +luaA_titlebar_new(lua_State *L) { - int width, x_offset = 0 , y_offset = 0; + titlebar_t **tb; + int objpos; - if(!c->titlebar.sw) - return; + luaA_checktable(L, 1); - switch(c->titlebar.position) + tb = lua_newuserdata(L, sizeof(titlebar_t *)); + *tb = p_new(titlebar_t, 1); + objpos = lua_gettop(L); + + (*tb)->text_normal = a_strdup(luaA_getopt_string(L, 1, "normal", "<title/>")); + (*tb)->text_focus = a_strdup(luaA_getopt_string(L, 1, "focus", "<title/>")); + (*tb)->text_urgent = a_strdup(luaA_getopt_string(L, 1, "urgent", "<title/>")); + + (*tb)->align = draw_align_get_from_str(luaA_getopt_string(L, 1, "align", "left")); + + (*tb)->width = luaA_getopt_number(L, 1, "width", 0); + (*tb)->height = luaA_getopt_number(L, 1, "height", 0); + if((*tb)->height <= 0) + /* 1.5 as default factor, it fits nice but no one knows why */ + (*tb)->height = 1.5 * globalconf.font->height; + + (*tb)->position = position_get_from_str(luaA_getopt_string(L, 1, "position", "top")); + + titlebar_ref(tb); + + lua_pushvalue(L, objpos); + return luaA_settype(L, "titlebar"); +} + +static int +luaA_titlebar_mouse(lua_State *L) +{ + size_t i, len; + int b; + Button *button; + + /* arg 1 is modkey table */ + luaA_checktable(L, 1); + /* arg 2 is mouse button */ + b = luaL_checknumber(L, 2); + /* arg 3 is cmd to run */ + luaA_checkfunction(L, 3); + + button = p_new(Button, 1); + button->button = xutil_button_fromint(b); + button->fct = luaL_ref(L, LUA_REGISTRYINDEX); + + len = lua_objlen(L, 1); + for(i = 1; i <= len; i++) { - default: - return; - case Off: - return; - case Top: - if(!c->titlebar.width) - width = geometry.width + 2 * c->border; - else - width = MIN(c->titlebar.width, geometry.width); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - x_offset = 2 * c->border + geometry.width - width; - break; - case AlignCenter: - x_offset = (geometry.width - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - geometry.x + x_offset, - geometry.y, - width, - c->titlebar.sw->geometry.height); - break; - case Bottom: - if(!c->titlebar.width) - width = geometry.width + 2 * c->border; - else - width = MIN(c->titlebar.width, geometry.width); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - x_offset = 2 * c->border + geometry.width - width; - break; - case AlignCenter: - x_offset = (geometry.width - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - geometry.x + x_offset, - geometry.y + geometry.height - - c->titlebar.sw->geometry.height + 2 * c->border, - width, - c->titlebar.sw->geometry.height); - break; - case Left: - if(!c->titlebar.width) - width = geometry.height + 2 * c->border; - else - width = MIN(c->titlebar.width, geometry.height); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - y_offset = 2 * c->border + geometry.height - width; - break; - case AlignCenter: - y_offset = (geometry.height - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - geometry.x, - geometry.y + y_offset, - c->titlebar.sw->geometry.width, - width); - break; - case Right: - if(!c->titlebar.width) - width = geometry.height + 2 * c->border; - else - width = MIN(c->titlebar.width, geometry.height); - switch(c->titlebar.align) - { - default: - break; - case AlignRight: - y_offset = 2 * c->border + geometry.height - width; - break; - case AlignCenter: - y_offset = (geometry.height - width) / 2; - break; - } - simplewindow_move_resize(c->titlebar.sw, - geometry.x + geometry.width - - c->titlebar.sw->geometry.width + 2 * c->border, - geometry.y + y_offset, - c->titlebar.sw->geometry.width, - width); - break; + lua_rawgeti(L, 1, i); + button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); } - titlebar_draw(c); + button_list_push(&globalconf.buttons.titlebar, button); + + return 0; } -void -titlebar_position_set(titlebar_t *t, position_t p) +static int +luaA_titlebar_gc(lua_State *L) { - if(!t->sw) - return; - - if((t->position = p)) - xcb_map_window(globalconf.connection, t->sw->window); - else - xcb_unmap_window(globalconf.connection, t->sw->window); + titlebar_t **titlebar = luaL_checkudata(L, 1, "titlebar"); + titlebar_unref(titlebar); + return 0; } -/** Toggle the visibility of the focused window's titlebar. - * \param screen screen number (unused) - * \param arg unused argument - * \ingroup ui_callback - */ -void -uicb_client_toggletitlebar(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused))) +static int +luaA_titlebar_tostring(lua_State *L) { - client_t *c = globalconf.focus->client; - - if(!c || !c->titlebar.sw) - return; - - if(!c->titlebar.position) - titlebar_position_set(&c->titlebar, c->titlebar.dposition); - else - titlebar_position_set(&c->titlebar, Off); - - if(c->isfloating || layout_get_current(screen)->arrange == layout_floating) - titlebar_update_geometry_floating(c); - else - globalconf.screens[c->screen].need_arrange = true; + titlebar_t **p = luaL_checkudata(L, 1, "titlebar"); + lua_pushfstring(L, "[titlebar udata(%p)]", *p); + return 1; } +static int +luaA_titlebar_eq(lua_State *L) +{ + titlebar_t **t1 = luaL_checkudata(L, 1, "titlebar"); + titlebar_t **t2 = luaL_checkudata(L, 2, "titlebar"); + lua_pushboolean(L, (*t1 == *t2)); + return 1; +} + +const struct luaL_reg awesome_titlebar_methods[] = +{ + { "new", luaA_titlebar_new }, + { "mouse", luaA_titlebar_mouse }, + { NULL, NULL } +}; +const struct luaL_reg awesome_titlebar_meta[] = +{ + { "__eq", luaA_titlebar_eq }, + { "__gc", luaA_titlebar_gc }, + { "__tostring", luaA_titlebar_tostring }, + { NULL, NULL } +}; + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/titlebar.h b/titlebar.h index 91d6e788..eb5645d4 100644 --- a/titlebar.h +++ b/titlebar.h @@ -24,15 +24,72 @@ #include "structs.h" -void titlebar_init(client_t *); void titlebar_draw(client_t *); void titlebar_update_geometry_floating(client_t *); void titlebar_update_geometry(client_t *, area_t); -area_t titlebar_geometry_add(titlebar_t *, area_t); -area_t titlebar_geometry_remove(titlebar_t *, area_t); -void titlebar_position_set(titlebar_t *, position_t); +void titlebar_init(client_t *); -uicb_t uicb_client_toggletitlebar; +/** Add the titlebar geometry to a geometry. + * \param t the titlebar + * \param geometry the geometry + * \return a new geometry bigger if the titlebar is visible + */ +static inline area_t +titlebar_geometry_add(titlebar_t *t, area_t geometry) +{ + switch(t->position) + { + case Top: + geometry.y -= t->height; + geometry.height += t->height; + break; + case Bottom: + geometry.height += t->height; + break; + case Left: + geometry.x -= t->width; + geometry.width += t->width; + break; + case Right: + geometry.width += t->width; + break; + default: + break; + } + + return geometry; +} + +/** Remove the titlebar geometry to a geometry. + * \param t the titlebar + * \param geometry the geometry + * \return a new geometry smaller if the titlebar is visible + */ +static inline area_t +titlebar_geometry_remove(titlebar_t *t, area_t geometry) +{ + switch(t->position) + { + case Top: + geometry.y += t->height; + geometry.height -= t->height; + break; + case Bottom: + geometry.height -= t->height; + break; + case Left: + geometry.x += t->width; + geometry.width -= t->width; + break; + case Right: + geometry.width -= t->width; + break; + default: + break; + } + + return geometry; +} #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/uicb.c b/uicb.c deleted file mode 100644 index cc8bd688..00000000 --- a/uicb.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * uicb.c - user interface callbacks management - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/** - * @defgroup ui_callback User Interface Callbacks - */ - -#include <sys/wait.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <xcb/xcb.h> -#include <xcb/xcb_aux.h> - -#include "awesome.h" -#include "tag.h" -#include "mouse.h" -#include "statusbar.h" -#include "widget.h" -#include "focus.h" -#include "client.h" -#include "screen.h" -#include "titlebar.h" -#include "layouts/tile.h" - -extern AwesomeConf globalconf; - -const name_func_link_t UicbList[] = -{ - /* awesome.h */ - { "quit", uicb_quit }, - /* client.h */ - { "client_kill", uicb_client_kill }, - { "client_moveresize", uicb_client_moveresize }, - { "client_settrans", uicb_client_settrans }, - { "client_swap", uicb_client_swap }, - { "client_togglemax", uicb_client_togglemax }, - { "client_focus", uicb_client_focus }, - { "client_setfloating", uicb_client_setfloating }, - { "client_togglescratch", uicb_client_togglescratch }, - { "client_setscratch", uicb_client_setscratch }, - { "client_redraw", uicb_client_redraw }, - /* focus.h */ - { "focus_history", uicb_focus_history }, - { "focus_client_byname", uicb_focus_client_byname }, - /* layout.h */ - { "tag_setlayout", uicb_tag_setlayout }, - /* mouse.h */ - { "client_movemouse", uicb_client_movemouse }, - { "client_resizemouse", uicb_client_resizemouse }, - /* screen.h */ - { "screen_focus", uicb_screen_focus }, - { "client_movetoscreen", uicb_client_movetoscreen }, - /* statusbar.h */ - { "statusbar_toggle", uicb_statusbar_toggle }, - /* tag.h */ - { "client_tag", uicb_client_tag }, - { "client_toggletag", uicb_client_toggletag }, - { "tag_toggleview", uicb_tag_toggleview }, - { "tag_view", uicb_tag_view }, - { "tag_prev_selected", uicb_tag_prev_selected }, - { "tag_viewnext", uicb_tag_viewnext }, - { "tag_viewprev", uicb_tag_viewprev }, - { "tag_create", uicb_tag_create }, - /* titlebar.h */ - { "client_toggletitlebar", uicb_client_toggletitlebar }, - /* uicb.h */ - { "restart", uicb_restart }, - { "exec", uicb_exec }, - { "spawn", uicb_spawn }, - /* widget.h */ - { "widget_tell", uicb_widget_tell }, - /* layouts/tile.h */ - { "tag_setnmaster", uicb_tag_setnmaster}, - { "tag_setncol", uicb_tag_setncol }, - { "tag_setmwfact", uicb_tag_setmwfact }, - { NULL, NULL } -}; - -/** Restart awesome with the current command line. - * \param screen The virtual screen number. - * \param arg An unused argument. - * \ingroup ui_callback - */ -void -uicb_restart(int screen, char *arg __attribute__ ((unused))) -{ - uicb_exec(screen, globalconf.argv); -} - -/** Execute another process, replacing the current instance of awesome. - * \param screen The virtual screen number. - * \param cmd The command to start. - * \ingroup ui_callback - */ -void -uicb_exec(int screen __attribute__ ((unused)), char *cmd) -{ - client_t *c; - char *args, *path; - - /* remap all clients since some WM won't handle them otherwise */ - for(c = globalconf.clients; c; c = c->next) - client_unban(c); - - xcb_aux_sync(globalconf.connection); - xcb_disconnect(globalconf.connection); - - /* Ignore the leading spaces if any */ - while(cmd[0] && cmd[0] == ' ') - cmd++; - - /* Get the beginning of the arguments */ - args = strchr(cmd, ' '); - - if(args) - path = a_strndup(cmd, args - cmd); - else - path = a_strndup(cmd, a_strlen(cmd)); - - execlp(path, cmd, NULL); - - p_delete(&path); -} - -/** Spawn another process. - * \param screen The virtual screen number. - * \param arg The command to run. - * \ingroup ui_callback - */ -void -uicb_spawn(int screen, char *arg) -{ - static char *shell = NULL; - char *display = NULL; - char *tmp, newdisplay[128]; - - if(!arg) - return; - - if(!shell && !(shell = getenv("SHELL"))) - shell = a_strdup("/bin/sh"); - - if(!globalconf.screens_info->xinerama_is_active && (tmp = getenv("DISPLAY"))) - { - display = a_strdup(tmp); - if((tmp = strrchr(display, '.'))) - *tmp = '\0'; - snprintf(newdisplay, sizeof(newdisplay), "%s.%d", display, screen); - setenv("DISPLAY", newdisplay, 1); - } - - /* The double-fork construct avoids zombie processes and keeps the code - * clean from stupid signal handlers. */ - if(fork() == 0) - { - if(fork() == 0) - { - if(globalconf.connection) - close(xcb_get_file_descriptor(globalconf.connection)); - setsid(); - execl(shell, shell, "-c", arg, NULL); - warn("execl '%s -c %s' failed: %s\n", shell, arg, strerror(errno)); - } - exit(EXIT_SUCCESS); - } - wait(0); -} - -/** Run the uicb. - * \param cmd The uicb command to parse. - * \return true on succes, false on failure. - */ -static bool -__uicb_run(char *cmd) -{ - char *p, *argcpy; - const char *arg; - int screen; - ssize_t len; - uicb_t *uicb; - - len = a_strlen(cmd); - p = strtok(cmd, " "); - if (!p) - { - warn("ignoring malformed command\n"); - return false; - } - screen = atoi(cmd); - if(screen >= globalconf.screens_info->nscreen || screen < 0) - { - warn("invalid screen specified: %i\n", screen); - return false; - } - - p = strtok(NULL, " "); - if (!p) - { - warn("ignoring malformed command.\n"); - return false; - } - - uicb = name_func_lookup(p, UicbList); - if (!uicb) - { - warn("unknown uicb function: %s.\n", p); - return false; - } - - if (p + a_strlen(p) < cmd + len) - { - arg = p + a_strlen(p) + 1; - len = a_strlen(arg); - /* Allow our callees to modify this string. */ - argcpy = p_new(char, len + 1); - a_strncpy(argcpy, len + 1, arg, len); - uicb(screen, argcpy); - p_delete(&argcpy); - } - else - uicb(screen, NULL); - - return true; -} - -/** Parse a command. - * \param cmd The buffer to parse. - * \return true on succes, false on failure. - */ -bool -__uicb_parsecmd(char *cmd) -{ - char *p, *curcmd = cmd; - bool ret = false; - - if(a_strlen(cmd)) - while((p = strchr(curcmd, '\n'))) - { - *p = '\0'; - ret = __uicb_run(curcmd); - curcmd = p + 1; - } - - return ret; -} - -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/uicb.h b/uicb.h deleted file mode 100644 index 8f535d46..00000000 --- a/uicb.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * uicb.h - user interface callbacks management header - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef AWESOME_UICB_H -#define AWESOME_UICB_H - -#include <stdbool.h> - -typedef void (uicb_t)(int, char *); - -bool __uicb_parsecmd(char *); - -uicb_t uicb_restart; -uicb_t uicb_exec; -uicb_t uicb_spawn; - -#endif -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widget.c b/widget.c index f95542fe..c99b900c 100644 --- a/widget.c +++ b/widget.c @@ -23,50 +23,12 @@ #include "widget.h" #include "statusbar.h" #include "event.h" +#include "lua.h" extern AwesomeConf globalconf; #include "widgetgen.h" -/** Compute widget alignment. - * This will process all widget starting at `widget' and will check their - * alignment and guess it if set to AlignAuto. - * \param widget A linked list of all widgets. - */ -void -widget_calculate_alignments(widget_t *widget) -{ - for(; widget && widget->alignment != AlignFlex; widget = widget->next) - switch(widget->alignment) - { - case AlignCenter: - warn("widgets cannot be center aligned\n"); - case AlignAuto: - widget->alignment = AlignLeft; - break; - default: - break; - } - - if(widget) - for(widget = widget->next; widget; widget = widget->next) - switch(widget->alignment) - { - case AlignFlex: - warn("multiple flex widgets (%s) in panel -" - " ignoring flex for all but the first.\n", widget->name); - widget->alignment = AlignRight; - break; - case AlignCenter: - warn("widget %s cannot be center aligned\n", widget->name); - case AlignAuto: - widget->alignment = AlignRight; - break; - default: - break; - } -} - /** Compute offset for drawing the first pixel of a widget. * \param barwidth The statusbar width. * \param widgetwidth The widget width. @@ -93,29 +55,31 @@ widget_calculate_offset(int barwidth, int widgetwidth, int offset, int alignment widget_t * widget_getbyname(statusbar_t *sb, char *name) { - widget_t *widget; + widget_node_t *widget; for(widget = sb->widgets; widget; widget = widget->next) - if(!a_strcmp(name, widget->name)) - return widget; + if(!a_strcmp(name, widget->widget->name)) + return widget->widget; return NULL; } /** Common function for button press event on widget. * It will look into configuration to find the callback function to call. - * \param widget The widget. + * \param w The widget node. + * \param statusbar The statusbar. * \param ev The button press event the widget received. */ static void -widget_common_button_press(widget_t *widget, xcb_button_press_event_t *ev) +widget_common_button_press(widget_node_t *w, + statusbar_t *statusbar __attribute__ ((unused)), + xcb_button_press_event_t *ev) { Button *b; - for(b = widget->buttons; b; b = b->next) - if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod - && b->func) - b->func(widget->statusbar->screen, b->arg); + for(b = w->widget->buttons; b; b = b->next) + if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct) + luaA_dofunction(globalconf.L, b->fct, 0); } /** Common tell function for widget, which only warn user that widget @@ -125,8 +89,9 @@ widget_common_button_press(widget_t *widget, xcb_button_press_event_t *ev) * \return The status of the command, which is always an error in this case. */ static widget_tell_status_t -widget_common_tell(widget_t *widget, char *property __attribute__ ((unused)), - char *new_value __attribute__ ((unused))) +widget_common_tell(widget_t *widget, + const char *property __attribute__ ((unused)), + const char *new_value __attribute__ ((unused))) { warn("%s widget does not accept commands.\n", widget->name); return WIDGET_ERROR_CUSTOM; @@ -134,20 +99,13 @@ widget_common_tell(widget_t *widget, char *property __attribute__ ((unused)), /** Common function for creating a widget. * \param widget The allocated widget. - * \param statusbar The statusbar the widget is on. - * \param config The cfg_t structure we will parse to set common info. */ void -widget_common_new(widget_t *widget, statusbar_t *statusbar, cfg_t *config) +widget_common_new(widget_t *widget) { - widget->statusbar = statusbar; - widget->name = a_strdup(cfg_title(config)); + widget->align = AlignLeft; widget->tell = widget_common_tell; widget->button_press = widget_common_button_press; - widget->area.x = cfg_getint(config, "x"); - widget->area.y = cfg_getint(config, "y"); - widget->user_supplied_x = (widget->area.x != (int) 0xffffffff); - widget->user_supplied_y = (widget->area.y != (int) 0xffffffff); } /** Invalidate widgets which should be refresh upon @@ -160,94 +118,238 @@ void widget_invalidate_cache(int screen, int flags) { statusbar_t *statusbar; - widget_t *widget; + widget_node_t *widget; for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next) for(widget = statusbar->widgets; widget; widget = widget->next) - if(widget->cache_flags & flags) + if(widget->widget->cache_flags & flags) + { statusbar->need_update = true; + break; + } } -/** Send commands to widgets. - * \param screen Virtual screen number. - * \param arg Widget command. Syntax depends on specific widget. - * \ingroup ui_callback - */ void -uicb_widget_tell(int screen, char *arg) +widget_invalidate_statusbar_bywidget(widget_t *widget) { + int screen; statusbar_t *statusbar; - widget_t *widget; - char *p, *property = NULL, *new_value; - ssize_t len; + widget_node_t *witer; + + for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) + for(statusbar = globalconf.screens[screen].statusbar; + statusbar; + statusbar = statusbar->next) + for(witer = statusbar->widgets; witer; witer = witer->next) + if(witer->widget == widget) + { + statusbar->need_update = true; + break; + } +} + +static int +luaA_widget_new(lua_State *L) +{ + const char *type; + widget_t **widget, *w; + WidgetConstructor *wc; + int objpos; + alignment_t align; + + luaA_checktable(L, 1); + align = draw_align_get_from_str(luaA_getopt_string(L, 1, "align", "left")); + + type = luaA_getopt_string(L, 1, "type", NULL); + + /* \todo use type to call the WidgetConstructor and set ->tell*/ + if((wc = name_func_lookup(type, WidgetList))) + w = wc(align); + else + return 0; + + widget = lua_newuserdata(L, sizeof(widget_t *)); + objpos = lua_gettop(L); + *widget = w; + + /* \todo check that the name is unique */ + (*widget)->name = luaA_name_init(L); + + widget_ref(widget); + + /* repush obj on top */ + lua_pushvalue(L, objpos); + return luaA_settype(L, "widget"); +} + +static int +luaA_widget_mouse(lua_State *L) +{ + size_t i, len; + /* arg 1 is object */ + widget_t **widget = luaL_checkudata(L, 1, "widget"); + int b; + Button *button; + + /* arg 2 is modkey table */ + luaA_checktable(L, 2); + /* arg 3 is mouse button */ + b = luaL_checknumber(L, 3); + /* arg 4 is cmd to run */ + luaA_checkfunction(L, 4); + + button = p_new(Button, 1); + button->button = xutil_button_fromint(b); + button->fct = luaL_ref(L, LUA_REGISTRYINDEX); + + len = lua_objlen(L, 2); + for(i = 1; i <= len; i++) + { + lua_rawgeti(L, 2, i); + button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); + } + + button_list_push(&(*widget)->buttons, button); + + return 0; +} + +static int +luaA_widget_set(lua_State *L) +{ + widget_t **widget = luaL_checkudata(L, 1, "widget"); + const char *property, *value; widget_tell_status_t status; - if(!(len = a_strlen(arg))) - return warn("must specify a statusbar and a widget.\n"); + property = luaL_checkstring(L, 2); + value = luaL_checkstring(L, 3); - if(!(p = strtok(arg, " "))) - return warn("ignoring malformed widget command (missing statusbar name).\n"); - - if(!(statusbar = statusbar_getbyname(screen, p))) - return warn("no such statusbar: %s\n", p); - - if(!(p = strtok(NULL, " "))) - return warn("ignoring malformed widget command (missing widget name).\n"); - - if(!(widget = widget_getbyname(statusbar, p))) - return warn("no such widget: %s in statusbar %s.\n", p, statusbar->name); - - if(!(p = strtok(NULL, " "))) - return warn("ignoring malformed widget command (missing property name).\n"); - - property = p; - p += a_strlen(property) + 1; /* could be out of 'arg' now */ - - /* arg + len points to the finishing \0. - * p to the char right of the first space (strtok delimiter) - * - * \0 is on the right(>) of p pointer => some text (new_value) */ - if(arg + len > p) - { - len = a_strlen(p); - new_value = p_new(char, len + 1); - a_strncpy(new_value, len + 1, p, len); - status = widget->tell(widget, property, new_value); - p_delete(&new_value); - } - else - status = widget->tell(widget, property, NULL); - - switch(status) + switch((status = (*widget)->tell(*widget, property, value))) { case WIDGET_ERROR: warn("error changing property %s of widget %s\n", - property, widget->name); + property, (*widget)->name); break; case WIDGET_ERROR_NOVALUE: - warn("error changing property %s of widget %s, no value given\n", - property, widget->name); + warn("error changing property %s of widget %s, no value given\n", + property, (*widget)->name); break; case WIDGET_ERROR_FORMAT_FONT: warn("error changing property %s of widget %s, must be a valid font\n", - property, widget->name); + property, (*widget)->name); break; case WIDGET_ERROR_FORMAT_COLOR: warn("error changing property %s of widget %s, must be a valid color\n", - property, widget->name); + property, (*widget)->name); break; case WIDGET_ERROR_FORMAT_SECTION: warn("error changing property %s of widget %s, section/title not found\n", - property, widget->name); + property, (*widget)->name); break; case WIDGET_NOERROR: - widget->statusbar->need_update = true; - break; + widget_invalidate_statusbar_bywidget(*widget); + break; case WIDGET_ERROR_CUSTOM: break; } + + return 0; } +static int +luaA_widget_gc(lua_State *L) +{ + widget_t **widget = luaL_checkudata(L, 1, "widget"); + widget_unref(widget); + return 0; +} + +static int +luaA_widget_tostring(lua_State *L) +{ + widget_t **p = luaL_checkudata(L, 1, "widget"); + lua_pushfstring(L, "[widget udata(%p) name(%s)]", *p, (*p)->name); + return 1; +} + +static int +luaA_widget_eq(lua_State *L) +{ + widget_t **t1 = luaL_checkudata(L, 1, "widget"); + widget_t **t2 = luaL_checkudata(L, 2, "widget"); + lua_pushboolean(L, (*t1 == *t2)); + return 1; +} + +static int +luaA_widget_get(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + statusbar_t *sb; + widget_t **wobj; + widget_node_t *widget; + int ret, i = 1, screen; + regex_t r; + regmatch_t match; + char error[512]; + bool add = true; + widget_node_t *wlist = NULL, *witer; + + if((ret = regcomp(&r, name, REG_EXTENDED))) + { + regerror(ret, &r, error, sizeof(error)); + luaL_error(L, "regex compilation error: %s\n", error); + } + + lua_newtable(L); + + for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) + for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next) + for(widget = sb->widgets; widget; widget = widget->next) + if(!regexec(&r, widget->widget->name, 1, &match, 0)) + { + for(witer = wlist; witer; witer = witer->next) + if(witer->widget == widget->widget) + { + add = false; + break; + } + if(add) + { + witer = p_new(widget_node_t, 1); + wobj = lua_newuserdata(L, sizeof(tag_t *)); + witer->widget = *wobj = widget->widget; + widget_ref(&widget->widget); + widget_node_list_push(&wlist, witer); + /* ref again for the list */ + widget_ref(&widget->widget); + luaA_settype(L, "widget"); + lua_rawseti(L, -2, i++); + } + add = true; + } + + widget_node_list_wipe(&wlist); + + return 1; +} + +const struct luaL_reg awesome_widget_methods[] = +{ + { "new", luaA_widget_new }, + { "get", luaA_widget_get }, + { NULL, NULL } +}; +const struct luaL_reg awesome_widget_meta[] = +{ + { "mouse", luaA_widget_mouse }, + { "set", luaA_widget_set }, + { "__gc", luaA_widget_gc }, + { "__eq", luaA_widget_eq }, + { "__tostring", luaA_widget_tostring }, + { NULL, NULL } +}; + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widget.h b/widget.h index 75157145..f3164160 100644 --- a/widget.h +++ b/widget.h @@ -30,27 +30,21 @@ #define WIDGET_CACHE_TAGS 1<<2 #define WIDGET_CACHE_ALL (WIDGET_CACHE_CLIENTS | WIDGET_CACHE_LAYOUTS | WIDGET_CACHE_TAGS) -typedef widget_t *(WidgetConstructor)(statusbar_t *, cfg_t *); +typedef widget_t *(WidgetConstructor)(alignment_t); void widget_invalidate_cache(int, int); int widget_calculate_offset(int, int, int, int); -void widget_calculate_alignments(widget_t *); -void widget_common_new(widget_t*, statusbar_t *, cfg_t *); +void widget_common_new(widget_t *); widget_t * widget_getbyname(statusbar_t *, char *); +void widget_invalidate_statusbar_bywidget(widget_t *); -WidgetConstructor layoutinfo_new; WidgetConstructor taglist_new; WidgetConstructor textbox_new; WidgetConstructor iconbox_new; -WidgetConstructor focusicon_new; WidgetConstructor progressbar_new; WidgetConstructor graph_new; WidgetConstructor tasklist_new; -uicb_t uicb_widget_tell; - -DO_SLIST(widget_t, widget, p_delete) - #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/common.c b/widgets/common.c index b20b13c9..e4679aa9 100644 --- a/widgets/common.c +++ b/widgets/common.c @@ -25,7 +25,7 @@ extern AwesomeConf globalconf; widget_tell_status_t -widget_set_color_for_data(widget_t *widget, xcolor_t *color, char *new_value, int data_items, char ** data_title) +widget_set_color_for_data(xcolor_t *color, char *new_value, int data_items, char ** data_title) { char *title, *setting; int i; @@ -36,7 +36,7 @@ widget_set_color_for_data(widget_t *widget, xcolor_t *color, char *new_value, in if(!a_strcmp(title, data_title[i])) { if(draw_color_new(globalconf.connection, - widget->statusbar->phys_screen, + globalconf.default_screen, setting, &color[i])) return WIDGET_NOERROR; else @@ -45,7 +45,7 @@ widget_set_color_for_data(widget_t *widget, xcolor_t *color, char *new_value, in return WIDGET_ERROR_FORMAT_SECTION; } widget_tell_status_t -widget_set_color_pointer_for_data(widget_t *widget, xcolor_t **color, char *new_value, int data_items, char ** data_title) +widget_set_color_pointer_for_data(xcolor_t **color, char *new_value, int data_items, char ** data_title) { char *title, *setting; int i; @@ -63,8 +63,8 @@ widget_set_color_pointer_for_data(widget_t *widget, xcolor_t **color, char *new_ color[i] = p_new(xcolor_t, 1); } if(!(draw_color_new(globalconf.connection, - widget->statusbar->phys_screen, - setting, color[i]))) + globalconf.default_screen, + setting, color[i]))) { if(flag) /* restore */ { diff --git a/widgets/common.h b/widgets/common.h index 980ef2ba..da4d7bee 100644 --- a/widgets/common.h +++ b/widgets/common.h @@ -24,8 +24,8 @@ #define AWESOME_WIDGETS_COMMON_H #include "widget.h" -widget_tell_status_t widget_set_color_for_data(widget_t *, xcolor_t *, char *, int, char **); -widget_tell_status_t widget_set_color_pointer_for_data(widget_t *, xcolor_t **, char *, int, char **); +widget_tell_status_t widget_set_color_for_data(xcolor_t *, char *, int, char **); +widget_tell_status_t widget_set_color_pointer_for_data(xcolor_t **, char *, int, char **); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/focusicon.c b/widgets/focusicon.c deleted file mode 100644 index cdebae14..00000000 --- a/widgets/focusicon.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * focusicon.c - focused window icon widget - * - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - - -#include "focus.h" -#include "tag.h" -#include "widget.h" -#include "rules.h" -#include "ewmh.h" -#include "common/configopts.h" - -extern AwesomeConf globalconf; - -static int -focusicon_draw(widget_t *widget, draw_context_t *ctx, int offset, - int used __attribute__ ((unused))) -{ - area_t area; - rule_t *r; - client_t *sel = focus_get_current_client(widget->statusbar->screen); - NetWMIcon *icon; - - if(!sel) - return (widget->area.width = 0); - - widget->area.height = widget->statusbar->height; - - if((r = rule_matching_client(sel)) && r->icon) - { - area = draw_get_image_size(r->icon); - widget->area.width = ((double) widget->statusbar->height / (double) area.height) - * area.width; - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->area.width, - offset, - widget->alignment); - - if(!widget->user_supplied_y) - widget->area.y = 0; - draw_image(ctx, widget->area.x, widget->area.y, - widget->statusbar->height, r->icon); - - return widget->area.width; - } - - if(!(icon = ewmh_get_window_icon(sel->win))) - return (widget->area.width = 0); - - widget->area.width = ((double) widget->statusbar->height / (double) icon->height) * icon->width; - - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->area.width, - offset, - widget->alignment); - - if(!widget->user_supplied_y) - widget->area.y = 0; - - draw_image_from_argb_data(ctx, - widget->area.x, widget->area.y, - icon->width, icon->height, - widget->statusbar->height, icon->image); - - p_delete(&icon->image); - p_delete(&icon); - - return widget->area.width; -} - -widget_t * -focusicon_new(statusbar_t *statusbar, cfg_t *config) -{ - widget_t *w; - - w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); - w->draw = focusicon_draw; - w->alignment = cfg_getalignment(config, "align"); - - /* Set cache property */ - w->cache_flags = WIDGET_CACHE_CLIENTS; - - return w; -} -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/graph.c b/widgets/graph.c index cc9aeb8d..2e9d8474 100644 --- a/widgets/graph.c +++ b/widgets/graph.c @@ -80,33 +80,31 @@ typedef struct } Data; static int -graph_draw(widget_t *widget, draw_context_t *ctx, int offset, - int used __attribute__ ((unused))) +graph_draw(widget_node_t *w, statusbar_t *statusbar, int offset, + int used __attribute__ ((unused))) { int margin_top; int z, y, x, tmp, cur_index, test_index; - Data *d = widget->data; + Data *d = w->widget->data; area_t rectangle, pattern_area; + draw_context_t *ctx = statusbar->ctx; if(!d->data_items) return 0; - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - d->width, - offset, - widget->alignment); - if(!widget->user_supplied_y) - widget->area.y = 0; + w->area.x = widget_calculate_offset(statusbar->width, + d->width, offset, + w->widget->align); + w->area.y = 0; /* box = the graph inside the rectangle */ if(!(d->box_height)) - d->box_height = (int) (widget->statusbar->height * d->height + 0.5) - 2; + d->box_height = (int) (statusbar->height * d->height + 0.5) - 2; - margin_top = (int)((widget->statusbar->height - (d->box_height + 2)) / 2 + 0.5) + widget->area.y; + margin_top = (int)((statusbar->height - (d->box_height + 2)) / 2 + 0.5) + w->area.y; /* draw background */ - rectangle.x = widget->area.x + 1; + rectangle.x = w->area.x + 1; rectangle.y = margin_top + 1; rectangle.width = d->size; rectangle.height = d->box_height; @@ -262,19 +260,19 @@ graph_draw(widget_t *widget, draw_context_t *ctx, int offset, } /* draw border (after line-drawing, what paints 0-values to the border) */ - rectangle.x = widget->area.x; + rectangle.x = w->area.x; rectangle.y = margin_top; rectangle.width = d->size + 2; rectangle.height = d->box_height + 2; draw_rectangle(ctx, rectangle, 1.0, false, d->bordercolor); - widget->area.width = d->width; - widget->area.height = widget->statusbar->height; - return widget->area.width; + w->area.width = d->width; + w->area.height = statusbar->height; + return w->area.width; } static widget_tell_status_t -graph_tell(widget_t *widget, char *property, char *new_value) +graph_tell(widget_t *widget, const char *property, const char *new_value) { Data *d = widget->data; int i, u; @@ -347,14 +345,14 @@ graph_tell(widget_t *widget, char *property, char *new_value) else if(!a_strcmp(property, "bg")) { if(!draw_color_new(globalconf.connection, - widget->statusbar->phys_screen, + globalconf.default_screen, new_value, &d->bg)) return WIDGET_ERROR_FORMAT_COLOR; } else if(!a_strcmp(property, "bordercolor")) { if(!draw_color_new(globalconf.connection, - widget->statusbar->phys_screen, + globalconf.default_screen, new_value, &d->bordercolor)) return WIDGET_ERROR_FORMAT_COLOR; } @@ -376,7 +374,7 @@ graph_tell(widget_t *widget, char *property, char *new_value) } widget_t * -graph_new(statusbar_t *statusbar, cfg_t *config) +graph_new(alignment_t align) { widget_t *w; Data *d; @@ -389,17 +387,18 @@ graph_new(statusbar_t *statusbar, cfg_t *config) xcolor_t *ptmp_color_end; w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); + widget_common_new(w); w->draw = graph_draw; w->tell = graph_tell; - w->alignment = cfg_getalignment(config, "align"); + w->align = align; d = w->data = p_new(Data, 1); - d->width = cfg_getint(config, "width"); - d->height = cfg_getfloat(config, "height"); + d->width = 100; + d->height = 0.67; d->size = d->width - 2; + /* if(!(d->data_items = cfg_size(config, "data"))) { warn("graph widget needs at least one data section\n"); @@ -410,8 +409,10 @@ graph_new(statusbar_t *statusbar, cfg_t *config) if(d->grow != Left && d->grow != Right) { warn("graph widget: 'grow' argument must be 'left' or 'right'\n"); + */ + /* d->data_items = 0; /* disable widget drawing */ - return w; + /* return w; } d->draw_from = p_new(int, d->size); @@ -476,11 +477,12 @@ graph_new(statusbar_t *statusbar, cfg_t *config) d->values[i] = p_new(float, d->size); /* not null -> scale = true */ /* prevent: division by zero */ + /* d->current_max[i] = d->max[i] = cfg_getfloat(cfg, "max"); d->lines[i] = p_new(int, d->size); /* filter each style-typ into it's own array (for easy looping later)*/ - +/* if ((type = cfg_getstr(cfg, "draw_style"))) { if(!a_strncmp(type, "bottom", sizeof("bottom"))) @@ -525,7 +527,7 @@ graph_new(statusbar_t *statusbar, cfg_t *config) draw_color_new(globalconf.connection, statusbar->phys_screen, color, &d->bordercolor); else d->bordercolor = tmp_color; - +*/ return w; } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/iconbox.c b/widgets/iconbox.c index d318660e..9b5b7c7e 100644 --- a/widgets/iconbox.c +++ b/widgets/iconbox.c @@ -32,44 +32,42 @@ typedef struct } Data; static int -iconbox_draw(widget_t *widget, draw_context_t *ctx, int offset, +iconbox_draw(widget_node_t *w, statusbar_t *statusbar, int offset, int used __attribute__ ((unused))) { - Data *d = widget->data; + Data *d = w->widget->data; area_t area = draw_get_image_size(d->image); /* image not valid */ if(area.width < 0 || area.height < 0) - return (widget->area.width = 0); + return (w->area.width = 0); if(d->resize) - widget->area.width = ((double) widget->statusbar->height / area.height) * area.width; + w->area.width = ((double) statusbar->height / area.height) * area.width; else - widget->area.width = area.width; + w->area.width = area.width; - widget->area.height = widget->statusbar->height; + w->area.height = statusbar->height; - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->area.width, - offset, - widget->alignment); + w->area.x = widget_calculate_offset(statusbar->width, + w->area.width, + offset, + w->widget->align); - if(!widget->user_supplied_y) - widget->area.y = 0; + w->area.y = 0; - draw_image(ctx, widget->area.x, widget->area.y, - d->resize ? widget->statusbar->height : 0, d->image); + draw_image(statusbar->ctx, w->area.x, w->area.y, + d->resize ? statusbar->height : 0, d->image); - return widget->area.width; + return w->area.width; } static widget_tell_status_t -iconbox_tell(widget_t *widget, char *property, char *new_value) +iconbox_tell(widget_t *widget, const char *property, const char *new_value) { Data *d = widget->data; - if(new_value == NULL) + if(!new_value) return WIDGET_ERROR_NOVALUE; if(!a_strcmp(property, "image")) @@ -86,19 +84,18 @@ iconbox_tell(widget_t *widget, char *property, char *new_value) } widget_t * -iconbox_new(statusbar_t *statusbar, cfg_t *config) +iconbox_new(alignment_t align) { widget_t *w; Data *d; w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); - w->alignment = cfg_getalignment(config, "align"); + widget_common_new(w); + w->align = align; w->draw = iconbox_draw; w->tell = iconbox_tell; w->data = d = p_new(Data, 1); - d->image = a_strdup(cfg_getstr(config, "image")); - d->resize = cfg_getbool(config, "resize"); + d->resize = true; return w; } diff --git a/widgets/layoutinfo.c b/widgets/layoutinfo.c deleted file mode 100644 index 12364670..00000000 --- a/widgets/layoutinfo.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * layoutinfo.c - layout info widget - * - * Copyright © 2007 Aldo Cortesi <aldo@nullcube.com> - * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> - * Aldo Cortesi <aldo@nullcube.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "widget.h" -#include "tag.h" -#include "common/configopts.h" - -extern AwesomeConf globalconf; - -static int -layoutinfo_draw(widget_t *widget, - draw_context_t *ctx, - int offset, - int used __attribute__ ((unused))) -{ - tag_t **curtags = tags_get_current(widget->statusbar->screen); - area_t area = draw_get_image_size(curtags[0]->layout->image); - - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->statusbar->height, - offset, - widget->alignment); - - if(!widget->user_supplied_y) - widget->area.y = 0; - - widget->area.width = ((double) widget->statusbar->height / (double) area.height) * area.width;; - widget->area.height = widget->statusbar->height; - - draw_image(ctx, widget->area.x, widget->area.y, - widget->statusbar->height, - curtags[0]->layout->image); - - p_delete(&curtags); - - return widget->area.width; -} - -widget_t * -layoutinfo_new(statusbar_t *statusbar, cfg_t* config) -{ - widget_t *w; - w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); - w->draw = layoutinfo_draw; - w->alignment = cfg_getalignment(config, "align"); - - /* Set cache property */ - w->cache_flags = WIDGET_CACHE_LAYOUTS; - - return w; -} - -// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/progressbar.c b/widgets/progressbar.c index 1c537ef9..f483bd42 100644 --- a/widgets/progressbar.c +++ b/widgets/progressbar.c @@ -112,14 +112,15 @@ check_settings(Data *d, int status_height) static int -progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, +progressbar_draw(widget_node_t *w, statusbar_t *statusbar, int offset, int used __attribute__ ((unused))) { /* pb_.. values points to the widget inside a potential border */ int i, percent_ticks, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset; int unit = 0; /* tick + gap */ area_t rectangle, pattern_rect; - Data *d = widget->data; + draw_context_t *ctx = statusbar->ctx; + Data *d = w->widget->data; if(!d->data_items) return 0; @@ -128,9 +129,9 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, { pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->data_items - d->gap * (d->data_items - 1)) / d->data_items); - widget->area.width = d->data_items - * (pb_width + 2 * (d->border_width + d->border_padding) - + d->gap) - d->gap; + w->area.width = d->data_items + * (pb_width + 2 * (d->border_width + d->border_padding) + + d->gap) - d->gap; } else { @@ -140,16 +141,14 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, unit = (pb_width + d->ticks_gap) / d->ticks_count; pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */ } - widget->area.width = pb_width + 2 * (d->border_width + d->border_padding); + w->area.width = pb_width + 2 * (d->border_width + d->border_padding); } - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->area.width, - offset, - widget->alignment); - if(!widget->user_supplied_y) - widget->area.y = 0; + w->area.x = widget_calculate_offset(statusbar->width, + w->area.width, + offset, + w->widget->align); + w->area.y = 0; /* for a 'reversed' progressbar: * basic progressbar: @@ -162,14 +161,14 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, * 2. finally draw the gaps */ - pb_x = widget->area.x + d->border_width + d->border_padding; + pb_x = w->area.x + d->border_width + d->border_padding; pb_offset = 0; if(d->vertical) { /* TODO: maybe prevent to calculate that stuff below over and over again * (->use static-values) */ - pb_height = (int) (widget->statusbar->height * d->height + 0.5) + pb_height = (int) (statusbar->height * d->height + 0.5) - 2 * (d->border_width + d->border_padding); if(d->ticks_count && d->ticks_gap) { @@ -178,7 +177,7 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, pb_height = unit * d->ticks_count - d->ticks_gap; } - pb_y = widget->area.y + ((int) (widget->statusbar->height * (1 - d->height)) / 2) + pb_y = w->area.y + ((int) (statusbar->height * (1 - d->height)) / 2) + d->border_width + d->border_padding; for(i = 0; i < d->data_items; i++) @@ -275,10 +274,10 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, } else /* a horizontal progressbar */ { - pb_height = (int) ((widget->statusbar->height * d->height + pb_height = (int) ((statusbar->height * d->height - d->data_items * 2 * (d->border_width + d->border_padding) - (d->gap * (d->data_items - 1))) / d->data_items + 0.5); - pb_y = widget->area.y + ((int) (widget->statusbar->height * (1 - d->height)) / 2) + pb_y = w->area.y + ((int) (statusbar->height * (1 - d->height)) / 2) + d->border_width + d->border_padding; for(i = 0; i < d->data_items; i++) @@ -373,12 +372,12 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset, } } - widget->area.height = widget->statusbar->height; - return widget->area.width; + w->area.height = statusbar->height; + return w->area.width; } static widget_tell_status_t -progressbar_tell(widget_t *widget, char *property, char *new_value) +progressbar_tell(widget_t *widget, const char *property, const char *new_value) { Data *d = widget->data; int i = 0, percent, tmp; @@ -406,39 +405,23 @@ progressbar_tell(widget_t *widget, char *property, char *new_value) return WIDGET_ERROR_FORMAT_SECTION; } else if(!a_strcmp(property, "fg")) - return widget_set_color_for_data(widget, d->fg, new_value, d->data_items, d->data_title); + return widget_set_color_for_data(d->fg, new_value, d->data_items, d->data_title); else if(!a_strcmp(property, "fg_off")) - return widget_set_color_for_data(widget, d->fg_off, new_value, d->data_items, d->data_title); + return widget_set_color_for_data(d->fg_off, new_value, d->data_items, d->data_title); else if(!a_strcmp(property, "bg")) - return widget_set_color_for_data(widget, d->bg, new_value, d->data_items, d->data_title); + return widget_set_color_for_data(d->bg, new_value, d->data_items, d->data_title); else if(!a_strcmp(property, "bordercolor")) - return widget_set_color_for_data(widget, d->bordercolor, new_value, d->data_items, d->data_title); + return widget_set_color_for_data(d->bordercolor, new_value, d->data_items, d->data_title); else if(!a_strcmp(property, "fg_center")) - return widget_set_color_pointer_for_data(widget, d->pfg_center, new_value, d->data_items, d->data_title); + return widget_set_color_pointer_for_data(d->pfg_center, new_value, d->data_items, d->data_title); else if(!a_strcmp(property, "fg_end")) - return widget_set_color_pointer_for_data(widget, d->pfg_end, new_value, d->data_items, d->data_title); + return widget_set_color_pointer_for_data(d->pfg_end, new_value, d->data_items, d->data_title); else if(!a_strcmp(property, "gap")) d->gap = atoi(new_value); else if(!a_strcmp(property, "width")) - { - tmp = d->width; d->width = atoi(new_value); - if(!check_settings(d, widget->statusbar->height)) - { - d->width = tmp; /* restore */ - return WIDGET_ERROR_CUSTOM; - } - } else if(!a_strcmp(property, "height")) - { - tmpf = d->height; d->height = atof(new_value); - if(!check_settings(d, widget->statusbar->height)) - { - d->height = tmpf; /* restore */ - return WIDGET_ERROR_CUSTOM; - } - } else return WIDGET_ERROR; @@ -446,7 +429,7 @@ progressbar_tell(widget_t *widget, char *property, char *new_value) } widget_t * -progressbar_new(statusbar_t *statusbar, cfg_t *config) +progressbar_new(alignment_t align) { widget_t *w; Data *d; @@ -456,26 +439,20 @@ progressbar_new(statusbar_t *statusbar, cfg_t *config) w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); + widget_common_new(w); + w->align = align; w->draw = progressbar_draw; w->tell = progressbar_tell; d = w->data = p_new(Data, 1); - d->height = cfg_getfloat(config, "height"); - d->width = cfg_getint(config, "width"); + d->height = 0.67; + d->width = 100; - d->border_padding = cfg_getint(config, "border_padding"); - d->ticks_gap = cfg_getint(config, "ticks_gap"); - d->ticks_count = cfg_getint(config, "ticks_count"); - d->border_width = cfg_getint(config, "border_width"); - - if(!(d->vertical = cfg_getbool(config, "vertical"))) - d->vertical = false; - - d->gap = cfg_getint(config, "gap"); - - w->alignment = cfg_getalignment(config, "align"); + d->ticks_gap = 1; + d->border_width = 1; + d->gap = 2; + /* if(!(d->data_items = cfg_size(config, "data"))) { warn("progressbar widget needs at least one bar section\n"); @@ -539,6 +516,7 @@ progressbar_new(statusbar_t *statusbar, cfg_t *config) else d->bordercolor[i] = d->fg[i]; } + */ return w; } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/taglist.c b/widgets/taglist.c index d247e996..786627d9 100644 --- a/widgets/taglist.c +++ b/widgets/taglist.c @@ -19,20 +19,31 @@ * */ -#include "config.h" #include "client.h" #include "widget.h" #include "tag.h" +#include "lua.h" #include "event.h" #include "common/markup.h" #include "common/configopts.h" extern AwesomeConf globalconf; +typedef struct taglist_drawn_area_t taglist_drawn_area_t; +struct taglist_drawn_area_t +{ + statusbar_t *statusbar; + area_t *area; + taglist_drawn_area_t *next, *prev; +}; + +DO_SLIST(taglist_drawn_area_t, taglist_drawn_area, p_delete); + typedef struct { char *text_normal, *text_focus, *text_urgent; - area_t *draw_area; + taglist_drawn_area_t *drawn_area; + } taglist_data_t; static char * @@ -90,17 +101,6 @@ tag_isurgent(tag_t *t) return false; } -static style_t * -taglist_style_get(tag_t *tag, VirtScreen *vs) -{ - if(tag->selected) - return &vs->styles.focus; - else if(tag_isurgent(tag)) - return &vs->styles.urgent; - - return &vs->styles.normal; -} - static char * taglist_text_get(tag_t *tag, taglist_data_t *data) { @@ -113,139 +113,178 @@ taglist_text_get(tag_t *tag, taglist_data_t *data) } static int -taglist_draw(widget_t *widget, - draw_context_t *ctx, +taglist_draw(widget_node_t *w, + statusbar_t *statusbar, int offset, int used __attribute__ ((unused))) { tag_t *tag; - taglist_data_t *data = widget->data; + taglist_data_t *data = w->widget->data; client_t *sel = globalconf.focus->client; - VirtScreen *vscreen = &globalconf.screens[widget->statusbar->screen]; + VirtScreen *vscreen = &globalconf.screens[statusbar->screen]; + draw_context_t *ctx = statusbar->ctx; int i = 0; - style_t **styles; area_t *area, rectangle = { 0, 0, 0, 0, NULL, NULL }; char **text; + taglist_drawn_area_t *tda; - widget->area.width = 0; + w->area.width = 0; - area_list_wipe(&data->draw_area); + w->area.x = widget_calculate_offset(statusbar->width, w->area.width, + offset, w->widget->align); + w->area.y = 0; + + + /* Lookup for our taglist_drawn_area. + * This will be used to store area where we draw tag list for each + * statusbar. + */ + for(tda = data->drawn_area; tda && tda->statusbar != statusbar; tda = tda->next); + + /* Oh, we did not find a drawn area for our statusbar. First time? */ + if(!tda) + { + tda = p_new(taglist_drawn_area_t, 1); + tda->statusbar = statusbar; + taglist_drawn_area_list_push(&data->drawn_area, tda); + } text = p_new(char *, 1); - styles = p_new(style_t *, 1); for(tag = vscreen->tags; tag; tag = tag->next, i++) { p_realloc(&text, i + 1); - p_realloc(&styles, i + 1); - styles[i] = taglist_style_get(tag, vscreen); area = p_new(area_t, 1); text[i] = taglist_text_get(tag, data); text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i])); *area = draw_text_extents(ctx->connection, ctx->phys_screen, - styles[i]->font, text[i]); - area->x = widget->area.width; - area->height = widget->statusbar->height; - area_list_append(&data->draw_area, area); - widget->area.width += area->width; + globalconf.font, text[i]); + area->x = w->area.x + w->area.width; + area->height = statusbar->height; + area_list_append(&tda->area, area); + w->area.width += area->width; } - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->area.width, - offset, - widget->alignment); - - if(!widget->user_supplied_y) - widget->area.y = 0; - - for(area = data->draw_area, tag = vscreen->tags, i = 0; + for(area = tda->area, tag = vscreen->tags, i = 0; tag && area; tag = tag->next, area = area->next, i++) { - draw_text(ctx, *area, text[i], styles[i]); + draw_text(ctx, globalconf.font, &statusbar->colors.fg, *area, text[i]); p_delete(&text[i]); if(tag_isoccupied(tag)) { - rectangle.width = rectangle.height = (styles[i]->font->height + 2) / 3; + rectangle.width = rectangle.height = (globalconf.font->height + 2) / 3; rectangle.x = area->x; rectangle.y = area->y; draw_rectangle(ctx, rectangle, 1.0, - sel && is_client_tagged(sel, tag), styles[i]->fg); + sel && is_client_tagged(sel, tag), statusbar->colors.fg); } } p_delete(&text); - p_delete(&styles); - widget->area.height = widget->statusbar->height; - return widget->area.width; + w->area.height = statusbar->height; + return w->area.width; } static void -taglist_button_press(widget_t *widget, xcb_button_press_event_t *ev) +taglist_button_press(widget_node_t *w, statusbar_t *statusbar, + xcb_button_press_event_t *ev) { - VirtScreen *vscreen = &globalconf.screens[widget->statusbar->screen]; + VirtScreen *vscreen = &globalconf.screens[statusbar->screen]; Button *b; - tag_t *tag; - char buf[4]; - int i = 1; - taglist_data_t *data = widget->data; - area_t *area = data->draw_area; + taglist_data_t *data = w->widget->data; + taglist_drawn_area_t *tda; + area_t *area; + tag_t *tag, **ltag; - for(b = widget->buttons; b; b = b->next) - if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->func) - switch(widget->statusbar->position) + /* Find the good drawn area list */ + for(tda = data->drawn_area; tda && tda->statusbar != statusbar; tda = tda->next); + area = tda->area; + + for(b = w->widget->buttons; b; b = b->next) + if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct) + switch(statusbar->position) { default: - for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next) + for(tag = vscreen->tags; tag; tag = tag->next, area = area->next) if(ev->event_x >= AREA_LEFT(*area) && ev->event_x < AREA_RIGHT(*area)) { - snprintf(buf, sizeof(buf), "%d", i); - b->func(widget->statusbar->screen, buf); - return; + ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *)); + luaA_settype(globalconf.L, "tag"); + *ltag = tag; + luaA_dofunction(globalconf.L, b->fct, 1); } break; case Right: - for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next) + for(tag = vscreen->tags; tag; tag = tag->next, area = area->next) if(ev->event_y >= AREA_LEFT(*area) && ev->event_y < AREA_RIGHT(*area)) { - snprintf(buf, sizeof(buf), "%d", i); - b->func(widget->statusbar->screen, buf); - return; + ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *)); + luaA_settype(globalconf.L, "tag"); + *ltag = tag; + luaA_dofunction(globalconf.L, b->fct, 1); } break; case Left: - for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next) - if(widget->statusbar->width - ev->event_y >= AREA_LEFT(*area) - && widget->statusbar->width - ev->event_y < AREA_RIGHT(*area)) + for(tag = vscreen->tags; tag; tag = tag->next, area = area->next) + if(statusbar->width - ev->event_y >= AREA_LEFT(*area) + && statusbar->width - ev->event_y < AREA_RIGHT(*area)) { - snprintf(buf, sizeof(buf), "%d", i); - b->func(widget->statusbar->screen, buf); - return; + ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *)); + luaA_settype(globalconf.L, "tag"); + *ltag = tag; + luaA_dofunction(globalconf.L, b->fct, 1); } break; } } +static widget_tell_status_t +taglist_tell(widget_t *widget, const char *property, const char *new_value) +{ + taglist_data_t *d = widget->data; + + if(!a_strcmp(property, "text_normal")) + { + p_delete(&d->text_normal); + d->text_normal = a_strdup(new_value); + } + else if(!a_strcmp(property, "text_focus")) + { + p_delete(&d->text_focus); + d->text_focus = a_strdup(new_value); + } + else if(!a_strcmp(property, "text_urgent")) + { + p_delete(&d->text_urgent); + d->text_urgent = a_strdup(new_value); + } + else + return WIDGET_ERROR; + + return WIDGET_NOERROR; +} + widget_t * -taglist_new(statusbar_t *statusbar, cfg_t *config) +taglist_new(alignment_t align) { widget_t *w; taglist_data_t *d; w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); + widget_common_new(w); + w->align = align; w->draw = taglist_draw; w->button_press = taglist_button_press; - w->alignment = cfg_getalignment(config, "align"); + w->tell = taglist_tell; w->data = d = p_new(taglist_data_t, 1); - d->text_normal = a_strdup(cfg_getstr(config, "text_normal")); - d->text_focus = a_strdup(cfg_getstr(config, "text_focus")); - d->text_urgent = a_strdup(cfg_getstr(config, "text_urgent")); + d->text_normal = a_strdup(" <text align=\"center\"/><title/> "); + d->text_focus = a_strdup(" <text align=\"center\"/><title/> "); + d->text_urgent = a_strdup(" <text align=\"center\"/><title/> "); /* Set cache property */ w->cache_flags = WIDGET_CACHE_TAGS | WIDGET_CACHE_CLIENTS; diff --git a/widgets/tasklist.c b/widgets/tasklist.c index fd968708..75aff808 100644 --- a/widgets/tasklist.c +++ b/widgets/tasklist.c @@ -25,7 +25,6 @@ #include "screen.h" #include "event.h" #include "ewmh.h" -#include "rules.h" #include "tag.h" #include "common/configopts.h" @@ -64,47 +63,39 @@ tasklist_isvisible(client_t *c, int screen, showclient_t show) } static int -tasklist_draw(widget_t *widget, draw_context_t *ctx, int offset, int used) +tasklist_draw(widget_node_t *w, statusbar_t *statusbar, int offset, int used) { client_t *c; - Data *d = widget->data; - rule_t *r; + Data *d = w->widget->data; area_t area; char *text; int n = 0, i = 0, box_width = 0, icon_width = 0, box_width_rest = 0; NetWMIcon *icon; - style_t *style; - if(used >= widget->statusbar->width) - return (widget->area.width = 0); + if(used >= statusbar->width) + return (w->area.width = 0); for(c = globalconf.clients; c; c = c->next) - if(tasklist_isvisible(c, widget->statusbar->screen, d->show)) + if(tasklist_isvisible(c, statusbar->screen, d->show)) n++; if(!n) - return (widget->area.width = 0); + return (w->area.width = 0); - box_width = (widget->statusbar->width - used) / n; + box_width = (statusbar->width - used) / n; /* compute how many pixel we left empty */ - box_width_rest = (widget->statusbar->width - used) % n; + box_width_rest = (statusbar->width - used) % n; - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - 0, - offset, - widget->alignment); + w->area.x = widget_calculate_offset(statusbar->width, + 0, offset, w->widget->align); - if(!widget->user_supplied_y) - widget->area.y = widget->area.y = 0; + w->area.y = 0; for(c = globalconf.clients; c; c = c->next) - if(tasklist_isvisible(c, widget->statusbar->screen, d->show)) + if(tasklist_isvisible(c, statusbar->screen, d->show)) { icon_width = 0; - style = client_style_get(c); - if(globalconf.focus->client == c) text = d->text_focus; else if(c->isurgent) @@ -117,167 +108,177 @@ tasklist_draw(widget_t *widget, draw_context_t *ctx, int offset, int used) if(d->show_icons) { /* draw a background for icons */ - area.x = widget->area.x + box_width * i; - area.y = widget->area.y; - area.height = widget->statusbar->height; + area.x = w->area.x + box_width * i; + area.y = w->area.y; + area.height = statusbar->height; area.width = box_width; - draw_rectangle(ctx, area, 1.0, true, style->bg); + draw_rectangle(statusbar->ctx, area, 1.0, true, + statusbar->colors.bg); - if((r = rule_matching_client(c)) && r->icon) + if(0) { - area = draw_get_image_size(r->icon); +// area = draw_get_image_size(r->icon); if(area.width > 0 && area.height > 0) { - icon_width = ((double) widget->statusbar->height / (double) area.height) * area.width; - draw_image(ctx, - widget->area.x + box_width * i, - widget->area.y, - widget->statusbar->height, - r->icon); + icon_width = ((double) statusbar->height / (double) area.height) * area.width; + draw_image(statusbar->ctx, + w->area.x + box_width * i, + w->area.y, + statusbar->height, + NULL); +// r->icon); } } if(!icon_width && (icon = ewmh_get_window_icon(c->win))) { - icon_width = ((double) widget->statusbar->height / (double) icon->height) + icon_width = ((double) statusbar->height / (double) icon->height) * icon->width; - draw_image_from_argb_data(ctx, - widget->area.x + box_width * i, - widget->area.y, + draw_image_from_argb_data(statusbar->ctx, + w->area.x + box_width * i, + w->area.y, icon->width, icon->height, - widget->statusbar->height, icon->image); + statusbar->height, icon->image); p_delete(&icon->image); p_delete(&icon); } } - area.x = widget->area.x + icon_width + box_width * i; - area.y = widget->area.y; + area.x = w->area.x + icon_width + box_width * i; + area.y = w->area.y; area.width = box_width - icon_width; - area.height = widget->statusbar->height; + area.height = statusbar->height; /* if we're on last elem, it has the last pixels left */ if(i == n - 1) area.width += box_width_rest; - draw_text(ctx, area, text, style); + draw_text(statusbar->ctx, globalconf.font, + &statusbar->colors.fg, + area, text); p_delete(&text); if(c == globalconf.scratch.client) { - area.x = widget->area.x + icon_width + box_width * i; - area.y = widget->area.y; - area.width = (style->font->height + 2) / 3; - area.height = (style->font->height + 2) / 3; - draw_rectangle(ctx, area, 1.0, c->isfloating, style->fg); + area.x = w->area.x + icon_width + box_width * i; + area.y = w->area.y; + area.width = (globalconf.font->height + 2) / 3; + area.height = (globalconf.font->height + 2) / 3; + draw_rectangle(statusbar->ctx, area, 1.0, c->isfloating, statusbar->colors.fg); } else if(c->isfloating || c->ismax) - draw_circle(ctx, widget->area.x + icon_width + box_width * i, - widget->area.y, - (style->font->height + 2) / 4, - c->ismax, style->fg); + draw_circle(statusbar->ctx, w->area.x + icon_width + box_width * i, + w->area.y, + (globalconf.font->height + 2) / 4, + c->ismax, statusbar->colors.fg); i++; } - widget->area.width = widget->statusbar->width - used; - widget->area.height = widget->statusbar->height; + w->area.width = statusbar->width - used; + w->area.height = statusbar->height; - return widget->area.width; + return w->area.width; } static void -tasklist_button_press(widget_t *widget, xcb_button_press_event_t *ev) +tasklist_button_press(widget_node_t *w, statusbar_t *statusbar, + xcb_button_press_event_t *ev) { Button *b; - client_t *c; - Data *d = widget->data; - tag_t *tag; + client_t *c, **lc; + Data *d = w->widget->data; int n = 0, box_width = 0, i, ci = 0; - /* button1 give focus */ - if(ev->detail == XCB_BUTTON_INDEX_1 && CLEANMASK(ev->state) == XCB_NO_SYMBOL) + for(c = globalconf.clients; c; c = c->next) + if(tasklist_isvisible(c, statusbar->screen, d->show)) + n++; + + if(!n) + return; + + box_width = w->area.width / n; + + switch(statusbar->position) { - for(c = globalconf.clients; c; c = c->next) - if(tasklist_isvisible(c, widget->statusbar->screen, d->show)) - n++; - - if(!n) - return; - - box_width = widget->area.width / n; - - if(ev->detail == XCB_BUTTON_INDEX_1 && CLEANMASK(ev->state) == XCB_NO_SYMBOL) - { - switch(widget->statusbar->position) - { - case Top: - case Bottom: - ci = (ev->event_x - widget->area.x) / box_width; - break; - case Right: - ci = (ev->event_y - widget->area.x) / box_width; - break; - default: - ci = ((widget->statusbar->width - ev->event_y) - widget->area.x) / box_width; - break; - } - /* found first visible client */ - for(c = globalconf.clients; - c && !tasklist_isvisible(c, widget->statusbar->screen, d->show); - c = c->next); - /* found ci-th visible client */ - for(i = 0; c ; c = c->next) - if(tasklist_isvisible(c, widget->statusbar->screen, d->show)) - if(i++ >= ci) - break; - - if(c) - { - /* first switch tag if client not visible */ - if(!client_isvisible(c, widget->statusbar->screen)) - for(i = 0, tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++) - if(is_client_tagged(c, tag)) - tag_view_only_byindex(c->screen, i); - client_focus(c, widget->statusbar->screen, true); - } - - return; - } + case Top: + case Bottom: + ci = (ev->event_x - w->area.x) / box_width; + break; + case Right: + ci = (ev->event_y - w->area.x) / box_width; + break; + default: + ci = ((statusbar->width - ev->event_y) - w->area.x) / box_width; + break; } + /* found first visible client */ + for(c = globalconf.clients; + c && !tasklist_isvisible(c, statusbar->screen, d->show); + c = c->next); + /* found ci-th visible client */ + for(i = 0; c ; c = c->next) + if(tasklist_isvisible(c, statusbar->screen, d->show)) + if(i++ >= ci) + break; - for(b = widget->buttons; b; b = b->next) - if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->func) - b->func(widget->statusbar->screen, b->arg); + if(c) + for(b = w->widget->buttons; b; b = b->next) + if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct) + { + lc = lua_newuserdata(globalconf.L, sizeof(client_t *)); + *lc = c; + luaA_settype(globalconf.L, "client"); + luaA_dofunction(globalconf.L, b->fct, 1); + } +} + +static widget_tell_status_t +tasklist_tell(widget_t *widget, const char *property, const char *new_value) +{ + Data *d = widget->data; + + if(!a_strcmp(property, "text_normal")) + { + p_delete(&d->text_normal); + d->text_normal = a_strdup(new_value); + } + else if(!a_strcmp(property, "text_focus")) + { + p_delete(&d->text_focus); + d->text_focus = a_strdup(new_value); + } + else if(!a_strcmp(property, "text_urgent")) + { + p_delete(&d->text_urgent); + d->text_urgent = a_strdup(new_value); + } + else + return WIDGET_ERROR; + + return WIDGET_NOERROR; } widget_t * -tasklist_new(statusbar_t *statusbar, cfg_t *config) +tasklist_new(alignment_t align __attribute__ ((unused))) { widget_t *w; Data *d; - char *buf; w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); + widget_common_new(w); w->draw = tasklist_draw; w->button_press = tasklist_button_press; - w->alignment = AlignFlex; + w->align = AlignFlex; w->data = d = p_new(Data, 1); + w->tell = tasklist_tell; - d->text_normal = a_strdup(cfg_getstr(config, "text_normal")); - d->text_focus = a_strdup(cfg_getstr(config, "text_focus")); - d->text_urgent = a_strdup(cfg_getstr(config, "text_urgent")); - d->show_icons = cfg_getbool(config, "show_icons"); - - buf = cfg_getstr(config, "show"); - if(!a_strcmp(buf, "all")) - d->show = ShowAll; - else if(!a_strcmp(buf, "tags")) - d->show = ShowTags; - else - d->show = ShowFocus; + d->text_normal = a_strdup(" <title/> "); + d->text_focus = a_strdup(" <title/> "); + d->text_urgent = a_strdup(" <title/> "); + d->show_icons = true; + d->show = ShowTags; /* Set cache property */ w->cache_flags = WIDGET_CACHE_CLIENTS; diff --git a/widgets/textbox.c b/widgets/textbox.c index b0e7a482..3a53c994 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -1,6 +1,7 @@ /* * textbox.c - text box widget * + * Copyright © 2007-2008 Julien Danjou <julien@danjou.info> * Copyright © 2007 Aldo Cortesi <aldo@nullcube.com> * * This program is free software; you can redistribute it and/or modify @@ -33,37 +34,37 @@ typedef struct } Data; static int -textbox_draw(widget_t *widget, draw_context_t *ctx, int offset, int used) +textbox_draw(widget_node_t *w, statusbar_t *statusbar, int offset, int used) { - Data *d = widget->data; + Data *d = w->widget->data; if(d->width) - widget->area.width = d->width; - else if(widget->alignment == AlignFlex) - widget->area.width = widget->statusbar->width - used; + w->area.width = d->width; + else if(w->widget->align == AlignFlex) + w->area.width = statusbar->width - used; else - widget->area.width = MIN(draw_text_extents(ctx->connection, ctx->phys_screen, - globalconf.screens[widget->statusbar->screen].styles.normal.font, d->text).width, - widget->statusbar->width - used); + w->area.width = MIN(draw_text_extents(statusbar->ctx->connection, + statusbar->ctx->phys_screen, + globalconf.font, d->text).width, + statusbar->width - used); - widget->area.height = widget->statusbar->height; + w->area.height = statusbar->height; - if(!widget->user_supplied_x) - widget->area.x = widget_calculate_offset(widget->statusbar->width, - widget->area.width, - offset, - widget->alignment); - if(!widget->user_supplied_y) - widget->area.y = 0; + w->area.x = widget_calculate_offset(statusbar->width, + w->area.width, + offset, + w->widget->align); + w->area.y = 0; - draw_text(ctx, widget->area, d->text, - &globalconf.screens[widget->statusbar->screen].styles.normal); + draw_text(statusbar->ctx, globalconf.font, + &statusbar->colors.fg, + w->area, d->text); - return widget->area.width; + return w->area.width; } static widget_tell_status_t -textbox_tell(widget_t *widget, char *property, char *new_value) +textbox_tell(widget_t *widget, const char *property, const char *new_value) { Data *d = widget->data; @@ -81,23 +82,18 @@ textbox_tell(widget_t *widget, char *property, char *new_value) } widget_t * -textbox_new(statusbar_t *statusbar, cfg_t *config) +textbox_new(alignment_t align) { widget_t *w; Data *d; w = p_new(widget_t, 1); - widget_common_new(w, statusbar, config); + widget_common_new(w); + w->align = align; w->draw = textbox_draw; w->tell = textbox_tell; - w->alignment = cfg_getalignment(config, "align"); - w->data = d = p_new(Data, 1); - d->width = cfg_getint(config, "width"); - - d->text = a_strdup(cfg_getstr(config, "text")); - return w; } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/window.c b/window.c index 7fec3b29..12d1e264 100644 --- a/window.c +++ b/window.c @@ -149,17 +149,51 @@ window_grabbuttons(xcb_window_t win, int phys_screen) ANY_MODIFIER); } -/** Grab buttons on the root window. - * \param phys_screen physical screen id +/** Grab all buttons on the root window. + * \param b The button binding. */ void -window_root_grabbuttons(int phys_screen) +window_root_grabbuttons(void) { Button *b; - xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, phys_screen); + xcb_screen_t *s; + int phys_screen = globalconf.default_screen; - for(b = globalconf.buttons.root; b; b = b->next) + do { + s = xcb_aux_get_screen(globalconf.connection, phys_screen); + for(b = globalconf.buttons.root; b; b = b->next) + { + xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, + b->button, b->mod); + xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, + b->button, b->mod | XCB_MOD_MASK_LOCK); + xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, + b->button, b->mod | globalconf.numlockmask); + xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, + b->button, b->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK); + } + phys_screen++; + } while(!globalconf.screens_info->xinerama_is_active + && phys_screen < globalconf.screens_info->nscreen); +} + +/** Grab button on the root window. + * \param b The button binding. + */ +void +window_root_grabbutton(Button *b) +{ + xcb_screen_t *s; + int phys_screen = globalconf.default_screen; + + do + { + s = xcb_aux_get_screen(globalconf.connection, phys_screen); xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, b->button, b->mod); @@ -172,22 +206,27 @@ window_root_grabbuttons(int phys_screen) xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, b->button, b->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK); - } + phys_screen++; + } while(!globalconf.screens_info->xinerama_is_active + && phys_screen < globalconf.screens_info->nscreen); } -/** Grab keys on the root window. - * \param phys_screen Physical screen number. +/** Grab key on the root windows. + * \param k The keybinding. */ void -window_root_grabkeys(int phys_screen) +window_root_grabkey(keybinding_t *k) { - xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, phys_screen); - keybinding_t *k; + int phys_screen = globalconf.default_screen; + xcb_screen_t *s; xcb_keycode_t kc; - - for(k = globalconf.keys; k; k = k->next) - if((kc = k->keycode) || (k->keysym && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym)))) + + if((kc = k->keycode) + || (k->keysym && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym)))) + { + do { + s = xcb_aux_get_screen(globalconf.connection, phys_screen); xcb_grab_key(globalconf.connection, true, s->root, k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_key(globalconf.connection, true, s->root, @@ -197,7 +236,10 @@ window_root_grabkeys(int phys_screen) xcb_grab_key(globalconf.connection, true, s->root, k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); - } + phys_screen++; + } while(!globalconf.screens_info->xinerama_is_active + && phys_screen < globalconf.screens_info->nscreen); + } } /** Set shape property on window. diff --git a/window.h b/window.h index d3188e3c..5e19ec84 100644 --- a/window.h +++ b/window.h @@ -28,8 +28,9 @@ void window_setstate(xcb_window_t, long); long window_getstate(xcb_window_t); void window_configure(xcb_window_t, area_t, int); void window_grabbuttons(xcb_window_t, int); -void window_root_grabbuttons(int); -void window_root_grabkeys(int); +void window_root_grabbutton(Button *); +void window_root_grabbuttons(void); +void window_root_grabkey(keybinding_t *); void window_setshape(xcb_window_t, int); void window_settrans(xcb_window_t, double);