Anyone who wants status at the top please test this, particularly if you use the various tmux mouse options...
Testing from people who use the mouse but are going to keep status line at the bottom would be useful too (apply this and set -g status-position bottom). The default will stay bottom once this is working. Index: layout.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/layout.c,v retrieving revision 1.7 diff -u -p -r1.7 layout.c --- layout.c 8 May 2011 20:34:12 -0000 1.7 +++ layout.c 24 Jan 2012 11:14:01 -0000 @@ -502,14 +502,14 @@ layout_resize_pane_mouse(struct client * wp->yoff <= 1 + c->last_mouse.y && wp->yoff + wp->sy >= c->last_mouse.y) { layout_resize_pane(wp, LAYOUT_LEFTRIGHT, - mouse->x - c->last_mouse.x); + mouse->x - c->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) { layout_resize_pane(wp, LAYOUT_TOPBOTTOM, - mouse->y - c->last_mouse.y); + mouse->y - c->last_mouse.y); pane_border = 1; } } Index: options-table.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/options-table.c,v retrieving revision 1.19 diff -u -p -r1.19 options-table.c --- options-table.c 21 Jan 2012 08:40:09 -0000 1.19 +++ options-table.c 24 Jan 2012 11:14:02 -0000 @@ -48,6 +48,9 @@ const char *options_table_status_keys_li const char *options_table_status_justify_list[] = { "left", "centre", "right", NULL }; +const char *options_table_status_position_list[] = { + "top", "bottom", NULL +}; const char *options_table_bell_action_list[] = { "none", "any", "current", NULL }; @@ -357,6 +360,12 @@ const struct options_table_entry session .minimum = 0, .maximum = SHRT_MAX, .default_num = 10 + }, + + { .name = "status-position", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_status_position_list, + .default_num = 0 }, { .name = "status-right", Index: screen-redraw.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/screen-redraw.c,v retrieving revision 1.20 diff -u -p -r1.20 screen-redraw.c --- screen-redraw.c 21 Jan 2012 23:45:44 -0000 1.20 +++ screen-redraw.c 24 Jan 2012 11:14:02 -0000 @@ -170,25 +170,33 @@ void screen_redraw_screen(struct client *c, int status_only, int borders_only) { struct window *w = c->session->curw->window; + struct options *oo = &c->session->options; struct tty *tty = &c->tty; struct window_pane *wp; struct grid_cell active_gc, other_gc; - u_int i, j, type; - int status, fg, bg; + u_int i, j, type, top; + int status, spos, fg, bg; /* Suspended clients should not be updated. */ if (c->flags & CLIENT_SUSPENDED) return; /* Get status line, er, status. */ + spos = options_get_number(oo, "status-position"); if (c->message_string != NULL || c->prompt_string != NULL) status = 1; else - status = options_get_number(&c->session->options, "status"); + status = options_get_number(oo, "status"); + top = 0; + if (status && spos == 0) + top = 1; /* If only drawing status and it is present, don't need the rest. */ if (status_only && status) { - tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); + if (top) + tty_draw_line(tty, &c->status, 0, 0, 0); + else + tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); tty_reset(tty); return; } @@ -198,19 +206,23 @@ screen_redraw_screen(struct client *c, i memcpy(&active_gc, &grid_default_cell, sizeof active_gc); active_gc.data = other_gc.data = 'x'; /* not space */ active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET; - fg = options_get_number(&c->session->options, "pane-border-fg"); + fg = options_get_number(oo, "pane-border-fg"); colour_set_fg(&other_gc, fg); - bg = options_get_number(&c->session->options, "pane-border-bg"); + bg = options_get_number(oo, "pane-border-bg"); colour_set_bg(&other_gc, bg); - fg = options_get_number(&c->session->options, "pane-active-border-fg"); + fg = options_get_number(oo, "pane-active-border-fg"); colour_set_fg(&active_gc, fg); - bg = options_get_number(&c->session->options, "pane-active-border-bg"); + bg = options_get_number(oo, "pane-active-border-bg"); colour_set_bg(&active_gc, bg); /* Draw background and borders. */ for (j = 0; j < tty->sy - status; j++) { - if (status_only && j != tty->sy - 1) - continue; + if (status_only) { + if (spos == 1 && j != tty->sy - 1) + continue; + else if (spos == 0 && j != 0) + break; + } for (i = 0; i < tty->sx; i++) { type = screen_redraw_check_cell(c, i, j); if (type == CELL_INSIDE) @@ -219,7 +231,7 @@ screen_redraw_screen(struct client *c, i tty_attributes(tty, &active_gc); else tty_attributes(tty, &other_gc); - tty_cursor(tty, i, j); + tty_cursor(tty, i, top + j); tty_putc(tty, CELL_BORDERS[type]); } } @@ -233,17 +245,26 @@ screen_redraw_screen(struct client *c, i if (!window_pane_visible(wp)) continue; for (i = 0; i < wp->sy; i++) { - if (status_only && wp->yoff + i != tty->sy - 1) - continue; - tty_draw_line(tty, wp->screen, i, wp->xoff, wp->yoff); + if (status_only) { + if (spos == 1 && wp->yoff + i != tty->sy - 1) + continue; + else if (spos == 0 && wp->yoff + i != 0) + break; + } + tty_draw_line( + tty, wp->screen, i, wp->xoff, top + wp->yoff); } if (c->flags & CLIENT_IDENTIFY) screen_redraw_draw_number(c, wp); } /* Draw the status line. */ - if (status) - tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); + if (status) { + if (top) + tty_draw_line(tty, &c->status, 0, 0, 0); + else + tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); + } tty_reset(tty); } @@ -251,10 +272,14 @@ screen_redraw_screen(struct client *c, i void screen_redraw_pane(struct client *c, struct window_pane *wp) { - u_int i; + u_int i, yoff; + + yoff = wp->yoff; + if (status_at_line(c) == 0) + yoff++; for (i = 0; i < wp->sy; i++) - tty_draw_line(&c->tty, wp->screen, i, wp->xoff, wp->yoff); + tty_draw_line(&c->tty, wp->screen, i, wp->xoff, yoff); tty_reset(&c->tty); } Index: server-client.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/server-client.c,v retrieving revision 1.64 diff -u -p -r1.64 server-client.c --- server-client.c 21 Jan 2012 23:51:34 -0000 1.64 +++ server-client.c 24 Jan 2012 11:14:03 -0000 @@ -27,6 +27,8 @@ #include "tmux.h" +void server_client_check_mouse(struct client *c, + struct window_pane *wp, struct mouse_event *mouse); void server_client_handle_key(int, struct mouse_event *, void *); void server_client_repeat_timer(int, short, void *); void server_client_check_exit(struct client *); @@ -262,6 +264,65 @@ server_client_status_timer(void) } } +/* Check for mouse keys. */ +void +server_client_check_mouse( + struct client *c, struct window_pane *wp, struct mouse_event *mouse) +{ + struct session *s = c->session; + struct options *oo = &s->options; + int statusat; + + statusat = status_at_line(c); + + /* Is this a window selection click on the status line? */ + if (statusat != -1 && mouse->y == (u_int)statusat && + options_get_number(oo, "mouse-select-window")) { + 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; + } + } + + /* + * Not on status line - adjust mouse position if status line is at the + * top and limit if at the bottom. From here on a struct mouse + * represents the offset onto the window itself. + */ + if (statusat == 0 &&mouse->y > 0) + mouse->y--; + else if (statusat > 0 && mouse->y >= (u_int)statusat) + mouse->y = statusat - 1; + + /* Is this a pane selection? Allow down only in copy mode. */ + if (options_get_number(oo, "mouse-select-pane") && + ((!(mouse->b & MOUSE_DRAG) && mouse->b != MOUSE_UP) || + wp->mode != &window_copy_mode)) { + window_set_active_at(wp->window, mouse->x, mouse->y); + server_redraw_window_borders(wp->window); + wp = wp->window->active; /* may have changed */ + } + + /* Check if trying to resize pane. */ + if (options_get_number(oo, "mouse-resize-pane")) + layout_resize_pane_mouse(c, mouse); + + /* Update last and pass through to client. */ + memcpy(&c->last_mouse, mouse, sizeof c->last_mouse); + window_pane_mouse(wp, c->session, mouse); +} + /* Handle data key input from client. */ void server_client_handle_key(int key, struct mouse_event *mouse, void *data) @@ -317,43 +378,7 @@ server_client_handle_key(int key, struct if (key == KEYC_MOUSE) { if (c->flags & CLIENT_READONLY) return; - if (options_get_number(oo, "mouse-select-pane") && - (!(options_get_number(oo, "status") && - mouse->y + 1 == c->tty.sy)) && - ((!(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); + server_client_check_mouse(c, wp, mouse); return; } @@ -472,7 +497,7 @@ server_client_reset_state(struct client struct screen *s = wp->screen; struct options *oo = &c->session->options; struct options *wo = &w->options; - int status, mode; + int status, mode, o; if (c->flags & CLIENT_SUSPENDED) return; @@ -482,8 +507,10 @@ server_client_reset_state(struct client status = options_get_number(oo, "status"); if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status) tty_cursor(&c->tty, 0, 0); - else - tty_cursor(&c->tty, wp->xoff + s->cx, wp->yoff + s->cy); + else { + o = status && options_get_number (oo, "status-position") == 0; + tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy); + } /* * Resizing panes with the mouse requires at least button mode to give Index: status.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/status.c,v retrieving revision 1.84 diff -u -p -r1.84 status.c --- status.c 20 Jan 2012 19:51:28 -0000 1.84 +++ status.c 24 Jan 2012 11:14:03 -0000 @@ -60,6 +60,20 @@ status_out_cmp(struct status_out *so1, s return (strcmp(so1->cmd, so2->cmd)); } +/* Get screen line of status line. -1 means off. */ +int +status_at_line(struct client *c) +{ + struct session *s = c->session; + + if (!options_get_number(&s->options, "status")) + return (-1); + + if (options_get_number(&s->options, "status-position") == 0) + return (0); + return (c->tty.sy - 1); +} + /* Retrieve options for left string. */ char * status_redraw_get_left(struct client *c, Index: tmux.h =================================================================== RCS file: /cvs/src/usr.bin/tmux/tmux.h,v retrieving revision 1.307 diff -u -p -r1.307 tmux.h --- tmux.h 21 Jan 2012 23:51:34 -0000 1.307 +++ tmux.h 24 Jan 2012 11:14:05 -0000 @@ -1078,6 +1078,9 @@ struct tty_ctx { u_int orupper; u_int orlower; + u_int xoff; + u_int yoff; + /* Saved last cell on line. */ struct grid_cell last_cell; struct grid_utf8 last_utf8; @@ -1463,8 +1466,8 @@ void tty_draw_line(struct tty *, struct int tty_open(struct tty *, const char *, char **); void tty_close(struct tty *); void tty_free(struct tty *); -void tty_write(void (*)( - struct tty *, const struct tty_ctx *), const struct tty_ctx *); +void tty_write( + void (*)(struct tty *, const struct tty_ctx *), struct tty_ctx *); void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *); void tty_cmd_cell(struct tty *, const struct tty_ctx *); void tty_cmd_clearendofline(struct tty *, const struct tty_ctx *); @@ -1722,6 +1725,7 @@ void server_update_event(struct client /* status.c */ int status_out_cmp(struct status_out *, struct status_out *); RB_PROTOTYPE(status_out_tree, status_out, entry, status_out_cmp); +int status_at_line(struct client *); void status_free_jobs(struct status_out_tree *); void status_update_jobs(struct client *); void status_set_window_at(struct client *, u_int); Index: tty.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/tty.c,v retrieving revision 1.112 diff -u -p -r1.112 tty.c --- tty.c 21 Jan 2012 08:23:12 -0000 1.112 +++ tty.c 24 Jan 2012 11:14:05 -0000 @@ -513,10 +513,10 @@ tty_redraw_region(struct tty *tty, const if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) { for (i = ctx->ocy; i < screen_size_y(s); i++) - tty_draw_line(tty, s, i, wp->xoff, wp->yoff); + tty_draw_line(tty, s, i, ctx->xoff, ctx->yoff); } else { for (i = ctx->orupper; i <= ctx->orlower; i++) - tty_draw_line(tty, s, i, wp->xoff, wp->yoff); + tty_draw_line(tty, s, i, ctx->xoff, ctx->yoff); } } @@ -585,11 +585,13 @@ tty_draw_line(struct tty *tty, struct sc } void -tty_write(void (*cmdfn)( - struct tty *, const struct tty_ctx *), const struct tty_ctx *ctx) +tty_write( + void (*cmdfn)(struct tty *, const struct tty_ctx *), struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; struct client *c; + struct session *s; + struct options *oo; u_int i; /* wp can be NULL if updating the screen but not the terminal. */ @@ -607,12 +609,20 @@ tty_write(void (*cmdfn)( continue; if (c->flags & CLIENT_SUSPENDED) continue; + s = c->session; - if (c->session->curw->window == wp->window) { + if (s->curw->window == wp->window) { if (c->tty.term == NULL) continue; if (c->tty.flags & (TTY_FREEZE|TTY_BACKOFF)) continue; + oo = &s->options; + + ctx->xoff = wp->xoff; + ctx->yoff = wp->yoff; + if (status_at_line(c) == 0) + ctx->yoff++; + cmdfn(&c->tty, ctx); } } @@ -625,8 +635,8 @@ tty_cmd_insertcharacter(struct tty *tty, struct screen *s = wp->screen; u_int i; - if (wp->xoff != 0 || screen_size_x(s) < tty->sx) { - tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff); + if (ctx->xoff != 0 || screen_size_x(s) < tty->sx) { + tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); return; } @@ -644,7 +654,7 @@ tty_cmd_insertcharacter(struct tty *tty, tty_putc(tty, ' '); tty_putcode(tty, TTYC_RMIR); } else - tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff); + tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); } void @@ -653,10 +663,10 @@ tty_cmd_deletecharacter(struct tty *tty, struct window_pane *wp = ctx->wp; struct screen *s = wp->screen; - if (wp->xoff != 0 || screen_size_x(s) < tty->sx || + if (ctx->xoff != 0 || screen_size_x(s) < tty->sx || (!tty_term_has(tty->term, TTYC_DCH) && !tty_term_has(tty->term, TTYC_DCH1))) { - tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff); + tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); return; } @@ -675,7 +685,7 @@ tty_cmd_insertline(struct tty *tty, cons struct window_pane *wp = ctx->wp; struct screen *s = wp->screen; - if (wp->xoff != 0 || screen_size_x(s) < tty->sx || + if (ctx->xoff != 0 || screen_size_x(s) < tty->sx || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_IL1)) { tty_redraw_region(tty, ctx); @@ -696,7 +706,7 @@ tty_cmd_deleteline(struct tty *tty, cons struct window_pane *wp = ctx->wp; struct screen *s = wp->screen; - if (wp->xoff != 0 || screen_size_x(s) < tty->sx || + if (ctx->xoff != 0 || screen_size_x(s) < tty->sx || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_DL1)) { tty_redraw_region(tty, ctx); @@ -722,7 +732,7 @@ tty_cmd_clearline(struct tty *tty, const tty_cursor_pane(tty, ctx, 0, ctx->ocy); - if (wp->xoff == 0 && screen_size_x(s) >= tty->sx && + if (ctx->xoff == 0 && screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { tty_putcode(tty, TTYC_EL); } else { @@ -742,7 +752,7 @@ tty_cmd_clearendofline(struct tty *tty, tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - if (wp->xoff == 0 && screen_size_x(s) >= tty->sx && + if (ctx->xoff == 0 && screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) tty_putcode(tty, TTYC_EL); else { @@ -754,12 +764,11 @@ tty_cmd_clearendofline(struct tty *tty, void tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int i; + u_int i; tty_reset(tty); - if (wp->xoff == 0 && tty_term_has(tty->term, TTYC_EL1)) { + if (ctx->xoff == 0 && tty_term_has(tty->term, TTYC_EL1)) { tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); tty_putcode(tty, TTYC_EL1); } else { @@ -778,7 +787,7 @@ tty_cmd_reverseindex(struct tty *tty, co if (ctx->ocy != ctx->orupper) return; - if (wp->xoff != 0 || screen_size_x(s) < tty->sx || + if (ctx->xoff != 0 || screen_size_x(s) < tty->sx || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_RI)) { tty_redraw_region(tty, ctx); @@ -802,7 +811,7 @@ tty_cmd_linefeed(struct tty *tty, const if (ctx->ocy != ctx->orlower) return; - if (wp->xoff != 0 || screen_size_x(s) < tty->sx || + if (ctx->xoff != 0 || screen_size_x(s) < tty->sx || !tty_term_has(tty->term, TTYC_CSR)) { tty_redraw_region(tty, ctx); return; @@ -836,7 +845,7 @@ tty_cmd_clearendofscreen(struct tty *tty tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - if (wp->xoff == 0 && screen_size_x(s) >= tty->sx && + if (ctx->xoff == 0 && screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { tty_putcode(tty, TTYC_EL); if (ctx->ocy != screen_size_y(s) - 1) { @@ -872,7 +881,7 @@ tty_cmd_clearstartofscreen(struct tty *t tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); tty_cursor_pane(tty, ctx, 0, 0); - if (wp->xoff == 0 && screen_size_x(s) >= tty->sx && + if (ctx->xoff == 0 && screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { for (i = 0; i < ctx->ocy; i++) { tty_putcode(tty, TTYC_EL); @@ -902,7 +911,7 @@ tty_cmd_clearscreen(struct tty *tty, con tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); tty_cursor_pane(tty, ctx, 0, 0); - if (wp->xoff == 0 && screen_size_x(s) >= tty->sx && + if (ctx->xoff == 0 && screen_size_x(s) >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { for (i = 0; i < screen_size_y(s); i++) { tty_putcode(tty, TTYC_EL); @@ -957,7 +966,7 @@ tty_cmd_cell(struct tty *tty, const stru /* Is the cursor in the very last position? */ if (ctx->ocx > wp->sx - width) { - if (wp->xoff != 0 || wp->sx != tty->sx) { + if (ctx->xoff != 0 || wp->sx != tty->sx) { /* * The pane doesn't fill the entire line, the linefeed * will already have happened, so just move the cursor. @@ -991,7 +1000,7 @@ tty_cmd_utf8character(struct tty *tty, c * Cannot rely on not being a partial character, so just redraw the * whole line. */ - tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff); + tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); } void @@ -1078,9 +1087,7 @@ void tty_region_pane( struct tty *tty, const struct tty_ctx *ctx, u_int rupper, u_int rlower) { - struct window_pane *wp = ctx->wp; - - tty_region(tty, wp->yoff + rupper, wp->yoff + rlower); + tty_region(tty, ctx->yoff + rupper, ctx->yoff + rlower); } /* Set region at absolute position. */ @@ -1112,9 +1119,7 @@ tty_region(struct tty *tty, u_int rupper void tty_cursor_pane(struct tty *tty, const struct tty_ctx *ctx, u_int cx, u_int cy) { - struct window_pane *wp = ctx->wp; - - tty_cursor(tty, wp->xoff + cx, wp->yoff + cy); + tty_cursor(tty, ctx->xoff + cx, ctx->yoff + cy); } /* Move cursor to absolute position. */ ------------------------------------------------------------------------------ Keep Your Developer Skills Current with LearnDevNow! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-d2d _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users