[everything] Switch from libconfuse to Lua

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-05-20 15:39:47 +02:00
parent 61d552a860
commit 1f046b3c9f
77 changed files with 3471 additions and 6995 deletions

9
.gitignore vendored
View File

@ -3,7 +3,6 @@ awesome
awesome-client awesome-client
doc doc
*.swp *.swp
defconfig.h
.deps .deps
.dirstamp .dirstamp
configure configure
@ -16,16 +15,10 @@ aclocal.m4
autom4te.cache autom4te.cache
awesome.doxygen awesome.doxygen
awesome-client.1 awesome-client.1
awesome-message.1
awesome-menu.1 awesome-menu.1
awesome.1 awesome.1
awesomerc.5 awesomerc.5
awesomerc awesomerc.lua
widgetgen.h widgetgen.h
layoutgen.h layoutgen.h
awesome-version-internal.h awesome-version-internal.h
awesome-message
awesome-menu
uicbdocgen.txt
optsdocgen.txt
rcskeletongen.txt

View File

@ -9,6 +9,8 @@ iconsdir = $(pkgdatadir)/icons
dist_icons_DATA = dist_icons_DATA =
iconslayoutsdir = $(iconsdir)/layouts iconslayoutsdir = $(iconsdir)/layouts
dist_iconslayouts_DATA = dist_iconslayouts_DATA =
awfuldir = $(pkgdatadir)/lib
dist_awful_DATA =
LAYOUTS = LAYOUTS =
@ -27,10 +29,8 @@ LAYOUTS += layouts/fibonacci.h
WIDGETS = WIDGETS =
WIDGETS += widgets/taglist.c WIDGETS += widgets/taglist.c
WIDGETS += widgets/layoutinfo.c
WIDGETS += widgets/textbox.c WIDGETS += widgets/textbox.c
WIDGETS += widgets/iconbox.c WIDGETS += widgets/iconbox.c
WIDGETS += widgets/focusicon.c
WIDGETS += widgets/progressbar.c WIDGETS += widgets/progressbar.c
WIDGETS += widgets/tasklist.c WIDGETS += widgets/tasklist.c
WIDGETS += widgets/graph.c WIDGETS += widgets/graph.c
@ -39,32 +39,22 @@ WIDGETS += widgets/common.c widgets/common.h
doc_DATA += README doc_DATA += README
doc_DATA += UPGRADE
EXTRA_DIST += UPGRADE
EXTRA_DIST += LICENSE EXTRA_DIST += LICENSE
EXTRA_DIST += UPGRADE
EXTRA_DIST += STYLE EXTRA_DIST += STYLE
doc_DATA += STYLE doc_DATA += STYLE
EXTRA_DIST += awesomerc.in EXTRA_DIST += awful.lua
CLEANFILES += awesomerc dist_awful_DATA += awful.lua
BUILT_SOURCES += awesomerc
doc_DATA += awesomerc
awesomerc: $(srcdir)/awesomerc.in
$(SED) -e "s|[@]iconslayoutsdir@|$(iconslayoutsdir)|;s|[@]iconsdir@|$(iconsdir)|" \
< $(srcdir)/awesomerc.in > awesomerc
CLEANFILES += defconfig.h EXTRA_DIST += awesomerc.lua.in
BUILT_SOURCES += defconfig.h CLEANFILES += awesomerc.lua
defconfig.h: awesomerc BUILT_SOURCES += awesomerc.lua
@echo "generating defconfig.h from awesomerc" doc_DATA += awesomerc.lua
@echo "static const char *AWESOME_DEFAULT_CONFIG = " > defconfig.h awesomerc.lua: $(srcdir)/awesomerc.lua.in
@echo -n "\"" >> defconfig.h $(SED) -e "s|[@]iconslayoutsdir@|$(iconslayoutsdir)|;s|[@]iconsdir@|$(iconsdir)|" \
@$(SED) 's,\\,\\\\,g;s/$$/\\n\\/;s/"/\\"/g' "awesomerc" >> defconfig.h < $(srcdir)/awesomerc.lua.in > awesomerc.lua
@echo "\";" >> defconfig.h
CLEANFILES += layoutgen.h CLEANFILES += layoutgen.h
BUILT_SOURCES += layoutgen.h BUILT_SOURCES += layoutgen.h
@ -102,12 +92,12 @@ AWESOME_CFLAGS = -std=gnu99 -pipe \
-Wunused -Winit-self -Wpointer-arith -Wredundant-decls \ -Wunused -Winit-self -Wpointer-arith -Wredundant-decls \
-Wmissing-prototypes -Wmissing-format-attribute -Wmissing-noreturn -Wmissing-prototypes -Wmissing-format-attribute -Wmissing-noreturn
endif endif
AM_CPPFLAGS = $(pangocairo_CFLAGS) $(confuse_CFLAGS) $(AWESOME_CFLAGS) \ AM_CPPFLAGS = $(pangocairo_CFLAGS) $(AWESOME_CFLAGS) \
$(GTK_CFLAGS) $(imlib2_CFLAGS) \ $(GTK_CFLAGS) $(imlib2_CFLAGS) \
$(xcb_CFLAGS) $(xcb_event_CFLAGS) \ $(xcb_CFLAGS) $(xcb_event_CFLAGS) \
$(xcb_randr_CFLAGS) $(xcb_xinerama_CFLAGS) $(xcb_shape_CFLAGS) \ $(xcb_randr_CFLAGS) $(xcb_xinerama_CFLAGS) $(xcb_shape_CFLAGS) \
$(xcb_aux_CFLAGS) $(xcb_atom_CFLAGS) $(xcb_keysyms_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 bin_PROGRAMS += awesome
awesome_SOURCES = \ awesome_SOURCES = \
@ -120,7 +110,7 @@ awesome_SOURCES = \
common/xscreen.h common/xscreen.c \ common/xscreen.h common/xscreen.c \
common/draw.c common/draw.h \ common/draw.c common/draw.h \
common/markup.c common/markup.h \ common/markup.c common/markup.h \
common/list.h \ common/list.h common/refcount.h \
structs.h \ structs.h \
client.c client.h \ client.c client.h \
titlebar.c titlebar.h \ titlebar.c titlebar.h \
@ -128,24 +118,22 @@ awesome_SOURCES = \
focus.c focus.h \ focus.c focus.h \
event.c event.h \ event.c event.h \
layout.c layout.h \ layout.c layout.h \
awesome.c awesome.h \ awesome.c \
tag.c tag.h \ tag.c tag.h \
config.c config.h \ lua.c lua.h \
screen.c screen.h \ screen.c screen.h \
statusbar.c statusbar.h \ statusbar.c statusbar.h \
uicb.c uicb.h \
window.c window.h \ window.c window.h \
rules.c rules.h \
mouse.c mouse.h \ mouse.c mouse.h \
widget.c widget.h \ widget.c widget.h \
ewmh.c ewmh.h \ ewmh.c ewmh.h \
dbus.c dbus.h dbus.c dbus.h
awesome_SOURCES += $(LAYOUTS) awesome_SOURCES += $(LAYOUTS)
awesome_SOURCES += $(WIDGETS) 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_randr_LIBS) $(xcb_xinerama_LIBS) $(xcb_shape_LIBS) $(xcb_aux_LIBS) \
$(xcb_atom_LIBS) $(xcb_keysyms_LIBS) $(xcb_icccm_LIBS) $(dbus_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 bin_PROGRAMS += awesome-client
awesome_client_SOURCES = \ awesome_client_SOURCES = \
@ -153,41 +141,13 @@ awesome_client_SOURCES = \
common/socket.c common/socket.h \ common/socket.c common/socket.h \
common/version.c common/version.h \ common/version.c common/version.h \
common/util.c common/util.h common/util.c common/util.h
awesome_client_LDADD = -lreadline
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)
if HAVE_XMLTO if HAVE_XMLTO
if HAVE_ASCIIDOC if HAVE_ASCIIDOC
if XMLTO_MAN_WORKS if XMLTO_MAN_WORKS
man_MANS += awesome.1 man_MANS += awesome.1
man_MANS += awesome-client.1 man_MANS += awesome-client.1
man_MANS += awesome-message.1
man_MANS += awesome-menu.1
man_MANS += awesomerc.5 man_MANS += awesomerc.5
endif endif
endif endif
@ -195,8 +155,6 @@ endif
EXTRA_DIST += awesome.1.txt EXTRA_DIST += awesome.1.txt
EXTRA_DIST += awesome-client.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 EXTRA_DIST += awesomerc.5.txt
dist_icons_DATA += icons/awesome16.png dist_icons_DATA += icons/awesome16.png
@ -221,13 +179,10 @@ dist_iconslayouts_DATA += icons/layouts/tiletopw.png
dist_iconslayouts_DATA += icons/layouts/tilew.png dist_iconslayouts_DATA += icons/layouts/tilew.png
clean-local: 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 += .1.xml .1
SUFFIXES += .5.xml .5 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 if HAVE_XMLTO
.1.xml.1: .1.xml.1:
$(XMLTO) man $< $(XMLTO) man $<
@ -238,26 +193,12 @@ endif
SUFFIXES += .1.txt .1.xml SUFFIXES += .1.txt .1.xml
SUFFIXES += .5.txt .5.xml SUFFIXES += .5.txt .5.xml
if HAVE_ASCIIDOC 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: .1.txt.1.xml:
$(ASCIIDOC) -d manpage -b docbook -o $@ $< $(ASCIIDOC) -d manpage -b docbook -o $@ $<
awesomerc.5.xml: optsdocgen.txt rcskeletongen.txt uicbdocgen.txt awesomerc.5.xml:
.5.txt.5.xml: .5.txt.5.xml:
$(ASCIIDOC) -d manpage -b docbook -o $@ $< $(ASCIIDOC) -d manpage -b docbook -o $@ $<
endif endif
endif
# Check that package version matches git version before creating dist tarballs # Check that package version matches git version before creating dist tarballs

6
README
View File

@ -5,8 +5,8 @@ awesome is an extremely fast, small, and dynamic window manager for X.
Requirements Requirements
------------ ------------
In order to build awesome itself, you need header files and libs of: In order to build awesome itself, you need header files and libs of:
- Xlib, Xinerama, Xrandr - Xlib, xcb and xcb-util.
- libconfuse >= 2.6 - Lua 5.1
- cairo - cairo
- pango and pangocairo - pango and pangocairo
- glib - glib
@ -57,5 +57,5 @@ the DISPLAY environment variable is set correctly, e.g.:
Configuration 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. An example is provided in the sources.

View File

@ -1 +0,0 @@
Run awesome -k to check your configuration file syntax.

44
as_ac_expand.m4 Normal file
View File

@ -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
])

View File

@ -20,12 +20,18 @@
* *
*/ */
#define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "common/socket.h" #include "common/socket.h"
#include "common/version.h" #include "common/version.h"
#include "common/util.h" #include "common/util.h"
@ -41,7 +47,7 @@
* \return errno of sendto() * \return errno of sendto()
*/ */
static int static int
send_msg(char *msg, ssize_t msg_len) send_msg(const char *msg, ssize_t msg_len)
{ {
struct sockaddr_un *addr; struct sockaddr_un *addr;
int csfd, ret_value = EXIT_SUCCESS; int csfd, ret_value = EXIT_SUCCESS;
@ -94,52 +100,59 @@ exit_help(int exit_code)
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
char buf[1024], *msg; char buf[1024], *msg, *prompt;
int ret_value = EXIT_SUCCESS; int ret_value = EXIT_SUCCESS;
ssize_t len, msg_len = 1; ssize_t len, msg_len = 1;
if (argc < 2) if(argc == 2)
{
/* no args to parse, nothing to do */
}
else if (argc == 2)
{ {
if(!a_strcmp("-v", argv[1]) || !a_strcmp("--version", argv[1])) if(!a_strcmp("-v", argv[1]) || !a_strcmp("--version", argv[1]))
eprint_version("awesome-client"); eprint_version("awesome-client");
else if(!a_strcmp("-h", argv[1]) || !a_strcmp("--help", argv[1])) else if(!a_strcmp("-h", argv[1]) || !a_strcmp("--help", argv[1]))
exit_help(EXIT_SUCCESS); 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 else
{ {
exit_help(EXIT_SUCCESS); msg = p_new(char, 1);
} while(fgets(buf, sizeof(buf), stdin))
msg = p_new(char, 1);
while(fgets(buf, sizeof(buf), stdin))
{
len = a_strlen(buf);
if (len < 2 && msg_len > 1)
{ {
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); ret_value = send_msg(msg, msg_len);
p_delete(&msg); 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);
return ret_value; return ret_value;
} }
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -1,62 +0,0 @@
awesome-menu(1)
=================
NAME
----
awesome-menu - awesome menu system
SYNOPSIS
--------
awesome-menu [-c config] [-e command] <title>
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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -9,7 +9,7 @@ awesome - awesome window manager
SYNOPSIS SYNOPSIS
-------- --------
awesome [ -v | --version ] [ -h | --help ] [ -k | --check ] [ --config | -c configuration file ] awesome [ -v | --version ] [ -h | --help ] [ --config | -c configuration file ]
DESCRIPTION DESCRIPTION
----------- -----------
@ -47,8 +47,6 @@ OPTIONS
Print help information, then exit. Print help information, then exit.
--config | -c:: --config | -c::
Use an alternate configuration file instead of $HOME/.awesomerc. Use an alternate configuration file instead of $HOME/.awesomerc.
--check | -k::
Check configuration file syntax.
DEFAULTS MOUSE BINDINGS DEFAULTS MOUSE BINDINGS
----------------------- -----------------------

View File

@ -41,8 +41,7 @@
#include <xcb/xcb_atom.h> #include <xcb/xcb_atom.h>
#include <xcb/xcb_icccm.h> #include <xcb/xcb_icccm.h>
#include "config.h" #include "lua.h"
#include "awesome.h"
#include "event.h" #include "event.h"
#include "layout.h" #include "layout.h"
#include "screen.h" #include "screen.h"
@ -58,7 +57,7 @@
#include "common/configopts.h" #include "common/configopts.h"
#include "common/xutil.h" #include "common/xutil.h"
static bool running = true; bool running = true;
AwesomeConf globalconf; AwesomeConf globalconf;
@ -200,17 +199,6 @@ xerrorstart(void * data __attribute__ ((unused)),
eprint("another window manager is already running\n"); 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. /** Function to exit on some signals.
* \param sig the signal received, unused * \param sig the signal received, unused
*/ */
@ -292,21 +280,21 @@ main(int argc, char **argv)
int r, xfd, csfd, dbusfd, i, screen_nbr, opt; int r, xfd, csfd, dbusfd, i, screen_nbr, opt;
ssize_t cmdlen = 1; ssize_t cmdlen = 1;
const xcb_query_extension_reply_t *shape_query, *randr_query; const xcb_query_extension_reply_t *shape_query, *randr_query;
statusbar_t *statusbar;
fd_set rd; fd_set rd;
xcb_generic_event_t *ev; xcb_generic_event_t *ev;
struct sockaddr_un *addr; struct sockaddr_un *addr;
client_t *c; client_t *c;
bool confcheck = false;
static struct option long_options[] = static struct option long_options[] =
{ {
{"help", 0, NULL, 'h'}, {"help", 0, NULL, 'h'},
{"version", 0, NULL, 'v'}, {"version", 0, NULL, 'v'},
{"check", 0, NULL, 'k'},
{"config", 1, NULL, 'c'}, {"config", 1, NULL, 'c'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
/* clear the globalconf structure */
p_clear(&globalconf, 1);
/* save argv */ /* save argv */
for(i = 0; i < argc; i++) for(i = 0; i < argc; i++)
cmdlen += a_strlen(argv[i]) + 1; cmdlen += a_strlen(argv[i]) + 1;
@ -337,17 +325,11 @@ main(int argc, char **argv)
else else
eprint("-c option requires a file name\n"); eprint("-c option requires a file name\n");
break; break;
case 'k':
confcheck = true;
break;
} }
/* Text won't be printed correctly otherwise */ /* Text won't be printed correctly otherwise */
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
if(confcheck)
return config_check(confpath);
/* X stuff */ /* X stuff */
globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); globalconf.connection = xcb_connect(NULL, &globalconf.default_screen);
if(xcb_connection_has_error(globalconf.connection)) if(xcb_connection_has_error(globalconf.connection))
@ -396,23 +378,15 @@ main(int argc, char **argv)
focus_add_client(NULL); focus_add_client(NULL);
/* parse config */ /* parse config */
config_parse(confpath); if(!confpath)
confpath = config_file();
luaA_parserc(confpath);
/* init cursors */ /* init cursors */
globalconf.cursor[CurNormal] = create_font_cursor(CURSOR_LEFT_PTR); globalconf.cursor[CurNormal] = create_font_cursor(CURSOR_LEFT_PTR);
globalconf.cursor[CurResize] = create_font_cursor(CURSOR_SIZING); globalconf.cursor[CurResize] = create_font_cursor(CURSOR_SIZING);
globalconf.cursor[CurMove] = create_font_cursor(CURSOR_FLEUR); 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 */ /* select for events */
const uint32_t change_win_vals[] = const uint32_t change_win_vals[] =
{ {
@ -433,8 +407,7 @@ main(int argc, char **argv)
change_win_vals); change_win_vals);
ewmh_set_supported_hints(screen_nbr); ewmh_set_supported_hints(screen_nbr);
/* call this to at least grab root window clicks */ /* call this to at least grab root window clicks */
window_root_grabbuttons(screen_nbr); window_root_grabbuttons();
window_root_grabkeys(screen_nbr);
} }
/* scan existing windows */ /* scan existing windows */
@ -450,7 +423,6 @@ main(int argc, char **argv)
set_enter_notify_event_handler(globalconf.evenths, event_handle_enternotify, NULL); set_enter_notify_event_handler(globalconf.evenths, event_handle_enternotify, NULL);
set_expose_event_handler(globalconf.evenths, event_handle_expose, NULL); set_expose_event_handler(globalconf.evenths, event_handle_expose, NULL);
set_key_press_event_handler(globalconf.evenths, event_handle_keypress, 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_map_request_event_handler(globalconf.evenths, event_handle_maprequest, NULL);
set_property_notify_event_handler(globalconf.evenths, event_handle_propertynotify, NULL); set_property_notify_event_handler(globalconf.evenths, event_handle_propertynotify, NULL);
set_unmap_notify_event_handler(globalconf.evenths, event_handle_unmapnotify, NULL); set_unmap_notify_event_handler(globalconf.evenths, event_handle_unmapnotify, NULL);
@ -519,7 +491,7 @@ main(int argc, char **argv)
eprint("select failed\n"); eprint("select failed\n");
} }
if(csfd >= 0 && FD_ISSET(csfd, &rd)) 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: case -1:
warn("error reading UNIX domain socket: %s\n", strerror(errno)); warn("error reading UNIX domain socket: %s\n", strerror(errno));
@ -531,7 +503,7 @@ main(int argc, char **argv)
if(r >= ssizeof(buf)) if(r >= ssizeof(buf))
break; break;
buf[r] = '\0'; buf[r] = '\0';
__uicb_parsecmd(buf); luaA_docmd(buf);
statusbar_refresh(); statusbar_refresh();
layout_refresh(); layout_refresh();
} }

