35 Commits

Author SHA1 Message Date
oga
590eb4f37b use fnmatch to glob the entries in the exec menu.
allows shell globbing constructs such as *ctl, etc in the exec menu (m-?
by default).

Adapted from a diff from Thomas Pfaff, okan@ got almost the same diff as
me when reworking it, and oked this one.
2009-06-26 12:45:12 +00:00
okan
f44862be9c static local functions and data; almost identical diff from Thomas Pfaff
ok oga@
2009-06-26 12:21:58 +00:00
okan
b13d592c57 tidy up startup/init routines
ok oga@
2009-06-23 21:52:38 +00:00
okan
bcc0f73bb6 compact a bit by condensing a few if-else's; from Thomas Pfaff
"go on then" oga@
2009-06-20 00:55:41 +00:00
okan
58d12134b1 unroll XCALLOC/XMALLOC macros; since we use xcalloc/xmalloc all over the
place anyway, this makes things a bit more consistent; from Thomas Pfaff

ok oga@
2009-06-20 00:22:39 +00:00
okan
18c7d89c98 spacing 2009-06-20 00:19:56 +00:00
sobrado
ee59e4a5a1 `exec'' and `ssh'' are lowercase.
ok martynas@
2009-06-19 10:43:49 +00:00
sobrado
055b244bb4 items on the first list should have full stops too.
ok martynas@
2009-06-18 20:44:40 +00:00
sobrado
71ad069846 the on-line manual should use the same notation for key bindings
as the configuration file, this way writing configuration files is easier;
add a few missing interactive command (.Ic) macros to key bindings;
slightly improve spacing in the lists; other tweaks.

ok martynas@
2009-06-18 20:24:54 +00:00
okan
11b4b7fec6 remove unnecessary casts; from Thomas Pfaff
ok oga@
2009-06-17 13:08:37 +00:00
okan
61f841ea58 re-factor parts of mouse move/resize bit to shrink and make more
readable; no behavior change

ok oga@
2009-06-17 12:45:01 +00:00
okan
d7589ca80b move like defines to a central, logical location; no binary change.
aok oga@
2009-06-17 12:30:17 +00:00
okan
3eec3b3802 'no' is the answer to the comment question: cc->name can't be NULL at
this point due to client_setname()'s work; remove this check.

