diff options
| author | Devin J. Pohly <djpohly@gmail.com> | 2018-02-21 23:29:41 -0600 |
|---|---|---|
| committer | Devin J. Pohly <djpohly@gmail.com> | 2018-02-25 21:53:24 -0600 |
| commit | bcb5d3adbe57ead05a829e5144c2ba1dc465865f (patch) | |
| tree | d72e99c54044e02063924f2416ceb9760c2141ec | |
| parent | 5683b1f80c5ac274adf98517ce2217b4d4896243 (diff) | |
| download | st-bcb5d3adbe57ead05a829e5144c2ba1dc465865f.tar.gz st-bcb5d3adbe57ead05a829e5144c2ba1dc465865f.zip | |
Move terminal-related selection logic into st.c
The front-end determines information about mouse clicks and motion, and
the terminal handles the actual selection start/extend/dirty logic by
row and column.
While we're in the neighborhood, we'll also rename getbuttoninfo() to
mousesel() which is, at least, less wrong.
Signed-off-by: Devin J. Pohly <djpohly@gmail.com>
| -rw-r--r-- | st.c | 37 | ||||
| -rw-r--r-- | st.h | 3 | ||||
| -rw-r--r-- | x.c | 55 |
3 files changed, 54 insertions, 41 deletions
| @@ -140,6 +140,7 @@ static void tscrollup(int, int); | |||
| 140 | static void tscrolldown(int, int); | 140 | static void tscrolldown(int, int); |
| 141 | static void tsetattr(int *, int); | 141 | static void tsetattr(int *, int); |
| 142 | static void tsetchar(Rune, Glyph *, int, int); | 142 | static void tsetchar(Rune, Glyph *, int, int); |
| 143 | static void tsetdirt(int, int); | ||
| 143 | static void tsetscroll(int, int); | 144 | static void tsetscroll(int, int); |
| 144 | static void tswapscreen(void); | 145 | static void tswapscreen(void); |
| 145 | static void tsetmode(int, int, int *, int); | 146 | static void tsetmode(int, int, int *, int); |
| @@ -385,6 +386,42 @@ tlinelen(int y) | |||
| 385 | } | 386 | } |
| 386 | 387 | ||
| 387 | void | 388 | void |
| 389 | selstart(int col, int row, int snap) | ||
| 390 | { | ||
| 391 | selclear(); | ||
| 392 | sel.mode = SEL_EMPTY; | ||
| 393 | sel.type = SEL_REGULAR; | ||
| 394 | sel.snap = snap; | ||
| 395 | sel.oe.x = sel.ob.x = col; | ||
| 396 | sel.oe.y = sel.ob.y = row; | ||
| 397 | selnormalize(); | ||
| 398 | |||
| 399 | if (sel.snap != 0) | ||
| 400 | sel.mode = SEL_READY; | ||
| 401 | tsetdirt(sel.nb.y, sel.ne.y); | ||
| 402 | } | ||
| 403 | |||
| 404 | void | ||
| 405 | selextend(int col, int row, int type) | ||
| 406 | { | ||
| 407 | int oldey, oldex, oldsby, oldsey, oldtype; | ||
| 408 | oldey = sel.oe.y; | ||
| 409 | oldex = sel.oe.x; | ||
| 410 | oldsby = sel.nb.y; | ||
| 411 | oldsey = sel.ne.y; | ||
| 412 | oldtype = sel.type; | ||
| 413 | |||
| 414 | sel.alt = IS_SET(MODE_ALTSCREEN); | ||
| 415 | sel.oe.x = col; | ||
| 416 | sel.oe.y = row; | ||
| 417 | selnormalize(); | ||
| 418 | sel.type = type; | ||
| 419 | |||
| 420 | if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) | ||
| 421 | tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); | ||
| 422 | } | ||
| 423 | |||
| 424 | void | ||
| 388 | selnormalize(void) | 425 | selnormalize(void) |
| 389 | { | 426 | { |
| 390 | int i; | 427 | int i; |
| @@ -172,7 +172,6 @@ void toggleprinter(const Arg *); | |||
| 172 | int tattrset(int); | 172 | int tattrset(int); |
| 173 | void tnew(int, int); | 173 | void tnew(int, int); |
| 174 | void tresize(int, int); | 174 | void tresize(int, int); |
| 175 | void tsetdirt(int, int); | ||
| 176 | void tsetdirtattr(int); | 175 | void tsetdirtattr(int); |
| 177 | void ttynew(char *, char *, char **); | 176 | void ttynew(char *, char *, char **); |
| 178 | size_t ttyread(void); | 177 | size_t ttyread(void); |
| @@ -184,6 +183,8 @@ void resettitle(void); | |||
| 184 | 183 | ||
| 185 | void selclear(void); | 184 | void selclear(void); |
| 186 | void selinit(void); | 185 | void selinit(void); |
| 186 | void selstart(int, int, int); | ||
| 187 | void selextend(int, int, int); | ||
| 187 | void selnormalize(void); | 188 | void selnormalize(void); |
| 188 | int selected(int, int); | 189 | int selected(int, int); |
| 189 | char *getsel(void); | 190 | char *getsel(void); |
| @@ -157,7 +157,7 @@ static void selnotify(XEvent *); | |||
| 157 | static void selclear_(XEvent *); | 157 | static void selclear_(XEvent *); |
| 158 | static void selrequest(XEvent *); | 158 | static void selrequest(XEvent *); |
| 159 | static void setsel(char *, Time); | 159 | static void setsel(char *, Time); |
| 160 | static void getbuttoninfo(XEvent *); | 160 | static void mousesel(XEvent *); |
| 161 | static void mousereport(XEvent *); | 161 | static void mousereport(XEvent *); |
| 162 | static char *kmap(KeySym, uint); | 162 | static char *kmap(KeySym, uint); |
| 163 | static int match(uint, uint); | 163 | static int match(uint, uint); |
| @@ -313,24 +313,19 @@ y2row(int y) | |||
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | void | 315 | void |
| 316 | getbuttoninfo(XEvent *e) | 316 | mousesel(XEvent *e) |
| 317 | { | 317 | { |
| 318 | int type; | 318 | int type, seltype = SEL_REGULAR; |
| 319 | uint state = e->xbutton.state & ~(Button1Mask | forceselmod); | 319 | uint state = e->xbutton.state & ~(Button1Mask | forceselmod); |
| 320 | 320 | ||
| 321 | sel.alt = IS_SET(MODE_ALTSCREEN); | ||
| 322 | |||
| 323 | sel.oe.x = x2col(e->xbutton.x); | ||
| 324 | sel.oe.y = y2row(e->xbutton.y); | ||
| 325 | selnormalize(); | ||
| 326 | |||
| 327 | sel.type = SEL_REGULAR; | ||
| 328 | for (type = 1; type < LEN(selmasks); ++type) { | 321 | for (type = 1; type < LEN(selmasks); ++type) { |
| 329 | if (match(selmasks[type], state)) { | 322 | if (match(selmasks[type], state)) { |
| 330 | sel.type = type; | 323 | seltype = type; |
| 331 | break; | 324 | break; |
| 332 | } | 325 | } |
| 333 | } | 326 | } |
| 327 | |||
| 328 | selextend(x2col(e->xbutton.x), y2row(e->xbutton.y), seltype); | ||
| 334 | } | 329 | } |
| 335 | 330 | ||
| 336 | void | 331 | void |
| @@ -402,6 +397,7 @@ bpress(XEvent *e) | |||
| 402 | { | 397 | { |
| 403 | struct timespec now; | 398 | struct timespec now; |
| 404 | MouseShortcut *ms; | 399 | MouseShortcut *ms; |
| 400 | int snap; | ||
| 405 | 401 | ||
| 406 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { | 402 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { |
| 407 | mousereport(e); | 403 | mousereport(e); |
| @@ -417,33 +413,22 @@ bpress(XEvent *e) | |||
| 417 | } | 413 | } |
| 418 | 414 | ||
| 419 | if (e->xbutton.button == Button1) { | 415 | if (e->xbutton.button == Button1) { |
| 420 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
| 421 | |||
| 422 | /* Clear previous selection, logically and visually. */ | ||
| 423 | selclear_(NULL); | ||
| 424 | sel.mode = SEL_EMPTY; | ||
| 425 | sel.type = SEL_REGULAR; | ||
| 426 | sel.oe.x = sel.ob.x = x2col(e->xbutton.x); | ||
| 427 | sel.oe.y = sel.ob.y = y2row(e->xbutton.y); | ||
| 428 | |||
| 429 | /* | 416 | /* |
| 430 | * If the user clicks below predefined timeouts specific | 417 | * If the user clicks below predefined timeouts specific |
| 431 | * snapping behaviour is exposed. | 418 | * snapping behaviour is exposed. |
| 432 | */ | 419 | */ |
| 420 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
| 433 | if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { | 421 | if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { |
| 434 | sel.snap = SNAP_LINE; | 422 | snap = SNAP_LINE; |
| 435 | } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { | 423 | } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { |
| 436 | sel.snap = SNAP_WORD; | 424 | snap = SNAP_WORD; |
| 437 | } else { | 425 | } else { |
| 438 | sel.snap = 0; | 426 | snap = 0; |
| 439 | } | 427 | } |
| 440 | selnormalize(); | ||
| 441 | |||
| 442 | if (sel.snap != 0) | ||
| 443 | sel.mode = SEL_READY; | ||
| 444 | tsetdirt(sel.nb.y, sel.ne.y); | ||
| 445 | xsel.tclick2 = xsel.tclick1; | 428 | xsel.tclick2 = xsel.tclick1; |
| 446 | xsel.tclick1 = now; | 429 | xsel.tclick1 = now; |
| 430 | |||
| 431 | selstart(x2col(e->xbutton.x), y2row(e->xbutton.y), snap); | ||
| 447 | } | 432 | } |
| 448 | } | 433 | } |
| 449 | 434 | ||
| @@ -649,20 +634,17 @@ brelease(XEvent *e) | |||
| 649 | selpaste(NULL); | 634 | selpaste(NULL); |
| 650 | } else if (e->xbutton.button == Button1) { | 635 | } else if (e->xbutton.button == Button1) { |
| 651 | if (sel.mode == SEL_READY) { | 636 | if (sel.mode == SEL_READY) { |
| 652 | getbuttoninfo(e); | 637 | mousesel(e); |
| 653 | setsel(getsel(), e->xbutton.time); | 638 | setsel(getsel(), e->xbutton.time); |
| 654 | } else | 639 | } else |
| 655 | selclear_(NULL); | 640 | selclear_(NULL); |
| 656 | sel.mode = SEL_IDLE; | 641 | sel.mode = SEL_IDLE; |
| 657 | tsetdirt(sel.nb.y, sel.ne.y); | ||
| 658 | } | 642 | } |
| 659 | } | 643 | } |
| 660 | 644 | ||
| 661 | void | 645 | void |
| 662 | bmotion(XEvent *e) | 646 | bmotion(XEvent *e) |
| 663 | { | 647 | { |
| 664 | int oldey, oldex, oldsby, oldsey; | ||
| 665 | |||
| 666 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { | 648 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { |
| 667 | mousereport(e); | 649 | mousereport(e); |
| 668 | return; | 650 | return; |
| @@ -672,14 +654,7 @@ bmotion(XEvent *e) | |||
| 672 | return; | 654 | return; |
| 673 | 655 | ||
| 674 | sel.mode = SEL_READY; | 656 | sel.mode = SEL_READY; |
| 675 | oldey = sel.oe.y; | 657 | mousesel(e); |
| 676 | oldex = sel.oe.x; | ||
| 677 | oldsby = sel.nb.y; | ||
| 678 | oldsey = sel.ne.y; | ||
| 679 | getbuttoninfo(e); | ||
| 680 | |||
| 681 | if (oldey != sel.oe.y || oldex != sel.oe.x) | ||
| 682 | tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); | ||
| 683 | } | 658 | } |
| 684 | 659 | ||
| 685 | void | 660 | void |
