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

View File

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

6
README
View File

@ -5,8 +5,8 @@ awesome is an extremely fast, small, and dynamic window manager for X.
Requirements
------------
In order to build awesome itself, you need header files and libs of:
- Xlib, Xinerama, Xrandr
- libconfuse >= 2.6
- Xlib, xcb and xcb-util.
- Lua 5.1
- cairo
- pango and pangocairo
- glib
@ -57,5 +57,5 @@ the DISPLAY environment variable is set correctly, e.g.:
Configuration
-------------
The configuration of awesome is done by creating a ~/.awesomerc file.
The configuration of awesome is done by creating a ~/.awesomerc.lua file.
An example is provided in the sources.

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

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

View File

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

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
--------
..........................
<section> [title]
{
<option> = <value>
<section> [title]
{
<option> = <value>
...
}
...
}
<option> = <value>
include(file.conf)
..........................
None.
DESCRIPTION
-----------
@ -34,182 +18,14 @@ be used to configure the behaviour and look of awesome in a variety of ways.
It is read at startup.
OPTIONS
--------
*awesomerc* contains 5 global sections: *screen*, *rules*, *keys*, *mouse* and *menu* which
are described here.
All these sections contain options which may be strings, integers, floats, or
even sections again.
include::optsdocgen.txt[]
UICB FUNCTIONS
--------------
In awesome, a lot of *functions* are available. These functions are called
uicb (User Interface Call Backs). Each function can be bound to a key shortcut
or a mouse button.
include::uicbdocgen.txt[]
EXAMPLES
--------
More examples are available on awesome's wiki:
http://awesome.naquadah.org/wiki/
Simple textbox example
~~~~~~~~~~~~~~~~~~~~~~
..............................................
1. Add an include directive into ~/.awesomerc
screen 0 { include(~/.awesome/bottom-status-bar) }
2. Create ~/.awesome/bottom-status-bar
statusbar "bottom"
{
position = "bottom"
textbox "clock" { }
}
3. Check the configuration file for errors
$ awesome -k
Configuration file OK.
Note: If you see anything other than "Configuration file OK." you have a
typo somewhere.
4. Create ~/bin/awesome-clock
#!/bin/sh
while true
do
# if you start this from .xinitrc, the script will start before
# awesome, and will fail.
if [ -S ~/.awesome_ctl.0 ]; then
while true
do
echo "0 widget_tell bottom clock text `date`"
echo "" # an empty line flushes data inside awesome
sleep 1
done | awesome-client
else
sleep 1
fi
done
Note: What we are saying is "awesome-client, tell the bottom status bar's
widget named 'clock' to set it's 'text' property to date's output".
5. Make your ~/bin/awesome-clock executable
$ chmod a+x ~/bin/awesome-clock
6. Modify ~/.xinitrc
~/bin/awesome-clock &
exec awesome
7. Restart awesome
8. If you did not get what you were expecting, take a look at
~/.xsession-errors or the terminal where X got started.
..............................................
Simple progressbar example
~~~~~~~~~~~~~~~~~~~~~~~~~~
..............................................
1. Add an include directive into ~/.awesomerc
screen 0 { include(~/.awesome/bottom-status-bar) }
2. Create ~/.awesome/bottom-status-bar
statusbar "bottom"
{
position = "bottom"
progressbar "diskusage"
{
data "disk"
{
bordercolor = "#006e96"
bg = "#000000"
fg = "#ff0000"
fg_center = "#daaf0a"
fg_end = "#00ff00"
}
width = 100
align = "left"
}
}
3. Check the configuration file for errors
$ awesome -k
Configuration file OK.
Note: If you see anything other than "Configuration file OK," you have a
typo somewhere.
4. Create ~/bin/awesome-diskusage
#!/bin/sh
while true
do
# if you start this from .xinitrc, the script will start before
# awesome, and will fail.
if [ -S ~/.awesome_ctl.0 ]; then
while true; do
usage = `df /dev/sda5 | awk '/\/dev\/sda5/ { print 100-$5 }'`
echo "0 widget_tell bottom diskusage data disk ${usage}"
echo "" # an empty line flushes data inside awesome
sleep 600;
done | awesome-client
else
sleep 1
fi
done
Note: What we are saying is "awesome-client, tell the bottom status bar's
widget named 'diskusage' to set it's 'data' property named 'disk' to
${usage}."
5. Make ~/bin/awesome-diskusage executable
$ chmod a+x ~/bin/awesome-diskusage
6. Modify ~/.xinitrc
~/bin/awesome-diskusage &
exec awesome
7. Restart awesome
8. If you did not get what you were expecting, take a look at
~/.xsession-errors or the terminal where X got started.
..............................................
AWESOMERC SKELETON
------------------
The following skeleton lists all available configuration options in *awesomerc*.
..........................
include::rcskeletongen.txt[]
..........................
SEE ALSO
--------
awesome(1) awesome-client(1) awesome-menu(1) awesome-message(1)
awesome(1) awesome-client(1)
AUTHORS
-------
This man page was written by Julien Danjou <julien@danjou.info>, Marco Candrian <mac@calmar.ws>
and Chris Ciulla <chris.ciulla@gmail.com> (Simple Examples).
This man page was written by Julien Danjou <julien@danjou.info>.
WWW
---

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)

832
client.c

File diff suppressed because it is too large Load Diff

View File

@ -43,18 +43,6 @@ void client_saveprops(client_t *);
void client_kill(client_t *);
void client_setfloating(client_t *, bool, layer_t);
char * client_markup_parse(client_t *, const char *, ssize_t);
style_t * client_style_get(client_t *);
uicb_t uicb_client_kill;
uicb_t uicb_client_moveresize;
uicb_t uicb_client_settrans;
uicb_t uicb_client_swap;
uicb_t uicb_client_togglemax;
uicb_t uicb_client_focus;
uicb_t uicb_client_setfloating;
uicb_t uicb_client_togglescratch;
uicb_t uicb_client_setscratch;
uicb_t uicb_client_redraw;
DO_SLIST(client_t, client, p_delete)

View File

