From c900e378435e09732046a1f2e8850c0cffa577bd Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Thu, 27 Dec 2007 15:49:00 +0100 Subject: [PATCH] add mouse bindings to status bar --- awesome.c | 3 -- awesomerc | 120 ++++++++++++++++++++++--------------------- config.c | 64 +++++++++++------------ config.h | 5 +- draw.c | 20 ++++---- draw.h | 3 +- event.c | 55 ++++++++++---------- event.h | 2 + widget.c | 12 +++++ widgets/layoutinfo.c | 2 +- widgets/taglist.c | 33 +++++++++++- widgets/textbox.c | 2 +- 12 files changed, 180 insertions(+), 141 deletions(-) diff --git a/awesome.c b/awesome.c index 7a079e0f..1ee98423 100644 --- a/awesome.c +++ b/awesome.c @@ -129,9 +129,6 @@ cleanup() p_delete(&k); } - cleanup_buttons(globalconf.buttons.tag); - cleanup_buttons(globalconf.buttons.title); - cleanup_buttons(globalconf.buttons.layout); cleanup_buttons(globalconf.buttons.root); cleanup_buttons(globalconf.buttons.client); diff --git a/awesomerc b/awesomerc index 47876597..3a451e2b 100644 --- a/awesomerc +++ b/awesomerc @@ -25,8 +25,68 @@ screen 0 { position = "top" - taglist mytaglist {} - layoutinfo mylayoutinfo {} + 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" + arg = "+1" + } + mouse + { + button = "4" + command = "tag_setlayout" + arg = "+1" + } + mouse + { + button = "3" + command = "tag_setlayout" + arg = "-1" + } + mouse + { + button = "5" + command = "tag_setlayout" + arg = "-1" + } + } netwmicon mynetwmicon {} focustitle myfocustitle {} textbox mytextbox { text = "awesome!" } @@ -43,62 +103,6 @@ rules mouse { - tag - { - button = "1" - command = "tag_view" - } - tag - { - button = "1" - modkey = {"Mod4"} - command = "client_tag" - } - tag - { - button = "3" - command = "tag_toggleview" - } - tag - { - button = "3" - modkey = {"Mod4"} - command = "client_toggletag" - } - tag - { - button = "4" - command = "tag_viewnext" - } - tag - { - button = "5" - command = "tag_viewprev" - } - layout - { - button = "1" - command = "tag_setlayout" - arg = "+1" - } - layout - { - button = "4" - command = "tag_setlayout" - arg = "+1" - } - layout - { - button = "3" - command = "tag_setlayout" - arg = "-1" - } - layout - { - button = "5" - command = "tag_setlayout" - arg = "-1" - } root { button = "3" diff --git a/config.c b/config.c index fe076523..286360ab 100644 --- a/config.c +++ b/config.c @@ -286,17 +286,17 @@ create_widgets(cfg_t* cfg_statusbar, Statusbar *statusbar) { wptr = widgets + i; widget_new = name_func_lookup(cfg_name(wptr), WidgetList); - if (widget_new) + if(widget_new) + { if(!widget) - { - widget = widget_new(statusbar, wptr); - statusbar->widgets = widget; - } + statusbar->widgets = widget = widget_new(statusbar, wptr); else { widget->next = widget_new(statusbar, wptr); widget = widget->next; } + widget->buttons = parse_mouse_bindings(wptr, "mouse", a_strcmp(cfg_name(wptr), "taglist")); + } else warn("Ignoring unknown widget: %s.\n", cfg_name(widgets + i)); } @@ -332,17 +332,40 @@ config_parse(const char *confpatharg) CFG_STR((char *) "tab_border", (char *) "#ff0000", CFGF_NONE), CFG_END() }; + static cfg_opt_t mouse_taglist_opts[] = + { + CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE), + CFG_STR((char *) "button", (char *) "None", CFGF_NONE), + CFG_STR((char *) "command", (char *) "", CFGF_NONE), + CFG_END() + }; + static cfg_opt_t mouse_generic_opts[] = + { + CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE), + CFG_STR((char *) "button", (char *) "None", CFGF_NONE), + CFG_STR((char *) "command", (char *) "", CFGF_NONE), + CFG_STR((char *) "arg", NULL, CFGF_NONE), + CFG_END() + }; static cfg_opt_t widget_opts[] = { + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), + CFG_END() + }; + static cfg_opt_t widget_taglist_opts[] = + { + CFG_SEC((char *) "mouse", mouse_taglist_opts, CFGF_MULTI), CFG_END() }; static cfg_opt_t widget_iconbox_opts[] = { + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), CFG_STR((char *) "image", (char *) NULL, CFGF_NONE), CFG_END() }; static cfg_opt_t widget_textbox_opts[] = { + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), CFG_STR((char *) "text", (char *) NULL, CFGF_NONE), CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), @@ -350,6 +373,7 @@ config_parse(const char *confpatharg) }; static cfg_opt_t widget_progressbar_opts[] = { + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), CFG_INT((char *) "width", 102, CFGF_NONE), CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), @@ -359,7 +383,7 @@ config_parse(const char *confpatharg) { CFG_STR((char *) "position", (char *) "top", CFGF_NONE), CFG_SEC((char *) "textbox", widget_textbox_opts, CFGF_TITLE | CFGF_MULTI), - CFG_SEC((char *) "taglist", widget_opts, CFGF_TITLE | CFGF_MULTI), + CFG_SEC((char *) "taglist", widget_taglist_opts, CFGF_TITLE | CFGF_MULTI), CFG_SEC((char *) "focustitle", widget_opts, CFGF_TITLE | CFGF_MULTI), CFG_SEC((char *) "layoutinfo", widget_opts, CFGF_TITLE | CFGF_MULTI), CFG_SEC((char *) "iconbox", widget_iconbox_opts, CFGF_TITLE | CFGF_MULTI), @@ -443,26 +467,8 @@ config_parse(const char *confpatharg) CFG_SEC((char *) "keylist", keylist_opts, CFGF_MULTI), CFG_END() }; - static cfg_opt_t mouse_tag_opts[] = - { - CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE), - CFG_STR((char *) "button", (char *) "None", CFGF_NONE), - CFG_STR((char *) "command", (char *) "", CFGF_NONE), - CFG_END() - }; - static cfg_opt_t mouse_generic_opts[] = - { - CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE), - CFG_STR((char *) "button", (char *) "None", CFGF_NONE), - CFG_STR((char *) "command", (char *) "", CFGF_NONE), - CFG_STR((char *) "arg", NULL, CFGF_NONE), - CFG_END() - }; static cfg_opt_t mouse_opts[] = { - CFG_SEC((char *) "tag", mouse_tag_opts, CFGF_MULTI), - CFG_SEC((char *) "layout", mouse_generic_opts, CFGF_MULTI), - CFG_SEC((char *) "title", mouse_generic_opts, CFGF_MULTI), CFG_SEC((char *) "root", mouse_generic_opts, CFGF_MULTI), CFG_SEC((char *) "client", mouse_generic_opts, CFGF_MULTI), CFG_END() @@ -675,16 +681,6 @@ config_parse(const char *confpatharg) compileregs(globalconf.rules); - - /* Mouse: tags click bindings */ - globalconf.buttons.tag = parse_mouse_bindings(cfg_mouse, "tag", False); - - /* Mouse: layout click bindings */ - globalconf.buttons.layout = parse_mouse_bindings(cfg_mouse, "layout", True); - - /* Mouse: title click bindings */ - globalconf.buttons.title = parse_mouse_bindings(cfg_mouse, "title", True); - /* Mouse: root window click bindings */ globalconf.buttons.root = parse_mouse_bindings(cfg_mouse, "root", True); diff --git a/config.h b/config.h index c485d963..5d4d3c93 100644 --- a/config.h +++ b/config.h @@ -229,11 +229,13 @@ struct Widget char *name; int (*draw)(Widget *, DrawCtx *, int, int); void (*tell)(Widget *, char *); + void (*button_press)(Widget *, XButtonPressedEvent *); Statusbar *statusbar; int alignment; void *data; int location; int width; + Button *buttons; Widget *next; }; @@ -252,9 +254,6 @@ struct AwesomeConf /** Mouse bindings list */ struct { - Button *tag; - Button *title; - Button *layout; Button *root; Button *client; } buttons; diff --git a/draw.c b/draw.c index cfb6e496..428fd3ac 100644 --- a/draw.c +++ b/draw.c @@ -27,6 +27,8 @@ #include "util.h" #include "draw.h" +extern AwesomeConf globalconf; + DrawCtx * draw_get_context(Display *display, int phys_screen, int width, int height) { @@ -77,7 +79,7 @@ draw_text(DrawCtx *ctx, int x, int y, int w, int h, XftFont *font, const char *t len = sizeof(buf) - 1; memcpy(buf, text, len); buf[len] = 0; - while(len && (nw = textwidth(ctx, font, buf)) > w) + while(len && (nw = textwidth(font, buf)) > w) buf[--len] = 0; if(nw > w) return; /* too long */ @@ -244,18 +246,18 @@ draw_rotate(DrawCtx *ctx, int screen, double angle, int tx, int ty) return newdrawable; } -unsigned short -textwidth_primitive(Display *display, XftFont *font, char *text) +static unsigned short +textwidth_primitive(XftFont *font, char *text) { cairo_surface_t *surface; cairo_t *cr; cairo_font_face_t *font_face; cairo_text_extents_t te; - surface = cairo_xlib_surface_create(display, DefaultScreen(display), - DefaultVisual(display, DefaultScreen(display)), - DisplayWidth(display, DefaultScreen(display)), - DisplayHeight(display, DefaultScreen(display))); + surface = cairo_xlib_surface_create(globalconf.display, DefaultScreen(globalconf.display), + DefaultVisual(globalconf.display, DefaultScreen(globalconf.display)), + DisplayWidth(globalconf.display, DefaultScreen(globalconf.display)), + DisplayHeight(globalconf.display, DefaultScreen(globalconf.display))); cr = cairo_create(surface); font_face = cairo_ft_font_face_create_for_pattern(font->pattern); cairo_set_font_face(cr, font_face); @@ -269,11 +271,11 @@ textwidth_primitive(Display *display, XftFont *font, char *text) } unsigned short -textwidth(DrawCtx *ctx, XftFont *font, char *text) +textwidth(XftFont *font, char *text) { if (!a_strlen(text)) return 0; - return textwidth_primitive(ctx->display, font, text); + return textwidth_primitive(font, text); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/draw.h b/draw.h index dc78cae5..6d07bfd5 100644 --- a/draw.h +++ b/draw.h @@ -45,7 +45,6 @@ void draw_image(DrawCtx *, int, int, int, const char *); void draw_image_from_argb_data(DrawCtx *, int, int, int, int, int, unsigned char *); int draw_get_image_width(const char *filename); Drawable draw_rotate(DrawCtx *, int, double, int, int); -unsigned short textwidth(DrawCtx *, XftFont *, char *); -unsigned short textwidth_primitive(Display*, XftFont*, char*); +unsigned short textwidth(XftFont *, char *); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/event.c b/event.c index ef1772e2..6bc37380 100644 --- a/event.c +++ b/event.c @@ -40,8 +40,6 @@ extern AwesomeConf globalconf; -#define CLEANMASK(mask) (mask & ~(globalconf.numlockmask | LockMask)) - static void handle_mouse_button_press(int screen, unsigned int button, unsigned int state, Button *buttons, char *arg) @@ -60,43 +58,44 @@ handle_mouse_button_press(int screen, unsigned int button, unsigned int state, } void -handle_event_buttonpress(XEvent * e) +handle_event_buttonpress(XEvent *e) { int i, screen, x = 0, y = 0; unsigned int udummy; Client *c; Window wdummy; - char arg[256]; - Tag *tag; + Widget *widget; XButtonPressedEvent *ev = &e->xbutton; for(screen = 0; screen < get_screen_count(); screen++) if(globalconf.screens[screen].statusbar->window == ev->window) { - for(i = 1, tag = globalconf.screens[screen].tags; tag; tag = tag->next, i++) - { - x += textwidth_primitive(e->xany.display, globalconf.screens[screen].font, tag->name); - if(((globalconf.screens[screen].statusbar->position == BarTop - || globalconf.screens[screen].statusbar->position == BarBot) - && ev->x < x) - || (globalconf.screens[screen].statusbar->position == BarRight && ev->y < x) - || (globalconf.screens[screen].statusbar->position == BarLeft && ev->y > globalconf.screens[screen].statusbar->width - x)) - { - snprintf(arg, sizeof(arg), "%d", i); - handle_mouse_button_press(screen, ev->button, ev->state, globalconf.buttons.tag, arg); - return; - } - } - x += globalconf.screens[screen].statusbar->txtlayoutwidth; - if(((globalconf.screens[screen].statusbar->position == BarTop + if(globalconf.screens[screen].statusbar->position == BarTop || globalconf.screens[screen].statusbar->position == BarBot) - && ev->x < x) - || (globalconf.screens[screen].statusbar->position == BarRight && ev->y < x) - || (globalconf.screens[screen].statusbar->position == BarLeft && ev->y > globalconf.screens[screen].statusbar->width - x)) - handle_mouse_button_press(screen, ev->button, ev->state, globalconf.buttons.layout, NULL); - else - handle_mouse_button_press(screen, ev->button, ev->state, globalconf.buttons.title, NULL); - return; + for(widget = globalconf.screens[screen].statusbar->widgets; widget; widget = widget->next) + if(ev->x >= widget->location && ev->x <= widget->location + widget->width) + { + widget->button_press(widget, ev); + return; + } + + if(globalconf.screens[screen].statusbar->position == BarRight) + for(widget = globalconf.screens[screen].statusbar->widgets; widget; widget = widget->next) + if(ev->y >= widget->location && ev->y <= widget->location + widget->width) + { + widget->button_press(widget, ev); + return; + } + + if(globalconf.screens[screen].statusbar->position == BarLeft) + for(widget = globalconf.screens[screen].statusbar->widgets; widget; widget = widget->next) + if(globalconf.screens[screen].statusbar->width - ev->y >= widget->location + && globalconf.screens[screen].statusbar->width - ev->y + <= widget->location + widget->width) + { + widget->button_press(widget, ev); + return; + } } if((c = get_client_bywin(globalconf.clients, ev->window))) diff --git a/event.h b/event.h index fa84e7cd..9e719d96 100644 --- a/event.h +++ b/event.h @@ -24,6 +24,8 @@ #include "config.h" +#define CLEANMASK(mask) (mask & ~(globalconf.numlockmask | LockMask)) + void grabkeys(int); void handle_event_buttonpress(XEvent *); diff --git a/widget.c b/widget.c index 2cd69de3..d38712d1 100644 --- a/widget.c +++ b/widget.c @@ -23,6 +23,7 @@ #include "util.h" #include "widget.h" #include "statusbar.h" +#include "event.h" extern AwesomeConf globalconf; @@ -80,6 +81,16 @@ widget_find(char *name, int screen) return NULL; } +static void +widget_common_button_press(Widget *widget, XButtonPressedEvent *ev) +{ + Button *b; + + for(b = widget->buttons; b; b = b->next) + if(ev->button == b->button && CLEANMASK(ev->state) == b->mod && b->func) + b->func(widget->statusbar->screen, b->arg); +} + static void widget_common_tell(Widget *widget, char *command __attribute__ ((unused))) { @@ -95,6 +106,7 @@ widget_common_new(Widget *widget, Statusbar *statusbar, cfg_t* config) name = cfg_title(config); widget->name = a_strdup(name); widget->tell = widget_common_tell; + widget->button_press = widget_common_button_press; } /** Send command to widget diff --git a/widgets/layoutinfo.c b/widgets/layoutinfo.c index 14c1eff0..98e047e7 100644 --- a/widgets/layoutinfo.c +++ b/widgets/layoutinfo.c @@ -56,7 +56,7 @@ layoutinfo_new(Statusbar *statusbar, cfg_t* config) Widget *w; w = p_new(Widget, 1); widget_common_new(w, statusbar, config); - w->draw = (void*) layoutinfo_draw; + w->draw = layoutinfo_draw; return w; } diff --git a/widgets/taglist.c b/widgets/taglist.c index 2918ff4a..910cc8ad 100644 --- a/widgets/taglist.c +++ b/widgets/taglist.c @@ -24,6 +24,7 @@ #include "util.h" #include "widget.h" #include "tag.h" +#include "event.h" extern AwesomeConf globalconf; @@ -71,7 +72,7 @@ taglist_draw(Widget *widget, flagsize = (vscreen.font->height + 2) / 4; for(tag = vscreen.tags; tag; tag = tag->next) - widget->width += textwidth(ctx, vscreen.font, tag->name); + widget->width += textwidth(vscreen.font, tag->name); widget->location = widget_calculate_offset(widget->statusbar->width, widget->width, @@ -81,7 +82,7 @@ taglist_draw(Widget *widget, widget->width = 0; for(tag = vscreen.tags; tag; tag = tag->next) { - w = textwidth(ctx, vscreen.font, tag->name); + w = textwidth(vscreen.font, tag->name); if(tag->selected) colors = vscreen.colors_selected; else if(isurgent(widget->statusbar->screen, tag)) @@ -105,6 +106,33 @@ taglist_draw(Widget *widget, return widget->width; } +static void +taglist_button_press(Widget *widget, XButtonPressedEvent *ev) +{ + VirtScreen vscreen = globalconf.screens[widget->statusbar->screen]; + Button *b; + Tag *tag; + char buf[4]; + int prev_width = 0, width = 0, i = 1; + + for(b = widget->buttons; b; b = b->next) + if(ev->button == b->button && CLEANMASK(ev->state) == b->mod && b->func) + for(tag = vscreen.tags; tag; tag = tag->next, i++) + { + width = textwidth(vscreen.font, tag->name); + if(widget->statusbar->position == BarTop + || widget->statusbar->position == BarBot) + if(ev->x >= widget->location + prev_width + && ev->x <= widget->location + prev_width + width) + { + snprintf(buf, sizeof(buf), "%d", i); + b->func(widget->statusbar->screen, buf); + return; + } + prev_width += width; + } +} + Widget * taglist_new(Statusbar *statusbar, cfg_t *config) { @@ -112,6 +140,7 @@ taglist_new(Statusbar *statusbar, cfg_t *config) w = p_new(Widget, 1); widget_common_new(w, statusbar, config); w->draw = taglist_draw; + w->button_press = taglist_button_press; return w; } diff --git a/widgets/textbox.c b/widgets/textbox.c index e3e96c21..0d186952 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -49,7 +49,7 @@ textbox_draw(Widget *widget, DrawCtx *ctx, int offset, VirtScreen vscreen = globalconf.screens[widget->statusbar->screen]; Data *d = widget->data; - widget->width = textwidth(ctx, vscreen.font, d->text); + widget->width = textwidth(vscreen.font, d->text); widget->location = widget_calculate_offset(widget->statusbar->width, widget->width, offset,