ok oga@
2009-05-30 00:30:27 +00:00
okan
d1b84c5415 re-order a bit for readability.
"if it makes you happy" oga@
2009-05-30 00:30:17 +00:00
okan
6e9fa7548b revert the 1.4 change - causes a double free noticed by grange@ a while
ago while using kazehakase (or clients that don't set a name).

ok oga@
2009-05-30 00:29:08 +00:00
sthen
8bbc376fd9 In movetogroup, check the window's current group and skip client_hide()
if it's the same as the active group. Was in my original movetogroup diff,
but it got simplified a little too far.  ok oga@
2009-05-19 12:49:37 +00:00
okan
2c29a1de65 nuke the leading underscore notation for local static functions - there
are far better ways to know.

"go for it" oga@
2009-05-18 00:23:35 +00:00
oga
d2cfeb40b4 oops, we appear to have grown an extra prototype for group_only(), get
the secateurs out.
2009-05-18 00:17:46 +00:00
oga
382662d003 Rip out the event layer and just use a static array of callbacks like
every other window manager since twm.

The event layer is very nice, very shiny, very flexible, and very much
underutilised. We don't need any of those shiny features so it's
probably better to earn ourselves 1k smaller text size instead.

ok todd@, okan@
2009-05-18 00:14:19 +00:00
okan
9be7726606 redraw all borders at once on reload
"sure" oga@
2009-05-17 23:54:17 +00:00
okan
4d5dc5d9ea a long time coming - re-work the way we deal with colors: since we're
using Xft(3), use it to select the font color as well instead of trying
to build one; properly allocate and free colors at-will, e.g. we now
have configurable colors.

feedback and ok's todd@ and oga@
2009-05-17 23:40:57 +00:00
okan
5d51c8e0e5 minor bit of knf, just to be consistent; oga@ doesn't mind that much 2009-05-17 23:37:52 +00:00
okan
4c10afe2cc unbreak 2009-05-17 22:48:47 +00:00
sthen
eb7803269e add a "movetogroup" function, which hides the current window from
display and moves it to another group. useful with the recently added
"grouponly" function, giving the ability to use groups as simple
virtual desktops (similar to e.g. xmonad, dwm and scrotwm).

this doesn't have default keyboard bindings; cwmrc(5) now shows how
you could use these functions (use M-1...9 for grouponly1...9 and
MS-1...9 for movetogroup1...9 to emulate the default dwm bindings).

ok oga@
2009-05-17 17:04:59 +00:00
sthen
6df7cba24e redraw the border when unhiding a client window. fixes the situation where
you change to a different group and the mouse isn't over a window; previously
the border of the previously active window was highlighted but it didn't
actually have focus.

reads ok to oga@.
2009-05-17 16:51:43 +00:00
oga
29cdc29c6e add missing prototype. 2009-05-14 16:29:58 +00:00
oga
3de90d44fc Add a new command (currently no default keybindings for it), grouponly[1-9].
This works like the group select binding, but hides all other groups.

So, the people who've been complaining that they don't get "virtual
desktops" in cwm may want to try this out in cwmrc (from memory, untested):

---

#cwmrc

# add new windows to the current group
set sticky

# automatically sticky windows. xclock for now.
# to make more windows sticky use group_toggle to unset their group
autogroup 0 xclock

# make the group selection keys hide other groups, emulate virtual desktops
bind CM-1 grouponly1
bind CM-2 grouponly2
bind CM-3 grouponly3
bind CM-4 grouponly4
bind CM-5 grouponly5
bind CM-6 grouponly6
bind CM-7 grouponly7
bind CM-8 grouponly8
bind CM-9 grouponly9

---

mostly by sthen, tweaks from me.

ok todd@, "if it works i'm ok with it" okan@, ok sthen@
2009-05-14 16:24:04 +00:00
okan
fbb1edf2b3 right and middle mouse buttons swapped; from rgouveia@cosmico.net 2009-05-04 22:01:35 +00:00
okan
64f0038db7 no need to use the global here.
ok todd@ oga@
2009-05-04 19:13:33 +00:00
okan
4f34392258 properly document menu_unhide; tweak a patch from rgouveia@cosmico.net - thanks.
ok oga@
2009-05-04 18:05:21 +00:00
okan
655c33c489 fix the other 50% of xrandr cases; reported by sthen@
"commit that" oga@, ok sthen@
2009-05-01 17:50:20 +00:00
okan
cc68490fe1 don't sync more than 60 times per sec on resize and move; idea from scrotwm.
ok oga@ sometime ago
2009-04-15 14:10:07 +00:00
okan
ea96e92ac8 properly teardown X connection upon quit; static a few while here,
requested by oga@

ok oga@ sometime ago
2009-04-15 14:01:45 +00:00
okan
8a490fc270 we include sys/param.h, so remove sys/types.h; sort while here.
ok oga@
2009-04-12 23:51:10 +00:00
martynas
8346de997f - avoid shadowed Mask declaration in menu_filter
- make _xev_reincorporate static
evmask naming oga@, input okan@.  ok okan@, oga@
2009-03-28 16:38:54 +00:00
18 changed files with 604 additions and 597 deletions

View File

@@ -38,8 +38,12 @@ int HasXinerama, HasRandr, Randr_ev;
int Starting;
struct conf Conf;
static void _sigchld_cb(int);
static void sigchld_cb(int);
static void dpy_init(const char *);
static int x_errorhandler(Display *, XErrorEvent *);
static void x_setup(void);
static void x_setupscreen(struct screen_ctx *, u_int);
static void x_teardown(void);
int
main(int argc, char **argv)
@@ -63,44 +67,30 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (signal(SIGCHLD, _sigchld_cb) == SIG_ERR)
if (signal(SIGCHLD, sigchld_cb) == SIG_ERR)
err(1, "signal");
group_init();
Starting = 1;
dpy_init(display_name);
screen_init();
group_init();
client_init();
bzero(&Conf, sizeof(Conf));
conf_setup(&Conf, conf_file);
client_setup();
xu_getatoms();
x_setup();
Starting = 0;
xev_init();
XEV_QUICK(NULL, NULL, MapRequest, xev_handle_maprequest, NULL);
XEV_QUICK(NULL, NULL, UnmapNotify, xev_handle_unmapnotify, NULL);
XEV_QUICK(NULL, NULL, ConfigureRequest,
xev_handle_configurerequest, NULL);
XEV_QUICK(NULL, NULL, PropertyNotify, xev_handle_propertynotify, NULL);
XEV_QUICK(NULL, NULL, EnterNotify, xev_handle_enternotify, NULL);
XEV_QUICK(NULL, NULL, LeaveNotify, xev_handle_leavenotify, NULL);
XEV_QUICK(NULL, NULL, ButtonPress, xev_handle_buttonpress, NULL);
XEV_QUICK(NULL, NULL, ButtonRelease, xev_handle_buttonrelease, NULL);
XEV_QUICK(NULL, NULL, KeyPress, xev_handle_keypress, NULL);
XEV_QUICK(NULL, NULL, KeyRelease, xev_handle_keyrelease, NULL);
XEV_QUICK(NULL, NULL, Expose, xev_handle_expose, NULL);
XEV_QUICK(NULL, NULL, DestroyNotify, xev_handle_destroynotify, NULL);
XEV_QUICK(NULL, NULL, ClientMessage, xev_handle_clientmessage, NULL);
XEV_QUICK(NULL, NULL, MappingNotify, xev_handle_mapping, NULL);
xev_loop();
x_teardown();
return (0);
}
void
static void
dpy_init(const char *dpyname)
{
int i;
@@ -112,11 +102,9 @@ dpy_init(const char *dpyname)
XSetErrorHandler(x_errorhandler);
HasRandr = XRRQueryExtension(X_Dpy, &Randr_ev, &i);
TAILQ_INIT(&Screenq);
}
void
static void
x_setup(void)
{
struct screen_ctx *sc;
@@ -124,7 +112,7 @@ x_setup(void)
int i;
for (i = 0; i < ScreenCount(X_Dpy); i++) {
XCALLOC(sc, struct screen_ctx);
sc = xcalloc(1, sizeof(*sc));
x_setupscreen(sc, i);
TAILQ_INSERT_TAIL(&Screenq, sc, entry);
}
@@ -143,11 +131,20 @@ x_setup(void)
Cursor_question = XCreateFontCursor(X_Dpy, XC_question_arrow);
}
void
static void
x_teardown(void)
{
struct screen_ctx *sc;
TAILQ_FOREACH(sc, &Screenq, entry)
XFreeGC(X_Dpy, sc->gc);
XCloseDisplay(X_Dpy);
}
static void
x_setupscreen(struct screen_ctx *sc, u_int which)
{
XColor tmp;
XGCValues gv;
Window *wins, w0, w1;
XWindowAttributes winattr;
XSetWindowAttributes rootattr;
@@ -157,41 +154,11 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
Curscreen = sc;
sc->which = which;
sc->rootwin = RootWindow(X_Dpy, which);
sc->rootwin = RootWindow(X_Dpy, sc->which);
sc->xmax = DisplayWidth(X_Dpy, sc->which);
sc->ymax = DisplayHeight(X_Dpy, sc->which);
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
"black", &sc->fgcolor, &tmp);
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
"#00cc00", &sc->bgcolor, &tmp);
XAllocNamedColor(X_Dpy,DefaultColormap(X_Dpy, which),
"blue", &sc->fccolor, &tmp);
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
"red", &sc->redcolor, &tmp);
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
"#666666", &sc->graycolor, &tmp);
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
"white", &sc->whitecolor, &tmp);
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
"black", &sc->blackcolor, &tmp);
sc->blackpixl = BlackPixel(X_Dpy, sc->which);
sc->whitepixl = WhitePixel(X_Dpy, sc->which);
sc->bluepixl = sc->fccolor.pixel;
sc->redpixl = sc->redcolor.pixel;
sc->graypixl = sc->graycolor.pixel;
gv.foreground = sc->blackpixl^sc->whitepixl;
gv.background = sc->whitepixl;
gv.function = GXxor;
gv.line_width = 1;
gv.subwindow_mode = IncludeInferiors;
sc->gc = XCreateGC(X_Dpy, sc->rootwin,
GCForeground|GCBackground|GCFunction|
GCLineWidth|GCSubwindowMode, &gv);
conf_color(&Conf);
font_init(sc);
conf_font(&Conf);
@@ -234,11 +201,9 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
screen_init_xinerama(sc);
XSync(X_Dpy, False);
return;
}
int
static int
x_errorhandler(Display *dpy, XErrorEvent *e)
{
#ifdef DEBUG
@@ -264,7 +229,7 @@ x_errorhandler(Display *dpy, XErrorEvent *e)
}
static void
_sigchld_cb(int which)
sigchld_cb(int which)
{
pid_t pid;
int save_errno = errno;

101
calmwm.h
View File

@@ -33,6 +33,27 @@
#define ChildMask (SubstructureRedirectMask|SubstructureNotifyMask)
#define ButtonMask (ButtonPressMask|ButtonReleaseMask)
#define MouseMask (ButtonMask|PointerMotionMask)
#define KeyMask (KeyPressMask|ExposureMask)
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask| \
PointerMotionMask)
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask|\
PointerMotionMask)
#define SearchMask (KeyPressMask|ExposureMask)
enum cwmcolor {
CWM_COLOR_BORDOR_ACTIVE,
CWM_COLOR_BORDER_INACTIVE,
CWM_COLOR_BORDER_GROUP,
CWM_COLOR_BORDER_UNGROUP,
CWM_COLOR_FG_MENU,
CWM_COLOR_BG_MENU,
CWM_COLOR_MAX
};
struct color {
unsigned long pixel;
char *name;
};
struct client_ctx;
@@ -44,10 +65,8 @@ struct screen_ctx {
u_int which;
Window rootwin;
Window menuwin;
Colormap colormap;
XColor bgcolor, fgcolor, fccolor, redcolor, graycolor,
whitecolor, blackcolor;
unsigned long blackpixl, whitepixl, redpixl, bluepixl, graypixl;
struct color color[CWM_COLOR_MAX];
GC gc;
int altpersist;
@@ -78,8 +97,8 @@ TAILQ_HEAD(screen_ctx_q, screen_ctx);
#define CLIENT_DOVMAXIMIZE 0x10
#define CLIENT_VMAXIMIZED 0x20
#define CLIENT_HIGHLIGHT_BLUE 1
#define CLIENT_HIGHLIGHT_RED 2
#define CLIENT_HIGHLIGHT_GROUP 1
#define CLIENT_HIGHLIGHT_UNGROUP 2
struct winname {
TAILQ_ENTRY(winname) entry;
@@ -159,18 +178,6 @@ struct autogroupwin {
TAILQ_HEAD(autogroupwin_q, autogroupwin);
/* NULL/0 values indicate match any. */
struct xevent {
TAILQ_ENTRY(xevent) entry;
Window *xev_win;
Window *xev_root;
int xev_type;
void (*xev_cb)(struct xevent *, XEvent *);
void *xev_arg;
};
TAILQ_HEAD(xevent_q, xevent);
#define CWM_MOVE 0x01
#define CWM_RESIZE 0x02
#define CWM_PTRMOVE 0x04
@@ -259,6 +266,14 @@ struct conf {
#define CONF_MAMOUNT 1
int mamount;
#define CONF_COLOR_ACTIVEBORDER "#CCCCCC"
#define CONF_COLOR_INACTIVEBORDER "#666666"
#define CONF_COLOR_GROUPBORDER "blue"
#define CONF_COLOR_UNGROUPBORDER "red"
#define CONF_COLOR_MENUFG "black"
#define CONF_COLOR_MENUBG "white"
struct color color[CWM_COLOR_MAX];
char termpath[MAXPATHLEN];
char lockpath[MAXPATHLEN];
@@ -309,13 +324,10 @@ struct mwm_hints {
int input_keycodetrans(KeyCode, u_int, enum ctltype *,
char *);
int x_errorhandler(Display *, XErrorEvent *);
void x_setup(void);
void x_setupscreen(struct screen_ctx *, u_int);
__dead void usage(void);
struct client_ctx *client_find(Window);
void client_setup(void);
void client_init(void);
struct client_ctx *client_new(Window, struct screen_ctx *, int);
int client_delete(struct client_ctx *);
void client_setactive(struct client_ctx *, int);
@@ -333,50 +345,20 @@ void client_warp(struct client_ctx *);
void client_ptrwarp(struct client_ctx *);
void client_ptrsave(struct client_ctx *);
void client_draw_border(struct client_ctx *);
void client_update(struct client_ctx *);
void client_placecalc(struct client_ctx *);
void client_maximize(struct client_ctx *);
void client_vertmaximize(struct client_ctx *);
void client_map(struct client_ctx *);
void client_mtf(struct client_ctx *);
struct client_ctx *client_cycle(int);
struct client_ctx *client_mrunext(struct client_ctx *);
struct client_ctx *client_mruprev(struct client_ctx *);
void client_gethints(struct client_ctx *);
void client_freehints(struct client_ctx *);
struct menu *menu_filter(struct menu_q *, char *, char *, int,
void (*)(struct menu_q *, struct menu_q *, char *),
void (*)(struct menu *, int));
void menu_init(struct screen_ctx *);
void xev_handle_maprequest(struct xevent *, XEvent *);
void xev_handle_unmapnotify(struct xevent *, XEvent *);
void xev_handle_destroynotify(struct xevent *, XEvent *);
void xev_handle_configurerequest(struct xevent *, XEvent *);
void xev_handle_propertynotify(struct xevent *, XEvent *);
void xev_handle_enternotify(struct xevent *, XEvent *);
void xev_handle_leavenotify(struct xevent *, XEvent *);
void xev_handle_buttonpress(struct xevent *, XEvent *);
void xev_handle_buttonrelease(struct xevent *, XEvent *);
void xev_handle_keypress(struct xevent *, XEvent *);
void xev_handle_keyrelease(struct xevent *, XEvent *);
void xev_handle_expose(struct xevent *, XEvent *);
void xev_handle_clientmessage(struct xevent *, XEvent *);
void xev_handle_randr(struct xevent *, XEvent *);
void xev_handle_mapping(struct xevent *, XEvent *);
#define XEV_QUICK(a, b, c, d, e) do { \
xev_register(xev_new(a, b, c, d, e)); \
} while (0)
/* XXX should be xu_ */
void xev_reconfig(struct client_ctx *);
void xev_init(void);
struct xevent *xev_new(Window *, Window *, int,
void (*)(struct xevent *, XEvent *), void *);
void xev_register(struct xevent *);
void xev_loop(void);
void xu_getatoms(void);
@@ -395,6 +377,8 @@ int xu_getprop(struct client_ctx *, Atom, Atom, long,
char *xu_getstrprop(struct client_ctx *, Atom atm);
void xu_setstate(struct client_ctx *, int);
int xu_getstate(struct client_ctx *, int *);
unsigned long xu_getcolor(struct screen_ctx *, char *);
void xu_freecolor(struct screen_ctx *, unsigned long);
int u_spawn(char *);
void u_exec(char *);
@@ -404,9 +388,7 @@ void *xmalloc(size_t);
void *xcalloc(size_t, size_t);
char *xstrdup(const char *);
#define XMALLOC(p, t) ((p) = (t *)xmalloc(sizeof * (p)))
#define XCALLOC(p, t) ((p) = (t *)xcalloc(1, sizeof * (p)))
void screen_init(void);
struct screen_ctx *screen_fromroot(Window);
struct screen_ctx *screen_current(void);
void screen_updatestackingorder(void);
@@ -418,12 +400,11 @@ void conf_client(struct client_ctx *);
void conf_grab(struct conf *, struct keybinding *);
void conf_ungrab(struct conf *, struct keybinding *);
void conf_bindname(struct conf *, char *, char *);
void conf_unbind(struct conf *, struct keybinding *);
void conf_mousebind(struct conf *, char *, char *);
void conf_mouseunbind(struct conf *, struct mousebinding *);
void conf_grab_mouse(struct client_ctx *);
void conf_reload(struct conf *);
void conf_font(struct conf *);
void conf_color(struct conf *);
void conf_init(struct conf *);
void conf_clear(struct conf *);
void conf_cmd_add(struct conf *, char *, char *, int);
@@ -440,12 +421,16 @@ void kbfunc_cmdexec(struct client_ctx *, union arg *);
void kbfunc_client_label(struct client_ctx *, union arg *);
void kbfunc_client_delete(struct client_ctx *, union arg *);
void kbfunc_client_group(struct client_ctx *, union arg *);
void kbfunc_client_grouponly(struct client_ctx *,
union arg *);
void kbfunc_client_cyclegroup(struct client_ctx *,
union arg *);
void kbfunc_client_nogroup(struct client_ctx *,
union arg *);
void kbfunc_client_grouptoggle(struct client_ctx *,
union arg *);
void kbfunc_client_movetogroup(struct client_ctx *,
union arg *);
void kbfunc_client_maximize(struct client_ctx *,
union arg *);
void kbfunc_client_vmaximize(struct client_ctx *,
@@ -479,6 +464,7 @@ void search_match_exec(struct menu_q *, struct menu_q *,
void group_init(void);
void group_hidetoggle(int);
void group_only(int);
void group_cycle(int);
void group_sticky(struct client_ctx *);
void group_client_delete(struct client_ctx *);
@@ -487,6 +473,7 @@ void group_alltoggle(void);
void group_sticky_toggle_enter(struct client_ctx *);
void group_sticky_toggle_exit(struct client_ctx *);
void group_autogroup(struct client_ctx *);
void group_movetogroup(struct client_ctx *, int);
void font_init(struct screen_ctx *);
int font_width(const char *, int);

View File

@@ -21,13 +21,19 @@
#include "headers.h"
#include "calmwm.h"
static int _client_inbound(struct client_ctx *, int, int);
static struct client_ctx *client_mrunext(struct client_ctx *);
static struct client_ctx *client_mruprev(struct client_ctx *);
static void client_placecalc(struct client_ctx *);
static void client_update(struct client_ctx *);
static void client_gethints(struct client_ctx *);
static void client_freehints(struct client_ctx *);
static int client_inbound(struct client_ctx *, int, int);
static char emptystring[] = "";
struct client_ctx *_curcc = NULL;
void
client_setup(void)
client_init(void)
{
TAILQ_INIT(&Clientq);
}
@@ -56,7 +62,7 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
if (win == None)
return (NULL);
XCALLOC(cc, struct client_ctx);
cc = xcalloc(1, sizeof(*cc));
XGrabServer(X_Dpy);
@@ -64,22 +70,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
cc->sc = sc;
cc->win = win;
cc->size = XAllocSizeHints();
XGetWMNormalHints(X_Dpy, cc->win, cc->size, &tmp);
if (cc->size->width_inc == 0)
cc->size->width_inc = 1;
if (cc->size->height_inc == 0)
cc->size->height_inc = 1;
TAILQ_INIT(&cc->nameq);
client_setname(cc);
/*
* conf_client() needs at least cc->win and cc->name
*/
conf_client(cc);
XGetWindowAttributes(X_Dpy, cc->win, &wattr);
if (cc->size->flags & PBaseSize) {
cc->geom.min_dx = cc->size->base_width;
cc->geom.min_dy = cc->size->base_height;
@@ -88,10 +80,16 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
cc->geom.min_dy = cc->size->min_height;
}
TAILQ_INIT(&cc->nameq);
client_setname(cc);
conf_client(cc);
/* Saved pointer position */
cc->ptr.x = -1;
cc->ptr.y = -1;
XGetWindowAttributes(X_Dpy, cc->win, &wattr);
cc->geom.x = wattr.x;
cc->geom.y = wattr.y;
cc->geom.width = wattr.width;
@@ -121,11 +119,7 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
/* Notify client of its configuration. */
xev_reconfig(cc);
if (state == IconicState)
client_hide(cc);
else
client_unhide(cc);
(state == IconicState) ? client_hide(cc) : client_unhide(cc);
xu_setstate(cc, cc->state);
XSync(X_Dpy, False);
@@ -174,7 +168,6 @@ client_delete(struct client_ctx *cc)
}
client_freehints(cc);
xfree(cc);
return (0);
@@ -354,11 +347,7 @@ client_ptrwarp(struct client_ctx *cc)
y = cc->geom.height / 2;
}
if (cc->state == IconicState)
client_unhide(cc);
else
client_raise(cc);
(cc->state == IconicState) ? client_unhide(cc) : client_raise(cc);
xu_ptr_setpos(cc->win, x, y);
}
@@ -368,7 +357,7 @@ client_ptrsave(struct client_ctx *cc)
int x, y;
xu_ptr_getpos(cc->win, &x, &y);
if (_client_inbound(cc, x, y)) {
if (client_inbound(cc, x, y)) {
cc->ptr.x = x;
cc->ptr.y = y;
}
@@ -396,34 +385,35 @@ client_unhide(struct client_ctx *cc)
cc->highlight = 0;
cc->flags &= ~CLIENT_HIDDEN;
xu_setstate(cc, NormalState);
client_draw_border(cc);
}
void
client_draw_border(struct client_ctx *cc)
{
struct screen_ctx *sc = CCTOSC(cc);
u_long pixl;
unsigned long pixel;
if (cc->active)
switch (cc->highlight) {
case CLIENT_HIGHLIGHT_BLUE:
pixl = sc->bluepixl;
case CLIENT_HIGHLIGHT_GROUP:
pixel = sc->color[CWM_COLOR_BORDER_GROUP].pixel;
break;
case CLIENT_HIGHLIGHT_RED:
pixl = sc->redpixl;
case CLIENT_HIGHLIGHT_UNGROUP:
pixel = sc->color[CWM_COLOR_BORDER_UNGROUP].pixel;
break;
default:
pixl = sc->whitepixl;
pixel = sc->color[CWM_COLOR_BORDOR_ACTIVE].pixel;
break;
}
else
pixl = sc->graypixl;
pixel = sc->color[CWM_COLOR_BORDER_INACTIVE].pixel;
XSetWindowBorderWidth(X_Dpy, cc->win, cc->bwidth);
XSetWindowBorder(X_Dpy, cc->win, pixl);
XSetWindowBorder(X_Dpy, cc->win, pixel);
}
void
static void
client_update(struct client_ctx *cc)
{
Atom *p;
@@ -446,7 +436,6 @@ client_update(struct client_ctx *cc)
void
client_send_delete(struct client_ctx *cc)
{
if (cc->xproto & CLIENT_PROTO_DELETE)
xu_sendmsg(cc, WM_PROTOCOLS, WM_DELETE_WINDOW);
else
@@ -471,7 +460,7 @@ client_setname(struct client_ctx *cc)
goto match;
}
XMALLOC(wn, struct winname);
wn = xmalloc(sizeof(*wn));
wn->name = newname;
TAILQ_INSERT_TAIL(&cc->nameq, wn, entry);
cc->nameqlen++;
@@ -539,7 +528,7 @@ client_cycle(int reverse)
return (newcc);
}
struct client_ctx *
static struct client_ctx *
client_mrunext(struct client_ctx *cc)
{
struct screen_ctx *sc = CCTOSC(cc);
@@ -549,7 +538,7 @@ client_mrunext(struct client_ctx *cc)
ccc : TAILQ_FIRST(&sc->mruq));
}
struct client_ctx *
static struct client_ctx *
client_mruprev(struct client_ctx *cc)
{
struct screen_ctx *sc = CCTOSC(cc);
@@ -559,7 +548,7 @@ client_mruprev(struct client_ctx *cc)
ccc : TAILQ_LAST(&sc->mruq, cycle_entry_q));
}
void
static void
client_placecalc(struct client_ctx *cc)
{
struct screen_ctx *sc = CCTOSC(cc);
@@ -646,7 +635,7 @@ client_mtf(struct client_ctx *cc)
TAILQ_INSERT_HEAD(&sc->mruq, cc, mru_entry);
}
void
static void
client_gethints(struct client_ctx *cc)
{
XClassHint xch;
@@ -692,7 +681,7 @@ client_gethints(struct client_ctx *cc)
}
}
void
static void
client_freehints(struct client_ctx *cc)
{
if (cc->app_name != NULL)
@@ -703,7 +692,7 @@ client_freehints(struct client_ctx *cc)
}
static int
_client_inbound(struct client_ctx *cc, int x, int y)
client_inbound(struct client_ctx *cc, int x, int y)
{
return (x < cc->geom.width && x >= 0 &&
y < cc->geom.height && y >= 0);

99
conf.c
View File

@@ -28,6 +28,9 @@
((tsp)->tv_sec cmp (usp)->tv_sec))
#endif
static void conf_mouseunbind(struct conf *, struct mousebinding *);
static void conf_unbind(struct conf *, struct keybinding *);
extern struct screen_ctx *Curscreen;
/* Add an command menu entry to the end of the menu */
@@ -41,8 +44,7 @@ conf_cmd_add(struct conf *c, char *image, char *label, int flags)
else if (strcmp(label, "lock") == 0)
strlcpy(c->lockpath, image, sizeof(c->lockpath));
else {
struct cmd *cmd;
XMALLOC(cmd, struct cmd);
struct cmd *cmd = xmalloc(sizeof(*cmd));
cmd->flags = flags;
strlcpy(cmd->image, image, sizeof(cmd->image));
strlcpy(cmd->label, label, sizeof(cmd->label));
@@ -57,18 +59,37 @@ conf_font(struct conf *c)
sc = screen_current();
c->DefaultFont = font_make(sc, Conf.DefaultFontName);
c->DefaultFont = font_make(sc, c->DefaultFontName);
c->FontHeight = font_ascent() + font_descent() + 1;
}
void
conf_color(struct conf *c)
{
struct screen_ctx *sc;
int i;
sc = screen_current();
for (i = 0; i < CWM_COLOR_MAX; i++) {
xu_freecolor(sc, sc->color[i].pixel);
sc->color[i].pixel = xu_getcolor(sc, c->color[i].name);
}
}
void
conf_reload(struct conf *c)
{
struct client_ctx *cc;
if (parse_config(c->conf_path, c) == -1) {
warnx("config file %s has errors, not reloading", c->conf_path);
return;
}
conf_color(c);
TAILQ_FOREACH(cc, &Clientq, entry)
client_draw_border(cc);
conf_font(c);
}
@@ -157,6 +178,19 @@ conf_init(struct conf *c)
strlcpy(c->termpath, "xterm", sizeof(c->termpath));
strlcpy(c->lockpath, "xlock", sizeof(c->lockpath));
c->color[CWM_COLOR_BORDOR_ACTIVE].name =
xstrdup(CONF_COLOR_ACTIVEBORDER);
c->color[CWM_COLOR_BORDER_INACTIVE].name =
xstrdup(CONF_COLOR_INACTIVEBORDER);
c->color[CWM_COLOR_BORDER_GROUP].name =
xstrdup(CONF_COLOR_GROUPBORDER);
c->color[CWM_COLOR_BORDER_UNGROUP].name =
xstrdup(CONF_COLOR_UNGROUPBORDER);
c->color[CWM_COLOR_FG_MENU].name =
xstrdup(CONF_COLOR_MENUFG);
c->color[CWM_COLOR_BG_MENU].name =
xstrdup(CONF_COLOR_MENUBG);
c->DefaultFontName = xstrdup(DEFAULTFONTNAME);
}
@@ -168,6 +202,7 @@ conf_clear(struct conf *c)
struct winmatch *wm;
struct cmd *cmd;
struct mousebinding *mb;
int i;
while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) {
TAILQ_REMOVE(&c->cmdq, cmd, entry);
@@ -198,6 +233,9 @@ conf_clear(struct conf *c)
xfree(mb);
}
for (i = 0; i < CWM_COLOR_MAX; i++)
xfree(c->color[i].name);
xfree(c->DefaultFontName);
}
@@ -232,23 +270,18 @@ conf_client(struct client_ctx *cc)
char *wname = cc->name;
int ignore = 0;
/* Can wname be NULL? */
if (wname != NULL) {
TAILQ_FOREACH(wm, &Conf.ignoreq, entry) {
if (strncasecmp(wm->title, wname, strlen(wm->title))
== 0) {
ignore = 1;
break;
}
TAILQ_FOREACH(wm, &Conf.ignoreq, entry) {
if (strncasecmp(wm->title, wname, strlen(wm->title)) == 0) {
ignore = 1;
break;
}
} else
ignore = 1;
}
cc->bwidth = ignore ? 0 : Conf.bwidth;
cc->flags |= ignore ? CLIENT_IGNORE : 0;
}
struct {
static struct {
char *tag;
void (*handler)(struct client_ctx *, union arg *);
int flags;
@@ -272,6 +305,33 @@ struct {
{ "group7", kbfunc_client_group, 0, {.i = 7} },
{ "group8", kbfunc_client_group, 0, {.i = 8} },
{ "group9", kbfunc_client_group, 0, {.i = 9} },
{ "grouponly1", kbfunc_client_grouponly, 0, {.i = 1} },
{ "grouponly2", kbfunc_client_grouponly, 0, {.i = 2} },
{ "grouponly3", kbfunc_client_grouponly, 0, {.i = 3} },
{ "grouponly4", kbfunc_client_grouponly, 0, {.i = 4} },
{ "grouponly5", kbfunc_client_grouponly, 0, {.i = 5} },
{ "grouponly6", kbfunc_client_grouponly, 0, {.i = 6} },
{ "grouponly7", kbfunc_client_grouponly, 0, {.i = 7} },
{ "grouponly8", kbfunc_client_grouponly, 0, {.i = 8} },
{ "grouponly9", kbfunc_client_grouponly, 0, {.i = 9} },
{ "movetogroup1", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 1} },
{ "movetogroup2", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 2} },
{ "movetogroup3", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 3} },
{ "movetogroup4", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 4} },
{ "movetogroup5", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 5} },
{ "movetogroup6", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 6} },
{ "movetogroup7", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 7} },
{ "movetogroup8", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 8} },
{ "movetogroup9", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
{.i = 9} },
{ "nogroup", kbfunc_client_nogroup, 0, {0} },
{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLEGROUP} },
{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLEGROUP} },
@@ -349,7 +409,6 @@ conf_grab(struct conf *c, struct keybinding *kb)
TAILQ_FOREACH(sc, &Screenq, entry)
xu_key_grab(sc->rootwin, kb->modmask, kb->keysym);
}
/*
@@ -372,7 +431,7 @@ conf_bindname(struct conf *c, char *name, char *binding)
char *substring;
int iter;
XCALLOC(current_binding, struct keybinding);
current_binding = xcalloc(1, sizeof(*current_binding));
if (strchr(name, 'C') != NULL &&
strchr(name, 'C') < strchr(name, '-'))
@@ -437,7 +496,7 @@ conf_bindname(struct conf *c, char *name, char *binding)
return;
}
void
static void
conf_unbind(struct conf *c, struct keybinding *unbind)
{
struct keybinding *key = NULL, *keynxt;
@@ -459,7 +518,7 @@ conf_unbind(struct conf *c, struct keybinding *unbind)
}
}
struct {
static struct {
char *tag;
void (*handler)(struct client_ctx *, void *);
int context;
@@ -484,7 +543,7 @@ conf_mousebind(struct conf *c, char *name, char *binding)
const char *errstr;
int iter;
XCALLOC(current_binding, struct mousebinding);
current_binding = xcalloc(1, sizeof(*current_binding));
if (strchr(name, 'C') != NULL &&
strchr(name, 'C') < strchr(name, '-'))
@@ -527,7 +586,7 @@ conf_mousebind(struct conf *c, char *name, char *binding)
}
}
void
static void
conf_mouseunbind(struct conf *c, struct mousebinding *unbind)
{
struct mousebinding *mb = NULL, *mbnxt;

104
cwm.1
View File

@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 22 2008 $
.Dd $Mdocdate: June 18 2009 $
.Dt CWM 1
.Os
.Sh NAME
@@ -36,29 +36,29 @@ The following notation is used throughout this page:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It Ic C
Control
Control.
.It Ic M
Meta
Meta.
.It Ic S
Shift
Shift.
.It Ic M1
Left mouse button
Left mouse button.
.It Ic M2
Middle mouse button
Middle mouse button.
.It Ic M3
Right mouse button
Right mouse button.
.El
.Pp
.Nm
is very simple in its use.
Most of the actions are initiated via keybindings.
The current keybindings are described below;
Most of the actions are initiated via key bindings.
The current key bindings are described below;
their functionality is described in more detail later.
.Pp
.Bl -tag -width "C-M-EscapeXXX" -offset indent -compact
.It Ic C-M-Return
.Bl -tag -width "CM-EscapeXXXXX" -offset indent -compact
.It Ic CM-Return
Spawn a new terminal.
.It Ic C-M-Delete
.It Ic CM-Delete
Lock the screen.
.It Ic M-Return
Hide current window.
@@ -70,50 +70,50 @@ Raise current window.
Search for windows.
.It Ic C-/
Search for applications.
.It Ic C-M-n
.It Ic CM-n
Label current window.
.It Ic M-Tab
Cycle through currently visible windows.
.It Ic M-S-Tab
.It Ic MS-Tab
Reverse cycle through currently visible windows.
.It Ic C-M-x
.It Ic CM-x
Delete current window.
.It Ic C-M-[n]
.It Ic CM-[n]
Select group n, where n is 1-9.
.It Ic C-M-0
.It Ic CM-0
Select all groups.
.It Ic C-M-g
.It Ic CM-g
Toggle group membership of current window.
.It Ic M-Right
Cycle through active groups.
.It Ic M-Left
Reverse cycle through active groups.
.It Ic C-M-f
.It Ic CM-f
Toggle full-screen size of current window.
.It Ic C-M-=
.It Ic CM-=
Toggle vertical maximization of current window.
.It Ic M-?
Spawn
.Dq Exec program
.Dq exec program
dialog.
.It Ic M-.
Spawn
.Dq Ssh to
.Dq ssh to
dialog.
This parses
.Pa $HOME/.ssh/known_hosts
to provide host auto-completion.
.Xr ssh 1
will be executed via the configured terminal emulator.
.It Ic C-M-w
.It Ic CM-w
Spawn
.Dq Exec WindowManager
.Dq exec WindowManager
dialog; allows you to switch from
.Nm
to another window manager without restarting the X server.
.It Ic C-M-S-r
.It Ic CMS-r
Reload configuration.
.It Ic C-M-S-q
.It Ic CMS-q
Quit
.Nm .
.El
@@ -121,15 +121,15 @@ Quit
The mouse bindings are also important, they are:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It M-M1
.It Ic M-M1
Move current window.
.It C-M-M1
.It Ic CM-M1
Toggle group membership of current window.
.It M-M2
.It Ic M-M2
Resize current window
.It M-M3
.It Ic M-M3
Lower current window.
.It CMS-M3
.It Ic CMS-M3
Hide current window.
.El
.Pp
@@ -145,22 +145,34 @@ Specify the display to use.
.El
.Sh POINTER MOVEMENT
The pointer can be moved with the use of the keyboard through bindings.
C-[UP|DOWN|LEFT|RIGHT] moves the pointer a small amount, while
C-shift-[UP|DOWN|LEFT|RIGHT] moves the pointer a larger amount.
.Ic C-[Up|Down|Left|Right]
moves the pointer a small amount, while
.Ic CS-[Up|Down|Left|Right]
moves the pointer a larger amount.
For example, to move the pointer to the left by a small amount,
press C-LEFT.
To move the pointer down by a larger amount, press C-shift-DOWN.
press
.Ic C-Left .
To move the pointer down by a larger amount, press
.Ic CS-Down .
.Sh WINDOW MOVEMENT AND RESIZING
.Nm
windows can be moved with the use of the keyboard through Vi-like bindings.
M-[hjkl] moves the current window a small amount, while M-shift-[hjkl] moves
the current window a larger amount.
For example, to move the current window to the left a small amount, press M-h.
To move the current window down by a larger amount, press M-shift-j.
windows can be moved with the use of the keyboard through
.Cm vi Ns -like
bindings.
.Ic M-[hjkl]
moves the current window a small amount, while
.Ic MS-[hjkl]
moves the current window a larger amount.
For example, to move the current window to the left a small amount, press
.Ic M-h .
To move the current window down by a larger amount, press
.Ic MS-j .
.Pp
Similarly, windows may be resized with the same keybindings with the addition
Similarly, windows may be resized with the same key bindings with the addition
of the Control key.
C-M-[hjkl] resizes the window a small amount and C-M-shift-[hjkl]
.Ic CM-[hjkl]
resizes the window a small amount and
.Ic CMS-[hjkl]
resizes by a larger increment.
.Sh SEARCH
.Nm
@@ -181,7 +193,7 @@ The window is the currently focused window.
The window is hidden.
.El
.Pp
The following keybindings may be used to navigate the result list:
The following key bindings may be used to navigate the result list:
.Pp
.Bl -tag -width "[Down] or C-s or M-j" -offset indent -compact
.It Ic [Down], C-s No or Ic M-j
@@ -217,13 +229,13 @@ and a red border will be shown on those just removed.
Menus are recalled by clicking the mouse on the root window:
.Pp
.Bl -tag -width 10n -offset -indent -compact
.It M1
.It Ic M1
Show list of currently hidden windows.
Clicking on an item will unhide that window.
.It M2
.It Ic M2
Show list of currently defined groups.
Clicking on an item will hide/unhide that group.
.It M3
.It Ic M3
Show list of applications as defined in
.Pa ~/.cwmrc .
Clicking on an item will spawn that application.

32
cwmrc.5
View File

@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: February 7 2009 $
.Dd $Mdocdate: May 17 2009 $
.Dt CWMRC 5
.Os
.Sh NAME
@@ -84,6 +84,18 @@ application.
Set the window border width to
.Ar pixels .
.Pp
.It Ic color activeborder Ar color
Set the color of the active border.
.Pp
.It Ic color groupborder Ar color
Set the color of the border while grouping a window.
.Pp
.It Ic color inactiveborder Ar color
Set the color of the inactive border.
.Pp
.It Ic color ungroupborder Ar color
Set the color of the border while ungrouping a window.
.Pp
.It Ic command Ar name Ar path
Every
.Ar name
@@ -158,9 +170,9 @@ should be followed by number:
.It 1
Left mouse button.
.It 2
Right mouse button.
.It 3
Middle mouse button.
.It 3
Right mouse button.
.El
.Pp
The
@@ -208,6 +220,12 @@ ignore xclock
bind CM-r label
bind CS-Return "xterm -e top"
bind 4-o unmap
bind M-1 grouponly1
bind M-2 grouponly2
bind M-3 grouponly3
bind MS-1 movetogroup1
bind MS-2 movetogroup2
bind MS-3 movetogroup3
# Mousebindings
mousebind M-2 window_lower
@@ -242,10 +260,16 @@ Launch
menu.
.It group[n]
Select group n, where n is 1-9.
.It grouponly[n]
Like
.Ar group[n]
but also hides the other groups.
.It nogroup
Select all groups.
.It grouptoggle
Toggle group membership of current window.
.It movetogroup[n]
Hide current window from display and move to group n, where n is 1-9.
.It cyclegroup
Forward cycle through groups.
.It rcyclegroup
@@ -380,7 +404,7 @@ Toggle group membership of current window.
.It menu_group
Launch group list.
.It menu_unhide
Launch group list.
Launch hidden window list.
.It menu_cmd
Launch command list.
.El

14
font.c
View File

@@ -22,22 +22,14 @@
void
font_init(struct screen_ctx *sc)
{
XColor xcolor, tmp;
sc->xftdraw = XftDrawCreate(X_Dpy, sc->rootwin,
DefaultVisual(X_Dpy, sc->which), DefaultColormap(X_Dpy, sc->which));
if (sc->xftdraw == NULL)
errx(1, "XftDrawCreate");
if (!XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, sc->which),
"black", &xcolor, &tmp))
errx(1, "XAllocNamedColor");
sc->xftcolor.color.red = xcolor.red;
sc->xftcolor.color.green = xcolor.green;
sc->xftcolor.color.blue = xcolor.blue;
sc->xftcolor.color.alpha = 0x00ff00;
sc->xftcolor.pixel = xcolor.pixel;
if (!XftColorAllocName(X_Dpy, DefaultVisual(X_Dpy, sc->which),
DefaultColormap(X_Dpy, sc->which), "black", &sc->xftcolor))
errx(1, "XftColorAllocName");
}
int

91
group.c
View File

@@ -24,11 +24,11 @@
#define CALMWM_NGROUPS 9
static void _group_add(struct group_ctx *, struct client_ctx *);
static void _group_remove(struct client_ctx *);
static void _group_hide(struct group_ctx *);
static void _group_show(struct group_ctx *);
static void _group_fix_hidden_state(struct group_ctx *);
static void group_add(struct group_ctx *, struct client_ctx *);
static void group_remove(struct client_ctx *);
static void group_hide(struct group_ctx *);
static void group_show(struct group_ctx *);
static void group_fix_hidden_state(struct group_ctx *);
struct group_ctx *Group_active = NULL;
struct group_ctx Groups[CALMWM_NGROUPS];
@@ -41,10 +41,10 @@ const char *shortcut_to_name[] = {
};
static void
_group_add(struct group_ctx *gc, struct client_ctx *cc)
group_add(struct group_ctx *gc, struct client_ctx *cc)
{
if (cc == NULL || gc == NULL)
errx(1, "_group_add: a ctx is NULL");
errx(1, "group_add: a ctx is NULL");
if (cc->group == gc)
return;
@@ -60,10 +60,10 @@ _group_add(struct group_ctx *gc, struct client_ctx *cc)
}
static void
_group_remove(struct client_ctx *cc)
group_remove(struct client_ctx *cc)
{
if (cc == NULL || cc->group == NULL)
errx(1, "_group_remove: a ctx is NULL");
errx(1, "group_remove: a ctx is NULL");
XChangeProperty(X_Dpy, cc->win, _CWM_GRP, XA_STRING, 8,
PropModeReplace, shortcut_to_name[0],
@@ -74,7 +74,7 @@ _group_remove(struct client_ctx *cc)
}
static void
_group_hide(struct group_ctx *gc)
group_hide(struct group_ctx *gc)
{
struct client_ctx *cc;
@@ -92,7 +92,7 @@ _group_hide(struct group_ctx *gc)
}
static void
_group_show(struct group_ctx *gc)
group_show(struct group_ctx *gc)
{
struct client_ctx *cc;
Window *winlist;
@@ -146,6 +146,17 @@ group_init(void)
Group_active = &Groups[0];
}
void
group_movetogroup(struct client_ctx *cc, int idx)
{
if (idx < 0 || idx >= CALMWM_NGROUPS)
err(1, "group_movetogroup: index out of range (%d)", idx);
if(Group_active != &Groups[idx])
client_hide(cc);
group_add(&Groups[idx], cc);
}
/*
* Colouring for groups upon add/remove.
*/
@@ -157,11 +168,11 @@ group_sticky_toggle_enter(struct client_ctx *cc)
gc = Group_active;
if (gc == cc->group) {
_group_remove(cc);
cc->highlight = CLIENT_HIGHLIGHT_RED;
group_remove(cc);
cc->highlight = CLIENT_HIGHLIGHT_UNGROUP;
} else {
_group_add(gc, cc);
cc->highlight = CLIENT_HIGHLIGHT_BLUE;
group_add(gc, cc);
cc->highlight = CLIENT_HIGHLIGHT_GROUP;
}
client_draw_border(cc);
@@ -178,7 +189,7 @@ group_sticky_toggle_exit(struct client_ctx *cc)
* if group_hidetoggle would produce no effect, toggle the group's hidden state
*/
static void
_group_fix_hidden_state(struct group_ctx *gc)
group_fix_hidden_state(struct group_ctx *gc)
{
struct client_ctx *cc;
int same = 0;
@@ -202,17 +213,33 @@ group_hidetoggle(int idx)
gc = &Groups[idx];
_group_fix_hidden_state(gc);
group_fix_hidden_state(gc);
if (gc->hidden)
_group_show(gc);
group_show(gc);
else {
_group_hide(gc);
group_hide(gc);
if (TAILQ_EMPTY(&gc->clients))
Group_active = gc;
}
}
void
group_only(int idx)
{
int i;
if (idx < 0 || idx >= CALMWM_NGROUPS)
err(1, "group_only: index out of range (%d)", idx);
for (i = 0; i < CALMWM_NGROUPS; i++) {
if (i == idx)
group_show(&Groups[i]);
else
group_hide(&Groups[i]);
}
}
/*
* Cycle through active groups. If none exist, then just stay put.
*/
@@ -236,16 +263,16 @@ group_cycle(int reverse)
if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL)
showgroup = gc;
else if (!gc->hidden)
_group_hide(gc);
group_hide(gc);
}
if (showgroup == NULL)
return;
_group_hide(Group_active);
group_hide(Group_active);
if (showgroup->hidden)
_group_show(showgroup);
group_show(showgroup);
else
Group_active = showgroup;
}
@@ -277,7 +304,7 @@ group_menu(XButtonEvent *e)
if (TAILQ_EMPTY(&gc->clients))
continue;
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
if (gc->hidden)
snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
gc->shortcut, shortcut_to_name[gc->shortcut]);
@@ -298,10 +325,7 @@ group_menu(XButtonEvent *e)
gc = (struct group_ctx *)mi->ctx;
if (gc->hidden)
_group_show(gc);
else
_group_hide(gc);
(gc->hidden) ? group_show(gc) : group_hide(gc);
cleanup:
while ((mi = TAILQ_FIRST(&menuq)) != NULL) {
@@ -317,15 +341,12 @@ group_alltoggle(void)
for (i = 0; i < CALMWM_NGROUPS; i++) {
if (Grouphideall)
_group_show(&Groups[i]);
group_show(&Groups[i]);
else
_group_hide(&Groups[i]);
group_hide(&Groups[i]);
}
if (Grouphideall)
Grouphideall = 0;
else
Grouphideall = 1;
Grouphideall = (Grouphideall) ? 0 : 1;
}
void
@@ -358,12 +379,12 @@ group_autogroup(struct client_ctx *cc)
TAILQ_FOREACH(gc, &Groupq, entry) {
if (strcmp(shortcut_to_name[gc->shortcut], group) == 0) {
_group_add(gc, cc);
group_add(gc, cc);
return;
}
}
if (Conf.flags & CONF_STICKY_GROUPS)
_group_add(Group_active, cc);
group_add(Group_active, cc);
}

