Fix 998529, mono (invert) cursors not visible on a black background, by doing simple edge detection on the cursor (this is done once when the cursor is changed and then cached, cursors are 32x32 generally) and thus having a cursor with contrast on both dark and light backgrounds. When (if) GDK gets invert cursor support (wayland?) then we can just use the cursor as is. Until then X doesn't provide any way I see of solving this otherwise. The end result was tested with the I beam cursor that the original bug was referring to (run putty on a windows 7 vm) and looks ok to me. --- gtk/channel-cursor.c | 86 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c index 66e91df..2c48d37 100644 --- a/gtk/channel-cursor.c +++ b/gtk/channel-cursor.c @@ -275,15 +275,67 @@ static void print_cursor(display_cursor *cursor, const guint8 *data) } #endif +static bool cursor_xor_pixel(const guint8 *xor, int bpl, int x, int y) +{ + return (xor[bpl * y + (x / 8)] & (0x80 >> (x % 8))) > 0; +} + +static guint8 cursor_is_xor_edge(display_cursor *cursor, const guint8 *xor, int bpl, int x, int y) +{ + if (x == 0 || x == cursor->hdr.width -1 || y == 0 || y == cursor->hdr.height - 1) { + return 0; + } +#define P(x, y) cursor_xor_pixel(xor, bpl, x, y) + return !P(x, y) && (P(x - 1, y + 1) || P(x, y + 1) || P(x + 1, y + 1) || + P(x - 1, y) || P(x + 1, y) || + P(x - 1, y - 1) || P(x, y - 1) || P(x + 1, y - 1)); +#undef P +} + +static bool cursor_is_and_ones(display_cursor *cursor, const guint8 *data) +{ + int x, y, bpl; + + bpl = (cursor->hdr.width + 7) / 8; + for (y = 0 ; y < cursor->hdr.height; ++y) { + for (x = 0 ; x < cursor->hdr.width / 8; ++x) { + if (data[x] != 0xff) { + return false; + } + } + data += bpl; + } + return true; +} + +/* Mono cursors have two places, "and" and "xor". If a bit is 1 in both, it + * means invertion of the corresponding pixel in the display. Since X11 (and + * gdk) doesn't do invertion, instead we do edge detection and turn the + * sorrounding edge pixels black, and the invert-me pixels white. To + * illustrate: + * + * and xor dest RGB (1=0xffffff, 0=0x000000) + * + * dest alpha (1=0xff, 0=0x00) + * + * 11111 00000 00000 00000 + * 11111 00000 00000 01110 + * 11111 00100 => 00100 01110 + * 11111 00100 00100 01110 + * 11111 00000 00000 01110 + * 11111 00000 00000 00000 + * + */ static void mono_cursor(display_cursor *cursor, const guint8 *data) { - const guint8 *xor, *and; + const guint8 *xor, *xor_base, *and; guint8 *dest; int bpl, x, y, bit; + bool and_ones = cursor_is_and_ones(cursor, data); bpl = (cursor->hdr.width + 7) / 8; and = data; - xor = and + bpl * cursor->hdr.height; + xor_base = xor = and + bpl * cursor->hdr.height; dest = (uint8_t *)cursor->data; #ifdef DEBUG_CURSOR print_cursor(cursor, data); @@ -291,26 +343,19 @@ static void mono_cursor(display_cursor *cursor, const guint8 *data) for (y = 0; y < cursor->hdr.height; y++) { bit = 0x80; for (x = 0; x < cursor->hdr.width; x++, dest += 4) { + if (cursor_is_xor_edge(cursor, xor_base, bpl, x, y) && and_ones) { + dest[0] = 0x00; + dest[1] = 0x00; + dest[2] = 0x00; + dest[3] = 0xff; + goto next_bit; + } if (and[x/8] & bit) { if (xor[x/8] & bit) { - /* - * flip -> unsupported by x11, since XCreatePixmapCursor has - * no invert functionality, only a mask, shape, background and - * foreground colors. Use this checkerboard hack to get some - * contrast for cursors in the guest that relied on invert for - * the same contrast. - */ - if ((x ^ y) & 1) { - dest[0] = 0xff; - dest[1] = 0xff; - dest[2] = 0xff; - dest[3] = 0xff; - } else { - dest[0] = 0x00; - dest[1] = 0x00; - dest[2] = 0x00; - dest[3] = 0x00; - } + dest[0] = 0xff; + dest[1] = 0xff; + dest[2] = 0xff; + dest[3] = 0xff; } else { /* unchanged -> transparent */ dest[0] = 0x00; @@ -333,6 +378,7 @@ static void mono_cursor(display_cursor *cursor, const guint8 *data) dest[3] = 0xff; } } + next_bit: bit >>= 1; if (bit == 0) { bit = 0x80; -- 1.8.3.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel