....phew, mind twisting TAILQ_* macros..but it works now. The problem
you described is gone with this, and also this patch allows for complex
mouse click patterns (like kill window on triple middle button click
then shift left click within one second).. that needs a config syntax
though. and yet the coolest thing to try: ncurses mousemask() mode, so
the mouse works without xorg - and nested programs in tmux receive input
too (finally)... Nicholas can you take a peek at
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/mouse.html ?
...and now: the bed x)
#regards|marcel.
--- input.c.orig 2011-10-24 19:46:41.526436392 +0200
+++ input.c 2011-12-05 20:43:32.997082068 +0100
@@ -723,7 +723,7 @@
/* Parse the input. */
while (off < len) {
ictx->ch = buf[off++];
- log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
+ //log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
/* Find the transition. */
itr = ictx->state->transitions;
@@ -899,7 +899,7 @@
struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s;
- log_debug("%s: '%c", __func__, ictx->ch);
+ //log_debug("%s: '%c", __func__, ictx->ch);
switch (ictx->ch) {
case '\000': /* NUL */
@@ -937,7 +937,7 @@
ictx->cell.attr &= ~GRID_ATTR_CHARSET;
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
@@ -954,12 +954,12 @@
if (ictx->flags & INPUT_DISCARD)
return (0);
- log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
+ //log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
sizeof input_esc_table[0], input_table_compare);
if (entry == NULL) {
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
return (0);
}
@@ -1044,13 +1044,13 @@
return (0);
if (input_split(ictx) != 0)
return (0);
- log_debug("%s: '%c' \"%s\" \"%s\"",
- __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
+ //log_debug("%s: '%c' \"%s\" \"%s\"",
+ // __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
sizeof input_csi_table[0], input_table_compare);
if (entry == NULL) {
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
return (0);
}
@@ -1087,7 +1087,7 @@
input_reply(ictx, "\033[?1;2c");
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1111,7 +1111,7 @@
input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1138,7 +1138,7 @@
}
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1154,7 +1154,7 @@
screen_write_clearline(sctx);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1174,7 +1174,7 @@
screen_write_insertmode(&ictx->ctx, 0);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1203,7 +1203,7 @@
window_pane_alternate_off(wp, &ictx->cell);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1216,7 +1216,7 @@
screen_write_insertmode(&ictx->ctx, 1);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1250,7 +1250,7 @@
window_pane_alternate_on(wp, &ictx->cell);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1264,7 +1264,7 @@
bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
break;
default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ //log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
@@ -1437,7 +1437,7 @@
if (ictx->flags & INPUT_DISCARD)
return (0);
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+ //log_debug("%s: \"%s\"", __func__, ictx->input_buf);
/* Check for tmux prefix. */
if (ictx->input_len >= prefix_len &&
@@ -1453,7 +1453,7 @@
void
input_enter_osc(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ //log_debug("%s", __func__);
input_clear(ictx);
}
@@ -1470,7 +1470,7 @@
if (ictx->input_len < 1 || *p < '0' || *p > '9')
return;
- log_debug("%s: \"%s\"", __func__, p);
+ //log_debug("%s: \"%s\"", __func__, p);
option = 0;
while (*p >= '0' && *p <= '9')
@@ -1492,7 +1492,7 @@
screen_set_cursor_colour(ictx->ctx.s, "");
break;
default:
- log_debug("%s: unknown '%u'", __func__, option);
+ //log_debug("%s: unknown '%u'", __func__, option);
break;
}
}
@@ -1501,7 +1501,7 @@
void
input_enter_apc(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ //log_debug("%s", __func__);
input_clear(ictx);
}
@@ -1512,7 +1512,7 @@
{
if (ictx->flags & INPUT_DISCARD)
return;
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+ //log_debug("%s: \"%s\"", __func__, ictx->input_buf);
screen_set_title(ictx->ctx.s, ictx->input_buf);
server_status_window(ictx->wp->window);
@@ -1522,7 +1522,7 @@
void
input_enter_rename(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ //log_debug("%s", __func__);
input_clear(ictx);
}
@@ -1533,7 +1533,7 @@
{
if (ictx->flags & INPUT_DISCARD)
return;
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+ //log_debug("%s: \"%s\"", __func__, ictx->input_buf);
xfree(ictx->wp->window->name);
ictx->wp->window->name = xstrdup(ictx->input_buf);
@@ -1551,7 +1551,7 @@
input_print(ictx);
return (-1);
}
- log_debug("%s", __func__);
+ //log_debug("%s", __func__);
utf8_open(&ictx->utf8data, ictx->ch);
return (0);
@@ -1561,7 +1561,7 @@
int
input_utf8_add(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ //log_debug("%s", __func__);
utf8_append(&ictx->utf8data, ictx->ch);
return (0);
@@ -1571,7 +1571,7 @@
int
input_utf8_close(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ //log_debug("%s", __func__);
utf8_append(&ictx->utf8data, ictx->ch);
--- server-client.c.orig 2011-08-31 21:13:19.912686029 +0200
+++ server-client.c 2011-12-06 02:22:54.380602287 +0100
@@ -88,8 +88,7 @@
c->prompt_buffer = NULL;
c->prompt_index = 0;
- c->last_mouse.b = MOUSE_UP;
- c->last_mouse.x = c->last_mouse.y = -1;
+ TAILQ_INIT(&c->mouse_events);
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
@@ -261,6 +260,149 @@
}
}
+ char *
+ format_binary(unsigned int x)
+ { //panic.cc !!!
+ #define MAXLEN 8 // width of format
+ #define MAXCNT 4 // count per printf
+ static char fmtbuf[(MAXLEN+1)*MAXCNT];
+ static int count = 0;
+ char *b;
+ count = count % MAXCNT + 1;
+ b = &fmtbuf[(MAXLEN+1)*count];
+ b[MAXLEN] = '\0';
+ for (int z = 0; z < MAXLEN; z++) { b[MAXLEN-1-z] = ((x>>z) & 0x1) ? '1' : '0'; }
+ return b;
+ }
+
+u_int usec_diff(struct timeval tv1, struct timeval tv2)
+{
+ u_int diff_usec; //tv1 - tv2
+
+ diff_usec = tv1.tv_usec - tv2.tv_usec;
+ diff_usec += (tv1.tv_sec - tv2.tv_sec) * 1000000;
+ return diff_usec;
+}
+
+char *
+server_client_mouse_button_string(int b) {
+ static char buf[200];
+// for (int i = 32; i < 33; i++)
+// log_debug("mouse event (%u & %u) = %u = (%s & %s) = %s", b, i, (b & i), format_binary(b), format_binary(i), format_binary(b & i));
+ buf[0] = '\0';
+ if (b & MOUSE_SHIFT) strcat(buf, "shift ");
+ if (b & MOUSE_ALT) strcat(buf, "alt ");
+ if (b & MOUSE_CTRL) strcat(buf, "ctrl ");
+ if (!(b & MOUSE_45) && ((b & MOUSE_BUTTON) == MOUSE_1)) strcat(buf, "left ");
+ if (!(b & MOUSE_45) && ((b & MOUSE_BUTTON) == MOUSE_2)) strcat(buf, "middle ");
+ if ((b & MOUSE_BUTTON) == MOUSE_3) strcat(buf, "right ");
+ if (!(b & MOUSE_45) && ((b & MOUSE_BUTTON) == MOUSE_BUTTON)) strcat(buf, "buttonup ");
+ if (b & MOUSE_DRAG) strcat(buf, "drag ");
+ if ((b & MOUSE_45) && (b & MOUSE_BUTTON) == MOUSE_1) strcat(buf, "wheelup ");
+ if ((b & MOUSE_45) && (b & MOUSE_BUTTON) == MOUSE_2) strcat(buf, "wheeldown ");
+
+/*
+#define MODE_CURSOR 0x1 #define MOUSE_1 0 0
+#define MODE_INSERT 0x2 #define MOUSE_2 1 01
+#define MODE_KCURSOR 0x4 #define MOUSE_3 2 10
+#define MODE_KKEYPAD 0x8 // set = application, clear = number #define MOUSE_UP 3 11
+#define MODE_WRAP 0x10 // whether lines wrap #define MOUSE_BUTTON 3 11
+#define MODE_MOUSE_STANDARD 0x20 #define MOUSE_SHIFT 4 100
+#define MODE_MOUSE_BUTTON 0x40 #define MOUSE_ALT 8 1000
+#define MODE_MOUSE_ANY 0x80 #define MOUSE_CTRL 16 10000
+#define MODE_MOUSE_UTF8 0x100 #define MOUSE_DRAG 32 100000
+#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD #define MOUSE_45 64 1000000
+ |MODE_MOUSE_BUTTON|MODE_MOUSE_ANY) #define MOUSE_RESIZE_PANE ?
+ }*/
+ return buf;
+}
+
+#define MAXMOUSEEVENTS 100
+void
+server_client_prune_mouse_stack(struct client *c)
+{
+ struct mouse_event *m = TAILQ_FIRST(&c->mouse_events);
+ int i = 0;
+
+ while (m) {
+ if(++i == MAXMOUSEEVENTS) {
+ TAILQ_REMOVE(&c->mouse_events, m, entry);
+ xfree(m);
+ break;
+ } else
+ m = TAILQ_NEXT(m, entry);
+ }
+ log_debug("%u elements in tail queue", i);
+
+}
+
+void
+server_client_handle_mouse_event(struct client *c, struct mouse_event *mouse)
+{
+ struct mouse_event *m[MAXMOUSEEVENTS];
+ struct session *s;
+ struct window *w;
+ struct window_pane *wp;
+ struct options *oo;
+ char *button;
+ u_int tdiff, i = 0;
+
+ s = c->session;
+ w = s->curw->window;
+ wp = w->active;
+ oo = &s->options;
+
+ memset(m, 0, MAXMOUSEEVENTS * sizeof *m);
+ m[0] = xmalloc(sizeof(struct mouse_event));
+ memcpy(m[0], mouse, sizeof(struct mouse_event));
+
+ button = server_client_mouse_button_string(m[0]->b);
+ tdiff = TAILQ_EMPTY(&c->mouse_events) ? 0 : usec_diff(m[0]->time, TAILQ_FIRST(&c->mouse_events)->time);
+ log_debug("mouse event (%p): button=%u (%s), (x,y)=(%u,%u) @ %u.%u (+%.2fsec)", m[0], m[0]->b, button, m[0]->x, m[0]->y, (uint) m[0]->time.tv_sec, (uint) m[0]->time.tv_usec, tdiff/1000000.0);
+
+ TAILQ_INSERT_HEAD(&c->mouse_events, m[0], entry);
+ server_client_prune_mouse_stack(c);
+ TAILQ_FOREACH(mouse, &c->mouse_events, entry) {
+ m[i] = mouse;
+ i++;
+ }
+
+ if (options_get_number(oo, "mouse-select-pane") &&
+ ((!(m[0]->b & MOUSE_DRAG) && m[0]->b != MOUSE_UP) || //is neither mouse drag nor button up
+ wp->mode != &window_copy_mode)) {
+ /*
+ * Allow pane switching in copy mode only by mouse down
+ * (click).
+ */
+ window_set_active_at(w, m[0]->x, m[0]->y);
+ server_redraw_window_borders(w);
+ wp = w->active;
+ }
+ if (m[0]->y + 1 == c->tty.sy &&
+ options_get_number(oo, "mouse-select-window") &&
+ options_get_number(oo, "status")) {
+ if (m[0]->b == MOUSE_UP && m[1] && m[1]->b != MOUSE_UP) {
+ status_set_window_at(c, m[0]->x);
+ return;
+ }
+ if (m[0]->b & MOUSE_45) {
+ if ((m[0]->b & MOUSE_BUTTON) == MOUSE_1) {
+ session_previous(c->session, 0);
+ server_redraw_session(s);
+ }
+ if ((m[0]->b & MOUSE_BUTTON) == MOUSE_2) {
+ session_next(c->session, 0);
+ server_redraw_session(s);
+ }
+ return;
+ }
+ }
+ if (options_get_number(oo, "mouse-resize-pane"))
+ layout_resize_pane_mouse(c, m[0]);
+ window_pane_mouse(wp, c->session, m[0]);
+ return;
+}
+
/* Handle data key input from client. */
void
server_client_handle_key(int key, struct mouse_event *mouse, void *data)
@@ -287,6 +429,7 @@
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday failed");
memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time);
+ memcpy(&mouse->time, &c->activity_time, sizeof mouse->time);
w = c->session->curw->window;
wp = w->active;
@@ -318,42 +461,8 @@
if (key == KEYC_MOUSE) {
if (c->flags & CLIENT_READONLY)
return;
- if (options_get_number(oo, "mouse-select-pane") &&
- ((!(mouse->b & MOUSE_DRAG) && mouse->b != MOUSE_UP) ||
- wp->mode != &window_copy_mode)) {
- /*
- * Allow pane switching in copy mode only by mouse down
- * (click).
- */
- window_set_active_at(w, mouse->x, mouse->y);
- server_redraw_window_borders(w);
- wp = w->active;
- }
- if (mouse->y + 1 == c->tty.sy &&
- options_get_number(oo, "mouse-select-window") &&
- options_get_number(oo, "status")) {
- if (mouse->b == MOUSE_UP &&
- c->last_mouse.b != MOUSE_UP) {
- status_set_window_at(c, mouse->x);
- return;
- }
- if (mouse->b & MOUSE_45) {
- if ((mouse->b & MOUSE_BUTTON) == MOUSE_1) {
- session_previous(c->session, 0);
- server_redraw_session(s);
- }
- if ((mouse->b & MOUSE_BUTTON) == MOUSE_2) {
- session_next(c->session, 0);
- server_redraw_session(s);
- }
- return;
- }
- }
- if (options_get_number(oo, "mouse-resize-pane"))
- layout_resize_pane_mouse(c, mouse);
- memcpy(&c->last_mouse, mouse, sizeof c->last_mouse);
- window_pane_mouse(wp, c->session, mouse);
- return;
+ else
+ server_client_handle_mouse_event(c, mouse);
}
/* Is this a prefix key? */
@@ -473,6 +582,7 @@
struct screen *s = wp->screen;
struct options *oo = &c->session->options;
struct options *wo = &w->options;
+ struct mouse_event *lm;
int status, mode;
if (c->flags & CLIENT_SUSPENDED)
@@ -491,7 +601,9 @@
* a smooth appearance.
*/
mode = s->mode;
- if ((c->last_mouse.b & MOUSE_RESIZE_PANE) &&
+ if (!TAILQ_EMPTY(&c->mouse_events) &&
+ (lm = TAILQ_NEXT(TAILQ_FIRST(&c->mouse_events), entry)) != NULL &&
+ lm->b & MOUSE_RESIZE_PANE &&
!(mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)))
mode |= MODE_MOUSE_BUTTON;
--- layout.c.orig 2011-07-14 17:05:30.322902790 +0200
+++ layout.c 2011-12-06 02:13:16.110926213 +0100
@@ -490,26 +490,27 @@
{
struct window *w;
struct window_pane *wp;
+ struct mouse_event *last_mouse = TAILQ_NEXT(mouse, entry);
int pane_border;
w = c->session->curw->window;
-
pane_border = 0;
- if ((c->last_mouse.b & MOUSE_BUTTON) != MOUSE_UP &&
- (c->last_mouse.b & MOUSE_RESIZE_PANE)) {
+
+ if (last_mouse != NULL && (last_mouse->b & MOUSE_BUTTON) != MOUSE_UP &&
+ (last_mouse->b & MOUSE_RESIZE_PANE)) {
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (wp->xoff + wp->sx == c->last_mouse.x &&
- wp->yoff <= 1 + c->last_mouse.y &&
- wp->yoff + wp->sy >= c->last_mouse.y) {
+ if (wp->xoff + wp->sx == last_mouse->x &&
+ wp->yoff <= 1 + last_mouse->y &&
+ wp->yoff + wp->sy >= last_mouse->y) {
layout_resize_pane(wp, LAYOUT_LEFTRIGHT,
- mouse->x - c->last_mouse.x);
+ mouse->x - last_mouse->x);
pane_border = 1;
}
- if (wp->yoff + wp->sy == c->last_mouse.y &&
- wp->xoff <= 1 + c->last_mouse.x &&
- wp->xoff + wp->sx >= c->last_mouse.x) {
+ if (wp->yoff + wp->sy == last_mouse->y &&
+ wp->xoff <= 1 + last_mouse->x &&
+ wp->xoff + wp->sx >= last_mouse->x) {
layout_resize_pane(wp, LAYOUT_TOPBOTTOM,
- mouse->y - c->last_mouse.y);
+ mouse->y - last_mouse->y);
pane_border = 1;
}
}
--- tty-keys.c.orig 2011-07-14 17:05:30.325902745 +0200
+++ tty-keys.c 2011-12-05 20:43:33.005082367 +0100
@@ -645,7 +645,7 @@
m->y = value;
}
log_debug("mouse input: %.*s", (int) *size, buf);
-
+ memset(&m->entry, 0, sizeof(m->entry));
/* Check and return the mouse input. */
if (m->b < 32 || m->x < 33 || m->y < 33)
return (-1);
--- tmux.h.orig 2011-11-26 04:59:34.927771326 +0100
+++ tmux.h 2011-12-05 20:51:22.352676154 +0100
@@ -1097,12 +1097,18 @@
#define MOUSE_3 2
#define MOUSE_UP 3
#define MOUSE_BUTTON 3
+#define MOUSE_SHIFT 4
+#define MOUSE_ALT 8
+#define MOUSE_CTRL 16
#define MOUSE_DRAG 32
#define MOUSE_45 64
#define MOUSE_RESIZE_PANE 128 /* marker for resizing */
u_int x;
u_int y;
+ struct timeval time;
+ TAILQ_ENTRY(mouse_event) entry;
};
+TAILQ_HEAD(mouse_event_stack, mouse_event);
/* Saved message entry. */
struct message_entry {
@@ -1191,7 +1197,7 @@
struct session *session;
struct session *last_session;
- struct mouse_event last_mouse;
+ struct mouse_event_stack mouse_events;
int references;
};
------------------------------------------------------------------------------
Cloud Services Checklist: Pricing and Packaging Optimization
This white paper is intended to serve as a reference, checklist and point of
discussion for anyone considering optimizing the pricing and packaging model
of a cloud services business. Read Now!
http://www.accelacomm.com/jaw/sfnl/114/51491232/
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users