! NEW LAUNCHER ! Uicb function 'launcher', new [lauchers] section and 'l' infobarelement. See default wmfsrc please

This commit is contained in:
Martin Duquesnoy 2012-01-25 23:11:15 +01:00
parent 0ee606d251
commit 99bb7e0812
10 changed files with 354 additions and 9 deletions

View File

@ -11,6 +11,7 @@ SRCS= \
src/ewmh.c \ src/ewmh.c \
src/infobar.c \ src/infobar.c \
src/layout.c \ src/layout.c \
src/launcher.c \
src/parse_api.c \ src/parse_api.c \
src/parse.c \ src/parse.c \
src/screen.c \ src/screen.c \

View File

@ -267,6 +267,38 @@ config_rule(void)
free(ks); free(ks);
} }
static void
config_launcher(void)
{
struct conf_sec *sec, **ks;
struct launcher *l;
int n, i;
/* [launchers] */
sec = fetch_section_first(NULL, "launchers");
ks = fetch_section(sec, "launcher");
n = fetch_section_count(ks);
SLIST_INIT(&W->h.launcher);
/* [launcher] */
for(i = 0; i < n; ++i)
{
l = xcalloc(1, sizeof(struct launcher));
l->name = xstrdup(fetch_opt_first(ks[i], "default", "name").str);
l->prompt = xstrdup(fetch_opt_first(ks[i], ":", "prompt").str);
l->command = xstrdup(fetch_opt_first(ks[i], "spawn", "command").str);
if((l->width = fetch_opt_first(ks[i], "150", "width").num) <= 0)
l->width = 150;
SLIST_INSERT_HEAD(&W->h.launcher, l, next);
}
free(ks);
}
static void static void
config_keybind(void) config_keybind(void)
{ {
@ -338,6 +370,7 @@ config_init(void)
config_client(); config_client();
config_bars(); config_bars();
config_rule(); config_rule();
config_launcher();
free_conf(); free_conf();
} }

View File

