From 1f046b3c9f9610549babf44cb82ba2773c494593 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 20 May 2008 15:39:47 +0200 Subject: [PATCH] [everything] Switch from libconfuse to Lua Signed-off-by: Julien Danjou --- .gitignore | 9 +- Makefile.am | 101 +-- README | 6 +- UPGRADE | 1 - as_ac_expand.m4 | 44 + awesome-client.c | 77 +- awesome-menu.1.txt | 62 -- awesome-menu.c | 1411 ------------------------------ awesome-message.1.txt | 49 -- awesome-message.c | 260 ------ awesome.1.txt | 4 +- awesome.c | 52 +- awesome.h | 30 - awesomerc.5.txt | 190 +--- awesomerc.in | 183 ---- awesomerc.lua.in | 191 ++++ awful.lua | 223 +++++ build-utils/extractoptsdoc.py | 83 -- build-utils/extractrcskeleton.py | 139 --- build-utils/extractuicbdoc.py | 70 -- client.c | 832 ++++++++---------- client.h | 12 - common/configopts.c | 735 +--------------- common/configopts.h | 12 - common/draw.c | 81 +- common/draw.h | 37 +- common/list.h | 24 +- common/refcount.h | 39 + common/util.c | 30 +- common/util.h | 1 + common/xutil.c | 75 ++ common/xutil.h | 2 + config.c | 524 ----------- config.h | 33 - configure.ac | 12 +- event.c | 134 +-- event.h | 1 - ewmh.c | 18 +- focus.c | 50 -- focus.h | 3 - layout.c | 74 +- layout.h | 15 +- layouts/fibonacci.c | 2 +- layouts/tile.c | 98 +-- layouts/tile.h | 4 - lua.c | 383 ++++++++ lua.h | 117 +++ mouse.c | 153 ++-- mouse.h | 6 +- placement.c | 4 +- rules.c | 109 --- rules.h | 36 - screen.c | 78 -- screen.h | 3 - statusbar.c | 402 +++++---- statusbar.h | 21 +- structs.h | 192 ++-- tag.c | 432 +++++---- tag.h | 26 +- titlebar.c | 803 +++++++++-------- titlebar.h | 67 +- uicb.c | 267 ------ uicb.h | 36 - widget.c | 330 ++++--- widget.h | 12 +- widgets/common.c | 10 +- widgets/common.h | 4 +- widgets/focusicon.c | 105 --- widgets/graph.c | 58 +- widgets/iconbox.c | 43 +- widgets/layoutinfo.c | 75 -- widgets/progressbar.c | 94 +- widgets/taglist.c | 187 ++-- widgets/tasklist.c | 251 +++--- widgets/textbox.c | 52 +- window.c | 72 +- window.h | 5 +- 77 files changed, 3471 insertions(+), 6995 deletions(-) delete mode 100644 UPGRADE create mode 100644 as_ac_expand.m4 delete mode 100644 awesome-menu.1.txt delete mode 100644 awesome-menu.c delete mode 100644 awesome-message.1.txt delete mode 100644 awesome-message.c delete mode 100644 awesome.h delete mode 100644 awesomerc.in create mode 100644 awesomerc.lua.in create mode 100644 awful.lua delete mode 100755 build-utils/extractoptsdoc.py delete mode 100755 build-utils/extractrcskeleton.py delete mode 100755 build-utils/extractuicbdoc.py create mode 100644 common/refcount.h delete mode 100644 config.c delete mode 100644 config.h create mode 100644 lua.c create mode 100644 lua.h delete mode 100644 rules.c delete mode 100644 rules.h delete mode 100644 uicb.c delete mode 100644 uicb.h delete mode 100644 widgets/focusicon.c delete mode 100644 widgets/layoutinfo.c diff --git a/.gitignore b/.gitignore index fa167b7ad..6dc2fb44a 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 1bda0c11f..18869dc0c 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 c0cec6057..5af4d3537 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 2cca3ade7..000000000 --- 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 000000000..7355c7d7c --- /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 31601cf2f..80de4d423 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 15085d7d1..000000000 --- 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 2daa66718..000000000 --- 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 2b471f802..000000000 --- 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 16b0ba587..000000000 --- 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 2b213bee3..4126019a9 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 c4892f29b..9b7808703 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 85cc528aa..000000000 --- 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 3e9b761d9..cd488bd99 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 812c95b69..000000000 --- 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 000000000..da445739f --- /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 000000000..36eb16900 --- /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 cabd10fe9..000000000 --- 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 a4589a38c..000000000 --- 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 7978df8f4..000000000 --- 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 984b3c27d..0da822369 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 47352a960..d8592925c 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 11062c3b0..68b7c24d8 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 75055f58b..be567edc5 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 f85814a1f..b7e4ae440 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 a3c6b8db5..fcfa5ddac 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 8589e9e28..c59355f2b 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 000000000..1eb56c796 --- /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 edacee938..983f7141b 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 cf44f0c95..af0bc9a5b 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 0ca4f0cf0..c7f2354ac 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 d06fff274..1e7e6eec9 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 0fb1bf212..000000000 --- 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 c53339d24..000000000 --- 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 fe2c756d6..9500b759c 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 4b7d4c60f..2c0d60000 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 7dd997dab..e3cb56cc7 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 40866fdfc..17a4a997c 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 0af7659ec..f9f34b3d5 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 a8bdb6658..2da6e6dc1 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 0f3e2c944..344ac0014 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 427d2cec9..c3e7a6ed4 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 61478fcde..9b712f50e 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 6738504c6..a52d42665 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 6280f56cd..a7f3e169d 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 000000000..c11da31c0 --- /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 000000000..fb4f2c066 --- /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 44e35d33c..b05d0a374 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 95a11b90a..04e433356 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 e97f77b61..88c86711a 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 19c3dbc91..000000000 --- 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 14739a6e8..000000000 --- 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 472435561..1ad852a8f 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 c85ef6325..70bfea599 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 0ffa9f40c..fc5182ec4 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 6cdee9c69..8b88a7cc4 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 ba9188753..223e3ea51 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 675f668b6..1423b32c0 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 12d4cca8c..502fa5cc5 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 d2f8508da..1421e67d8 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 91d6e788e..eb5645d45 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 cc8bd6883..000000000 --- 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 8f535d46e..000000000 --- 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 f95542fe2..c99b900c6 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 75157145b..f3164160c 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 b20b13c9d..e4679aa9b 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 980ef2ba6..da4d7bee3 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 cdebae144..000000000 --- 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 cc9aeb8de..2e9d84743 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 d318660e6..9b5b7c7e3 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 12364670f..000000000 --- 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 1c537ef9f..f483bd429 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 d247e996b..786627d9d 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 fd9687088..75aff8089 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 b0e7a482c..3a53c9947 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 7fec3b293..12d1e264e 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 d3188e3c8..5e19ec844 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);