diff --git a/protocols/rdp/include/rdp_handlers.h b/protocols/rdp/include/rdp_handlers.h index 5d43e044..cd06344e 100644 --- a/protocols/rdp/include/rdp_handlers.h +++ b/protocols/rdp/include/rdp_handlers.h @@ -63,7 +63,7 @@ void guac_rdp_ui_bell(rdpInst* inst); void guac_rdp_ui_destblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy); void guac_rdp_ui_patblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_BRUSH* brush, int bgcolour, int fgcolour); void guac_rdp_ui_screenblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy); -void guac_rdp_ui_memblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy); +void guac_rdp_ui_memblt(rdpInst* inst, uint8 opcode, int x, int y, int width, int height, RD_HBITMAP src, int srcx, int srcy); void guac_rdp_ui_triblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy, RD_BRUSH* brush, int bgcolour, int fgcolour); RD_HGLYPH guac_rdp_ui_create_glyph(rdpInst* inst, int width, int height, uint8* data); void guac_rdp_ui_destroy_glyph(rdpInst* inst, RD_HGLYPH glyph); diff --git a/protocols/rdp/src/rdp_handlers.c b/protocols/rdp/src/rdp_handlers.c index caedcc32..01ba5ded 100644 --- a/protocols/rdp/src/rdp_handlers.c +++ b/protocols/rdp/src/rdp_handlers.c @@ -36,6 +36,9 @@ * ***** END LICENSE BLOCK ***** */ #include +#include + +#include #include #include @@ -69,7 +72,9 @@ void guac_rdp_ui_begin_update(rdpInst* inst) { } void guac_rdp_ui_end_update(rdpInst* inst) { - /* UNUSED */ + guac_client* client = (guac_client*) inst->param1; + GUACIO* io = client->io; + guac_flush(io); } void guac_rdp_ui_desktop_save(rdpInst* inst, int offset, int x, int y, int cx, int cy) { @@ -80,13 +85,75 @@ void guac_rdp_ui_desktop_restore(rdpInst* inst, int offset, int x, int y, int cx guac_log_info("guac_rdp_ui_desktop_restore: STUB\n"); } + RD_HBITMAP guac_rdp_ui_create_bitmap(rdpInst* inst, int width, int height, uint8* data) { - /* Allocate and return buffer */ + /* Allocate buffer */ guac_client* client = (guac_client*) inst->param1; + GUACIO* io = client->io; guac_layer* buffer = guac_client_alloc_buffer(client); - guac_log_info("guac_rdp_ui_create_bitmap: STUB %ix%i, bpp=%i (got buffer %i)\n", width, height, inst->settings->server_depth, buffer->index); + int x, y; + int stride; + int bpp = inst->settings->server_depth / 8; + unsigned char* image_buffer; + unsigned char* image_buffer_row; + + cairo_surface_t* surface; + + /* Init Cairo buffer */ + stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, width); + image_buffer = malloc(height*stride); + image_buffer_row = image_buffer; + + /* Copy image data from image data to buffer */ + for (y = 0; y> 8) & 0xF8) | ((v >> 13) & 0x07); + green = ((v >> 3) & 0xFC) | ((v >> 9) & 0x03); + blue = ((v << 3) & 0xF8) | ((v >> 2) & 0x07); + break; + + default: /* The Magenta of Failure */ + red = 0xFF; + green = 0x00; + blue = 0xFF; + } + + /* Output RGB */ + *(image_buffer_current++) = (red << 16) | (green << 8) | blue; + + } + } + + surface = cairo_image_surface_create_for_data(image_buffer, CAIRO_FORMAT_RGB24, width, height, stride); + guac_send_png(io, GUAC_COMP_OVER, buffer, 0, 0, surface); + + /* Free surface */ + cairo_surface_destroy(surface); + free(image_buffer); return (RD_HBITMAP) buffer; @@ -108,11 +175,49 @@ void guac_rdp_ui_line(rdpInst* inst, uint8 opcode, int startx, int starty, int e guac_log_info("guac_rdp_ui_line: STUB\n"); } -void guac_rdp_ui_rect(rdpInst* inst, int x, int y, int cx, int cy, int colour) { - guac_log_info("guac_rdp_ui_rect: STUB\n"); +void guac_rdp_ui_rect(rdpInst* inst, int x, int y, int cx, int cy, int color) { + + guac_client* client = (guac_client*) inst->param1; + GUACIO* io = client->io; + + unsigned char red, green, blue; + + /* Create surface */ + cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, cx, cy); + cairo_t* cairo = cairo_create(surface); + + switch (inst->settings->server_depth) { + case 24: + red = (color >> 16) & 0xFF; + green = (color >> 8) & 0xFF; + blue = (color ) & 0xFF; + break; + + case 16: + red = ((color >> 8) & 0xF8) | ((color >> 13) & 0x07); + green = ((color >> 3) & 0xFC) | ((color >> 9) & 0x03); + blue = ((color << 3) & 0xF8) | ((color >> 2) & 0x07); + break; + + default: /* The Magenta of Failure */ + red = 0xFF; + green = 0x00; + blue = 0xFF; + } + + /* Render rectangle */ + cairo_set_source_rgb(cairo, red, green, blue); + cairo_rectangle(cairo, 0, 0, cx, cy); + cairo_fill(cairo); + + /* Send background */ + cairo_destroy(cairo); + guac_send_png(io, GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, x, y, surface); + cairo_surface_destroy(surface); + } -void guac_rdp_ui_polygon(rdpInst* inst, uint8 opcode, uint8 fillmode, RD_POINT* point, int npoints, RD_BRUSH* brush, int bgcolour, int fgcolour) { +void guac_rdp_ui_polygon(rdpInst* inst, uint8 opcode, uint8 fillmode, RD_POINT* point, int npoints, RD_BRUSH* brush, int bgcolor, int fgcolor) { guac_log_info("guac_rdp_ui_polygon: STUB\n"); } @@ -120,12 +225,12 @@ void guac_rdp_ui_polyline(rdpInst* inst, uint8 opcode, RD_POINT* points, int npo guac_log_info("guac_rdp_ui_polyline: STUB\n"); } -void guac_rdp_ui_ellipse(rdpInst* inst, uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, RD_BRUSH* brush, int bgcolour, int fgcolour) { +void guac_rdp_ui_ellipse(rdpInst* inst, uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, RD_BRUSH* brush, int bgcolor, int fgcolor) { guac_log_info("guac_rdp_ui_ellipse: STUB\n"); } -void guac_rdp_ui_start_draw_glyphs(rdpInst* inst, int bgcolour, int fgcolour) { - guac_log_info("guac_rdp_ui_start_draw_glyphs: STUB\n"); +void guac_rdp_ui_start_draw_glyphs(rdpInst* inst, int bgcolor, int fgcolor) { + /* UNUSED */ } void guac_rdp_ui_draw_glyph(rdpInst* inst, int x, int y, int cx, int cy, RD_HGLYPH glyph) { @@ -133,7 +238,7 @@ void guac_rdp_ui_draw_glyph(rdpInst* inst, int x, int y, int cx, int cy, RD_HGLY } void guac_rdp_ui_end_draw_glyphs(rdpInst* inst, int x, int y, int cx, int cy) { - guac_log_info("guac_rdp_ui_end_draw_glyphs: STUB\n"); + /* UNUSED */ } uint32 guac_rdp_ui_get_toggle_keys_state(rdpInst* inst) { @@ -149,7 +254,7 @@ void guac_rdp_ui_destblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int guac_log_info("guac_rdp_ui_destblt: STUB\n"); } -void guac_rdp_ui_patblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_BRUSH* brush, int bgcolour, int fgcolour) { +void guac_rdp_ui_patblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_BRUSH* brush, int bgcolor, int fgcolor) { guac_log_info("guac_rdp_ui_patblt: STUB\n"); } @@ -157,11 +262,21 @@ void guac_rdp_ui_screenblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, in guac_log_info("guac_rdp_ui_screenblt: STUB\n"); } -void guac_rdp_ui_memblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy) { - guac_log_info("guac_rdp_ui_memblt: STUB\n"); +void guac_rdp_ui_memblt(rdpInst* inst, uint8 opcode, int x, int y, int width, int height, RD_HBITMAP src, int srcx, int srcy) { + + guac_client* client = (guac_client*) inst->param1; + GUACIO* io = client->io; + + guac_log_info("guac_rdp_ui_memblt: opcode=%i, index=%i\n", opcode, + ((guac_layer*) src)->index); + + guac_send_copy(io, + (guac_layer*) src, srcx, srcy, width, height, + GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, x, y); + } -void guac_rdp_ui_triblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy, RD_BRUSH* brush, int bgcolour, int fgcolour) { +void guac_rdp_ui_triblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy, RD_BRUSH* brush, int bgcolor, int fgcolor) { guac_log_info("guac_rdp_ui_triblt: STUB\n"); } @@ -219,7 +334,7 @@ void guac_rdp_ui_set_default_cursor(rdpInst* inst) { guac_log_info("guac_rdp_ui_set_default_cursor: STUB\n"); } -RD_HPALETTE guac_rdp_ui_create_colormap(rdpInst* inst, RD_PALETTE* colours) { +RD_HPALETTE guac_rdp_ui_create_colormap(rdpInst* inst, RD_PALETTE* colors) { guac_log_info("guac_rdp_ui_create_colormap: STUB\n"); return NULL; }