diff options
| author | Quentin Carbonneaux | 2014-10-23 11:28:12 -0400 |
|---|---|---|
| committer | Quentin Carbonneaux | 2014-10-23 11:43:36 -0400 |
| commit | 0fde8d24f4008126d8334ba98939bb268717de43 (patch) | |
| tree | c4b83b1493a332a81bf8f8e486f00d50906f486b | |
| parent | ba552a054ffcdd4a97e32e777f59386695465836 (diff) | |
improve visual feedback of cursor
| -rw-r--r-- | cmd.h | 3 | ||||
| -rw-r--r-- | exec.c | 3 | ||||
| -rw-r--r-- | gui.h | 1 | ||||
| -rw-r--r-- | main.c | 31 | ||||
| -rw-r--r-- | vicmd.w | 28 | ||||
| -rw-r--r-- | win.c | 16 | ||||
| -rw-r--r-- | win.h | 6 | ||||
| -rw-r--r-- | x11.c | 22 |
8 files changed, 69 insertions, 41 deletions
@@ -1 +1,4 @@ +extern int mode; + void cmd_parse(Rune r); +#define cmd_reset() cmd_parse(GKEsc); @@ -21,6 +21,7 @@ #include "evnt.h" extern W *curwin; +void repaint(void); void die(char *); typedef struct ecmd ECmd; @@ -409,7 +410,7 @@ runev(int fd, int flag, void *data) eb_setmark(t->eb, SelBeg, t->p); eb_setmark(t->eb, SelEnd, t->p + t->ins); eb_commit(t->eb); - win_redraw_frame(); + repaint(); } if (flag & EWrite) { assert(t->ob && t->wfd == fd); @@ -100,6 +100,7 @@ struct gui { void (*drawtext)(GRect *clip, Rune *str, int len, int x, int y, GColor color); void (*drawrect)(GRect *clip, int x, int y, int w, int h, GColor c); + void (*drawcursor)(GRect *clip, int insert, int x, int y, int w); void (*setpointer)(GPointer pt); int (*textwidth)(Rune *str, int len); int (*nextevent)(GEvent *eret); @@ -17,9 +17,13 @@ W *curwin; int scrolling; +int needsredraw; +enum { + RedrawDelay = 16, /* in milliseconds */ + DoubleClick = 600, +}; static struct gui *g; -static int needsredraw; static int clicks; @@ -32,8 +36,13 @@ risword(Rune r) static void redraw() { + static W *old; + assert(needsredraw); - win_redraw_frame(); + if (old != curwin && old) + old->dirty = 1; + win_redraw_frame(curwin, mode == 'i'); + old = curwin; needsredraw = 0; } @@ -43,13 +52,18 @@ resetclicks() clicks = 0; } +void +repaint() +{ + if (needsredraw) + return; + ev_alarm(RedrawDelay, redraw); + needsredraw = 1; +} + static void gev(int fd, int flag, void *unused) { - enum { - RedrawDelay = 16, /* in milliseconds */ - DoubleClick = 200, - }; static unsigned selbeg; static W *mousewin; static int resizing; @@ -59,10 +73,7 @@ gev(int fd, int flag, void *unused) (void)fd; (void)flag; (void)unused; while (g->nextevent(&e)) { - if (!needsredraw) { - ev_alarm(RedrawDelay, redraw); - needsredraw = 1; - } + repaint(); switch (e.type) { case GResize: win_resize_frame(e.resize.width, e.resize.height); @@ -52,7 +52,7 @@ enum { Command = 'c', Insert = 'i' }; -static int mode = Command; +int mode = Command; @** Parsing of commands. We structure the parsing function as a @@ -159,6 +159,19 @@ if (!risbuf(r)) goto err; buf = r; state = CmdChar; +@ When a double character command is expected we ensure that the +second character received is the same as the first and resume +the processing performed in |@<Input command count...@>|. + +@<Get the second char...@>= +if (r != pcmd->chr) + goto err; +goto gotdbl; + +@ @<Get the command arg...@>= +pcmd->arg = r; +goto gotarg; + @ The |CmdChar| state needs to handle both the count and the command name. Depending on the command kind (double char, expecting an argument, ...) we have to update the state differently. To get this @@ -191,19 +204,6 @@ gotarg: @<Reset parsing state@>; } -@ When a double character command is expected we ensure that the -second character received is the same as the first and resume -the processing performed in |@<Input command count...@>|. - -@<Get the second char...@>= -if (r != pcmd->chr) - goto err; -goto gotdbl; - -@ @<Get the command arg...@>= -pcmd->arg = r; -goto gotarg; - @ The internal state is reset by zeroing the |count| field of the commands, this is necessary since |@<Input command count...@>| relies on it to determine if a received |'0'| is part of the count or is the @@ -19,7 +19,7 @@ struct lineinfo { }; static int dirty(W *); -static void draw(W *w, GColor bg); +static void draw(W *w, GColor bg, W *focus, int insert); static void move(W *pw, int x, int y, int w, int h); static void lineinfo(W *w, unsigned off, unsigned lim, struct lineinfo *li); static int runewidth(Rune r, int x); @@ -239,7 +239,7 @@ win_resize_frame(int w1, int h1) /* win_redraw_frame - Redraw the whole frame. */ void -win_redraw_frame() +win_redraw_frame(W *focus, int insert) { GRect b; W *w; @@ -253,7 +253,7 @@ win_redraw_frame() b.x = w->rectx + w->rectw; g->drawrect(&b, 0, 0, b.w, b.h, GGray); } - draw(w, GPaleYellow); + draw(w, GPaleYellow, focus, insert); if (tag.owner == w) tag.win.dirty = 1; } @@ -262,7 +262,7 @@ win_redraw_frame() b = tag.win.rect; b.y -= g->border; g->drawrect(&b, 0, 0, b.w, g->border, GGray); - draw(&tag.win, GPaleGreen); + draw(&tag.win, GPaleGreen, focus, insert); } g->sync(); } @@ -442,7 +442,7 @@ flushfrag(struct frag *f, W *w, int x, int y, int sel) } static void -draw(W *w, GColor bg) +draw(W *w, GColor bg, W *focus, int insert) { struct frag f; int x, y, cx, cy, cw, rw, sel; @@ -496,8 +496,8 @@ draw(W *w, GColor bg) pushfrag(&f, r, rw); } - if (cw != 0) - g->drawrect(&w->rect, cx, cy, cw, font.height, GXBlack); + if (cw != 0 && w == focus) + g->drawcursor(&w->rect, insert, cx, cy, cw); g->decorate(&w->rect, w->eb->path && w->eb->frev != eb_revision(w->eb), GGray); w->dirty = 0; } @@ -642,7 +642,7 @@ int main() do { select(0, 0, 0, 0, &(struct timeval){ 0, 30000 }); - win_redraw_frame(); + win_redraw_frame(w, 0); if (!g->nextevent(&e)) continue; if (e.type == GResize) @@ -26,7 +26,9 @@ struct w { unsigned cu; /* cursor offset */ EBuf *eb; /* underlying buffer object */ GRect rect; /* rectangle on the screen */ - int dirty; /* force redraw */ + int dirty: 1; /* force redraw */ + int insert: 1; /* inserting */ + int focus: 1; /* focused window */ }; enum CursorLoc { CTop, CMid, CBot }; @@ -38,7 +40,7 @@ unsigned win_at(W *w, int x, int y); W *win_which(int x, int y); void win_move(W *, int x, int y); void win_resize_frame(int w, int h); -void win_redraw_frame(void); +void win_redraw_frame(W *focus, int insert); void win_scroll(W *, int); void win_show_cursor(W *, enum CursorLoc); W *win_tag_toggle(W *); @@ -160,6 +160,15 @@ drawrect(GRect *clip, int x, int y, int w, int h, GColor c) } static void +drawcursor(GRect *clip, int insert, int x, int y, int w) +{ + if (insert) + drawrect(clip, x, y, 2, font->height, GXBlack); + else + drawrect(clip, x, y, w, font->height, GXBlack); +} + +static void decorate(GRect *clip, int dirty, GColor c) { int boxh; @@ -335,15 +344,16 @@ struct gui gui_x11 = { .init = init, .fini = fini, .sync = sync, - .decorate = decorate, + .decorate = decorate, .drawrect = drawrect, + .drawcursor = drawcursor, .drawtext = drawtext, .getfont = getfont, .nextevent = nextevent, - .setpointer = setpointer, + .setpointer = setpointer, .textwidth = textwidth, - .hmargin = HMargin, - .vmargin = VMargin, - .border = Border, - .actionr = {0, 0, 0, 0}, + .hmargin = HMargin, + .vmargin = VMargin, + .border = Border, + .actionr = {0, 0, 0, 0}, }; |
