From: ori@eigenstate.org
To: 9front@9front.org
Subject: rio triple click selection
Date: Sun, 12 Apr 2020 10:19:56 -0700 [thread overview]
Message-ID: <C7827F0F34D2D38F9BE060A6F635EF8E@eigenstate.org> (raw)
To improve plumbing in vt, I recently implemented triple click.
Doubleclick selects an alphanumeric segment. Triple click selects
a non-whitespace segment, making it easy to sleect paths, urls,
and other larger chunks of text.
tclick
v-----------v
x something/bar y
^-------^
dclick
This worked out well enough that it seems like a good idea to add
it to rio. Sam and Acme should probably get the same treatment.
Are there any other programs where text selection should be patched
to match?
Here's a patch that does this:
diff -r d0d202a26d24 sys/src/cmd/rio/dat.h
--- a/sys/src/cmd/rio/dat.h Sun Apr 12 16:12:41 2020 +0200
+++ b/sys/src/cmd/rio/dat.h Sun Apr 12 10:18:43 2020 -0700
@@ -195,7 +195,7 @@
void wcurrent(Window*);
void wcut(Window*);
void wdelete(Window*, uint, uint);
-void wdoubleclick(Window*, uint*, uint*);
+void wstretchsel(Window*, uint*, uint*, int);
void wfill(Window*);
void wframescroll(Window*, int);
void wkeyctl(Window*, Rune);
diff -r d0d202a26d24 sys/src/cmd/rio/fns.h
--- a/sys/src/cmd/rio/fns.h Sun Apr 12 16:12:41 2020 +0200
+++ b/sys/src/cmd/rio/fns.h Sun Apr 12 10:18:43 2020 -0700
@@ -9,6 +9,7 @@
int max(int, int);
Rune* strrune(Rune*, Rune);
int isalnum(Rune);
+int isspace(Rune);
void timerstop(Timer*);
void timercancel(Timer*);
Timer* timerstart(int);
diff -r d0d202a26d24 sys/src/cmd/rio/util.c
--- a/sys/src/cmd/rio/util.c Sun Apr 12 16:12:41 2020 +0200
+++ b/sys/src/cmd/rio/util.c Sun Apr 12 10:18:43 2020 -0700
@@ -105,6 +105,13 @@
return TRUE;
}
+int
+isspace(Rune c)
+{
+ return c == 0 || c == ' ' || c == '\t' ||
+ c == '\n' || c == '\r' || c == '\v';
+}
+
Rune*
strrune(Rune *s, Rune c)
{
diff -r d0d202a26d24 sys/src/cmd/rio/wind.c
--- a/sys/src/cmd/rio/wind.c Sun Apr 12 16:12:41 2020 +0200
+++ b/sys/src/cmd/rio/wind.c Sun Apr 12 10:18:43 2020 -0700
@@ -962,6 +962,7 @@
static Window *clickwin;
static uint clickmsec;
+static uint clickcount;
static Window *selectwin;
static uint selectq;
@@ -1007,7 +1008,7 @@
wselect(Window *w)
{
uint q0, q1;
- int b, x, y, first;
+ int b, x, y, dx, dy, mode, first;
first = 1;
selectwin = w;
@@ -1018,23 +1019,31 @@
q0 = w->q0;
q1 = w->q1;
selectq = w->org+frcharofpt(w, w->mc.xy);
- if(clickwin==w && w->mc.msec-clickmsec<500)
- if(q0==q1 && selectq==w->q0){
- wdoubleclick(w, &q0, &q1);
+ clickcount++;
+ if(w->mc.msec-clickmsec >= 500 || clickwin != w)
+ clickcount = 0;
+ if(clickwin == w && clickcount > 1 && w->mc.msec-clickmsec < 500){
+ mode = (clickcount > 2) ? 2 : clickcount;
+ wstretchsel(w, &q0, &q1, mode);
wsetselect(w, q0, q1);
x = w->mc.xy.x;
y = w->mc.xy.y;
/* stay here until something interesting happens */
- do
+ while(1){
readmouse(&w->mc);
- while(w->mc.buttons==b && abs(w->mc.xy.x-x)<3 && abs(w->mc.xy.y-y)<3);
+ dx = abs(w->mc.xy.x-x);
+ dy = abs(w->mc.xy.y-y);
+ if(w->mc.buttons != b || dx >= 3 && dy >= 3)
+ break;
+ clickcount++;
+ }
w->mc.xy.x = x; /* in case we're calling frselect */
w->mc.xy.y = y;
q0 = w->q0; /* may have changed */
q1 = w->q1;
selectq = q0;
}
- if(w->mc.buttons == b){
+ if(w->mc.buttons == b && clickcount == 0){
w->scroll = framescroll;
frselect(w, &w->mc);
/* horrible botch: while asleep, may have lost selection altogether */
@@ -1051,15 +1060,14 @@
q1 = w->org+w->p1;
}
if(q0 == q1){
+ mode = (clickcount > 2) ? 2 : clickcount;
if(q0==w->q0 && clickwin==w && w->mc.msec-clickmsec<500){
- wdoubleclick(w, &q0, &q1);
- clickwin = nil;
+ wstretchsel(w, &q0, &q1, mode);
}else{
clickwin = w;
clickmsec = w->mc.msec;
}
- }else
- clickwin = nil;
+ }
wsetselect(w, q0, q1);
while(w->mc.buttons){
w->mc.msec = 0;
@@ -1079,7 +1087,8 @@
wscrdraw(w);
while(w->mc.buttons == b)
readmouse(&w->mc);
- clickwin = nil;
+ if(w->mc.msec-clickmsec >= 500)
+ clickwin = nil;
}
}
@@ -1483,8 +1492,14 @@
nil
};
+int
+inmode(Rune r, int mode)
+{
+ return (mode == 1) ? isalnum(r) : r && !isspace(r);
+}
+
void
-wdoubleclick(Window *w, uint *q0, uint *q1)
+wstretchsel(Window *w, uint *q0, uint *q1, int mode)
{
int c, i;
Rune *r, *l, *p;
@@ -1522,10 +1537,10 @@
}
}
/* try filling out word to right */
- while(*q1<w->nr && isalnum(w->r[*q1]))
+ while(*q1<w->nr && inmode(w->r[*q1], mode))
(*q1)++;
/* try filling out word to left */
- while(*q0>0 && isalnum(w->r[*q0-1]))
+ while(*q0>0 && inmode(w->r[*q0-1], mode))
(*q0)--;
}
next reply other threads:[~2020-04-12 17:19 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-12 17:19 ori [this message]
2020-04-12 17:44 ` [9front] " Stanley Lieber
2020-04-13 5:15 ` ori
2020-04-25 5:48 ` ori
2020-04-25 12:44 ` Ethan Gardener
2020-04-25 14:00 ` cinap_lenrek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=C7827F0F34D2D38F9BE060A6F635EF8E@eigenstate.org \
--to=ori@eigenstate.org \
--cc=9front@9front.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).