diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 0f424df96..4baf76ee9 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -54,6 +54,7 @@ void xf_begin_paint(rdpUpdate* update) GDI* gdi; gdi = GET_GDI(update); gdi->primary->hdc->hwnd->invalid->null = 1; + gdi->primary->hdc->hwnd->ninvalid = 0; } void xf_end_paint(rdpUpdate* update) @@ -66,22 +67,41 @@ void xf_end_paint(rdpUpdate* update) gdi = GET_GDI(update); xfi = GET_XFI(update); - if (gdi->primary->hdc->hwnd->invalid->null) - return; - - x = gdi->primary->hdc->hwnd->invalid->x; - y = gdi->primary->hdc->hwnd->invalid->y; - w = gdi->primary->hdc->hwnd->invalid->w; - h = gdi->primary->hdc->hwnd->invalid->h; - if (xfi->remote_app != True) { - XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h); - XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y); + int i; + int ninvalid; + HGDI_RGN* cinvalid; + + if (gdi->primary->hdc->hwnd->ninvalid < 1) + return; + + ninvalid = gdi->primary->hdc->hwnd->ninvalid; + cinvalid = gdi->primary->hdc->hwnd->cinvalid; + + for (i = 0; i < ninvalid; i++) + { + x = cinvalid[i]->x; + y = cinvalid[i]->y; + w = cinvalid[i]->w; + h = cinvalid[i]->h; + + XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h); + XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y); + } + XFlush(xfi->display); } else { + if (gdi->primary->hdc->hwnd->invalid->null) + return; + + x = gdi->primary->hdc->hwnd->invalid->x; + y = gdi->primary->hdc->hwnd->invalid->y; + w = gdi->primary->hdc->hwnd->invalid->w; + h = gdi->primary->hdc->hwnd->invalid->h; + xf_rail_paint(xfi, update->rail, x, y, x + w - 1, y + h - 1); } } diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index e5564c8b1..2eac3fb5b 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -193,7 +193,9 @@ typedef GDI_BRUSH* HGDI_BRUSH; struct _GDI_WND { + int ninvalid; HGDI_RGN invalid; + HGDI_RGN* cinvalid; }; typedef struct _GDI_WND GDI_WND; typedef GDI_WND* HGDI_WND; @@ -214,6 +216,7 @@ struct _GDI_DC int alpha; int invert; int rgb555; + int complex; }; typedef struct _GDI_DC GDI_DC; typedef GDI_DC* HGDI_DC; diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index aae832226..9e92a6b72 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -949,6 +949,7 @@ int gdi_init(freerdp* instance, uint32 flags) gdi->hdc->alpha = gdi->clrconv->alpha; gdi->hdc->invert = gdi->clrconv->invert; gdi->hdc->rgb555 = gdi->clrconv->rgb555; + gdi->hdc->complex = 1; gdi->primary = gdi_bitmap_new(gdi, gdi->width, gdi->height, gdi->dstBpp, NULL); gdi->primary_buffer = gdi->primary->bitmap->data; diff --git a/libfreerdp-gdi/region.c b/libfreerdp-gdi/region.c index cab2f4cc2..8948af4c5 100644 --- a/libfreerdp-gdi/region.c +++ b/libfreerdp-gdi/region.c @@ -378,6 +378,28 @@ inline int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h) if (hdc->hwnd == NULL) return 0; + if (hdc->complex) + { + HGDI_RGN* cinvalid; + + cinvalid = hdc->hwnd->cinvalid; + + if (hdc->hwnd->ninvalid < 1) + { + hdc->hwnd->ninvalid = 0; + cinvalid = (HGDI_RGN*) malloc(sizeof(HGDI_RGN)); + } + else + { + cinvalid = (HGDI_RGN*) realloc(cinvalid, sizeof(HGDI_RGN) * (hdc->hwnd->ninvalid + 1)); + } + + invalid = gdi_CreateRectRgn(x, y, x + w - 1, y + h - 1); + cinvalid[hdc->hwnd->ninvalid] = invalid; + hdc->hwnd->cinvalid = cinvalid; + hdc->hwnd->ninvalid++; + } + if (hdc->hwnd->invalid == NULL) return 0;