Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Aug 2017 07:04:41 +0000 (UTC)
From:      Bruce Evans <bde@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r322878 - in head: sys/dev/syscons sys/sys usr.sbin/vidcontrol
Message-ID:  <201708250704.v7P74fE9028895@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bde
Date: Fri Aug 25 07:04:41 2017
New Revision: 322878
URL: https://svnweb.freebsd.org/changeset/base/322878

Log:
  Support setting the colors of cursors for the VGA renderer.
  
  Advertise this by changing the defaults to mostly red.  If you don't like
  this, change them (almost) back using:
     vidcontrol -c charcolors,base=7,height=0
     vidcontrol -c mousecolors,base=0[,height=15]
  
  The (graphics mode only) mouse cursor colors were hard-coded to a black
  border and lightwhite interior.  Black for the border is the worst
  possible default, since it is the same as the default black background
  and not good for any dark background.  Reversing this gives the better
  default of X Windows.  Coloring everything works better still.  Now
  the coloring defaults to a lightwhite border and red interior.
  
  Coloring for the character cursor is more complicated and mode
  dependent.  The new coloring doesn't apply for hardware cursors.  For
  non-block cursors, it only applies in graphics mode.  In text mode,
  the cursor color was usually a hard-coded (dull)white for the background
  only, unless the foreground was white when it was a hard-coded black
  for the background only, unless the foreground was white and the
  background was black it was reverse video.  In graphics mode, it was
  always reverse video for the block cursor.  Reverse video is worse,
  especially over cutmarking regions, since cutmarking still uses simple
  reverse video (nothing better is possible in text mode) and double
  reverse video for the cursor gives normal video.  Now, graphics mode
  uses the same algorithm as the best case for text mode in all cases
  for graphics mode.  The hard-coded sequence { white, black, } for the
  background is now { red, white, blue, } where the first 2 colors can
  be configured.  The blue color at the end is a sentinel which prevents
  reverse video being used in most cases but breaks the compatibility
  setting for white on black and black on white characters.  This will
  be fixed later.  The compatibility setting is most needed for mono modes.
  
  The previous commit to syscons.c changed sc_cnterm() to be more careful.
  It followed null pointers in some cases.  But sc_cnterm() has been
  unreachable for 15+ years since changes for multiple consoles turned
  off calls to the the cnterm destructor for all console drivers.  Before
  them, it was only called at boot time.  So no driver with an attached
  console has ever been unloadable and not even the non-console destructors
  have been tested much.

Modified:
  head/sys/dev/syscons/scvgarndr.c
  head/sys/dev/syscons/syscons.c
  head/sys/dev/syscons/syscons.h
  head/sys/sys/consio.h
  head/usr.sbin/vidcontrol/vidcontrol.1
  head/usr.sbin/vidcontrol/vidcontrol.c

Modified: head/sys/dev/syscons/scvgarndr.c
==============================================================================
--- head/sys/dev/syscons/scvgarndr.c	Fri Aug 25 05:49:37 2017	(r322877)
+++ head/sys/dev/syscons/scvgarndr.c	Fri Aug 25 07:04:41 2017	(r322878)
@@ -356,32 +356,28 @@ vga_flipattr(u_short a, int blink)
 }
 
 static u_short