View File

@@ -21,36 +21,33 @@
#ifndef _CALMWM_HEADERS_H_
#define _CALMWM_HEADERS_H_
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <dirent.h>
#include <getopt.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xrandr.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Intrinsic.h>
#include <X11/Xos.h>
#include <X11/Xft/Xft.h>
#include <err.h>
#endif /* _CALMWM_HEADERS_H_ */

View File

@@ -29,10 +29,7 @@ input_keycodetrans(KeyCode kc, u_int state, enum ctltype *ctl, char *chr)
*ctl = CTL_NONE;
*chr = '\0';
if (state & ShiftMask)
ks = XKeycodeToKeysym(X_Dpy, kc, 1);
else
ks = XKeycodeToKeysym(X_Dpy, kc, 0);
ks = XKeycodeToKeysym(X_Dpy, kc, (state & ShiftMask) ? 1 : 0);
/* Look for control characters. */
switch (ks) {

View File

@@ -135,7 +135,7 @@ kbfunc_client_search(struct client_ctx *scratch, union arg *arg)
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cc, &Clientq, entry) {
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
strlcpy(mi->text, cc->name, sizeof(mi->text));
mi->ctx = cc;
TAILQ_INSERT_TAIL(&menuq, mi, entry);
@@ -168,7 +168,7 @@ kbfunc_menu_search(struct client_ctx *scratch, union arg *arg)
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
strlcpy(mi->text, cmd->label, sizeof(mi->text));
mi->ctx = cmd;
TAILQ_INSERT_TAIL(&menuq, mi, entry);
@@ -304,7 +304,7 @@ kbfunc_exec(struct client_ctx *scratch, union arg *arg)
continue;
executable:
/* the thing in tpath, we may execute */
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
strlcpy(mi->text, dp->d_name, sizeof(mi->text));
TAILQ_INSERT_TAIL(&menuq, mi, entry);
}
@@ -380,7 +380,7 @@ kbfunc_ssh(struct client_ctx *scratch, union arg *arg)
if (p - buf + 1 > sizeof(hostbuf))
continue;
(void) strlcpy(hostbuf, buf, p - buf + 1);
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
(void) strlcpy(mi->text, hostbuf, sizeof(mi->text));
TAILQ_INSERT_TAIL(&menuq, mi, entry);
}
@@ -412,10 +412,7 @@ kbfunc_client_label(struct client_ctx *cc, union arg *arg)
TAILQ_INIT(&menuq);
if (cc->label != NULL)
current = cc->label;
else
current = NULL;
current = cc->label;
if ((mi = menu_filter(&menuq, "label", current, 1,
search_match_text, NULL)) != NULL) {
@@ -438,6 +435,12 @@ kbfunc_client_group(struct client_ctx *cc, union arg *arg)
group_hidetoggle(KBTOGROUP(arg->i));
}
void
kbfunc_client_grouponly(struct client_ctx *cc, union arg *arg)
{
group_only(KBTOGROUP(arg->i));
}
void
kbfunc_client_cyclegroup(struct client_ctx *cc, union arg *arg)
{
@@ -460,6 +463,12 @@ kbfunc_client_grouptoggle(struct client_ctx *cc, union arg *arg)
group_sticky_toggle_enter(cc);
}
void
kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
{
group_movetogroup(cc, KBTOGROUP(arg->i));
}
void
kbfunc_client_maximize(struct client_ctx *cc, union arg *arg)
{

40
menu.c
View File

@@ -18,11 +18,6 @@
#include "headers.h"
#include "calmwm.h"
#define KeyMask (KeyPressMask|ExposureMask)
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask| \
PointerMotionMask)
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask|\
PointerMotionMask)
#define PROMPT_SCHAR '<27>'
#define PROMPT_ECHAR '<27>'
@@ -48,7 +43,7 @@ static struct menu *menu_handle_key(XEvent *, struct menu_ctx *,
struct menu_q *, struct menu_q *);
static void menu_handle_move(XEvent *, struct menu_ctx *,
struct screen_ctx *);
struct menu *menu_handle_release(XEvent *, struct menu_ctx *,
static struct menu *menu_handle_release(XEvent *, struct menu_ctx *,
struct screen_ctx *, struct menu_q *);
static void menu_draw(struct screen_ctx *, struct menu_ctx *,
struct menu_q *, struct menu_q *);
@@ -58,8 +53,19 @@ static int menu_calc_entry(struct screen_ctx *, struct menu_ctx *,
void
menu_init(struct screen_ctx *sc)
{
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0,
1, 1, 1, sc->blackpixl, sc->whitepixl);
XGCValues gv;
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1, 0,
sc->color[CWM_COLOR_BG_MENU].pixel,
sc->color[CWM_COLOR_BG_MENU].pixel);
gv.foreground =
sc->color[CWM_COLOR_FG_MENU].pixel^sc->color[CWM_COLOR_BG_MENU].pixel;
gv.background = sc->color[CWM_COLOR_BG_MENU].pixel;
gv.function = GXxor;
sc->gc = XCreateGC(X_Dpy, sc->menuwin,
GCForeground|GCBackground|GCFunction, &gv);
}
struct menu *
@@ -73,7 +79,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
struct menu *mi = NULL;
XEvent e;
Window focuswin;
int Mask, focusrevert;
int evmask, focusrevert;
sc = screen_current();
@@ -84,11 +90,11 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y);
if (prompt == NULL) {
Mask = MenuMask;
evmask = MenuMask;
mc.promptstr[0] = '\0';
mc.list = 1;
} else {
Mask = MenuMask | KeyMask; /* only accept keys if prompt */
evmask = MenuMask | KeyMask; /* only accept keys if prompt */
snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%c", prompt,
PROMPT_SCHAR);
snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%c", mc.promptstr,
@@ -108,7 +114,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width,
font_height());
XSelectInput(X_Dpy, sc->menuwin, Mask);
XSelectInput(X_Dpy, sc->menuwin, evmask);
XMapRaised(X_Dpy, sc->menuwin);
if (xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_question) < 0) {
@@ -126,7 +132,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
for (;;) {
mc.changed = 0;
XWindowEvent(X_Dpy, sc->menuwin, Mask, &e);
XWindowEvent(X_Dpy, sc->menuwin, evmask, &e);
switch (e.type) {
default:
@@ -150,7 +156,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
}
}
out:
if ((dummy == 0 && mi->dummy) || (mi->text[0] == '\0')) { /* no match */
if (dummy == 0 && mi->dummy) { /* no match */
xfree (mi);
mi = NULL;
xu_ptr_ungrab();
@@ -343,7 +349,7 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
0, 0, mc->width, font_height());
}
void
static void
menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
{
mc->prev = mc->entry;
@@ -360,7 +366,7 @@ menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
xu_ptr_regrab(MenuGrabMask, Cursor_default);
}
struct menu *
static struct menu *
menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
struct menu_q *resultq)
{
@@ -377,7 +383,7 @@ menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
if (entry == i++)
break;
if (mi == NULL) {
XMALLOC(mi, struct menu);
mi = xmalloc(sizeof(*mi));
mi->text[0] = '\0';
mi->dummy = 1;
}

View File

@@ -22,14 +22,11 @@
#include "headers.h"
#include "calmwm.h"
static int _mousefunc_sweep_calc(struct client_ctx *, int, int, int, int);
static void _mousefunc_sweep_draw(struct client_ctx *, int, int);
#define ADJUST_HEIGHT(cc, dy) ((cc->geom.height - cc->geom.min_dy) / dy)
#define ADJUST_WIDTH(cc, dx) ((cc->geom.width - cc->geom.min_dx) / dx)
static int mousefunc_sweep_calc(struct client_ctx *, int, int, int, int);
static void mousefunc_sweep_draw(struct client_ctx *);
static int
_mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my)
mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my)
{
int width = cc->geom.width, height = cc->geom.height;
@@ -60,49 +57,50 @@ _mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my)
}
static void
_mousefunc_sweep_draw(struct client_ctx *cc, int dx, int dy)
mousefunc_sweep_draw(struct client_ctx *cc)
{
struct screen_ctx *sc = CCTOSC(cc);
char asize[10]; /* fits "nnnnxnnnn\0" */
int wide, height, wide_size, wide_name;
int x = cc->geom.x, y = cc->geom.y;
int width, height, width_size, width_name;
snprintf(asize, sizeof(asize), "%dx%d",
ADJUST_WIDTH(cc, dx), ADJUST_HEIGHT(cc, dy));
wide_size = font_width(asize, strlen(asize)) + 4;
wide_name = font_width(cc->name, strlen(cc->name)) + 4;
wide = MAX(wide_size, wide_name);
(cc->geom.width - cc->geom.min_dx) / cc->size->width_inc,
(cc->geom.height - cc->geom.min_dy) / cc->size->height_inc);
width_size = font_width(asize, strlen(asize)) + 4;
width_name = font_width(cc->name, strlen(cc->name)) + 4;
width = MAX(width_size, width_name);
height = font_ascent() + font_descent() + 1;
XMoveResizeWindow(X_Dpy, sc->menuwin, x, y, wide, height * 2);
XMoveResizeWindow(X_Dpy, sc->menuwin, cc->geom.x, cc->geom.y,
width, height * 2);
XMapWindow(X_Dpy, sc->menuwin);
XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0);
XClearWindow(X_Dpy, sc->menuwin);
font_draw(sc, cc->name, strlen(cc->name), sc->menuwin,
2, font_ascent() + 1);
font_draw(sc, asize, strlen(asize), sc->menuwin,
wide / 2 - wide_size / 2, height + font_ascent() + 1);
width / 2 - width_size / 2, height + font_ascent() + 1);
}
void
mousefunc_window_resize(struct client_ctx *cc, void *arg)
{
XEvent ev;
Time time = 0;
struct screen_ctx *sc = CCTOSC(cc);
int dx, dy;
int x = cc->geom.x, y = cc->geom.y;
dx = MAX(1, cc->size->width_inc);
dy = MAX(1, cc->size->height_inc);
cc->size->width_inc = MAX(1, cc->size->width_inc);
cc->size->height_inc = MAX(1, cc->size->height_inc);
client_raise(cc);
client_ptrsave(cc);
if (xu_ptr_grab(sc->rootwin, MouseMask, Cursor_resize) < 0)
if (xu_ptr_grab(cc->win, MouseMask, Cursor_resize) < 0)
return;
xu_ptr_setpos(cc->win, cc->geom.width, cc->geom.height);
_mousefunc_sweep_draw(cc, dx, dy);
mousefunc_sweep_draw(cc);
for (;;) {
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
@@ -112,13 +110,23 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg)
client_draw_border(cc);
break;
case MotionNotify:
if (_mousefunc_sweep_calc(cc, x, y,
ev.xmotion.x, ev.xmotion.y))
if (mousefunc_sweep_calc(cc, x, y,
ev.xmotion.x_root, ev.xmotion.y_root))
/* Recompute window output */
_mousefunc_sweep_draw(cc, dx, dy);
client_resize(cc);
mousefunc_sweep_draw(cc);
/* don't sync more than 60 times / second */
if ((ev.xmotion.time - time) > (1000 / 60)) {
time = ev.xmotion.time;
XSync(X_Dpy, False);
client_resize(cc);
}
break;
case ButtonRelease:
if (time) {
XSync(X_Dpy, False);
client_resize(cc);
}
XUnmapWindow(X_Dpy, sc->menuwin);
XReparentWindow(X_Dpy, sc->menuwin, sc->rootwin, 0, 0);
xu_ptr_ungrab();
@@ -140,16 +148,15 @@ void
mousefunc_window_move(struct client_ctx *cc, void *arg)
{
XEvent ev;
struct screen_ctx *sc = CCTOSC(cc);
int mx, my;
int x = cc->geom.x, y = cc->geom.y;
Time time = 0;
int px, py;
client_raise(cc);
if (xu_ptr_grab(sc->rootwin, MouseMask, Cursor_move) < 0)
if (xu_ptr_grab(cc->win, MouseMask, Cursor_move) < 0)
return;
xu_ptr_getpos(sc->rootwin, &mx, &my);
xu_ptr_getpos(cc->win, &px, &py);
for (;;) {
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
@@ -159,11 +166,21 @@ mousefunc_window_move(struct client_ctx *cc, void *arg)
client_draw_border(cc);
break;
case MotionNotify:
cc->geom.x = x + (ev.xmotion.x - mx);
cc->geom.y = y + (ev.xmotion.y - my);
client_move(cc);
cc->geom.x = ev.xmotion.x_root - px;
cc->geom.y = ev.xmotion.y_root - py;
/* don't sync more than 60 times / second */
if ((ev.xmotion.time - time) > (1000 / 60)) {
time = ev.xmotion.time;
XSync(X_Dpy, False);
client_move(cc);
}
break;
case ButtonRelease:
if (time) {
XSync(X_Dpy, False);
client_move(cc);
}
xu_ptr_ungrab();
return;
}
@@ -209,15 +226,11 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cc, &Clientq, entry)
if (cc->flags & CLIENT_HIDDEN) {
if (cc->label != NULL)
wname = cc->label;
else
wname = cc->name;
wname = (cc->label) ? cc->label : cc->name;
if (wname == NULL)
continue;
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
strlcpy(mi->text, wname, sizeof(mi->text));
mi->ctx = cc;
TAILQ_INSERT_TAIL(&menuq, mi, entry);
@@ -251,7 +264,7 @@ mousefunc_menu_cmd(struct client_ctx *cc, void *arg)
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
XCALLOC(mi, struct menu);
mi = xcalloc(1, sizeof(*mi));
strlcpy(mi->text, cmd->label, sizeof(mi->text));
mi->ctx = cmd;
TAILQ_INSERT_TAIL(&menuq, mi, entry);

40
parse.y
View File

@@ -67,6 +67,9 @@ typedef struct {
%token FONTNAME STICKY GAP MOUSEBIND
%token AUTOGROUP BIND COMMAND IGNORE
%token YES NO BORDERWIDTH MOVEAMOUNT
%token COLOR
%token ACTIVEBORDER INACTIVEBORDER
%token GROUPBORDER UNGROUPBORDER
%token ERROR
%token <v.string> STRING
%token <v.number> NUMBER
@@ -77,6 +80,7 @@ typedef struct {
grammar : /* empty */
| grammar '\n'
| grammar main '\n'
| grammar color '\n'
| grammar error '\n' { file->errors++; }
;
@@ -128,7 +132,7 @@ main : FONTNAME STRING {
YYERROR;
}
XCALLOC(aw, struct autogroupwin);
aw = xcalloc(1, sizeof(*aw));
if ((p = strchr($3, ',')) == NULL) {
aw->name = NULL;
@@ -147,7 +151,7 @@ main : FONTNAME STRING {
| IGNORE STRING {
struct winmatch *wm;
XCALLOC(wm, struct winmatch);
wm = xcalloc(1, sizeof(*wm));
strlcpy(wm->title, $2, sizeof(wm->title));
TAILQ_INSERT_TAIL(&conf->ignoreq, wm, entry);
@@ -170,6 +174,27 @@ main : FONTNAME STRING {
free($3);
}
;
color : COLOR colors
;
colors : ACTIVEBORDER STRING {
free(conf->color[CWM_COLOR_BORDOR_ACTIVE].name);
conf->color[CWM_COLOR_BORDOR_ACTIVE].name = $2;
}
| INACTIVEBORDER STRING {
free(conf->color[CWM_COLOR_BORDER_INACTIVE].name);
conf->color[CWM_COLOR_BORDER_INACTIVE].name = $2;
}
| GROUPBORDER STRING {
free(conf->color[CWM_COLOR_BORDER_GROUP].name);
conf->color[CWM_COLOR_BORDER_GROUP].name = $2;
}
| UNGROUPBORDER STRING {
free(conf->color[CWM_COLOR_BORDER_UNGROUP].name);
conf->color[CWM_COLOR_BORDER_UNGROUP].name = $2;
}
;
%%
struct keywords {
@@ -202,17 +227,22 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
{ "activeborder", ACTIVEBORDER},
{ "autogroup", AUTOGROUP},
{ "bind", BIND},
{ "borderwidth", BORDERWIDTH},
{ "color", COLOR},
{ "command", COMMAND},
{ "fontname", FONTNAME},
{ "gap", GAP},
{ "groupborder", GROUPBORDER},
{ "ignore", IGNORE},
{ "inactiveborder", INACTIVEBORDER},
{ "mousebind", MOUSEBIND},
{ "moveamount", MOVEAMOUNT},
{ "no", NO},
{ "sticky", STICKY},
{ "ungroupborder", UNGROUPBORDER},
{ "yes", YES}
};
const struct keywords *p;
@@ -473,7 +503,7 @@ parse_config(const char *filename, struct conf *xconf)
{
int errors = 0;
XCALLOC(conf, struct conf);
conf = xcalloc(1, sizeof(*conf));
if ((file = pushfile(filename)) == NULL) {
free(conf);
@@ -498,6 +528,7 @@ parse_config(const char *filename, struct conf *xconf)
struct winmatch *wm;
struct cmd *cmd;
struct mousebinding *mb;
int i;
conf_clear(xconf);
@@ -535,6 +566,9 @@ parse_config(const char *filename, struct conf *xconf)
strlcpy(xconf->lockpath, conf->lockpath,
sizeof(xconf->lockpath));
for (i = 0; i < CWM_COLOR_MAX; i++)
xconf->color[i].name = conf->color[i].name;
xconf->DefaultFontName = conf->DefaultFontName;
bcopy(&(conf->gap_top), &(xconf->gap_top), sizeof(int) * 4);

View File

@@ -21,9 +21,14 @@
#include "headers.h"
#include "calmwm.h"
extern struct screen_ctx_q Screenq;
extern struct screen_ctx *Curscreen;
void
screen_init(void)
{
TAILQ_INIT(&Screenq);
}
struct screen_ctx *
screen_fromroot(Window rootwin)
{

View File

@@ -17,12 +17,11 @@
* $Id$
*/
#include <fnmatch.h>
#include "headers.h"
#include "calmwm.h"
#define SearchMask (KeyPressMask|ExposureMask)
static int _strsubmatch(char *, char *, int);
static int strsubmatch(char *, char *, int);
/*
* Match: label, title, class.
@@ -54,7 +53,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
struct client_ctx *cc = mi->ctx;
/* First, try to match on labels. */
if (cc->label != NULL && _strsubmatch(search, cc->label, 0)) {
if (cc->label != NULL && strsubmatch(search, cc->label, 0)) {
cc->matchname = cc->label;
tier = 0;
}
@@ -62,7 +61,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
/* Then, on window names. */
if (tier < 0) {
TAILQ_FOREACH_REVERSE(wn, &cc->nameq, winname_q, entry)
if (_strsubmatch(search, wn->name, 0)) {
if (strsubmatch(search, wn->name, 0)) {
cc->matchname = wn->name;
tier = 2;
break;
@@ -74,7 +73,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
* name.
*/
if (tier < 0 && _strsubmatch(search, cc->app_class, 0)) {
if (tier < 0 && strsubmatch(search, cc->app_class, 0)) {
cc->matchname = cc->app_class;
tier = 3;
}
@@ -168,7 +167,7 @@ search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry)
if (_strsubmatch(search, mi->text, 0))
if (strsubmatch(search, mi->text, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
@@ -180,8 +179,9 @@ search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
if (_strsubmatch(search, mi->text, 1) == 0)
continue;
if (strsubmatch(search, mi->text, 1) == 0 &&
fnmatch(search, mi->text, 0) == FNM_NOMATCH)
continue;
for (mj = TAILQ_FIRST(resultq); mj != NULL;
mj = TAILQ_NEXT(mj, resultentry)) {
if (strcasecmp(mi->text, mj->text) < 0) {
@@ -195,7 +195,7 @@ search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)
}
static int
_strsubmatch(char *sub, char *str, int zeroidx)
strsubmatch(char *sub, char *str, int zeroidx)
{
size_t len, sublen;
u_int n, flen;

291
xevents.c
View File

@@ -27,13 +27,42 @@
#include "headers.h"
#include "calmwm.h"
/*
* NOTE: in reality, many of these should move to client.c now that
* we've got this nice event layer.
*/
static void xev_handle_maprequest(XEvent *);
static void xev_handle_unmapnotify(XEvent *);
static void xev_handle_destroynotify(XEvent *);
static void xev_handle_configurerequest(XEvent *);
static void xev_handle_propertynotify(XEvent *);
static void xev_handle_enternotify(XEvent *);
static void xev_handle_leavenotify(XEvent *);
static void xev_handle_buttonpress(XEvent *);
static void xev_handle_buttonrelease(XEvent *);
static void xev_handle_keypress(XEvent *);
static void xev_handle_keyrelease(XEvent *);
static void xev_handle_expose(XEvent *);
static void xev_handle_clientmessage(XEvent *);
static void xev_handle_randr(XEvent *);
static void xev_handle_mappingnotify(XEvent *);
void
xev_handle_maprequest(struct xevent *xev, XEvent *ee)
void (*xev_handlers[LASTEvent])(XEvent *) = {
[MapRequest] = xev_handle_maprequest,
[UnmapNotify] = xev_handle_unmapnotify,
[ConfigureRequest] = xev_handle_configurerequest,
[PropertyNotify] = xev_handle_propertynotify,
[EnterNotify] = xev_handle_enternotify,
[LeaveNotify] = xev_handle_leavenotify,
[ButtonPress] = xev_handle_buttonpress,
[ButtonRelease] = xev_handle_buttonrelease,
[KeyPress] = xev_handle_keypress,
[KeyRelease] = xev_handle_keyrelease,
[Expose] = xev_handle_expose,
[DestroyNotify] = xev_handle_destroynotify,
[ClientMessage] = xev_handle_clientmessage,
[MappingNotify] = xev_handle_mappingnotify,
};
static void
xev_handle_maprequest(XEvent *ee)
{
XMapRequestEvent *e = &ee->xmaprequest;
struct client_ctx *cc = NULL, *old_cc;
@@ -48,11 +77,10 @@ xev_handle_maprequest(struct xevent *xev, XEvent *ee)
}
client_ptrwarp(cc);
xev_register(xev);
}
void
xev_handle_unmapnotify(struct xevent *xev, XEvent *ee)
static void
xev_handle_unmapnotify(XEvent *ee)
{
XUnmapEvent *e = &ee->xunmap;
XEvent ev;
@@ -76,24 +104,20 @@ xev_handle_unmapnotify(struct xevent *xev, XEvent *ee)
client_hide(cc);
}
XUngrabServer(X_Dpy);
xev_register(xev);
}
void
xev_handle_destroynotify(struct xevent *xev, XEvent *ee)
static void
xev_handle_destroynotify(XEvent *ee)
{
XDestroyWindowEvent *e = &ee->xdestroywindow;
struct client_ctx *cc;
if ((cc = client_find(e->window)) != NULL)
client_delete(cc);
xev_register(xev);
}
void
xev_handle_configurerequest(struct xevent *xev, XEvent *ee)
static void
xev_handle_configurerequest(XEvent *ee)
{
XConfigureRequestEvent *e = &ee->xconfigurerequest;
struct client_ctx *cc;
@@ -140,12 +164,10 @@ xev_handle_configurerequest(struct xevent *xev, XEvent *ee)
XConfigureWindow(X_Dpy, e->window, e->value_mask, &wc);
}
xev_register(xev);
}
void
xev_handle_propertynotify(struct xevent *xev, XEvent *ee)
static void
xev_handle_propertynotify(XEvent *ee)
{
XPropertyEvent *e = &ee->xproperty;
struct client_ctx *cc;
@@ -164,8 +186,6 @@ xev_handle_propertynotify(struct xevent *xev, XEvent *ee)
break;
}
}
xev_register(xev);
}
void
@@ -187,29 +207,25 @@ xev_reconfig(struct client_ctx *cc)
XSendEvent(X_Dpy, cc->win, False, StructureNotifyMask, (XEvent *)&ce);
}
void
xev_handle_enternotify(struct xevent *xev, XEvent *ee)
static void
xev_handle_enternotify(XEvent *ee)
{
XCrossingEvent *e = &ee->xcrossing;
struct client_ctx *cc;
if ((cc = client_find(e->window)) != NULL)
client_setactive(cc, 1);
xev_register(xev);
}
void
xev_handle_leavenotify(struct xevent *xev, XEvent *ee)
static void
xev_handle_leavenotify(XEvent *ee)
{
client_leave(NULL);
xev_register(xev);
}
/* We can split this into two event handlers. */
void
xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
static void
xev_handle_buttonpress(XEvent *ee)
{
XButtonEvent *e = &ee->xbutton;
struct client_ctx *cc;
@@ -228,35 +244,31 @@ xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
}
if (mb == NULL)
goto out;
return;
if (mb->context == MOUSEBIND_CTX_ROOT) {
if (e->window != sc->rootwin)
goto out;
return;
} else if (mb->context == MOUSEBIND_CTX_WIN) {
cc = client_find(e->window);
if (cc == NULL)
goto out;
return;
}
(*mb->callback)(cc, e);
out:
xev_register(xev);
}
void
xev_handle_buttonrelease(struct xevent *xev, XEvent *ee)
static void
xev_handle_buttonrelease(XEvent *ee)
{
struct client_ctx *cc;
if ((cc = client_current()) != NULL)
group_sticky_toggle_exit(cc);
xev_register(xev);
}
void
xev_handle_keypress(struct xevent *xev, XEvent *ee)
static void
xev_handle_keypress(XEvent *ee)
{
XKeyEvent *e = &ee->xkey;
struct client_ctx *cc = NULL;
@@ -286,25 +298,22 @@ xev_handle_keypress(struct xevent *xev, XEvent *ee)
}
if (kb == NULL)
goto out;
return;
if ((kb->flags & (KBFLAG_NEEDCLIENT)) &&
(cc = client_find(e->window)) == NULL &&
(cc = client_current()) == NULL)
if (kb->flags & KBFLAG_NEEDCLIENT)
goto out;
return;
(*kb->callback)(cc, &kb->argument);
out:
xev_register(xev);
}
/*
* This is only used for the alt suppression detection.
*/
void
xev_handle_keyrelease(struct xevent *xev, XEvent *ee)
static void
xev_handle_keyrelease(XEvent *ee)
{
XKeyEvent *e = &ee->xkey;
struct screen_ctx *sc;
@@ -316,7 +325,7 @@ xev_handle_keyrelease(struct xevent *xev, XEvent *ee)
keysym = XKeycodeToKeysym(X_Dpy, e->keycode, 0);
if (keysym != XK_Alt_L && keysym != XK_Alt_R)
goto out;
return;
sc->altpersist = 0;
@@ -330,13 +339,10 @@ xev_handle_keyrelease(struct xevent *xev, XEvent *ee)
group_sticky_toggle_exit(cc);
XUngrabKeyboard(X_Dpy, CurrentTime);
}
out:
xev_register(xev);
}
void
xev_handle_clientmessage(struct xevent *xev, XEvent *ee)
static void
xev_handle_clientmessage(XEvent *ee)
{
XClientMessageEvent *e = &ee->xclient;
Atom xa_wm_change_state;
@@ -345,28 +351,28 @@ xev_handle_clientmessage(struct xevent *xev, XEvent *ee)
xa_wm_change_state = XInternAtom(X_Dpy, "WM_CHANGE_STATE", False);
if ((cc = client_find(e->window)) == NULL)
goto out;
return;
if (e->message_type == xa_wm_change_state && e->format == 32 &&
e->data.l[0] == IconicState)
client_hide(cc);
out:
xev_register(xev);
}
void
xev_handle_randr(struct xevent *xev, XEvent *ee)
static void
xev_handle_randr(XEvent *ee)
{
XRRScreenChangeNotifyEvent *rev = (XRRScreenChangeNotifyEvent *)ee;
struct client_ctx *cc;
struct screen_ctx *sc;
int i;
if ((cc = client_find(rev->window)) != NULL) {
XRRUpdateConfiguration(ee);
sc = CCTOSC(cc);
sc->xmax = rev->width;
sc->ymax = rev->height;
screen_init_xinerama(sc);
i = XRRRootToScreen(X_Dpy, rev->root);
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->which == (u_int)i) {
XRRUpdateConfiguration(ee);
sc->xmax = rev->width;
sc->ymax = rev->height;
screen_init_xinerama(sc);
}
}
}
@@ -374,8 +380,8 @@ xev_handle_randr(struct xevent *xev, XEvent *ee)
* Called when the keymap has changed.
* Ungrab all keys, reload keymap and then regrab
*/
void
xev_handle_mapping(struct xevent *xev, XEvent *ee)
static void
xev_handle_mappingnotify(XEvent *ee)
{
XMappingEvent *e = &ee->xmapping;
struct keybinding *kb;
@@ -387,160 +393,31 @@ xev_handle_mapping(struct xevent *xev, XEvent *ee)
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
conf_grab(&Conf, kb);
xev_register(xev);
}
/*
* X Event handling
*/
static struct xevent_q _xevq, _xevq_putaway;
static short _xev_q_lock = 0;
volatile sig_atomic_t _xev_quit = 0;
void
xev_init(void)
{
TAILQ_INIT(&_xevq);
TAILQ_INIT(&_xevq_putaway);
}
struct xevent *
xev_new(Window *win, Window *root,
int type, void (*cb)(struct xevent *, XEvent *), void *arg)
{
struct xevent *xev;
XMALLOC(xev, struct xevent);
xev->xev_win = win;
xev->xev_root = root;
xev->xev_type = type;
xev->xev_cb = cb;
xev->xev_arg = arg;
return (xev);
}
void
xev_register(struct xevent *xev)
{
struct xevent_q *xq;
xq = _xev_q_lock ? &_xevq_putaway : &_xevq;
TAILQ_INSERT_TAIL(xq, xev, entry);
}
void
_xev_reincorporate(void)
{
struct xevent *xev;
while ((xev = TAILQ_FIRST(&_xevq_putaway)) != NULL) {
TAILQ_REMOVE(&_xevq_putaway, xev, entry);
TAILQ_INSERT_TAIL(&_xevq, xev, entry);
}
}
void
xev_handle_expose(struct xevent *xev, XEvent *ee)
static void
xev_handle_expose(XEvent *ee)
{
XExposeEvent *e = &ee->xexpose;
struct client_ctx *cc;
if ((cc = client_find(e->window)) != NULL && e->count == 0)
client_draw_border(cc);
xev_register(xev);
}
#define ASSIGN(xtype) do { \
root = e. xtype .root; \
win = e. xtype .window; \
} while (0)
#define ASSIGN1(xtype) do { \
win = e. xtype .window; \
} while (0)
volatile sig_atomic_t _xev_quit = 0;
void
xev_loop(void)
{
Window win, root;
XEvent e;
struct xevent *xev = NULL, *nextxev;
int type;
while (_xev_quit == 0) {
#ifdef DIAGNOSTIC
if (TAILQ_EMPTY(&_xevq))
errx(1, "X event queue empty");
#endif
XNextEvent(X_Dpy, &e);
type = e.type;
win = root = 0;
switch (type) {
case MapRequest:
ASSIGN1(xmaprequest);
break;
case UnmapNotify:
ASSIGN1(xunmap);
break;
case ConfigureRequest:
ASSIGN1(xconfigurerequest);
break;
case PropertyNotify:
ASSIGN1(xproperty);
break;
case EnterNotify:
case LeaveNotify:
ASSIGN(xcrossing);
break;
case ButtonPress:
ASSIGN(xbutton);
break;
case ButtonRelease:
ASSIGN(xbutton);
break;
case KeyPress:
case KeyRelease:
ASSIGN(xkey);
break;
case DestroyNotify:
ASSIGN1(xdestroywindow);
break;
case ClientMessage:
ASSIGN1(xclient);
break;
default:
if (e.type == Randr_ev)
xev_handle_randr(xev, &e);
break;
}
/*
* Now, search for matches, and call each of them.
*/
_xev_q_lock = 1;
for (xev = TAILQ_FIRST(&_xevq); xev != NULL; xev = nextxev) {
nextxev = TAILQ_NEXT(xev, entry);
if ((type != xev->xev_type && xev->xev_type != 0) ||
(xev->xev_win != NULL && win != *xev->xev_win) ||
(xev->xev_root != NULL && root != *xev->xev_root))
continue;
TAILQ_REMOVE(&_xevq, xev, entry);
(*xev->xev_cb)(xev, &e);
}
_xev_q_lock = 0;
_xev_reincorporate();
if (e.type - Randr_ev == RRScreenChangeNotify)
xev_handle_randr(&e);
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
(*xev_handlers[e.type])(&e);
}
}
#undef ASSIGN
#undef ASSIGN1

26
xutil.c
View File

@@ -21,7 +21,7 @@
#include "headers.h"
#include "calmwm.h"
unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
int
xu_ptr_grab(Window win, int mask, Cursor curs)
@@ -161,8 +161,8 @@ xu_setstate(struct client_ctx *cc, int state)
{
long dat[2];
dat[0] = (long)state;
dat[1] = (long)None;
dat[0] = state;
dat[1] = None;
cc->state = state;
XChangeProperty(X_Dpy, cc->win, WM_STATE, WM_STATE, 32,
@@ -184,3 +184,23 @@ xu_getatoms(void)
{
XInternAtoms(X_Dpy, atoms, CWM_NO_ATOMS, False, cwm_atoms);
}
unsigned long
xu_getcolor(struct screen_ctx *sc, char *name)
{
XColor color, tmp;
if (!XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, sc->which),
name, &color, &tmp)) {
warnx("XAllocNamedColor error: '%s'", name);
return 0;
}
return color.pixel;
}
void
xu_freecolor(struct screen_ctx *sc, unsigned long pixel)
{
XFreeColors(X_Dpy, DefaultColormap(X_Dpy, sc->which), &pixel, 1, 0L);
}