View File

@ -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

View File

@ -8,23 +8,7 @@ awesomerc - Configuration file for the 'awesome window manager'
SYNOPSIS SYNOPSIS
-------- --------
.......................... None.
<section> [title]
{
<option> = <value>
<section> [title]
{
<option> = <value>
...
}
...
}
<option> = <value>
include(file.conf)
..........................
DESCRIPTION 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. 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 SEE ALSO
-------- --------
awesome(1) awesome-client(1) awesome-menu(1) awesome-message(1) awesome(1) awesome-client(1)
AUTHORS AUTHORS
------- -------
This man page was written by Julien Danjou <julien@danjou.info>, Marco Candrian <mac@calmar.ws> This man page was written by Julien Danjou <julien@danjou.info>.
and Chris Ciulla <chris.ciulla@gmail.com> (Simple Examples).
WWW WWW
--- ---

View File

@ -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

191
awesomerc.lua.in Normal file
View File

@ -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)

223
awful.lua Normal file
View File

@ -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

View File

@ -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])))

View File

@ -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

View File

@ -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)

790
client.c
View File

@ -28,13 +28,13 @@
#include "client.h" #include "client.h"
#include "tag.h" #include "tag.h"
#include "rules.h"
#include "window.h" #include "window.h"
#include "focus.h" #include "focus.h"
#include "ewmh.h" #include "ewmh.h"
#include "widget.h" #include "widget.h"
#include "screen.h" #include "screen.h"
#include "titlebar.h" #include "titlebar.h"
#include "lua.h"
#include "layouts/floating.h" #include "layouts/floating.h"
#include "common/markup.h" #include "common/markup.h"
#include "common/xutil.h" #include "common/xutil.h"
@ -221,13 +221,13 @@ client_updatetitle(client_t *c)
static void static void
client_unfocus(client_t *c) client_unfocus(client_t *c)
{ {
if(globalconf.screens[c->screen].opacity_unfocused != -1) /* Call hook */
window_settrans(c->win, globalconf.screens[c->screen].opacity_unfocused); client_t **lc = lua_newuserdata(globalconf.L, sizeof(client_t *));
else if(globalconf.screens[c->screen].opacity_focused != -1) *lc = c;
window_settrans(c->win, -1); luaA_settype(globalconf.L, "client");
luaA_dofunction(globalconf.L, globalconf.hooks.unfocus, 1);
focus_add_client(NULL); 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); widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
titlebar_draw(c); titlebar_draw(c);
} }
@ -242,8 +242,8 @@ client_ban(client_t *c)
client_unfocus(c); client_unfocus(c);
xcb_unmap_window(globalconf.connection, c->win); xcb_unmap_window(globalconf.connection, c->win);
window_setstate(c->win, XCB_WM_ICONIC_STATE); window_setstate(c->win, XCB_WM_ICONIC_STATE);
if(c->titlebar.position && c->titlebar.sw) if(c->titlebar.position && c->titlebar_sw)
xcb_unmap_window(globalconf.connection, c->titlebar.sw->window); xcb_unmap_window(globalconf.connection, c->titlebar_sw->window);
} }
/** Give focus to client, or to first client if c is NULL /** Give focus to client, or to first client if c is NULL
@ -255,6 +255,7 @@ client_ban(client_t *c)
bool bool
client_focus(client_t *c, int screen, bool raise) client_focus(client_t *c, int screen, bool raise)
{ {
client_t **lc;
int phys_screen; int phys_screen;
/* if c is NULL or invisible, take next client in the focus history */ /* 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); client_unban(c);
/* save sel in focus history */ /* save sel in focus history */
focus_add_client(c); 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); titlebar_draw(c);
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT, xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT,
c->win, XCB_CURRENT_TIME); 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); ewmh_update_net_active_window(phys_screen);
widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS); 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; return true;
} }
@ -326,13 +326,13 @@ client_stack(client_t *c)
if(client->layer == layer && client != c if(client->layer == layer && client != c
&& client_isvisible_anyscreen(client)) && client_isvisible_anyscreen(client))
{ {
if(client->titlebar.position && client->titlebar.sw) if(client->titlebar.position && client->titlebar_sw)
{ {
xcb_configure_window(globalconf.connection, xcb_configure_window(globalconf.connection,
client->titlebar.sw->window, client->titlebar_sw->window,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals); 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_configure_window(globalconf.connection, client->win,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
@ -342,12 +342,12 @@ client_stack(client_t *c)
} }
if(c->layer == layer) 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, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals); 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_configure_window(globalconf.connection, c->win,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
@ -365,12 +365,10 @@ client_stack(client_t *c)
void void
client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen) 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; xcb_window_t trans;
bool rettrans, retloadprops; bool rettrans, retloadprops;
uint32_t config_win_val;
tag_t *tag; tag_t *tag;
rule_t *rule;
xcb_size_hints_t *u_size_hints; xcb_size_hints_t *u_size_hints;
c = p_new(client_t, 1); 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->newcomer = true;
c->layer = c->oldlayer = LAYER_TILE; 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 */ /* update window title */
client_updatetitle(c); 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 */ /* Then check clients hints */
ewmh_check_client_hints(c); 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 */ /* check for transient and set tags like its parent */
if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans)) if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans))
&& (t = client_get_bywin(globalconf.clients, 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) if(rettrans || c->isfixed)
client_setfloating(c, true, c->layer != LAYER_TILE ? c->layer : LAYER_FLOAT); client_setfloating(c, true, c->layer != LAYER_TILE ? c->layer : LAYER_FLOAT);
/* titlebar init */ if(globalconf.floating_placement
if(rule && rule->titlebar.position != Auto) && !retloadprops
c->titlebar = rule->titlebar;
titlebar_init(c);
if(!retloadprops
&& u_size_hints && u_size_hints
&& !(xcb_size_hints_get_flags(u_size_hints) & (XCB_SIZE_US_POSITION_HINT | && !(xcb_size_hints_get_flags(u_size_hints) & (XCB_SIZE_US_POSITION_HINT |
XCB_SIZE_P_POSITION_HINT))) XCB_SIZE_P_POSITION_HINT)))
{ {
if(c->isfloating && !c->ismax) 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 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); 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[] = { const uint32_t select_input_val[] = {
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE |
XCB_EVENT_MASK_ENTER_WINDOW }; 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); window_setshape(c->win, c->phys_screen);
} }
/* attach to the stack */ client_list_push(&globalconf.clients, c);
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);
}
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
ewmh_update_net_client_list(c->phys_screen); 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 static area_t
@ -574,10 +513,10 @@ client_resize(client_t *c, area_t geometry, bool hints)
{ {
int new_screen; int new_screen;
area_t area; area_t area;
Layout *layout = layout_get_current(c->screen); LayoutArrange *layout = layout_get_current(c->screen);
bool resized = false; 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); titlebar_update_geometry(c, geometry);
geometry = titlebar_geometry_remove(&c->titlebar, 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 /* save the floating geometry if the window is floating but not
* maximized */ * maximized */
if(c->ismoving || c->isfloating if(c->ismoving || c->isfloating
|| layout_get_current(new_screen)->arrange == layout_floating) || layout_get_current(new_screen) == layout_floating)
{ {
if(!c->ismax) if(!c->ismax)
c->f_geometry = geometry; 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, /* call it again like it was floating,
* we want it to be sticked to the window */ * 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); titlebar_update_geometry_floating(c);
return resized; return resized;
@ -717,8 +656,8 @@ client_unban(client_t *c)
{ {
xcb_map_window(globalconf.connection, c->win); xcb_map_window(globalconf.connection, c->win);
window_setstate(c->win, XCB_WM_NORMAL_STATE); window_setstate(c->win, XCB_WM_NORMAL_STATE);
if(c->titlebar.sw && c->titlebar.position != Off) if(c->titlebar_sw && c->titlebar.position != Off)
xcb_map_window(globalconf.connection, c->titlebar.sw->window); xcb_map_window(globalconf.connection, c->titlebar_sw->window);
} }
void void
@ -750,7 +689,7 @@ client_unmanage(client_t *c)
xcb_aux_sync(globalconf.connection); xcb_aux_sync(globalconf.connection);
xcb_ungrab_server(globalconf.connection); xcb_ungrab_server(globalconf.connection);
simplewindow_delete(&c->titlebar.sw); simplewindow_delete(&c->titlebar_sw);
p_delete(&c); p_delete(&c);
} }
@ -828,21 +767,6 @@ client_updatesizehints(client_t *c)
return size; 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 * char *
client_markup_parse(client_t *c, const char *str, ssize_t len) 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; 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(&current_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 /** Kill a client via a WM_DELETE_WINDOW request or XKillClient if not
* supported. * supported.
* \param c the client to kill * \param c the client to kill
@ -1089,189 +827,343 @@ client_kill(client_t *c)
xcb_kill_client(globalconf.connection, c->win); xcb_kill_client(globalconf.connection, c->win);
} }
/** Kill the currently focused client. static int
* \param screen Screen ID luaA_client_get(lua_State *L)
* \param arg unused
* \ingroup ui_callback
*/
void
uicb_client_kill(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused)))
{ {
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) if((ret = regcomp(&r, name, REG_EXTENDED)))
client_kill(sel); {
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(!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;
} }
/** Maximize the client to the given geometry. static int
* \param c the client to maximize luaA_client_mouse(lua_State *L)
* \param geometry the geometry to use for maximizing
*/
static void
client_maximize(client_t *c, area_t geometry)
{ {
if((c->ismax = !c->ismax)) size_t i, len;
int b;
Button *button;
/* 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);
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++)
{ {
/* disable titlebar */ lua_rawgeti(L, 1, i);
c->titlebar.position = Off; button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1));
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);
} }
else if(c->wasfloating)
{ button_list_push(&globalconf.buttons.client, button);
c->titlebar.position = c->titlebar.dposition;
client_setfloating(c, true, LAYER_FULLSCREEN); return 0;
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. static int
* \param screen Virtual screen number. luaA_client_visible_get(lua_State *L)
* \param arg Either "vertical", "horizontal" or nothing for both.
* \ingroup ui_callback
*/
void
uicb_client_togglemax(int screen, char *arg)
{ {
area_t area; 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) if(!globalconf.focus->client)
return; return 0;
area = screen_get_area(screen, cobj = lua_newuserdata(L, sizeof(client_t *));
globalconf.screens[screen].statusbar, *cobj = globalconf.focus->client;
&globalconf.screens[screen].padding); luaA_settype(L, "client");
if(arg && arg[0] == 'v') 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)
{ {
area.x = globalconf.focus->client->geometry.x; (*c)->border = width;
area.width = globalconf.focus->client->geometry.width; globalconf.screens[(*c)->screen].need_arrange = true;
area.height -= 2 * globalconf.focus->client->border; xcb_configure_window(globalconf.connection, (*c)->win,
} XCB_CONFIG_WINDOW_BORDER_WIDTH, (uint32_t *) &width);
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;
} }
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 else
{ globalconf.screens[(*c)->screen].need_arrange = true;
area.width -= 2 * globalconf.focus->client->border;
area.height -= 2 * globalconf.focus->client->border; return 0;
}
client_maximize(globalconf.focus->client, area);
} }
/** Give focus to the next or previous visible client in the stack. static int
* Argument mus be a relative number of windows to give focus after current one. luaA_client_screen_set(lua_State *L)
* 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; client_t **c = luaL_checkudata(L, 1, "client");
int i; int screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen);
if(arg && (i = atoi(arg))) move_client_to_screen(*c, screen, true);
next = client_find_visible(globalconf.focus->client, i); return 0;
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. static int
* Argument must be none to toggle, or a boolean value to set. luaA_client_screen_get(lua_State *L)
* \param screen Virtual screen number.
* \param arg
* \ingroup ui_callback
*/
void
uicb_client_setfloating(int screen __attribute__ ((unused)), char *arg)
{ {
bool floating; client_t **c = luaL_checkudata(L, 1, "client");
lua_pushnumber(L, 1 + (*c)->screen);
return 1;
}
if(!globalconf.focus->client)
return;
if(!arg) static int
floating = !globalconf.focus->client->isfloating; 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 else
floating = a_strtobool(arg); untag_client(*c, *tag);
return 0;
client_setfloating(globalconf.focus->client, !globalconf.focus->client->isfloating,
globalconf.focus->client->layer == LAYER_FLOAT ? LAYER_TILE : LAYER_FLOAT);
} }
/** Toggle the scratch client attribute on the focused client. static int
* \param screen screen number luaA_client_istagged(lua_State *L)
* \param arg unused argument
* \ingroup ui_callback
*/
void
uicb_client_setscratch(int screen, char *arg __attribute__ ((unused)))
{ {
if(!globalconf.focus->client) client_t **c = luaL_checkudata(L, 1, "client");
return; tag_t **tag = luaL_checkudata(L, 2, "tag");
lua_pushboolean(L, is_client_tagged(*c, *tag));
if(globalconf.scratch.client == globalconf.focus->client) return 1;
globalconf.scratch.client = NULL;
else
globalconf.scratch.client = globalconf.focus->client;
widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS | WIDGET_CACHE_TAGS);
globalconf.screens[screen].need_arrange = true;
} }
void static int
uicb_client_redraw(int screen __attribute__ ((unused)), luaA_client_coords_get(lua_State *L)
char *arg __attribute__ ((unused)))
{ {
if(!globalconf.focus->client) client_t **c = luaL_checkudata(L, 1, "client");
return; lua_newtable(L);
lua_pushnumber(L, (*c)->geometry.width);
/* Use unmap/map ATM but it would be better to used SendEvent, lua_setfield(L, -2, "width");
* however the client doesn't seem to handle it... */ lua_pushnumber(L, (*c)->geometry.height);
xcb_unmap_window(globalconf.connection, globalconf.focus->client->win); lua_setfield(L, -2, "height");
xcb_map_window(globalconf.connection, globalconf.focus->client->win); lua_pushnumber(L, (*c)->geometry.x);
lua_setfield(L, -2, "x");
lua_pushnumber(L, (*c)->geometry.y);
lua_setfield(L, -2, "y");
return 1;
} }
/** Toggle the scratch client's visibility. static int
* \param screen screen number luaA_client_coords_set(lua_State *L)
* \param arg unused argument
* \ingroup ui_callback
*/
void
uicb_client_togglescratch(int screen, char *arg __attribute__ ((unused)))
{ {
if(globalconf.scratch.client) client_t **c = luaL_checkudata(L, 1, "client");
area_t geometry;
if((*c)->isfloating || layout_get_current((*c)->screen) == layout_floating)
{ {
globalconf.scratch.isvisible = !globalconf.scratch.isvisible; luaA_checktable(L, 2);
if(globalconf.scratch.isvisible) geometry.x = luaA_getopt_number(L, 2, "x", (*c)->geometry.x);
client_focus(globalconf.scratch.client, screen, true); geometry.y = luaA_getopt_number(L, 2, "y", (*c)->geometry.y);
globalconf.screens[globalconf.scratch.client->screen].need_arrange = true; geometry.width = luaA_getopt_number(L, 2, "width", (*c)->geometry.width);
widget_invalidate_cache(globalconf.scratch.client->screen, WIDGET_CACHE_CLIENTS); 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -43,18 +43,6 @@ void client_saveprops(client_t *);
void client_kill(client_t *); void client_kill(client_t *);
void client_setfloating(client_t *, bool, layer_t); void client_setfloating(client_t *, bool, layer_t);
char * client_markup_parse(client_t *, const char *, ssize_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) DO_SLIST(client_t, client, p_delete)

View File

@ -24,601 +24,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "rules.h"
#include "common/configopts.h" #include "common/configopts.h"
#include "common/util.h"
#define AWESOME_CONFIG_FILE ".awesomerc" #define AWESOME_CONFIG_FILE ".awesomerc.lua"
#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()
};
/** Return default configuration file path /** Return default configuration file path
* \return path to the default configuration file * \return path to the default configuration file
@ -640,144 +49,4 @@ config_file(void)
return confpath; 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -22,19 +22,7 @@
#ifndef AWESOME_COMMON_CONFIGOPTS_H #ifndef AWESOME_COMMON_CONFIGOPTS_H
#define AWESOME_COMMON_CONFIGOPTS_H #define AWESOME_COMMON_CONFIGOPTS_H
#include <confuse.h>
cfg_t * cfg_new(void);
char * config_file(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 #endif

View File

@ -141,7 +141,7 @@ draw_context_new(xcb_connection_t *conn, int phys_screen, int width, int height,
* \return a new font * \return a new font
*/ */
font_t * 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; cairo_surface_t *surface;
xcb_screen_t *s = xcb_aux_get_screen(conn, phys_screen); xcb_screen_t *s = xcb_aux_get_screen(conn, phys_screen);
@ -213,7 +213,11 @@ typedef struct
} margin; } margin;
bool has_bg_color; bool has_bg_color;
xcolor_t bg_color; xcolor_t bg_color;
shadow_t shadow; struct
{
int offset;
xcolor_t color;
} shadow;
} draw_parser_data_t; } draw_parser_data_t;
static bool static bool
@ -278,13 +282,13 @@ draw_text_markup_expand(draw_parser_data_t *data,
* \param style A pointer to the style to use. * \param style A pointer to the style to use.
*/ */
void 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; int x, y;
ssize_t len, olen; ssize_t len, olen;
char *buf = NULL, *utf8 = NULL; char *buf = NULL, *utf8 = NULL;
PangoRectangle ext; PangoRectangle ext;
shadow_t shadow;
draw_parser_data_t parser_data; draw_parser_data_t parser_data;
if(!(len = a_strlen(text))) 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) if(parser_data.has_bg_color)
draw_rectangle(ctx, area, 1.0, true, parser_data.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_layout_set_width(ctx->layout,
pango_units_from_double(area.width 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))); + parser_data.margin.right)));
pango_layout_set_ellipsize(ctx->layout, PANGO_ELLIPSIZE_END); pango_layout_set_ellipsize(ctx->layout, PANGO_ELLIPSIZE_END);
pango_layout_set_markup(ctx->layout, buf, len); 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); pango_layout_get_pixel_extents(ctx->layout, NULL, &ext);
x = area.x + parser_data.margin.left; x = area.x + parser_data.margin.left;
/* + 1 is added for rounding, so that in any case of doubt we rather draw /* + 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 * the text 1px lower than too high which usually results in a better type
* face */ * face */
y = area.y + (ctx->height - style->font->height + 1) / 2; y = area.y + (ctx->height - font->height + 1) / 2;
switch(parser_data.align) 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; break;
} }
p_clear(&shadow, 1);
if(parser_data.shadow.offset) 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, cairo_set_source_rgb(ctx->cr,
shadow.color.red / 65535.0, parser_data.shadow.color.red / 65535.0,
shadow.color.green / 65535.0, parser_data.shadow.color.green / 65535.0,
shadow.color.blue / 65535.0); parser_data.shadow.color.blue / 65535.0);
cairo_move_to(ctx->cr, x + shadow.offset, y + shadow.offset); 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_update_layout(ctx->cr, ctx->layout);
pango_cairo_show_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_move_to(ctx->cr, x, y);
cairo_set_source_rgb(ctx->cr, cairo_set_source_rgb(ctx->cr,
style->fg.red / 65535.0, fg->red / 65535.0,
style->fg.green / 65535.0, fg->green / 65535.0,
style->fg.blue / 65535.0); fg->blue / 65535.0);
pango_cairo_update_layout(ctx->cr, ctx->layout); pango_cairo_update_layout(ctx->cr, ctx->layout);
pango_cairo_show_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; 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, /** Remove a area from a list of them,
* spliting the space between several area that can overlap * spliting the space between several area that can overlap
* \param head list head * \param head list head

View File

@ -35,7 +35,7 @@
typedef enum typedef enum
{ {
AlignLeft, AlignLeft = 0,
AlignRight, AlignRight,
AlignCenter, AlignCenter,
AlignFlex, AlignFlex,
@ -88,27 +88,6 @@ typedef struct
int height; int height;
} font_t; } 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 typedef struct
{ {
xcb_connection_t *connection; xcb_connection_t *connection;
@ -132,17 +111,20 @@ draw_context_delete(draw_context_t **ctx)
{ {
if(*ctx) if(*ctx)
{ {
g_object_unref((*ctx)->layout); if((*ctx)->layout)
cairo_surface_destroy((*ctx)->surface); g_object_unref((*ctx)->layout);
cairo_destroy((*ctx)->cr); if((*ctx)->surface)
cairo_surface_destroy((*ctx)->surface);
if((*ctx)->cr)
cairo_destroy((*ctx)->cr);
p_delete(ctx); 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_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(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 *); 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 *); area_t draw_text_extents(xcb_connection_t *, int, font_t *, const char *);
alignment_t draw_align_get_from_str(const char *); alignment_t draw_align_get_from_str(const char *);
bool draw_color_new(xcb_connection_t *, int, const char *, xcolor_t *); 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 *); void area_list_remove(area_t **, area_t *);

View File

@ -159,7 +159,7 @@
return NULL; \ 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) \ if(item == *list) \
*list = item->next; \ *list = item->next; \
@ -169,7 +169,27 @@
item->next->prev = item->prev; \ item->next->prev = item->prev; \
item->next = NULL; \ item->next = NULL; \
item->prev = 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 #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

39
common/refcount.h Normal file
View File

@ -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

View File

@ -175,7 +175,8 @@ fuzzy_get_from_str(const char *str)
* *
* \return minimum of \c src \e length and \c l. * \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); 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 * \return \c src \e length. If this value is \>= \c n then the copy was
* truncated. * 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); ssize_t len = a_strlen(src);
@ -213,4 +215,28 @@ ssize_t a_strcpy(char *dst, ssize_t n, const char *src)
return len; 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -284,6 +284,7 @@ char * position_to_str(position_t);
fuzzy_t fuzzy_get_from_str(const char *); fuzzy_t fuzzy_get_from_str(const char *);
double compute_new_value_from_arg(const char *, double); double compute_new_value_from_arg(const char *, double);
void *name_func_lookup(const char *, const name_func_link_t *); void *name_func_lookup(const char *, const name_func_link_t *);
void a_exec(const char *);
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -505,4 +505,79 @@ xutil_delete_error(xutil_error_t *err)
p_delete(&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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -158,6 +158,8 @@ typedef struct
xutil_error_t *xutil_get_error(const xcb_generic_error_t *); xutil_error_t *xutil_get_error(const xcb_generic_error_t *);
void xutil_delete_error(xutil_error_t *); void xutil_delete_error(xutil_error_t *);
xcb_keysym_t xutil_keymask_fromstr(const char *);
unsigned int xutil_button_fromint(int);
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

524
config.c
View File

@ -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

View File

@ -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

View File

@ -1,6 +1,8 @@
# -*- Autoconf -*- # -*- Autoconf -*-
# Process this file with autoreconf to produce a configure script. # Process this file with autoreconf to produce a configure script.
m4_include(as_ac_expand.m4)
AC_PREREQ(2.61) AC_PREREQ(2.61)
dnl Each time you want an updated version number for your build, you need to dnl Each time you want an updated version number for your build, you need to
dnl (re-)run autoreconf. 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$ASCIIDOC" = "x" && AC_PATH_PROG([ASCIIDOC], [asciidoc], [:])
test "x$XMLTO" = "x" && AC_PATH_PROG([XMLTO], [xmlto], [:]) 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$DOXYGEN" = "x" && AC_PATH_PROG([DOXYGEN], [doxygen], [:])
test "x$ASCIIDOC" = "x:" && AC_MSG_WARN([awesome man page generation requires asciidoc]) 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$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]) test "x$DOXYGEN" = "x:" && AC_MSG_WARN([awesome developer doc generation requires doxygen])
AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$ASCIIDOC" != "x:"]) AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$ASCIIDOC" != "x:"])
AM_CONDITIONAL([HAVE_XMLTO], [test "x$XMLTO" != "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:"]) AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != "x:"])
xmlto_man_works=no 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`]) AS_IF([test "x$WHOAMI" = "xfalse"], [aw_whoami="???"], [aw_whoami=`$WHOAMI`])
AC_DEFINE_UNQUOTED([AWESOME_COMPILE_BY], ["$aw_whoami"], [build user]) 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. # Checks for libraries.
AC_PATH_XTRA AC_PATH_XTRA
PKG_CHECK_MODULES([pangocairo], [pangocairo],, PKG_CHECK_MODULES([pangocairo], [pangocairo],,
[AC_MSG_ERROR([awesome requires pangocairo.])]) [AC_MSG_ERROR([awesome requires pangocairo.])])
PKG_CHECK_MODULES([confuse], [libconfuse >= 2.6],, PKG_CHECK_MODULES([Lua], [lua5.1],,
[AC_MSG_ERROR([awesome requires libconfuse >= 2.6.])]) [AC_MSG_ERROR([awesome requires Lua >= 5.1.])])
PKG_CHECK_MODULES([glib], [glib-2.0],, PKG_CHECK_MODULES([glib], [glib-2.0],,
[AC_MSG_ERROR([awesome requires glib-2.0.])]) [AC_MSG_ERROR([awesome requires glib-2.0.])])
PKG_CHECK_MODULES([dbus], [dbus-1],, PKG_CHECK_MODULES([dbus], [dbus-1],,

134
event.c
View File

@ -32,8 +32,8 @@
#include "ewmh.h" #include "ewmh.h"
#include "client.h" #include "client.h"
#include "widget.h" #include "widget.h"
#include "rules.h"
#include "titlebar.h" #include "titlebar.h"
#include "lua.h"
#include "layouts/tile.h" #include "layouts/tile.h"
#include "layouts/floating.h" #include "layouts/floating.h"
#include "common/xscreen.h" #include "common/xscreen.h"
@ -46,18 +46,17 @@ extern AwesomeConf globalconf;
* \param button button number * \param button button number
* \param state modkeys state * \param state modkeys state
* \param buttons buttons list to check for * \param buttons buttons list to check for
* \param arg optional arg passed to uicb, otherwise buttons' arg are used
*/ */
static void static void
event_handle_mouse_button_press(int screen, unsigned int button, event_handle_mouse_button_press(unsigned int button,
unsigned int state, unsigned int state,
Button *buttons) Button *buttons)
{ {
Button *b; Button *b;
for(b = buttons; b; b = b->next) for(b = buttons; b; b = b->next)
if(button == b->button && CLEANMASK(state) == b->mod && b->func) if(button == b->button && CLEANMASK(state) == b->mod && b->fct)
b->func(screen, b->arg); luaA_dofunction(globalconf.L, b->fct, 0);
} }
/** Handle XButtonPressed events /** Handle XButtonPressed events
@ -70,12 +69,8 @@ event_handle_buttonpress(void *data __attribute__ ((unused)),
{ {
int screen; int screen;
client_t *c; client_t *c;
widget_t *widget; widget_node_t *w;
statusbar_t *statusbar; 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(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next) for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
@ -85,34 +80,34 @@ event_handle_buttonpress(void *data __attribute__ ((unused)),
{ {
case Top: case Top:
case Bottom: case Bottom:
for(widget = statusbar->widgets; widget; widget = widget->next) for(w = statusbar->widgets; w; w = w->next)
if(ev->event_x >= widget->area.x && ev->event_x < widget->area.x + widget->area.width if(ev->event_x >= w->area.x && ev->event_x < w->area.x + w->area.width
&& ev->event_y >= widget->area.y && ev->event_y < widget->area.y + widget->area.height) && 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; return 0;
} }
break; break;
case Right: case Right:
for(widget = statusbar->widgets; widget; widget = widget->next) for(w = statusbar->widgets; w; w = w->next)
if(ev->event_y >= widget->area.x && ev->event_y < widget->area.x + widget->area.width if(ev->event_y > w->area.x && ev->event_y < w->area.x + w->area.width
&& statusbar->sw->geometry.width - ev->event_x >= widget->area.y && statusbar->sw->geometry.width - ev->event_x >= w->area.y
&& statusbar->sw->geometry.width - ev->event_x && 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; return 0;
} }
break; break;
case Left: case Left:
for(widget = statusbar->widgets; widget; widget = widget->next) for(w = statusbar->widgets; w; w = w->next)
if(statusbar->sw->geometry.height - ev->event_y >= widget->area.x if(statusbar->sw->geometry.height - ev->event_y >= w->area.x
&& statusbar->sw->geometry.height - ev->event_y && statusbar->sw->geometry.height - ev->event_y
< widget->area.x + widget->area.width < w->area.x + w->area.width
&& ev->event_x >= widget->area.y && ev->event_x >= w->area.y
&& ev->event_x < widget->area.y + widget->area.height) && ev->event_x < w->area.y + w->area.height)
{ {
widget->button_press(widget, ev); w->widget->button_press(w, statusbar, ev);
return 0; return 0;
} }
break; break;
@ -125,14 +120,14 @@ event_handle_buttonpress(void *data __attribute__ ((unused)),
/* Check for titlebar first */ /* Check for titlebar first */
for(c = globalconf.clients; c; c = c->next) 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)) if(!client_focus(c, c->screen, true))
client_stack(c); client_stack(c);
if(CLEANMASK(ev->state) == XCB_NO_SYMBOL if(CLEANMASK(ev->state) == XCB_NO_SYMBOL
&& ev->detail == XCB_BUTTON_INDEX_1) && ev->detail == XCB_BUTTON_INDEX_1)
window_grabbuttons(c->win, c->phys_screen); 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); globalconf.buttons.titlebar);
return 0; return 0;
} }
@ -148,18 +143,14 @@ event_handle_buttonpress(void *data __attribute__ ((unused)),
window_grabbuttons(c->win, c->phys_screen); window_grabbuttons(c->win, c->phys_screen);
} }
else 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 else
for(screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(connection)); screen++) for(screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(connection)); screen++)
if(xcb_aux_get_screen(connection, screen)->root == ev->event if(xcb_aux_get_screen(connection, screen)->root == ev->event)
&& (qr = xcb_query_pointer_reply(connection, qc, NULL)))
{ {
screen = screen_get_bycoord(globalconf.screens_info, screen, qr->root_x, qr->root_y); event_handle_mouse_button_press(ev->detail, ev->state,
event_handle_mouse_button_press(screen, ev->detail, ev->state,
globalconf.buttons.root); globalconf.buttons.root);
p_delete(&qr);
return 0; return 0;
} }
@ -193,7 +184,7 @@ event_handle_configurerequest(void *data __attribute__ ((unused)),
if(geometry.x != c->geometry.x || geometry.y != c->geometry.y if(geometry.x != c->geometry.x || geometry.y != c->geometry.y
|| geometry.width != c->geometry.width || geometry.height != c->geometry.height) || 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); client_resize(c, geometry, false);
else else
{ {
@ -275,7 +266,7 @@ event_handle_configurenotify(void *data __attribute__ ((unused)),
&& (ev->width != screen->width_in_pixels && (ev->width != screen->width_in_pixels
|| ev->height != screen->height_in_pixels)) || ev->height != screen->height_in_pixels))
/* it's not that we panic, but restart */ /* it's not that we panic, but restart */
uicb_restart(0, NULL); a_exec(globalconf.argv);
return 0; return 0;
} }
@ -303,10 +294,10 @@ event_handle_destroynotify(void *data __attribute__ ((unused)),
*/ */
int int
event_handle_enternotify(void *data __attribute__ ((unused)), 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; client_t *c, **lc;
int screen;
if(ev->mode != XCB_NOTIFY_MODE_NORMAL if(ev->mode != XCB_NOTIFY_MODE_NORMAL
|| (ev->root_x == globalconf.pointer_x || (ev->root_x == globalconf.pointer_x
@ -314,7 +305,7 @@ event_handle_enternotify(void *data __attribute__ ((unused)),
return 0; return 0;
for(c = globalconf.clients; c; c = c->next) 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; break;
if(c || (c = client_get_bywin(globalconf.clients, ev->event))) 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_x = ev->root_x;
globalconf.pointer_y = ev->root_y; globalconf.pointer_y = ev->root_y;
if(globalconf.screens[c->screen].sloppy_focus) lc = lua_newuserdata(globalconf.L, sizeof(client_t *));
client_focus(c, c->screen, *lc = c;
globalconf.screens[c->screen].sloppy_focus_raise); luaA_settype(globalconf.L, "client");
luaA_dofunction(globalconf.L, globalconf.hooks.mouseover, 1);
} }
else else
for(screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(connection)); screen++) window_root_grabbuttons();
if(ev->event == xcb_aux_get_screen(connection, screen)->root)
{
window_root_grabbuttons(screen);
return 0;
}
return 0; return 0;
} }
@ -365,9 +352,9 @@ event_handle_expose(void *data __attribute__ ((unused)),
} }
for(c = globalconf.clients; c; c = c->next) 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; return 0;
} }
} }
@ -381,53 +368,18 @@ event_handle_expose(void *data __attribute__ ((unused)),
*/ */
int int
event_handle_keypress(void *data __attribute__ ((unused)), 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; xcb_keysym_t keysym;
keybinding_t *k; 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); keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, ev->detail, 0);
for(k = globalconf.keys; k; k = k->next) for(k = globalconf.keys; k; k = k->next)
if(((k->keycode && ev->detail == k->keycode) || (k->keysym && keysym == k->keysym)) if(((k->keycode && ev->detail == k->keycode) || (k->keysym && keysym == k->keysym))
&& k->func && CLEANMASK(k->mod) == CLEANMASK(ev->state)) && k->fct && CLEANMASK(k->mod) == CLEANMASK(ev->state))
k->func(screen, k->arg); luaA_dofunction(globalconf.L, k->fct, 0);
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);
return 0; return 0;
} }
@ -594,7 +546,7 @@ event_handle_randr_screen_change_notify(void *data __attribute__ ((unused)),
* XRenderSetSubpixelOrder(dpy, snum, scevent->subpixel_order); * XRenderSetSubpixelOrder(dpy, snum, scevent->subpixel_order);
*/ */
uicb_restart(0, NULL); a_exec(globalconf.argv);
return 0; return 0;
} }

View File

@ -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_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_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_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_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_propertynotify(void *, xcb_connection_t *, xcb_property_notify_event_t *);
int event_handle_unmapnotify(void *, xcb_connection_t *, xcb_unmap_notify_event_t *); int event_handle_unmapnotify(void *, xcb_connection_t *, xcb_unmap_notify_event_t *);

18
ewmh.c
View File

@ -281,7 +281,11 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
/* restore geometry */ /* restore geometry */
geometry = c->m_geometry; geometry = c->m_geometry;
/* restore borders and titlebar */ /* 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->border = c->oldborder;
c->ismax = false; c->ismax = false;
client_setfloating(c, c->wasfloating, c->oldlayer); 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->m_geometry = c->geometry;
c->wasfloating = c->isfloating; c->wasfloating = c->isfloating;
/* disable titlebar and borders */ /* 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->oldborder = c->border;
c->border = 0; c->border = 0;
c->ismax = true; c->ismax = true;
@ -343,7 +351,11 @@ ewmh_process_window_type_atom(client_t *c, xcb_atom_t state)
c->border = 0; c->border = 0;
c->skip = true; c->skip = true;
c->isfixed = 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); client_setfloating(c, true, LAYER_ABOVE);
} }
else if (state == net_wm_window_type_dialog) else if (state == net_wm_window_type_dialog)

50
focus.c
View File

@ -99,54 +99,4 @@ focus_get_current_client(int screen)
return sel; 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -28,9 +28,6 @@ void focus_add_client(client_t *);
void focus_delete_client(client_t *); void focus_delete_client(client_t *);
client_t * focus_get_current_client(int); 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) DO_SLIST(client_node_t, client_node, p_delete)
#endif #endif

View File

@ -36,8 +36,6 @@
extern AwesomeConf globalconf; extern AwesomeConf globalconf;
#include "layoutgen.h"
/** Arrange windows following current selected layout /** Arrange windows following current selected layout
* \param screen the screen to arrange * \param screen the screen to arrange
*/ */
@ -45,7 +43,7 @@ static void
arrange(int screen) arrange(int screen)
{ {
client_t *c; client_t *c;
Layout *curlay = layout_get_current(screen); LayoutArrange *curlay = layout_get_current(screen);
int phys_screen = screen_virttophys(screen); int phys_screen = screen_virttophys(screen);
xcb_query_pointer_cookie_t qp_c; xcb_query_pointer_cookie_t qp_c;
xcb_query_pointer_reply_t *qp_r; xcb_query_pointer_reply_t *qp_r;
@ -59,24 +57,19 @@ arrange(int screen)
client_ban(c); client_ban(c);
} }
curlay->arrange(screen); if(curlay)
curlay(screen);
for(c = globalconf.clients; c; c = c->next) for(c = globalconf.clients; c; c = c->next)
if(c->newcomer && client_isvisible(c, screen)) if(c->newcomer && client_isvisible(c, screen))
{ {
c->newcomer = false; c->newcomer = false;
client_unban(c); 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 /* if we have a valid client that could be focused but currently no window
* are focused, then set the focus on this 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); client_focus(c, screen, true);
qp_c = xcb_query_pointer_unchecked(globalconf.connection, 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 = 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) 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_x = qp_r->root_x;
globalconf.pointer_y = qp_r->root_y; globalconf.pointer_y = qp_r->root_y;
@ -117,62 +110,21 @@ layout_refresh(void)
return arranged; return arranged;
} }
/** Get current layout used on screen /** Get current layout used on screen.
* \param screen screen id * \param screen Virtual screen number.
* \return layout used on that screen * \return layout used on that screen
*/ */
Layout * LayoutArrange *
layout_get_current(int screen) layout_get_current(int screen)
{ {
LayoutArrange *l = NULL;
tag_t **curtags = tags_get_current(screen); tag_t **curtags = tags_get_current(screen);
Layout *l = curtags[0]->layout;
if(curtags[0])
l = curtags[0]->layout;
p_delete(&curtags); p_delete(&curtags);
return l; 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -22,26 +22,13 @@
#ifndef AWESOME_LAYOUT_H #ifndef AWESOME_LAYOUT_H
#define AWESOME_LAYOUT_H #define AWESOME_LAYOUT_H
#include "uicb.h"
#include "common/list.h" #include "common/list.h"
#include "common/util.h" #include "common/util.h"
typedef void (LayoutArrange)(int); typedef void (LayoutArrange)(int);
typedef struct Layout Layout; LayoutArrange * layout_get_current(int);
struct Layout
{
char *image;
LayoutArrange *arrange;
Layout *prev, *next;
};
DO_SLIST(Layout, layout, p_delete)
int layout_refresh(void); int layout_refresh(void);
Layout * layout_get_current(int);
uicb_t uicb_tag_setlayout;
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -81,7 +81,7 @@ layout_fibonacci(int screen, int shape)
} }
geometry.width -= 2 * c->border; geometry.width -= 2 * c->border;
geometry.height -= 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.width += 2 * c->border;
geometry.height += 2 * c->border; geometry.height += 2 * c->border;
} }

View File

@ -22,7 +22,6 @@
#include <stdio.h> #include <stdio.h>
#include "screen.h" #include "screen.h"
#include "awesome.h"
#include "tag.h" #include "tag.h"
#include "client.h" #include "client.h"
#include "layouts/tile.h" #include "layouts/tile.h"
@ -30,99 +29,6 @@
extern AwesomeConf globalconf; 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 static void
_tile(int screen, const position_t position) _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.width = mw - 2 * c->border;
geometry.height = mh - 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 else
{ {
@ -257,7 +163,7 @@ _tile(int screen, const position_t position)
if(position == Bottom) if(position == Bottom)
geometry.y += mh; geometry.y += mh;
} }
client_resize(c, geometry, globalconf.screens[screen].resize_hints); client_resize(c, geometry, globalconf.resize_hints);
} }
i++; i++;
} }

View File

@ -30,9 +30,5 @@ LayoutArrange layout_tileleft;
LayoutArrange layout_tilebottom; LayoutArrange layout_tilebottom;
LayoutArrange layout_tiletop; LayoutArrange layout_tiletop;
uicb_t uicb_tag_setnmaster;
uicb_t uicb_tag_setncol;
uicb_t uicb_tag_setmwfact;
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

383
lua.c Normal file
View File

@ -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;
}
}

117
lua.h Normal file
View File

@ -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

153
mouse.c
View File

