47 Commits
v6.2 ... v6.3

Author SHA1 Message Date
a9dbac8209 README: update 2018-05-14 15:31:34 +02:00
fae50566fc Makefile: drop unused fontconfig dependency 2018-05-14 14:47:24 +02:00
cae6987922 cvsimport
* refs/heads/master:
  Do not print any parse errors when ~/.cwmrc is missing. Regression introduced in revision 1.109 of calmwm.c.
  Store the screen's visual type and colormap.
  Consolidate region 'view' and 'area'.
  limit scope of screen_apply_gap()
  Clean up conf_file/homedir and conf_init() bits.
2018-02-19 19:29:42 +00:00
0551094182 Do not print any parse errors when ~/.cwmrc is missing. Regression introduced in
revision 1.109 of calmwm.c.

ok okan@
2018-02-19 19:29:42 +00:00
b1929b5ed6 Store the screen's visual type and colormap. 2018-02-13 15:43:15 +00:00
13763662c9 Consolidate region 'view' and 'area'. 2018-02-13 15:06:22 +00:00
e6bf7429b3 limit scope of screen_apply_gap() 2018-02-09 20:08:07 +00:00
1a5f80bd0b Clean up conf_file/homedir and conf_init() bits. 2018-02-09 19:54:54 +00:00
c6745ee21c calmwm: replace INFTIM with -1 2018-02-09 20:11:41 +01:00
f3211427c1 Use screen's saved view instead of re-querying the server. 2018-02-06 15:05:20 +00:00
63ebc0cd8b cvsimport
* refs/heads/master: (28 commits)
  Use screen's saved view instead of re-querying the server.
  Slightly expand and expose verbose debugging.
  add debugging for x events
  Add a simple debug logging mechanism.
  Simplification; use asprintf where appropriate now.
  Use func attributes where appropriate.
  Fix wins comparison declaration since it's unsigned from XQueryTree().
  Generate name_to_func[] in a clean and readable fashion.
  Shrink tier[] by one after removing matchname in r1.55.
  If the requested group number is invalid, bail but don't kill cwm.
  Quick fix: exit after a failed execvp in u_spawn instead; previously we did in u_exec, but the introduction of re-exec'ing the previous invocation of cwm if 'exec_wm' failed missed the 'exec' failing path. Will likely split out as a proper fix.
  Only exec the fallback when in CWM_EXEC_WM state.
  Typo, from Julien Steinhauser.
  Convert menu-exec-wm from an abritrary exec menu, into a config-based menu from which one may configure (wm <name> <path_and_args>) (and choose) specific window managers to replace the running one. 'wm cwm cwm' is included by default.
  As done for buttonrelease, work specific un-cycling and un-highlighting actions into the keyrelease event, only performing what's actually needed for each; should result in much fewer events against keyreleases. No intended behaviour change.
  Merge group_toggle_membership_leave into the buttonrelease event and only do border work for a group/ungroup action.
  add helper function client_show to bring together like actions for unhide/raise
  Add support for re-exec'ing with SIGHUP; equivalent to the already built-in 'restart' function.
  Use poll and XNextEvent to replace XNextEvent blocking inside the x11 event handler.
  zap stray that snuck in
  ...
2018-02-06 15:05:20 +00:00
14c17b5f9b Slightly expand and expose verbose debugging. 2018-02-04 22:56:26 +00:00
8623c7add7 add debugging for x events 2018-02-02 13:50:22 +00:00
34e15dbd7a Add a simple debug logging mechanism. 2018-02-02 13:40:55 +00:00
9bf750b054 Simplification; use asprintf where appropriate now. 2018-02-02 13:27:25 +00:00
174537f29e Use func attributes where appropriate. 2018-02-01 15:17:51 +00:00
f34e659ca7 Fix wins comparison declaration since it's unsigned from XQueryTree(). 2018-01-23 16:18:59 +00:00
03a2e9cf05 Generate name_to_func[] in a clean and readable fashion. 2018-01-23 16:00:21 +00:00
5324f9a4e3 Shrink tier[] by one after removing matchname in r1.55. 2018-01-23 13:51:39 +00:00
8675b5e158 If the requested group number is invalid, bail but don't kill cwm. 2018-01-23 13:48:49 +00:00
e99f1d4683 Quick fix: exit after a failed execvp in u_spawn instead; previously we did in
u_exec, but the introduction of re-exec'ing the previous invocation of cwm if
'exec_wm' failed missed the 'exec' failing path. Will likely split out as a
proper fix.

Odd behaviour reported by Ve Telko.
2018-01-08 16:21:54 +00:00
50c0a4eef6 Only exec the fallback when in CWM_EXEC_WM state.
Broken quit noticed by Ve Telko.
2018-01-02 14:04:58 +00:00
5672d5d203 Typo, from Julien Steinhauser. 2017-12-30 22:25:09 +00:00
15ca9c03ba If the replacement window manager fails to start, restart the fallback (the
original invocation of cwm).
2017-12-29 20:09:19 +00:00
6e7dbf5bb7 Convert menu-exec-wm from an abritrary exec menu, into a config-based menu from
which one may configure (wm <name> <path_and_args>) (and choose) specific
window managers to replace the running one. 'wm cwm cwm' is included by
default.

No objections and seems sensible to sthen.
2017-12-29 20:03:46 +00:00
43db5b55ea As done for buttonrelease, work specific un-cycling and un-highlighting actions
into the keyrelease event, only performing what's actually needed for each;
should result in much fewer events against keyreleases. No intended behaviour
change.

Additionally, like we do for group membership, grab the keyboard only when
required for cycling.
2017-12-29 18:50:43 +00:00
ba75c13953 Merge group_toggle_membership_leave into the buttonrelease event and only do
border work for a group/ungroup action.
2017-12-29 16:55:50 +00:00
5ddaed415c add helper function client_show to bring together like actions for unhide/raise 2017-12-29 12:54:54 +00:00
156681f0a5 Add support for re-exec'ing with SIGHUP; equivalent to the already built-in
'restart' function.
2017-12-27 18:46:18 +00:00
3d7c82936e Use poll and XNextEvent to replace XNextEvent blocking inside the x11 event
handler.
2017-12-27 17:04:35 +00:00
03e5d86952 zap stray that snuck in 2017-12-22 21:30:01 +00:00
dfaf44c0ac Return the connection number for the display. 2017-12-22 21:27:45 +00:00
c5d03b0853 Fix a few comments and while here, wrap some long lines. 2017-12-22 21:21:44 +00:00
18a53717ae Use a variable to keep track of flags for menu_filter(). 2017-12-19 19:38:43 +00:00
bc5215f41a Add support for _NET_WM_STATE_SKIP_PAGER and _NET_WM_STATE_SKIP_TASKBAR; eerily
close to cwm's 'ignore'.

Roughly based on an initial diff from Walter Alejandro Iglesias, but with
support for both Atoms and without cwm-based bindings.
2017-12-19 14:30:53 +00:00
5e5d06f063 remove duplicate ExposureMask 2017-12-15 13:13:17 +00:00
64ff5f399a move variable declarations up, to match everything else 2017-12-13 15:10:17 +00:00
add109c006 clean up after previous (noprompt removal) 2017-12-12 15:37:16 +00:00
888f6c5319 Unconditionally show prompt on menus, regardless of invocation. 2017-12-11 20:58:18 +00:00
a0774f4777 cvsimport
* refs/heads/master:
  Original idea from Dimitris Papastamos to move windows to corners a while ago; re-proposed by Julien Steinhauser with an updated diff. Apparently this was in the original calmnwm.
  give command and group menus their own match callbacks
  stash dir into conf since it'll be of use
  organize this a bit better
  spacing
2017-12-07 16:25:33 +00:00
0fc9d47fb4 Original idea from Dimitris Papastamos to move windows to corners a while ago;
re-proposed by Julien Steinhauser with an updated diff. Apparently this was in
the original calmnwm.

However, expand the original idea and let clients 'snap' to edges instead,
neatly allowing key bindings that snap to adjacent edges (i.e. corners) as
well. No default bindings assigned.
2017-12-07 16:25:33 +00:00
f0524fe07a give command and group menus their own match callbacks 2017-12-07 16:03:10 +00:00
b06ddae624 stash dir into conf since it'll be of use 2017-12-07 15:47:14 +00:00
0d76265e23 organize this a bit better 2017-12-07 15:40:54 +00:00
592e8efaee spacing 2017-12-07 15:39:47 +00:00
dd5f951205 cvsimport
* refs/heads/master:
  Revert r1.109 (Switch to XWindowEvent() pulling out events that match the mask *and* window.) of mousefunc.c. When a client destroys itself while we are moving or resizing it, XWindowEvent() blocks. Found the hard way by Anton Lazarov, and Lea°hNeukirchen found the right bit to revert - thanks! Reverting since the reason to switch from XMaskEvent was unclear.
2017-11-30 18:18:51 +00:00
d9d6b4f88f Revert r1.109 (Switch to XWindowEvent() pulling out events that match the mask
*and* window.) of mousefunc.c. When a client destroys itself while we are
moving or resizing it, XWindowEvent() blocks. Found the hard way by Anton
Lazarov, and Lea°hNeukirchen found the right bit to revert - thanks! Reverting
since the reason to switch from XMaskEvent was unclear.
2017-11-30 18:18:51 +00:00
17 changed files with 773 additions and 531 deletions

View File

@ -14,11 +14,11 @@ OBJS= calmwm.o screen.o xmalloc.o client.o menu.o \
kbfunc.o strlcpy.o strlcat.o y.tab.o \
strtonum.o reallocarray.o
CPPFLAGS+= `pkg-config --cflags fontconfig x11 xft xrandr`
CPPFLAGS+= `pkg-config --cflags x11 xft xrandr`
CFLAGS?= -Wall -O2 -g -D_GNU_SOURCE
LDFLAGS+= `pkg-config --libs fontconfig x11 xft xrandr`
LDFLAGS+= `pkg-config --libs x11 xft xrandr`
MANPREFIX?= ${PREFIX}/share/man

8
README
View File

@ -107,6 +107,14 @@ Changes made between OpenBSD 5.8 and 5.9
2017-10-17: Fourth public release 6.2 of portable cwm.
Changes made between OpenBSD 6.2 and 6.3
* Fix blocking bug during moving or resizing.
* window-snap-* commands to move windows to edges and corners.
* Add support for _NET_WM_STATE_SKIP_PAGER and _NET_WM_STATE_SKIP_TASKBAR.
* Add support for re-exec'ing with SIGHUP.
2018-05-14: Fifth public release 6.3 of portable cwm.
--Leah Neukirchen <leah@vuxu.org>
[0]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/xenocara/app/cwm/

View File