@ -24,601 +24,10 @@
#include <sys/stat.h>
#include <unistd.h>
#include "rules.h"
#include "common/configopts.h"
#include "common/util.h"
#define AWESOME_CONFIG_FILE ".awesomerc"
#define CFG_AWESOME_END() \
CFG_FUNC((char *) "include", cfg_awesome_include), \
CFG_END()
#define CFG_POSITION(name, value, flags) \
CFG_PTR_CB(name, value, flags, \
cfg_position_parse, cfg_value_free)
#define CFG_ALIGNMENT(name, value, flags) \
CFG_PTR_CB(name, value, flags, \
cfg_alignment_parse, cfg_value_free)
/** This is a better writing of cfg_include coming from libconfuse.
* With this one, we do not treat errors as fatal.
*/
static int
cfg_awesome_include(cfg_t *cfg, cfg_opt_t *opt,
int argc, const char **argv)
{
char *filename;
FILE *fp;
if(argc != 1 || !a_strlen(argv[0]))
{
cfg_error(cfg, "wrong number of arguments to cfg_awesome_include()");
return 0;
}
filename = cfg_tilde_expand(argv[0]);
if(!(fp = fopen(filename, "r")))
{
cfg_error(cfg, "cannot include configuration file %s: %s",
filename, strerror(errno));
return 0;
}
p_delete(&filename);
fclose(fp);
return cfg_include(cfg, opt, argc, argv);
}
static int
cfg_position_parse(cfg_t *cfg, cfg_opt_t *opt,
const char *value, void *result)
{
position_t *p = p_new(position_t, 1);
if((*p = position_get_from_str(value)) == Off
&& a_strcmp(value, "off"))
{
cfg_error(cfg,
"position option '%s' must be top, bottom, right, left, auto or off in section '%s'",
opt->name, cfg->name);
p_delete(&p);
return -1;
}
*(void **) result = p;
return 0;
}
static int
cfg_alignment_parse(cfg_t *cfg, cfg_opt_t *opt,
const char *value, void *result)
{
alignment_t *p = p_new(alignment_t, 1);
if((*p = draw_align_get_from_str(value)) == Auto
&& a_strcmp(value, "auto"))
{
cfg_error(cfg,
"alignment option '%s' must be left, center, right, flex or auto in section '%s'",
opt->name, cfg->name);
p_delete(&p);
return -1;
}
*(void **) result = p;
return 0;
}
static void
cfg_value_free(void *value)
{
p_delete(&value);
}
alignment_t
cfg_opt_getnalignment(cfg_opt_t *opt, unsigned int oindex)
{
return * (alignment_t *) cfg_opt_getnptr(opt, oindex);
}
alignment_t
cfg_getnalignment(cfg_t *cfg, const char *name, unsigned int oindex)
{
return cfg_opt_getnalignment(cfg_getopt(cfg, name), oindex);
}
alignment_t
cfg_getalignment(cfg_t *cfg, const char *name)
{
return cfg_getnalignment(cfg, name, 0);
}
position_t
cfg_opt_getnposition(cfg_opt_t *opt, unsigned int oindex)
{
return * (position_t *) cfg_opt_getnptr(opt, oindex);
}
position_t
cfg_getnposition(cfg_t *cfg, const char *name, unsigned int oindex)
{
return cfg_opt_getnposition(cfg_getopt(cfg, name), oindex);
}
position_t
cfg_getposition(cfg_t *cfg, const char *name)
{
return cfg_getnposition(cfg, name, 0);
}
/** This section defines a style. */
cfg_opt_t style_opts[] =
{
/** Windows border color. */
CFG_STR((char *) "border", NULL, CFGF_NONE),
/** Background color. */
CFG_STR((char *) "bg", NULL, CFGF_NONE),
/** Foreground color. */
CFG_STR((char *) "fg", NULL, CFGF_NONE),
/** Shadow color. */
CFG_STR((char *) "shadow_color", NULL, CFGF_NONE),
/** Shadow offset in pixels. */
CFG_INT((char *) "shadow_offset", 0xffffffff, CFGF_NONE),
/** Font to use. */
CFG_STR((char *) "font", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines several styles in a row. */
cfg_opt_t styles_opts[] =
{
/** Normal style. */
CFG_SEC((char *) "normal", style_opts, CFGF_NONE),
/** Style used for the focused window. */
CFG_SEC((char *) "focus", style_opts, CFGF_NONE),
/** Style used for windows with urgency hint. */
CFG_SEC((char *) "urgent", style_opts, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines a titlebar. */
cfg_opt_t titlebar_opts[] =
{
/** Titlebar position. */
CFG_POSITION((char *) "position", (char *) "auto", CFGF_NONE),
/** Titlebar alignment around window. */
CFG_ALIGNMENT((char *) "align", (char *) "left", CFGF_NONE),
/** Titlebar width. Set to 0 for auto. */
CFG_INT((char *) "width", 0, CFGF_NONE),
/** Titlebar height. Set to 0 for auto. */
CFG_INT((char *) "height", 0, CFGF_NONE),
/** Titlebar markup string for normal windows. */
CFG_STR((char *) "text_normal", (char *) "<title/>", CFGF_NONE),
/** Titlebar markup string for focused windows. */
CFG_STR((char *) "text_focus", (char *) "<title/>", CFGF_NONE),
/** Titlebar markup string for urgent windows. */
CFG_STR((char *) "text_urgent", (char *) "<title/>", CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines general options. */
cfg_opt_t general_opts[] =
{
/** The border size of windows in pixels. */
CFG_INT((char *) "border", 1, CFGF_NONE),
/** The number of pixels to snap when moving floating windows. */
CFG_INT((char *) "snap", 8, CFGF_NONE),
/** Use resize hints when resizing tiled windows. Can produce gaps between windows. */
CFG_BOOL((char *) "resize_hints", cfg_true, CFGF_NONE),
/** Enable sloppy focus, also known as focus follows mouse. */
CFG_BOOL((char *) "sloppy_focus", cfg_true, CFGF_NONE),
/** Raise the window if it is given focus with the mouse. */
CFG_BOOL((char *) "sloppy_focus_raise", cfg_false, CFGF_NONE),
/** New windows become master windows. */
CFG_BOOL((char *) "new_become_master", cfg_true, CFGF_NONE),
/** New windows get focus. */
CFG_BOOL((char *) "new_get_focus", cfg_true, CFGF_NONE),
/** Opacity of windows when unfocused. */
CFG_FLOAT((char *) "opacity_unfocused", -1, CFGF_NONE),
/** Opacity of windows when focused. */
CFG_FLOAT((char *) "opacity_focused", -1, CFGF_NONE),
/** How to dispose floating windows. Can be smart or under_mouse. */
CFG_STR((char *) "floating_placement", (char *) "smart", CFGF_NONE),
/** Lower limit for the master window size factor. */
CFG_FLOAT((char *) "mwfact_lower_limit", 0.1, CFGF_NONE),
/** Upper limit for the master window size factor. */
CFG_FLOAT((char *) "mwfact_upper_limit", 0.9, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines mouse bindings or the taglist widget. */
cfg_opt_t mouse_taglist_opts[] =
{
/** Modifier keys. */
CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE),
/** Mouse button. */
CFG_STR((char *) "button", (char *) "XCB_NONE", CFGF_NONE),
/** Uicb command to run. */
CFG_STR((char *) "command", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines generic mouse bindings. */
cfg_opt_t mouse_generic_opts[] =
{
/** Modifier keys. */
CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE),
/** Mouse button. */
CFG_STR((char *) "button", (char *) "XCB_NONE", CFGF_NONE),
/** Uicb command to run. */
CFG_STR((char *) "command", NULL, CFGF_NONE),
/** Arguments to use for command. */
CFG_STR_LIST((char *) "args", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines common widgets options. */
cfg_opt_t widget_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Widget alignment. */
CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI),
CFG_AWESOME_END()
};
/** This section defines taglist widget options. */
cfg_opt_t widget_taglist_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Widget alignment. */
CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_taglist_opts, CFGF_MULTI),
/** Markup title string for normal tags */
CFG_STR((char *) "text_normal", (char *) " <text align=\"center\"/><title/> ", CFGF_NONE),
/** Markup title string for selected tags. */
CFG_STR((char *) "text_focus", (char *) " <text align=\"center\"/><title/> ", CFGF_NONE),
/** Markup title string for tags with urgent windows. */
CFG_STR((char *) "text_urgent", (char *) " <text align=\"center\"/><title/> ", CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines iconbox widget options. */
cfg_opt_t widget_iconbox_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Widget alignment. */
CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI),
/** Image to draw. */
CFG_STR((char *) "image", NULL, CFGF_NONE),
/** Enable automatic resize of the image. */
CFG_BOOL((char *) "resize", cfg_true, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines textbox widget options. */
cfg_opt_t widget_textbox_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Widget alignment. */
CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI),
/** Widget width. Set to 0 for auto. */
CFG_INT((char *) "width", 0, CFGF_NONE),
/** Default printed text. */
CFG_STR((char *) "text", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines tasklist widget options */
cfg_opt_t widget_tasklist_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI),
/** Markup title string for normal window. */
CFG_STR((char *) "text_normal", (char *) "<title/>", CFGF_NONE),
/** Markup title string for focused windows. */
CFG_STR((char *) "text_focus", (char *) "<title/>", CFGF_NONE),
/** Markup title string for urgent windows. */
CFG_STR((char *) "text_urgent", (char *) "<title/>", CFGF_NONE),
/** Which windows to show: tags, all or focus. */
CFG_STR((char *) "show", (char *) "tags", CFGF_NONE),
/** Show icons of windows. */
CFG_BOOL((char *) "show_icons", cfg_true, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines graph data widget options. */
cfg_opt_t widget_graph_data_opts[] =
{
/** Value of a full graph. */
CFG_FLOAT((char *) "max", 100.0f, CFGF_NONE),
/** Scale graph when values are bigger than 'max'. */
CFG_BOOL((char *) "scale", cfg_false, CFGF_NONE),
/** Foreground color. */
CFG_STR((char *) "fg", NULL, CFGF_NONE),
/** Foreground color in the center of the bar (as gradient). */
CFG_STR((char *) "fg_center", NULL, CFGF_NONE),
/** Foreground color at the end of a bar (as gradient). */
CFG_STR((char *) "fg_end", NULL, CFGF_NONE),
/** fg, fg_center and fg_end define a vertical gradient. */
CFG_BOOL((char *) "vertical_gradient", cfg_false, CFGF_NONE),
/** Draw style. */
CFG_STR((char *) "draw_style", (char *) "bottom", CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines graph widget options. */
cfg_opt_t widget_graph_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Widget alignment. */
CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI),
/** Data stream. */
CFG_SEC((char *) "data", widget_graph_data_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Widget width. Set to 0 for auto. */
CFG_INT((char *) "width", 100, CFGF_NONE),
/** Put new values onto the 'left' or 'right'. */
CFG_POSITION((char *) "grow", (char *) "left", CFGF_NONE),
/** Set height (i.e. 0.9 = 90%). */
CFG_FLOAT((char *) "height", 0.67, CFGF_NONE),
/** Background color. */
CFG_STR((char *) "bg", NULL, CFGF_NONE),
/** Border color. */
CFG_STR((char *) "bordercolor", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines graph widget options. */
cfg_opt_t widget_progressbar_data_opts[] =
{
/** Foreground color. */
CFG_STR((char *) "fg", NULL, CFGF_NONE),
/** Foreground color in the center of the bar (as gradient). */
CFG_STR((char *) "fg_center", NULL, CFGF_NONE),
/** Foreground color at the end of a bar (as gradient). */
CFG_STR((char *) "fg_end", NULL, CFGF_NONE),
/** Foreground color of not filled bar/ticks. */
CFG_STR((char *) "fg_off", NULL, CFGF_NONE),
/** Background color. */
CFG_STR((char *) "bg", NULL, CFGF_NONE),
/** Border color. */
CFG_STR((char *) "bordercolor", NULL, CFGF_NONE),
/** Reverse/mirror the bar. */
CFG_BOOL((char *) "reverse", cfg_false, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines progressbar widget options. */
cfg_opt_t widget_progressbar_opts[] =
{
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Widget alignment. */
CFG_ALIGNMENT((char *) "align", (char *) "auto", CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI),
/** Draws a bar for each data section. */
CFG_SEC((char *) "data", widget_progressbar_data_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Widget width. */
CFG_INT((char *) "width", 100, CFGF_NONE),
/** Distance between individual bars. */
CFG_INT((char *) "gap", 2, CFGF_NONE),
/** Border width in pixels. */
CFG_INT((char *) "border_width", 1, CFGF_NONE),
/** Padding between border and ticks/bar. */
CFG_INT((char *) "border_padding", 0, CFGF_NONE),
/** Distance between the ticks. */
CFG_INT((char *) "ticks_gap", 1, CFGF_NONE),
/** Number of 'ticks' to draw. */
CFG_INT((char *) "ticks_count", 0, CFGF_NONE),
/** Set height (i.e. 0.9 = 90%). */
CFG_FLOAT((char *) "height", 0.67, CFGF_NONE),
/** Draw the bar(s) vertically. */
CFG_BOOL((char *) "vertical", cfg_false, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines statusbar options. */
cfg_opt_t statusbar_opts[] =
{
/** Statusbar position. */
CFG_POSITION((char *) "position", (char *) "top", CFGF_NONE),
/** Statusbar height. Set to 0 for auto. */
CFG_INT((char *) "height", 0, CFGF_NONE),
/** Statusbar width. Set to 0 for auto. */
CFG_INT((char *) "width", 0, CFGF_NONE),
/** Textbox widget(s). */
CFG_SEC((char *) "textbox", widget_textbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Taglist widget(s). */
CFG_SEC((char *) "taglist", widget_taglist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Layoutinfo widget(s). */
CFG_SEC((char *) "layoutinfo", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Iconbox widget(s). */
CFG_SEC((char *) "iconbox", widget_iconbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Focusicon widget(s). */
CFG_SEC((char *) "focusicon", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Progressbar widget(s). */
CFG_SEC((char *) "progressbar", widget_progressbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Graph(s) widget(s). */
CFG_SEC((char *) "graph", widget_graph_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Tasklist(s) widget(s). */
CFG_SEC((char *) "tasklist", widget_tasklist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
CFG_AWESOME_END()
};
/** This section defines tag options. */
cfg_opt_t tag_opts[] =
{
/** Default layout for this tag. */
CFG_STR((char *) "layout", (char *) "tile", CFGF_NONE),
/** Default master width factor for this tag. */
CFG_FLOAT((char *) "mwfact", 0.61803398874989484820, CFGF_NONE),
/** Default number of master windows for this tag. */
CFG_INT((char *) "nmaster", 1, CFGF_NONE),
/** Default number of window columns for this tag. */
CFG_INT((char *) "ncol", 1, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines tags options. */
cfg_opt_t tags_opts[] =
{
/** Available tag(s). */
CFG_SEC((char *) "tag", tag_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
CFG_AWESOME_END()
};
/** This section defines layout options. */
cfg_opt_t layout_opts[] =
{
/** Image to represent layout in layoutinfo widget. */
CFG_STR((char *) "image", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines layouts options. */
cfg_opt_t layouts_opts[] =
{
/** Available layout(s). */
CFG_SEC((char *) "layout", layout_opts, CFGF_TITLE | CFGF_MULTI),
CFG_AWESOME_END()
};
/** This section defines padding options. */
cfg_opt_t padding_opts[] =
{
/** Top padding in pixels. */
CFG_INT((char *) "top", 0, CFGF_NONE),
/** Bottom padding in pixels. */
CFG_INT((char *) "bottom", 0, CFGF_NONE),
/** Right padding in pixels. */
CFG_INT((char *) "right", 0, CFGF_NONE),
/** Left padding in pixels. */
CFG_INT((char *) "left", 0, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines screen options. */
cfg_opt_t screen_opts[] =
{
/** General options. */
CFG_SEC((char *) "general", general_opts, CFGF_NONE),
/** Titlebar definitions. */
CFG_SEC((char *) "titlebar", titlebar_opts, CFGF_NONE),
/** Statubar(s) definitions. */
CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** Tags definitions. */
CFG_SEC((char *) "tags", tags_opts, CFGF_NONE),
/** Styles definitions. */
CFG_SEC((char *) "styles", styles_opts, CFGF_NONE),
/** Layouts definitions. */
CFG_SEC((char *) "layouts", layouts_opts, CFGF_NONE),
/** Paddings definitions. */
CFG_SEC((char *) "padding", padding_opts, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines rule options. */
cfg_opt_t rule_opts[] =
{
/** Name of the xproperty to match. */
CFG_STR((char *) "xproperty_name", NULL, CFGF_NONE),
/** Regexp value of the xproperty above to match. */
CFG_STR((char *) "xproperty_value", NULL, CFGF_NONE),
/** Regexp to match the window against a string formatted like: class:name:title. */
CFG_STR((char *) "name", NULL, CFGF_NONE),
/** Tags matching that regexp to tag windows with. */
CFG_STR((char *) "tags", NULL, CFGF_NONE),
/** Icon to use for that window. */
CFG_STR((char *) "icon", NULL, CFGF_NONE),
/** Set this window floating. */
CFG_STR((char *) "float", (char *) "auto", CFGF_NONE),
/** Set this window as master. */
CFG_STR((char *) "master", (char *) "auto", CFGF_NONE),
/** Titlebar for this window. */
CFG_SEC((char *) "titlebar", titlebar_opts, CFGF_NONE),
/** Screen to start this window on. */
CFG_INT((char *) "screen", RULE_NOSCREEN, CFGF_NONE),
/** Opacity for this window. */
CFG_FLOAT((char *) "opacity", -1, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines rules options. */
cfg_opt_t rules_opts[] =
{
/** A rule. A window can match one rule. */
CFG_SEC((char *) "rule", rule_opts, CFGF_MULTI),
CFG_AWESOME_END()
};
/** This section defines a global key binding. */
cfg_opt_t key_opts[] =
{
/** Modifier keys. */
CFG_STR_LIST((char *) "modkey", (char *) "", CFGF_NONE),
/** Key to press. */
CFG_STR((char *) "key", (char *) "XCB_NONE", CFGF_NONE),
/** Uicb command to run. */
CFG_STR((char *) "command", (char *) "", CFGF_NONE),
/** Argument to use for command. */
CFG_STR_LIST((char *) "args", NULL, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines keys options. */
cfg_opt_t keys_opts[] =
{
/** A key binding. */
CFG_SEC((char *) "key", key_opts, CFGF_MULTI),
CFG_AWESOME_END()
};
/** This section defines mouse options. */
cfg_opt_t mouse_opts[] =
{
/** Mouse bindings for the root window. */
CFG_SEC((char *) "root", mouse_generic_opts, CFGF_MULTI),
/** Mouse bindings for the clients' window. */
CFG_SEC((char *) "client", mouse_generic_opts, CFGF_MULTI),
/** Mouse bindings for the clients' titlebar. */
CFG_SEC((char *) "titlebar", mouse_generic_opts, CFGF_MULTI),
CFG_AWESOME_END()
};
/** This section defines menu options. */
cfg_opt_t menu_opts[] =
{
/** Width of the menu. Set to 0 for auto. */
CFG_INT((char *) "width", 0, CFGF_NONE),
/** Height of the menu. Set to 0 for auto. */
CFG_INT((char *) "height", 0, CFGF_NONE),
/** X coordinate, do not set for auto. */
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** Styles to use for this menu. */
CFG_SEC((char *) "styles", styles_opts, CFGF_NONE),
CFG_AWESOME_END()
};
/** This section defines global awesome options. */
cfg_opt_t awesome_opts[] =
{
/** The screens section. Make one for each of your screens. */
CFG_SEC((char *) "screen", screen_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
/** The rules section. This allows specific options for specific windows. */
CFG_SEC((char *) "rules", rules_opts, CFGF_NONE),
/** Key bindings. */
CFG_SEC((char *) "keys", keys_opts, CFGF_NONE),
/** Mouse bindings. */
CFG_SEC((char *) "mouse", mouse_opts, CFGF_NONE),
/** Menu options. */
CFG_SEC((char *) "menu", menu_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
CFG_AWESOME_END()
};
#define AWESOME_CONFIG_FILE ".awesomerc.lua"
/** Return default configuration file path
* \return path to the default configuration file
@ -640,144 +49,4 @@ config_file(void)
return confpath;
}
static int
config_validate_unsigned_int(cfg_t *cfg, cfg_opt_t *opt)
{
int value = cfg_opt_getnint(opt, cfg_opt_size(opt) - 1);
if(value < 0)
{
cfg_error(cfg, "integer option '%s' must be positive in section '%s'",
opt->name, cfg->name);
return -1;
}
return 0;
}
static int
config_validate_supone_int(cfg_t *cfg, cfg_opt_t *opt)
{
int value = cfg_opt_getnint(opt, cfg_opt_size(opt) - 1);
if(value < 1)
{
cfg_error(cfg, "integer option '%s' must be at least 1 in section '%s'",
opt->name, cfg->name);
return -1;
}
return 0;
}
static int
config_validate_zero_one_float(cfg_t *cfg, cfg_opt_t *opt)
{
float value = cfg_opt_getnfloat(opt, cfg_opt_size(opt) - 1);
if(value < 0.0 || value > 1.0)
{
cfg_error(cfg, "float option '%s' must be at least 0.0 and less than 1.0 in section '%s'",
opt->name, cfg->name);
return -1;
}
return 0;
}
static int
config_validate_supzero_float(cfg_t *cfg, cfg_opt_t *opt)
{
float value = cfg_opt_getnfloat(opt, cfg_opt_size(opt) - 1);
if(value <= 0.0)
{
cfg_error(cfg, "float option '%s' must be greater than 0.0 section '%s'",
opt->name, cfg->name);
return -1;
}
return 0;
}
cfg_t *
cfg_new(void)
{
cfg_t *cfg;
cfg = cfg_init(awesome_opts, CFGF_NONE);
/* Check integers values */
cfg_set_validate_func(cfg, "screen|general|snap", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|general|border", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|height", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|tags|tag|nmaster", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|titlebar|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|titlebar|height", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "rules|rule|titlebar|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "rules|rule|titlebar|height", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "rules|rule|screen", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|textbox|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|graph|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|progressbar|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|progressbar|border_width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|progressbar|border_padding", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|progressbar|ticks_gap", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "screen|statusbar|progressbar|ticks_count", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "menu|width", config_validate_unsigned_int);
cfg_set_validate_func(cfg, "menu|height", config_validate_unsigned_int);
/* Check integers values > 1 */
cfg_set_validate_func(cfg, "screen|tags|tag|ncol", config_validate_supone_int);
/* Check float values */
cfg_set_validate_func(cfg, "screen|general|mwfact_lower_limit", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "screen|general|mwfact_upper_limit", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "screen|tags|tag|mwfact", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "screen|general|opacity_unfocused", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "screen|general|opacity_focused", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "rules|rule|opacity", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "screen|statusbar|graph|height", config_validate_zero_one_float);
cfg_set_validate_func(cfg, "screen|statusbar|progressbar|height", config_validate_zero_one_float);
/* Check float values > 0.0 */
cfg_set_validate_func(cfg, "screen|statusbar|graph|data|max", config_validate_supzero_float);
return cfg;
}
/** Check configuration file syntax in regard of libconfuse parsing
* \param path to config file
* \return status returned by cfg_parse()
*/
int
config_check(const char *confpatharg)
{
cfg_t *cfg;
int ret;
char *confpath;
cfg = cfg_new();
if(confpatharg)
confpath = a_strdup(confpatharg);
else
confpath = config_file();
switch((ret = cfg_parse(cfg, confpath)))
{
case CFG_FILE_ERROR:
warn("parsing configuration file failed: %s\n", strerror(errno));
break;
case CFG_PARSE_ERROR:
cfg_error(cfg, "awesome: parsing configuration file %s failed.\n", confpath);
break;
case CFG_SUCCESS:
printf("Configuration file OK.\n");
break;
}
p_delete(&confpath);
cfg_free(cfg);
return ret;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -22,19 +22,7 @@
#ifndef AWESOME_COMMON_CONFIGOPTS_H
#define AWESOME_COMMON_CONFIGOPTS_H
#include <confuse.h>
cfg_t * cfg_new(void);
char * config_file(void);
int config_check(const char *);
alignment_t cfg_opt_getnalignment(cfg_opt_t *, unsigned int);
alignment_t cfg_getnalignment(cfg_t *, const char *, unsigned int);
alignment_t cfg_getalignment(cfg_t *, const char *);
position_t cfg_opt_getnposition(cfg_opt_t *, unsigned int);
position_t cfg_getnposition(cfg_t *, const char *, unsigned int);
position_t cfg_getposition(cfg_t *, const char *);
#endif

View File

@ -141,7 +141,7 @@ draw_context_new(xcb_connection_t *conn, int phys_screen, int width, int height,
* \return a new font
*/
font_t *
draw_font_new(xcb_connection_t *conn, int phys_screen, char *fontname)
draw_font_new(xcb_connection_t *conn, int phys_screen, const char *fontname)
{
cairo_surface_t *surface;
xcb_screen_t *s = xcb_aux_get_screen(conn, phys_screen);
@ -213,7 +213,11 @@ typedef struct
} margin;
bool has_bg_color;
xcolor_t bg_color;
shadow_t shadow;
struct
{
int offset;
xcolor_t color;
} shadow;
} draw_parser_data_t;
static bool
@ -278,13 +282,13 @@ draw_text_markup_expand(draw_parser_data_t *data,
* \param style A pointer to the style to use.
*/
void
draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *style)
draw_text(draw_context_t *ctx, font_t *font,
xcolor_t *fg, area_t area, const char *text)
{
int x, y;
ssize_t len, olen;
char *buf = NULL, *utf8 = NULL;
PangoRectangle ext;
shadow_t shadow;
draw_parser_data_t parser_data;
if(!(len = a_strlen(text)))
@ -311,8 +315,6 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty
if(parser_data.has_bg_color)
draw_rectangle(ctx, area, 1.0, true, parser_data.bg_color);
else
draw_rectangle(ctx, area, 1.0, true, style->bg);
pango_layout_set_width(ctx->layout,
pango_units_from_double(area.width
@ -320,14 +322,14 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty
+ parser_data.margin.right)));
pango_layout_set_ellipsize(ctx->layout, PANGO_ELLIPSIZE_END);
pango_layout_set_markup(ctx->layout, buf, len);
pango_layout_set_font_description(ctx->layout, style->font->desc);
pango_layout_set_font_description(ctx->layout, font->desc);
pango_layout_get_pixel_extents(ctx->layout, NULL, &ext);
x = area.x + parser_data.margin.left;
/* + 1 is added for rounding, so that in any case of doubt we rather draw
* the text 1px lower than too high which usually results in a better type
* face */
y = area.y + (ctx->height - style->font->height + 1) / 2;
y = area.y + (ctx->height - font->height + 1) / 2;
switch(parser_data.align)
{
@ -341,20 +343,13 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty
break;
}
p_clear(&shadow, 1);
if(parser_data.shadow.offset)
shadow = parser_data.shadow;
else if(style->shadow.offset)
shadow = style->shadow;
if(shadow.offset)
{
cairo_set_source_rgb(ctx->cr,
shadow.color.red / 65535.0,
shadow.color.green / 65535.0,
shadow.color.blue / 65535.0);
cairo_move_to(ctx->cr, x + shadow.offset, y + shadow.offset);
parser_data.shadow.color.red / 65535.0,
parser_data.shadow.color.green / 65535.0,
parser_data.shadow.color.blue / 65535.0);
cairo_move_to(ctx->cr, x + parser_data.shadow.offset, y + parser_data.shadow.offset);
pango_cairo_update_layout(ctx->cr, ctx->layout);
pango_cairo_show_layout(ctx->cr, ctx->layout);
}
@ -362,9 +357,9 @@ draw_text(draw_context_t *ctx, area_t area, const char *text, const style_t *sty
cairo_move_to(ctx->cr, x, y);
cairo_set_source_rgb(ctx->cr,
style->fg.red / 65535.0,
style->fg.green / 65535.0,
style->fg.blue / 65535.0);
fg->red / 65535.0,
fg->green / 65535.0,
fg->blue / 65535.0);
pango_cairo_update_layout(ctx->cr, ctx->layout);
pango_cairo_show_layout(ctx->cr, ctx->layout);
@ -1078,48 +1073,6 @@ draw_color_new(xcb_connection_t *conn, int phys_screen, const char *colstr, xcol
return false;
}
/** Init a style struct. Every value will be inherited from m
* if they are not set in the configuration section cfg.
* \param disp Display ref
* \param phys_screen Physical screen number
* \param cfg style configuration section
* \param c style to fill
* \param m style to use as template
*/
void
draw_style_init(xcb_connection_t *conn, int phys_screen, cfg_t *cfg,
style_t *c, style_t *m)
{
char *buf;
int shadow;
if(m)
*c = *m;
if(!cfg)
return;
if((buf = cfg_getstr(cfg, "font")))
c->font = draw_font_new(conn, phys_screen, buf);
draw_color_new(conn, phys_screen,
cfg_getstr(cfg, "fg"), &c->fg);
draw_color_new(conn, phys_screen,
cfg_getstr(cfg, "bg"), &c->bg);
draw_color_new(conn, phys_screen,
cfg_getstr(cfg, "border"), &c->border);
draw_color_new(conn, phys_screen,
cfg_getstr(cfg, "shadow_color"), &c->shadow.color);
if((shadow = cfg_getint(cfg, "shadow_offset")) != (int) 0xffffffff)
c->shadow.offset = shadow;
else if(!m)
c->shadow.offset = 0;
}
/** Remove a area from a list of them,
* spliting the space between several area that can overlap
* \param head list head

View File

@ -35,7 +35,7 @@
typedef enum
{
AlignLeft,
AlignLeft = 0,
AlignRight,
AlignCenter,
AlignFlex,
@ -88,27 +88,6 @@ typedef struct
int height;
} font_t;
typedef struct
{
int offset;
xcolor_t color;
} shadow_t;
/** Style structure */
typedef struct
{
/** Foreground color */
xcolor_t fg;
/** Background color */
xcolor_t bg;
/** Shadow color */
shadow_t shadow;
/** Border color */
xcolor_t border;
/** Font */
font_t *font;
} style_t;
typedef struct
{
xcb_connection_t *connection;
@ -132,17 +111,20 @@ draw_context_delete(draw_context_t **ctx)
{
if(*ctx)
{
g_object_unref((*ctx)->layout);
cairo_surface_destroy((*ctx)->surface);
cairo_destroy((*ctx)->cr);
if((*ctx)->layout)
g_object_unref((*ctx)->layout);
if((*ctx)->surface)
cairo_surface_destroy((*ctx)->surface);
if((*ctx)->cr)
cairo_destroy((*ctx)->cr);
p_delete(ctx);
}
}
font_t *draw_font_new(xcb_connection_t *, int, char *);
font_t *draw_font_new(xcb_connection_t *, int, const char *);
void draw_font_delete(font_t **);
void draw_text(draw_context_t *, area_t, const char *, const style_t *);
void draw_text(draw_context_t *, font_t *, xcolor_t *, area_t, const char *);
void draw_rectangle(draw_context_t *, area_t, float, bool, xcolor_t);
void draw_rectangle_gradient(draw_context_t *, area_t, float, bool, area_t, xcolor_t *, xcolor_t *, xcolor_t *);
@ -157,7 +139,6 @@ void draw_rotate(draw_context_t *, xcb_drawable_t, int, int, double, int, int);
area_t draw_text_extents(xcb_connection_t *, int, font_t *, const char *);
alignment_t draw_align_get_from_str(const char *);
bool draw_color_new(xcb_connection_t *, int, const char *, xcolor_t *);
void draw_style_init(xcb_connection_t *, int, cfg_t *, style_t *, style_t *);
void area_list_remove(area_t **, area_t *);

View File

@ -159,7 +159,7 @@
return NULL; \
} \
\
static inline void prefix##_list_detach(type **list, type *item) \
static inline type *prefix##_list_detach(type **list, type *item) \
{ \
if(item == *list) \
*list = item->next; \
@ -169,7 +169,27 @@
item->next->prev = item->prev; \
item->next = NULL; \
item->prev = NULL; \
} \
return item; \
}
#define DO_SLIST_UNREF(type, prefix, dtor) \
static inline void prefix##_list_unref(type **list) \
{ \
type *next, *item = *list; \
printf("list_unref\n");\
while(item) \
{ \
printf(" item %p refcount %d", item, item->refcount);\
next = item->next; \
if(--(item->refcount) <= 0) \
{ \
prefix##_list_detach(list, item); \
dtor(&item); \
} \
item = next; \
} \
printf("end list_unref\n");\
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

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.
*/
ssize_t a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l)
ssize_t
a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l)
{
ssize_t len = MIN(a_strlen(src), l);
@ -200,7 +201,8 @@ ssize_t a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l)
* \return \c src \e length. If this value is \>= \c n then the copy was
* truncated.
*/
ssize_t a_strcpy(char *dst, ssize_t n, const char *src)
ssize_t
a_strcpy(char *dst, ssize_t n, const char *src)
{
ssize_t len = a_strlen(src);
@ -213,4 +215,28 @@ ssize_t a_strcpy(char *dst, ssize_t n, const char *src)
return len;
}
/** Execute a command and replace the current process.
* \param cmd The command to execute.
*/
void
a_exec(const char *cmd)
{
char *args, *path;
/* Ignore the leading spaces if any */
while(cmd[0] && cmd[0] == ' ') cmd++;
/* Get the beginning of the arguments */
args = strchr(cmd, ' ');
if(args)
path = a_strndup(cmd, args - cmd);
else
path = a_strndup(cmd, a_strlen(cmd));
execlp(path, cmd, NULL);
p_delete(&path);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

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

View File

@ -505,4 +505,79 @@ xutil_delete_error(xutil_error_t *err)
p_delete(&err);
}
/** Link a name to a key symbol */
typedef struct
{
const char *name;
xcb_keysym_t keysym;
} keymod_t;
xcb_keysym_t
xutil_keymask_fromstr(const char *keyname)
{
/** List of keyname and corresponding X11 mask codes */
static const keymod_t KeyModList[] =
{
{ "Shift", XCB_MOD_MASK_SHIFT },
{ "Lock", XCB_MOD_MASK_LOCK },
{ "Control", XCB_MOD_MASK_CONTROL },
{ "Ctrl", XCB_MOD_MASK_CONTROL },
{ "Mod1", XCB_MOD_MASK_1 },
{ "Mod2", XCB_MOD_MASK_2 },
{ "Mod3", XCB_MOD_MASK_3 },
{ "Mod4", XCB_MOD_MASK_4 },
{ "Mod5", XCB_MOD_MASK_5 },
{ NULL, XCB_NO_SYMBOL }
};
int i;
if(keyname)
for(i = 0; KeyModList[i].name; i++)
if(!a_strcmp(keyname, KeyModList[i].name))
return KeyModList[i].keysym;
return XCB_NO_SYMBOL;
}
/** Permit to use mouse with many more buttons */
#ifndef XCB_BUTTON_INDEX_6
#define XCB_BUTTON_INDEX_6 6
#endif
#ifndef XCB_BUTTON_INDEX_7
#define XCB_BUTTON_INDEX_7 7
#endif
/** Link a name to a mouse button symbol */
typedef struct
{
int id;
unsigned int button;
} mouse_button_t;
/** Lookup for a mouse button from its index.
* \param button Mouse button index.
* \return Mouse button or 0 if not found.
*/
unsigned int
xutil_button_fromint(int button)
{
/** List of button name and corresponding X11 mask codes */
static const mouse_button_t mouse_button_list[] =
{
{ 1, XCB_BUTTON_INDEX_1 },
{ 2, XCB_BUTTON_INDEX_2 },
{ 3, XCB_BUTTON_INDEX_3 },
{ 4, XCB_BUTTON_INDEX_4 },
{ 5, XCB_BUTTON_INDEX_5 },
{ 6, XCB_BUTTON_INDEX_6 },
{ 7, XCB_BUTTON_INDEX_7 }
};
if(button >= 1 && button <= countof(mouse_button_list))
return mouse_button_list[button - 1].button;
return 0;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

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

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 -*-
# Process this file with autoreconf to produce a configure script.
m4_include(as_ac_expand.m4)
AC_PREREQ(2.61)
dnl Each time you want an updated version number for your build, you need to
dnl (re-)run autoreconf.
@ -44,17 +46,14 @@ AC_ARG_VAR([DOXYGEN], [doxygen source documentation system])
test "x$ASCIIDOC" = "x" && AC_PATH_PROG([ASCIIDOC], [asciidoc], [:])
test "x$XMLTO" = "x" && AC_PATH_PROG([XMLTO], [xmlto], [:])
test "x$DOXYGEN" = "x" && AC_PATH_PROG([PYTHON], [python], [:])
test "x$DOXYGEN" = "x" && AC_PATH_PROG([DOXYGEN], [doxygen], [:])
test "x$ASCIIDOC" = "x:" && AC_MSG_WARN([awesome man page generation requires asciidoc])
test "x$XMLTO" = "x:" && AC_MSG_WARN([awesome man page generation requires xmlto])
test "x$PYTHON" = "x:" && AC_MSG_WARN([awesome man page generation requires python])
test "x$DOXYGEN" = "x:" && AC_MSG_WARN([awesome developer doc generation requires doxygen])
AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$ASCIIDOC" != "x:"])
AM_CONDITIONAL([HAVE_XMLTO], [test "x$XMLTO" != "x:"])
AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != "x:"])
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != "x:"])
xmlto_man_works=no
@ -107,12 +106,15 @@ AC_PATH_PROG([WHOAMI], [whoami], [false])
AS_IF([test "x$WHOAMI" = "xfalse"], [aw_whoami="???"], [aw_whoami=`$WHOAMI`])
AC_DEFINE_UNQUOTED([AWESOME_COMPILE_BY], ["$aw_whoami"], [build user])
AS_AC_EXPAND(awesomelibdir, "$datarootdir/awesome/lib")
AC_DEFINE_UNQUOTED([AWESOME_LIB_PATH], "${awesomelibdir}", [awesome lib path])
# Checks for libraries.
AC_PATH_XTRA
PKG_CHECK_MODULES([pangocairo], [pangocairo],,
[AC_MSG_ERROR([awesome requires pangocairo.])])
PKG_CHECK_MODULES([confuse], [libconfuse >= 2.6],,
[AC_MSG_ERROR([awesome requires libconfuse >= 2.6.])])
PKG_CHECK_MODULES([Lua], [lua5.1],,
[AC_MSG_ERROR([awesome requires Lua >= 5.1.])])
PKG_CHECK_MODULES([glib], [glib-2.0],,
[AC_MSG_ERROR([awesome requires glib-2.0.])])
PKG_CHECK_MODULES([dbus], [dbus-1],,

134
event.c
View File

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

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_expose(void *, xcb_connection_t *, xcb_expose_event_t *);
int event_handle_keypress(void *, xcb_connection_t *, xcb_key_press_event_t *);
int event_handle_mappingnotify(void *, xcb_connection_t *, xcb_mapping_notify_event_t *);
int event_handle_maprequest(void *, xcb_connection_t *, xcb_map_request_event_t *);
int event_handle_propertynotify(void *, xcb_connection_t *, xcb_property_notify_event_t *);
int event_handle_unmapnotify(void *, xcb_connection_t *, xcb_unmap_notify_event_t *);

18
ewmh.c
View File

@ -281,7 +281,11 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
/* restore geometry */
geometry = c->m_geometry;
/* restore borders and titlebar */
titlebar_position_set(&c->titlebar, c->titlebar.dposition);
if((c->titlebar.position = c->titlebar_oldposition))
{
c->titlebar.position = c->titlebar_oldposition;
xcb_map_window(globalconf.connection, c->titlebar_sw->window);
}
c->border = c->oldborder;
c->ismax = false;
client_setfloating(c, c->wasfloating, c->oldlayer);
@ -293,7 +297,11 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
c->m_geometry = c->geometry;
c->wasfloating = c->isfloating;
/* disable titlebar and borders */
titlebar_position_set(&c->titlebar, Off);
if((c->titlebar_oldposition = c->titlebar.position))
{
xcb_unmap_window(globalconf.connection, c->titlebar_sw->window);
c->titlebar.position = Off;
}
c->oldborder = c->border;
c->border = 0;
c->ismax = true;
@ -343,7 +351,11 @@ ewmh_process_window_type_atom(client_t *c, xcb_atom_t state)
c->border = 0;
c->skip = true;
c->isfixed = true;
titlebar_position_set(&c->titlebar, Off);
if(c->titlebar.position)
{
xcb_unmap_window(globalconf.connection, c->titlebar_sw->window);
c->titlebar.position = Off;
}
client_setfloating(c, true, LAYER_ABOVE);
}
else if (state == net_wm_window_type_dialog)

50
focus.c
View File

@ -99,54 +99,4 @@ focus_get_current_client(int screen)
return sel;
}
/** Jump back in the focus history stack.
* Set arg to 0 for previous, -1 for previous of previous, etc.
* \param screen Screen ID
* \param arg Integer argument
* \ingroup ui_callback
*/
void
uicb_focus_history(int screen, char *arg)
{
int i;
tag_t **curtags;
client_t *c;
if(arg)
{
i = atoi(arg);
if(i < 0)
{
curtags = tags_get_current(screen);
c = focus_get_latest_client_for_tags(curtags, i);
p_delete(&curtags);
if(c)
client_focus(c, screen, true);
}
}
}
/** Focus one of the visible clients by its name.
* \param screen screen id
* \param arg client's name
* \ingroup ui_callback
*/
void
uicb_focus_client_byname(int screen, char *arg)
{
client_t *c;
tag_t **curtags, **tag;
if(arg)
{
curtags = tags_get_current(screen);
if((c = client_get_byname(globalconf.clients, arg)))
for(tag = curtags; *tag; tag++)
if(is_client_tagged(c, *tag))
client_focus(c, screen, true);
p_delete(&curtags);
}
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -28,9 +28,6 @@ void focus_add_client(client_t *);
void focus_delete_client(client_t *);
client_t * focus_get_current_client(int);
uicb_t uicb_focus_history;
uicb_t uicb_focus_client_byname;
DO_SLIST(client_node_t, client_node, p_delete)
#endif

View File

@ -36,8 +36,6 @@
extern AwesomeConf globalconf;
#include "layoutgen.h"
/** Arrange windows following current selected layout
* \param screen the screen to arrange
*/
@ -45,7 +43,7 @@ static void
arrange(int screen)
{
client_t *c;
Layout *curlay = layout_get_current(screen);
LayoutArrange *curlay = layout_get_current(screen);
int phys_screen = screen_virttophys(screen);
xcb_query_pointer_cookie_t qp_c;
xcb_query_pointer_reply_t *qp_r;
@ -59,24 +57,19 @@ arrange(int screen)
client_ban(c);
}
curlay->arrange(screen);
if(curlay)
curlay(screen);
for(c = globalconf.clients; c; c = c->next)
if(c->newcomer && client_isvisible(c, screen))
{
c->newcomer = false;
client_unban(c);
if(globalconf.screens[screen].new_get_focus
&& !c->skip
&& (!globalconf.focus->client || !globalconf.focus->client->ismax))
client_focus(c, screen, true);
else if(globalconf.focus->client && globalconf.focus->client->ismax)
client_stack(globalconf.focus->client);
}
/* if we have a valid client that could be focused but currently no window
* are focused, then set the focus on this window */
if((c = focus_get_current_client(screen)) && globalconf.focus->client != c)
if((c = focus_get_current_client(screen)) && !globalconf.focus->client)
client_focus(c, screen, true);
qp_c = xcb_query_pointer_unchecked(globalconf.connection,
@ -87,7 +80,7 @@ arrange(int screen)
if((qp_r = xcb_query_pointer_reply(globalconf.connection, qp_c, NULL)))
{
if(qp_r->root == XCB_NONE || qp_r->child == XCB_NONE || qp_r->root == qp_r->child)
window_root_grabbuttons(phys_screen);
window_root_grabbuttons();
globalconf.pointer_x = qp_r->root_x;
globalconf.pointer_y = qp_r->root_y;
@ -117,62 +110,21 @@ layout_refresh(void)
return arranged;
}
/** Get current layout used on screen
* \param screen screen id
/** Get current layout used on screen.
* \param screen Virtual screen number.
* \return layout used on that screen
*/
Layout *
LayoutArrange *
layout_get_current(int screen)
{
LayoutArrange *l = NULL;
tag_t **curtags = tags_get_current(screen);
Layout *l = curtags[0]->layout;
if(curtags[0])
l = curtags[0]->layout;
p_delete(&curtags);
return l;
}
/** Set the layout of the current tag.
* Argument must be a relative or absolute integer of available layouts.
* \param screen Screen ID
* \param arg Layout specifier
* \ingroup ui_callback
*/
void
uicb_tag_setlayout(int screen, char *arg)
{
Layout *l = globalconf.screens[screen].layouts;
tag_t *tag, **curtags;
int i;
if(arg)
{
curtags = tags_get_current(screen);
for(i = 0; l && l != curtags[0]->layout; i++, l = l->next);
p_delete(&curtags);
if(!l)
i = 0;
i = compute_new_value_from_arg(arg, (double) i);
if(i >= 0)
for(l = globalconf.screens[screen].layouts; l && i > 0; i--)
l = l->next;
else
for(l = globalconf.screens[screen].layouts; l && i < 0; i++)
l = layout_list_prev_cycle(&globalconf.screens[screen].layouts, l);
if(!l)
l = globalconf.screens[screen].layouts;
}
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
if(tag->selected)
tag->layout = l;
if(globalconf.focus->client)
arrange(screen);
widget_invalidate_cache(screen, WIDGET_CACHE_LAYOUTS);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

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

View File

@ -81,7 +81,7 @@ layout_fibonacci(int screen, int shape)
}
geometry.width -= 2 * c->border;
geometry.height -= 2 * c->border;
client_resize(c, geometry, globalconf.screens[screen].resize_hints);
client_resize(c, geometry, globalconf.resize_hints);
geometry.width += 2 * c->border;
geometry.height += 2 * c->border;
}

View File

@ -22,7 +22,6 @@
#include <stdio.h>
#include "screen.h"
#include "awesome.h"
#include "tag.h"
#include "client.h"
#include "layouts/tile.h"
@ -30,99 +29,6 @@
extern AwesomeConf globalconf;
void
uicb_tag_setnmaster(int screen, char * arg)
{
tag_t **curtags = tags_get_current(screen);
Layout *curlay = curtags[0]->layout;
client_t *c;
int n;
if(!arg || (curlay->arrange != layout_tile
&& curlay->arrange != layout_tileleft
&& curlay->arrange != layout_tilebottom
&& curlay->arrange != layout_tiletop))
return;
if((curtags[0]->nmaster = (int) compute_new_value_from_arg(arg, (double) curtags[0]->nmaster)) < 0)
curtags[0]->nmaster = 0;
for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))
n++;
if(curtags[0]->nmaster > n - 1)
curtags[0]->nmaster = n;
p_delete(&curtags);
globalconf.screens[screen].need_arrange = true;
}
void
uicb_tag_setncol(int screen, char * arg)
{
tag_t **curtags = tags_get_current(screen);
Layout *curlay = curtags[0]->layout;
client_t *c;
int n;
if(!arg || (curlay->arrange != layout_tile
&& curlay->arrange != layout_tileleft
&& curlay->arrange != layout_tilebottom
&& curlay->arrange != layout_tiletop))
return;
if((curtags[0]->ncol = (int) compute_new_value_from_arg(arg, (double) curtags[0]->ncol)) < 1)
curtags[0]->ncol = 1;
for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))
n++;
if(curtags[0]->ncol > n - 1)
curtags[0]->ncol = n - 1;
p_delete(&curtags);
globalconf.screens[screen].need_arrange = true;
}
void
uicb_tag_setmwfact(int screen, char *arg)
{
char *newarg;
tag_t **curtags = tags_get_current(screen);
Layout *curlay = curtags[0]->layout;
if(!arg || (curlay->arrange != layout_tile
&& curlay->arrange != layout_tileleft
&& curlay->arrange != layout_tilebottom
&& curlay->arrange != layout_tiletop))
return;
newarg = a_strdup(arg);
if(curlay->arrange == layout_tileleft || curlay->arrange == layout_tiletop)
{
if(newarg[0] == '+')
newarg[0] = '-';
else if(arg[0] == '-')
newarg[0] = '+';
}
curtags[0]->mwfact = compute_new_value_from_arg(newarg, curtags[0]->mwfact);
if(curtags[0]->mwfact < globalconf.screens[screen].mwfact_lower_limit)
curtags[0]->mwfact = globalconf.screens[screen].mwfact_lower_limit;
else if(curtags[0]->mwfact > globalconf.screens[screen].mwfact_upper_limit)
curtags[0]->mwfact = globalconf.screens[screen].mwfact_upper_limit;
p_delete(&newarg);
p_delete(&curtags);
globalconf.screens[screen].need_arrange = true;
}
static void
_tile(int screen, const position_t position)
{
@ -206,7 +112,7 @@ _tile(int screen, const position_t position)
geometry.width = mw - 2 * c->border;
geometry.height = mh - 2 * c->border;
client_resize(c, geometry, globalconf.screens[screen].resize_hints);
client_resize(c, geometry, globalconf.resize_hints);
}
else
{
@ -257,7 +163,7 @@ _tile(int screen, const position_t position)
if(position == Bottom)
geometry.y += mh;
}
client_resize(c, geometry, globalconf.screens[screen].resize_hints);
client_resize(c, geometry, globalconf.resize_hints);
}
i++;
}

View File

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

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
*/
static area_t
mouse_snapclient(client_t *c, area_t geometry)
mouse_snapclient(client_t *c, area_t geometry, int snap)
{
client_t *snapper;
int snap = globalconf.screens[c->screen].snap;
area_t snapper_geometry;
area_t screen_geometry =
screen_get_area(c->screen,
@ -117,8 +116,7 @@ mouse_snapclient(client_t *c, area_t geometry)
snapper_geometry = snapper->geometry;
snapper_geometry.width += 2 * c->border;
snapper_geometry.height += 2 * c->border;
snapper_geometry = titlebar_geometry_add(&snapper->titlebar,
snapper_geometry);
snapper_geometry = titlebar_geometry_add(&snapper->titlebar, snapper_geometry);
geometry =
mouse_snapclienttogeometry_outside(geometry,
snapper_geometry,
@ -137,15 +135,17 @@ mouse_snapclient(client_t *c, area_t geometry)
* \param border The client border size.
*/
static void
mouse_resizebar_draw(draw_context_t *ctx, style_t *style,
simple_window_t *sw, area_t geometry, int border)
mouse_resizebar_draw(draw_context_t *ctx,
simple_window_t *sw,
area_t geometry, int border)
{
area_t draw_geometry = { 0, 0, ctx->width, ctx->height, NULL, NULL };
char size[64];
snprintf(size, sizeof(size), "<text align=\"center\"/>%dx%d+%d+%d",
geometry.x, geometry.y, geometry.width, geometry.height);
draw_text(ctx, draw_geometry, size, style);
draw_rectangle(ctx, draw_geometry, 1.0, true, globalconf.colors.bg);
draw_text(ctx, globalconf.font, &globalconf.colors.fg, draw_geometry, size);
simplewindow_move(sw,
geometry.x + ((2 * border + geometry.width) - sw->geometry.width) / 2,
geometry.y + ((2 * border + geometry.height) - sw->geometry.height) / 2);
@ -162,14 +162,14 @@ mouse_resizebar_draw(draw_context_t *ctx, style_t *style,
*/
static simple_window_t *
mouse_resizebar_new(int phys_screen, int border, area_t geometry,
style_t *style, draw_context_t **ctx)
draw_context_t **ctx)
{
simple_window_t *sw;
area_t geom;
geom = draw_text_extents(globalconf.connection,
globalconf.default_screen,
style->font,
globalconf.font,
"0000x0000+0000+0000");
geom.x = geometry.x + ((2 * border + geometry.width) - geom.width) / 2;
geom.y = geometry.y + ((2 * border + geometry.height) - geom.height) / 2;
@ -183,37 +183,36 @@ mouse_resizebar_new(int phys_screen, int border, area_t geometry,
sw->drawable);
xcb_map_window(globalconf.connection, sw->window);
mouse_resizebar_draw(*ctx, style, sw, geometry, border);
mouse_resizebar_draw(*ctx, sw, geometry, border);
return sw;
}
/** Move the focused window with the mouse.
* \param screen Screen ID
* \param arg Unused
* \ingroup ui_callback
*/
void
uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
mouse_client_move(int snap)
{
int ocx, ocy, newscreen;
area_t geometry;
client_t *c = globalconf.focus->client, *target;
Layout *layout = layout_get_current(screen);
LayoutArrange *layout;
simple_window_t *sw = NULL;
draw_context_t *ctx;
style_t *style;
xcb_generic_event_t *ev = NULL;
xcb_motion_notify_event_t *ev_motion = NULL;
xcb_grab_pointer_reply_t *grab_pointer_r = NULL;
xcb_grab_pointer_cookie_t grab_pointer_c;
xcb_query_pointer_reply_t *query_pointer_r = NULL, *mquery_pointer_r = NULL;
xcb_query_pointer_cookie_t query_pointer_c;
xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
xcb_screen_t *s;
if(!c)
return;
layout = layout_get_current(c->screen);
s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
/* Send pointer requests */
grab_pointer_c = xcb_grab_pointer(globalconf.connection, false, s->root,
MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
@ -224,7 +223,6 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
geometry = c->geometry;
ocx = geometry.x;
ocy = geometry.y;
style = &globalconf.screens[c->screen].styles.focus;
/* Get responses */
if(!(grab_pointer_r = xcb_grab_pointer_reply(globalconf.connection, grab_pointer_c, NULL)))
@ -236,9 +234,9 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
query_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL);
if(c->isfloating || layout->arrange == layout_floating)
if(c->isfloating || layout == layout_floating)
{
sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, style, &ctx);
sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, &ctx);
xcb_aux_sync(globalconf.connection);
}
@ -261,20 +259,20 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
p_delete(&ev);
return;
case XCB_MOTION_NOTIFY:
if(c->isfloating || layout->arrange == layout_floating)
if(c->isfloating || layout == layout_floating)
{
ev_motion = (xcb_motion_notify_event_t *) ev;
geometry.x = ocx + (ev_motion->event_x - query_pointer_r->root_x);
geometry.y = ocy + (ev_motion->event_y - query_pointer_r->root_y);
geometry = mouse_snapclient(c, geometry);
geometry = mouse_snapclient(c, geometry, snap);
c->ismoving = true;
client_resize(c, geometry, false);
c->ismoving = false;
if(sw)
mouse_resizebar_draw(ctx, style, sw, c->geometry, c->border);
mouse_resizebar_draw(ctx, sw, c->geometry, c->border);
xcb_aux_sync(globalconf.connection);
}
@ -317,53 +315,53 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
/** Resize the focused window with the mouse.
* \param screen Screen ID
* \param arg Unused
* \ingroup ui_callback
*/
void
uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
mouse_client_resize(void)
{
int ocx = 0, ocy = 0, n;
xcb_generic_event_t *ev = NULL;
xcb_motion_notify_event_t *ev_motion = NULL;
client_t *c = globalconf.focus->client;
tag_t **curtags = tags_get_current(screen);
Layout *layout = curtags[0]->layout;
tag_t **curtags;
LayoutArrange *layout;
area_t area = { 0, 0, 0, 0, NULL, NULL }, geometry = { 0, 0, 0, 0, NULL, NULL };
double mwfact;
simple_window_t *sw = NULL;
draw_context_t *ctx = NULL;
style_t *style;
xcb_grab_pointer_cookie_t grab_pointer_c;
xcb_grab_pointer_reply_t *grab_pointer_r = NULL;
xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
xcb_screen_t *s;
/* only handle floating and tiled layouts */
if(!c || c->isfixed)
return;
style = &globalconf.screens[c->screen].styles.focus;
curtags = tags_get_current(c->screen);
layout = curtags[0]->layout;
s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
if(layout->arrange == layout_floating || c->isfloating)
if(layout == layout_floating || c->isfloating)
{
ocx = c->geometry.x;
ocy = c->geometry.y;
c->ismax = false;
sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, style, &ctx);
sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, &ctx);
}
else if (layout->arrange == layout_tile || layout->arrange == layout_tileleft
|| layout->arrange == layout_tilebottom || layout->arrange == layout_tiletop)
else if (layout == layout_tile || layout == layout_tileleft
|| layout == layout_tilebottom || layout == layout_tiletop)
{
for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))
if(IS_TILED(c, c->screen))
n++;
if(n <= curtags[0]->nmaster) return;
for(c = globalconf.clients; c && !IS_TILED(c, screen); c = c->next);
for(c = globalconf.clients; c && !IS_TILED(c, c->screen); c = c->next);
if(!c) return;
area = screen_get_area(screen,
area = screen_get_area(c->screen,
globalconf.screens[c->screen].statusbar,
&globalconf.screens[c->screen].padding);
}
@ -380,10 +378,10 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
p_delete(&grab_pointer_r);
if(curtags[0]->layout->arrange == layout_tileleft)
if(curtags[0]->layout == layout_tileleft)
xcb_warp_pointer(globalconf.connection, XCB_NONE, c->win, 0, 0, 0, 0,
0, c->geometry.height + c->border - 1);
else if(curtags[0]->layout->arrange == layout_tiletop)
else if(curtags[0]->layout == layout_tiletop)
xcb_warp_pointer(globalconf.connection, XCB_NONE, c->win, 0, 0, 0, 0,
c->geometry.width + c->border - 1, 0);
else
@ -414,7 +412,7 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
case XCB_MOTION_NOTIFY:
ev_motion = (xcb_motion_notify_event_t *) ev;
if(layout->arrange == layout_floating || c->isfloating)
if(layout == layout_floating || c->isfloating)
{
if((geometry.width = ev_motion->event_x - ocx - 2 * c->border + 1) <= 0)
geometry.width = 1;
@ -424,26 +422,24 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
geometry.y = c->geometry.y;
client_resize(c, geometry, true);
if(sw)
mouse_resizebar_draw(ctx, style, sw, c->geometry, c->border);
mouse_resizebar_draw(ctx, sw, c->geometry, c->border);
xcb_aux_sync(globalconf.connection);
}
else if(layout->arrange == layout_tile || layout->arrange == layout_tileleft
|| layout->arrange == layout_tiletop || layout->arrange == layout_tilebottom)
else if(layout == layout_tile || layout == layout_tileleft
|| layout == layout_tiletop || layout == layout_tilebottom)
{
if(layout->arrange == layout_tile)
if(layout == layout_tile)
mwfact = (double) (ev_motion->event_x - area.x) / area.width;
else if(curtags[0]->layout->arrange == layout_tileleft)
else if(curtags[0]->layout == layout_tileleft)
mwfact = 1 - (double) (ev_motion->event_x - area.x) / area.width;
else if(curtags[0]->layout->arrange == layout_tilebottom)
else if(curtags[0]->layout == layout_tilebottom)
mwfact = (double) (ev_motion->event_y - area.y) / area.height;
else
mwfact = 1 - (double) (ev_motion->event_y - area.y) / area.height;
mwfact = MAX(globalconf.screens[screen].mwfact_lower_limit,
MIN(globalconf.screens[screen].mwfact_upper_limit, mwfact));
if(fabs(curtags[0]->mwfact - mwfact) >= 0.01)
{
curtags[0]->mwfact = mwfact;
globalconf.screens[screen].need_arrange = true;
globalconf.screens[c->screen].need_arrange = true;
layout_refresh();
}
}
@ -461,4 +457,63 @@ uicb_client_resizemouse(int screen, char *arg __attribute__ ((unused)))
}
}
static int
luaA_mouse_coords_set(lua_State *L)
{
int x, y;
x = luaL_checknumber(L, 1);
y = luaL_checknumber(L, 2);
xcb_warp_pointer(globalconf.connection, XCB_NONE,
xcb_aux_get_screen(globalconf.connection, globalconf.default_screen)->root,
0, 0, 0, 0, x, y);
return 0;
}
static int
luaA_mouse_client_resize(lua_State *L __attribute__ ((unused)))
{
mouse_client_resize();
return 0;
}
static int
luaA_mouse_client_move(lua_State *L)
{
int snap = luaL_optnumber(L, 1, 8);
mouse_client_move(snap);
return 0;
}
static int
luaA_mouse_screen_get(lua_State *L)
{
int screen;
xcb_query_pointer_cookie_t qc;
xcb_query_pointer_reply_t *qr;
qc = xcb_query_pointer(globalconf.connection,
xcb_aux_get_screen(globalconf.connection,
globalconf.default_screen)->root);
if(!(qr = xcb_query_pointer_reply(globalconf.connection, qc, NULL)))
return 0;
screen = screen_get_bycoord(globalconf.screens_info,
globalconf.default_screen,
qr->root_x, qr->root_y);
p_delete(&qr);
lua_pushnumber(L, screen + 1);
return 1;
}
const struct luaL_reg awesome_mouse_lib[] =
{
{ "screen_get", luaA_mouse_screen_get },
{ "coords_set", luaA_mouse_coords_set },
{ "client_resize", luaA_mouse_client_resize },
{ "client_move", luaA_mouse_client_move },
{ NULL, NULL }
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

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

View File

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

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

View File

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

View File

@ -32,84 +32,10 @@
extern AwesomeConf globalconf;
static void
statusbar_position_update(statusbar_t *statusbar)
{
statusbar_t *sb;
area_t area;
if(statusbar->position == Off)
{
xcb_unmap_window(globalconf.connection, statusbar->sw->window);
return;
}
xcb_map_window(globalconf.connection, statusbar->sw->window);
/* Top and Bottom statusbar_t have prio */
if(statusbar->position == Top || statusbar->position == Bottom)
area = screen_get_area(statusbar->screen,
NULL,
&globalconf.screens[statusbar->screen].padding);
else
area = screen_get_area(statusbar->screen,
globalconf.screens[statusbar->screen].statusbar,
&globalconf.screens[statusbar->screen].padding);
for(sb = globalconf.screens[statusbar->screen].statusbar; sb && sb != statusbar; sb = sb->next)
switch(sb->position)
{
case Top:
if(sb->position == statusbar->position)
area.y += sb->height;
break;
case Bottom:
if(sb->position == statusbar->position)
area.height -= sb->height;
break;
case Left:
/* we need to re-add our own value removed in the
* screen_get_area computation */
if(statusbar->position == Left
|| statusbar->position == Right)
{
area.x -= statusbar->sw->geometry.width;
area.width += statusbar->sw->geometry.width;
}
break;
case Right:
if(statusbar->position == Left
|| statusbar->position == Right)
area.width += statusbar->sw->geometry.width;
break;
default:
break;
}
switch(statusbar->position)
{
case Top:
simplewindow_move(statusbar->sw, area.x, area.y);
break;
case Bottom:
simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->sw->geometry.height);
break;
case Left:
simplewindow_move(statusbar->sw, area.x - statusbar->sw->geometry.width,
(area.y + area.height) - statusbar->sw->geometry.height);
break;
case Right:
simplewindow_move(statusbar->sw, area.x + area.width, area.y);
break;
default:
break;
}
}
static void
statusbar_draw(statusbar_t *statusbar)
{
widget_t *widget;
widget_node_t *w;
int left = 0, right = 0;
area_t rectangle = { 0, 0, 0, 0, NULL, NULL };
@ -121,22 +47,20 @@ statusbar_draw(statusbar_t *statusbar)
rectangle.width = statusbar->width;
rectangle.height = statusbar->height;
draw_rectangle(statusbar->ctx, rectangle, 1.0, true,
globalconf.screens[statusbar->screen].styles.normal.bg);
statusbar->colors.bg);
for(widget = statusbar->widgets; widget; widget = widget->next)
if (widget->alignment == AlignLeft)
left += widget->draw(widget, statusbar->ctx, left, (left + right));
for(w = statusbar->widgets; w; w = w->next)
if(w->widget->align == AlignLeft)
left += w->widget->draw(w, statusbar, left, (left + right));
/* renders right widget from last to first */
for(widget = *widget_list_last(&statusbar->widgets);
widget;
widget = widget_list_prev(&statusbar->widgets, widget))
if (widget->alignment == AlignRight)
right += widget->draw(widget, statusbar->ctx, right, (left + right));
for(w = *widget_node_list_last(&statusbar->widgets); w; w = w->prev)
if(w->widget->align == AlignRight)
right += w->widget->draw(w, statusbar, right, (left + right));
for(widget = statusbar->widgets; widget; widget = widget->next)
if (widget->alignment == AlignFlex)
left += widget->draw(widget, statusbar->ctx, left, (left + right));
for(w = statusbar->widgets; w; w = w->next)
if(w->widget->align == AlignFlex)
left += w->widget->draw(w, statusbar, left, (left + right));
switch(statusbar->position)
{
@ -158,96 +82,145 @@ statusbar_draw(statusbar_t *statusbar)
}
void
statusbar_preinit(statusbar_t *statusbar)
{
if(statusbar->height <= 0)
/* 1.5 as default factor, it fits nice but no one knows why */
statusbar->height = 1.5 * MAX(globalconf.screens[statusbar->screen].styles.normal.font->height,
MAX(globalconf.screens[statusbar->screen].styles.focus.font->height,
globalconf.screens[statusbar->screen].styles.urgent.font->height));
}
void
statusbar_init(statusbar_t *statusbar)
statusbar_position_update(statusbar_t *statusbar, position_t position)
{
statusbar_t *sb;
area_t area;
xcb_drawable_t dw;
xcb_screen_t *s = NULL;
int phys_screen = screen_virttophys(statusbar->screen);
area_t area = screen_get_area(statusbar->screen,
globalconf.screens[statusbar->screen].statusbar,
&globalconf.screens[statusbar->screen].padding);
bool ignore = false;
statusbar->phys_screen = phys_screen;
simplewindow_delete(&statusbar->sw);
draw_context_delete(&statusbar->ctx);
if((statusbar->position = position) == Off)
return;
area = screen_get_area(statusbar->screen,
NULL,
&globalconf.screens[statusbar->screen].padding);
/* Top and Bottom statusbar_t have prio */
for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next)
{
/* Ignore every statusbar after me that is in the same position */
if(statusbar == sb)
{
ignore = true;
continue;
}
else if(ignore && statusbar->position == sb->position)
continue;
switch(sb->position)
{
case Left:
switch(statusbar->position)
{
case Left:
area.x += statusbar->height;
break;
default:
break;
}
break;
case Right:
area.width += sb->height;
switch(statusbar->position)
{
case Right:
area.x -= statusbar->height;
break;
default:
break;
}
break;
case Top:
switch(statusbar->position)
{
case Top:
area.y += sb->height;
break;
case Left:
case Right:
area.height -= sb->height;
area.y += sb->height;
break;
default:
break;
}
break;
case Bottom:
switch(statusbar->position)
{
case Bottom:
area.y -= sb->height;
break;
case Left:
case Right:
area.height -= sb->height;
break;
default:
break;
}
break;
default:
break;
}
if(statusbar->width <= 0)
{
if(statusbar->position == Right || statusbar->position == Left)
statusbar->width = area.height;
else
statusbar->width = area.width;
}
switch(statusbar->position)
{
case Right:
case Left:
statusbar->sw =
simplewindow_new(globalconf.connection, phys_screen, 0, 0,
statusbar->height, statusbar->width, 0);
break;
default:
statusbar->sw =
simplewindow_new(globalconf.connection, phys_screen, 0, 0,
statusbar->width, statusbar->height, 0);
break;
}
widget_calculate_alignments(statusbar->widgets);
statusbar_position_update(statusbar);
switch(statusbar->position)
{
case Off:
return;
case Right:
case Left:
s = xcb_aux_get_screen(globalconf.connection, phys_screen);
statusbar->width = area.height;
statusbar->sw =
simplewindow_new(globalconf.connection, statusbar->phys_screen, 0, 0,
statusbar->height, statusbar->width, 0);
s = xcb_aux_get_screen(globalconf.connection, statusbar->phys_screen);
/* we need a new pixmap this way [ ] to render */
dw = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection,
s->root_depth, dw, s->root,
statusbar->width, statusbar->height);
statusbar->ctx = draw_context_new(globalconf.connection,
phys_screen,
statusbar->phys_screen,
statusbar->width,
statusbar->height,
dw);
break;
default:
statusbar->width = area.width;
statusbar->sw =
simplewindow_new(globalconf.connection, statusbar->phys_screen, 0, 0,
statusbar->width, statusbar->height, 0);
statusbar->ctx = draw_context_new(globalconf.connection,
phys_screen,
statusbar->phys_screen,
statusbar->width,
statusbar->height,
statusbar->sw->drawable);
break;
}
switch(statusbar->position)
{
case Top:
simplewindow_move(statusbar->sw, area.x, area.y);
break;
case Bottom:
simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->height);
break;
case Left:
simplewindow_move(statusbar->sw, area.x,
(area.y + area.height) - statusbar->sw->geometry.height);
break;
case Right:
simplewindow_move(statusbar->sw, area.x + area.width - statusbar->height, area.y);
break;
default:
break;
}
globalconf.screens[statusbar->screen].need_arrange = true;
xcb_map_window(globalconf.connection, statusbar->sw->window);
statusbar_draw(statusbar);
}
@ -262,10 +235,7 @@ statusbar_refresh()
statusbar;
statusbar = statusbar->next)
if(statusbar->need_update)
{
statusbar_draw(statusbar);
break;
}
}
statusbar_t *
@ -280,36 +250,140 @@ statusbar_getbyname(int screen, const char *name)
return NULL;
}
static void
statusbar_toggle(statusbar_t *statusbar)
static int
luaA_statusbar_eq(lua_State *L)
{
if(statusbar->position == Off)
statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition;
else
statusbar->position = Off;
globalconf.screens[statusbar->screen].need_arrange = true;
statusbar_t **t1 = luaL_checkudata(L, 1, "statusbar");
statusbar_t **t2 = luaL_checkudata(L, 2, "statusbar");
lua_pushboolean(L, (*t1 == *t2));
return 1;
}
/** Toggle the statusbar on or off.
* Argument must be a statusbar name, or no argument for all statusbars.
* \param screen Screen ID
* \param arg statusbar name
* \ingroup ui_callback
*/
void
uicb_statusbar_toggle(int screen, char *arg)
static int
luaA_statusbar_position_set(lua_State *L)
{
statusbar_t *sb = statusbar_getbyname(screen, arg);
statusbar_t *s, **sb = luaL_checkudata(L, 1, "statusbar");
const char *pos = luaL_checkstring(L, 2);
position_t position = position_get_from_str(pos);
if(sb)
statusbar_toggle(sb);
else
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
statusbar_toggle(sb);
if(position != (*sb)->position)
{
(*sb)->position = position;
for(s = globalconf.screens[(*sb)->screen].statusbar; s; s = s->next)
statusbar_position_update(s, s->position);
}
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
statusbar_position_update(sb);
return 0;
}
static int
luaA_statusbar_tostring(lua_State *L)
{
statusbar_t **p = luaL_checkudata(L, 1, "statusbar");
lua_pushfstring(L, "[statusbar udata(%p) name(%s)]", *p, (*p)->name);
return 1;
}
static int
luaA_statusbar_widget_add(lua_State *L)
{
statusbar_t **sb = luaL_checkudata(L, 1, "statusbar");
widget_t **widget = luaL_checkudata(L, 2, "widget");
widget_node_t *w = p_new(widget_node_t, 1);
(*sb)->need_update = true;
w->widget = *widget;
widget_node_list_append(&(*sb)->widgets, w);
widget_ref(widget);
return 0;
}
static int
luaA_statusbar_add(lua_State *L)
{
statusbar_t *s, **sb = luaL_checkudata(L, 1, "statusbar");
int screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen);
(*sb)->screen = screen;
/* \todo check for uniq name */
statusbar_list_append(&globalconf.screens[screen].statusbar, *sb);
for(s = globalconf.screens[(*sb)->screen].statusbar; s; s = s->next)
statusbar_position_update(s, s->position);
statusbar_ref(sb);
(*sb)->screen = screen;
(*sb)->phys_screen = screen_virttophys(screen);
return 0;
}
static int
luaA_statusbar_new(lua_State *L)
{
statusbar_t **sb = lua_newuserdata(L, sizeof(statusbar_t *));
int objpos = lua_gettop(L);
const char *color;
luaA_checktable(L, 1);
*sb = p_new(statusbar_t, 1);
/* \todo check that the name is unique */
(*sb)->name = luaA_name_init(L);
lua_getfield(L, 1, "fg");
if((color = luaL_optstring(L, -1, NULL)))
draw_color_new(globalconf.connection, globalconf.default_screen,
color, &(*sb)->colors.fg);
else
(*sb)->colors.fg = globalconf.colors.fg;
lua_getfield(L, 1, "bg");
if((color = luaL_optstring(L, -1, NULL)))
draw_color_new(globalconf.connection, globalconf.default_screen,
color, &(*sb)->colors.bg);
else
(*sb)->colors.bg = globalconf.colors.bg;
(*sb)->width = luaA_getopt_number(L, 1, "width", 0);
(*sb)->height = luaA_getopt_number(L, 1, "height", 0);
if((*sb)->height <= 0)
/* 1.5 as default factor, it fits nice but no one knows why */
(*sb)->height = 1.5 * globalconf.font->height;
(*sb)->position = position_get_from_str(luaA_getopt_string(L, 1, "position", "top"));
statusbar_ref(sb);
lua_pushvalue(L, objpos);
return luaA_settype(L, "statusbar");
}
static int
luaA_statusbar_gc(lua_State *L)
{
statusbar_t **sb = luaL_checkudata(L, 1, "statusbar");
statusbar_unref(sb);
return 0;
}
const struct luaL_reg awesome_statusbar_methods[] =
{
{ "new", luaA_statusbar_new },
{ NULL, NULL }
};
const struct luaL_reg awesome_statusbar_meta[] =
{
{ "widget_add", luaA_statusbar_widget_add },
{ "position_set", luaA_statusbar_position_set },
{ "add", luaA_statusbar_add },
{ "__gc", luaA_statusbar_gc },
{ "__eq", luaA_statusbar_eq },
{ "__tostring", luaA_statusbar_tostring },
{ NULL, NULL },
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -23,15 +23,26 @@
#define AWESOME_STATUSBAR_H
#include "structs.h"
#include "widget.h"
#include "common/refcount.h"
#include "common/swindow.h"
static inline void
statusbar_delete(statusbar_t **statusbar)
{
simplewindow_delete(&(*statusbar)->sw);
widget_node_list_wipe(&(*statusbar)->widgets);
p_delete(&(*statusbar)->name);
p_delete(statusbar);
}
void statusbar_position_update(statusbar_t *, position_t);
void statusbar_refresh(void);
void statusbar_preinit(statusbar_t *);
void statusbar_init(statusbar_t *);
statusbar_t * statusbar_getbyname(int, const char *);
uicb_t uicb_statusbar_toggle;
DO_SLIST(statusbar_t, statusbar, p_delete)
DO_RCNT(statusbar_t, statusbar, statusbar_delete)
DO_SLIST(statusbar_t, statusbar, statusbar_delete)
DO_SLIST_UNREF(statusbar_t, statusbar, statusbar_delete)
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

192
structs.h
View File

@ -25,10 +25,13 @@
#include <xcb/xcb_event.h>
#include <regex.h>
#include "lua.h"
#include "layout.h"
#include "common/draw.h"
#include "common/swindow.h"
#include "common/xscreen.h"
#include "common/refcount.h"
/** stacking layout */
typedef enum
@ -47,58 +50,60 @@ enum
typedef struct
{
simple_window_t *sw;
/** Ref count */
int refcount;
position_t position;
position_t dposition;
alignment_t align;
int width, height;
char *text_normal, *text_focus, *text_urgent;
} titlebar_t;
/** Rule type */
typedef struct rule_t rule_t;
struct rule_t
static inline void
titlebar_delete(titlebar_t **t)
{
char *icon;
char *xprop;
int screen;
fuzzy_t isfloating;
fuzzy_t ismaster;
titlebar_t titlebar;
double opacity;
regex_t *prop_r;
regex_t *tags_r;
regex_t *xpropval_r;
/** Next and previous rules */
rule_t *prev, *next;
};
p_delete(&(*t)->text_normal);
p_delete(&(*t)->text_focus);
p_delete(&(*t)->text_urgent);
p_delete(t);
}
DO_RCNT(titlebar_t, titlebar, titlebar_delete)
/** Keys bindings */
typedef struct keybinding_t keybinding_t;
struct keybinding_t
{
/** Key modifier */
unsigned long mod;
/** Keysym */
xcb_keysym_t keysym;
/** Keycode */
xcb_keycode_t keycode;
uicb_t *func;
char *arg;
/** Lua function to execute. */
luaA_function fct;
/** Next and previous keys */
keybinding_t *prev, *next;
};
DO_SLIST(keybinding_t, keybinding, p_delete)
/** Mouse buttons bindings */
typedef struct Button Button;
struct Button
{
/** Key modifiers */
unsigned long mod;
/** Mouse button number */
unsigned int button;
uicb_t *func;
char *arg;
/** Lua function to execute. */
luaA_function fct;
/** Next and previous buttons */
Button *prev, *next;
};
/** widget_t tell status code */
DO_SLIST(Button, button, p_delete)
/** Widget tell status code */
typedef enum
{
WIDGET_NOERROR = 0,
@ -110,41 +115,67 @@ typedef enum
WIDGET_ERROR_FORMAT_SECTION
} widget_tell_status_t;
/** widget_t */
/** Widget */
typedef struct widget_t widget_t;
typedef struct widget_node_t widget_node_t;
typedef struct statusbar_t statusbar_t;
struct widget_t
{
/** Ref count */
int refcount;
/** widget_t name */
char *name;
/** Draw function */
int (*draw)(widget_t *, draw_context_t *, int, int);
int (*draw)(widget_node_t *, statusbar_t *, int, int);
/** Update function */
widget_tell_status_t (*tell)(widget_t *, char *, char *);
widget_tell_status_t (*tell)(widget_t *, const char *, const char *);
/** ButtonPressedEvent handler */
void (*button_press)(widget_t *, xcb_button_press_event_t *);
/** statusbar_t */
statusbar_t *statusbar;
void (*button_press)(widget_node_t *, statusbar_t *, xcb_button_press_event_t *);
/** Alignement */
alignment_t alignment;
alignment_t align;
/** Misc private data */
void *data;
/** true if user supplied coords */
bool user_supplied_x;
bool user_supplied_y;
/** area_t */
area_t area;
/** Buttons bindings */
Button *buttons;
/** Cache flags */
int cache_flags;
/** Next and previous widgets */
widget_t *prev, *next;
};
struct widget_node_t
{
/** The widget */
widget_t *widget;
/** The area where the widget was drawn */
area_t area;
/** Next and previous widget in the list */
widget_node_t *prev, *next;
};
static inline void
widget_delete(widget_t **widget)
{
button_list_wipe(&(*widget)->buttons);
p_delete(&(*widget)->data);
p_delete(&(*widget)->name);
p_delete(widget);
}
DO_RCNT(widget_t, widget, widget_delete)
static inline void
widget_node_delete(widget_node_t **node)
{
widget_unref(&(*node)->widget);
p_delete(node);
}
DO_SLIST(widget_node_t, widget_node, widget_node_delete)
/** Status bar */
struct statusbar_t
{
/** Ref count */
int refcount;
/** Window */
simple_window_t *sw;
/** statusbar_t name */
@ -153,20 +184,23 @@ struct statusbar_t
int width;
/** Bar height */
int height;
/** Default position */
position_t dposition;
/** Bar position */
position_t position;
/** Screen */
int screen;
/** Physical screen id */
int phys_screen;
/** widget_t list */
widget_t *widgets;
/** Widget list */
widget_node_t *widgets;
/** Draw context */
draw_context_t *ctx;
/** Need update */
bool need_update;
/** Default colors */
struct
{
xcolor_t fg, bg;
} colors;
/** Next and previous statusbars */
statusbar_t *prev, *next;
};
@ -212,11 +246,14 @@ struct client_t
int phys_screen;
/** True if the client is a new one */
bool newcomer;
/** titlebar_t */
/** Titlebar */
titlebar_t titlebar;
/** layer in the stacking order */
layer_t layer;
layer_t oldlayer;
/** Titlebar window */
simple_window_t *titlebar_sw;
/** Old position */
position_t titlebar_oldposition;
/** Layer in the stacking order */
layer_t layer, oldlayer;
};
typedef struct client_node_t client_node_t;
@ -231,16 +268,16 @@ struct client_node_t
typedef struct _tag_t tag_t;
struct _tag_t
{
/** Ref count */
int refcount;
/** Tag name */
char *name;
/** Screen */
int screen;
/** true if selected */
bool selected;
/** true if was selected before selecting others tags */
bool was_selected;
/** Current tag layout */
Layout *layout;
LayoutArrange *layout;
/** Master width factor */
double mwfact;
/** Number of master windows */
@ -277,43 +314,10 @@ typedef struct
typedef area_t (FloatingPlacement)(client_t *);
typedef struct
{
/** titlebar_t default parameters */
titlebar_t titlebar_default;
/** Number of pixels to snap windows */
int snap;
/** Border size */
int borderpx;
/** Mwfact limits */
float mwfact_upper_limit, mwfact_lower_limit;
/** Floating window placement algo */
FloatingPlacement *floating_placement;
/** Respect resize hints */
bool resize_hints;
/** Sloppy focus: focus follow mouse */
bool sloppy_focus;
/** true if we should raise windows on focus */
bool sloppy_focus_raise;
/** Focus new clients */
bool new_get_focus;
/** true if new clients should become master */
bool new_become_master;
/** true if we need to arrange() */
bool need_arrange;
/** Colors */
struct
{
style_t normal;
style_t focus;
style_t urgent;
} styles;
/** Transparency of unfocused clients */
double opacity_unfocused;
/** Transparency of focused clients */
double opacity_focused;
/** Tag list */
tag_t *tags;
/** Layout list */
Layout *layouts;
/** Status bar */
statusbar_t *statusbar;
/** Padding */
@ -336,8 +340,6 @@ struct AwesomeConf
VirtScreen *screens;
/** Screens info */
screens_info_t *screens_info;
/** Rules list */
rule_t *rules;
/** Keys bindings list */
keybinding_t *keys;
/** Mouse bindings list */
@ -369,6 +371,8 @@ struct AwesomeConf
} scratch;
/** Path to config file */
char *configpath;
/** Floating window placement algo */
FloatingPlacement *floating_placement;
/** Selected clients history */
client_node_t *focus;
/** Link between tags and clients */
@ -379,6 +383,28 @@ struct AwesomeConf
int pointer_x, pointer_y;
/** Atoms cache */
xutil_atom_cache_t *atoms;
/** Lua VM state */
lua_State *L;
/** Default colors */
struct
{
xcolor_t fg, bg;
} colors;
/** Default font */
font_t *font;
/** Respect resize hints */
bool resize_hints;
struct
{
/** Command to execute when spawning a new client */
luaA_function newclient;
/** Command to execute when giving focus to a client */
luaA_function focus;
/** Command to execute when removing focus to a client */
luaA_function unfocus;
/** Command to run when mouse is over */
luaA_function mouseover;
} hooks;
};
#endif

432
tag.c
View File

@ -24,11 +24,17 @@
#include "screen.h"
#include "tag.h"
#include "rules.h"
#include "client.h"
#include "ewmh.h"
#include "widget.h"
#include "layouts/tile.h"
#include "layouts/max.h"
#include "layouts/floating.h"
#include "layouts/fibonacci.h"
#include "layoutgen.h"
extern AwesomeConf globalconf;
/** Create a new tag. Parameteres values are checked.
@ -40,7 +46,7 @@ extern AwesomeConf globalconf;
* \return a new tag with all these parameters
*/
tag_t *
tag_new(const char *name, Layout *layout, double mwfact, int nmaster, int ncol)
tag_new(const char *name, LayoutArrange *layout, double mwfact, int nmaster, int ncol)
{
tag_t *tag;
@ -58,6 +64,8 @@ tag_new(const char *name, Layout *layout, double mwfact, int nmaster, int ncol)
if((tag->ncol = ncol) < 1)
tag->ncol = 1;
tag_ref(&tag);
return tag;
}
@ -72,22 +80,7 @@ tag_append_to_screen(tag_t *tag, int screen)
tag->screen = screen;
tag_list_append(&globalconf.screens[screen].tags, tag);
ewmh_update_net_numbers_of_desktop(phys_screen);
ewmh_update_net_desktop_names(phys_screen);
widget_invalidate_cache(screen, WIDGET_CACHE_TAGS);
}
/** Push a tag to a screen tag list.
* \param tag the tag to push
* \param screen the screen
*/
void
tag_push_to_screen(tag_t *tag, int screen)
{
int phys_screen = screen_virttophys(screen);
tag->screen = screen;
tag_list_push(&globalconf.screens[screen].tags, tag);
tag_ref(&tag);
ewmh_update_net_numbers_of_desktop(phys_screen);
ewmh_update_net_desktop_names(phys_screen);
widget_invalidate_cache(screen, WIDGET_CACHE_TAGS);
@ -173,34 +166,6 @@ tag_client_with_current_selected(client_t *c)
untag_client(c, tag);
}
/** Tag the client according to a rule.
* \param c the client
* \param r the rule
*/
void
tag_client_with_rule(client_t *c, rule_t *r)
{
tag_t *tag;
bool matched = false;
if(!r) return;
/* check if at least one tag match */
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
if(tag_match_rule(tag, r))
{
matched = true;
break;
}
if(matched)
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
if(tag_match_rule(tag, r))
tag_client(c, tag);
else
untag_client(c, tag);
}
/** Get the current tags for the specified screen.
* Returned pointer must be p_delete'd after.
* \param screen screen id
@ -226,123 +191,6 @@ tags_get_current(int screen)
return tags;
}
/** Tag the focused client with the given tag.
* \param screen Screen ID
* \param arg tag name
* \ingroup ui_callback
*/
void
uicb_client_tag(int screen, char *arg)
{
int tag_id = -1;
tag_t *tag, *target_tag;
client_t *sel = globalconf.focus->client;
if(!sel)
return;
if(arg)
{
tag_id = atoi(arg) - 1;
if(tag_id != -1)
{
for(target_tag = globalconf.screens[screen].tags; target_tag && tag_id > 0;
target_tag = target_tag->next, tag_id--);
if(target_tag)
{
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
untag_client(sel, tag);
tag_client(sel, target_tag);
}
}
}
else
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
tag_client(sel, tag);
}
/** Toggle a tag on the focused client.
* \param screen virtual screen id
* \param arg tag number
* \ingroup ui_callback
*/
void
uicb_client_toggletag(int screen, char *arg)
{
client_t *sel = globalconf.focus->client;
int i;
Bool is_sticky = True;
tag_t *tag, *target_tag;
if(!sel)
return;
if(arg)
{
i = atoi(arg) - 1;
for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0;
target_tag = target_tag->next, i--);
if(target_tag)
{
if(is_client_tagged(sel, target_tag))
untag_client(sel, target_tag);
else
tag_client(sel, target_tag);
}
/* check that there's at least one tag selected for this client*/
for(tag = globalconf.screens[screen].tags; tag
&& !is_client_tagged(sel, tag); tag = tag->next);
if(!tag)
tag_client(sel, target_tag);
}
else
{
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
if(!is_client_tagged(sel, tag))
{
is_sticky = False;
tag_client(sel, tag);
}
if(is_sticky)
tag_client_with_current_selected(sel);
}
}
/** Toggle the visibility of a tag.
* \param screen Screen ID
* \param arg tag_t name
* \ingroup ui_callback
*/
void
uicb_tag_toggleview(int screen, char *arg)
{
int i;
tag_t *tag, *target_tag,
**backtag, **curtags = tags_get_current(screen);
if(arg)
{
i = atoi(arg) - 1;
for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0;
target_tag = target_tag->next, i--);
if(target_tag)
tag_view(target_tag, !target_tag->selected);
}
else
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
tag_view(tag, !tag->selected);
/* check that there's at least one tag selected */
for(tag = globalconf.screens[screen].tags; tag && !tag->selected; tag = tag->next);
if(!tag)
for(backtag = curtags; *backtag; backtag++)
tag_view(*backtag, True);
p_delete(&curtags);
}
/** Set a tag to be the only one viewed.
* \param target the tag to see
@ -400,94 +248,226 @@ tag_view_only_byindex(int screen, int dindex)
void
tag_view(tag_t *tag, bool view)
{
tag->was_selected = tag->selected;
tag->selected = view;
ewmh_update_net_current_desktop(screen_virttophys(tag->screen));
widget_invalidate_cache(tag->screen, WIDGET_CACHE_TAGS);
globalconf.screens[tag->screen].need_arrange = true;
}
/** View only this tag.
* \param screen Screen ID
* \param arg tag to view
* \ingroup ui_callback
*/
void
uicb_tag_view(int screen, char *arg)
static int
luaA_tag_eq(lua_State *L)
{
tag_t *tag;
if(arg)
tag_view_only_byindex(screen, atoi(arg) - 1);
else
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
tag_view(tag, true);
tag_t **t1 = luaL_checkudata(L, 1, "tag");
tag_t **t2 = luaL_checkudata(L, 2, "tag");
lua_pushboolean(L, (*t1 == *t2));
return 1;
}
/** View the previously selected tags.
* \param screen Screen ID
* \param arg unused
* \ingroup ui_callback
*/
void
uicb_tag_prev_selected(int screen, char *arg __attribute__ ((unused)))
static int
luaA_tag_tostring(lua_State *L)
{
tag_t *tag;
tag_t **p = luaL_checkudata(L, 1, "tag");
lua_pushfstring(L, "[tag udata(%p) name(%s)]", *p, (*p)->name);
return 1;
}
static int
luaA_tag_add(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
int screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen);
/* \todo check tag is not already in another screen */
tag_append_to_screen(*tag, screen);
return 0;
}
static int
luaA_tag_get(lua_State *L)
{
int screen = luaL_checknumber(L, 1) - 1;
const char *name = luaL_checkstring(L, 2);
tag_t *tag, **tobj;
int ret, i = 1;
regex_t r;
regmatch_t match;
char error[512];
luaA_checkscreen(screen);
if((ret = regcomp(&r, name, REG_EXTENDED)))
{
regerror(ret, &r, error, sizeof(error));
luaL_error(L, "regex compilation error: %s\n", error);
}
lua_newtable(L);
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
tag_view(tag, tag->was_selected);
if(!regexec(&r, tag->name, 1, &match, 0))
{
tobj = lua_newuserdata(L, sizeof(tag_t *));
*tobj = tag;
tag_ref(&tag);
luaA_settype(L, "tag");
lua_rawseti(L, -2, i++);
}
return 1;
}
/** View the next tag.
* \param screen Screen ID
* \param arg unused
* \ingroup ui_callback
/** Create a new tag.
* \param L Lua state.
* \return One because there's one element, a user data.
*/
void
uicb_tag_viewnext(int screen, char *arg __attribute__ ((unused)))
static int
luaA_tag_new(lua_State *L)
{
tag_t *tag, **curtags = tags_get_current(screen);
tag_t **tag;
int ncol, nmaster;
const char *name, *lay;
double mwfact;
LayoutArrange *layout;
tag = tag_list_next_cycle(&globalconf.screens[screen].tags, curtags[0]);
luaA_checktable(L, 1);
tag_view(curtags[0], false);
tag_view(tag, true);
name = luaA_name_init(L);
mwfact = luaA_getopt_number(L, 1, "mwfact", 0.5);
ncol = luaA_getopt_number(L, 1, "ncol", 1);
nmaster = luaA_getopt_number(L, 1, "nmaster", 1);
lay = luaA_getopt_string(L, 1, "layout", "tile");
p_delete(&curtags);
layout = name_func_lookup(lay, LayoutList);
tag = lua_newuserdata(L, sizeof(tag_t *));
*tag = tag_new(name,
layout,
mwfact, nmaster, ncol);
return luaA_settype(L, "tag");
}
/** View the previous tag.
* \param screen Screen ID
* \param arg unused
* \ingroup ui_callback
*/
void
uicb_tag_viewprev(int screen, char *arg __attribute__ ((unused)))
static int
luaA_tag_view(lua_State *L)
{
tag_t *tag, **curtags = tags_get_current(screen);
tag = tag_list_prev_cycle(&globalconf.screens[screen].tags, curtags[0]);
tag_view(curtags[0], false);
tag_view(tag, true);
p_delete(&curtags);
tag_t **tag = luaL_checkudata(L, 1, "tag");
bool view = luaA_checkboolean(L, 2);
tag_view(*tag, view);
return 0;
}
/** Create a new tag. Argument must be the tag name.
* \param screen the screen id
* \param arg the tag name
*/
void
uicb_tag_create(int screen, char *arg)
static int
luaA_tag_isselected(lua_State *L)
{
tag_t *tag;
if(!a_strlen(arg))
return;
tag = tag_new(arg, globalconf.screens[screen].layouts, 0.5, 1, 1);
tag_append_to_screen(tag, screen);
tag_t **tag = luaL_checkudata(L, 1, "tag");
lua_pushboolean(L, (*tag)->selected);
return 1;
}
static int
luaA_tag_mwfact_set(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
double mwfact = luaL_checknumber(L, 2);
if(mwfact < 1 && mwfact > 0)
{
(*tag)->mwfact = mwfact;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "bad value, must be between 0 and 1");
return 0;
}
static int
luaA_tag_mwfact_get(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
lua_pushnumber(L, (*tag)->mwfact);
return 1;
}
static int
luaA_tag_ncol_set(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
int ncol = luaL_checknumber(L, 2);
if(ncol >= 1)
{
(*tag)->ncol = ncol;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "bad value, must be greater than 1");
return 0;
}
static int
luaA_tag_ncol_get(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
lua_pushnumber(L, (*tag)->ncol);
return 1;
}
static int
luaA_tag_nmaster_set(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
int nmaster = luaL_checknumber(L, 2);
if(nmaster >= 0)
{
(*tag)->nmaster = nmaster;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "bad value, must be greater than 0");
return 0;
}
static int
luaA_tag_nmaster_get(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
lua_pushnumber(L, (*tag)->nmaster);
return 1;
}
static int
luaA_tag_gc(lua_State *L)
{
tag_t **tag = luaL_checkudata(L, 1, "tag");
tag_unref(tag);
return 0;
}
const struct luaL_reg awesome_tag_methods[] =
{
{ "new", luaA_tag_new },
{ "get", luaA_tag_get},
{ NULL, NULL }
};
const struct luaL_reg awesome_tag_meta[] =
{
{ "add", luaA_tag_add },
{ "view", luaA_tag_view },
{ "isselected", luaA_tag_isselected },
{ "mwfact_set", luaA_tag_mwfact_set },
{ "mwfact_get", luaA_tag_mwfact_get },
{ "ncol_set", luaA_tag_ncol_set },
{ "ncol_get", luaA_tag_ncol_get },
{ "nmaster_set", luaA_tag_nmaster_set },
{ "nmaster_get", luaA_tag_nmaster_get },
{ "__eq", luaA_tag_eq },
{ "__gc", luaA_tag_gc },
{ "__tostring", luaA_tag_tostring },
{ NULL, NULL },
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

26
tag.h
View File

@ -23,33 +23,35 @@
#define AWESOME_TAG_H
#include "structs.h"
#include "common/refcount.h"
/** Check if a client is tiled */
#define IS_TILED(client, screen) (client && !client->isfloating && !client->ismax && client_isvisible(client, screen))
tag_t * tag_new(const char *, Layout *, double, int, int);
/* Contructor, destructor and referencors */
tag_t * tag_new(const char *, LayoutArrange *, double, int, int);
static inline void
tag_delete(tag_t **tag)
{
p_delete(&(*tag)->name);
p_delete(tag);
}
void tag_view(tag_t *, bool);
void tag_view_byindex(int, int, bool);
void tag_push_to_screen(tag_t *, int);
tag_t ** tags_get_current(int);
void tag_client(client_t *, tag_t *);
void untag_client(client_t *, tag_t *);
bool is_client_tagged(client_t *, tag_t *);
void tag_client_with_rule(client_t *, rule_t *r);
void tag_client_with_current_selected(client_t *);
void tag_view_only_byindex(int, int);
void tag_append_to_screen(tag_t *, int);
uicb_t uicb_client_tag;
uicb_t uicb_client_toggletag;
uicb_t uicb_tag_toggleview;
uicb_t uicb_tag_view;
uicb_t uicb_tag_prev_selected;
uicb_t uicb_tag_viewnext;
uicb_t uicb_tag_viewprev;
uicb_t uicb_tag_create;
DO_RCNT(tag_t, tag, tag_delete)
DO_SLIST(tag_t, tag, tag_delete)
DO_SLIST_UNREF(tag_t, tag, tag_delete)
DO_SLIST(tag_t, tag, p_delete)
DO_SLIST(tag_client_node_t, tag_client_node, p_delete)
#endif

View File

@ -50,35 +50,327 @@ static inline area_t
titlebar_size(client_t *c)
{
return draw_text_extents(globalconf.connection, globalconf.default_screen,
globalconf.screens[c->screen].styles.normal.font, titlebar_text(c));
globalconf.font, titlebar_text(c));
}
/** Initialize a titlebar: create the simple_window_t.
* We still need to update its geometry to have it placed correctly.
/** Draw the titlebar content.
* \param c the client
*/
void
titlebar_draw(client_t *c)
{
xcb_drawable_t dw = 0;
draw_context_t *ctx;
area_t geometry;
xcb_screen_t *s;
char *text;
if(!c->titlebar_sw)
return;
s = xcb_aux_get_screen(globalconf.connection,
c->titlebar_sw->phys_screen);
switch(c->titlebar.position)
{
case Off:
return;
case Right:
case Left:
dw = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth,
dw,
s->root,
c->titlebar_sw->geometry.height,
c->titlebar_sw->geometry.width);
ctx = draw_context_new(globalconf.connection, c->titlebar_sw->phys_screen,
c->titlebar_sw->geometry.height,
c->titlebar_sw->geometry.width,
dw);
geometry.width = c->titlebar_sw->geometry.height;
geometry.height = c->titlebar_sw->geometry.width;
break;
default:
ctx = draw_context_new(globalconf.connection, c->titlebar_sw->phys_screen,
c->titlebar_sw->geometry.width,
c->titlebar_sw->geometry.height,
c->titlebar_sw->drawable);
geometry = c->titlebar_sw->geometry;
break;
}
text = titlebar_text(c);
geometry.x = geometry.y = 0;
draw_rectangle(ctx, geometry, 1.0, true, globalconf.colors.bg);
draw_text(ctx, globalconf.font, &globalconf.colors.fg, geometry, text);
p_delete(&text);
switch(c->titlebar.position)
{
case Left:
draw_rotate(ctx, c->titlebar_sw->drawable, ctx->height, ctx->width,
- M_PI_2, 0, c->titlebar_sw->geometry.height);
xcb_free_pixmap(globalconf.connection, dw);
break;
case Right:
draw_rotate(ctx, c->titlebar_sw->drawable, ctx->height, ctx->width,
M_PI_2, c->titlebar_sw->geometry.width, 0);
xcb_free_pixmap(globalconf.connection, dw);
default:
break;
}
simplewindow_refresh_drawable(c->titlebar_sw);
draw_context_delete(&ctx);
}
/** Update the titlebar geometry for a floating client.
* \param c the client
*/
void
titlebar_update_geometry_floating(client_t *c)
{
int width, x_offset = 0, y_offset = 0;
if(!c->titlebar_sw)
return;
switch(c->titlebar.position)
{
default:
return;
case Off:
return;
case Top:
if(!c->titlebar.width)
width = c->geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + c->geometry.width - width;
break;
case AlignCenter:
x_offset = (c->geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
c->geometry.x + x_offset,
c->geometry.y - c->titlebar_sw->geometry.height,
width,
c->titlebar_sw->geometry.height);
break;
case Bottom:
if(!c->titlebar.width)
width = c->geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + c->geometry.width - width;
break;
case AlignCenter:
x_offset = (c->geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
c->geometry.x + x_offset,
c->geometry.y + c->geometry.height + 2 * c->border,
width,
c->titlebar_sw->geometry.height);
break;
case Left:
if(!c->titlebar.width)
width = c->geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + c->geometry.height - width;
break;
case AlignCenter:
y_offset = (c->geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
c->geometry.x - c->titlebar_sw->geometry.width,
c->geometry.y + y_offset,
c->titlebar_sw->geometry.width,
width);
break;
case Right:
if(!c->titlebar.width)
width = c->geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + c->geometry.height - width;
break;
case AlignCenter:
y_offset = (c->geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
c->geometry.x + c->geometry.width + 2 * c->border,
c->geometry.y + y_offset,
c->titlebar_sw->geometry.width,
width);
break;
}
titlebar_draw(c);
}
/** Update the titlebar geometry for a tiled client.
* \param c the client
* \param geometry the geometry the client will receive
*/
void
titlebar_update_geometry(client_t *c, area_t geometry)
{
int width, x_offset = 0 , y_offset = 0;
if(!c->titlebar_sw)
return;
switch(c->titlebar.position)
{
default:
return;
case Off:
return;
case Top:
if(!c->titlebar.width)
width = geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + geometry.width - width;
break;
case AlignCenter:
x_offset = (geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
geometry.x + x_offset,
geometry.y,
width,
c->titlebar_sw->geometry.height);
break;
case Bottom:
if(!c->titlebar.width)
width = geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + geometry.width - width;
break;
case AlignCenter:
x_offset = (geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
geometry.x + x_offset,
geometry.y + geometry.height
- c->titlebar_sw->geometry.height + 2 * c->border,
width,
c->titlebar_sw->geometry.height);
break;
case Left:
if(!c->titlebar.width)
width = geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + geometry.height - width;
break;
case AlignCenter:
y_offset = (geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
geometry.x,
geometry.y + y_offset,
c->titlebar_sw->geometry.width,
width);
break;
case Right:
if(!c->titlebar.width)
width = geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + geometry.height - width;
break;
case AlignCenter:
y_offset = (geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar_sw,
geometry.x + geometry.width
- c->titlebar_sw->geometry.width + 2 * c->border,
geometry.y + y_offset,
c->titlebar_sw->geometry.width,
width);
break;
}
titlebar_draw(c);
}
/** Set client titlebar position.
* \param c The client.
* \param p The position.
*/
void
titlebar_init(client_t *c)
{
int width = 0, height = 0;
if(!c->titlebar.height)
c->titlebar.height = MAX(MAX(draw_text_extents(globalconf.connection, globalconf.default_screen,
globalconf.screens[c->screen].styles.focus.font,
client_markup_parse(c, c->titlebar.text_focus, a_strlen(c->titlebar.text_focus))).height,
draw_text_extents(globalconf.connection, globalconf.default_screen,
globalconf.screens[c->screen].styles.normal.font,
client_markup_parse(c, c->titlebar.text_normal, a_strlen(c->titlebar.text_normal))).height),
draw_text_extents(globalconf.connection, globalconf.default_screen,
globalconf.screens[c->screen].styles.urgent.font,
client_markup_parse(c, c->titlebar.text_urgent, a_strlen(c->titlebar.text_urgent))).height);
c->titlebar.height = draw_text_extents(globalconf.connection, globalconf.default_screen,
globalconf.font,
client_markup_parse(c,
c->titlebar.text_focus,
a_strlen(c->titlebar.text_focus))).height;
switch(c->titlebar.position)
{
case Off:
return;
default:
c->titlebar.position = Off;
if(c->titlebar_sw)
xcb_unmap_window(globalconf.connection, c->titlebar_sw->window);
return;
return;
case Top:
case Bottom:
@ -97,411 +389,116 @@ titlebar_init(client_t *c)
width = c->titlebar.height;
break;
}
c->titlebar.sw = simplewindow_new(globalconf.connection,
/* Delete old statusbar */
simplewindow_delete(&c->titlebar_sw);
c->titlebar_sw = simplewindow_new(globalconf.connection,
c->phys_screen, 0, 0,
width, height, 0);
xcb_map_window(globalconf.connection, c->titlebar.sw->window);
}
/** Add the titlebar geometry to a geometry.
* \param t the titlebar
* \param geometry the geometry
* \return a new geometry bigger if the titlebar is visible
*/
area_t
titlebar_geometry_add(titlebar_t *t, area_t geometry)
{
if(!t->sw)
return geometry;
switch(t->position)
{
case Top:
geometry.y -= t->sw->geometry.height;
geometry.height += t->sw->geometry.height;
break;
case Bottom:
geometry.height += t->sw->geometry.height;
break;
case Left:
geometry.x -= t->sw->geometry.width;
geometry.width += t->sw->geometry.width;
break;
case Right:
geometry.width += t->sw->geometry.width;
break;
default:
break;
}
return geometry;
}
/** Remove the titlebar geometry to a geometry.
* \param t the titlebar
* \param geometry the geometry
* \return a new geometry smaller if the titlebar is visible
*/
area_t
titlebar_geometry_remove(titlebar_t *t, area_t geometry)
{
if(!t->sw)
return geometry;
switch(t->position)
{
case Top:
geometry.y += t->sw->geometry.height;
geometry.height -= t->sw->geometry.height;
break;
case Bottom:
geometry.height -= t->sw->geometry.height;
break;
case Left:
geometry.x += t->sw->geometry.width;
geometry.width -= t->sw->geometry.width;
break;
case Right:
geometry.width -= t->sw->geometry.width;
break;
default:
break;
}
return geometry;
}
/** Draw the titlebar content.
* \param c the client
*/
void
titlebar_draw(client_t *c)
{
xcb_drawable_t dw = 0;
draw_context_t *ctx;
area_t geometry;
xcb_screen_t *s;
char *text;
style_t *style;
if(!c->titlebar.sw)
return;
s = xcb_aux_get_screen(globalconf.connection,
c->titlebar.sw->phys_screen);
switch(c->titlebar.position)
{
case Off:
return;
case Right:
case Left:
dw = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth,
dw,
s->root,
c->titlebar.sw->geometry.height,
c->titlebar.sw->geometry.width);
ctx = draw_context_new(globalconf.connection, c->titlebar.sw->phys_screen,
c->titlebar.sw->geometry.height,
c->titlebar.sw->geometry.width,
dw);
geometry.width = c->titlebar.sw->geometry.height;
geometry.height = c->titlebar.sw->geometry.width;
break;
default:
ctx = draw_context_new(globalconf.connection, c->titlebar.sw->phys_screen,
c->titlebar.sw->geometry.width,
c->titlebar.sw->geometry.height,
c->titlebar.sw->drawable);
geometry = c->titlebar.sw->geometry;
break;
}
text = titlebar_text(c);
geometry.x = geometry.y = 0;
style = client_style_get(c);
draw_text(ctx, geometry, text, style);
p_delete(&text);
switch(c->titlebar.position)
{
case Left:
draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width,
- M_PI_2, 0, c->titlebar.sw->geometry.height);
xcb_free_pixmap(globalconf.connection, dw);
break;
case Right:
draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width,
M_PI_2, c->titlebar.sw->geometry.width, 0);
xcb_free_pixmap(globalconf.connection, dw);
default:
break;
}
simplewindow_refresh_drawable(c->titlebar.sw);
draw_context_delete(&ctx);
}
/** Update the titlebar geometry for a floating client.
* \param c the client
*/
void
titlebar_update_geometry_floating(client_t *c)
{
int width, x_offset = 0, y_offset = 0;
if(!c->titlebar.sw)
return;
switch(c->titlebar.position)
{
default:
return;
case Off:
return;
case Top:
if(!c->titlebar.width)
width = c->geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + c->geometry.width - width;
break;
case AlignCenter:
x_offset = (c->geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
c->geometry.x + x_offset,
c->geometry.y - c->titlebar.sw->geometry.height,
width,
c->titlebar.sw->geometry.height);
break;
case Bottom:
if(!c->titlebar.width)
width = c->geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + c->geometry.width - width;
break;
case AlignCenter:
x_offset = (c->geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
c->geometry.x + x_offset,
c->geometry.y + c->geometry.height + 2 * c->border,
width,
c->titlebar.sw->geometry.height);
break;
case Left:
if(!c->titlebar.width)
width = c->geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + c->geometry.height - width;
break;
case AlignCenter:
y_offset = (c->geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
c->geometry.x - c->titlebar.sw->geometry.width,
c->geometry.y + y_offset,
c->titlebar.sw->geometry.width,
width);
break;
case Right:
if(!c->titlebar.width)
width = c->geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, c->geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + c->geometry.height - width;
break;
case AlignCenter:
y_offset = (c->geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
c->geometry.x + c->geometry.width + 2 * c->border,
c->geometry.y + y_offset,
c->titlebar.sw->geometry.width,
width);
break;
}
titlebar_draw(c);
xcb_map_window(globalconf.connection, c->titlebar_sw->window);
}
/** Update the titlebar geometry for a tiled client.
* \param c the client
* \param geometry the geometry the client will receive
*/
void
titlebar_update_geometry(client_t *c, area_t geometry)
static int
luaA_titlebar_new(lua_State *L)
{
int width, x_offset = 0 , y_offset = 0;
titlebar_t **tb;
int objpos;
if(!c->titlebar.sw)
return;
luaA_checktable(L, 1);
switch(c->titlebar.position)
tb = lua_newuserdata(L, sizeof(titlebar_t *));
*tb = p_new(titlebar_t, 1);
objpos = lua_gettop(L);
(*tb)->text_normal = a_strdup(luaA_getopt_string(L, 1, "normal", "<title/>"));
(*tb)->text_focus = a_strdup(luaA_getopt_string(L, 1, "focus", "<title/>"));
(*tb)->text_urgent = a_strdup(luaA_getopt_string(L, 1, "urgent", "<title/>"));
(*tb)->align = draw_align_get_from_str(luaA_getopt_string(L, 1, "align", "left"));
(*tb)->width = luaA_getopt_number(L, 1, "width", 0);
(*tb)->height = luaA_getopt_number(L, 1, "height", 0);
if((*tb)->height <= 0)
/* 1.5 as default factor, it fits nice but no one knows why */
(*tb)->height = 1.5 * globalconf.font->height;
(*tb)->position = position_get_from_str(luaA_getopt_string(L, 1, "position", "top"));
titlebar_ref(tb);
lua_pushvalue(L, objpos);
return luaA_settype(L, "titlebar");
}
static int
luaA_titlebar_mouse(lua_State *L)
{
size_t i, len;
int b;
Button *button;
/* arg 1 is modkey table */
luaA_checktable(L, 1);
/* arg 2 is mouse button */
b = luaL_checknumber(L, 2);
/* arg 3 is cmd to run */
luaA_checkfunction(L, 3);
button = p_new(Button, 1);
button->button = xutil_button_fromint(b);
button->fct = luaL_ref(L, LUA_REGISTRYINDEX);
len = lua_objlen(L, 1);
for(i = 1; i <= len; i++)
{
default:
return;
case Off:
return;
case Top:
if(!c->titlebar.width)
width = geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + geometry.width - width;
break;
case AlignCenter:
x_offset = (geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
geometry.x + x_offset,
geometry.y,
width,
c->titlebar.sw->geometry.height);
break;
case Bottom:
if(!c->titlebar.width)
width = geometry.width + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.width);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + geometry.width - width;
break;
case AlignCenter:
x_offset = (geometry.width - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
geometry.x + x_offset,
geometry.y + geometry.height
- c->titlebar.sw->geometry.height + 2 * c->border,
width,
c->titlebar.sw->geometry.height);
break;
case Left:
if(!c->titlebar.width)
width = geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + geometry.height - width;
break;
case AlignCenter:
y_offset = (geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
geometry.x,
geometry.y + y_offset,
c->titlebar.sw->geometry.width,
width);
break;
case Right:
if(!c->titlebar.width)
width = geometry.height + 2 * c->border;
else
width = MIN(c->titlebar.width, geometry.height);
switch(c->titlebar.align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + geometry.height - width;
break;
case AlignCenter:
y_offset = (geometry.height - width) / 2;
break;
}
simplewindow_move_resize(c->titlebar.sw,
geometry.x + geometry.width
- c->titlebar.sw->geometry.width + 2 * c->border,
geometry.y + y_offset,
c->titlebar.sw->geometry.width,
width);
break;
lua_rawgeti(L, 1, i);
button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1));
}
titlebar_draw(c);
button_list_push(&globalconf.buttons.titlebar, button);
return 0;
}
void
titlebar_position_set(titlebar_t *t, position_t p)
static int
luaA_titlebar_gc(lua_State *L)
{
if(!t->sw)
return;
if((t->position = p))
xcb_map_window(globalconf.connection, t->sw->window);
else
xcb_unmap_window(globalconf.connection, t->sw->window);
titlebar_t **titlebar = luaL_checkudata(L, 1, "titlebar");
titlebar_unref(titlebar);
return 0;
}
/** Toggle the visibility of the focused window's titlebar.
* \param screen screen number (unused)
* \param arg unused argument
* \ingroup ui_callback
*/
void
uicb_client_toggletitlebar(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused)))
static int
luaA_titlebar_tostring(lua_State *L)
{
client_t *c = globalconf.focus->client;
if(!c || !c->titlebar.sw)
return;
if(!c->titlebar.position)
titlebar_position_set(&c->titlebar, c->titlebar.dposition);
else
titlebar_position_set(&c->titlebar, Off);
if(c->isfloating || layout_get_current(screen)->arrange == layout_floating)
titlebar_update_geometry_floating(c);
else
globalconf.screens[c->screen].need_arrange = true;
titlebar_t **p = luaL_checkudata(L, 1, "titlebar");
lua_pushfstring(L, "[titlebar udata(%p)]", *p);
return 1;
}
static int
luaA_titlebar_eq(lua_State *L)
{
titlebar_t **t1 = luaL_checkudata(L, 1, "titlebar");
titlebar_t **t2 = luaL_checkudata(L, 2, "titlebar");
lua_pushboolean(L, (*t1 == *t2));
return 1;
}
const struct luaL_reg awesome_titlebar_methods[] =
{
{ "new", luaA_titlebar_new },
{ "mouse", luaA_titlebar_mouse },
{ NULL, NULL }
};
const struct luaL_reg awesome_titlebar_meta[] =
{
{ "__eq", luaA_titlebar_eq },
{ "__gc", luaA_titlebar_gc },
{ "__tostring", luaA_titlebar_tostring },
{ NULL, NULL }
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -24,15 +24,72 @@
#include "structs.h"
void titlebar_init(client_t *);
void titlebar_draw(client_t *);
void titlebar_update_geometry_floating(client_t *);
void titlebar_update_geometry(client_t *, area_t);
area_t titlebar_geometry_add(titlebar_t *, area_t);
area_t titlebar_geometry_remove(titlebar_t *, area_t);
void titlebar_position_set(titlebar_t *, position_t);
void titlebar_init(client_t *);
uicb_t uicb_client_toggletitlebar;
/** Add the titlebar geometry to a geometry.
* \param t the titlebar
* \param geometry the geometry
* \return a new geometry bigger if the titlebar is visible
*/
static inline area_t
titlebar_geometry_add(titlebar_t *t, area_t geometry)
{
switch(t->position)
{
case Top:
geometry.y -= t->height;
geometry.height += t->height;
break;
case Bottom:
geometry.height += t->height;
break;
case Left:
geometry.x -= t->width;
geometry.width += t->width;
break;
case Right:
geometry.width += t->width;
break;
default:
break;
}
return geometry;
}
/** Remove the titlebar geometry to a geometry.
* \param t the titlebar
* \param geometry the geometry
* \return a new geometry smaller if the titlebar is visible
*/
static inline area_t
titlebar_geometry_remove(titlebar_t *t, area_t geometry)
{
switch(t->position)
{
case Top:
geometry.y += t->height;
geometry.height -= t->height;
break;
case Bottom:
geometry.height -= t->height;
break;
case Left:
geometry.x += t->width;
geometry.width -= t->width;
break;
case Right:
geometry.width -= t->width;
break;
default:
break;
}
return geometry;
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

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 "statusbar.h"
#include "event.h"
#include "lua.h"
extern AwesomeConf globalconf;
#include "widgetgen.h"
/** Compute widget alignment.
* This will process all widget starting at `widget' and will check their
* alignment and guess it if set to AlignAuto.
* \param widget A linked list of all widgets.
*/
void
widget_calculate_alignments(widget_t *widget)
{
for(; widget && widget->alignment != AlignFlex; widget = widget->next)
switch(widget->alignment)
{
case AlignCenter:
warn("widgets cannot be center aligned\n");
case AlignAuto:
widget->alignment = AlignLeft;
break;
default:
break;
}
if(widget)
for(widget = widget->next; widget; widget = widget->next)
switch(widget->alignment)
{
case AlignFlex:
warn("multiple flex widgets (%s) in panel -"
" ignoring flex for all but the first.\n", widget->name);
widget->alignment = AlignRight;
break;
case AlignCenter:
warn("widget %s cannot be center aligned\n", widget->name);
case AlignAuto:
widget->alignment = AlignRight;
break;
default:
break;
}
}
/** Compute offset for drawing the first pixel of a widget.
* \param barwidth The statusbar width.
* \param widgetwidth The widget width.
@ -93,29 +55,31 @@ widget_calculate_offset(int barwidth, int widgetwidth, int offset, int alignment
widget_t *
widget_getbyname(statusbar_t *sb, char *name)
{
widget_t *widget;
widget_node_t *widget;
for(widget = sb->widgets; widget; widget = widget->next)
if(!a_strcmp(name, widget->name))
return widget;
if(!a_strcmp(name, widget->widget->name))
return widget->widget;
return NULL;
}
/** Common function for button press event on widget.
* It will look into configuration to find the callback function to call.
* \param widget The widget.
* \param w The widget node.
* \param statusbar The statusbar.
* \param ev The button press event the widget received.
*/
static void
widget_common_button_press(widget_t *widget, xcb_button_press_event_t *ev)
widget_common_button_press(widget_node_t *w,
statusbar_t *statusbar __attribute__ ((unused)),
xcb_button_press_event_t *ev)
{
Button *b;
for(b = widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod
&& b->func)
b->func(widget->statusbar->screen, b->arg);
for(b = w->widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
luaA_dofunction(globalconf.L, b->fct, 0);
}
/** Common tell function for widget, which only warn user that widget
@ -125,8 +89,9 @@ widget_common_button_press(widget_t *widget, xcb_button_press_event_t *ev)
* \return The status of the command, which is always an error in this case.
*/
static widget_tell_status_t
widget_common_tell(widget_t *widget, char *property __attribute__ ((unused)),
char *new_value __attribute__ ((unused)))
widget_common_tell(widget_t *widget,
const char *property __attribute__ ((unused)),
const char *new_value __attribute__ ((unused)))
{
warn("%s widget does not accept commands.\n", widget->name);
return WIDGET_ERROR_CUSTOM;
@ -134,20 +99,13 @@ widget_common_tell(widget_t *widget, char *property __attribute__ ((unused)),
/** Common function for creating a widget.
* \param widget The allocated widget.
* \param statusbar The statusbar the widget is on.
* \param config The cfg_t structure we will parse to set common info.
*/
void
widget_common_new(widget_t *widget, statusbar_t *statusbar, cfg_t *config)
widget_common_new(widget_t *widget)
{
widget->statusbar = statusbar;
widget->name = a_strdup(cfg_title(config));
widget->align = AlignLeft;
widget->tell = widget_common_tell;
widget->button_press = widget_common_button_press;
widget->area.x = cfg_getint(config, "x");
widget->area.y = cfg_getint(config, "y");
widget->user_supplied_x = (widget->area.x != (int) 0xffffffff);
widget->user_supplied_y = (widget->area.y != (int) 0xffffffff);
}
/** Invalidate widgets which should be refresh upon
@ -160,94 +118,238 @@ void
widget_invalidate_cache(int screen, int flags)
{
statusbar_t *statusbar;
widget_t *widget;
widget_node_t *widget;
for(statusbar = globalconf.screens[screen].statusbar;
statusbar;
statusbar = statusbar->next)
for(widget = statusbar->widgets; widget; widget = widget->next)
if(widget->cache_flags & flags)
if(widget->widget->cache_flags & flags)
{
statusbar->need_update = true;
break;
}
}
/** Send commands to widgets.
* \param screen Virtual screen number.
* \param arg Widget command. Syntax depends on specific widget.
* \ingroup ui_callback
*/
void
uicb_widget_tell(int screen, char *arg)
widget_invalidate_statusbar_bywidget(widget_t *widget)
{
int screen;
statusbar_t *statusbar;
widget_t *widget;
char *p, *property = NULL, *new_value;
ssize_t len;
widget_node_t *witer;
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar = globalconf.screens[screen].statusbar;
statusbar;
statusbar = statusbar->next)
for(witer = statusbar->widgets; witer; witer = witer->next)
if(witer->widget == widget)
{
statusbar->need_update = true;
break;
}
}
static int
luaA_widget_new(lua_State *L)
{
const char *type;
widget_t **widget, *w;
WidgetConstructor *wc;
int objpos;
alignment_t align;
luaA_checktable(L, 1);
align = draw_align_get_from_str(luaA_getopt_string(L, 1, "align", "left"));
type = luaA_getopt_string(L, 1, "type", NULL);
/* \todo use type to call the WidgetConstructor and set ->tell*/
if((wc = name_func_lookup(type, WidgetList)))
w = wc(align);
else
return 0;
widget = lua_newuserdata(L, sizeof(widget_t *));
objpos = lua_gettop(L);
*widget = w;
/* \todo check that the name is unique */
(*widget)->name = luaA_name_init(L);
widget_ref(widget);
/* repush obj on top */
lua_pushvalue(L, objpos);
return luaA_settype(L, "widget");
}
static int
luaA_widget_mouse(lua_State *L)
{
size_t i, len;
/* arg 1 is object */
widget_t **widget = luaL_checkudata(L, 1, "widget");
int b;
Button *button;
/* arg 2 is modkey table */
luaA_checktable(L, 2);
/* arg 3 is mouse button */
b = luaL_checknumber(L, 3);
/* arg 4 is cmd to run */
luaA_checkfunction(L, 4);
button = p_new(Button, 1);
button->button = xutil_button_fromint(b);
button->fct = luaL_ref(L, LUA_REGISTRYINDEX);
len = lua_objlen(L, 2);
for(i = 1; i <= len; i++)
{
lua_rawgeti(L, 2, i);
button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1));
}
button_list_push(&(*widget)->buttons, button);
return 0;
}
static int
luaA_widget_set(lua_State *L)
{
widget_t **widget = luaL_checkudata(L, 1, "widget");
const char *property, *value;
widget_tell_status_t status;
if(!(len = a_strlen(arg)))
return warn("must specify a statusbar and a widget.\n");
property = luaL_checkstring(L, 2);
value = luaL_checkstring(L, 3);
if(!(p = strtok(arg, " ")))
return warn("ignoring malformed widget command (missing statusbar name).\n");
if(!(statusbar = statusbar_getbyname(screen, p)))
return warn("no such statusbar: %s\n", p);
if(!(p = strtok(NULL, " ")))
return warn("ignoring malformed widget command (missing widget name).\n");
if(!(widget = widget_getbyname(statusbar, p)))
return warn("no such widget: %s in statusbar %s.\n", p, statusbar->name);
if(!(p = strtok(NULL, " ")))
return warn("ignoring malformed widget command (missing property name).\n");
property = p;
p += a_strlen(property) + 1; /* could be out of 'arg' now */
/* arg + len points to the finishing \0.
* p to the char right of the first space (strtok delimiter)
*
* \0 is on the right(>) of p pointer => some text (new_value) */
if(arg + len > p)
{
len = a_strlen(p);
new_value = p_new(char, len + 1);
a_strncpy(new_value, len + 1, p, len);
status = widget->tell(widget, property, new_value);
p_delete(&new_value);
}
else
status = widget->tell(widget, property, NULL);
switch(status)
switch((status = (*widget)->tell(*widget, property, value)))
{
case WIDGET_ERROR:
warn("error changing property %s of widget %s\n",
property, widget->name);
property, (*widget)->name);
break;
case WIDGET_ERROR_NOVALUE:
warn("error changing property %s of widget %s, no value given\n",
property, widget->name);
warn("error changing property %s of widget %s, no value given\n",
property, (*widget)->name);
break;
case WIDGET_ERROR_FORMAT_FONT:
warn("error changing property %s of widget %s, must be a valid font\n",
property, widget->name);
property, (*widget)->name);
break;
case WIDGET_ERROR_FORMAT_COLOR:
warn("error changing property %s of widget %s, must be a valid color\n",
property, widget->name);
property, (*widget)->name);
break;
case WIDGET_ERROR_FORMAT_SECTION:
warn("error changing property %s of widget %s, section/title not found\n",
property, widget->name);
property, (*widget)->name);
break;
case WIDGET_NOERROR:
widget->statusbar->need_update = true;
break;
widget_invalidate_statusbar_bywidget(*widget);
break;
case WIDGET_ERROR_CUSTOM:
break;
}
return 0;
}
static int
luaA_widget_gc(lua_State *L)
{
widget_t **widget = luaL_checkudata(L, 1, "widget");
widget_unref(widget);
return 0;
}
static int
luaA_widget_tostring(lua_State *L)
{
widget_t **p = luaL_checkudata(L, 1, "widget");
lua_pushfstring(L, "[widget udata(%p) name(%s)]", *p, (*p)->name);
return 1;
}
static int
luaA_widget_eq(lua_State *L)
{
widget_t **t1 = luaL_checkudata(L, 1, "widget");
widget_t **t2 = luaL_checkudata(L, 2, "widget");
lua_pushboolean(L, (*t1 == *t2));
return 1;
}
static int
luaA_widget_get(lua_State *L)
{
const char *name = luaL_checkstring(L, 1);
statusbar_t *sb;
widget_t **wobj;
widget_node_t *widget;
int ret, i = 1, screen;
regex_t r;
regmatch_t match;
char error[512];
bool add = true;
widget_node_t *wlist = NULL, *witer;
if((ret = regcomp(&r, name, REG_EXTENDED)))
{
regerror(ret, &r, error, sizeof(error));
luaL_error(L, "regex compilation error: %s\n", error);
}
lua_newtable(L);
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
for(widget = sb->widgets; widget; widget = widget->next)
if(!regexec(&r, widget->widget->name, 1, &match, 0))
{
for(witer = wlist; witer; witer = witer->next)
if(witer->widget == widget->widget)
{
add = false;
break;
}
if(add)
{
witer = p_new(widget_node_t, 1);
wobj = lua_newuserdata(L, sizeof(tag_t *));
witer->widget = *wobj = widget->widget;
widget_ref(&widget->widget);
widget_node_list_push(&wlist, witer);
/* ref again for the list */
widget_ref(&widget->widget);
luaA_settype(L, "widget");
lua_rawseti(L, -2, i++);
}
add = true;
}
widget_node_list_wipe(&wlist);
return 1;
}
const struct luaL_reg awesome_widget_methods[] =
{
{ "new", luaA_widget_new },
{ "get", luaA_widget_get },
{ NULL, NULL }
};
const struct luaL_reg awesome_widget_meta[] =
{
{ "mouse", luaA_widget_mouse },
{ "set", luaA_widget_set },
{ "__gc", luaA_widget_gc },
{ "__eq", luaA_widget_eq },
{ "__tostring", luaA_widget_tostring },
{ NULL, NULL }
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

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

View File

@ -25,7 +25,7 @@
extern AwesomeConf globalconf;
widget_tell_status_t
widget_set_color_for_data(widget_t *widget, xcolor_t *color, char *new_value, int data_items, char ** data_title)
widget_set_color_for_data(xcolor_t *color, char *new_value, int data_items, char ** data_title)
{
char *title, *setting;
int i;
@ -36,7 +36,7 @@ widget_set_color_for_data(widget_t *widget, xcolor_t *color, char *new_value, in
if(!a_strcmp(title, data_title[i]))
{
if(draw_color_new(globalconf.connection,
widget->statusbar->phys_screen,
globalconf.default_screen,
setting, &color[i]))
return WIDGET_NOERROR;
else
@ -45,7 +45,7 @@ widget_set_color_for_data(widget_t *widget, xcolor_t *color, char *new_value, in
return WIDGET_ERROR_FORMAT_SECTION;
}
widget_tell_status_t
widget_set_color_pointer_for_data(widget_t *widget, xcolor_t **color, char *new_value, int data_items, char ** data_title)
widget_set_color_pointer_for_data(xcolor_t **color, char *new_value, int data_items, char ** data_title)
{
char *title, *setting;
int i;
@ -63,8 +63,8 @@ widget_set_color_pointer_for_data(widget_t *widget, xcolor_t **color, char *new_
color[i] = p_new(xcolor_t, 1);
}
if(!(draw_color_new(globalconf.connection,
widget->statusbar->phys_screen,
setting, color[i])))
globalconf.default_screen,
setting, color[i])))
{
if(flag) /* restore */
{

View File

@ -24,8 +24,8 @@
#define AWESOME_WIDGETS_COMMON_H
#include "widget.h"
widget_tell_status_t widget_set_color_for_data(widget_t *, xcolor_t *, char *, int, char **);
widget_tell_status_t widget_set_color_pointer_for_data(widget_t *, xcolor_t **, char *, int, char **);
widget_tell_status_t widget_set_color_for_data(xcolor_t *, char *, int, char **);
widget_tell_status_t widget_set_color_pointer_for_data(xcolor_t **, char *, int, char **);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

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

View File

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

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

View File

@ -19,20 +19,31 @@
*
*/
#include "config.h"
#include "client.h"
#include "widget.h"
#include "tag.h"
#include "lua.h"
#include "event.h"
#include "common/markup.h"
#include "common/configopts.h"
extern AwesomeConf globalconf;
typedef struct taglist_drawn_area_t taglist_drawn_area_t;
struct taglist_drawn_area_t
{
statusbar_t *statusbar;
area_t *area;
taglist_drawn_area_t *next, *prev;
};
DO_SLIST(taglist_drawn_area_t, taglist_drawn_area, p_delete);
typedef struct
{
char *text_normal, *text_focus, *text_urgent;
area_t *draw_area;
taglist_drawn_area_t *drawn_area;
} taglist_data_t;
static char *
@ -90,17 +101,6 @@ tag_isurgent(tag_t *t)
return false;
}
static style_t *
taglist_style_get(tag_t *tag, VirtScreen *vs)
{
if(tag->selected)
return &vs->styles.focus;
else if(tag_isurgent(tag))
return &vs->styles.urgent;
return &vs->styles.normal;
}
static char *
taglist_text_get(tag_t *tag, taglist_data_t *data)
{
@ -113,139 +113,178 @@ taglist_text_get(tag_t *tag, taglist_data_t *data)
}
static int
taglist_draw(widget_t *widget,
draw_context_t *ctx,
taglist_draw(widget_node_t *w,
statusbar_t *statusbar,
int offset,
int used __attribute__ ((unused)))
{
tag_t *tag;
taglist_data_t *data = widget->data;
taglist_data_t *data = w->widget->data;
client_t *sel = globalconf.focus->client;
VirtScreen *vscreen = &globalconf.screens[widget->statusbar->screen];
VirtScreen *vscreen = &globalconf.screens[statusbar->screen];
draw_context_t *ctx = statusbar->ctx;
int i = 0;
style_t **styles;
area_t *area, rectangle = { 0, 0, 0, 0, NULL, NULL };
char **text;
taglist_drawn_area_t *tda;
widget->area.width = 0;
w->area.width = 0;
area_list_wipe(&data->draw_area);
w->area.x = widget_calculate_offset(statusbar->width, w->area.width,
offset, w->widget->align);
w->area.y = 0;
/* Lookup for our taglist_drawn_area.
* This will be used to store area where we draw tag list for each
* statusbar.
*/
for(tda = data->drawn_area; tda && tda->statusbar != statusbar; tda = tda->next);
/* Oh, we did not find a drawn area for our statusbar. First time? */
if(!tda)
{
tda = p_new(taglist_drawn_area_t, 1);
tda->statusbar = statusbar;
taglist_drawn_area_list_push(&data->drawn_area, tda);
}
text = p_new(char *, 1);
styles = p_new(style_t *, 1);
for(tag = vscreen->tags; tag; tag = tag->next, i++)
{
p_realloc(&text, i + 1);
p_realloc(&styles, i + 1);
styles[i] = taglist_style_get(tag, vscreen);
area = p_new(area_t, 1);
text[i] = taglist_text_get(tag, data);
text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i]));
*area = draw_text_extents(ctx->connection, ctx->phys_screen,
styles[i]->font, text[i]);
area->x = widget->area.width;
area->height = widget->statusbar->height;
area_list_append(&data->draw_area, area);
widget->area.width += area->width;
globalconf.font, text[i]);
area->x = w->area.x + w->area.width;
area->height = statusbar->height;
area_list_append(&tda->area, area);
w->area.width += area->width;
}
if(!widget->user_supplied_x)
widget->area.x = widget_calculate_offset(widget->statusbar->width,
widget->area.width,
offset,
widget->alignment);
if(!widget->user_supplied_y)
widget->area.y = 0;
for(area = data->draw_area, tag = vscreen->tags, i = 0;
for(area = tda->area, tag = vscreen->tags, i = 0;
tag && area;
tag = tag->next, area = area->next, i++)
{
draw_text(ctx, *area, text[i], styles[i]);
draw_text(ctx, globalconf.font, &statusbar->colors.fg, *area, text[i]);
p_delete(&text[i]);
if(tag_isoccupied(tag))
{
rectangle.width = rectangle.height = (styles[i]->font->height + 2) / 3;
rectangle.width = rectangle.height = (globalconf.font->height + 2) / 3;
rectangle.x = area->x;
rectangle.y = area->y;
draw_rectangle(ctx, rectangle, 1.0,
sel && is_client_tagged(sel, tag), styles[i]->fg);
sel && is_client_tagged(sel, tag), statusbar->colors.fg);
}
}
p_delete(&text);
p_delete(&styles);
widget->area.height = widget->statusbar->height;
return widget->area.width;
w->area.height = statusbar->height;
return w->area.width;
}
static void
taglist_button_press(widget_t *widget, xcb_button_press_event_t *ev)
taglist_button_press(widget_node_t *w, statusbar_t *statusbar,
xcb_button_press_event_t *ev)
{
VirtScreen *vscreen = &globalconf.screens[widget->statusbar->screen];
VirtScreen *vscreen = &globalconf.screens[statusbar->screen];
Button *b;
tag_t *tag;
char buf[4];
int i = 1;
taglist_data_t *data = widget->data;
area_t *area = data->draw_area;
taglist_data_t *data = w->widget->data;
taglist_drawn_area_t *tda;
area_t *area;
tag_t *tag, **ltag;
for(b = widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->func)
switch(widget->statusbar->position)
/* Find the good drawn area list */
for(tda = data->drawn_area; tda && tda->statusbar != statusbar; tda = tda->next);
area = tda->area;
for(b = w->widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
switch(statusbar->position)
{
default:
for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next)
for(tag = vscreen->tags; tag; tag = tag->next, area = area->next)
if(ev->event_x >= AREA_LEFT(*area)
&& ev->event_x < AREA_RIGHT(*area))
{
snprintf(buf, sizeof(buf), "%d", i);
b->func(widget->statusbar->screen, buf);
return;
ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *));
luaA_settype(globalconf.L, "tag");
*ltag = tag;
luaA_dofunction(globalconf.L, b->fct, 1);
}
break;
case Right:
for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next)
for(tag = vscreen->tags; tag; tag = tag->next, area = area->next)
if(ev->event_y >= AREA_LEFT(*area)
&& ev->event_y < AREA_RIGHT(*area))
{
snprintf(buf, sizeof(buf), "%d", i);
b->func(widget->statusbar->screen, buf);
return;
ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *));
luaA_settype(globalconf.L, "tag");
*ltag = tag;
luaA_dofunction(globalconf.L, b->fct, 1);
}
break;
case Left:
for(tag = vscreen->tags; tag; tag = tag->next, i++, area = area->next)
if(widget->statusbar->width - ev->event_y >= AREA_LEFT(*area)
&& widget->statusbar->width - ev->event_y < AREA_RIGHT(*area))
for(tag = vscreen->tags; tag; tag = tag->next, area = area->next)
if(statusbar->width - ev->event_y >= AREA_LEFT(*area)
&& statusbar->width - ev->event_y < AREA_RIGHT(*area))
{
snprintf(buf, sizeof(buf), "%d", i);
b->func(widget->statusbar->screen, buf);
return;
ltag = lua_newuserdata(globalconf.L, sizeof(tag_t *));
luaA_settype(globalconf.L, "tag");
*ltag = tag;
luaA_dofunction(globalconf.L, b->fct, 1);
}
break;
}
}
static widget_tell_status_t
taglist_tell(widget_t *widget, const char *property, const char *new_value)
{
taglist_data_t *d = widget->data;
if(!a_strcmp(property, "text_normal"))
{
p_delete(&d->text_normal);
d->text_normal = a_strdup(new_value);
}
else if(!a_strcmp(property, "text_focus"))
{
p_delete(&d->text_focus);
d->text_focus = a_strdup(new_value);
}
else if(!a_strcmp(property, "text_urgent"))
{
p_delete(&d->text_urgent);
d->text_urgent = a_strdup(new_value);
}
else
return WIDGET_ERROR;
return WIDGET_NOERROR;
}
widget_t *
taglist_new(statusbar_t *statusbar, cfg_t *config)
taglist_new(alignment_t align)
{
widget_t *w;
taglist_data_t *d;
w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config);
widget_common_new(w);
w->align = align;
w->draw = taglist_draw;
w->button_press = taglist_button_press;
w->alignment = cfg_getalignment(config, "align");
w->tell = taglist_tell;
w->data = d = p_new(taglist_data_t, 1);
d->text_normal = a_strdup(cfg_getstr(config, "text_normal"));
d->text_focus = a_strdup(cfg_getstr(config, "text_focus"));
d->text_urgent = a_strdup(cfg_getstr(config, "text_urgent"));
d->text_normal = a_strdup(" <text align=\"center\"/><title/> ");
d->text_focus = a_strdup(" <text align=\"center\"/><title/> ");
d->text_urgent = a_strdup(" <text align=\"center\"/><title/> ");
/* Set cache property */
w->cache_flags = WIDGET_CACHE_TAGS | WIDGET_CACHE_CLIENTS;

View File

@ -25,7 +25,6 @@
#include "screen.h"
#include "event.h"
#include "ewmh.h"
#include "rules.h"
#include "tag.h"
#include "common/configopts.h"
@ -64,47 +63,39 @@ tasklist_isvisible(client_t *c, int screen, showclient_t show)
}
static int
tasklist_draw(widget_t *widget, draw_context_t *ctx, int offset, int used)
tasklist_draw(widget_node_t *w, statusbar_t *statusbar, int offset, int used)
{
client_t *c;
Data *d = widget->data;
rule_t *r;
Data *d = w->widget->data;
area_t area;
char *text;
int n = 0, i = 0, box_width = 0, icon_width = 0, box_width_rest = 0;
NetWMIcon *icon;
style_t *style;
if(used >= widget->statusbar->width)
return (widget->area.width = 0);
if(used >= statusbar->width)
return (w->area.width = 0);
for(c = globalconf.clients; c; c = c->next)
if(tasklist_isvisible(c, widget->statusbar->screen, d->show))
if(tasklist_isvisible(c, statusbar->screen, d->show))
n++;
if(!n)
return (widget->area.width = 0);
return (w->area.width = 0);
box_width = (widget->statusbar->width - used) / n;
box_width = (statusbar->width - used) / n;
/* compute how many pixel we left empty */
box_width_rest = (widget->statusbar->width - used) % n;
box_width_rest = (statusbar->width - used) % n;
if(!widget->user_supplied_x)
widget->area.x = widget_calculate_offset(widget->statusbar->width,
0,
offset,
widget->alignment);
w->area.x = widget_calculate_offset(statusbar->width,
0, offset, w->widget->align);
if(!widget->user_supplied_y)
widget->area.y = widget->area.y = 0;
w->area.y = 0;
for(c = globalconf.clients; c; c = c->next)
if(tasklist_isvisible(c, widget->statusbar->screen, d->show))
if(tasklist_isvisible(c, statusbar->screen, d->show))
{
icon_width = 0;
style = client_style_get(c);
if(globalconf.focus->client == c)
text = d->text_focus;
else if(c->isurgent)
@ -117,167 +108,177 @@ tasklist_draw(widget_t *widget, draw_context_t *ctx, int offset, int used)
if(d->show_icons)
{
/* draw a background for icons */
area.x = widget->area.x + box_width * i;
area.y = widget->area.y;
area.height = widget->statusbar->height;
area.x = w->area.x + box_width * i;
area.y = w->area.y;
area.height = statusbar->height;
area.width = box_width;
draw_rectangle(ctx, area, 1.0, true, style->bg);
draw_rectangle(statusbar->ctx, area, 1.0, true,
statusbar->colors.bg);
if((r = rule_matching_client(c)) && r->icon)
if(0)
{
area = draw_get_image_size(r->icon);
// area = draw_get_image_size(r->icon);
if(area.width > 0 && area.height > 0)
{
icon_width = ((double) widget->statusbar->height / (double) area.height) * area.width;
draw_image(ctx,
widget->area.x + box_width * i,
widget->area.y,
widget->statusbar->height,
r->icon);
icon_width = ((double) statusbar->height / (double) area.height) * area.width;
draw_image(statusbar->ctx,
w->area.x + box_width * i,
w->area.y,
statusbar->height,
NULL);
// r->icon);
}
}
if(!icon_width && (icon = ewmh_get_window_icon(c->win)))
{
icon_width = ((double) widget->statusbar->height / (double) icon->height)
icon_width = ((double) statusbar->height / (double) icon->height)
* icon->width;
draw_image_from_argb_data(ctx,
widget->area.x + box_width * i,
widget->area.y,
draw_image_from_argb_data(statusbar->ctx,
w->area.x + box_width * i,
w->area.y,
icon->width, icon->height,
widget->statusbar->height, icon->image);
statusbar->height, icon->image);
p_delete(&icon->image);
p_delete(&icon);
}
}
area.x = widget->area.x + icon_width + box_width * i;
area.y = widget->area.y;
area.x = w->area.x + icon_width + box_width * i;
area.y = w->area.y;
area.width = box_width - icon_width;
area.height = widget->statusbar->height;
area.height = statusbar->height;
/* if we're on last elem, it has the last pixels left */
if(i == n - 1)
area.width += box_width_rest;
draw_text(ctx, area, text, style);
draw_text(statusbar->ctx, globalconf.font,
&statusbar->colors.fg,
area, text);
p_delete(&text);
if(c == globalconf.scratch.client)
{
area.x = widget->area.x + icon_width + box_width * i;
area.y = widget->area.y;
area.width = (style->font->height + 2) / 3;
area.height = (style->font->height + 2) / 3;
draw_rectangle(ctx, area, 1.0, c->isfloating, style->fg);
area.x = w->area.x + icon_width + box_width * i;
area.y = w->area.y;
area.width = (globalconf.font->height + 2) / 3;
area.height = (globalconf.font->height + 2) / 3;
draw_rectangle(statusbar->ctx, area, 1.0, c->isfloating, statusbar->colors.fg);
}
else if(c->isfloating || c->ismax)
draw_circle(ctx, widget->area.x + icon_width + box_width * i,
widget->area.y,
(style->font->height + 2) / 4,
c->ismax, style->fg);
draw_circle(statusbar->ctx, w->area.x + icon_width + box_width * i,
w->area.y,
(globalconf.font->height + 2) / 4,
c->ismax, statusbar->colors.fg);
i++;
}
widget->area.width = widget->statusbar->width - used;
widget->area.height = widget->statusbar->height;
w->area.width = statusbar->width - used;
w->area.height = statusbar->height;
return widget->area.width;
return w->area.width;
}
static void
tasklist_button_press(widget_t *widget, xcb_button_press_event_t *ev)
tasklist_button_press(widget_node_t *w, statusbar_t *statusbar,
xcb_button_press_event_t *ev)
{
Button *b;
client_t *c;
Data *d = widget->data;
tag_t *tag;
client_t *c, **lc;
Data *d = w->widget->data;
int n = 0, box_width = 0, i, ci = 0;
/* button1 give focus */
if(ev->detail == XCB_BUTTON_INDEX_1 && CLEANMASK(ev->state) == XCB_NO_SYMBOL)
for(c = globalconf.clients; c; c = c->next)
if(tasklist_isvisible(c, statusbar->screen, d->show))
n++;
if(!n)
return;
box_width = w->area.width / n;
switch(statusbar->position)
{
for(c = globalconf.clients; c; c = c->next)
if(tasklist_isvisible(c, widget->statusbar->screen, d->show))
n++;
if(!n)
return;
box_width = widget->area.width / n;
if(ev->detail == XCB_BUTTON_INDEX_1 && CLEANMASK(ev->state) == XCB_NO_SYMBOL)
{
switch(widget->statusbar->position)
{
case Top:
case Bottom:
ci = (ev->event_x - widget->area.x) / box_width;
break;
case Right:
ci = (ev->event_y - widget->area.x) / box_width;
break;
default:
ci = ((widget->statusbar->width - ev->event_y) - widget->area.x) / box_width;
break;
}
/* found first visible client */
for(c = globalconf.clients;
c && !tasklist_isvisible(c, widget->statusbar->screen, d->show);
c = c->next);
/* found ci-th visible client */
for(i = 0; c ; c = c->next)
if(tasklist_isvisible(c, widget->statusbar->screen, d->show))
if(i++ >= ci)
break;
if(c)
{
/* first switch tag if client not visible */
if(!client_isvisible(c, widget->statusbar->screen))
for(i = 0, tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++)
if(is_client_tagged(c, tag))
tag_view_only_byindex(c->screen, i);
client_focus(c, widget->statusbar->screen, true);
}
return;
}
case Top:
case Bottom:
ci = (ev->event_x - w->area.x) / box_width;
break;
case Right:
ci = (ev->event_y - w->area.x) / box_width;
break;
default:
ci = ((statusbar->width - ev->event_y) - w->area.x) / box_width;
break;
}
/* found first visible client */
for(c = globalconf.clients;
c && !tasklist_isvisible(c, statusbar->screen, d->show);
c = c->next);
/* found ci-th visible client */
for(i = 0; c ; c = c->next)
if(tasklist_isvisible(c, statusbar->screen, d->show))
if(i++ >= ci)
break;
for(b = widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->func)
b->func(widget->statusbar->screen, b->arg);
if(c)
for(b = w->widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
{
lc = lua_newuserdata(globalconf.L, sizeof(client_t *));
*lc = c;
luaA_settype(globalconf.L, "client");
luaA_dofunction(globalconf.L, b->fct, 1);
}
}
static widget_tell_status_t
tasklist_tell(widget_t *widget, const char *property, const char *new_value)
{
Data *d = widget->data;
if(!a_strcmp(property, "text_normal"))
{
p_delete(&d->text_normal);
d->text_normal = a_strdup(new_value);
}
else if(!a_strcmp(property, "text_focus"))
{
p_delete(&d->text_focus);
d->text_focus = a_strdup(new_value);
}
else if(!a_strcmp(property, "text_urgent"))
{
p_delete(&d->text_urgent);
d->text_urgent = a_strdup(new_value);
}
else
return WIDGET_ERROR;
return WIDGET_NOERROR;
}
widget_t *
tasklist_new(statusbar_t *statusbar, cfg_t *config)
tasklist_new(alignment_t align __attribute__ ((unused)))
{
widget_t *w;
Data *d;
char *buf;
w = p_new(widget_t, 1);
widget_common_new(w, statusbar, config);
widget_common_new(w);
w->draw = tasklist_draw;
w->button_press = tasklist_button_press;
w->alignment = AlignFlex;
w->align = AlignFlex;
w->data = d = p_new(Data, 1);
w->tell = tasklist_tell;
d->text_normal = a_strdup(cfg_getstr(config, "text_normal"));
d->text_focus = a_strdup(cfg_getstr(config, "text_focus"));
d->text_urgent = a_strdup(cfg_getstr(config, "text_urgent"));
d->show_icons = cfg_getbool(config, "show_icons");
buf = cfg_getstr(config, "show");
if(!a_strcmp(buf, "all"))
d->show = ShowAll;
else if(!a_strcmp(buf, "tags"))
d->show = ShowTags;
else
d->show = ShowFocus;
d->text_normal = a_strdup(" <title/> ");
d->text_focus = a_strdup(" <title/> ");
d->text_urgent = a_strdup(" <title/> ");
d->show_icons = true;
d->show = ShowTags;
/* Set cache property */
w->cache_flags = WIDGET_CACHE_CLIENTS;

View File

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

View File

@ -149,17 +149,51 @@ window_grabbuttons(xcb_window_t win, int phys_screen)
ANY_MODIFIER);
}
/** Grab buttons on the root window.
* \param phys_screen physical screen id
/** Grab all buttons on the root window.
* \param b The button binding.
*/
void
window_root_grabbuttons(int phys_screen)
window_root_grabbuttons(void)
{
Button *b;
xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, phys_screen);
xcb_screen_t *s;
int phys_screen = globalconf.default_screen;
for(b = globalconf.buttons.root; b; b = b->next)
do
{
s = xcb_aux_get_screen(globalconf.connection, phys_screen);
for(b = globalconf.buttons.root; b; b = b->next)
{
xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod);
xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod | XCB_MOD_MASK_LOCK);
xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod | globalconf.numlockmask);
xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK);
}
phys_screen++;
} while(!globalconf.screens_info->xinerama_is_active
&& phys_screen < globalconf.screens_info->nscreen);
}
/** Grab button on the root window.
* \param b The button binding.
*/
void
window_root_grabbutton(Button *b)
{
xcb_screen_t *s;
int phys_screen = globalconf.default_screen;
do
{
s = xcb_aux_get_screen(globalconf.connection, phys_screen);
xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod);
@ -172,22 +206,27 @@ window_root_grabbuttons(int phys_screen)
xcb_grab_button(globalconf.connection, false, s->root, BUTTONMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_NONE, XCB_NONE,
b->button, b->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK);
}
phys_screen++;
} while(!globalconf.screens_info->xinerama_is_active
&& phys_screen < globalconf.screens_info->nscreen);
}
/** Grab keys on the root window.
* \param phys_screen Physical screen number.
/** Grab key on the root windows.
* \param k The keybinding.
*/
void
window_root_grabkeys(int phys_screen)
window_root_grabkey(keybinding_t *k)
{
xcb_screen_t *s = xcb_aux_get_screen(globalconf.connection, phys_screen);
keybinding_t *k;
int phys_screen = globalconf.default_screen;
xcb_screen_t *s;
xcb_keycode_t kc;
for(k = globalconf.keys; k; k = k->next)
if((kc = k->keycode) || (k->keysym && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym))))
if((kc = k->keycode)
|| (k->keysym && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym))))
{
do
{
s = xcb_aux_get_screen(globalconf.connection, phys_screen);
xcb_grab_key(globalconf.connection, true, s->root,
k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, s->root,
@ -197,7 +236,10 @@ window_root_grabkeys(int phys_screen)
xcb_grab_key(globalconf.connection, true, s->root,
k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC);
}
phys_screen++;
} while(!globalconf.screens_info->xinerama_is_active
&& phys_screen < globalconf.screens_info->nscreen);
}
}
/** Set shape property on window.

View File

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