Submitted By: Ben Swartzlander (ben at swartzlander dot org) Date: 2008-09-07 Initial Package Version: 1.6.0 Description: Change cursor emulation to make XOR cursors stand out better on black backgrounds (similar to WINE implementation) diff -Naur rdesktop-1.6.0.orig/xwin.c rdesktop-1.6.0/xwin.c --- rdesktop-1.6.0.orig/xwin.c 2008-09-06 00:43:49.000000000 -0400 +++ rdesktop-1.6.0/xwin.c 2008-09-06 22:30:29.000000000 -0400 @@ -2770,28 +2770,66 @@ XFreePixmap(g_display, (Pixmap) glyph); } -RD_HCURSOR -ui_create_cursor(unsigned int x, unsigned int y, int width, int height, - uint8 * andmask, uint8 * xormask) +static int +ui_get_cursor_bit(uint8 * buffer, int stride, int x, int y) { - RD_HGLYPH maskglyph, cursorglyph; - XColor bg, fg; - Cursor xcursor; - uint8 *cursor, *pcursor; - uint8 *mask, *pmask; + return 0 != (buffer[stride * y + (x >> 3)] & (0x80 >> (x & 7))); +} + +static void +ui_set_cursor_bit(uint8 * buffer, int stride, int x, int y) +{ + buffer[stride * y + (x >> 3)] |= 0x80 >> (x & 7); +} + +static void +ui_add_xor_cursor_shadow(uint8 * cursor, uint8 * mask, int width, int scanline, + int height, uint8 * andmask, uint8 * xormask) +{ + int x, x2, y, y2; + uint8 * xorptr; + + cursor += (height - 1) * scanline; + mask += (height - 1) * scanline; + + /* + * For every pixel in the cursor that should be color-inverting + * (andmask == 0 && xormask != 0) we look one pixel down and one + * to the right and make that pixel white if it was previously + * transparent. This creates a white shadow effect under the black + * cursor that makes the cursor much more visible against dark + * backgrounds without affecting the cursor appearance on lighter + * backgrounds. This is the best we can do given the limitations of + * X cursors. + */ + for (y = 1; y < height; y++) { + y2 = y - 1; + xormask += 24 * scanline; + for (x = 0; x < width - 1; x++) { + x2 = x + 1; + xorptr = xormask + 3 * x; + if ((xorptr[0] || xorptr[1] || xorptr[2]) && + ui_get_cursor_bit(andmask, scanline, x, y) && + ! ui_get_cursor_bit(mask, -scanline, x2, y2)) { + ui_set_cursor_bit(cursor, -scanline, x2, y2); + ui_set_cursor_bit(mask, -scanline, x2, y2); + } + } + } +} + +static void +ui_convert_cursor(uint8 * cursor, uint8 * mask, int scanline, int height, + uint8 * andmask, uint8 * xormask) +{ + uint8 * pcursor; + uint8 * pmask; uint8 nextbit; - int scanline, offset; int i, j; + int offset; - scanline = (width + 7) / 8; offset = scanline * height; - cursor = (uint8 *) xmalloc(offset); - memset(cursor, 0, offset); - - mask = (uint8 *) xmalloc(offset); - memset(mask, 0, offset); - /* approximate AND and XOR masks with a monochrome X pointer */ for (i = 0; i < height; i++) { @@ -2822,6 +2860,34 @@ pmask++; } } +} + +RD_HCURSOR +ui_create_cursor(unsigned int x, unsigned int y, int width, int height, + uint8 * andmask, uint8 * xormask) +{ + RD_HGLYPH maskglyph, cursorglyph; + XColor bg, fg; + Cursor xcursor; + uint8 * cursor; + uint8 * mask; + int scanline, offset; + + scanline = (width + 7) / 8; + offset = scanline * height; + + cursor = (uint8 *) xmalloc(offset); + memset(cursor, 0, offset); + + mask = (uint8 *) xmalloc(offset); + memset(mask, 0, offset); + + /* original cursor conversion code */ + ui_convert_cursor(cursor, mask, scanline, height, andmask, xormask); + + /* code to add a "shadow" to XOR cursors for improved visibility */ + ui_add_xor_cursor_shadow(cursor, mask, width, scanline, height, + andmask, xormask); fg.red = fg.blue = fg.green = 0xffff; bg.red = bg.blue = bg.green = 0x0000;