@ -18,6 +18,7 @@
#include "mouse.h" #include "mouse.h"
#include "screen.h" #include "screen.h"
#include "infobar.h" #include "infobar.h"
#include "launcher.h"
#define THEME_DEFAULT (SLIST_FIRST(&W->h.theme)) #define THEME_DEFAULT (SLIST_FIRST(&W->h.theme))
@ -88,6 +89,9 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
{ "screen_move_client_next", uicb_screen_move_client_next }, { "screen_move_client_next", uicb_screen_move_client_next },
{ "screen_move_client_prev", uicb_screen_move_client_prev }, { "screen_move_client_prev", uicb_screen_move_client_prev },
/* Launcher */
{ "launcher", uicb_launcher },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -18,6 +18,8 @@ static void infobar_elem_status_init(struct element *e);
static void infobar_elem_status_update(struct element *e); static void infobar_elem_status_update(struct element *e);
static void infobar_elem_systray_init(struct element *e); static void infobar_elem_systray_init(struct element *e);
static void infobar_elem_systray_update(struct element *e); static void infobar_elem_systray_update(struct element *e);
static void infobar_elem_launcher_init(struct element *e);
static void infobar_elem_launcher_update(struct element *e);
const struct elem_funcs const struct elem_funcs
{ {
@ -26,9 +28,10 @@ const struct elem_funcs
void (*func_update)(struct element *e); void (*func_update)(struct element *e);
} elem_funcs[] = } elem_funcs[] =
{ {
{ 't', infobar_elem_tag_init, infobar_elem_tag_update }, { 't', infobar_elem_tag_init, infobar_elem_tag_update },
{ 's', infobar_elem_status_init, infobar_elem_status_update }, { 's', infobar_elem_status_init, infobar_elem_status_update },
{ 'y', infobar_elem_systray_init, infobar_elem_systray_update }, { 'y', infobar_elem_systray_init, infobar_elem_systray_update },
{ 'l', infobar_elem_launcher_init, infobar_elem_launcher_update },
{ '\0', NULL, NULL } { '\0', NULL, NULL }
}; };
@ -218,12 +221,60 @@ infobar_elem_systray_update(struct element *e)
systray_update(); systray_update();
} }
static void
infobar_elem_launcher_init(struct element *e)
{
struct barwin *b;
if(!(W->flags & WMFS_LAUNCHER))
e->geo.w = 1;
infobar_elem_placement(e);
if(!(b = SLIST_FIRST(&e->bars)))
{
b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
b->fg = e->infobar->theme->bars.fg;
b->bg = e->infobar->theme->bars.bg;
SLIST_INSERT_HEAD(&e->bars, b, enext);
}
else
{
barwin_move(b, e->geo.x, e->geo.y);
barwin_resize(b, e->geo.w, e->geo.h);
}
barwin_refresh_color(b);
barwin_refresh(b);
}
static void
infobar_elem_launcher_update(struct element *e)
{
struct barwin *b = SLIST_FIRST(&e->bars);
int l;
if(!(W->flags & WMFS_LAUNCHER))
return;
barwin_refresh_color(b);
l = draw_textw(e->infobar->theme, e->data) + 2;
draw_text(b->dr, e->infobar->theme, 1, TEXTY(e->infobar->theme, e->geo.h), b->fg, e->data);
/* Cursor */
XDrawLine(W->dpy, b->dr, W->gc, l, 2, l, e->geo.h - 4);
barwin_refresh(b);
}
#define ELEM_INIT(a) \ #define ELEM_INIT(a) \
do { \ do { \
e = xcalloc(1, sizeof(struct element)); \ e = xcalloc(1, sizeof(struct element)); \
SLIST_INIT(&e->bars); \ SLIST_INIT(&e->bars); \
e->infobar = i; \ e->infobar = i; \
e->type = j; \ e->type = j; \
e->data = NULL; \
e->align = a; \ e->align = a; \
e->func_init = elem_funcs[j].func_init; \ e->func_init = elem_funcs[j].func_init; \
e->func_update = elem_funcs[j].func_update; \ e->func_update = elem_funcs[j].func_update; \
@ -336,6 +387,8 @@ infobar_elem_reinit(struct infobar *i)
{ {
struct element *e; struct element *e;
barwin_refresh_color(i->bar);
TAILQ_FOREACH(e, &i->elements, next) TAILQ_FOREACH(e, &i->elements, next)
{ {
/* Status element found, scan from the tail now */ /* Status element found, scan from the tail now */
@ -361,6 +414,8 @@ infobar_elem_reinit(struct infobar *i)
e->func_init(e); e->func_init(e);
e->func_update(e); e->func_update(e);
} }
barwin_refresh(i->bar);
} }
struct infobar* struct infobar*
@ -412,7 +467,6 @@ infobar_remove(struct infobar *i)
free(i->elemorder); free(i->elemorder);
free(i->name); free(i->name);
free(i->status);
if(i == W->systray.infobar) if(i == W->systray.infobar)
systray_freeicons(); systray_freeicons();

View File

@ -10,7 +10,7 @@
#include "util.h" #include "util.h"
#include "tag.h" #include "tag.h"
enum { ElemTag = 0, ElemStatus, ElemSystray, ElemCustom, ElemLast }; enum { ElemTag = 0, ElemStatus, ElemSystray, ElemLauncher, ElemCustom, ElemLast };
struct infobar *infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos, const char *elem); struct infobar *infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos, const char *elem);
void infobar_elem_update(struct infobar *i, int type); void infobar_elem_update(struct infobar *i, int type);

196
src/launcher.c Normal file
View File

