Hi again,

The attached patch allows you to assign functions to mouse clicks on the
tag indicators in the status bar. The default actions are:

    * left click to toggle viewing that tag
    * left double click to view only that tag
    * middle click to view all tags
    * right click to toggle assignment of the current client to that tag

I want to expand the functionality to include the ability to assign
functions to mouse clicks on other parts of the status bar, such as
clicking on the layout indicator to cycle through the layouts, and
clicking on the text area to create a new client. But, this will be much
cleaner and require much less code if we switch the mouse handling to be
more like that of the current dwm code.

So, I've attached this patch as is, with its functionality for pressing
just on the tag indicators in the status bar, but I'm stopping there and
will work on rewriting the mouse handling in general within dvtm.

Feedback appreciated! -Ross

diff --git a/config.def.h b/config.def.h
index b0a68d4..fe8dedd 100644
--- a/config.def.h
+++ b/config.def.h
@@ -192,6 +192,13 @@ static Button buttons[] = {
 	{ BUTTON2_CLICKED,        { mouse_zoom,       { NULL  } } },
 	{ BUTTON3_CLICKED,        { mouse_minimize,   { NULL  } } },
 };
+
+static Button tag_buttons[] = {
+	{ BUTTON1_CLICKED,        { mouse_toggleview, { NULL  } } },
+	{ BUTTON1_DOUBLE_CLICKED, { mouse_view,       { NULL  } } },
+	{ BUTTON2_CLICKED,        { view,             { NULL  } } },
+	{ BUTTON3_CLICKED,        { mouse_toggletag,  { NULL  } } },
+};
 #endif /* CONFIG_MOUSE */
 
 static Cmd commands[] = {
diff --git a/dvtm.c b/dvtm.c
index 464a223..c01f006 100644
--- a/dvtm.c
+++ b/dvtm.c
@@ -210,6 +210,9 @@ static void mouse_focus(const char *args[]);
 static void mouse_fullscreen(const char *args[]);
 static void mouse_minimize(const char *args[]);
 static void mouse_zoom(const char *args[]);
+static void mouse_toggleview(const char *args[]);
+static void mouse_view(const char *args[]);
+static void mouse_toggletag(const char *args[]);
 
 /* functions and variables available to layouts via config.h */
 static Client* nextvisible(Client *c);
@@ -231,6 +234,7 @@ static Client *lastsel = NULL;
 static Client *msel = NULL;
 static unsigned int seltags;
 static unsigned int tagset[2] = { 1, 1 };
+static int tsel = -1;
 static bool mouse_events_enabled = ENABLE_MOUSE;
 static Layout *layout = layouts;
 static StatusBar bar = { .fd = -1, .lastpos = BAR_POS, .pos = BAR_POS, .autohide = BAR_AUTOHIDE, .h = 1 };
@@ -683,6 +687,32 @@ get_client_by_coord(unsigned int x, unsigned int y) {
 	return NULL;
 }
 
+static int
+get_tag_by_coord(unsigned int x, unsigned int y) {
+	unsigned int i;
+	unsigned int pos = 0;
+	int tagfield, labellen;
+
+	if ((bar.pos == BAR_OFF) ||
+			(bar.pos == BAR_TOP && y >= bar.h) ||
+			(bar.pos == BAR_BOTTOM && y < screen.h - bar.h))
+		return -1;
+
+	/* Assumes TAG_SYMBOL includes '%s', a 2 character format specification */
+	tagfield = strlen(TAG_SYMBOL) - 2;
+
+	for (i = 0; i < LENGTH(tags); i++){
+		labellen = tagfield + strlen(tags[i]);
+		if (x >= pos && x < pos + labellen) {
+			debug("mouse event, x: %d y: %d tag: %d\n", x, y, i);
+			return i;
+		}
+		pos += labellen;
+	}
+
+	return -1;
+}
+
 static void
 sigchld_handler(int sig) {
 	int errsv = errno;
@@ -1418,6 +1448,24 @@ mouse_zoom(const char *args[]) {
 	zoom(NULL);
 }
 
+static void
+mouse_toggleview(const char *args[]) {
+	args[0] = tags[tsel];
+	toggleview(args);
+}
+
+static void
+mouse_view(const char *args[]) {
+	args[0] = tags[tsel];
+	view(args);
+}
+
+static void
+mouse_toggletag(const char *args[]) {
+	args[0] = tags[tsel];
+	toggletag(args);
+}
+
 static Cmd *
 get_cmd_by_name(const char *name) {
 	for (unsigned int i = 0; i < LENGTH(commands); i++) {
@@ -1531,8 +1579,19 @@ handle_mouse(void) {
 		return;
 	msel = get_client_by_coord(event.x, event.y);
 
-	if (!msel)
+	if (!msel) {
+		tsel = get_tag_by_coord(event.x, event.y);
+		if (tsel == -1)
+			return;
+		debug("mouse x:%d y:%d tag:%d mask:%d\n", event.x, event.y, tsel, event.bstate);
+		for (i = 0; i < LENGTH(tag_buttons); i++) {
+			if (event.bstate & tag_buttons[i].mask)
+				tag_buttons[i].action.cmd(tag_buttons[i].action.args);
+		}
+
+		tsel = -1;
 		return;
+	}
 
 	debug("mouse x:%d y:%d cx:%d cy:%d mask:%d\n", event.x, event.y, event.x - msel->x, event.y - msel->y, event.bstate);
 
@@ -1776,6 +1835,7 @@ main(int argc, char *argv[]) {
 				keys[key_index++] = code;
 				KeyBinding *binding = NULL;
 				if (code == KEY_MOUSE) {
+					key_index = 0;
 					handle_mouse();
 				} else if ((binding = keybinding(keys))) {
 					unsigned int key_length = 0;

Reply via email to