@ -94,10 +94,9 @@ mouse_snapclienttogeometry_inside(area_t geometry, area_t snap_geometry, int sna
* \return geometry to set to the client * \return geometry to set to the client
*/ */
static area_t static area_t
mouse_snapclient(client_t *c, area_t geometry) mouse_snapclient(client_t *c, area_t geometry, int snap)
{ {
client_t *snapper; client_t *snapper;
int snap = globalconf.screens[c->screen].snap;
area_t snapper_geometry; area_t snapper_geometry;
area_t screen_geometry = area_t screen_geometry =
screen_get_area(c->screen, screen_get_area(c->screen,
@ -117,8 +116,7 @@ mouse_snapclient(client_t *c, area_t geometry)
snapper_geometry = snapper->geometry; snapper_geometry = snapper->geometry;
snapper_geometry.width += 2 * c->border; snapper_geometry.width += 2 * c->border;
snapper_geometry.height += 2 * c->border; snapper_geometry.height += 2 * c->border;
snapper_geometry = titlebar_geometry_add(&snapper->titlebar, snapper_geometry = titlebar_geometry_add(&snapper->titlebar, snapper_geometry);
snapper_geometry);
geometry = geometry =
mouse_snapclienttogeometry_outside(geometry, mouse_snapclienttogeometry_outside(geometry,
snapper_geometry, snapper_geometry,
@ -137,15 +135,17 @@ mouse_snapclient(client_t *c, area_t geometry)
* \param border The client border size. * \param border The client border size.
*/ */
static void static void
mouse_resizebar_draw(draw_context_t *ctx, style_t *style, mouse_resizebar_draw(draw_context_t *ctx,
simple_window_t *sw, area_t geometry, int border) simple_window_t *sw,
area_t geometry, int border)
{ {
area_t draw_geometry = { 0, 0, ctx->width, ctx->height, NULL, NULL }; area_t draw_geometry = { 0, 0, ctx->width, ctx->height, NULL, NULL };
char size[64]; char size[64];
snprintf(size, sizeof(size), "<text align=\"center\"/>%dx%d+%d+%d", snprintf(size, sizeof(size), "<text align=\"center\"/>%dx%d+%d+%d",
geometry.x, geometry.y, geometry.width, geometry.height); 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, simplewindow_move(sw,
geometry.x + ((2 * border + geometry.width) - sw->geometry.width) / 2, geometry.x + ((2 * border + geometry.width) - sw->geometry.width) / 2,
geometry.y + ((2 * border + geometry.height) - sw->geometry.height) / 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 * static simple_window_t *
mouse_resizebar_new(int phys_screen, int border, area_t geometry, 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; simple_window_t *sw;
area_t geom; area_t geom;
geom = draw_text_extents(globalconf.connection, geom = draw_text_extents(globalconf.connection,
globalconf.default_screen, globalconf.default_screen,
style->font, globalconf.font,
"0000x0000+0000+0000"); "0000x0000+0000+0000");
geom.x = geometry.x + ((2 * border + geometry.width) - geom.width) / 2; geom.x = geometry.x + ((2 * border + geometry.width) - geom.width) / 2;
geom.y = geometry.y + ((2 * border + geometry.height) - geom.height) / 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); sw->drawable);
xcb_map_window(globalconf.connection, sw->window); xcb_map_window(globalconf.connection, sw->window);
mouse_resizebar_draw(*ctx, style, sw, geometry, border); mouse_resizebar_draw(*ctx, sw, geometry, border);
return sw; return sw;
} }
/** Move the focused window with the mouse. /** Move the focused window with the mouse.
* \param screen Screen ID
* \param arg Unused
* \ingroup ui_callback
*/ */
void void
uicb_client_movemouse(int screen, char *arg __attribute__ ((unused))) mouse_client_move(int snap)
{ {
int ocx, ocy, newscreen; int ocx, ocy, newscreen;
area_t geometry; area_t geometry;
client_t *c = globalconf.focus->client, *target; client_t *c = globalconf.focus->client, *target;
Layout *layout = layout_get_current(screen); LayoutArrange *layout;
simple_window_t *sw = NULL; simple_window_t *sw = NULL;
draw_context_t *ctx; draw_context_t *ctx;
style_t *style;
xcb_generic_event_t *ev = NULL; xcb_generic_event_t *ev = NULL;
xcb_motion_notify_event_t *ev_motion = NULL; xcb_motion_notify_event_t *ev_motion = NULL;
xcb_grab_pointer_reply_t *grab_pointer_r = NULL; xcb_grab_pointer_reply_t *grab_pointer_r = NULL;
xcb_grab_pointer_cookie_t grab_pointer_c; xcb_grab_pointer_cookie_t grab_pointer_c;
xcb_query_pointer_reply_t *query_pointer_r = NULL, *mquery_pointer_r = NULL; xcb_query_pointer_reply_t *query_pointer_r = NULL, *mquery_pointer_r = NULL;
xcb_query_pointer_cookie_t query_pointer_c; 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) if(!c)
return; return;
layout = layout_get_current(c->screen);
s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
/* Send pointer requests */ /* Send pointer requests */
grab_pointer_c = xcb_grab_pointer(globalconf.connection, false, s->root, grab_pointer_c = xcb_grab_pointer(globalconf.connection, false, s->root,
MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, 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; geometry = c->geometry;
ocx = geometry.x; ocx = geometry.x;
ocy = geometry.y; ocy = geometry.y;
style = &globalconf.screens[c->screen].styles.focus;
/* Get responses */ /* Get responses */
if(!(grab_pointer_r = xcb_grab_pointer_reply(globalconf.connection, grab_pointer_c, NULL))) 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); 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); xcb_aux_sync(globalconf.connection);
} }
@ -261,20 +259,20 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
p_delete(&ev); p_delete(&ev);
return; return;
case XCB_MOTION_NOTIFY: 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; ev_motion = (xcb_motion_notify_event_t *) ev;
geometry.x = ocx + (ev_motion->event_x - query_pointer_r->root_x); 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.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; c->ismoving = true;
client_resize(c, geometry, false); client_resize(c, geometry, false);
c->ismoving = false; c->ismoving = false;
if(sw) 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); 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. /** Resize the focused window with the mouse.
* \param screen Screen ID * \param screen Screen ID
* \param arg Unused * \param arg Unused
* \ingroup ui_callback
*/ */
void void
uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused))) mouse_client_resize(void)
{ {
int ocx = 0, ocy = 0, n; int ocx = 0, ocy = 0, n;
xcb_generic_event_t *ev = NULL; xcb_generic_event_t *ev = NULL;
xcb_motion_notify_event_t *ev_motion = NULL; xcb_motion_notify_event_t *ev_motion = NULL;
client_t *c = globalconf.focus->client; client_t *c = globalconf.focus->client;
tag_t **curtags = tags_get_current(screen); tag_t **curtags;
Layout *layout = curtags[0]->layout; LayoutArrange *layout;
area_t area = { 0, 0, 0, 0, NULL, NULL }, geometry = { 0, 0, 0, 0, NULL, NULL }; area_t area = { 0, 0, 0, 0, NULL, NULL }, geometry = { 0, 0, 0, 0, NULL, NULL };
double mwfact; double mwfact;
simple_window_t *sw = NULL; simple_window_t *sw = NULL;
draw_context_t *ctx = NULL; draw_context_t *ctx = NULL;
style_t *style;
xcb_grab_pointer_cookie_t grab_pointer_c; xcb_grab_pointer_cookie_t grab_pointer_c;
xcb_grab_pointer_reply_t *grab_pointer_r = NULL; 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 */ /* only handle floating and tiled layouts */
if(!c || c->isfixed) if(!c || c->isfixed)
return; 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; ocx = c->geometry.x;
ocy = c->geometry.y; ocy = c->geometry.y;
c->ismax = false; 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 else if (layout == layout_tile || layout == layout_tileleft
|| layout->arrange == layout_tilebottom || layout->arrange == layout_tiletop) || layout == layout_tilebottom || layout == layout_tiletop)
{ {
for(n = 0, c = globalconf.clients; c; c = c->next) for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen)) if(IS_TILED(c, c->screen))
n++; n++;
if(n <= curtags[0]->nmaster) return; 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; if(!c) return;
area = screen_get_area(screen, area = screen_get_area(c->screen,
globalconf.screens[c->screen].statusbar, globalconf.screens[c->screen].statusbar,
&globalconf.screens[c->screen].padding); &globalconf.screens[c->screen].padding);
} }
@ -380,10 +378,10 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
p_delete(&grab_pointer_r); 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, xcb_warp_pointer(globalconf.connection, XCB_NONE, c->win, 0, 0, 0, 0,
0, c->geometry.height + c->border - 1); 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, xcb_warp_pointer(globalconf.connection, XCB_NONE, c->win, 0, 0, 0, 0,
c->geometry.width + c->border - 1, 0); c->geometry.width + c->border - 1, 0);
else else
@ -414,7 +412,7 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
case XCB_MOTION_NOTIFY: case XCB_MOTION_NOTIFY:
ev_motion = (xcb_motion_notify_event_t *) ev; 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) if((geometry.width = ev_motion->event_x - ocx - 2 * c->border + 1) <= 0)
geometry.width = 1; geometry.width = 1;
@ -424,26 +422,24 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
geometry.y = c->geometry.y; geometry.y = c->geometry.y;
client_resize(c, geometry, true); client_resize(c, geometry, true);
if(sw) 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); xcb_aux_sync(globalconf.connection);
} }
else if(layout->arrange == layout_tile || layout->arrange == layout_tileleft else if(layout == layout_tile || layout == layout_tileleft
|| layout->arrange == layout_tiletop || layout->arrange == layout_tilebottom) || 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; 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; 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; mwfact = (double) (ev_motion->event_y - area.y) / area.height;
else else
mwfact = 1 - (double) (ev_motion->event_y - area.y) / area.height; 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) if(fabs(curtags[0]->mwfact - mwfact) >= 0.01)
{ {
curtags[0]->mwfact = mwfact; curtags[0]->mwfact = mwfact;
globalconf.screens[screen].need_arrange = true; globalconf.screens[c->screen].need_arrange = true;
layout_refresh(); 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -22,10 +22,8 @@
#ifndef AWESOME_MOUSE_H #ifndef AWESOME_MOUSE_H
#define AWESOME_MOUSE_H #define AWESOME_MOUSE_H
#include "uicb.h" void mouse_client_move(int);
void mouse_client_resize(void);
uicb_t uicb_client_movemouse;
uicb_t uicb_client_resizemouse;
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -72,7 +72,7 @@ placement_smart(client_t *c)
area_t newgeometry = { 0, 0, 0, 0, NULL, NULL }; area_t newgeometry = { 0, 0, 0, 0, NULL, NULL };
area_t *screen_geometry, *arealist = NULL, *r; area_t *screen_geometry, *arealist = NULL, *r;
bool found = false; bool found = false;
Layout *layout; LayoutArrange *layout;
screen_geometry = p_new(area_t, 1); screen_geometry = p_new(area_t, 1);
@ -85,7 +85,7 @@ placement_smart(client_t *c)
area_list_push(&arealist, screen_geometry); area_list_push(&arealist, screen_geometry);
for(client = globalconf.clients; client; client = client->next) 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)) && client_isvisible(client, c->screen))
{ {
newgeometry = client->f_geometry; newgeometry = client->f_geometry;

109
rules.c
View File

@ -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(&reg);
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

36
rules.h
View File

@ -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

View File

@ -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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -29,8 +29,5 @@ area_t get_display_area(int, statusbar_t *, Padding *);
int screen_virttophys(int); int screen_virttophys(int);
void move_client_to_screen(client_t *, int, bool); void move_client_to_screen(client_t *, int, bool);
uicb_t uicb_screen_focus;
uicb_t uicb_client_movetoscreen;
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -32,84 +32,10 @@
extern AwesomeConf globalconf; 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 static void
statusbar_draw(statusbar_t *statusbar) statusbar_draw(statusbar_t *statusbar)
{ {
widget_t *widget; widget_node_t *w;
int left = 0, right = 0; int left = 0, right = 0;
area_t rectangle = { 0, 0, 0, 0, NULL, NULL }; area_t rectangle = { 0, 0, 0, 0, NULL, NULL };
@ -121,22 +47,20 @@ statusbar_draw(statusbar_t *statusbar)
rectangle.width = statusbar->width; rectangle.width = statusbar->width;
rectangle.height = statusbar->height; rectangle.height = statusbar->height;
draw_rectangle(statusbar->ctx, rectangle, 1.0, true, 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) for(w = statusbar->widgets; w; w = w->next)
if (widget->alignment == AlignLeft) if(w->widget->align == AlignLeft)
left += widget->draw(widget, statusbar->ctx, left, (left + right)); left += w->widget->draw(w, statusbar, left, (left + right));
/* renders right widget from last to first */ /* renders right widget from last to first */
for(widget = *widget_list_last(&statusbar->widgets); for(w = *widget_node_list_last(&statusbar->widgets); w; w = w->prev)
widget; if(w->widget->align == AlignRight)
widget = widget_list_prev(&statusbar->widgets, widget)) right += w->widget->draw(w, statusbar, right, (left + right));
if (widget->alignment == AlignRight)
right += widget->draw(widget, statusbar->ctx, right, (left + right));
for(widget = statusbar->widgets; widget; widget = widget->next) for(w = statusbar->widgets; w; w = w->next)
if (widget->alignment == AlignFlex) if(w->widget->align == AlignFlex)
left += widget->draw(widget, statusbar->ctx, left, (left + right)); left += w->widget->draw(w, statusbar, left, (left + right));
switch(statusbar->position) switch(statusbar->position)
{ {
@ -158,96 +82,145 @@ statusbar_draw(statusbar_t *statusbar)
} }
void void
statusbar_preinit(statusbar_t *statusbar) statusbar_position_update(statusbar_t *statusbar, position_t position)
{
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_t *sb; statusbar_t *sb;
area_t area;
xcb_drawable_t dw; xcb_drawable_t dw;
xcb_screen_t *s = NULL; xcb_screen_t *s = NULL;
int phys_screen = screen_virttophys(statusbar->screen); bool ignore = false;
area_t area = screen_get_area(statusbar->screen,
globalconf.screens[statusbar->screen].statusbar,
&globalconf.screens[statusbar->screen].padding);
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 */ /* Top and Bottom statusbar_t have prio */
for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next) 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) switch(sb->position)
{ {
case Left: case Left:
switch(statusbar->position)
{
case Left:
area.x += statusbar->height;
break;
default:
break;
}
break;
case Right: 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; break;
default: default:
break; break;
} }
if(statusbar->width <= 0)
{
if(statusbar->position == Right || statusbar->position == Left)
statusbar->width = area.height;
else
statusbar->width = area.width;
} }
switch(statusbar->position) switch(statusbar->position)
{ {
case Right: case Right:
case Left: case Left:
statusbar->sw = statusbar->width = area.height;
simplewindow_new(globalconf.connection, phys_screen, 0, 0, statusbar->sw =
statusbar->height, statusbar->width, 0); simplewindow_new(globalconf.connection, statusbar->phys_screen, 0, 0,
break; statusbar->height, statusbar->width, 0);
default: s = xcb_aux_get_screen(globalconf.connection, statusbar->phys_screen);
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);
/* we need a new pixmap this way [ ] to render */ /* we need a new pixmap this way [ ] to render */
dw = xcb_generate_id(globalconf.connection); dw = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, xcb_create_pixmap(globalconf.connection,
s->root_depth, dw, s->root, s->root_depth, dw, s->root,
statusbar->width, statusbar->height); statusbar->width, statusbar->height);
statusbar->ctx = draw_context_new(globalconf.connection, statusbar->ctx = draw_context_new(globalconf.connection,
phys_screen, statusbar->phys_screen,
statusbar->width, statusbar->width,
statusbar->height, statusbar->height,
dw); dw);
break; break;
default: 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, statusbar->ctx = draw_context_new(globalconf.connection,
phys_screen, statusbar->phys_screen,
statusbar->width, statusbar->width,
statusbar->height, statusbar->height,
statusbar->sw->drawable); statusbar->sw->drawable);
break; 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); statusbar_draw(statusbar);
} }
@ -262,10 +235,7 @@ statusbar_refresh()
statusbar; statusbar;
statusbar = statusbar->next) statusbar = statusbar->next)
if(statusbar->need_update) if(statusbar->need_update)
{
statusbar_draw(statusbar); statusbar_draw(statusbar);
break;
}
} }
statusbar_t * statusbar_t *
@ -280,36 +250,140 @@ statusbar_getbyname(int screen, const char *name)
return NULL; return NULL;
} }
static void static int
statusbar_toggle(statusbar_t *statusbar) luaA_statusbar_eq(lua_State *L)
{ {
if(statusbar->position == Off) statusbar_t **t1 = luaL_checkudata(L, 1, "statusbar");
statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition; statusbar_t **t2 = luaL_checkudata(L, 2, "statusbar");
else lua_pushboolean(L, (*t1 == *t2));
statusbar->position = Off; return 1;
globalconf.screens[statusbar->screen].need_arrange = true;
} }
/** Toggle the statusbar on or off. static int
* Argument must be a statusbar name, or no argument for all statusbars. luaA_statusbar_position_set(lua_State *L)
* \param screen Screen ID
* \param arg statusbar name
* \ingroup ui_callback
*/
void
uicb_statusbar_toggle(int screen, char *arg)
{ {
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) if(position != (*sb)->position)
statusbar_toggle(sb); {
else (*sb)->position = position;
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next) for(s = globalconf.screens[(*sb)->screen].statusbar; s; s = s->next)
statusbar_toggle(sb); statusbar_position_update(s, s->position);
}
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next) return 0;
statusbar_position_update(sb);
} }
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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -23,15 +23,26 @@
#define AWESOME_STATUSBAR_H #define AWESOME_STATUSBAR_H
#include "structs.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_refresh(void);
void statusbar_preinit(statusbar_t *);
void statusbar_init(statusbar_t *);
statusbar_t * statusbar_getbyname(int, const char *); statusbar_t * statusbar_getbyname(int, const char *);
uicb_t uicb_statusbar_toggle; DO_RCNT(statusbar_t, statusbar, statusbar_delete)
DO_SLIST(statusbar_t, statusbar, statusbar_delete)
DO_SLIST(statusbar_t, statusbar, p_delete) DO_SLIST_UNREF(statusbar_t, statusbar, statusbar_delete)
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

192
structs.h
View File

@ -25,10 +25,13 @@
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
#include <regex.h> #include <regex.h>
#include "lua.h"
#include "layout.h" #include "layout.h"
#include "common/draw.h" #include "common/draw.h"
#include "common/swindow.h" #include "common/swindow.h"
#include "common/xscreen.h" #include "common/xscreen.h"
#include "common/refcount.h"
/** stacking layout */ /** stacking layout */
typedef enum typedef enum
@ -47,58 +50,60 @@ enum
typedef struct typedef struct
{ {
simple_window_t *sw; /** Ref count */
int refcount;
position_t position; position_t position;
position_t dposition;
alignment_t align; alignment_t align;
int width, height; int width, height;
char *text_normal, *text_focus, *text_urgent; char *text_normal, *text_focus, *text_urgent;
} titlebar_t; } titlebar_t;
/** Rule type */ static inline void
typedef struct rule_t rule_t; titlebar_delete(titlebar_t **t)
struct rule_t
{ {
char *icon; p_delete(&(*t)->text_normal);
char *xprop; p_delete(&(*t)->text_focus);
int screen; p_delete(&(*t)->text_urgent);
fuzzy_t isfloating; p_delete(t);
fuzzy_t ismaster; }
titlebar_t titlebar;
double opacity; DO_RCNT(titlebar_t, titlebar, titlebar_delete)
regex_t *prop_r;
regex_t *tags_r;
regex_t *xpropval_r;
/** Next and previous rules */
rule_t *prev, *next;
};
/** Keys bindings */ /** Keys bindings */
typedef struct keybinding_t keybinding_t; typedef struct keybinding_t keybinding_t;
struct keybinding_t struct keybinding_t
{ {
/** Key modifier */
unsigned long mod; unsigned long mod;
/** Keysym */
xcb_keysym_t keysym; xcb_keysym_t keysym;
/** Keycode */
xcb_keycode_t keycode; xcb_keycode_t keycode;
uicb_t *func; /** Lua function to execute. */
char *arg; luaA_function fct;
/** Next and previous keys */ /** Next and previous keys */
keybinding_t *prev, *next; keybinding_t *prev, *next;
}; };
DO_SLIST(keybinding_t, keybinding, p_delete)
/** Mouse buttons bindings */ /** Mouse buttons bindings */
typedef struct Button Button; typedef struct Button Button;
struct Button struct Button
{ {
/** Key modifiers */
unsigned long mod; unsigned long mod;
/** Mouse button number */
unsigned int button; unsigned int button;
uicb_t *func; /** Lua function to execute. */
char *arg; luaA_function fct;
/** Next and previous buttons */ /** Next and previous buttons */
Button *prev, *next; Button *prev, *next;
}; };
/** widget_t tell status code */ DO_SLIST(Button, button, p_delete)
/** Widget tell status code */
typedef enum typedef enum
{ {
WIDGET_NOERROR = 0, WIDGET_NOERROR = 0,
@ -110,41 +115,67 @@ typedef enum
WIDGET_ERROR_FORMAT_SECTION WIDGET_ERROR_FORMAT_SECTION
} widget_tell_status_t; } widget_tell_status_t;
/** widget_t */ /** Widget */
typedef struct widget_t widget_t; typedef struct widget_t widget_t;
typedef struct widget_node_t widget_node_t;
typedef struct statusbar_t statusbar_t; typedef struct statusbar_t statusbar_t;
struct widget_t struct widget_t
{ {
/** Ref count */
int refcount;
/** widget_t name */ /** widget_t name */
char *name; char *name;
/** Draw function */ /** Draw function */
int (*draw)(widget_t *, draw_context_t *, int, int); int (*draw)(widget_node_t *, statusbar_t *, int, int);
/** Update function */ /** Update function */
widget_tell_status_t (*tell)(widget_t *, char *, char *); widget_tell_status_t (*tell)(widget_t *, const char *, const char *);
/** ButtonPressedEvent handler */ /** ButtonPressedEvent handler */
void (*button_press)(widget_t *, xcb_button_press_event_t *); void (*button_press)(widget_node_t *, statusbar_t *, xcb_button_press_event_t *);
/** statusbar_t */
statusbar_t *statusbar;
/** Alignement */ /** Alignement */
alignment_t alignment; alignment_t align;
/** Misc private data */ /** Misc private data */
void *data; void *data;
/** true if user supplied coords */
bool user_supplied_x;
bool user_supplied_y;
/** area_t */
area_t area;
/** Buttons bindings */ /** Buttons bindings */
Button *buttons; Button *buttons;
/** Cache flags */ /** Cache flags */
int 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 */ /** Status bar */
struct statusbar_t struct statusbar_t
{ {
/** Ref count */
int refcount;
/** Window */ /** Window */
simple_window_t *sw; simple_window_t *sw;
/** statusbar_t name */ /** statusbar_t name */
@ -153,20 +184,23 @@ struct statusbar_t
int width; int width;
/** Bar height */ /** Bar height */
int height; int height;
/** Default position */
position_t dposition;
/** Bar position */ /** Bar position */
position_t position; position_t position;
/** Screen */ /** Screen */
int screen; int screen;
/** Physical screen id */ /** Physical screen id */
int phys_screen; int phys_screen;
/** widget_t list */ /** Widget list */
widget_t *widgets; widget_node_t *widgets;
/** Draw context */ /** Draw context */
draw_context_t *ctx; draw_context_t *ctx;
/** Need update */ /** Need update */
bool need_update; bool need_update;
/** Default colors */
struct
{
xcolor_t fg, bg;
} colors;
/** Next and previous statusbars */ /** Next and previous statusbars */
statusbar_t *prev, *next; statusbar_t *prev, *next;
}; };
@ -212,11 +246,14 @@ struct client_t
int phys_screen; int phys_screen;
/** True if the client is a new one */ /** True if the client is a new one */
bool newcomer; bool newcomer;
/** titlebar_t */ /** Titlebar */
titlebar_t titlebar; titlebar_t titlebar;
/** layer in the stacking order */ /** Titlebar window */
layer_t layer; simple_window_t *titlebar_sw;
layer_t oldlayer; /** Old position */
position_t titlebar_oldposition;
/** Layer in the stacking order */
layer_t layer, oldlayer;
}; };
typedef struct client_node_t client_node_t; typedef struct client_node_t client_node_t;
@ -231,16 +268,16 @@ struct client_node_t
typedef struct _tag_t tag_t; typedef struct _tag_t tag_t;
struct _tag_t struct _tag_t
{ {
/** Ref count */
int refcount;
/** Tag name */ /** Tag name */
char *name; char *name;
/** Screen */ /** Screen */
int screen; int screen;
/** true if selected */ /** true if selected */
bool selected; bool selected;
/** true if was selected before selecting others tags */
bool was_selected;
/** Current tag layout */ /** Current tag layout */
Layout *layout; LayoutArrange *layout;
/** Master width factor */ /** Master width factor */
double mwfact; double mwfact;
/** Number of master windows */ /** Number of master windows */
@ -277,43 +314,10 @@ typedef struct
typedef area_t (FloatingPlacement)(client_t *); typedef area_t (FloatingPlacement)(client_t *);
typedef struct 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() */ /** true if we need to arrange() */
bool need_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 list */
tag_t *tags; tag_t *tags;
/** Layout list */
Layout *layouts;
/** Status bar */ /** Status bar */
statusbar_t *statusbar; statusbar_t *statusbar;
/** Padding */ /** Padding */
@ -336,8 +340,6 @@ struct AwesomeConf
VirtScreen *screens; VirtScreen *screens;
/** Screens info */ /** Screens info */
screens_info_t *screens_info; screens_info_t *screens_info;
/** Rules list */
rule_t *rules;
/** Keys bindings list */ /** Keys bindings list */
keybinding_t *keys; keybinding_t *keys;
/** Mouse bindings list */ /** Mouse bindings list */
@ -369,6 +371,8 @@ struct AwesomeConf
} scratch; } scratch;
/** Path to config file */ /** Path to config file */
char *configpath; char *configpath;
/** Floating window placement algo */
FloatingPlacement *floating_placement;
/** Selected clients history */ /** Selected clients history */
client_node_t *focus; client_node_t *focus;
/** Link between tags and clients */ /** Link between tags and clients */
@ -379,6 +383,28 @@ struct AwesomeConf
int pointer_x, pointer_y; int pointer_x, pointer_y;
/** Atoms cache */ /** Atoms cache */
xutil_atom_cache_t *atoms; 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 #endif