@ -27,7 +27,7 @@
#include <getopt.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@ -42,36 +42,42 @@ Atom cwmh[CWMH_NITEMS];
Atom ewmh[EWMH_NITEMS];
struct screen_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
struct conf Conf;
const char *homedir;
volatile sig_atomic_t cwm_status;
static void sighdlr(int);
static int x_errorhandler(Display *, XErrorEvent *);
static void x_init(const char *);
static int x_init(const char *);
static void x_teardown(void);
static int x_wmerrorhandler(Display *, XErrorEvent *);
int
main(int argc, char **argv)
{
const char *conf_file = NULL;
char *conf_path, *display_name = NULL;
int ch;
struct passwd *pw;
char *display_name = NULL;
char *fallback;
int ch, xfd;
struct pollfd pfd[1];
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
warnx("no locale support");
mbtowc(NULL, NULL, MB_CUR_MAX);
conf_init(&Conf);
fallback = u_argv(argv);
Conf.wm_argv = u_argv(argv);
while ((ch = getopt(argc, argv, "c:d:")) != -1) {
while ((ch = getopt(argc, argv, "c:d:v")) != -1) {
switch (ch) {
case 'c':
conf_file = optarg;
free(Conf.conf_file);
Conf.conf_file = xstrdup(optarg);
break;
case 'd':
display_name = optarg;
break;
case 'v':
Conf.debug++;
break;
default:
usage();
}
@ -81,34 +87,13 @@ main(int argc, char **argv)
if (signal(SIGCHLD, sighdlr) == SIG_ERR)
err(1, "signal");
if (signal(SIGHUP, sighdlr) == SIG_ERR)
err(1, "signal");
if ((homedir = getenv("HOME")) == NULL || *homedir == '\0') {
pw = getpwuid(getuid());
if (pw != NULL && pw->pw_dir != NULL && *pw->pw_dir != '\0')
homedir = pw->pw_dir;
else
homedir = "/";
}
if (parse_config(Conf.conf_file, &Conf) == -1)
warnx("error parsing config file");
if (conf_file == NULL)
xasprintf(&conf_path, "%s/%s", homedir, CONFFILE);
else
conf_path = xstrdup(conf_file);
if (access(conf_path, R_OK) != 0) {
if (conf_file != NULL)
warn("%s", conf_file);
free(conf_path);
conf_path = NULL;
}
conf_init(&Conf);
if (conf_path && (parse_config(conf_path, &Conf) == -1))
warnx("config file %s has errors", conf_path);
free(conf_path);
x_init(display_name);
xfd = x_init(display_name);
cwm_status = CWM_RUNNING;
#ifdef __OpenBSD__
@ -116,16 +101,27 @@ main(int argc, char **argv)
err(1, "pledge");
#endif
while (cwm_status == CWM_RUNNING)
memset(&pfd, 0, sizeof(pfd));
pfd[0].fd = xfd;
pfd[0].events = POLLIN;
while (cwm_status == CWM_RUNNING) {
xev_process();
if (poll(pfd, 1, -1) == -1) {
if (errno != EINTR)
warn("poll");
}
}
x_teardown();
if (cwm_status == CWM_EXEC_WM)
if (cwm_status == CWM_EXEC_WM) {
u_exec(Conf.wm_argv);
warnx("'%s' failed to start, starting fallback", Conf.wm_argv);
u_exec(fallback);
}
return(0);
}
static void
static int
x_init(const char *dpyname)
{
int i;
@ -145,6 +141,8 @@ x_init(const char *dpyname)
for (i = 0; i < ScreenCount(X_Dpy); i++)
screen_init(i);
return ConnectionNumber(X_Dpy);
}
static void
@ -178,7 +176,6 @@ static int
x_wmerrorhandler(Display *dpy, XErrorEvent *e)
{
errx(1, "root window unavailable - perhaps another wm is running?");
return(0);
}
@ -211,6 +208,9 @@ sighdlr(int sig)
(pid < 0 && errno == EINTR))
;
break;
case SIGHUP:
cwm_status = CWM_EXEC_WM;
break;
}
errno = save_errno;
@ -221,7 +221,7 @@ usage(void)
{
extern char *__progname;
(void)fprintf(stderr, "usage: %s [-c file] [-d display]\n",
(void)fprintf(stderr, "usage: %s [-v] [-c file] [-d display]\n",
__progname);
exit(1);
}

View File

@ -52,6 +52,11 @@ size_t strlcpy(char *, const char *, size_t);
#include <X11/extensions/Xrandr.h>
#include <X11/keysym.h>
#define LOG_DEBUG0(...) log_debug(0, __func__, __VA_ARGS__)
#define LOG_DEBUG1(...) log_debug(1, __func__, __VA_ARGS__)
#define LOG_DEBUG2(...) log_debug(2, __func__, __VA_ARGS__)
#define LOG_DEBUG3(...) log_debug(3, __func__, __VA_ARGS__)
#undef MIN
#undef MAX
#define MIN(x, y) ((x) < (y) ? (x) : (y))
@ -61,13 +66,11 @@ size_t strlcpy(char *, const char *, size_t);
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
#define CONFFILE ".cwmrc"
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define MENUMASK (MOUSEMASK | ButtonMotionMask | ExposureMask)
#define MENUMASK (MOUSEMASK | ButtonMotionMask | KeyPressMask | \
ExposureMask)
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
#define KEYMASK (KeyPressMask | ExposureMask)
#define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000)
/* direction/amount */
@ -76,7 +79,15 @@ size_t strlcpy(char *, const char *, size_t);
#define CWM_LEFT 0x0004
#define CWM_RIGHT 0x0008
#define CWM_BIGAMOUNT 0x0010
#define DIRECTIONMASK (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
#define CWM_UP_BIG (CWM_UP | CWM_BIGAMOUNT)
#define CWM_DOWN_BIG (CWM_DOWN | CWM_BIGAMOUNT)
#define CWM_LEFT_BIG (CWM_LEFT | CWM_BIGAMOUNT)
#define CWM_RIGHT_BIG (CWM_RIGHT | CWM_BIGAMOUNT)
#define CWM_UP_RIGHT (CWM_UP | CWM_RIGHT)
#define CWM_UP_LEFT (CWM_UP | CWM_LEFT)
#define CWM_DOWN_RIGHT (CWM_DOWN | CWM_RIGHT)
#define CWM_DOWN_LEFT (CWM_DOWN | CWM_LEFT)
#define DIRECTIONMASK (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
#define CWM_CYCLE_FORWARD 0x0001
#define CWM_CYCLE_REVERSE 0x0002
@ -176,6 +187,11 @@ struct client_ctx {
#define CLIENT_FULLSCREEN 0x0800
#define CLIENT_STICKY 0x1000
#define CLIENT_ACTIVE 0x2000
#define CLIENT_SKIP_PAGER 0x4000
#define CLIENT_SKIP_TASKBAR 0x8000
#define CLIENT_SKIP_CYCLE (CLIENT_HIDDEN | CLIENT_IGNORE | \
CLIENT_SKIP_TASKBAR | CLIENT_SKIP_PAGER)
#define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP)
#define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
#define CLIENT_MAXIMIZED (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
@ -209,7 +225,6 @@ TAILQ_HEAD(autogroup_q, autogroup);
struct region_ctx {
TAILQ_ENTRY(region_ctx) entry;
int num;
struct geom area;
struct geom view; /* viewable area */
struct geom work; /* workable area, gap-applied */
};
@ -229,6 +244,8 @@ struct screen_ctx {
struct region_q regionq;
struct group_q groupq;
struct group_ctx *group_active;
Colormap colormap;
Visual *visual;
struct {
Window win;
XftDraw *xftdraw;
@ -268,14 +285,11 @@ TAILQ_HEAD(mousebind_q, bind_ctx);
struct cmd_ctx {
TAILQ_ENTRY(cmd_ctx) entry;
char *name;
char path[PATH_MAX];
char *path;
};
TAILQ_HEAD(cmd_q, cmd_ctx);
TAILQ_HEAD(wm_q, cmd_ctx);
enum menu_exec {
CWM_MENU_EXEC_EXEC,
CWM_MENU_EXEC_WM
};
#define CWM_MENU_DUMMY 0x0001
#define CWM_MENU_FILE 0x0002
#define CWM_MENU_LIST 0x0004
@ -300,6 +314,7 @@ struct conf {
struct autogroup_q autogroupq;
struct ignore_q ignoreq;
struct cmd_q cmdq;
struct wm_q wmq;
int ngroups;
int stickygroups;
int nameqlen;
@ -308,13 +323,15 @@ struct conf {
int snapdist;
struct gap gap;
char *color[CWM_COLOR_NITEMS];
char known_hosts[PATH_MAX];
char *font;
char *wmname;
Cursor cursor[CF_NITEMS];
int xrandr;
int xrandr_event_base;
char *conf_file;
char *known_hosts;
char *wm_argv;
int debug;
};
/* MWM hints */
@ -373,13 +390,15 @@ enum ewmh {
_NET_WM_DESKTOP,
_NET_CLOSE_WINDOW,
_NET_WM_STATE,
#define _NET_WM_STATES_NITEMS 7
#define _NET_WM_STATES_NITEMS 9
_NET_WM_STATE_STICKY,
_NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_HIDDEN,
_NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_DEMANDS_ATTENTION,
_NET_WM_STATE_SKIP_PAGER,
_NET_WM_STATE_SKIP_TASKBAR,
_CWM_WM_STATE_FREEZE,
EWMH_NITEMS
};
@ -395,7 +414,6 @@ extern Atom cwmh[CWMH_NITEMS];
extern Atom ewmh[EWMH_NITEMS];
extern struct screen_q Screenq;
extern struct conf Conf;
extern const char *homedir;
void usage(void);
@ -403,7 +421,6 @@ void client_applysizehints(struct client_ctx *);
void client_config(struct client_ctx *);
struct client_ctx *client_current(void);
void client_cycle(struct screen_ctx *, int);
void client_cycle_leave(struct screen_ctx *);
void client_delete(struct client_ctx *);
void client_draw_border(struct client_ctx *);
struct client_ctx *client_find(Window);
@ -415,6 +432,7 @@ void client_lower(struct client_ctx *);
void client_map(struct client_ctx *);
void client_msg(struct client_ctx *, Atom, Time);
void client_move(struct client_ctx *);
void client_mtf(struct client_ctx *);
int client_inbound(struct client_ctx *, int, int);
struct client_ctx *client_init(Window, struct screen_ctx *, int);
void client_ptr_inbound(struct client_ctx *, int);
@ -426,12 +444,15 @@ void client_send_delete(struct client_ctx *);
void client_set_wm_state(struct client_ctx *, long);
void client_setactive(struct client_ctx *);
void client_setname(struct client_ctx *);
void client_show(struct client_ctx *);
int client_snapcalc(int, int, int, int, int);
void client_toggle_freeze(struct client_ctx *);
void client_toggle_fullscreen(struct client_ctx *);
void client_toggle_hidden(struct client_ctx *);
void client_toggle_hmaximize(struct client_ctx *);
void client_toggle_maximize(struct client_ctx *);
void client_toggle_skip_pager(struct client_ctx *);
void client_toggle_skip_taskbar(struct client_ctx *);
void client_toggle_sticky(struct client_ctx *);
void client_toggle_vmaximize(struct client_ctx *);
void client_transient(struct client_ctx *);
@ -453,8 +474,7 @@ void group_movetogroup(struct client_ctx *, int);
void group_only(struct screen_ctx *, int);
int group_restore(struct client_ctx *);
void group_show(struct group_ctx *);
void group_toggle_membership_enter(struct client_ctx *);
void group_toggle_membership_leave(struct client_ctx *);
void group_toggle_membership(struct client_ctx *);
void group_update_names(struct screen_ctx *);
void search_match_client(struct menu_q *, struct menu_q *,
@ -465,13 +485,19 @@ void search_match_path(struct menu_q *, struct menu_q *,
char *);
void search_match_text(struct menu_q *, struct menu_q *,
char *);
void search_match_cmd(struct menu_q *, struct menu_q *,
char *);
void search_match_group(struct menu_q *, struct menu_q *,
char *);
void search_match_wm(struct menu_q *, struct menu_q *,
char *);
void search_print_client(struct menu *, int);
void search_print_cmd(struct menu *, int);
void search_print_group(struct menu *, int);
void search_print_text(struct menu *, int);
void search_print_wm(struct menu *, int);
struct region_ctx *region_find(struct screen_ctx *, int, int);
struct geom screen_apply_gap(struct screen_ctx *, struct geom);
struct screen_ctx *screen_find(Window);
struct geom screen_area(struct screen_ctx *, int, int,
enum apply_gap);
@ -482,6 +508,7 @@ void screen_assert_clients_within(struct screen_ctx *);
void kbfunc_cwm_status(void *, struct cargs *);
void kbfunc_ptrmove(void *, struct cargs *);
void kbfunc_client_snap(void *, struct cargs *);
void kbfunc_client_move(void *, struct cargs *);
void kbfunc_client_resize(void *, struct cargs *);
void kbfunc_client_delete(void *, struct cargs *);
@ -507,6 +534,7 @@ void kbfunc_group_alltoggle(void *, struct cargs *);
void kbfunc_menu_client(void *, struct cargs *);
void kbfunc_menu_cmd(void *, struct cargs *);
void kbfunc_menu_group(void *, struct cargs *);
void kbfunc_menu_wm(void *, struct cargs *);
void kbfunc_menu_exec(void *, struct cargs *);
void kbfunc_menu_ssh(void *, struct cargs *);
void kbfunc_client_menu_label(void *, struct cargs *);
@ -515,12 +543,15 @@ void kbfunc_exec_lock(void *, struct cargs *);
void kbfunc_exec_term(void *, struct cargs *);
void menu_windraw(struct screen_ctx *, Window,
const char *, ...);
const char *, ...)
__attribute__((__format__ (printf, 3, 4)))
__attribute__((__nonnull__ (3)));
struct menu *menu_filter(struct screen_ctx *, struct menu_q *,
const char *, const char *, int,
void (*)(struct menu_q *, struct menu_q *, char *),
void (*)(struct menu *, int));
void menuq_add(struct menu_q *, void *, const char *, ...);
void menuq_add(struct menu_q *, void *, const char *, ...)
__attribute__((__format__ (printf, 3, 4)));
void menuq_clear(struct menu_q *);
int parse_config(const char *, struct conf *);
@ -534,7 +565,9 @@ int conf_bind_mouse(struct conf *, const char *,
const char *);
void conf_clear(struct conf *);
void conf_client(struct client_ctx *);
int conf_cmd_add(struct conf *, const char *,
void conf_cmd_add(struct conf *, const char *,
const char *);
void conf_wm_add(struct conf *, const char *,
const char *);
void conf_cursor(struct conf *);
void conf_grab_kbd(Window);
@ -576,6 +609,9 @@ void xu_ewmh_restore_net_wm_state(struct client_ctx *);
char *u_argv(char * const *);
void u_exec(char *);
void u_spawn(char *);
void log_debug(int, const char *, const char *, ...)
__attribute__((__format__ (printf, 3, 4)))
__attribute__((__nonnull__ (3)));
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);

View File

@ -33,7 +33,6 @@
static struct client_ctx *client_next(struct client_ctx *);
static struct client_ctx *client_prev(struct client_ctx *);
static void client_mtf(struct client_ctx *);
static void client_placecalc(struct client_ctx *);
static void client_wm_protocols(struct client_ctx *);
static void client_mwm_hints(struct client_ctx *);
@ -104,8 +103,8 @@ client_init(Window win, struct screen_ctx *sc, int active)
if ((cc->wmh) && (cc->wmh->flags & StateHint))
client_set_wm_state(cc, cc->wmh->initial_state);
} else {
if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin, &cwin,
&x, &y, &wx, &wy, &mask)) && (cwin != None))
if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin,
&cwin, &x, &y, &wx, &wy, &mask)) && (cwin != None))
active = 1;
}
@ -222,7 +221,7 @@ client_setactive(struct client_ctx *cc)
client_draw_border(oldcc);
}
/* If we're in the middle of cycing, don't change the order. */
/* If we're in the middle of cycling, don't change the order. */
if (!sc->cycling)
client_mtf(cc);
@ -265,6 +264,20 @@ client_toggle_hidden(struct client_ctx *cc)
xu_ewmh_set_net_wm_state(cc);
}
void
client_toggle_skip_pager(struct client_ctx *cc)
{
cc->flags ^= CLIENT_SKIP_PAGER;
xu_ewmh_set_net_wm_state(cc);
}
void
client_toggle_skip_taskbar(struct client_ctx *cc)
{
cc->flags ^= CLIENT_SKIP_TASKBAR;
xu_ewmh_set_net_wm_state(cc);
}
void
client_toggle_sticky(struct client_ctx *cc)
{
@ -330,11 +343,6 @@ client_toggle_maximize(struct client_ctx *cc)
cc->savegeom.x = cc->geom.x;
}
/*
* pick screen that the middle of the window is on.
* that's probably more fair than if just the origin of
* a window is poking over a boundary
*/
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
@ -522,6 +530,15 @@ client_hide(struct client_ctx *cc)
client_set_wm_state(cc, IconicState);
}
void
client_show(struct client_ctx *cc)
{
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
else
client_raise(cc);
}
void
client_unhide(struct client_ctx *cc)
{
@ -644,7 +661,6 @@ client_setname(struct client_ctx *cc)
wn = xmalloc(sizeof(*wn));
wn->name = newname;
TAILQ_INSERT_TAIL(&cc->nameq, wn, entry);
match:
cc->name = wn->name;
@ -666,10 +682,6 @@ client_cycle(struct screen_ctx *sc, int flags)
struct client_ctx *newcc, *oldcc, *prevcc;
int again = 1;
/* For X apps that ignore events. */
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (TAILQ_EMPTY(&sc->clientq))
return;
@ -688,21 +700,20 @@ client_cycle(struct screen_ctx *sc, int flags)
client_next(newcc);
/* Only cycle visible and non-ignored windows. */
if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE))
|| ((flags & CWM_CYCLE_INGROUP) &&
(newcc->gc != oldcc->gc)))
if ((newcc->flags & (CLIENT_SKIP_CYCLE)) ||
((flags & CWM_CYCLE_INGROUP) &&
(newcc->gc != oldcc->gc)))
again = 1;
/* Is oldcc the only non-hidden window? */
if (newcc == oldcc) {
if (again)
return; /* No windows visible. */
break;
}
}
/* reset when cycling mod is released. XXX I hate this hack */
/* Reset when cycling mod is released. XXX I hate this hack */
sc->cycling = 1;
client_ptrsave(oldcc);
client_raise(prevcc);
@ -714,21 +725,6 @@ client_cycle(struct screen_ctx *sc, int flags)
client_ptrwarp(newcc);
}
void
client_cycle_leave(struct screen_ctx *sc)
{
struct client_ctx *cc;
sc->cycling = 0;
if ((cc = client_current()) != NULL) {
client_mtf(cc);
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
XUngrabKeyboard(X_Dpy, CurrentTime);
}
}
static struct client_ctx *
client_next(struct client_ctx *cc)
{
@ -756,17 +752,12 @@ client_placecalc(struct client_ctx *cc)
int xslack, yslack;
if (cc->hint.flags & (USPosition | PPosition)) {
int wmax, hmax;
wmax = DisplayWidth(X_Dpy, sc->which);
hmax = DisplayHeight(X_Dpy, sc->which);
if (cc->geom.x >= wmax)
cc->geom.x = wmax - cc->bwidth - 1;
if (cc->geom.x >= sc->view.w)
cc->geom.x = sc->view.w - cc->bwidth - 1;
if (cc->geom.x + cc->geom.w + cc->bwidth <= 0)
cc->geom.x = -(cc->geom.w + cc->bwidth - 1);
if (cc->geom.y >= hmax)
cc->geom.x = hmax - cc->bwidth - 1;
if (cc->geom.y >= sc->view.h)
cc->geom.x = sc->view.h - cc->bwidth - 1;
if (cc->geom.y + cc->geom.h + cc->bwidth <= 0)
cc->geom.y = -(cc->geom.h + cc->bwidth - 1);
} else {
@ -801,7 +792,7 @@ client_placecalc(struct client_ctx *cc)
}
}
static void
void
client_mtf(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
@ -910,8 +901,9 @@ client_mwm_hints(struct client_ctx *cc)
{
struct mwm_hints *mwmh;
if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS], cwmh[_MOTIF_WM_HINTS],
MWM_HINTS_ELEMENTS, (unsigned char **)&mwmh) == MWM_HINTS_ELEMENTS) {
if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS],
cwmh[_MOTIF_WM_HINTS], MWM_HINTS_ELEMENTS,
(unsigned char **)&mwmh) == MWM_HINTS_ELEMENTS) {
if (mwmh->flags & MWM_FLAGS_DECORATIONS &&
!(mwmh->decorations & MWM_DECOR_ALL) &&
!(mwmh->decorations & MWM_DECOR_BORDER))

321
conf.c
View File

@ -25,6 +25,7 @@
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -33,7 +34,6 @@
#include "calmwm.h"
static const char *conf_bind_getmask(const char *, unsigned int *);
static void conf_cmd_remove(struct conf *, const char *);
static void conf_unbind_key(struct conf *, struct bind_ctx *);
static void conf_unbind_mouse(struct conf *, struct bind_ctx *);
@ -60,131 +60,111 @@ static const struct {
enum context context;
int flag;
} name_to_func[] = {
{ "window-menu-label", kbfunc_client_menu_label, CWM_CONTEXT_CC, 0 },
{ "window-lower", kbfunc_client_lower, CWM_CONTEXT_CC, 0 },
{ "window-raise", kbfunc_client_raise, CWM_CONTEXT_CC, 0 },
{ "window-hide", kbfunc_client_hide, CWM_CONTEXT_CC, 0 },
{ "window-delete", kbfunc_client_delete, CWM_CONTEXT_CC, 0 },
{ "window-htile", kbfunc_client_htile, CWM_CONTEXT_CC, 0 },
{ "window-vtile", kbfunc_client_vtile, CWM_CONTEXT_CC, 0 },
{ "window-stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CC, 0 },
{ "window-fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CC, 0 },
{ "window-maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CC, 0 },
{ "window-vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CC, 0 },
{ "window-hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CC, 0 },
{ "window-freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CC, 0 },
{ "window-cycle", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_FORWARD) },
{ "window-rcycle", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_REVERSE) },
{ "window-cycle-ingroup", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP) },
{ "window-rcycle-ingroup", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP) },
{ "window-group", kbfunc_client_toggle_group, CWM_CONTEXT_CC, 0 },
{ "window-movetogroup-1", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 1 },
{ "window-movetogroup-2", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 2 },
{ "window-movetogroup-3", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 3 },
{ "window-movetogroup-4", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 4 },
{ "window-movetogroup-5", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 5 },
{ "window-movetogroup-6", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 6 },
{ "window-movetogroup-7", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 7 },
{ "window-movetogroup-8", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 8 },
{ "window-movetogroup-9", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 9 },
#define FUNC_CC(t, h, n) \
#t, kbfunc_ ## h, CWM_CONTEXT_CC, n
#define FUNC_SC(t, h, n) \
#t, kbfunc_ ## h, CWM_CONTEXT_SC, n
{ "window-move", kbfunc_client_move, CWM_CONTEXT_CC, 0 },
{ "window-move-up", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_UP) },
{ "window-move-down", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_DOWN) },
{ "window-move-right", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_RIGHT) },
{ "window-move-left", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_LEFT) },
{ "window-move-up-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_UP | CWM_BIGAMOUNT) },
{ "window-move-down-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_DOWN | CWM_BIGAMOUNT) },
{ "window-move-right-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_RIGHT | CWM_BIGAMOUNT) },
{ "window-move-left-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_LEFT | CWM_BIGAMOUNT) },
{ "window-resize", kbfunc_client_resize, CWM_CONTEXT_CC, 0 },
{ "window-resize-up", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_UP) },
{ "window-resize-down", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_DOWN) },
{ "window-resize-right", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_RIGHT) },
{ "window-resize-left", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_LEFT) },
{ "window-resize-up-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_UP | CWM_BIGAMOUNT) },
{ "window-resize-down-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_DOWN | CWM_BIGAMOUNT) },
{ "window-resize-right-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_RIGHT | CWM_BIGAMOUNT) },
{ "window-resize-left-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_LEFT | CWM_BIGAMOUNT) },
{ FUNC_CC(window-lower, client_lower, 0) },
{ FUNC_CC(window-raise, client_raise, 0) },
{ FUNC_CC(window-hide, client_hide, 0) },
{ FUNC_CC(window-delete, client_delete, 0) },
{ FUNC_CC(window-htile, client_htile, 0) },
{ FUNC_CC(window-vtile, client_vtile, 0) },
{ FUNC_CC(window-stick, client_toggle_sticky, 0) },
{ FUNC_CC(window-fullscreen, client_toggle_fullscreen, 0) },
{ FUNC_CC(window-maximize, client_toggle_maximize, 0) },
{ FUNC_CC(window-vmaximize, client_toggle_vmaximize, 0) },
{ FUNC_CC(window-hmaximize, client_toggle_hmaximize, 0) },
{ FUNC_CC(window-freeze, client_toggle_freeze, 0) },
{ FUNC_CC(window-group, client_toggle_group, 0) },
{ FUNC_CC(window-movetogroup-1, client_movetogroup, 1) },
{ FUNC_CC(window-movetogroup-2, client_movetogroup, 2) },
{ FUNC_CC(window-movetogroup-3, client_movetogroup, 3) },
{ FUNC_CC(window-movetogroup-4, client_movetogroup, 4) },
{ FUNC_CC(window-movetogroup-5, client_movetogroup, 5) },
{ FUNC_CC(window-movetogroup-6, client_movetogroup, 6) },
{ FUNC_CC(window-movetogroup-7, client_movetogroup, 7) },
{ FUNC_CC(window-movetogroup-8, client_movetogroup, 8) },
{ FUNC_CC(window-movetogroup-9, client_movetogroup, 9) },
{ FUNC_CC(window-snap-up, client_snap, (CWM_UP)) },
{ FUNC_CC(window-snap-down, client_snap, (CWM_DOWN)) },
{ FUNC_CC(window-snap-right, client_snap, (CWM_RIGHT)) },
{ FUNC_CC(window-snap-left, client_snap, (CWM_LEFT)) },
{ FUNC_CC(window-snap-up-right, client_snap, (CWM_UP_RIGHT)) },
{ FUNC_CC(window-snap-up-left, client_snap, (CWM_UP_LEFT)) },
{ FUNC_CC(window-snap-down-right, client_snap, (CWM_DOWN_RIGHT)) },
{ FUNC_CC(window-snap-down-left, client_snap, (CWM_DOWN_LEFT)) },
{ FUNC_CC(window-move, client_move, 0) },
{ FUNC_CC(window-move-up, client_move, (CWM_UP)) },
{ FUNC_CC(window-move-down, client_move, (CWM_DOWN)) },
{ FUNC_CC(window-move-right, client_move, (CWM_RIGHT)) },
{ FUNC_CC(window-move-left, client_move, (CWM_LEFT)) },
{ FUNC_CC(window-move-up-big, client_move, (CWM_UP_BIG)) },
{ FUNC_CC(window-move-down-big, client_move, (CWM_DOWN_BIG)) },
{ FUNC_CC(window-move-right-big, client_move, (CWM_RIGHT_BIG)) },
{ FUNC_CC(window-move-left-big, client_move, (CWM_LEFT_BIG)) },
{ FUNC_CC(window-resize, client_resize, 0) },
{ FUNC_CC(window-resize-up, client_resize, (CWM_UP)) },
{ FUNC_CC(window-resize-down, client_resize, (CWM_DOWN)) },
{ FUNC_CC(window-resize-right, client_resize, (CWM_RIGHT)) },
{ FUNC_CC(window-resize-left, client_resize, (CWM_LEFT)) },
{ FUNC_CC(window-resize-up-big, client_resize, (CWM_UP_BIG)) },
{ FUNC_CC(window-resize-down-big, client_resize, (CWM_DOWN_BIG)) },
{ FUNC_CC(window-resize-right-big, client_resize, (CWM_RIGHT_BIG)) },
{ FUNC_CC(window-resize-left-big, client_resize, (CWM_LEFT_BIG)) },
{ FUNC_CC(window-menu-label, client_menu_label, 0) },
{ "group-cycle", kbfunc_group_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_FORWARD) },
{ "group-rcycle", kbfunc_group_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_REVERSE) },
{ "group-toggle-all", kbfunc_group_alltoggle, CWM_CONTEXT_SC, 0 },
{ "group-toggle-1", kbfunc_group_toggle, CWM_CONTEXT_SC, 1 },
{ "group-toggle-2", kbfunc_group_toggle, CWM_CONTEXT_SC, 2 },
{ "group-toggle-3", kbfunc_group_toggle, CWM_CONTEXT_SC, 3 },
{ "group-toggle-4", kbfunc_group_toggle, CWM_CONTEXT_SC, 4 },
{ "group-toggle-5", kbfunc_group_toggle, CWM_CONTEXT_SC, 5 },
{ "group-toggle-6", kbfunc_group_toggle, CWM_CONTEXT_SC, 6 },
{ "group-toggle-7", kbfunc_group_toggle, CWM_CONTEXT_SC, 7 },
{ "group-toggle-8", kbfunc_group_toggle, CWM_CONTEXT_SC, 8 },
{ "group-toggle-9", kbfunc_group_toggle, CWM_CONTEXT_SC, 9 },
{ "group-only-1", kbfunc_group_only, CWM_CONTEXT_SC, 1 },
{ "group-only-2", kbfunc_group_only, CWM_CONTEXT_SC, 2 },
{ "group-only-3", kbfunc_group_only, CWM_CONTEXT_SC, 3 },
{ "group-only-4", kbfunc_group_only, CWM_CONTEXT_SC, 4 },
{ "group-only-5", kbfunc_group_only, CWM_CONTEXT_SC, 5 },
{ "group-only-6", kbfunc_group_only, CWM_CONTEXT_SC, 6 },
{ "group-only-7", kbfunc_group_only, CWM_CONTEXT_SC, 7 },
{ "group-only-8", kbfunc_group_only, CWM_CONTEXT_SC, 8 },
{ "group-only-9", kbfunc_group_only, CWM_CONTEXT_SC, 9 },
{ FUNC_SC(window-cycle, client_cycle, (CWM_CYCLE_FORWARD)) },
{ FUNC_SC(window-rcycle, client_cycle, (CWM_CYCLE_REVERSE)) },
{ FUNC_SC(window-cycle-ingroup, client_cycle,
(CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP)) },
{ FUNC_SC(window-rcycle-ingroup, client_cycle,
(CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP)) },
{ "pointer-move-up", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_UP) },
{ "pointer-move-down", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_DOWN) },
{ "pointer-move-left", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_LEFT) },
{ "pointer-move-right", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_RIGHT) },
{ "pointer-move-up-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_UP | CWM_BIGAMOUNT) },
{ "pointer-move-down-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_DOWN | CWM_BIGAMOUNT) },
{ "pointer-move-left-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_LEFT | CWM_BIGAMOUNT) },
{ "pointer-move-right-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_RIGHT | CWM_BIGAMOUNT) },
{ FUNC_SC(group-cycle, group_cycle, (CWM_CYCLE_FORWARD)) },
{ FUNC_SC(group-rcycle, group_cycle, (CWM_CYCLE_REVERSE)) },
{ FUNC_SC(group-toggle-all, group_alltoggle, 0) },
{ FUNC_SC(group-toggle-1, group_toggle, 1) },
{ FUNC_SC(group-toggle-2, group_toggle, 2) },
{ FUNC_SC(group-toggle-3, group_toggle, 3) },
{ FUNC_SC(group-toggle-4, group_toggle, 4) },
{ FUNC_SC(group-toggle-5, group_toggle, 5) },
{ FUNC_SC(group-toggle-6, group_toggle, 6) },
{ FUNC_SC(group-toggle-7, group_toggle, 7) },
{ FUNC_SC(group-toggle-8, group_toggle, 8) },
{ FUNC_SC(group-toggle-9, group_toggle, 9) },
{ FUNC_SC(group-only-1, group_only, 1) },
{ FUNC_SC(group-only-2, group_only, 2) },
{ FUNC_SC(group-only-3, group_only, 3) },
{ FUNC_SC(group-only-4, group_only, 4) },
{ FUNC_SC(group-only-5, group_only, 5) },
{ FUNC_SC(group-only-6, group_only, 6) },
{ FUNC_SC(group-only-7, group_only, 7) },
{ FUNC_SC(group-only-8, group_only, 8) },
{ FUNC_SC(group-only-9, group_only, 9) },
{ "menu-cmd", kbfunc_menu_cmd, CWM_CONTEXT_SC, 0 },
{ "menu-group", kbfunc_menu_group, CWM_CONTEXT_SC, 0 },
{ "menu-ssh", kbfunc_menu_ssh, CWM_CONTEXT_SC, 0 },
{ "menu-window", kbfunc_menu_client, CWM_CONTEXT_SC,
CWM_MENU_WINDOW_ALL },
{ "menu-window-hidden", kbfunc_menu_client, CWM_CONTEXT_SC,
CWM_MENU_WINDOW_HIDDEN },
{ "menu-exec", kbfunc_menu_exec, CWM_CONTEXT_SC,
CWM_MENU_EXEC_EXEC },
{ "menu-exec-wm", kbfunc_menu_exec, CWM_CONTEXT_SC,
CWM_MENU_EXEC_WM },
{ FUNC_SC(pointer-move-up, ptrmove, (CWM_UP)) },
{ FUNC_SC(pointer-move-down, ptrmove, (CWM_DOWN)) },
{ FUNC_SC(pointer-move-left, ptrmove, (CWM_LEFT)) },
{ FUNC_SC(pointer-move-right, ptrmove, (CWM_RIGHT)) },
{ FUNC_SC(pointer-move-up-big, ptrmove, (CWM_UP_BIG)) },
{ FUNC_SC(pointer-move-down-big, ptrmove, (CWM_DOWN_BIG)) },
{ FUNC_SC(pointer-move-left-big, ptrmove, (CWM_LEFT_BIG)) },
{ FUNC_SC(pointer-move-right-big, ptrmove, (CWM_RIGHT_BIG)) },
{ "terminal", kbfunc_exec_term, CWM_CONTEXT_SC, 0 },
{ "lock", kbfunc_exec_lock, CWM_CONTEXT_SC, 0 },
{ "restart", kbfunc_cwm_status, CWM_CONTEXT_SC, CWM_EXEC_WM },
{ "quit", kbfunc_cwm_status, CWM_CONTEXT_SC, CWM_QUIT },
{ FUNC_SC(menu-cmd, menu_cmd, 0) },
{ FUNC_SC(menu-group, menu_group, 0) },
{ FUNC_SC(menu-ssh, menu_ssh, 0) },
{ FUNC_SC(menu-window, menu_client, CWM_MENU_WINDOW_ALL) },
{ FUNC_SC(menu-window-hidden, menu_client, CWM_MENU_WINDOW_HIDDEN) },
{ FUNC_SC(menu-exec, menu_exec, 0) },
{ FUNC_SC(menu-exec-wm, menu_wm, 0) },
{ FUNC_SC(terminal, exec_term, 0) },
{ FUNC_SC(lock, exec_lock, 0) },
{ FUNC_SC(restart, cwm_status, CWM_EXEC_WM) },
{ FUNC_SC(quit, cwm_status, CWM_QUIT) },
};
static unsigned int ignore_mods[] = {
0, LockMask, Mod2Mask, Mod2Mask | LockMask
@ -269,6 +249,8 @@ mouse_binds[] = {
void
conf_init(struct conf *c)
{
const char *home;
struct passwd *pw;
unsigned int i;
c->stickygroups = 0;
@ -279,10 +261,11 @@ conf_init(struct conf *c)
c->nameqlen = 5;
TAILQ_INIT(&c->ignoreq);
TAILQ_INIT(&c->cmdq);
TAILQ_INIT(&c->keybindq);
TAILQ_INIT(&c->autogroupq);
TAILQ_INIT(&c->keybindq);
TAILQ_INIT(&c->mousebindq);
TAILQ_INIT(&c->cmdq);
TAILQ_INIT(&c->wmq);
for (i = 0; i < nitems(key_binds); i++)
conf_bind_key(c, key_binds[i].key, key_binds[i].func);
@ -295,12 +278,21 @@ conf_init(struct conf *c)
conf_cmd_add(c, "lock", "xlock");
conf_cmd_add(c, "term", "xterm");
(void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s",
homedir, ".ssh/known_hosts");
conf_wm_add(c, "cwm", "cwm");
c->font = xstrdup("sans-serif:pixelsize=14:bold");
c->wmname = xstrdup("CWM");
home = getenv("HOME");
if ((home == NULL) || (*home == '\0')) {
pw = getpwuid(getuid());
if (pw != NULL && pw->pw_dir != NULL && *pw->pw_dir != '\0')
home = pw->pw_dir;
else
home = "/";
}
xasprintf(&c->conf_file, "%s/%s", home, ".cwmrc");
xasprintf(&c->known_hosts, "%s/%s", home, ".ssh/known_hosts");
}
void
@ -309,14 +301,21 @@ conf_clear(struct conf *c)
struct autogroup *ag;
struct bind_ctx *kb, *mb;
struct winname *wn;
struct cmd_ctx *cmd;
struct cmd_ctx *cmd, *wm;
int i;
while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) {
TAILQ_REMOVE(&c->cmdq, cmd, entry);
free(cmd->name);
free(cmd->path);
free(cmd);
}
while ((wm = TAILQ_FIRST(&c->wmq)) != NULL) {
TAILQ_REMOVE(&c->wmq, wm, entry);
free(wm->name);
free(wm->path);
free(wm);
}
while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) {
TAILQ_REMOVE(&c->keybindq, kb, entry);
free(kb);
@ -339,40 +338,50 @@ conf_clear(struct conf *c)
for (i = 0; i < CWM_COLOR_NITEMS; i++)
free(c->color[i]);
free(c->conf_file);
free(c->known_hosts);
free(c->font);
free(c->wmname);
}
int
void
conf_cmd_add(struct conf *c, const char *name, const char *path)
{
struct cmd_ctx *cmd;
struct cmd_ctx *cmd, *cmdtmp = NULL, *cmdnxt;
cmd = xmalloc(sizeof(*cmd));
cmd->name = xstrdup(name);
if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= sizeof(cmd->path)) {
free(cmd->name);
free(cmd);
return(0);
}
conf_cmd_remove(c, name);
cmd->path = xstrdup(path);
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
return(1);
}
static void
conf_cmd_remove(struct conf *c, const char *name)
{
struct cmd_ctx *cmd = NULL, *cmdnxt;
TAILQ_FOREACH_SAFE(cmd, &c->cmdq, entry, cmdnxt) {
if (strcmp(cmd->name, name) == 0) {
TAILQ_REMOVE(&c->cmdq, cmd, entry);
free(cmd->name);
free(cmd);
TAILQ_FOREACH_SAFE(cmdtmp, &c->cmdq, entry, cmdnxt) {
if (strcmp(cmdtmp->name, name) == 0) {
TAILQ_REMOVE(&c->cmdq, cmdtmp, entry);
free(cmdtmp->name);
free(cmdtmp->path);
free(cmdtmp);
}
}
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
}
void
conf_wm_add(struct conf *c, const char *name, const char *path)
{
struct cmd_ctx *wm, *wmtmp = NULL, *wmnxt;
wm = xmalloc(sizeof(*wm));
wm->name = xstrdup(name);
wm->path = xstrdup(path);
TAILQ_FOREACH_SAFE(wmtmp, &c->cmdq, entry, wmnxt) {
if (strcmp(wmtmp->name, name) == 0) {
TAILQ_REMOVE(&c->wmq, wmtmp, entry);
free(wmtmp->name);
free(wmtmp->path);
free(wmtmp);
}
}
TAILQ_INSERT_TAIL(&c->wmq, wm, entry);
}
void
@ -442,8 +451,6 @@ conf_screen(struct screen_ctx *sc)
{
unsigned int i;
XftColor xc;
Colormap colormap = DefaultColormap(X_Dpy, sc->which);
Visual *visual = DefaultVisual(X_Dpy, sc->which);
sc->gap = Conf.gap;
sc->snapdist = Conf.snapdist;
@ -460,18 +467,18 @@ conf_screen(struct screen_ctx *sc)
xu_xorcolor(sc->xftcolor[CWM_COLOR_MENU_BG],
sc->xftcolor[CWM_COLOR_MENU_FG], &xc);
xu_xorcolor(sc->xftcolor[CWM_COLOR_MENU_FONT], xc, &xc);
if (!XftColorAllocValue(X_Dpy, visual, colormap,
if (!XftColorAllocValue(X_Dpy, sc->visual, sc->colormap,
&xc.color, &sc->xftcolor[CWM_COLOR_MENU_FONT_SEL]))
warnx("XftColorAllocValue: %s", Conf.color[i]);
break;
}
if (XftColorAllocName(X_Dpy, visual, colormap,
if (XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
Conf.color[i], &xc)) {
sc->xftcolor[i] = xc;
XftColorFree(X_Dpy, visual, colormap, &xc);
XftColorFree(X_Dpy, sc->visual, sc->colormap, &xc);
} else {
warnx("XftColorAllocName: %s", Conf.color[i]);
XftColorAllocName(X_Dpy, visual, colormap,
XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
color_binds[i], &sc->xftcolor[i]);
}
}
@ -481,7 +488,8 @@ conf_screen(struct screen_ctx *sc)
sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
sc->menu.xftdraw = XftDrawCreate(X_Dpy, sc->menu.win, visual, colormap);
sc->menu.xftdraw = XftDrawCreate(X_Dpy, sc->menu.win,
sc->visual, sc->colormap);
if (sc->menu.xftdraw == NULL)
errx(1, "%s: XftDrawCreate", __func__);
@ -702,9 +710,10 @@ static char *ewmhints[] = {
"_NET_WM_STATE_HIDDEN",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_NET_WM_STATE_SKIP_PAGER",
"_NET_WM_STATE_SKIP_TASKBAR",
"_CWM_WM_STATE_FREEZE",
};
void
conf_atoms(void)
{

16
cwm.1
View File

@ -23,6 +23,7 @@
.Sh SYNOPSIS
.\" For a program: program [-abc] file ...
.Nm cwm
.Op Fl v
.Op Fl c Ar file
.Op Fl d Ar display
.Sh DESCRIPTION
@ -47,6 +48,11 @@ however,
will continue to process the rest of the configuration file.
.It Fl d Ar display
Specify the display to use.
.It Fl v
Verbose mode.
Multiple
.Fl v
options increase the verbosity.
.El
.Pp
.Nm
@ -143,7 +149,7 @@ will be executed via the configured terminal emulator.
.It Ic CM-w
Spawn
.Dq exec WindowManager
dialog, allowing a switch to another window manager.
menu, allowing a switch to another window manager.
.It Ic CMS-r
Restart.
.It Ic CMS-q
@ -184,6 +190,14 @@ List all available items.
.It Ic [Esc]
Cancel.
.El
.Pp
.Nm
rereads its configuration file when it receives a hangup signal,
.Dv SIGHUP ,
by executing itself with the name and arguments with which it was started.
This is equivalent to the
.Ar restart
function.
.Sh SEARCH
.Nm
features the ability to search for windows by their current title,

22
cwmrc.5
View File

@ -245,6 +245,12 @@ A special
keyword
.Dq all
can be used to unbind all buttons.
.It Ic wm Ar name path
Every
.Ar name
entry is shown in the wm menu.
When selected, the window manager is replaced by
.Ar path .
.El
.Sh BIND FUNCTION LIST
.Bl -tag -width 23n -compact
@ -398,6 +404,22 @@ pixels right.
Resize window 10 times
.Ar moveamount
pixels left.
.It window-snap-up
Snap window to top edge.
.It window-snap-down
Snap window to bottom edge.
.It window-snap-right
Snap window to right edge.
.It window-snap-left
Snap window to left edge.
.It window-snap-up-right
Snap window to top-right corner.
.It window-snap-up-left
Snap window to top-left corner.
.It window-snap-down-right
Snap window to bottom-right corner.
.It window-snap-down-left
Snap window to bottom-left corner.
.It pointer-move-up
Move pointer
.Ar moveamount

15
group.c
View File

@ -155,7 +155,7 @@ group_movetogroup(struct client_ctx *cc, int idx)
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
errx(1, "%s: index out of range (%d)", __func__, idx);
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)
@ -170,7 +170,7 @@ group_movetogroup(struct client_ctx *cc, int idx)
}
void
group_toggle_membership_enter(struct client_ctx *cc)
group_toggle_membership(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct group_ctx *gc = sc->group_active;
@ -186,13 +186,6 @@ group_toggle_membership_enter(struct client_ctx *cc)
client_draw_border(cc);
}
void
group_toggle_membership_leave(struct client_ctx *cc)
{
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
}
int
group_holds_only_sticky(struct group_ctx *gc)
{
@ -223,7 +216,7 @@ group_hidetoggle(struct screen_ctx *sc, int idx)
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
errx(1, "%s: index out of range (%d)", __func__, idx);
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)
@ -246,7 +239,7 @@ group_only(struct screen_ctx *sc, int idx)
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
errx(1, "%s: index out of range (%d)", __func__, idx);
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)

164
kbfunc.c
View File

@ -171,7 +171,7 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y);
while (move) {
XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev);
XMaskEvent(X_Dpy, MOUSEMASK, &ev);
switch (ev.type) {
case MotionNotify:
/* not more than 60 times / second */
@ -259,7 +259,7 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
menu_windraw(sc, cc->win, "%4d x %-4d", cc->dim.w, cc->dim.h);
while (resize) {
XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev);
XMaskEvent(X_Dpy, MOUSEMASK, &ev);
switch (ev.type) {
case MotionNotify:
/* not more than 60 times / second */
@ -289,6 +289,42 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
client_ptr_inbound(cc, 0);
}
void
kbfunc_client_snap(void *ctx, struct cargs *cargs)
{
struct client_ctx *cc = ctx;
struct screen_ctx *sc = cc->sc;
struct geom area;
int flags;
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
flags = cargs->flag;
while (flags) {
if (flags & CWM_UP) {
cc->geom.y = area.y;
flags &= ~CWM_UP;
}
if (flags & CWM_LEFT) {
cc->geom.x = area.x;
flags &= ~CWM_LEFT;
}
if (flags & CWM_RIGHT) {
cc->geom.x = area.x + area.w - cc->geom.w -
(cc->bwidth * 2);
flags &= ~CWM_RIGHT;
}
if (flags & CWM_DOWN) {
cc->geom.y = area.y + area.h - cc->geom.h -
(cc->bwidth * 2);
flags &= ~CWM_DOWN;
}
}
client_move(cc);
}
void
kbfunc_client_delete(void *ctx, struct cargs *cargs)
{
@ -365,7 +401,14 @@ kbfunc_client_vtile(void *ctx, struct cargs *cargs)
void
kbfunc_client_cycle(void *ctx, struct cargs *cargs)
{
client_cycle(ctx, cargs->flag);
struct screen_ctx *sc = ctx;
/* For X apps that ignore/steal events. */
if (cargs->xev == CWM_XEV_KEY)
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
client_cycle(sc, cargs->flag);
}
void
@ -373,12 +416,12 @@ kbfunc_client_toggle_group(void *ctx, struct cargs *cargs)
{
struct client_ctx *cc = ctx;
/* For X apps that steal events. */
/* For X apps that ignore/steal events. */
if (cargs->xev == CWM_XEV_KEY)
XGrabKeyboard(X_Dpy, cc->win, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
group_toggle_membership_enter(cc);
group_toggle_membership(cc);
}
void
@ -418,8 +461,11 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
struct client_ctx *cc, *old_cc;
struct menu *mi;
struct menu_q menuq;
int m = (cargs->xev == CWM_XEV_BTN);
int all = (cargs->flag & CWM_MENU_WINDOW_ALL);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
old_cc = client_current();
@ -432,15 +478,10 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
menuq_add(&menuq, cc, NULL);
}
if ((mi = menu_filter(sc, &menuq,
(m) ? NULL : "window", NULL,
((m) ? CWM_MENU_LIST : 0),
if ((mi = menu_filter(sc, &menuq, "window", NULL, mflags,
search_match_client, search_print_client)) != NULL) {
cc = (struct client_ctx *)mi->ctx;
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
else
client_raise(cc);
client_show(cc);
if (old_cc)
client_ptrsave(old_cc);
client_ptrwarp(cc);
@ -456,21 +497,21 @@ kbfunc_menu_cmd(void *ctx, struct cargs *cargs)
struct cmd_ctx *cmd;
struct menu *mi;
struct menu_q menuq;
int m = (cargs->xev == CWM_XEV_BTN);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if ((strcmp(cmd->name, "lock") == 0) ||
(strcmp(cmd->name, "term") == 0))
continue;
/* search_match_text() needs mi->text */
menuq_add(&menuq, cmd, "%s", cmd->name);
menuq_add(&menuq, cmd, NULL);
}
if ((mi = menu_filter(sc, &menuq,
(m) ? NULL : "application", NULL,
((m) ? CWM_MENU_LIST : 0),
search_match_text, search_print_cmd)) != NULL) {
if ((mi = menu_filter(sc, &menuq, "application", NULL, mflags,
search_match_cmd, search_print_cmd)) != NULL) {
cmd = (struct cmd_ctx *)mi->ctx;
u_spawn(cmd->path);
}
@ -485,18 +526,20 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
struct group_ctx *gc;
struct menu *mi;
struct menu_q menuq;
int m = (cargs->xev == CWM_XEV_BTN);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (group_holds_only_sticky(gc))
continue;
menuq_add(&menuq, gc, "%d %s", gc->num, gc->name);
menuq_add(&menuq, gc, NULL);
}
if ((mi = menu_filter(sc, &menuq,
(m) ? NULL : "group", NULL, (CWM_MENU_LIST),
search_match_text, search_print_group)) != NULL) {
if ((mi = menu_filter(sc, &menuq, "group", NULL, mflags,
search_match_group, search_print_group)) != NULL) {
gc = (struct group_ctx *)mi->ctx;
(group_holds_only_hidden(gc)) ?
group_show(gc) : group_hide(gc);
@ -505,6 +548,33 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
menuq_clear(&menuq);
}
void
kbfunc_menu_wm(void *ctx, struct cargs *cargs)
{
struct screen_ctx *sc = ctx;
struct cmd_ctx *wm;
struct menu *mi;
struct menu_q menuq;
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(wm, &Conf.wmq, entry)
menuq_add(&menuq, wm, NULL);
if ((mi = menu_filter(sc, &menuq, "wm", NULL, mflags,
search_match_wm, search_print_wm)) != NULL) {
wm = (struct cmd_ctx *)mi->ctx;
free(Conf.wm_argv);
Conf.wm_argv = xstrdup(wm->path);
cwm_status = CWM_EXEC_WM;
}
menuq_clear(&menuq);
}
void
kbfunc_menu_exec(void *ctx, struct cargs *cargs)
{
@ -513,24 +583,12 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs)
char **ap, *paths[NPATHS], *path, *pathcpy;
char tpath[PATH_MAX];
struct stat sb;
const char *label;
DIR *dirp;
struct dirent *dp;
struct menu *mi;
struct menu_q menuq;
int l, i, cmd = cargs->flag;
switch (cmd) {
case CWM_MENU_EXEC_EXEC:
label = "exec";
break;
case CWM_MENU_EXEC_WM:
label = "wm";
break;
default:
errx(1, "%s: invalid cmd %d", __func__, cmd);
/* NOTREACHED */
}
int l, i;
int mflags = (CWM_MENU_DUMMY | CWM_MENU_FILE);
TAILQ_INIT(&menuq);
@ -570,24 +628,11 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs)
}
free(path);
if ((mi = menu_filter(sc, &menuq, label, NULL,
(CWM_MENU_DUMMY | CWM_MENU_FILE),
if ((mi = menu_filter(sc, &menuq, "exec", NULL, mflags,
search_match_exec, search_print_text)) != NULL) {
if (mi->text[0] == '\0')
goto out;
switch (cmd) {
case CWM_MENU_EXEC_EXEC:
u_spawn(mi->text);
break;
case CWM_MENU_EXEC_WM:
cwm_status = CWM_EXEC_WM;
free(Conf.wm_argv);
Conf.wm_argv = xstrdup(mi->text);
break;
default:
errx(1, "%s: egad, cmd changed value!", __func__);
/* NOTREACHED */
}
u_spawn(mi->text);
}
out:
if (mi != NULL && mi->dummy)
@ -609,6 +654,7 @@ kbfunc_menu_ssh(void *ctx, struct cargs *cargs)
int l;
size_t len;
ssize_t slen;
int mflags = (CWM_MENU_DUMMY);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if (strcmp(cmd->name, "term") == 0)
@ -631,9 +677,8 @@ kbfunc_menu_ssh(void *ctx, struct cargs *cargs)
/* skip hashed hosts */
if (strncmp(buf, HASH_MARKER, strlen(HASH_MARKER)) == 0)
continue;
for (p = buf; *p != ',' && *p != ' ' && p != buf + slen; p++) {
/* do nothing */
}
for (p = buf; *p != ',' && *p != ' ' && p != buf + slen; p++)
;
/* ignore badness */
if (p - buf + 1 > sizeof(hostbuf))
continue;
@ -645,7 +690,7 @@ kbfunc_menu_ssh(void *ctx, struct cargs *cargs)
err(1, "%s", path);
(void)fclose(fp);
menu:
if ((mi = menu_filter(sc, &menuq, "ssh", NULL, (CWM_MENU_DUMMY),
if ((mi = menu_filter(sc, &menuq, "ssh", NULL, mflags,
search_match_text, search_print_text)) != NULL) {
if (mi->text[0] == '\0')
goto out;
@ -667,11 +712,12 @@ kbfunc_client_menu_label(void *ctx, struct cargs *cargs)
struct client_ctx *cc = ctx;
struct menu *mi;
struct menu_q menuq;
int mflags = (CWM_MENU_DUMMY);
TAILQ_INIT(&menuq);
/* dummy is set, so this will always return */
mi = menu_filter(cc->sc, &menuq, "label", cc->label, (CWM_MENU_DUMMY),
mi = menu_filter(cc->sc, &menuq, "label", cc->label, mflags,
search_match_text, search_print_text);
if (!mi->abort) {

74
menu.c
View File

@ -48,7 +48,6 @@ struct menu_ctx {
char searchstr[MENU_MAXENTRY + 1];
char dispstr[MENU_MAXENTRY*2 + 1];
char promptstr[MENU_MAXENTRY + 1];
int hasprompt;
int list;
int listing;
int changed;
@ -85,15 +84,13 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
struct menu *mi = NULL;
XEvent e;
Window focuswin;
int evmask, focusrevert;
int xsave, ysave, xcur, ycur;
int focusrevert, xsave, ysave, xcur, ycur;
TAILQ_INIT(&resultq);
(void)memset(&mc, 0, sizeof(mc));
xu_ptr_getpos(sc->rootwin, &xsave, &ysave);
(void)memset(&mc, 0, sizeof(mc));
mc.sc = sc;
mc.flags = flags;
mc.match = match;
@ -105,19 +102,13 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
if (mc.flags & CWM_MENU_LIST)
mc.list = 1;
(void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr));
if (initial != NULL)
(void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr));
else
mc.searchstr[0] = '\0';
evmask = MENUMASK;
if (prompt != NULL) {
evmask |= KEYMASK; /* accept keys as well */
(void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr));
mc.hasprompt = 1;
}
XSelectInput(X_Dpy, sc->menu.win, evmask);
XSelectInput(X_Dpy, sc->menu.win, MENUMASK);
XMapRaised(X_Dpy, sc->menu.win);
if (XGrabPointer(X_Dpy, sc->menu.win, False, MENUGRABMASK,
@ -137,7 +128,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
for (;;) {
mc.changed = 0;
XWindowEvent(X_Dpy, sc->menu.win, evmask, &e);
XWindowEvent(X_Dpy, sc->menu.win, MENUMASK, &e);
switch (e.type) {
case KeyPress:
@ -188,13 +179,14 @@ menu_complete_path(struct menu_ctx *mc)
struct screen_ctx *sc = mc->sc;
struct menu *mi, *mr;
struct menu_q menuq;
int mflags = (CWM_MENU_DUMMY);
mr = xcalloc(1, sizeof(*mr));
TAILQ_INIT(&menuq);
if ((mi = menu_filter(sc, &menuq, mc->searchstr, NULL,
(CWM_MENU_DUMMY), search_match_path, search_print_text)) != NULL) {
if ((mi = menu_filter(sc, &menuq, mc->searchstr, NULL, mflags,
search_match_path, search_print_text)) != NULL) {
mr->abort = mi->abort;
mr->dummy = mi->dummy;
if (mi->text[0] != '\0')
@ -343,28 +335,19 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
mc->listing = 0;
}
mc->num = 0;
mc->geom.w = 0;
mc->geom.h = 0;
if (mc->hasprompt) {
(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s%s",
mc->promptstr, PROMPT_SCHAR, mc->searchstr, PROMPT_ECHAR);
XftTextExtentsUtf8(X_Dpy, sc->xftfont,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr), &extents);
mc->geom.w = extents.xOff;
mc->geom.h = sc->xftfont->height + 1;
mc->num = 1;
}
(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s%s",
mc->promptstr, PROMPT_SCHAR, mc->searchstr, PROMPT_ECHAR);
XftTextExtentsUtf8(X_Dpy, sc->xftfont,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr), &extents);
mc->geom.w = extents.xOff;
mc->geom.h = sc->xftfont->height + 1;
mc->num = 1;
TAILQ_FOREACH(mi, resultq, resultentry) {
(*mc->print)(mi, mc->listing);
XftTextExtentsUtf8(X_Dpy, sc->xftfont,
(const FcChar8*)mi->print,
MIN(strlen(mi->print), MENU_MAXENTRY), &extents);
mc->geom.w = MAX(mc->geom.w, extents.xOff);
mc->geom.h += sc->xftfont->height + 1;
mc->num++;
@ -398,14 +381,11 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
XMoveResizeWindow(X_Dpy, sc->menu.win, mc->geom.x, mc->geom.y,
mc->geom.w, mc->geom.h);
n = 0;
if (mc->hasprompt) {
XftDrawStringUtf8(sc->menu.xftdraw,
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
0, sc->xftfont->ascent,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr));
n++;
}
n = 1;
XftDrawStringUtf8(sc->menu.xftdraw,
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
0, sc->xftfont->ascent,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr));
TAILQ_FOREACH(mi, resultq, resultentry) {
int y = n * (sc->xftfont->height + 1) + sc->xftfont->ascent + 1;
@ -420,7 +400,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
(const FcChar8*)mi->print, strlen(mi->print));
n++;
}
if (mc->hasprompt && n > 1)
if (n > 1)
menu_draw_entry(mc, resultq, 1, 1);
}
@ -430,10 +410,7 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq,
{
struct screen_ctx *sc = mc->sc;
struct menu *mi;
int color, i = 0;
if (mc->hasprompt)
i = 1;
int color, i = 1;
TAILQ_FOREACH(mi, resultq, resultentry)
if (entry == i++)
@ -474,13 +451,10 @@ static struct menu *
menu_handle_release(struct menu_ctx *mc, struct menu_q *resultq, int x, int y)
{
struct menu *mi;
int entry, i = 0;
int entry, i = 1;
entry = menu_calc_entry(mc, x, y);
if (mc->hasprompt)
i = 1;
TAILQ_FOREACH(mi, resultq, resultentry)
if (entry == i++)
break;
@ -506,7 +480,7 @@ menu_calc_entry(struct menu_ctx *mc, int x, int y)
entry < 0 || entry >= mc->num)
entry = -1;
if (mc->hasprompt && entry == 0)
if (entry == 0)
entry = -1;
return(entry);

39
parse.y
View File

@ -45,7 +45,7 @@ static struct file {
int lineno;
int errors;
} *file, *topfile;
struct file *pushfile(const char *);
struct file *pushfile(const char *, FILE *);
int popfile(void);
int yyparse(void);
int yylex(void);
@ -72,7 +72,7 @@ typedef struct {
%token BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE
%token FONTNAME STICKY GAP
%token AUTOGROUP COMMAND IGNORE
%token AUTOGROUP COMMAND IGNORE WM
%token YES NO BORDERWIDTH MOVEAMOUNT
%token COLOR SNAPDIST
%token ACTIVEBORDER INACTIVEBORDER URGENCYBORDER
@ -139,12 +139,24 @@ main : FONTNAME STRING {
conf->snapdist = $2;
}
| COMMAND STRING string {
if (!conf_cmd_add(conf, $2, $3)) {
yyerror("command name/path too long");
if (strlen($3) >= PATH_MAX) {
yyerror("%s command path too long", $2);
free($2);
free($3);
YYERROR;
}
conf_cmd_add(conf, $2, $3);
free($2);
free($3);
}
| WM STRING string {
if (strlen($3) >= PATH_MAX) {
yyerror("%s wm path too long", $2);
free($2);
free($3);
YYERROR;
}
conf_wm_add(conf, $2, $3);
free($2);
free($3);
}
@ -319,6 +331,7 @@ lookup(char *s)
{ "unbind-mouse", UNBINDMOUSE},
{ "ungroupborder", UNGROUPBORDER},
{ "urgencyborder", URGENCYBORDER},
{ "wm", WM},
{ "yes", YES}
};
const struct keywords *p;
@ -546,19 +559,13 @@ nodigits:
}
struct file *
pushfile(const char *name)
pushfile(const char *name, FILE *stream)
{
struct file *nfile;
nfile = xcalloc(1, sizeof(struct file));
nfile->name = xstrdup(name);
if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
warn("%s", nfile->name);
free(nfile->name);
free(nfile);
return (NULL);
}
nfile->stream = stream;
nfile->lineno = 1;
TAILQ_INSERT_TAIL(&files, nfile, entry);
return (nfile);
@ -583,13 +590,19 @@ popfile(void)
int
parse_config(const char *filename, struct conf *xconf)
{
FILE *stream;
int errors = 0;
conf = xconf;
if ((file = pushfile(filename)) == NULL) {
stream = fopen(filename, "r");
if (stream == NULL) {
if (errno == ENOENT)
return (0);
warn("%s", filename);
return (-1);
}
file = pushfile(filename, stream);
topfile = file;
yyparse();

View File

@ -31,13 +31,16 @@
#include "calmwm.h"
static struct geom screen_apply_gap(struct screen_ctx *, struct geom);
void
screen_init(int which)
{
struct screen_ctx *sc;
Window *wins, w0, w1, active = None;
XSetWindowAttributes rootattr;
unsigned int nwins, i;
unsigned int nwins, w;
int i;
sc = xmalloc(sizeof(*sc));
@ -47,6 +50,8 @@ screen_init(int which)
sc->which = which;
sc->rootwin = RootWindow(X_Dpy, sc->which);
sc->colormap = DefaultColormap(X_Dpy, sc->which);
sc->visual = DefaultVisual(X_Dpy, sc->which);
sc->cycling = 0;
sc->hideall = 0;
@ -77,8 +82,8 @@ screen_init(int which)
/* Deal with existing clients. */
if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) {
for (i = 0; i < nwins; i++)
(void)client_init(wins[i], sc, (active == wins[i]));
for (w = 0; w < nwins; w++)
(void)client_init(wins[w], sc, (active == wins[w]));
XFree(wins);
}
@ -143,12 +148,12 @@ struct geom
screen_area(struct screen_ctx *sc, int x, int y, enum apply_gap apply_gap)
{
struct region_ctx *rc;
struct geom area = sc->work;
struct geom area = sc->view;
TAILQ_FOREACH(rc, &sc->regionq, entry) {
if ((x >= rc->area.x) && (x < (rc->area.x + rc->area.w)) &&
(y >= rc->area.y) && (y < (rc->area.y + rc->area.h))) {
area = rc->area;
if ((x >= rc->view.x) && (x < (rc->view.x + rc->view.w)) &&
(y >= rc->view.y) && (y < (rc->view.y + rc->view.h))) {
area = rc->view;
break;
}
}
@ -190,10 +195,6 @@ screen_update_geometry(struct screen_ctx *sc)
rc = xmalloc(sizeof(*rc));
rc->num = i;
rc->area.x = ci->x;
rc->area.y = ci->y;
rc->area.w = ci->width;
rc->area.h = ci->height;
rc->view.x = ci->x;
rc->view.y = ci->y;
rc->view.w = ci->width;
@ -219,7 +220,7 @@ screen_update_geometry(struct screen_ctx *sc)
xu_ewmh_net_workarea(sc);
}
struct geom
static struct geom
screen_apply_gap(struct screen_ctx *sc, struct geom geom)
{
geom.x += sc->gap.left;

258
search.c
View File

@ -36,40 +36,66 @@
#define PATH_ANY 0x0001
#define PATH_EXEC 0x0002
static void search_match_path_type(struct menu_q *, struct menu_q *,
char *, int);
static int strsubmatch(char *, char *, int);
static void match_path_type(struct menu_q *, char *, int);
static int match_substr(char *, char *, int);
static int
match_substr(char *sub, char *str, int zeroidx)
{
size_t len, sublen;
unsigned int n, flen;
if (sub == NULL || str == NULL)
return(0);
len = strlen(str);
sublen = strlen(sub);
if (sublen > len)
return(0);
if (zeroidx)
flen = 0;
else
flen = len - sublen;
for (n = 0; n <= flen; n++)
if (strncasecmp(sub, str + n, sublen) == 0)
return(1);
return(0);
}
void
search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct winname *wn;
struct menu *mi, *tierp[4], *before = NULL;
TAILQ_INIT(resultq);
struct menu *mi, *tierp[3], *before = NULL;
struct client_ctx *cc;
struct winname *wn;
(void)memset(tierp, 0, sizeof(tierp));
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
int tier = -1, t;
struct client_ctx *cc = (struct client_ctx *)mi->ctx;
cc = (struct client_ctx *)mi->ctx;
/* Match on label. */
if (strsubmatch(search, cc->label, 0))
if (match_substr(search, cc->label, 0))
tier = 0;
/* Match on window name history, from present to past. */
if (tier < 0) {
TAILQ_FOREACH_REVERSE(wn, &cc->nameq, name_q, entry)
if (strsubmatch(search, wn->name, 0)) {
tier = 2;
if (match_substr(search, wn->name, 0)) {
tier = 1;
break;
}
}
/* Match on window resource class. */
if ((tier < 0) && strsubmatch(search, cc->ch.res_class, 0))
tier = 3;
if ((tier < 0) && match_substr(search, cc->ch.res_class, 0))
tier = 2;
if (tier < 0)
continue;
@ -82,9 +108,6 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
if ((tier > 0) && (cc->flags & CLIENT_HIDDEN))
tier--;
if (tier >= nitems(tierp))
errx(1, "%s: invalid tier", __func__);
/*
* If you have a tierp, insert after it, and make it
* the new tierp. If you don't have a tierp, find the
@ -105,27 +128,115 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
}
void
search_print_text(struct menu *mi, int listing)
search_match_cmd(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
(void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text);
struct menu *mi;
struct cmd_ctx *cmd;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
cmd = (struct cmd_ctx *)mi->ctx;
if (match_substr(search, cmd->name, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
}
void
search_print_cmd(struct menu *mi, int listing)
search_match_group(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;
struct menu *mi;
struct group_ctx *gc;
char *s;
(void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
gc = (struct group_ctx *)mi->ctx;
xasprintf(&s, "%d %s", gc->num, gc->name);
if (match_substr(search, s, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
free(s);
}
}
static void
match_path_type(struct menu_q *resultq, char *search, int flag)
{
struct menu *mi;
char *pattern;
glob_t g;
int i;
xasprintf(&pattern, "%s*", search);
if (glob(pattern, GLOB_MARK, NULL, &g) != 0)
return;
for (i = 0; i < g.gl_pathc; i++) {
if ((flag & PATH_EXEC) && access(g.gl_pathv[i], X_OK))
continue;
mi = xcalloc(1, sizeof(*mi));
(void)strlcpy(mi->text, g.gl_pathv[i], sizeof(mi->text));
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
globfree(&g);
free(pattern);
}
void
search_print_group(struct menu *mi, int listing)
search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct group_ctx *gc = (struct group_ctx *)mi->ctx;
struct menu *mi, *mj;
int r;
(void)snprintf(mi->print, sizeof(mi->print),
(group_holds_only_hidden(gc)) ? "%d: [%s]" : "%d: %s",
gc->num, gc->name);
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
if (match_substr(search, mi->text, 1) == 0 &&
fnmatch(search, mi->text, 0) == FNM_NOMATCH)
continue;
TAILQ_FOREACH(mj, resultq, resultentry) {
r = strcmp(mi->text, mj->text);
if (r < 0)
TAILQ_INSERT_BEFORE(mj, mi, resultentry);
if (r <= 0)
break;
}
if (mj == NULL)
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
if (TAILQ_EMPTY(resultq))
match_path_type(resultq, search, PATH_EXEC);
}
void
search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
TAILQ_INIT(resultq);
match_path_type(resultq, search, PATH_ANY);
}
void
search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct menu *mi;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
if (match_substr(search, mi->text, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
}
void
search_match_wm(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct menu *mi;
struct cmd_ctx *wm;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
wm = (struct cmd_ctx *)mi->ctx;
if ((match_substr(search, wm->name, 0)) ||
(match_substr(search, wm->path, 0)))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
}
void
@ -144,100 +255,35 @@ search_print_client(struct menu *mi, int listing)
(cc->label) ? cc->label : "", cc->name);
}
static void
search_match_path_type(struct menu_q *menuq, struct menu_q *resultq,
char *search, int flag)
void
search_print_cmd(struct menu *mi, int listing)
{
struct menu *mi;
char pattern[PATH_MAX];
glob_t g;
int i;
struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;
(void)strlcpy(pattern, search, sizeof(pattern));
(void)strlcat(pattern, "*", sizeof(pattern));
if (glob(pattern, GLOB_MARK, NULL, &g) != 0)
return;
for (i = 0; i < g.gl_pathc; i++) {
if ((flag & PATH_EXEC) && access(g.gl_pathv[i], X_OK))
continue;
mi = xcalloc(1, sizeof(*mi));
(void)strlcpy(mi->text, g.gl_pathv[i], sizeof(mi->text));
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
globfree(&g);
(void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);
}
void
search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search)
search_print_group(struct menu *mi, int listing)
{
TAILQ_INIT(resultq);
struct group_ctx *gc = (struct group_ctx *)mi->ctx;
search_match_path_type(menuq, resultq, search, PATH_ANY);
(void)snprintf(mi->print, sizeof(mi->print),
(group_holds_only_hidden(gc)) ? "%d: [%s]" : "%d: %s",
gc->num, gc->name);
}
void
search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
search_print_text(struct menu *mi, int listing)
{
struct menu *mi;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry)
if (strsubmatch(search, mi->text, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
(void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text);
}
void
search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)
search_print_wm(struct menu *mi, int listing)
{
struct menu *mi, *mj;
int r;
struct cmd_ctx *wm = (struct cmd_ctx *)mi->ctx;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
if (strsubmatch(search, mi->text, 1) == 0 &&
fnmatch(search, mi->text, 0) == FNM_NOMATCH)
continue;
TAILQ_FOREACH(mj, resultq, resultentry) {
r = strcmp(mi->text, mj->text);
if (r < 0)
TAILQ_INSERT_BEFORE(mj, mi, resultentry);
if (r <= 0)
break;
}
if (mj == NULL)
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
if (TAILQ_EMPTY(resultq))
search_match_path_type(menuq, resultq, search, PATH_EXEC);
}
static int
strsubmatch(char *sub, char *str, int zeroidx)
{
size_t len, sublen;
unsigned int n, flen;
if (sub == NULL || str == NULL)
return(0);
len = strlen(str);
sublen = strlen(sub);
if (sublen > len)
return(0);
if (!zeroidx)
flen = len - sublen;
else
flen = 0;
for (n = 0; n <= flen; n++)
if (strncasecmp(sub, str + n, sublen) == 0)
return(1);
return(0);
(void)snprintf(mi->print, sizeof(mi->print), "%s [%s]",
wm->name, wm->path);
}

36
util.c
View File

@ -31,13 +31,15 @@
#include "calmwm.h"
static void log_msg(const char *, va_list);
void
u_spawn(char *argstr)
{
switch (fork()) {
case 0:
u_exec(argstr);
break;
exit(1);
case -1:
warn("fork");
default:
@ -78,7 +80,7 @@ u_exec(char *argstr)
(void)setsid();
(void)execvp(args[0], args);
err(1, "%s", s);
warn("%s", s);
}
char *
@ -104,3 +106,33 @@ u_argv(char * const *argv)
}
return(p);
}
static void
log_msg(const char *msg, va_list ap)
{
char *fmt;
if (asprintf(&fmt, "%s\n", msg) == -1) {
vfprintf(stderr, msg, ap);
fprintf(stderr, "\n");
} else {
vfprintf(stderr, fmt, ap);
free(fmt);
}
fflush(stderr);
}
void
log_debug(int level, const char *func, const char *msg, ...)
{
char *fmt;
va_list ap;
if (Conf.debug < level)
return;
va_start(ap, msg);
xasprintf(&fmt, "debug%d: %s: %s", level, func, msg);
log_msg(fmt, ap);
va_end(ap);
}

View File

@ -77,6 +77,8 @@ xev_handle_maprequest(XEvent *ee)
XMapRequestEvent *e = &ee->xmaprequest;
struct client_ctx *cc = NULL, *old_cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
@ -93,6 +95,8 @@ xev_handle_unmapnotify(XEvent *ee)
XUnmapEvent *e = &ee->xunmap;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL) {
if (e->send_event) {
client_set_wm_state(cc, WithdrawnState);
@ -109,6 +113,8 @@ xev_handle_destroynotify(XEvent *ee)
XDestroyWindowEvent *e = &ee->xdestroywindow;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL)
client_delete(cc);
}
@ -121,6 +127,8 @@ xev_handle_configurerequest(XEvent *ee)
struct screen_ctx *sc;
XWindowChanges wc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL) {
sc = cc->sc;
@ -174,6 +182,8 @@ xev_handle_propertynotify(XEvent *ee)
struct screen_ctx *sc;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL) {
switch (e->atom) {
case XA_WM_NORMAL_HINTS:
@ -209,6 +219,8 @@ xev_handle_enternotify(XEvent *ee)
XCrossingEvent *e = &ee->xcrossing;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
Last_Event_Time = e->time;
if ((cc = client_find(e->window)) != NULL)
@ -223,6 +235,8 @@ xev_handle_buttonpress(XEvent *ee)
struct screen_ctx *sc;
struct bind_ctx *mb;
LOG_DEBUG3("window: 0x%lx", e->window);
e->state &= ~IGNOREMODMASK;
TAILQ_FOREACH(mb, &Conf.mousebindq, entry) {
@ -259,9 +273,13 @@ xev_handle_buttonrelease(XEvent *ee)
XButtonEvent *e = &ee->xbutton;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", ee->xbutton.window);
if ((cc = client_find(e->window)) != NULL) {
if (cc->flags & CLIENT_ACTIVE)
group_toggle_membership_leave(cc);
if (cc->flags & (CLIENT_ACTIVE | CLIENT_HIGHLIGHT)) {
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
}
}
}
@ -275,6 +293,8 @@ xev_handle_keypress(XEvent *ee)
KeySym keysym, skeysym;
unsigned int modshift;
LOG_DEBUG3("window: 0x%lx", e->window);
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1);
@ -322,16 +342,29 @@ xev_handle_keyrelease(XEvent *ee)
{
XKeyEvent *e = &ee->xkey;
struct screen_ctx *sc;
struct client_ctx *cc;
KeySym keysym;
unsigned int i;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((sc = screen_find(e->root)) == NULL)
return;
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
for (i = 0; i < nitems(modkeys); i++) {
if (keysym == modkeys[i]) {
client_cycle_leave(sc);
if ((cc = client_current()) != NULL) {
if (sc->cycling) {
sc->cycling = 0;
client_mtf(cc);
}
if (cc->flags & CLIENT_HIGHLIGHT) {
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
}
}
XUngrabKeyboard(X_Dpy, CurrentTime);
break;
}
}
@ -344,6 +377,8 @@ xev_handle_clientmessage(XEvent *ee)
struct client_ctx *cc, *old_cc;
struct screen_ctx *sc;
LOG_DEBUG3("window: 0x%lx", e->window);
if (e->message_type == cwmh[WM_CHANGE_STATE]) {
if ((cc = client_find(e->window)) != NULL) {
if (e->data.l[0] == IconicState)
@ -357,10 +392,7 @@ xev_handle_clientmessage(XEvent *ee)
if ((cc = client_find(e->window)) != NULL) {
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
else
client_raise(cc);
client_show(cc);
client_ptrwarp(cc);
}
} else if (e->message_type == ewmh[_NET_WM_DESKTOP]) {
@ -394,6 +426,8 @@ xev_handle_randr(XEvent *ee)
struct screen_ctx *sc;
int i;
LOG_DEBUG3("new size: %d/%d", rev->width, rev->height);
i = XRRRootToScreen(X_Dpy, rev->root);
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->which == i) {
@ -414,6 +448,8 @@ xev_handle_mappingnotify(XEvent *ee)
XMappingEvent *e = &ee->xmapping;
struct screen_ctx *sc;
LOG_DEBUG3("window: 0x%lx", e->window);
XRefreshKeyboardMapping(e);
if (e->request == MappingKeyboard) {
TAILQ_FOREACH(sc, &Screenq, entry)
@ -427,6 +463,8 @@ xev_handle_expose(XEvent *ee)
XExposeEvent *e = &ee->xexpose;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL && e->count == 0)
client_draw_border(cc);
}
@ -436,9 +474,11 @@ xev_process(void)
{
XEvent e;
XNextEvent(X_Dpy, &e);
if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify)
xev_handle_randr(&e);
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
(*xev_handlers[e.type])(&e);
while (XPending(X_Dpy)) {
XNextEvent(X_Dpy, &e);
if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify)
xev_handle_randr(&e);
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
(*xev_handlers[e.type])(&e);
}
}

16
xutil.c
View File

@ -368,6 +368,12 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
{ _NET_WM_STATE_DEMANDS_ATTENTION,
CLIENT_URGENCY,
client_urgency },
{ _NET_WM_STATE_SKIP_PAGER,
CLIENT_SKIP_PAGER,
client_toggle_skip_pager},
{ _NET_WM_STATE_SKIP_TASKBAR,
CLIENT_SKIP_TASKBAR,
client_toggle_skip_taskbar},
{ _CWM_WM_STATE_FREEZE,
CLIENT_FREEZE,
client_toggle_freeze },
@ -412,6 +418,10 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
client_toggle_fullscreen(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
client_urgency(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_SKIP_PAGER])
client_toggle_skip_pager(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_SKIP_TASKBAR])
client_toggle_skip_taskbar(cc);
if (atoms[i] == ewmh[_CWM_WM_STATE_FREEZE])
client_toggle_freeze(cc);
}
@ -433,6 +443,8 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
oatoms[i] != ewmh[_NET_WM_STATE_HIDDEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION] &&
oatoms[i] != ewmh[_NET_WM_STATE_SKIP_PAGER] &&
oatoms[i] != ewmh[_NET_WM_STATE_SKIP_TASKBAR] &&
oatoms[i] != ewmh[_CWM_WM_STATE_FREEZE])
atoms[j++] = oatoms[i];
}
@ -451,6 +463,10 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
}
if (cc->flags & CLIENT_URGENCY)
atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION];
if (cc->flags & CLIENT_SKIP_PAGER)
atoms[j++] = ewmh[_NET_WM_STATE_SKIP_PAGER];
if (cc->flags & CLIENT_SKIP_TASKBAR)
atoms[j++] = ewmh[_NET_WM_STATE_SKIP_TASKBAR];
if (cc->flags & CLIENT_FREEZE)
atoms[j++] = ewmh[_CWM_WM_STATE_FREEZE];
if (j > 0)