! NEW LAUNCHER ! Uicb function 'launcher', new [lauchers] section and 'l' infobarelement. See default wmfsrc please
This commit is contained in:
parent
0ee606d251
commit
99bb7e0812
@ -11,6 +11,7 @@ SRCS= \
|
||||
src/ewmh.c \
|
||||
src/infobar.c \
|
||||
src/layout.c \
|
||||
src/launcher.c \
|
||||
src/parse_api.c \
|
||||
src/parse.c \
|
||||
src/screen.c \
|
||||
|
||||
33
src/config.c
33
src/config.c
@ -267,6 +267,38 @@ config_rule(void)
|
||||
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
|
||||
config_keybind(void)
|
||||
{
|
||||
@ -338,6 +370,7 @@ config_init(void)
|
||||
config_client();
|
||||
config_bars();
|
||||
config_rule();
|
||||
config_launcher();
|
||||
|
||||
free_conf();
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "mouse.h"
|
||||
#include "screen.h"
|
||||
#include "infobar.h"
|
||||
#include "launcher.h"
|
||||
|
||||
#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_prev", uicb_screen_move_client_prev },
|
||||
|
||||
/* Launcher */
|
||||
{ "launcher", uicb_launcher },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
@ -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_systray_init(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
|
||||
{
|
||||
@ -26,9 +28,10 @@ const struct elem_funcs
|
||||
void (*func_update)(struct element *e);
|
||||
} elem_funcs[] =
|
||||
{
|
||||
{ 't', infobar_elem_tag_init, infobar_elem_tag_update },
|
||||
{ 's', infobar_elem_status_init, infobar_elem_status_update },
|
||||
{ 'y', infobar_elem_systray_init, infobar_elem_systray_update },
|
||||
{ 't', infobar_elem_tag_init, infobar_elem_tag_update },
|
||||
{ 's', infobar_elem_status_init, infobar_elem_status_update },
|
||||
{ 'y', infobar_elem_systray_init, infobar_elem_systray_update },
|
||||
{ 'l', infobar_elem_launcher_init, infobar_elem_launcher_update },
|
||||
{ '\0', NULL, NULL }
|
||||
};
|
||||
|
||||
@ -218,12 +221,60 @@ infobar_elem_systray_update(struct element *e)
|
||||
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) \
|
||||
do { \
|
||||
e = xcalloc(1, sizeof(struct element)); \
|
||||
SLIST_INIT(&e->bars); \
|
||||
e->infobar = i; \
|
||||
e->type = j; \
|
||||
e->data = NULL; \
|
||||
e->align = a; \
|
||||
e->func_init = elem_funcs[j].func_init; \
|
||||
e->func_update = elem_funcs[j].func_update; \
|
||||
@ -336,6 +387,8 @@ infobar_elem_reinit(struct infobar *i)
|
||||
{
|
||||
struct element *e;
|
||||
|
||||
barwin_refresh_color(i->bar);
|
||||
|
||||
TAILQ_FOREACH(e, &i->elements, next)
|
||||
{
|
||||
/* Status element found, scan from the tail now */
|
||||
@ -361,6 +414,8 @@ infobar_elem_reinit(struct infobar *i)
|
||||
e->func_init(e);
|
||||
e->func_update(e);
|
||||
}
|
||||
|
||||
barwin_refresh(i->bar);
|
||||
}
|
||||
|
||||
struct infobar*
|
||||
@ -412,7 +467,6 @@ infobar_remove(struct infobar *i)
|
||||
|
||||
free(i->elemorder);
|
||||
free(i->name);
|
||||
free(i->status);
|
||||
|
||||
if(i == W->systray.infobar)
|
||||
systray_freeicons();
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "util.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);
|
||||
void infobar_elem_update(struct infobar *i, int type);
|
||||
|
||||
196
src/launcher.c
Normal file
196
src/launcher.c
Normal 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
13
src/launcher.h
Normal 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 */
|
||||
12
src/wmfs.c
12
src/wmfs.c
@ -406,6 +406,7 @@ wmfs_quit(void)
|
||||
struct theme *t;
|
||||
struct client *c;
|
||||
struct mousebind *m;
|
||||
struct launcher *l;
|
||||
|
||||
ewmh_update_wmfs_props();
|
||||
|
||||
@ -419,7 +420,6 @@ wmfs_quit(void)
|
||||
client_remove(c);
|
||||
}
|
||||
|
||||
|
||||
/* Will free:
|
||||
*
|
||||
* Screens -> tags
|
||||
@ -460,6 +460,16 @@ wmfs_quit(void)
|
||||
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))
|
||||
{
|
||||
m = SLIST_FIRST(&W->h.mousebind);
|
||||
|
||||
16
src/wmfs.h
16
src/wmfs.h
@ -123,6 +123,7 @@ struct element
|
||||
struct infobar *infobar;
|
||||
struct status_ctx *statusctx;
|
||||
int type;
|
||||
char *data;
|
||||
enum position align;
|
||||
void (*func_init)(struct element *e);
|
||||
void (*func_update)(struct element *e);
|
||||
@ -140,7 +141,6 @@ struct infobar
|
||||
enum barpos pos;
|
||||
char *elemorder;
|
||||
char *name;
|
||||
char *status;
|
||||
TAILQ_HEAD(esub, element) elements;
|
||||
SLIST_ENTRY(infobar) next;
|
||||
};
|
||||
@ -275,6 +275,18 @@ struct rule
|
||||
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 geo geo;
|
||||
@ -298,6 +310,7 @@ struct wmfs
|
||||
#define WMFS_RELOAD 0x04
|
||||
#define WMFS_SYSTRAY 0x08
|
||||
#define WMFS_LOG 0x10
|
||||
#define WMFS_LAUNCHER 0x20
|
||||
Flags flags;
|
||||
GC gc, rgc;
|
||||
Atom *net_atom;
|
||||
@ -325,6 +338,7 @@ struct wmfs
|
||||
SLIST_HEAD(, theme) theme;
|
||||
SLIST_HEAD(, rule) rule;
|
||||
SLIST_HEAD(, mousebind) mousebind;
|
||||
SLIST_HEAD(, launcher) launcher;
|
||||
} h;
|
||||
|
||||
/*
|
||||
|
||||
24
wmfsrc
24
wmfsrc
@ -65,11 +65,12 @@
|
||||
# t Tags
|
||||
# s Statustext (will take available space)
|
||||
# y Systray (can be set only ONE time among all element)
|
||||
# l Launcher (will be expended at launcher use)
|
||||
|
||||
[bar]
|
||||
position = 0
|
||||
screen = 0
|
||||
elements = "tsy" # element order in bar
|
||||
elements = "tlsy" # element order in bar
|
||||
theme = "default"
|
||||
[/bar]
|
||||
|
||||
@ -135,6 +136,22 @@
|
||||
|
||||
[/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]
|
||||
|
||||
[key] mod = {"Super"} key = "Return" func = "spawn" cmd = "urxvt || xterm" [/key]
|
||||
@ -215,6 +232,9 @@
|
||||
|
||||
# Layout set historic travelling function (TESTING)
|
||||
[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]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user