9front - general discussion about 9front
 help / color / mirror / Atom feed
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)--;
 }
 



             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).