From c4e88f9928cfea685f6d8ef3c0e90bad51130a99 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Thu, 3 Jan 2008 12:39:28 +0100 Subject: [PATCH] add new tasklist widget --- awesomerc.1.txt | 17 ++++ config.c | 25 +++++- config.mk | 2 +- widget.c | 1 + widget.h | 1 + widgets/tasklist.c | 188 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 widgets/tasklist.c diff --git a/awesomerc.1.txt b/awesomerc.1.txt index b20fa744..f10b198a 100644 --- a/awesomerc.1.txt +++ b/awesomerc.1.txt @@ -138,6 +138,23 @@ This widget shows the title of the focused window. *fg*:: Foreground color. +tasklist +~~~~~~~~ +This widget shows a list of running windows. + +*mouse*:: + Set mouse bindings. +*font*:: + Font to use. +*bg*:: + Background color. +*fg*:: + Foreground color. +*focus_bg*:: + Background color for focused window. +*focus_fg*:: + Foreground color for focused window. + textbox ~~~~~~~ This widget shows a text. diff --git a/config.c b/config.c index 0cd7c82d..d0d1cd3c 100644 --- a/config.c +++ b/config.c @@ -526,7 +526,7 @@ config_parse(const char *confpatharg) CFG_BOOL((char *) "resize", cfg_true, CFGF_NONE), CFG_END() }; - static cfg_opt_t widget_textbox_focus_opts[] = + static cfg_opt_t widget_textbox_opts[] = { CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), CFG_INT((char *) "width", 0, CFGF_NONE), @@ -536,6 +536,24 @@ config_parse(const char *confpatharg) CFG_STR((char *) "font", (char *) NULL, CFGF_NONE), CFG_END() }; + static cfg_opt_t widget_focustitle_opts[] = + { + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), + CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "font", (char *) NULL, CFGF_NONE), + CFG_END() + }; + static cfg_opt_t widget_tasklist_opts[] = + { + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), + CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "focus_fg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "focus_bg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "font", (char *) NULL, CFGF_NONE), + CFG_END() + }; static cfg_opt_t widget_progressbar_bar_opts[] = { CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), @@ -557,13 +575,14 @@ config_parse(const char *confpatharg) CFG_STR((char *) "position", (char *) "top", CFGF_NONE), CFG_INT((char *) "height", 0, CFGF_NONE), CFG_INT((char *) "width", 0, CFGF_NONE), - CFG_SEC((char *) "textbox", widget_textbox_focus_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), + CFG_SEC((char *) "textbox", widget_textbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "taglist", widget_taglist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), - CFG_SEC((char *) "focustitle", widget_textbox_focus_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), + CFG_SEC((char *) "focustitle", widget_focustitle_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "layoutinfo", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "iconbox", widget_iconbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "netwmicon", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "progressbar", widget_progressbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), + CFG_SEC((char *) "tasklist", widget_tasklist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_END() }; static cfg_opt_t tag_opts[] = diff --git a/config.mk b/config.mk index 3510f6c6..ab274d39 100644 --- a/config.mk +++ b/config.mk @@ -7,7 +7,7 @@ RELEASE = "Productivity Breaker" # additional layouts LAYOUTS = layouts/tile.c layouts/floating.c layouts/max.c layouts/fibonacci.c # additional widgets -WIDGETS = widgets/taglist.c widgets/layoutinfo.c widgets/textbox.c widgets/focustitle.c widgets/iconbox.c widgets/netwmicon.c widgets/progressbar.c +WIDGETS = widgets/taglist.c widgets/layoutinfo.c widgets/textbox.c widgets/focustitle.c widgets/iconbox.c widgets/netwmicon.c widgets/progressbar.c widgets/tasklist.c # paths PREFIX = /usr/local diff --git a/widget.c b/widget.c index 38f8632d..c2d105ba 100644 --- a/widget.c +++ b/widget.c @@ -36,6 +36,7 @@ const NameFuncLink WidgetList[] = {"iconbox", iconbox_new}, {"netwmicon", netwmicon_new}, {"progressbar", progressbar_new}, + {"tasklist", tasklist_new}, {NULL, NULL} }; diff --git a/widget.h b/widget.h index e13e3ad7..a0412c0a 100644 --- a/widget.h +++ b/widget.h @@ -42,6 +42,7 @@ WidgetConstructor focustitle_new; WidgetConstructor iconbox_new; WidgetConstructor netwmicon_new; WidgetConstructor progressbar_new; +WidgetConstructor tasklist_new; Uicb uicb_widget_tell; diff --git a/widgets/tasklist.c b/widgets/tasklist.c new file mode 100644 index 00000000..daa09852 --- /dev/null +++ b/widgets/tasklist.c @@ -0,0 +1,188 @@ +/* + * tasklist.c - task list widget + * + * Copyright © 2008 Julien Danjou + * + * 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 +#include "util.h" +#include "widget.h" +#include "layout.h" +#include "client.h" +#include "tag.h" +#include "focus.h" +#include "xutil.h" +#include "screen.h" +#include "event.h" + +extern AwesomeConf globalconf; + +typedef struct +{ + XColor fg_sel; + XColor bg_sel; + XColor fg; + XColor bg; +} Data; + +static int +tasklist_draw(Widget *widget, DrawCtx *ctx, int offset, int used) +{ + VirtScreen vscreen = globalconf.screens[widget->statusbar->screen]; + Client *c; + Data *d = widget->data; + Client *sel = focus_get_current_client(widget->statusbar->screen); + int n = 0, i = 0, box_width = 0; + + for(c = globalconf.clients; c; c = c->next) + if(client_isvisible(c, widget->statusbar->screen)) + n++; + + if(!n) + { + widget->width = 0; + return widget->width; + } + + box_width = (vscreen.statusbar->width - used) / n; + + widget->location = widget_calculate_offset(vscreen.statusbar->width, + 0, + offset, + widget->alignment); + + for(c = globalconf.clients; c; c = c->next) + if(client_isvisible(c, widget->statusbar->screen)) + { + if(sel == c) + { + draw_text(ctx, widget->location + box_width * i, 0, + box_width, + vscreen.statusbar->height, + widget->font->height / 2, widget->font, c->name, + d->fg_sel, d->bg_sel); + } + else + draw_text(ctx, widget->location + box_width * i, 0, + box_width, + vscreen.statusbar->height, + widget->font->height / 2, widget->font, c->name, + d->fg, d->bg); + if(sel->isfloating) + draw_circle(ctx, widget->location + box_width * i, 0, + (widget->font->height + 2) / 4, + sel->ismax, d->fg); + i++; + } + + widget->width = vscreen.statusbar->width - used; + + return widget->width; +} + +static void +tasklist_button_press(Widget *widget, XButtonPressedEvent *ev) +{ + Button *b; + Client *c; + int n = 0, box_width = 0, i = 0, ci = 0; + + /* button1 give focus */ + if(ev->button == Button1 && CLEANMASK(ev->state) == NoSymbol) + { + for(c = globalconf.clients; c; c = c->next) + if(client_isvisible(c, widget->statusbar->screen)) + n++; + + if(!n) + return; + + box_width = widget->width / n; + + if(ev->button == Button1 && CLEANMASK(ev->state) == NoSymbol) + if(widget->statusbar->position == BarTop + || widget->statusbar->position == BarBot) + { + ci = (ev->x - widget->location) / box_width; + + /* found first visible client */ + for(c = globalconf.clients; + c && !client_isvisible(c, widget->statusbar->screen); + c = c->next); + /* found ci-th visible client */ + for(; c && i < ci; c = c->next) + if(client_isvisible(c, widget->statusbar->screen)) + i++; + + focus(c, True, widget->statusbar->screen); + } + } + + 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); + return; + } +} + +Widget * +tasklist_new(Statusbar *statusbar, cfg_t *config) +{ + Widget *w; + Data *d; + char *buf; + int phys_screen = get_phys_screen(statusbar->screen); + + w = p_new(Widget, 1); + widget_common_new(w, statusbar, config); + w->draw = tasklist_draw; + w->button_press = tasklist_button_press; + w->alignment = AlignFlex; + w->data = d = p_new(Data, 1); + + if((buf = cfg_getstr(config, "fg"))) + d->fg = initxcolor(phys_screen, buf); + else + d->fg = globalconf.screens[statusbar->screen].colors_normal[ColFG]; + + if((buf = cfg_getstr(config, "bg"))) + d->bg = initxcolor(phys_screen, buf); + else + d->bg = globalconf.screens[statusbar->screen].colors_normal[ColBG]; + + if((buf = cfg_getstr(config, "focus_bg"))) + d->bg_sel = initxcolor(phys_screen, buf); + else + d->bg_sel = globalconf.screens[statusbar->screen].colors_selected[ColBG]; + + if((buf = cfg_getstr(config, "focus_fg"))) + d->fg_sel = initxcolor(phys_screen, buf); + else + d->fg_sel = globalconf.screens[statusbar->screen].colors_selected[ColFG]; + + if((buf = cfg_getstr(config, "font"))) + w->font = XftFontOpenName(globalconf.display, get_phys_screen(statusbar->screen), buf); + + if(!w->font) + w->font = globalconf.screens[statusbar->screen].font; + + return w; +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80