svn commit: r197539 - in head/sys: dev/syscons teken

Ed Schouten ed at FreeBSD.org
Sun Sep 27 18:19:42 UTC 2009


Author: ed
Date: Sun Sep 27 18:19:41 2009
New Revision: 197539
URL: http://svn.freebsd.org/changeset/base/197539

Log:
  Add support for VT200-style mouse input.
  
  Right now if applications want to use the mouse on the command line,
  they use sysmouse(4) and install a signal handler in the kernel to
  deliver signals when mouse events arrive. This conflicts with my plan to
  change to TERM=xterm, so implement proper VT200-style mouse input.
  
  Because mouse input is now streamed through the TTY, it means you can
  now SSH to another system on the console and use the mouse there as
  well. The disadvantage of the VT200 mouse protocol, is that it doesn't
  seem to generate events when moving the cursor. Only when pressing and
  releasing mouse buttons.
  
  There are different protocols as well, but this one seems to be most
  commonly supported.
  
  Reported by:	Paul B. Mahol <onemda gmail com>
  Tested with:	vim(1)

Modified:
  head/sys/dev/syscons/scmouse.c
  head/sys/dev/syscons/scterm-teken.c
  head/sys/dev/syscons/syscons.c
  head/sys/dev/syscons/syscons.h
  head/sys/teken/teken.h
  head/sys/teken/teken_subr.h

Modified: head/sys/dev/syscons/scmouse.c
==============================================================================
--- head/sys/dev/syscons/scmouse.c	Sun Sep 27 17:33:26 2009	(r197538)
+++ head/sys/dev/syscons/scmouse.c	Sun Sep 27 18:19:41 2009	(r197539)
@@ -117,6 +117,48 @@ sc_alloc_cut_buffer(scr_stat *scp, int w
 }
 #endif /* SC_NO_CUTPASTE */
 
+static void
+sc_mouse_input_button(scr_stat *scp, int button)
+{
+	char mouseb[6] = "\x1B[M";
+
+	mouseb[3] = ' ' + button;
+	mouseb[4] = '!' + scp->mouse_pos % scp->xsize;
+	mouseb[5] = '!' + scp->mouse_pos / scp->xsize;
+	sc_respond(scp, mouseb, sizeof mouseb, 1);
+}
+
+static void
+sc_mouse_input(scr_stat *scp, mouse_info_t *mouse)
+{
+
+	switch (mouse->operation) {
+	case MOUSE_BUTTON_EVENT:
+		if (mouse->u.event.value > 0) {
+			/* Mouse button pressed. */
+			if (mouse->u.event.id & MOUSE_BUTTON1DOWN)
+				sc_mouse_input_button(scp, 0);
+			if (mouse->u.event.id & MOUSE_BUTTON2DOWN)
+				sc_mouse_input_button(scp, 1);
+			if (mouse->u.event.id & MOUSE_BUTTON3DOWN)
+				sc_mouse_input_button(scp, 2);
+		} else {
+			/* Mouse button released. */
+			sc_mouse_input_button(scp, 3);
+		}
+		break;
+	case MOUSE_MOTION_EVENT:
+		if (mouse->u.data.z < 0) {
+			/* Scroll up. */
+			sc_mouse_input_button(scp, 64);
+		} else if (mouse->u.data.z > 0) {
+			/* Scroll down. */
+			sc_mouse_input_button(scp, 65);
+		}
+		break;
+	}
+}
+
 /* move mouse */
 void
 sc_mouse_move(scr_stat *scp, int x, int y)
@@ -755,6 +797,11 @@ sc_mouse_ioctl(struct tty *tp, u_long cm
 
 	    cur_scp->status &= ~MOUSE_HIDDEN;
 
+	    if (cur_scp->mouse_level > 0) {
+	    	sc_mouse_input(scp, mouse);
+		break;
+	    }
+
 	    if (cur_scp->mouse_signal && cur_scp->mouse_proc) {
     		/* has controlling process died? */
 		if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))) {
@@ -811,6 +858,11 @@ sc_mouse_ioctl(struct tty *tp, u_long cm
 
 	    cur_scp->status &= ~MOUSE_HIDDEN;
 
+	    if (cur_scp->mouse_level > 0) {
+	    	sc_mouse_input(scp, mouse);
+		break;
+	    }
+
 	    if (cur_scp->mouse_signal && cur_scp->mouse_proc) {
 		if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))){
 		    	cur_scp->mouse_signal = 0;

Modified: head/sys/dev/syscons/scterm-teken.c
==============================================================================
--- head/sys/dev/syscons/scterm-teken.c	Sun Sep 27 17:33:26 2009	(r197538)
+++ head/sys/dev/syscons/scterm-teken.c	Sun Sep 27 18:19:41 2009	(r197539)
@@ -644,6 +644,9 @@ scteken_param(void *arg, int cmd, unsign
 		scp->bell_pitch = TP_SETBELLPD_PITCH(value);
 		scp->bell_duration = TP_SETBELLPD_DURATION(value);
 		break;
+	case TP_MOUSE:
+		scp->mouse_level = value;
+		break;
 	}
 }
 
@@ -652,5 +655,5 @@ scteken_respond(void *arg, const void *b
 {
 	scr_stat *scp = arg;
 
-	sc_respond(scp, buf, len);
+	sc_respond(scp, buf, len, 0);
 }

Modified: head/sys/dev/syscons/syscons.c
==============================================================================
--- head/sys/dev/syscons/syscons.c	Sun Sep 27 17:33:26 2009	(r197538)
+++ head/sys/dev/syscons/syscons.c	Sun Sep 27 18:19:41 2009	(r197539)
@@ -3561,19 +3561,18 @@ sc_paste(scr_stat *scp, const u_char *p,
 }
 
 void
-sc_respond(scr_stat *scp, const u_char *p, int count) 
+sc_respond(scr_stat *scp, const u_char *p, int count, int wakeup) 
 {
     struct tty *tp;
 
     tp = SC_DEV(scp->sc, scp->sc->cur_scp->index);
     if (!tty_opened(tp))
 	return;
-    for (; count > 0; --count)
-	ttydisc_rint(tp, *p++, 0);
-#if 0
-    /* XXX: we can't call ttydisc_rint_done() here! */
-    ttydisc_rint_done(tp);
-#endif
+    ttydisc_rint_simple(tp, p, count);
+    if (wakeup) {
+	/* XXX: we can't always call ttydisc_rint_done() here! */
+	ttydisc_rint_done(tp);
+    }
 }
 
 void

Modified: head/sys/dev/syscons/syscons.h
==============================================================================
--- head/sys/dev/syscons/syscons.h	Sun Sep 27 17:33:26 2009	(r197538)
+++ head/sys/dev/syscons/syscons.h	Sun Sep 27 18:19:41 2009	(r197539)
@@ -314,6 +314,7 @@ typedef struct scr_stat {
 	short		mouse_buttons;		/* mouse buttons */
 	int		mouse_cut_start;	/* mouse cut start pos */
 	int		mouse_cut_end;		/* mouse cut end pos */
+	int		mouse_level;		/* xterm mouse protocol */
 	struct proc 	*mouse_proc;		/* proc* of controlling proc */
 	pid_t 		mouse_pid;		/* pid of controlling proc */
 	int		mouse_signal;		/* signal # to report with */
@@ -564,7 +565,8 @@ int		sc_switch_scr(sc_softc_t *sc, u_int
 void		sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard);
 int		sc_init_emulator(scr_stat *scp, char *name);
 void		sc_paste(scr_stat *scp, const u_char *p, int count);
-void		sc_respond(scr_stat *scp, const u_char *p, int count);
+void		sc_respond(scr_stat *scp, const u_char *p,
+			   int count, int wakeup);
 void		sc_bell(scr_stat *scp, int pitch, int duration);
 
 /* schistory.c */

Modified: head/sys/teken/teken.h
==============================================================================
--- head/sys/teken/teken.h	Sun Sep 27 17:33:26 2009	(r197538)
+++ head/sys/teken/teken.h	Sun Sep 27 18:19:41 2009	(r197539)
@@ -97,6 +97,7 @@ typedef void tf_param_t(void *, int, uns
 #define	TP_SETBELLPD	6
 #define	TP_SETBELLPD_PITCH(pd)		((pd) >> 16)
 #define	TP_SETBELLPD_DURATION(pd)	((pd) & 0xffff)
+#define	TP_MOUSE	7
 typedef void tf_respond_t(void *, const void *, size_t);
 
 typedef struct {

Modified: head/sys/teken/teken_subr.h
==============================================================================
--- head/sys/teken/teken_subr.h	Sun Sep 27 17:33:26 2009	(r197538)
+++ head/sys/teken/teken_subr.h	Sun Sep 27 18:19:41 2009	(r197539)
@@ -932,6 +932,9 @@ teken_subr_reset_dec_mode(teken_t *t, un
 	case 47: /* Switch to alternate buffer. */
 		teken_printf("Switch to alternate buffer\n");
 		break;
+	case 1000: /* Mouse input. */
+		teken_funcs_param(t, TP_MOUSE, 0);
+		break;
 	default:
 		teken_printf("Unknown DECRST: %u\n", cmd);
 	}
@@ -1078,6 +1081,9 @@ teken_subr_set_dec_mode(teken_t *t, unsi
 	case 47: /* Switch to alternate buffer. */
 		teken_printf("Switch away from alternate buffer\n");
 		break;
+	case 1000: /* Mouse input. */
+		teken_funcs_param(t, TP_MOUSE, 1);
+		break;
 	default:
 		teken_printf("Unknown DECSET: %u\n", cmd);
 	}


More information about the svn-src-all mailing list