summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--config.h7
-rw-r--r--mcwm.c93
-rw-r--r--mcwm.man27
4 files changed, 87 insertions, 48 deletions
diff --git a/NEWS b/NEWS
index 46f0b1e..fd9e18e 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,14 @@
User visible changes
+2011-11-22
+
+ * Now optionally starts programs when MODKEY + mouse buttons are
+ pressed on root window. See config.h for configuration and the
+ manual page for an example.
+
+ Also simplified starting programs.
+
2011-11-17
* In a ConfigureRequest we no longer obey window movements not
diff --git a/config.h b/config.h
index 35176a7..0291b11 100644
--- a/config.h
+++ b/config.h
@@ -33,6 +33,13 @@
#define TERMINAL "urxvt"
/*
+ * Start these programs when pressing MODKEY and mouse buttons on root window.
+ */
+#define MOUSE1 ""
+#define MOUSE2 ""
+#define MOUSE3 "mcmenu"
+
+/*
* Default colour on border for focused windows. Can be set from
* command line with "-f colour".
*/
diff --git a/mcwm.c b/mcwm.c
index 613d53e..0613c9f 100644
--- a/mcwm.c
+++ b/mcwm.c
@@ -326,7 +326,7 @@ static struct client *findclient(xcb_drawable_t win);
static void focusnext(void);
static void setunfocus(xcb_drawable_t win);
static void setfocus(struct client *client);
-static int start_terminal(void);
+static int start(char *program);
static void resizelim(struct client *client);
static void moveresize(xcb_drawable_t win, uint16_t x, uint16_t y,
uint16_t width, uint16_t height);
@@ -2085,15 +2085,10 @@ void setfocus(struct client *client)
focuswin = client;
}
-/*
- * Start a program specified in conf.terminal.
- *
- * Returns 0 on success.
- */
-int start_terminal(void)
+int start(char *program)
{
pid_t pid;
-
+
pid = fork();
if (-1 == pid)
{
@@ -2102,10 +2097,10 @@ int start_terminal(void)
}
else if (0 == pid)
{
- pid_t termpid;
-
- /* In our first child. */
+ char *argv[2];
+ /* In the child. */
+
/*
* Make this process a new process leader, otherwise the
* terminal will die when the wm dies. Also, this makes any
@@ -2117,39 +2112,15 @@ int start_terminal(void)
exit(1);
}
- /*
- * Fork again for the terminal process. This way, the wm won't
- * know anything about it.
- */
- termpid = fork();
- if (-1 == termpid)
+ argv[0] = program;
+ argv[1] = NULL;
+
+ if (-1 == execvp(program, argv))
{
- perror("fork");
+ perror("execve");
exit(1);
}
- else if (0 == termpid)
- {
- char *argv[2];
-
- /* In the second child, now starting terminal. */
-
- argv[0] = conf.terminal;
- argv[1] = NULL;
-
- if (-1 == execvp(conf.terminal, argv))
- {
- perror("execve");
- exit(1);
- }
- } /* second child */
-
- /* Exit our first child so the wm can pick up and continue. */
exit(0);
- } /* first child */
- else
- {
- /* Wait for the first forked process to exit. */
- waitpid(pid, NULL, 0);
}
return 0;
@@ -3010,7 +2981,7 @@ void handle_keypress(xcb_key_press_event_t *ev)
switch (key)
{
case KEY_RET: /* return */
- start_terminal();
+ start(conf.terminal);
break;
case KEY_F: /* f */
@@ -3486,6 +3457,32 @@ void events(void)
e->detail, (long)e->event, e->child, e->event_x,
e->event_y);
+ if (0 == e->child)
+ {
+ /* Mouse click on root window. Start programs? */
+
+ switch (e->detail)
+ {
+ case 1: /* Mouse button one. */
+ start(MOUSE1);
+ break;
+
+ case 2: /* Middle mouse button. */
+ start(MOUSE2);
+ break;
+
+ case 3: /* Mouse button three. */
+ start(MOUSE3);
+ break;
+
+ default:
+ break;
+ } /* switch */
+
+ /* Break out of event switch. */
+ break;
+ }
+
/*
* If we don't have any currently focused window, we can't
* do anything. We don't want to do anything if the mouse
@@ -3498,11 +3495,6 @@ void events(void)
}
/*
- * XXX if 0 == e->child, we're on the root window. Do
- * something on the root when mouse buttons are pressed?
- */
-
- /*
* If middle button was pressed, raise window or lower
* it if it was already on top.
*/
@@ -4004,6 +3996,13 @@ int main(int argc, char **argv)
/* Install signal handlers. */
+ /* We ignore child exists. Don't create zombies. */
+ if (SIG_ERR == signal(SIGCHLD, SIG_IGN))
+ {
+ perror("mcwm: signal");
+ exit(1);
+ }
+
if (SIG_ERR == signal(SIGINT, sigcatch))
{
perror("mcwm: signal");
@@ -4111,7 +4110,7 @@ int main(int argc, char **argv)
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
1 /* left mouse button */,
MOUSEMODKEY);
-
+
xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
diff --git a/mcwm.man b/mcwm.man
index 5b234db..1f4ebf7 100644
--- a/mcwm.man
+++ b/mcwm.man
@@ -147,7 +147,10 @@ cursor. Of course, changing workspaces has nothing to do with the
focused window.
.PP
If you don't like the default key bindings, border width, et cetera,
-look in the config.h file, change and recompile.
+look in the config.h file, change and recompile. In the config.h file
+you can also define mouse button actions on the root window. By
+default button 3 starts the command mcmenu. You can write your own
+mcmenu by using, for instance, 9menu or ratmenu.
.PP
.SH STARTING
Typically the window manager is started from a script, either run by
@@ -179,5 +182,27 @@ exec urxvt
.fi
.in -4
.sp
+.PP
+You may also want to define an mcmenu program for use with mcwm.
+Here's a complete example using the 9menu program:
+.sp
+.in +4
+.nf
+\&#! /bin/sh
+9menu -bg black -fg white \\
+ -popup \\
+ 'cpu:urxvt -e ssh cpu.example.org' \\
+ ':' \\
+ 'VGA On: xrandr --output VGA --on' \\
+ 'VGA Off: xrandr --output VGA --off' \\
+ 'VGA Above: xrandr --output VGA --auto --above LVDS' \\
+ ':' \\
+ 'HHKB: xkbcomp -I$HOME/conf/xkb $HOME/conf/xkb/hhkb.xkb $DISPLAY' \\
+ 'Thinkpad: xmodmap /home/mc/lib/xmodmap/thinkpad-x60.xmodmap' \\
+ ':' \\
+ 'close:'
+.fi
+.in -4
+.sp
.SH AUTHOR
Michael Cardell Widerkrantz <mc@hack.org>.