From fdcd8d75917b7da3f0c07c5869981f918cea86e3 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sun, 25 Oct 2009 21:36:17 +0000 Subject: [PATCH] added new pointers git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/rdesktop/trunk@1520 423420c4-83ab-492f-b58f-81f9feb106b5 --- constants.h | 4 ++- proto.h | 3 +- rdp.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++------ rdp5.c | 3 ++ xwin.c | 79 +++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 151 insertions(+), 20 deletions(-) diff --git a/constants.h b/constants.h index 0185504..a3b04d3 100644 --- a/constants.h +++ b/constants.h @@ -149,7 +149,8 @@ enum RDP_POINTER_PDU_TYPE RDP_POINTER_SYSTEM = 1, RDP_POINTER_MOVE = 3, RDP_POINTER_COLOR = 6, - RDP_POINTER_CACHED = 7 + RDP_POINTER_CACHED = 7, + RDP_POINTER_NEW = 8 }; enum RDP_SYSTEM_POINTER_TYPE @@ -244,6 +245,7 @@ enum RDP_INPUT_DEVICE #define RDP_CAPSET_POINTER 8 #define RDP_CAPLEN_POINTER 0x08 +#define RDP_CAPLEN_NEWPOINTER 0x0a #define RDP_CAPSET_SHARE 9 #define RDP_CAPLEN_SHARE 0x08 diff --git a/proto.h b/proto.h index 40457e6..70ee9ad 100644 --- a/proto.h +++ b/proto.h @@ -144,6 +144,7 @@ void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint1 uint16 param2); void rdp_send_client_window_status(int status); void process_colour_pointer_pdu(STREAM s); +void process_new_pointer_pdu(STREAM s); void process_cached_pointer_pdu(STREAM s); void process_system_pointer_pdu(STREAM s); void process_bitmap_updates(STREAM s); @@ -249,7 +250,7 @@ void ui_destroy_bitmap(RD_HBITMAP bmp); RD_HGLYPH ui_create_glyph(int width, int height, uint8 * data); void ui_destroy_glyph(RD_HGLYPH glyph); RD_HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask, - uint8 * xormask); + uint8 * xormask, int bpp); void ui_set_cursor(RD_HCURSOR cursor); void ui_destroy_cursor(RD_HCURSOR cursor); void ui_set_null_cursor(void); diff --git a/rdp.c b/rdp.c index fb6112c..438df7a 100644 --- a/rdp.c +++ b/rdp.c @@ -778,6 +778,18 @@ rdp_out_pointer_caps(STREAM s) out_uint16_le(s, 20); /* Cache size */ } +/* Output new pointer capability set */ +static void +rdp_out_newpointer_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_POINTER); + out_uint16_le(s, RDP_CAPLEN_NEWPOINTER); + + out_uint16_le(s, 1); /* Colour pointer */ + out_uint16_le(s, 20); /* Cache size */ + out_uint16_le(s, 20); /* Cache size for new pointers */ +} + /* Output share capability set */ static void rdp_out_share_caps(STREAM s) @@ -855,12 +867,23 @@ rdp_send_confirm_active(void) uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG; uint16 caplen = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER + - RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + - RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + + RDP_CAPLEN_SHARE + RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ + 4 /* w2k fix, sessionid */ ; + if (g_use_rdp5) + { + caplen += RDP_CAPLEN_BMPCACHE2; + caplen += RDP_CAPLEN_NEWPOINTER; + } + else + { + caplen += RDP_CAPLEN_BMPCACHE; + caplen += RDP_CAPLEN_POINTER; + } + s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE)); out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE)); @@ -879,11 +902,19 @@ rdp_send_confirm_active(void) rdp_out_general_caps(s); rdp_out_bitmap_caps(s); rdp_out_order_caps(s); - g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s); + if (g_use_rdp5) + { + rdp_out_bmpcache2_caps(s); + rdp_out_newpointer_caps(s); + } + else + { + rdp_out_bmpcache_caps(s); + rdp_out_pointer_caps(s); + } rdp_out_colcache_caps(s); rdp_out_activate_caps(s); rdp_out_control_caps(s); - rdp_out_pointer_caps(s); rdp_out_share_caps(s); rdp_out_brushcache_caps(s); @@ -1022,11 +1053,13 @@ process_demand_active(STREAM s) } /* Process a colour pointer PDU */ -void -process_colour_pointer_pdu(STREAM s) +static void +process_colour_pointer_common(STREAM s, int bpp) { - uint16 x, y, width, height, cache_idx, masklen, datalen; - uint8 *mask, *data; + uint16 width, height, cache_idx, masklen, datalen; + sint16 x, y; + uint8 * mask; + uint8 * data; RD_HCURSOR cursor; in_uint16_le(s, cache_idx); @@ -1038,11 +1071,38 @@ process_colour_pointer_pdu(STREAM s) in_uint16_le(s, datalen); in_uint8p(s, data, datalen); in_uint8p(s, mask, masklen); - cursor = ui_create_cursor(x, y, width, height, mask, data); + if ((width != 32) || (height != 32)) + { + warning("process_colour_pointer_common: " + "width %d height %d\n", width, height); + } + /* sometimes x or y is out of bounds */ + x = MAX(x, 0); + x = MIN(x, width - 1); + y = MAX(y, 0); + y = MIN(y, height - 1); + cursor = ui_create_cursor(x, y, width, height, mask, data, bpp); ui_set_cursor(cursor); cache_put_cursor(cache_idx, cursor); } +/* Process a colour pointer PDU */ +void +process_colour_pointer_pdu(STREAM s) +{ + process_colour_pointer_common(s, 24); +} + +/* Process a New Pointer PDU - these pointers have variable bit depth */ +void +process_new_pointer_pdu(STREAM s) +{ + int xor_bpp; + + in_uint16_le(s, xor_bpp); + process_colour_pointer_common(s, xor_bpp); +} + /* Process a cached pointer PDU */ void process_cached_pointer_pdu(STREAM s) @@ -1102,6 +1162,10 @@ process_pointer_pdu(STREAM s) process_system_pointer_pdu(s); break; + case RDP_POINTER_NEW: + process_new_pointer_pdu(s); + break; + default: unimpl("Pointer message 0x%x\n", message_type); } diff --git a/rdp5.c b/rdp5.c index e55852b..8d9b60a 100644 --- a/rdp5.c +++ b/rdp5.c @@ -111,6 +111,9 @@ rdp5_process(STREAM s) case 10: /* cached pointer */ process_cached_pointer_pdu(ts); break; + case 11: + process_new_pointer_pdu(ts); + break; default: unimpl("RDP5 opcode %d\n", type); } diff --git a/xwin.c b/xwin.c index 037288b..36479af 100644 --- a/xwin.c +++ b/xwin.c @@ -2099,7 +2099,7 @@ ui_create_window(void) /* create invisible 1x1 cursor to be used as null cursor */ if (g_null_cursor == NULL) - g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data); + g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data, 24); if (g_seamless_rdp) { @@ -2772,9 +2772,62 @@ ui_destroy_glyph(RD_HGLYPH glyph) XFreePixmap(g_display, (Pixmap) glyph); } +/* convert next pixel to 32 bpp */ +static int +get_next_xor_pixel(uint8 * xormask, int bpp, int * k) +{ + int rv = 0; + PixelColour pc; + uint8 * s8; + uint16 * s16; + + switch (bpp) + { + case 1: + s8 = xormask + (*k) / 8; + rv = (*s8) & (0x80 >> ((*k) % 8)); + rv = rv ? 0xffffff : 0; + (*k) += 1; + break; + case 8: + s8 = xormask + *k; + /* should use colour map */ + rv = s8[0]; + rv = rv ? 0xffffff : 0; + (*k) += 1; + break; + case 15: + s16 = (uint16 *) xormask; + SPLITCOLOUR15(s16[*k], pc); + rv = (pc.red << 16) | (pc.green << 8) | pc.blue; + (*k) += 1; + break; + case 16: + s16 = (uint16 *) xormask; + SPLITCOLOUR16(s16[*k], pc); + rv = (pc.red << 16) | (pc.green << 8) | pc.blue; + (*k) += 1; + break; + case 24: + s8 = xormask + *k; + rv = (s8[0] << 16) | (s8[1] << 8) | s8[2]; + (*k) += 3; + break; + case 32: + s8 = xormask + *k; + rv = (s8[1] << 16) | (s8[2] << 8) | s8[3]; + (*k) += 4; + break; + default: + error("unknown bpp in get_next_xor_pixel %d\n", bpp); + break; + } + return rv; +} + RD_HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, - uint8 * andmask, uint8 * xormask) + uint8 * andmask, uint8 * xormask, int bpp) { RD_HGLYPH maskglyph, cursorglyph; XColor bg, fg; @@ -2782,9 +2835,10 @@ ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 *cursor, *pcursor; uint8 *mask, *pmask; uint8 nextbit; - int scanline, offset; - int i, j; + int scanline, offset, delta; + int i, j, k; + k = 0; scanline = (width + 7) / 8; offset = scanline * height; @@ -2793,11 +2847,19 @@ ui_create_cursor(unsigned int x, unsigned int y, int width, int height, mask = (uint8 *) xmalloc(offset); memset(mask, 0, offset); - + if (bpp == 1) + { + offset = 0; + delta = scanline; + } + else + { + offset = scanline * height - scanline; + delta = -scanline; + } /* approximate AND and XOR masks with a monochrome X pointer */ for (i = 0; i < height; i++) { - offset -= scanline; pcursor = &cursor[offset]; pmask = &mask[offset]; @@ -2805,7 +2867,7 @@ ui_create_cursor(unsigned int x, unsigned int y, int width, int height, { for (nextbit = 0x80; nextbit != 0; nextbit >>= 1) { - if (xormask[0] || xormask[1] || xormask[2]) + if (get_next_xor_pixel(xormask, bpp, &k)) { *pcursor |= (~(*andmask) & nextbit); *pmask |= nextbit; @@ -2815,14 +2877,13 @@ ui_create_cursor(unsigned int x, unsigned int y, int width, int height, *pcursor |= ((*andmask) & nextbit); *pmask |= (~(*andmask) & nextbit); } - - xormask += 3; } andmask++; pcursor++; pmask++; } + offset += delta; } fg.red = fg.blue = fg.green = 0xffff;