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.
This commit is contained in:
parent
0012e436e3
commit
9bc7c36337
@ -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_short a, int flip)
|
||||
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_short a, int flip)
|
||||
{
|
||||
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, int flip)
|
||||
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, int flip)
|
||||
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
|
||||
|
@ -959,8 +959,16 @@ sctty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
|
||||
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);
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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)");
|
||||
|
Loading…
x
Reference in New Issue
Block a user