@ -0,0 +1,196 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#include <X11/Xutil.h>
#include <string.h>
#include "wmfs.h"
#include "event.h"
#include "util.h"
#include "infobar.h"
#include "config.h"
#define LAUNCHER_INIT_ELEM(width) \
SLIST_FOREACH(ib, &W->screen->infobars, next) \
{ \
TAILQ_FOREACH(e, &ib->elements, next) \
if(e->type == ElemLauncher) \
{ \
e->geo.w = width; \
e->data = data; \
} \
infobar_elem_reinit(ib); \
}
static void
launcher_process(struct launcher *l)
{
struct infobar *ib;
struct element *e;
bool loop = true;
char buf[512] = { 0 };
char tmp[32] = { 0 };
char *p, *data, *arg, *cmd = xstrdup(l->command);
int i, pos = 0, histpos = 0;
void (*func)(Uicb);
XEvent ev;
KeySym ks;
W->flags |= WMFS_LAUNCHER;
/* Prepare elements */
xasprintf(&data, "%s ", l->prompt);
LAUNCHER_INIT_ELEM(l->width);
XGrabKeyboard(W->dpy, W->root, true, GrabModeAsync, GrabModeAsync, CurrentTime);
while(loop)
{
XNextEvent(W->dpy, &ev);
if(ev.type != KeyPress)
{
EVENT_HANDLE(&ev);
continue;
}
/* Get pressed key */
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
/* Check Ctrl-c / Ctrl-d */
if(ev.xkey.state & ControlMask)
{
switch(ks)
{
case XK_c:
case XK_d:
ks = XK_Escape;
break;
case XK_p:
ks = XK_Up;
break;
case XK_n:
ks = XK_Down;
break;
}
}
/* Check if there is a keypad */
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
ks = XK_Return;
/* Manage pressed keys */
switch(ks)
{
case XK_Up:
if(l->nhisto)
{
if(histpos >= (int)l->nhisto)
histpos = 0;
strncpy(buf, l->histo[l->nhisto - ++histpos], sizeof(buf));
pos = strlen(buf);
}
break;
case XK_Down:
if(l->nhisto && histpos > 0 && histpos < (int)l->nhisto)
{
strncpy(buf, l->histo[l->nhisto - --histpos], sizeof(buf));
pos = strlen(buf);
}
break;
case XK_Return:
/* Get function name only, if cmds are added in command */
arg = NULL;
if((p = strchr(cmd, ' ')))
{
*p = '\0';
xasprintf(&arg, "%s %s", p + 1, buf);
}
if((func = uicb_name_func(cmd)))
{
if(arg)
{
func(arg);
free(arg);
}
else
func(buf);
}
/* Histo */
if(l->nhisto + 1 > HISTOLEN)
{
for(i = l->nhisto - 1; i > 1; --i)
strncpy(l->histo[i], l->histo[i - 1], sizeof(l->histo[i]));
l->nhisto = 0;
}
/* Store in histo array */
strncpy(l->histo[l->nhisto++], buf, sizeof(buf));
loop = false;
break;
case XK_Escape:
loop = false;
break;
/* TODO: Completion */
case XK_Tab:
break;
case XK_BackSpace:
if(pos)
buf[--pos] = '\0';
break;
default:
strncat(buf, tmp, sizeof(tmp));
++pos;
break;
}
free(data);
xasprintf(&data, "%s %s", l->prompt, buf);
/* Update EVERY launcher element of the screen */
SLIST_FOREACH(ib, &W->screen->infobars, next)
{
TAILQ_FOREACH(e, &ib->elements, next)
{
if(e->type != ElemLauncher)
continue;
e->data = data;
e->func_update(e);
}
}
}
XUngrabKeyboard(W->dpy, CurrentTime);
free(cmd);
/* 'Close' launcher elements */
W->flags ^= WMFS_LAUNCHER;
data = NULL;
LAUNCHER_INIT_ELEM(1);
}
void
uicb_launcher(Uicb cmd)
{
struct launcher *l;
SLIST_FOREACH(l, &W->h.launcher, next)
if(!strcmp(l->name, cmd))
{
launcher_process(l);
break;
}
}

13
src/launcher.h Normal file
View File

@ -0,0 +1,13 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#ifndef LAUNCHER_H
#define LAUNCHER_H
#include "wmfs.h"
void uicb_launcher(Uicb cmd);
#endif /* LAUNCHER_H */

View File