432
tag.c
View File

@ -24,11 +24,17 @@
#include "screen.h" #include "screen.h"
#include "tag.h" #include "tag.h"
#include "rules.h"
#include "client.h" #include "client.h"
#include "ewmh.h" #include "ewmh.h"
#include "widget.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; extern AwesomeConf globalconf;
/** Create a new tag. Parameteres values are checked. /** Create a new tag. Parameteres values are checked.
@ -40,7 +46,7 @@ extern AwesomeConf globalconf;
* \return a new tag with all these parameters * \return a new tag with all these parameters
*/ */
tag_t * 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; 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) if((tag->ncol = ncol) < 1)
tag->ncol = 1; tag->ncol = 1;
tag_ref(&tag);
return tag; return tag;
} }
@ -72,22 +80,7 @@ tag_append_to_screen(tag_t *tag, int screen)
tag->screen = screen; tag->screen = screen;
tag_list_append(&globalconf.screens[screen].tags, tag); tag_list_append(&globalconf.screens[screen].tags, tag);
ewmh_update_net_numbers_of_desktop(phys_screen); tag_ref(&tag);
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);
ewmh_update_net_numbers_of_desktop(phys_screen); ewmh_update_net_numbers_of_desktop(phys_screen);
ewmh_update_net_desktop_names(phys_screen); ewmh_update_net_desktop_names(phys_screen);
widget_invalidate_cache(screen, WIDGET_CACHE_TAGS); widget_invalidate_cache(screen, WIDGET_CACHE_TAGS);
@ -173,34 +166,6 @@ tag_client_with_current_selected(client_t *c)
untag_client(c, tag); 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. /** Get the current tags for the specified screen.
* Returned pointer must be p_delete'd after. * Returned pointer must be p_delete'd after.
* \param screen screen id * \param screen screen id
@ -226,123 +191,6 @@ tags_get_current(int screen)
return tags; 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. /** Set a tag to be the only one viewed.
* \param target the tag to see * \param target the tag to see
@ -400,94 +248,226 @@ tag_view_only_byindex(int screen, int dindex)
void void
tag_view(tag_t *tag, bool view) tag_view(tag_t *tag, bool view)
{ {
tag->was_selected = tag->selected;
tag->selected = view; tag->selected = view;
ewmh_update_net_current_desktop(screen_virttophys(tag->screen)); ewmh_update_net_current_desktop(screen_virttophys(tag->screen));
widget_invalidate_cache(tag->screen, WIDGET_CACHE_TAGS); widget_invalidate_cache(tag->screen, WIDGET_CACHE_TAGS);
globalconf.screens[tag->screen].need_arrange = true; globalconf.screens[tag->screen].need_arrange = true;
} }
/** View only this tag. static int
* \param screen Screen ID luaA_tag_eq(lua_State *L)
* \param arg tag to view
* \ingroup ui_callback
*/
void
uicb_tag_view(int screen, char *arg)
{ {
tag_t *tag; tag_t **t1 = luaL_checkudata(L, 1, "tag");
tag_t **t2 = luaL_checkudata(L, 2, "tag");
if(arg) lua_pushboolean(L, (*t1 == *t2));
tag_view_only_byindex(screen, atoi(arg) - 1); return 1;
else
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
tag_view(tag, true);
} }
/** View the previously selected tags. static int
* \param screen Screen ID luaA_tag_tostring(lua_State *L)
* \param arg unused
* \ingroup ui_callback
*/
void
uicb_tag_prev_selected(int screen, char *arg __attribute__ ((unused)))
{ {
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) 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. /** Create a new tag.
* \param screen Screen ID * \param L Lua state.
* \param arg unused * \return One because there's one element, a user data.
* \ingroup ui_callback
*/ */
void static int
uicb_tag_viewnext(int screen, char *arg __attribute__ ((unused))) 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); name = luaA_name_init(L);
tag_view(tag, true); 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. static int
* \param screen Screen ID luaA_tag_view(lua_State *L)
* \param arg unused
* \ingroup ui_callback
*/
void
uicb_tag_viewprev(int screen, char *arg __attribute__ ((unused)))
{ {
tag_t *tag, **curtags = tags_get_current(screen); tag_t **tag = luaL_checkudata(L, 1, "tag");
bool view = luaA_checkboolean(L, 2);
tag = tag_list_prev_cycle(&globalconf.screens[screen].tags, curtags[0]); tag_view(*tag, view);
return 0;
tag_view(curtags[0], false);
tag_view(tag, true);
p_delete(&curtags);
} }
/** Create a new tag. Argument must be the tag name. static int
* \param screen the screen id luaA_tag_isselected(lua_State *L)
* \param arg the tag name
*/
void
uicb_tag_create(int screen, char *arg)
{ {
tag_t *tag; tag_t **tag = luaL_checkudata(L, 1, "tag");
lua_pushboolean(L, (*tag)->selected);
if(!a_strlen(arg)) return 1;
return;
tag = tag_new(arg, globalconf.screens[screen].layouts, 0.5, 1, 1);
tag_append_to_screen(tag, screen);
} }
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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

26
tag.h
View File