-vga_cursorattr_adj(u_short a, int blink)
+vga_cursorattr_adj(scr_stat *scp, u_short a, int blink)
 {
-	/*
-	 * !blink means pixel mode, and the cursor attribute in that case
-	 * is simplistic reverse video.
-	 */
-	if (!blink)
-		return (vga_flipattr(a, blink));
+	int i;
+	u_short bg, bgmask, fg, newbg;
 
 	/*
 	 * The cursor attribute is usually that of the underlying char
-	 * with the bg changed to white.  If the bg is already white,
-	 * then the bg is changed to black.  The fg is usually not
-	 * changed, but if it is the same as the new bg then it is
-	 * changed to the inverse of the new bg.
+	 * with only the bg changed, to the first preferred color that
+	 * differs from both the fg and bg.  If there is no such color,
+	 * use reverse video.
 	 */
-	if ((a & 0x7000) == 0x7000) {
-		a &= 0x8f00;
-		if ((a & 0x0700) == 0)
-			a |= 0x0700;
-	} else {
-		a |= 0x7000;
-		if ((a & 0x0700) == 0x0700)
-			a &= 0xf000;
+	bgmask = blink ? 0x7000 : 0xf000;
+	bg = a & bgmask;
+	fg = a & 0x0f00;
+	for (i = 0; i < nitems(scp->curs_attr.bg); i++) {
+		newbg = (scp->curs_attr.bg[i] << 12) & bgmask;
+		if (newbg != bg && newbg != (fg << 4))
+			break;
 	}
-	return (a);
+	if (i == nitems(scp->curs_attr.bg))
+		return (vga_flipattr(a, blink));
+	return (fg | newbg | (blink ? a & 0x8000 : 0));
 }
 
 static void
@@ -522,6 +518,12 @@ draw_txtcharcursor(scr_stat *scp, int at, u_short c, u
 			return;
 		if (flip)
 			a = vga_flipattr(a, TRUE);
+		/*
+		 * This clause handles partial-block cursors in text mode.
+		 * We want to change the attribute only under the partial
+		 * block, but in text mode we can only change full blocks.
+		 * Use reverse video instead.
+		 */
 		bcopy(font + c*h, font + sc->cursor_char*h, h);
 		font = font + sc->cursor_char*h;
 		for (i = imax(h - scp->curs_attr.base - scp->curs_attr.height, 0);
@@ -536,7 +538,7 @@ draw_txtcharcursor(scr_stat *scp, int at, u_short c, u
 	{
 		if (flip)
 			a = vga_flipattr(a, TRUE);
-		a = vga_cursorattr_adj(a, TRUE);
+		a = vga_cursorattr_adj(scp, a, TRUE);
 		sc_vtb_putc(&scp->scr, at, c, a);
 	}
 }
@@ -1026,7 +1028,7 @@ draw_pxlcursor_direct(scr_stat *scp, int at, int on, i
 	if (flip)
 		a = vga_flipattr(a, FALSE);
 	if (on)
-		a = vga_cursorattr_adj(a, FALSE);
+		a = vga_cursorattr_adj(scp, a, FALSE);
 	col1 = (a & 0x0f00) >> 8;
 	col2 = a >> 12;
 
@@ -1070,7 +1072,7 @@ draw_pxlcursor_planar(scr_stat *scp, int at, int on, i
 	if (flip)
 		a = vga_flipattr(a, FALSE);
 	if (on)
-		a = vga_cursorattr_adj(a, FALSE);
+		a = vga_cursorattr_adj(scp, a, FALSE);
 	col = (a & 0xf000) >> 4;
 	outw(GDCIDX, col | 0x00);	/* set/reset */
 	outw(GDCIDX, 0xff08);		/* bit mask */
@@ -1202,7 +1204,7 @@ draw_pxlmouse_planar(scr_stat *scp, int x, int y)
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
 	outw(GDCIDX, 0x0f01);		/* set/reset enable */
 
-	outw(GDCIDX, (0 << 8) | 0x00); /* set/reset */
+	outw(GDCIDX, (scp->curs_attr.mouse_ba << 8) | 0x00); /* set/reset */
 	p = scp->sc->adp->va_window + line_width*y + x/8;
 	for (i = y, j = 0; i < ymax; ++i, ++j) {
 		m = mdp->md_border[j] << 8 >> xoff;
@@ -1221,7 +1223,7 @@ draw_pxlmouse_planar(scr_stat *scp, int x, int y)
 		}
 		p += line_width;
 	}
-	outw(GDCIDX, (15 << 8) | 0x00); /* set/reset */
+	outw(GDCIDX, (scp->curs_attr.mouse_ia << 8) | 0x00); /* set/reset */
 	p = scp->sc->adp->va_window + line_width*y + x/8;
 	for (i = y, j = 0; i < ymax; ++i, ++j) {
 		m = mdp->md_interior[j] << 8 >> xoff;
@@ -1325,9 +1327,11 @@ do_on:
 	for (i = 0; i < yend - y; i++, p += line_width)
 		for (j = xend - x - 1; j >= 0; j--)
 			if (mdp->md_interior[i] & (1 << (15 - j)))
-				DRAW_PIXEL(scp, p + j * pixel_size, 15);
+				DRAW_PIXEL(scp, p + j * pixel_size,
+				    scp->curs_attr.mouse_ia);
 			else if (mdp->md_border[i] & (1 << (15 - j)))
-				DRAW_PIXEL(scp, p + j * pixel_size, 0);
+				DRAW_PIXEL(scp, p + j * pixel_size,
+				    scp->curs_attr.mouse_ba);
 }
 
 static void 

Modified: head/sys/dev/syscons/syscons.c
==============================================================================
--- head/sys/dev/syscons/syscons.c	Fri Aug 25 05:49:37 2017	(r322877)
+++ head/sys/dev/syscons/syscons.c	Fri Aug 25 07:04:41 2017	(r322878)
@@ -959,8 +959,16 @@ sctty_ioctl(struct tty *tp, u_long cmd, caddr_t data, 
 	    cap = &scp->dflt_curs_attr;
 	    break;
 	}
-	((int *)data)[1] = cap->base;
-	((int *)data)[2] = cap->height;
+	if (((int *)data)[0] & CONS_CHARCURSOR_COLORS) {
+	    ((int *)data)[1] = cap->bg[0];
+	    ((int *)data)[2] = cap->bg[1];
+	} else if (((int *)data)[0] & CONS_MOUSECURSOR_COLORS) {
+	    ((int *)data)[1] = cap->mouse_ba;
+	    ((int *)data)[2] = cap->mouse_ia;
+	} else {
+	    ((int *)data)[1] = cap->base;
+	    ((int *)data)[2] = cap->height;
+	}
 	((int *)data)[0] = cap->flags;
 	return 0;
 
@@ -3025,8 +3033,12 @@ sc_set_cursor_image(scr_stat *scp)
 static void
 sc_adjust_ca(struct cursor_attr *cap, int flags, int base, int height)
 {
-    if (0) {
-	/* Dummy clause to avoid changing indentation later. */
+    if (flags & CONS_CHARCURSOR_COLORS) {
+	cap->bg[0] = base & 0xff;
+	cap->bg[1] = height & 0xff;
+    } else if (flags & CONS_MOUSECURSOR_COLORS) {
+	cap->mouse_ba = base & 0xff;
+	cap->mouse_ia = height & 0xff;
     } else {
 	if (base >= 0)
 	    cap->base = base;
@@ -3243,8 +3255,14 @@ scinit(int unit, int flags)
 	sc->dflt_curs_attr.base = 0;
 	sc->dflt_curs_attr.height = howmany(scp->font_size, 8);
 	sc->dflt_curs_attr.flags = 0;
+	sc->dflt_curs_attr.bg[0] = FG_RED;
+	sc->dflt_curs_attr.bg[1] = FG_LIGHTGREY;
+	sc->dflt_curs_attr.bg[2] = FG_BLUE;
+	sc->dflt_curs_attr.mouse_ba = FG_WHITE;
+	sc->dflt_curs_attr.mouse_ia = FG_RED;
 	sc->curs_attr = sc->dflt_curs_attr;
 	scp->base_curs_attr = scp->dflt_curs_attr = sc->curs_attr;
+	scp->curs_attr = scp->base_curs_attr;
 
 #ifndef SC_NO_SYSMOUSE
 	sc_mouse_move(scp, scp->xpixel/2, scp->ypixel/2);

Modified: head/sys/dev/syscons/syscons.h
==============================================================================
--- head/sys/dev/syscons/syscons.h	Fri Aug 25 05:49:37 2017	(r322877)
+++ head/sys/dev/syscons/syscons.h	Fri Aug 25 07:04:41 2017	(r322878)
@@ -167,11 +167,14 @@ typedef struct sc_vtb {
 	int		vtb_tail;	/* valid for VTB_RINGBUFFER only */
 } sc_vtb_t;
 
-/* text cursor attributes */
+/* text and some mouse cursor attributes */
 struct cursor_attr {
-	int		flags;
-	int		base;
-	int		height;
+	u_char		flags;
+	u_char		base;
+	u_char		height;
+	u_char		bg[3];
+	u_char		mouse_ba;
+	u_char		mouse_ia;
 };
 
 /* softc */

Modified: head/sys/sys/consio.h
==============================================================================
--- head/sys/sys/consio.h	Fri Aug 25 05:49:37 2017	(r322877)
+++ head/sys/sys/consio.h	Fri Aug 25 07:04:41 2017	(r322878)
@@ -187,6 +187,8 @@ typedef struct mouse_info mouse_info_t;
 #define CONS_HIDDEN_CURSOR	(1 << 2)
 #define CONS_CURSOR_ATTRS	(CONS_BLINK_CURSOR | CONS_CHAR_CURSOR |	\
 				 CONS_HIDDEN_CURSOR)
+#define CONS_CHARCURSOR_COLORS	(1 << 26)
+#define CONS_MOUSECURSOR_COLORS	(1 << 27)
 #define CONS_DEFAULT_CURSOR	(1 << 28)
 #define CONS_SHAPEONLY_CURSOR	(1 << 29)
 #define CONS_RESET_CURSOR	(1 << 30)

Modified: head/usr.sbin/vidcontrol/vidcontrol.1
==============================================================================
--- head/usr.sbin/vidcontrol/vidcontrol.1	Fri Aug 25 05:49:37 2017	(r322877)
+++ head/usr.sbin/vidcontrol/vidcontrol.1	Fri Aug 25 07:04:41 2017	(r322878)
@@ -219,6 +219,50 @@ Set or clear the hidden attribute.
 The following (non-sticky) flags control application of the
 .Cm setting Ns s :
 .Bl -tag -width indent
+.It Cm charcolors
+Apply
+.Cm base
+and
+.Cm height
+to the (character) cursor's list of preferred colors instead of its shape.
+Beware that the color numbers are raw VGA palette indexes,
+not ANSI color numbers.
+The indexes are reduced mod 8, 16 or 256,
+or ignored,
+depending on the video mode and renderer.
+.It Cm mousecolors
+Colors for the mouse cursor in graphics mode.
+Like
+.Cm charcolors ,
+except there is no preference or sequence;
+.Cm base
+gives the mouse border color and
+.Cm height
+gives the mouse interior color.
+Together with
+.Cm charcolors ,
+this gives 2 selection bits which select between
+only 3 of 4 sub-destinations of the 4 destinations selected by
+.Cm default
+and
+.Cm local
+(by ignoring
+.Cm mousecolors
+if
+.Cm charcolors
+is also set).
+.It Cm default
+Apply the changes to the default settings and then to the active settings,
+instead of only to the active settings.
+Together with
+.Cm local ,
+this gives 2 selection bits which select between 4 destinations.
+.It Cm shapeonly
+Ignore any changes to the 
+.Cm block
+and
+.Cm hidden
+attributes.
 .It Cm local
 Apply the changes to the current vty.
 The default is to apply them to a global place
@@ -233,10 +277,8 @@ to default local settings.
 Otherwise, the current global settings are reset to default
 global settings and then copied to the current and default
 settings for all vtys.
-The global defaults are decided (not quite right) at boot time
-and cannot be fixed up.
-The local defaults are obtained as above and cannot be fixed up
-locally.
+.It Cm show
+Show the current changes.
 .El
 .It Fl d
 Print out current output screen map.

Modified: head/usr.sbin/vidcontrol/vidcontrol.c
==============================================================================
--- head/usr.sbin/vidcontrol/vidcontrol.c	Fri Aug 25 05:49:37 2017	(r322877)
+++ head/usr.sbin/vidcontrol/vidcontrol.c	Fri Aug 25 07:04:41 2017	(r322878)
@@ -650,10 +650,21 @@ parse_cursor_params(char *param, struct cshape *shape)
 			shape->shape[1] = strtol(word + 5, NULL, 0);
 		else if (strncmp(word, "height=", 7) == 0)
 			shape->shape[2] = strtol(word + 7, NULL, 0);
+		else if (strcmp(word, "charcolors") == 0)
+			type |= CONS_CHARCURSOR_COLORS;
+		else if (strcmp(word, "mousecolors") == 0)
+			type |= CONS_MOUSECURSOR_COLORS;
+		else if (strcmp(word, "default") == 0)
+			type |= CONS_DEFAULT_CURSOR;
+		else if (strcmp(word, "shapeonly") == 0)
+			type |= CONS_SHAPEONLY_CURSOR;
 		else if (strcmp(word, "local") == 0)
 			type |= CONS_LOCAL_CURSOR;
 		else if (strcmp(word, "reset") == 0)
 			type |= CONS_RESET_CURSOR;
+		else if (strcmp(word, "show") == 0)
+			printf("flags %#x, base %d, height %d\n",
+			    type, shape->shape[1], shape->shape[2]);
 		else {
 			revert();
 			errx(1,
@@ -676,11 +687,13 @@ set_cursor_type(char *param)
 {
 	struct cshape shape;
 
-	/* Determine if the new setting is local (default to non-local). */
+	/* Dry run to determine color, default and local flags. */
 	shape.shape[0] = 0;
+	shape.shape[1] = -1;
+	shape.shape[2] = -1;
 	parse_cursor_params(param, &shape);
 
-	/* Get the relevant shape (the local flag is the only input arg). */
+	/* Get the relevant old setting. */
 	if (ioctl(0, CONS_GETCURSORSHAPE, &shape) != 0) {
 		revert();
 		err(1, "ioctl(CONS_GETCURSORSHAPE)");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708250704.v7P74fE9028895>