@ -406,6 +406,7 @@ wmfs_quit(void)
struct theme *t; struct theme *t;
struct client *c; struct client *c;
struct mousebind *m; struct mousebind *m;
struct launcher *l;
ewmh_update_wmfs_props(); ewmh_update_wmfs_props();
@ -419,7 +420,6 @@ wmfs_quit(void)
client_remove(c); client_remove(c);
} }
/* Will free: /* Will free:
* *
* Screens -> tags * Screens -> tags
@ -460,6 +460,16 @@ wmfs_quit(void)
free(k); free(k);
} }
while(!SLIST_EMPTY(&W->h.launcher))
{
l = SLIST_FIRST(&W->h.launcher);
SLIST_REMOVE_HEAD(&W->h.launcher, next);
free((void*)l->name);
free((void*)l->prompt);
free((void*)l->command);
free(l);
}
while(!SLIST_EMPTY(&W->h.mousebind)) while(!SLIST_EMPTY(&W->h.mousebind))
{ {
m = SLIST_FIRST(&W->h.mousebind); m = SLIST_FIRST(&W->h.mousebind);

View File

@ -123,6 +123,7 @@ struct element
struct infobar *infobar; struct infobar *infobar;
struct status_ctx *statusctx; struct status_ctx *statusctx;
int type; int type;
char *data;
enum position align; enum position align;
void (*func_init)(struct element *e); void (*func_init)(struct element *e);
void (*func_update)(struct element *e); void (*func_update)(struct element *e);
@ -140,7 +141,6 @@ struct infobar
enum barpos pos; enum barpos pos;
char *elemorder; char *elemorder;
char *name; char *name;
char *status;
TAILQ_HEAD(esub, element) elements; TAILQ_HEAD(esub, element) elements;
SLIST_ENTRY(infobar) next; SLIST_ENTRY(infobar) next;
}; };
@ -275,6 +275,18 @@ struct rule
SLIST_ENTRY(rule) next; SLIST_ENTRY(rule) next;
}; };
struct launcher
{
char *name;
char *prompt;
char *command;
#define HISTOLEN 64
char histo[HISTOLEN][256];
int nhisto;
int width;
SLIST_ENTRY(launcher) next;
};
struct _systray struct _systray
{ {
struct geo geo; struct geo geo;
@ -298,6 +310,7 @@ struct wmfs
#define WMFS_RELOAD 0x04 #define WMFS_RELOAD 0x04
#define WMFS_SYSTRAY 0x08 #define WMFS_SYSTRAY 0x08
#define WMFS_LOG 0x10 #define WMFS_LOG 0x10
#define WMFS_LAUNCHER 0x20
Flags flags; Flags flags;
GC gc, rgc; GC gc, rgc;
Atom *net_atom; Atom *net_atom;
@ -325,6 +338,7 @@ struct wmfs
SLIST_HEAD(, theme) theme; SLIST_HEAD(, theme) theme;
SLIST_HEAD(, rule) rule; SLIST_HEAD(, rule) rule;
SLIST_HEAD(, mousebind) mousebind; SLIST_HEAD(, mousebind) mousebind;
SLIST_HEAD(, launcher) launcher;
} h; } h;
/* /*

24
wmfsrc
View File

@ -65,11 +65,12 @@
# t Tags # t Tags
# s Statustext (will take available space) # s Statustext (will take available space)
# y Systray (can be set only ONE time among all element) # y Systray (can be set only ONE time among all element)
# l Launcher (will be expended at launcher use)
[bar] [bar]
position = 0 position = 0
screen = 0 screen = 0
elements = "tsy" # element order in bar elements = "tlsy" # element order in bar
theme = "default" theme = "default"
[/bar] [/bar]
@ -135,6 +136,22 @@
[/rules] [/rules]
[launchers]
# command can be an uicb function or an uicb function + extension (see example)
[launcher]
name = "exec"
prompt = "Run:"
# Example of uicb + ext:
# command = "spawn xterm -e"
command = "spawn"
width = 150
[/launcher]
[/launchers]
[keys] [keys]
[key] mod = {"Super"} key = "Return" func = "spawn" cmd = "urxvt || xterm" [/key] [key] mod = {"Super"} key = "Return" func = "spawn" cmd = "urxvt || xterm" [/key]
@ -215,6 +232,9 @@
# Layout set historic travelling function (TESTING) # Layout set historic travelling function (TESTING)
[key] mod = {"Super"} key = "o" func = "layout_prev_set" [/key] [key] mod = {"Super"} key = "o" func = "layout_prev_set" [/key]
[key] mod = {"Super"} key = "p" func = "layout_next_set" [/key] [key] mod = {"Super", "Shift"} key = "o" func = "layout_next_set" [/key]
# Launcher
[key] mod = {"Super"} key = "p" func = "launcher" cmd = "exec" [/key]
[/keys] [/keys]