@ -23,33 +23,35 @@
#define AWESOME_TAG_H #define AWESOME_TAG_H
#include "structs.h" #include "structs.h"
#include "common/refcount.h"
/** Check if a client is tiled */ /** Check if a client is tiled */
#define IS_TILED(client, screen) (client && !client->isfloating && !client->ismax && client_isvisible(client, screen)) #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(tag_t *, bool);
void tag_view_byindex(int, int, bool); void tag_view_byindex(int, int, bool);
void tag_push_to_screen(tag_t *, int);
tag_t ** tags_get_current(int); tag_t ** tags_get_current(int);
void tag_client(client_t *, tag_t *); void tag_client(client_t *, tag_t *);
void untag_client(client_t *, tag_t *); void untag_client(client_t *, tag_t *);
bool is_client_tagged(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_client_with_current_selected(client_t *);
void tag_view_only_byindex(int, int); void tag_view_only_byindex(int, int);
void tag_append_to_screen(tag_t *, int); void tag_append_to_screen(tag_t *, int);
uicb_t uicb_client_tag; DO_RCNT(tag_t, tag, tag_delete)
uicb_t uicb_client_toggletag; DO_SLIST(tag_t, tag, tag_delete)
uicb_t uicb_tag_toggleview; DO_SLIST_UNREF(tag_t, tag, tag_delete)
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_SLIST(tag_t, tag, p_delete)
DO_SLIST(tag_client_node_t, tag_client_node, p_delete) DO_SLIST(tag_client_node_t, tag_client_node, p_delete)
#endif #endif

View File

@ -50,35 +50,327 @@ static inline area_t
titlebar_size(client_t *c) titlebar_size(client_t *c)
{ {
return draw_text_extents(globalconf.connection, globalconf.default_screen, 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. /** Draw the titlebar content.
* We still need to update its geometry to have it placed correctly.
* \param c the client * \param c the client
*/ */
void 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) titlebar_init(client_t *c)
{ {
int width = 0, height = 0; int width = 0, height = 0;
if(!c->titlebar.height) if(!c->titlebar.height)
c->titlebar.height = MAX(MAX(draw_text_extents(globalconf.connection, globalconf.default_screen, c->titlebar.height = draw_text_extents(globalconf.connection, globalconf.default_screen,
globalconf.screens[c->screen].styles.focus.font, globalconf.font,
client_markup_parse(c, c->titlebar.text_focus, a_strlen(c->titlebar.text_focus))).height, client_markup_parse(c,
draw_text_extents(globalconf.connection, globalconf.default_screen, c->titlebar.text_focus,
globalconf.screens[c->screen].styles.normal.font, a_strlen(c->titlebar.text_focus))).height;
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);
switch(c->titlebar.position) switch(c->titlebar.position)
{ {
case Off:
return;
default: default:
c->titlebar.position = Off; c->titlebar.position = Off;
if(c->titlebar_sw)
xcb_unmap_window(globalconf.connection, c->titlebar_sw->window);
return;
return; return;
case Top: case Top:
case Bottom: case Bottom:
@ -97,411 +389,116 @@ titlebar_init(client_t *c)
width = c->titlebar.height; width = c->titlebar.height;
break; 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, c->phys_screen, 0, 0,
width, height, 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); titlebar_draw(c);
xcb_map_window(globalconf.connection, c->titlebar_sw->window);
} }
static int
/** Update the titlebar geometry for a tiled client. luaA_titlebar_new(lua_State *L)
* \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; titlebar_t **tb;
int objpos;
if(!c->titlebar.sw) luaA_checktable(L, 1);
return;
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: lua_rawgeti(L, 1, i);
return; button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1));
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); button_list_push(&globalconf.buttons.titlebar, button);
return 0;
} }
void static int
titlebar_position_set(titlebar_t *t, position_t p) luaA_titlebar_gc(lua_State *L)
{ {
if(!t->sw) titlebar_t **titlebar = luaL_checkudata(L, 1, "titlebar");
return; titlebar_unref(titlebar);
return 0;
if((t->position = p))
xcb_map_window(globalconf.connection, t->sw->window);
else
xcb_unmap_window(globalconf.connection, t->sw->window);
} }
/** Toggle the visibility of the focused window's titlebar. static int
* \param screen screen number (unused) luaA_titlebar_tostring(lua_State *L)
* \param arg unused argument
* \ingroup ui_callback
*/
void
uicb_client_toggletitlebar(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused)))
{ {
client_t *c = globalconf.focus->client; titlebar_t **p = luaL_checkudata(L, 1, "titlebar");
lua_pushfstring(L, "[titlebar udata(%p)]", *p);
if(!c || !c->titlebar.sw) return 1;
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;
} }
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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -24,15 +24,72 @@
#include "structs.h" #include "structs.h"
void titlebar_init(client_t *);
void titlebar_draw(client_t *); void titlebar_draw(client_t *);
void titlebar_update_geometry_floating(client_t *); void titlebar_update_geometry_floating(client_t *);
void titlebar_update_geometry(client_t *, area_t); void titlebar_update_geometry(client_t *, area_t);
area_t titlebar_geometry_add(titlebar_t *, area_t); void titlebar_init(client_t *);
area_t titlebar_geometry_remove(titlebar_t *, area_t);
void titlebar_position_set(titlebar_t *, position_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 #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

267
uicb.c
View File

@ -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

36
uicb.h
View File

@ -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

330
widget.c
View File

@ -23,50 +23,12 @@
#include "widget.h" #include "widget.h"
#include "statusbar.h" #include "statusbar.h"
#include "event.h" #include "event.h"
#include "lua.h"
extern AwesomeConf globalconf; extern AwesomeConf globalconf;
#include "widgetgen.h" #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. /** Compute offset for drawing the first pixel of a widget.
* \param barwidth The statusbar width. * \param barwidth The statusbar width.
* \param widgetwidth The widget width. * \param widgetwidth The widget width.
@ -93,29 +55,31 @@ widget_calculate_offset(int barwidth, int widgetwidth, int offset, int alignment
widget_t * widget_t *
widget_getbyname(statusbar_t *sb, char *name) widget_getbyname(statusbar_t *sb, char *name)
{ {
widget_t *widget; widget_node_t *widget;
for(widget = sb->widgets; widget; widget = widget->next) for(widget = sb->widgets; widget; widget = widget->next)
if(!a_strcmp(name, widget->name)) if(!a_strcmp(name, widget->widget->name))
return widget; return widget->widget;
return NULL; return NULL;
} }
/** Common function for button press event on widget. /** Common function for button press event on widget.
* It will look into configuration to find the callback function to call. * 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. * \param ev The button press event the widget received.
*/ */
static void 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; Button *b;
for(b = widget->buttons; b; b = b->next) for(b = w->widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
&& b->func) luaA_dofunction(globalconf.L, b->fct, 0);
b->func(widget->statusbar->screen, b->arg);
} }
/** Common tell function for widget, which only warn user that widget /** 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. * \return The status of the command, which is always an error in this case.
*/ */
static widget_tell_status_t static widget_tell_status_t
widget_common_tell(widget_t *widget, char *property __attribute__ ((unused)), widget_common_tell(widget_t *widget,
char *new_value __attribute__ ((unused))) const char *property __attribute__ ((unused)),
const char *new_value __attribute__ ((unused)))
{ {
warn("%s widget does not accept commands.\n", widget->name); warn("%s widget does not accept commands.\n", widget->name);
return WIDGET_ERROR_CUSTOM; return WIDGET_ERROR_CUSTOM;
@ -134,20 +99,13 @@ widget_common_tell(widget_t *widget, char *property __attribute__ ((unused)),
/** Common function for creating a widget. /** Common function for creating a widget.
* \param widget The allocated 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 void
widget_common_new(widget_t *widget, statusbar_t *statusbar, cfg_t *config) widget_common_new(widget_t *widget)
{ {
widget->statusbar = statusbar; widget->align = AlignLeft;
widget->name = a_strdup(cfg_title(config));
widget->tell = widget_common_tell; widget->tell = widget_common_tell;
widget->button_press = widget_common_button_press; 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 /** Invalidate widgets which should be refresh upon
@ -160,94 +118,238 @@ void
widget_invalidate_cache(int screen, int flags) widget_invalidate_cache(int screen, int flags)
{ {
statusbar_t *statusbar; statusbar_t *statusbar;
widget_t *widget; widget_node_t *widget;
for(statusbar = globalconf.screens[screen].statusbar; for(statusbar = globalconf.screens[screen].statusbar;
statusbar; statusbar;
statusbar = statusbar->next) statusbar = statusbar->next)
for(widget = statusbar->widgets; widget; widget = widget->next) for(widget = statusbar->widgets; widget; widget = widget->next)
if(widget->cache_flags & flags) if(widget->widget->cache_flags & flags)
{
statusbar->need_update = true; 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 void
uicb_widget_tell(int screen, char *arg) widget_invalidate_statusbar_bywidget(widget_t *widget)
{ {
int screen;
statusbar_t *statusbar; statusbar_t *statusbar;
widget_t *widget; widget_node_t *witer;
char *p, *property = NULL, *new_value;
ssize_t len; 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; widget_tell_status_t status;
if(!(len = a_strlen(arg))) property = luaL_checkstring(L, 2);
return warn("must specify a statusbar and a widget.\n"); value = luaL_checkstring(L, 3);
if(!(p = strtok(arg, " "))) switch((status = (*widget)->tell(*widget, property, value)))
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)
{ {
case WIDGET_ERROR: case WIDGET_ERROR:
warn("error changing property %s of widget %s\n", warn("error changing property %s of widget %s\n",
property, widget->name); property, (*widget)->name);
break; break;
case WIDGET_ERROR_NOVALUE: case WIDGET_ERROR_NOVALUE:
warn("error changing property %s of widget %s, no value given\n", warn("error changing property %s of widget %s, no value given\n",
property, widget->name); property, (*widget)->name);
break; break;
case WIDGET_ERROR_FORMAT_FONT: case WIDGET_ERROR_FORMAT_FONT:
warn("error changing property %s of widget %s, must be a valid font\n", warn("error changing property %s of widget %s, must be a valid font\n",
property, widget->name); property, (*widget)->name);
break; break;
case WIDGET_ERROR_FORMAT_COLOR: case WIDGET_ERROR_FORMAT_COLOR:
warn("error changing property %s of widget %s, must be a valid color\n", warn("error changing property %s of widget %s, must be a valid color\n",
property, widget->name); property, (*widget)->name);
break; break;
case WIDGET_ERROR_FORMAT_SECTION: case WIDGET_ERROR_FORMAT_SECTION:
warn("error changing property %s of widget %s, section/title not found\n", warn("error changing property %s of widget %s, section/title not found\n",
property, widget->name); property, (*widget)->name);
break; break;
case WIDGET_NOERROR: case WIDGET_NOERROR:
widget->statusbar->need_update = true; widget_invalidate_statusbar_bywidget(*widget);
break; break;
case WIDGET_ERROR_CUSTOM: case WIDGET_ERROR_CUSTOM:
break; 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -30,27 +30,21 @@
#define WIDGET_CACHE_TAGS 1<<2 #define WIDGET_CACHE_TAGS 1<<2
#define WIDGET_CACHE_ALL (WIDGET_CACHE_CLIENTS | WIDGET_CACHE_LAYOUTS | WIDGET_CACHE_TAGS) #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); void widget_invalidate_cache(int, int);
int widget_calculate_offset(int, int, int, int); int widget_calculate_offset(int, int, int, int);
void widget_calculate_alignments(widget_t *); void widget_common_new(widget_t *);
void widget_common_new(widget_t*, statusbar_t *, cfg_t *);
widget_t * widget_getbyname(statusbar_t *, char *); widget_t * widget_getbyname(statusbar_t *, char *);
void widget_invalidate_statusbar_bywidget(widget_t *);
WidgetConstructor layoutinfo_new;
WidgetConstructor taglist_new; WidgetConstructor taglist_new;
WidgetConstructor textbox_new; WidgetConstructor textbox_new;
WidgetConstructor iconbox_new; WidgetConstructor iconbox_new;
WidgetConstructor focusicon_new;
WidgetConstructor progressbar_new; WidgetConstructor progressbar_new;
WidgetConstructor graph_new; WidgetConstructor graph_new;
WidgetConstructor tasklist_new; WidgetConstructor tasklist_new;
uicb_t uicb_widget_tell;
DO_SLIST(widget_t, widget, p_delete)
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -25,7 +25,7 @@
extern AwesomeConf globalconf; extern AwesomeConf globalconf;
widget_tell_status_t 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; char *title, *setting;
int i; 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(!a_strcmp(title, data_title[i]))
{ {
if(draw_color_new(globalconf.connection, if(draw_color_new(globalconf.connection,
widget->statusbar->phys_screen, globalconf.default_screen,
setting, &color[i])) setting, &color[i]))
return WIDGET_NOERROR; return WIDGET_NOERROR;
else 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; return WIDGET_ERROR_FORMAT_SECTION;
} }
widget_tell_status_t 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; char *title, *setting;
int i; 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); color[i] = p_new(xcolor_t, 1);
} }
if(!(draw_color_new(globalconf.connection, if(!(draw_color_new(globalconf.connection,
widget->statusbar->phys_screen, globalconf.default_screen,
setting, color[i]))) setting, color[i])))
{ {
if(flag) /* restore */ if(flag) /* restore */
{ {

View File

@ -24,8 +24,8 @@
#define AWESOME_WIDGETS_COMMON_H #define AWESOME_WIDGETS_COMMON_H
#include "widget.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_for_data(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_pointer_for_data(xcolor_t **, char *, int, char **);
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -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

View File

@ -80,33 +80,31 @@ typedef struct
} Data; } Data;
static int static int
graph_draw(widget_t *widget, draw_context_t *ctx, int offset, graph_draw(widget_node_t *w, statusbar_t *statusbar, int offset,
int used __attribute__ ((unused))) int used __attribute__ ((unused)))
{ {
int margin_top; int margin_top;
int z, y, x, tmp, cur_index, test_index; int z, y, x, tmp, cur_index, test_index;
Data *d = widget->data; Data *d = w->widget->data;
area_t rectangle, pattern_area; area_t rectangle, pattern_area;
draw_context_t *ctx = statusbar->ctx;
if(!d->data_items) if(!d->data_items)
return 0; return 0;
if(!widget->user_supplied_x) w->area.x = widget_calculate_offset(statusbar->width,
widget->area.x = widget_calculate_offset(widget->statusbar->width, d->width, offset,
d->width, w->widget->align);
offset, w->area.y = 0;
widget->alignment);
if(!widget->user_supplied_y)
widget->area.y = 0;
/* box = the graph inside the rectangle */ /* box = the graph inside the rectangle */
if(!(d->box_height)) 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 */ /* draw background */
rectangle.x = widget->area.x + 1; rectangle.x = w->area.x + 1;
rectangle.y = margin_top + 1; rectangle.y = margin_top + 1;
rectangle.width = d->size; rectangle.width = d->size;
rectangle.height = d->box_height; 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) */ /* 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.y = margin_top;
rectangle.width = d->size + 2; rectangle.width = d->size + 2;
rectangle.height = d->box_height + 2; rectangle.height = d->box_height + 2;
draw_rectangle(ctx, rectangle, 1.0, false, d->bordercolor); draw_rectangle(ctx, rectangle, 1.0, false, d->bordercolor);
widget->area.width = d->width; w->area.width = d->width;
widget->area.height = widget->statusbar->height; w->area.height = statusbar->height;
return widget->area.width; return w->area.width;
} }
static widget_tell_status_t 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; Data *d = widget->data;
int i, u; int i, u;
@ -347,14 +345,14 @@ graph_tell(widget_t *widget, char *property, char *new_value)
else if(!a_strcmp(property, "bg")) else if(!a_strcmp(property, "bg"))
{ {
if(!draw_color_new(globalconf.connection, if(!draw_color_new(globalconf.connection,
widget->statusbar->phys_screen, globalconf.default_screen,
new_value, &d->bg)) new_value, &d->bg))
return WIDGET_ERROR_FORMAT_COLOR; return WIDGET_ERROR_FORMAT_COLOR;
} }
else if(!a_strcmp(property, "bordercolor")) else if(!a_strcmp(property, "bordercolor"))
{ {
if(!draw_color_new(globalconf.connection, if(!draw_color_new(globalconf.connection,
widget->statusbar->phys_screen, globalconf.default_screen,
new_value, &d->bordercolor)) new_value, &d->bordercolor))
return WIDGET_ERROR_FORMAT_COLOR; return WIDGET_ERROR_FORMAT_COLOR;
} }
@ -376,7 +374,7 @@ graph_tell(widget_t *widget, char *property, char *new_value)
} }
widget_t * widget_t *
graph_new(statusbar_t *statusbar, cfg_t *config) graph_new(alignment_t align)
{ {
widget_t *w; widget_t *w;
Data *d; Data *d;
@ -389,17 +387,18 @@ graph_new(statusbar_t *statusbar, cfg_t *config)
xcolor_t *ptmp_color_end; xcolor_t *ptmp_color_end;
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config); widget_common_new(w);
w->draw = graph_draw; w->draw = graph_draw;
w->tell = graph_tell; w->tell = graph_tell;
w->alignment = cfg_getalignment(config, "align"); w->align = align;
d = w->data = p_new(Data, 1); d = w->data = p_new(Data, 1);
d->width = cfg_getint(config, "width"); d->width = 100;
d->height = cfg_getfloat(config, "height"); d->height = 0.67;
d->size = d->width - 2; d->size = d->width - 2;
/*
if(!(d->data_items = cfg_size(config, "data"))) if(!(d->data_items = cfg_size(config, "data")))
{ {
warn("graph widget needs at least one data section\n"); 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) if(d->grow != Left && d->grow != Right)
{ {
warn("graph widget: 'grow' argument must be 'left' or 'right'\n"); warn("graph widget: 'grow' argument must be 'left' or 'right'\n");
*/
/*
d->data_items = 0; /* disable widget drawing */ d->data_items = 0; /* disable widget drawing */
return w; /* return w;
} }
d->draw_from = p_new(int, d->size); 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 */ d->values[i] = p_new(float, d->size); /* not null -> scale = true */
/* prevent: division by zero */ /* prevent: division by zero */
/*
d->current_max[i] = d->max[i] = cfg_getfloat(cfg, "max"); d->current_max[i] = d->max[i] = cfg_getfloat(cfg, "max");
d->lines[i] = p_new(int, d->size); d->lines[i] = p_new(int, d->size);
/* filter each style-typ into it's own array (for easy looping later)*/ /* filter each style-typ into it's own array (for easy looping later)*/
/*
if ((type = cfg_getstr(cfg, "draw_style"))) if ((type = cfg_getstr(cfg, "draw_style")))
{ {
if(!a_strncmp(type, "bottom", sizeof("bottom"))) 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); draw_color_new(globalconf.connection, statusbar->phys_screen, color, &d->bordercolor);
else else
d->bordercolor = tmp_color; d->bordercolor = tmp_color;
*/
return w; return w;
} }
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -32,44 +32,42 @@ typedef struct
} Data; } Data;
static int 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))) int used __attribute__ ((unused)))
{ {
Data *d = widget->data; Data *d = w->widget->data;
area_t area = draw_get_image_size(d->image); area_t area = draw_get_image_size(d->image);
/* image not valid */ /* image not valid */
if(area.width < 0 || area.height < 0) if(area.width < 0 || area.height < 0)
return (widget->area.width = 0); return (w->area.width = 0);
if(d->resize) 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 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) w->area.x = widget_calculate_offset(statusbar->width,
widget->area.x = widget_calculate_offset(widget->statusbar->width, w->area.width,
widget->area.width, offset,
offset, w->widget->align);
widget->alignment);
if(!widget->user_supplied_y) w->area.y = 0;
widget->area.y = 0;
draw_image(ctx, widget->area.x, widget->area.y, draw_image(statusbar->ctx, w->area.x, w->area.y,
d->resize ? widget->statusbar->height : 0, d->image); d->resize ? statusbar->height : 0, d->image);
return widget->area.width; return w->area.width;
} }
static widget_tell_status_t 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; Data *d = widget->data;
if(new_value == NULL) if(!new_value)
return WIDGET_ERROR_NOVALUE; return WIDGET_ERROR_NOVALUE;
if(!a_strcmp(property, "image")) if(!a_strcmp(property, "image"))
@ -86,19 +84,18 @@ iconbox_tell(widget_t *widget, char *property, char *new_value)
} }
widget_t * widget_t *
iconbox_new(statusbar_t *statusbar, cfg_t *config) iconbox_new(alignment_t align)
{ {
widget_t *w; widget_t *w;
Data *d; Data *d;
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config); widget_common_new(w);
w->alignment = cfg_getalignment(config, "align"); w->align = align;
w->draw = iconbox_draw; w->draw = iconbox_draw;
w->tell = iconbox_tell; w->tell = iconbox_tell;
w->data = d = p_new(Data, 1); w->data = d = p_new(Data, 1);
d->image = a_strdup(cfg_getstr(config, "image")); d->resize = true;
d->resize = cfg_getbool(config, "resize");
return w; return w;
} }

View File

@ -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

View File

@ -112,14 +112,15 @@ check_settings(Data *d, int status_height)
static int 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))) int used __attribute__ ((unused)))
{ {
/* pb_.. values points to the widget inside a potential border */ /* 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 i, percent_ticks, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset;
int unit = 0; /* tick + gap */ int unit = 0; /* tick + gap */
area_t rectangle, pattern_rect; area_t rectangle, pattern_rect;
Data *d = widget->data; draw_context_t *ctx = statusbar->ctx;
Data *d = w->widget->data;
if(!d->data_items) if(!d->data_items)
return 0; 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 pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->data_items
- d->gap * (d->data_items - 1)) / d->data_items); - d->gap * (d->data_items - 1)) / d->data_items);
widget->area.width = d->data_items w->area.width = d->data_items
* (pb_width + 2 * (d->border_width + d->border_padding) * (pb_width + 2 * (d->border_width + d->border_padding)
+ d->gap) - d->gap; + d->gap) - d->gap;
} }
else 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; unit = (pb_width + d->ticks_gap) / d->ticks_count;
pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */ 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) w->area.x = widget_calculate_offset(statusbar->width,
widget->area.x = widget_calculate_offset(widget->statusbar->width, w->area.width,
widget->area.width, offset,
offset, w->widget->align);
widget->alignment); w->area.y = 0;
if(!widget->user_supplied_y)
widget->area.y = 0;
/* for a 'reversed' progressbar: /* for a 'reversed' progressbar:
* basic progressbar: * basic progressbar:
@ -162,14 +161,14 @@ progressbar_draw(widget_t *widget, draw_context_t *ctx, int offset,
* 2. finally draw the gaps * 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; pb_offset = 0;
if(d->vertical) if(d->vertical)
{ {
/* TODO: maybe prevent to calculate that stuff below over and over again /* TODO: maybe prevent to calculate that stuff below over and over again
* (->use static-values) */ * (->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); - 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap) 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_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; + d->border_width + d->border_padding;
for(i = 0; i < d->data_items; i++) 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 */ 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->data_items * 2 * (d->border_width + d->border_padding)
- (d->gap * (d->data_items - 1))) / d->data_items + 0.5); - (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; + d->border_width + d->border_padding;
for(i = 0; i < d->data_items; i++) 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; w->area.height = statusbar->height;
return widget->area.width; return w->area.width;
} }
static widget_tell_status_t 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; Data *d = widget->data;
int i = 0, percent, tmp; int i = 0, percent, tmp;
@ -406,39 +405,23 @@ progressbar_tell(widget_t *widget, char *property, char *new_value)
return WIDGET_ERROR_FORMAT_SECTION; return WIDGET_ERROR_FORMAT_SECTION;
} }
else if(!a_strcmp(property, "fg")) 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")) 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")) 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")) 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")) 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")) 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")) else if(!a_strcmp(property, "gap"))
d->gap = atoi(new_value); d->gap = atoi(new_value);
else if(!a_strcmp(property, "width")) else if(!a_strcmp(property, "width"))
{
tmp = d->width;
d->width = atoi(new_value); 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")) else if(!a_strcmp(property, "height"))
{
tmpf = d->height;
d->height = atof(new_value); d->height = atof(new_value);
if(!check_settings(d, widget->statusbar->height))
{
d->height = tmpf; /* restore */
return WIDGET_ERROR_CUSTOM;
}
}
else else
return WIDGET_ERROR; return WIDGET_ERROR;
@ -446,7 +429,7 @@ progressbar_tell(widget_t *widget, char *property, char *new_value)
} }
widget_t * widget_t *
progressbar_new(statusbar_t *statusbar, cfg_t *config) progressbar_new(alignment_t align)
{ {
widget_t *w; widget_t *w;
Data *d; Data *d;
@ -456,26 +439,20 @@ progressbar_new(statusbar_t *statusbar, cfg_t *config)
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config); widget_common_new(w);
w->align = align;
w->draw = progressbar_draw; w->draw = progressbar_draw;
w->tell = progressbar_tell; w->tell = progressbar_tell;
d = w->data = p_new(Data, 1); d = w->data = p_new(Data, 1);
d->height = cfg_getfloat(config, "height"); d->height = 0.67;
d->width = cfg_getint(config, "width"); d->width = 100;
d->border_padding = cfg_getint(config, "border_padding"); d->ticks_gap = 1;
d->ticks_gap = cfg_getint(config, "ticks_gap"); d->border_width = 1;
d->ticks_count = cfg_getint(config, "ticks_count"); d->gap = 2;
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");
/*
if(!(d->data_items = cfg_size(config, "data"))) if(!(d->data_items = cfg_size(config, "data")))
{ {
warn("progressbar widget needs at least one bar section\n"); warn("progressbar widget needs at least one bar section\n");
@ -539,6 +516,7 @@ progressbar_new(statusbar_t *statusbar, cfg_t *config)
else else
d->bordercolor[i] = d->fg[i]; d->bordercolor[i] = d->fg[i];
} }
*/
return w; return w;
} }
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -19,20 +19,31 @@
* *
*/ */
#include "config.h"
#include "client.h" #include "client.h"
#include "widget.h" #include "widget.h"
#include "tag.h" #include "tag.h"
#include "lua.h"
#include "event.h" #include "event.h"
#include "common/markup.h" #include "common/markup.h"
#include "common/configopts.h" #include "common/configopts.h"
extern AwesomeConf globalconf; 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 typedef struct
{ {
char *text_normal, *text_focus, *text_urgent; char *text_normal, *text_focus, *text_urgent;
area_t *draw_area; taglist_drawn_area_t *drawn_area;
} taglist_data_t; } taglist_data_t;
static char * static char *
@ -90,17 +101,6 @@ tag_isurgent(tag_t *t)
return false; 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 * static char *
taglist_text_get(tag_t *tag, taglist_data_t *data) 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 static int
taglist_draw(widget_t *widget, taglist_draw(widget_node_t *w,
draw_context_t *ctx, statusbar_t *statusbar,
int offset, int offset,
int used __attribute__ ((unused))) int used __attribute__ ((unused)))
{ {
tag_t *tag; tag_t *tag;
taglist_data_t *data = widget->data; taglist_data_t *data = w->widget->data;
client_t *sel = globalconf.focus->client; 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; int i = 0;
style_t **styles;
area_t *area, rectangle = { 0, 0, 0, 0, NULL, NULL }; area_t *area, rectangle = { 0, 0, 0, 0, NULL, NULL };
char **text; 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); text = p_new(char *, 1);
styles = p_new(style_t *, 1);
for(tag = vscreen->tags; tag; tag = tag->next, i++) for(tag = vscreen->tags; tag; tag = tag->next, i++)
{ {
p_realloc(&text, i + 1); p_realloc(&text, i + 1);
p_realloc(&styles, i + 1);
styles[i] = taglist_style_get(tag, vscreen);
area = p_new(area_t, 1); area = p_new(area_t, 1);
text[i] = taglist_text_get(tag, data); text[i] = taglist_text_get(tag, data);
text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i])); text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i]));
*area = draw_text_extents(ctx->connection, ctx->phys_screen, *area = draw_text_extents(ctx->connection, ctx->phys_screen,
styles[i]->font, text[i]); globalconf.font, text[i]);
area->x = widget->area.width; area->x = w->area.x + w->area.width;
area->height = widget->statusbar->height; area->height = statusbar->height;
area_list_append(&data->draw_area, area); area_list_append(&tda->area, area);
widget->area.width += area->width; w->area.width += area->width;
} }
if(!widget->user_supplied_x) for(area = tda->area, tag = vscreen->tags, i = 0;
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;
tag && area; tag && area;
tag = tag->next, area = area->next, i++) 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]); p_delete(&text[i]);
if(tag_isoccupied(tag)) 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.x = area->x;
rectangle.y = area->y; rectangle.y = area->y;
draw_rectangle(ctx, rectangle, 1.0, 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(&text);
p_delete(&styles);
widget->area.height = widget->statusbar->height; w->area.height = statusbar->height;
return widget->area.width; return w->area.width;
} }
static void 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; Button *b;
tag_t *tag; taglist_data_t *data = w->widget->data;
char buf[4]; taglist_drawn_area_t *tda;
int i = 1; area_t *area;
taglist_data_t *data = widget->data; tag_t *tag, **ltag;
area_t *area = data->draw_area;
for(b = widget->buttons; b; b = b->next) /* Find the good drawn area list */
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->func) for(tda = data->drawn_area; tda && tda->statusbar != statusbar; tda = tda->next);
switch(widget->statusbar->position) 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: 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) if(ev->event_x >= AREA_LEFT(*area)
&& ev->event_x < AREA_RIGHT(*area)) && ev->event_x < AREA_RIGHT(*area))
{ {
snprintf(buf, sizeof(buf), "%d", i); ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *));
b->func(widget->statusbar->screen, buf); luaA_settype(globalconf.L, "tag");
return; *ltag = tag;
luaA_dofunction(globalconf.L, b->fct, 1);
} }
break; break;
case Right: 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) if(ev->event_y >= AREA_LEFT(*area)
&& ev->event_y < AREA_RIGHT(*area)) && ev->event_y < AREA_RIGHT(*area))
{ {
snprintf(buf, sizeof(buf), "%d", i); ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *));
b->func(widget->statusbar->screen, buf); luaA_settype(globalconf.L, "tag");
return; *ltag = tag;
luaA_dofunction(globalconf.L, b->fct, 1);
} }
break; break;
case Left: case Left:
for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next) for(tag = vscreen->tags; tag; tag = tag->next, area = area->next)
if(widget->statusbar->width - ev->event_y >= AREA_LEFT(*area) if(statusbar->width - ev->event_y >= AREA_LEFT(*area)
&& widget->statusbar->width - ev->event_y < AREA_RIGHT(*area)) && statusbar->width - ev->event_y < AREA_RIGHT(*area))
{ {
snprintf(buf, sizeof(buf), "%d", i); ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *));
b->func(widget->statusbar->screen, buf); luaA_settype(globalconf.L, "tag");
return; *ltag = tag;
luaA_dofunction(globalconf.L, b->fct, 1);
} }
break; 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 * widget_t *
taglist_new(statusbar_t *statusbar, cfg_t *config) taglist_new(alignment_t align)
{ {
widget_t *w; widget_t *w;
taglist_data_t *d; taglist_data_t *d;
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config); widget_common_new(w);
w->align = align;
w->draw = taglist_draw; w->draw = taglist_draw;
w->button_press = taglist_button_press; 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); w->data = d = p_new(taglist_data_t, 1);
d->text_normal = a_strdup(cfg_getstr(config, "text_normal")); d->text_normal = a_strdup(" <text align=\"center\"/><title/> ");
d->text_focus = a_strdup(cfg_getstr(config, "text_focus")); d->text_focus = a_strdup(" <text align=\"center\"/><title/> ");
d->text_urgent = a_strdup(cfg_getstr(config, "text_urgent")); d->text_urgent = a_strdup(" <text align=\"center\"/><title/> ");
/* Set cache property */ /* Set cache property */
w->cache_flags = WIDGET_CACHE_TAGS | WIDGET_CACHE_CLIENTS; w->cache_flags = WIDGET_CACHE_TAGS | WIDGET_CACHE_CLIENTS;

View File

@ -25,7 +25,6 @@
#include "screen.h" #include "screen.h"
#include "event.h" #include "event.h"
#include "ewmh.h" #include "ewmh.h"
#include "rules.h"
#include "tag.h" #include "tag.h"
#include "common/configopts.h" #include "common/configopts.h"
@ -64,47 +63,39 @@ tasklist_isvisible(client_t *c, int screen, showclient_t show)
} }
static int 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; client_t *c;
Data *d = widget->data; Data *d = w->widget->data;
rule_t *r;
area_t area; area_t area;
char *text; char *text;
int n = 0, i = 0, box_width = 0, icon_width = 0, box_width_rest = 0; int n = 0, i = 0, box_width = 0, icon_width = 0, box_width_rest = 0;
NetWMIcon *icon; NetWMIcon *icon;
style_t *style;
if(used >= widget->statusbar->width) if(used >= statusbar->width)
return (widget->area.width = 0); return (w->area.width = 0);
for(c = globalconf.clients; c; c = c->next) 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++; n++;
if(!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 */ /* 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) w->area.x = widget_calculate_offset(statusbar->width,
widget->area.x = widget_calculate_offset(widget->statusbar->width, 0, offset, w->widget->align);
0,
offset,
widget->alignment);
if(!widget->user_supplied_y) w->area.y = 0;
widget->area.y = widget->area.y = 0;
for(c = globalconf.clients; c; c = c->next) 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; icon_width = 0;
style = client_style_get(c);
if(globalconf.focus->client == c) if(globalconf.focus->client == c)
text = d->text_focus; text = d->text_focus;
else if(c->isurgent) 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) if(d->show_icons)
{ {
/* draw a background for icons */ /* draw a background for icons */
area.x = widget->area.x + box_width * i; area.x = w->area.x + box_width * i;
area.y = widget->area.y; area.y = w->area.y;
area.height = widget->statusbar->height; area.height = statusbar->height;
area.width = box_width; 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) if(area.width > 0 && area.height > 0)
{ {
icon_width = ((double) widget->statusbar->height / (double) area.height) * area.width; icon_width = ((double) statusbar->height / (double) area.height) * area.width;
draw_image(ctx, draw_image(statusbar->ctx,
widget->area.x + box_width * i, w->area.x + box_width * i,
widget->area.y, w->area.y,
widget->statusbar->height, statusbar->height,
r->icon); NULL);
// r->icon);
} }
} }
if(!icon_width && (icon = ewmh_get_window_icon(c->win))) 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; * icon->width;
draw_image_from_argb_data(ctx, draw_image_from_argb_data(statusbar->ctx,
widget->area.x + box_width * i, w->area.x + box_width * i,
widget->area.y, w->area.y,
icon->width, icon->height, icon->width, icon->height,
widget->statusbar->height, icon->image); statusbar->height, icon->image);
p_delete(&icon->image); p_delete(&icon->image);
p_delete(&icon); p_delete(&icon);
} }
} }
area.x = widget->area.x + icon_width + box_width * i; area.x = w->area.x + icon_width + box_width * i;
area.y = widget->area.y; area.y = w->area.y;
area.width = box_width - icon_width; 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 we're on last elem, it has the last pixels left */
if(i == n - 1) if(i == n - 1)
area.width += box_width_rest; 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); p_delete(&text);
if(c == globalconf.scratch.client) if(c == globalconf.scratch.client)
{ {
area.x = widget->area.x + icon_width + box_width * i; area.x = w->area.x + icon_width + box_width * i;
area.y = widget->area.y; area.y = w->area.y;
area.width = (style->font->height + 2) / 3; area.width = (globalconf.font->height + 2) / 3;
area.height = (style->font->height + 2) / 3; area.height = (globalconf.font->height + 2) / 3;
draw_rectangle(ctx, area, 1.0, c->isfloating, style->fg); draw_rectangle(statusbar->ctx, area, 1.0, c->isfloating, statusbar->colors.fg);
} }
else if(c->isfloating || c->ismax) else if(c->isfloating || c->ismax)
draw_circle(ctx, widget->area.x + icon_width + box_width * i, draw_circle(statusbar->ctx, w->area.x + icon_width + box_width * i,
widget->area.y, w->area.y,
(style->font->height + 2) / 4, (globalconf.font->height + 2) / 4,
c->ismax, style->fg); c->ismax, statusbar->colors.fg);
i++; i++;
} }
widget->area.width = widget->statusbar->width - used; w->area.width = statusbar->width - used;
widget->area.height = widget->statusbar->height; w->area.height = statusbar->height;
return widget->area.width; return w->area.width;
} }
static void 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; Button *b;
client_t *c; client_t *c, **lc;
Data *d = widget->data; Data *d = w->widget->data;
tag_t *tag;
int n = 0, box_width = 0, i, ci = 0; int n = 0, box_width = 0, i, ci = 0;
/* button1 give focus */ for(c = globalconf.clients; c; c = c->next)
if(ev->detail == XCB_BUTTON_INDEX_1 && CLEANMASK(ev->state) == XCB_NO_SYMBOL) 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) case Top:
if(tasklist_isvisible(c, widget->statusbar->screen, d->show)) case Bottom:
n++; ci = (ev->event_x - w->area.x) / box_width;
break;
if(!n) case Right:
return; ci = (ev->event_y - w->area.x) / box_width;
break;
box_width = widget->area.width / n; default:
ci = ((statusbar->width - ev->event_y) - w->area.x) / box_width;
if(ev->detail == XCB_BUTTON_INDEX_1 && CLEANMASK(ev->state) == XCB_NO_SYMBOL) break;
{
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;
}
} }
/* 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(c)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->func) for(b = w->widget->buttons; b; b = b->next)
b->func(widget->statusbar->screen, b->arg); 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 * widget_t *
tasklist_new(statusbar_t *statusbar, cfg_t *config) tasklist_new(alignment_t align __attribute__ ((unused)))
{ {
widget_t *w; widget_t *w;
Data *d; Data *d;
char *buf;
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config); widget_common_new(w);
w->draw = tasklist_draw; w->draw = tasklist_draw;
w->button_press = tasklist_button_press; w->button_press = tasklist_button_press;
w->alignment = AlignFlex; w->align = AlignFlex;
w->data = d = p_new(Data, 1); w->data = d = p_new(Data, 1);
w->tell = tasklist_tell;
d->text_normal = a_strdup(cfg_getstr(config, "text_normal")); d->text_normal = a_strdup(" <title/> ");
d->text_focus = a_strdup(cfg_getstr(config, "text_focus")); d->text_focus = a_strdup(" <title/> ");
d->text_urgent = a_strdup(cfg_getstr(config, "text_urgent")); d->text_urgent = a_strdup(" <title/> ");
d->show_icons = cfg_getbool(config, "show_icons"); d->show_icons = true;
d->show = ShowTags;
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;
/* Set cache property */ /* Set cache property */
w->cache_flags = WIDGET_CACHE_CLIENTS; w->cache_flags = WIDGET_CACHE_CLIENTS;

View File

@ -1,6 +1,7 @@
/* /*
* textbox.c - text box widget * textbox.c - text box widget
* *
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007 Aldo Cortesi <aldo@nullcube.com> * Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -33,37 +34,37 @@ typedef struct
} Data; } Data;
static int 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) if(d->width)
widget->area.width = d->width; w->area.width = d->width;
else if(widget->alignment == AlignFlex) else if(w->widget->align == AlignFlex)
widget->area.width = widget->statusbar->width - used; w->area.width = statusbar->width - used;
else else
widget->area.width = MIN(draw_text_extents(ctx->connection, ctx->phys_screen, w->area.width = MIN(draw_text_extents(statusbar->ctx->connection,
globalconf.screens[widget->statusbar->screen].styles.normal.font, d->text).width, statusbar->ctx->phys_screen,
widget->statusbar->width - used); globalconf.font, d->text).width,
statusbar->width - used);
widget->area.height = widget->statusbar->height; w->area.height = statusbar->height;
if(!widget->user_supplied_x) w->area.x = widget_calculate_offset(statusbar->width,
widget->area.x = widget_calculate_offset(widget->statusbar->width, w->area.width,
widget->area.width, offset,
offset, w->widget->align);
widget->alignment); w->area.y = 0;
if(!widget->user_supplied_y)
widget->area.y = 0;
draw_text(ctx, widget->area, d->text, draw_text(statusbar->ctx, globalconf.font,
&globalconf.screens[widget->statusbar->screen].styles.normal); &statusbar->colors.fg,
w->area, d->text);
return widget->area.width; return w->area.width;
} }
static widget_tell_status_t 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; Data *d = widget->data;
@ -81,23 +82,18 @@ textbox_tell(widget_t *widget, char *property, char *new_value)
} }
widget_t * widget_t *
textbox_new(statusbar_t *statusbar, cfg_t *config) textbox_new(alignment_t align)
{ {
widget_t *w; widget_t *w;
Data *d; Data *d;
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config); widget_common_new(w);
w->align = align;
w->draw = textbox_draw; w->draw = textbox_draw;
w->tell = textbox_tell; w->tell = textbox_tell;
w->alignment = cfg_getalignment(config, "align");
w->data = d = p_new(Data, 1); w->data = d = p_new(Data, 1);
d->width = cfg_getint(config, "width");
d->text = a_strdup(cfg_getstr(config, "text"));
return w; return w;
} }
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -149,17 +149,51 @@ window_grabbuttons(xcb_window_t win, int phys_screen)
ANY_MODIFIER); ANY_MODIFIER);
} }
/** Grab buttons on the root window. /** Grab all buttons on the root window.
* \param phys_screen physical screen id * \param b The button binding.
*/ */
void void
window_root_grabbuttons(int phys_screen) window_root_grabbuttons(void)
{ {
Button *b; 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_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod); 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_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK); 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. /** Grab key on the root windows.
* \param phys_screen Physical screen number. * \param k The keybinding.
*/ */
void 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); int phys_screen = globalconf.default_screen;
keybinding_t *k; xcb_screen_t *s;
xcb_keycode_t kc; xcb_keycode_t kc;
for(k = globalconf.keys; k; k = k->next) if((kc = k->keycode)
if((kc = k->keycode) || (k->keysym && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym)))) || (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, xcb_grab_key(globalconf.connection, true, s->root,
k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, s->root, 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, xcb_grab_key(globalconf.connection, true, s->root,
k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC, k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC,
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. /** Set shape property on window.

View File

@ -28,8 +28,9 @@ void window_setstate(xcb_window_t, long);
long window_getstate(xcb_window_t); long window_getstate(xcb_window_t);
void window_configure(xcb_window_t, area_t, int); void window_configure(xcb_window_t, area_t, int);
void window_grabbuttons(xcb_window_t, int); void window_grabbuttons(xcb_window_t, int);
void window_root_grabbuttons(int); void window_root_grabbutton(Button *);
void window_root_grabkeys(int); void window_root_grabbuttons(void);
void window_root_grabkey(keybinding_t *);
void window_setshape(xcb_window_t, int); void window_setshape(xcb_window_t, int);
void window_settrans(xcb_window_t, double); void window_settrans(xcb_window_t, double);