libfreerdp-core: add true asynchronous input and update
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 7 Feb 2013 02:57:49 +0000 (21:57 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 7 Feb 2013 02:57:49 +0000 (21:57 -0500)
client/X11/xf_event.c
client/X11/xf_gdi.c
client/X11/xf_graphics.c
client/X11/xf_window.c
client/X11/xfreerdp.c
client/X11/xfreerdp.h
server/X11/xf_peer.c

index cf16da2..59faa20 100644 (file)
@@ -358,7 +358,7 @@ static BOOL xf_event_KeyRelease(xfInfo* xfi, XEvent* event, BOOL app)
 
        if (XPending(xfi->display))
        {
-               memset(&next_event, 0, sizeof(next_event));
+               ZeroMemory(&next_event, sizeof(next_event));
                XPeekEvent(xfi->display, &next_event);
 
                if (next_event.type == KeyPress)
index 06898a4..b24457f 100644 (file)
@@ -33,7 +33,8 @@
 
 #include "xf_gdi.h"
 
-static UINT8 GDI_BS_HACHTED_PATTERNS[] = {
+static UINT8 GDI_BS_HACHTED_PATTERNS[] =
+{
        0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, /* HS_HORIZONTAL */
        0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_VERTICAL */
        0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, /* HS_FDIAGONAL */
@@ -262,33 +263,15 @@ Pixmap xf_mono_bitmap_new(xfInfo* xfi, int width, int height, BYTE* data)
        return bitmap;
 }
 
-Pixmap xf_glyph_new(xfInfo* xfi, int width, int height, BYTE* data)
-{
-       int scanline;
-       Pixmap bitmap;
-       XImage* image;
-
-       scanline = (width + 7) / 8;
-
-       bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, 1);
-
-       image = XCreateImage(xfi->display, xfi->visual, 1,
-                       ZPixmap, 0, (char*) data, width, height, 8, scanline);
-
-       image->byte_order = MSBFirst;
-       image->bitmap_bit_order = MSBFirst;
-
-       XInitImage(image);
-       XPutImage(xfi->display, bitmap, xfi->gc_mono, image, 0, 0, 0, 0, width, height);
-       XFree(image);
-
-       return bitmap;
-}
-
 void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
+
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        CopyMemory(xfi->clrconv->palette, palette, sizeof(rdpPalette));
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
@@ -296,6 +279,8 @@ void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
        XRectangle clip;
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (bounds != NULL)
        {
                clip.x = bounds->left;
@@ -308,12 +293,16 @@ void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
        {
                XSetClipMask(xfi->display, xfi->gc, None);
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        xf_set_rop3(xfi, gdi_rop3_code(dstblt->bRop));
 
        XSetFillStyle(xfi->display, xfi->gc, FillSolid);
@@ -331,7 +320,10 @@ void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
 
                gdi_InvalidateRegion(xfi->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
        }
+
        XSetFunction(xfi->display, xfi->gc, GXcopy);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
@@ -343,6 +335,8 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        brush = &patblt->brush;
        xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop));
 
@@ -424,12 +418,16 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
        }
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        xf_set_rop3(xfi, gdi_rop3_code(scrblt->bRop));
 
        XCopyArea(xfi->display, xfi->primary, xfi->drawing, xfi->gc, scrblt->nXSrc, scrblt->nYSrc,
@@ -458,6 +456,8 @@ void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
        }
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
@@ -466,6 +466,8 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        color = freerdp_color_convert_var(opaque_rect->color, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
@@ -487,6 +489,8 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
                gdi_InvalidateRegion(xfi->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect,
                                opaque_rect->nWidth, opaque_rect->nHeight);
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
@@ -497,6 +501,8 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        color = freerdp_color_convert_var(multi_opaque_rect->color, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
@@ -522,6 +528,8 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
                        gdi_InvalidateRegion(xfi->hdc, rectangle->left, rectangle->top, rectangle->width, rectangle->height);
                }
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_draw_nine_grid(rdpContext* context, DRAW_NINE_GRID_ORDER* draw_nine_grid)
@@ -535,6 +543,8 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        xf_set_rop2(xfi, line_to->bRop2);
        color = freerdp_color_convert_var(line_to->penColor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
 
@@ -568,6 +578,8 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
        }
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
@@ -583,6 +595,8 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        xf_set_rop2(xfi, polyline->bRop2);
        color = freerdp_color_convert_var(polyline->penColor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
 
@@ -631,6 +645,8 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
        free(points);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
@@ -638,6 +654,8 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
        xfBitmap* bitmap;
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        bitmap = (xfBitmap*) memblt->bitmap;
        xf_set_rop3(xfi, gdi_rop3_code(memblt->bRop));
 
@@ -658,6 +676,8 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
        }
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
@@ -670,6 +690,8 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        brush = &mem3blt->brush;
        bitmap = (xfBitmap*) mem3blt->bitmap;
        xf_set_rop3(xfi, gdi_rop3_code(mem3blt->bRop));
@@ -733,6 +755,8 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
                XFreePixmap(xfi->display, pattern);
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
@@ -742,6 +766,8 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
        UINT32 brush_color;
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        xf_set_rop2(xfi, polygon_sc->bRop2);
        brush_color = freerdp_color_convert_var(polygon_sc->brushColor, ((xfContext*)context)->settings->ColorDepth, xfi->bpp, xfi->clrconv);
 
@@ -786,6 +812,8 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
        free(points);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
@@ -798,6 +826,8 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
        UINT32 backColor;
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        brush = &(polygon_cb->brush);
        xf_set_rop2(xfi, polygon_cb->bRop2);
        foreColor = freerdp_color_convert_var(polygon_cb->foreColor, ((xfContext*) context)->settings->ColorDepth, xfi->bpp, xfi->clrconv);
@@ -889,6 +919,8 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
 
        XSetFunction(xfi->display, xfi->gc, GXcopy);
        free(points);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_ellipse_sc(rdpContext* context, ELLIPSE_SC_ORDER* ellipse_sc)
@@ -908,6 +940,9 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
 
        xfi = ((xfContext*) context)->xfi;
        settings = xfi->instance->settings;
+
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        switch (surface_frame_marker->frameAction)
        {
                case SURFACECMD_FRAMEACTION_BEGIN:
@@ -938,6 +973,8 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
                        }
                        break;
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 static void xf_gdi_surface_update_frame(xfInfo* xfi, UINT16 tx, UINT16 ty, UINT16 width, UINT16 height)
@@ -983,6 +1020,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
        RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfi->rfx_context;
        NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfi->nsc_context;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
        {
                message = rfx_process_message(rfx_context,
@@ -1024,6 +1063,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
        {
                nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
                        surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
+
                XSetFunction(xfi->display, xfi->gc, GXcopy);
                XSetFillStyle(xfi->display, xfi->gc, FillSolid);
 
@@ -1053,7 +1093,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
                XSetFillStyle(xfi->display, xfi->gc, FillSolid);
 
                /* Validate that the data received is large enough */
-               if( surface_bits_command->width * surface_bits_command->height * surface_bits_command->bpp / 8 <= surface_bits_command->bitmapDataLength )
+               if ((surface_bits_command->width * surface_bits_command->height * surface_bits_command->bpp / 8) <= (surface_bits_command->bitmapDataLength))
                {
                        xfi->bmp_codec_none = (BYTE*) realloc(xfi->bmp_codec_none,
                                        surface_bits_command->width * surface_bits_command->height * 4);
@@ -1074,7 +1114,9 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
                                surface_bits_command->width, surface_bits_command->height);
 
                        XSetClipMask(xfi->display, xfi->gc, None);
-               } else {
+               }
+               else
+               {
                        printf("Invalid bitmap size - data is %d bytes for %dx%d\n update", surface_bits_command->bitmapDataLength, surface_bits_command->width, surface_bits_command->height);
                }
        }
@@ -1082,6 +1124,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
        {
                printf("Unsupported codecID %d\n", surface_bits_command->codecID);
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_gdi_register_update_callbacks(rdpUpdate* update)
index d43a587..9f43b98 100644 (file)
@@ -46,6 +46,8 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
        xfContext* context_ = (xfContext*) context;
        xfInfo* xfi = context_->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        XSetFunction(xfi->display, xfi->gc, GXcopy);
        pixmap = XCreatePixmap(xfi->display, xfi->drawable, bitmap->width, bitmap->height, xfi->depth);
 
@@ -75,14 +77,20 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
        }
 
        ((xfBitmap*) bitmap)->pixmap = pixmap;
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (((xfBitmap*) bitmap)->pixmap != 0)
                XFreePixmap(xfi->display, ((xfBitmap*) bitmap)->pixmap);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
@@ -94,6 +102,8 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
        width = bitmap->right - bitmap->left + 1;
        height = bitmap->bottom - bitmap->top + 1;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        XSetFunction(xfi->display, xfi->gc, GXcopy);
 
        image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
@@ -111,6 +121,8 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
        }
 
        gdi_InvalidateRegion(xfi->hdc, bitmap->left, bitmap->top, width, height);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
@@ -118,13 +130,15 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
                BOOL compressed, int codec_id)
 {
        UINT16 size;
-       RFX_MESSAGE* msg;
        BYTE* src;
        BYTE* dst;
        int yindex;
        int xindex;
        xfInfo* xfi;
        BOOL status;
+       RFX_MESSAGE* msg;
+
+       xfi = ((xfContext*) context)->xfi;
 
        size = width * height * (bpp + 7) / 8;
 
@@ -138,10 +152,11 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
                case RDP_CODEC_ID_NSCODEC:
                        printf("xf_Bitmap_Decompress: nsc not done\n");
                        break;
+
                case RDP_CODEC_ID_REMOTEFX:
-                       xfi = ((xfContext*)context)->xfi;
                        rfx_context_set_pixel_format(xfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
                        msg = rfx_process_message(xfi->rfx_context, data, length);
+
                        if (msg == NULL)
                        {
                                printf("xf_Bitmap_Decompress: rfx Decompression Failed\n");
@@ -163,12 +178,14 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
                                rfx_message_free(xfi->rfx_context, msg);
                        }
                        break;
+
                case RDP_CODEC_ID_JPEG:
                        if (!jpeg_decompress(data, bitmap->data, width, height, length, bpp))
                        {
                                printf("xf_Bitmap_Decompress: jpeg Decompression Failed\n");
                        }
                        break;
+
                default:
                        if (compressed)
                        {
@@ -195,10 +212,14 @@ void xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (primary)
                xfi->drawing = xfi->primary;
        else
                xfi->drawing = ((xfBitmap*) bitmap)->pixmap;
+
+       ReleaseMutex(xfi->mutex);
 }
 
 /* Pointer Class */
@@ -209,7 +230,9 @@ void xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
        XcursorImage ci;
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
-       memset(&ci, 0, sizeof(ci));
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
+       ZeroMemory(&ci, sizeof(ci));
        ci.version = XCURSOR_IMAGE_VERSION;
        ci.size = sizeof(ci);
        ci.width = pointer->width;
@@ -229,6 +252,8 @@ void xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
        ((xfPointer*) pointer)->cursor = XcursorImageLoadCursor(xfi->display, &ci);
 
        free(ci.pixels);
+
+       ReleaseMutex(xfi->mutex);
 #endif
 }
 
@@ -237,8 +262,12 @@ void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
 #ifdef WITH_XCURSOR
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (((xfPointer*) pointer)->cursor != 0)
                XFreeCursor(xfi->display, ((xfPointer*) pointer)->cursor);
+
+       ReleaseMutex(xfi->mutex);
 #endif
 }
 
@@ -247,10 +276,14 @@ void xf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
 #ifdef WITH_XCURSOR
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        /* in RemoteApp mode, window can be null if none has had focus */
 
        if (xfi->window != NULL)
                XDefineCursor(xfi->display, xfi->window->handle, ((xfPointer*) pointer)->cursor);
+
+       ReleaseMutex(xfi->mutex);
 #endif
 }
 
@@ -260,11 +293,13 @@ void xf_Pointer_SetNull(rdpContext* context)
        xfInfo* xfi = ((xfContext*) context)->xfi;
        static Cursor nullcursor = None;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (nullcursor == None)
        {
                XcursorImage ci;
                XcursorPixel xp = 0;
-               memset(&ci, 0, sizeof(ci));
+               ZeroMemory(&ci, sizeof(ci));
                ci.version = XCURSOR_IMAGE_VERSION;
                ci.size = sizeof(ci);
                ci.width = ci.height = 1;
@@ -275,6 +310,8 @@ void xf_Pointer_SetNull(rdpContext* context)
 
        if (xfi->window != NULL && nullcursor != None)
                XDefineCursor(xfi->display, xfi->window->handle, nullcursor);
+
+       ReleaseMutex(xfi->mutex);
 #endif
 }
 
@@ -283,8 +320,12 @@ void xf_Pointer_SetDefault(rdpContext* context)
 #ifdef WITH_XCURSOR
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (xfi->window != NULL)
                XUndefineCursor(xfi->display, xfi->window->handle);
+
+       ReleaseMutex(xfi->mutex);
 #endif
 }
 
@@ -300,6 +341,8 @@ void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph)
        xf_glyph = (xfGlyph*) glyph;
        xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        scanline = (glyph->cx + 7) / 8;
 
        xf_glyph->pixmap = XCreatePixmap(xfi->display, xfi->drawing, glyph->cx, glyph->cy, 1);
@@ -313,14 +356,20 @@ void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph)
        XInitImage(image);
        XPutImage(xfi->display, xf_glyph->pixmap, xfi->gc_mono, image, 0, 0, 0, 0, glyph->cx, glyph->cy);
        XFree(image);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (((xfGlyph*) glyph)->pixmap != 0)
                XFreePixmap(xfi->display, ((xfGlyph*) glyph)->pixmap);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y)
@@ -330,10 +379,14 @@ void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y)
 
        xf_glyph = (xfGlyph*) glyph;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        XSetStipple(xfi->display, xfi->gc, xf_glyph->pixmap);
        XSetTSOrigin(xfi->display, xfi->gc, x, y);
        XFillRectangle(xfi->display, xfi->drawing, xfi->gc, x, y, glyph->cx, glyph->cy);
        XSetStipple(xfi->display, xfi->gc, xfi->bitmap_mono);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, UINT32 bgcolor, UINT32 fgcolor)
@@ -349,6 +402,8 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height
                freerdp_color_convert_var_bgr(fgcolor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv):
                freerdp_color_convert_var_rgb(fgcolor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        XSetFunction(xfi->display, xfi->gc, GXcopy);
        XSetFillStyle(xfi->display, xfi->gc, FillSolid);
        XSetForeground(xfi->display, xfi->gc, fgcolor);
@@ -357,12 +412,16 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height
        XSetForeground(xfi->display, xfi->gc, bgcolor);
        XSetBackground(xfi->display, xfi->gc, fgcolor);
        XSetFillStyle(xfi->display, xfi->gc, FillStippled);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, UINT32 bgcolor, UINT32 fgcolor)
 {
        xfInfo* xfi = ((xfContext*) context)->xfi;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (xfi->drawing == xfi->primary)
        {
                if (xfi->remote_app != TRUE)
@@ -372,6 +431,8 @@ void xf_Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height,
 
                gdi_InvalidateRegion(xfi->hdc, x, y, width, height);
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 /* Graphics Module */
index 2f1f8e8..809deaf 100644 (file)
@@ -873,6 +873,8 @@ void xf_UpdateWindowArea(xfInfo* xfi, xfWindow* window, int x, int y, int width,
                         height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
        }
        
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (xfi->sw_gdi)
        {
                XPutImage(xfi->display, xfi->primary, window->gc, xfi->image,
@@ -883,6 +885,8 @@ void xf_UpdateWindowArea(xfInfo* xfi, xfWindow* window, int x, int y, int width,
                        ax, ay, width, height, x, y);
 
        XFlush(xfi->display);
+
+       ReleaseMutex(xfi->mutex);
 }
 
 BOOL xf_IsWindowBorder(xfInfo* xfi, xfWindow* xfw, int x, int y)
index a0e8ac9..7883999 100644 (file)
@@ -127,8 +127,12 @@ void xf_sw_end_paint(rdpContext* context)
                        w = gdi->primary->hdc->hwnd->invalid->w;
                        h = gdi->primary->hdc->hwnd->invalid->h;
 
+                       WaitForSingleObject(xfi->mutex, INFINITE);
+
                        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);
+
+                       ReleaseMutex(xfi->mutex);
                }
                else
                {
@@ -142,6 +146,8 @@ void xf_sw_end_paint(rdpContext* context)
                        ninvalid = gdi->primary->hdc->hwnd->ninvalid;
                        cinvalid = gdi->primary->hdc->hwnd->cinvalid;
 
+                       WaitForSingleObject(xfi->mutex, INFINITE);
+
                        for (i = 0; i < ninvalid; i++)
                        {
                                x = cinvalid[i].x;
@@ -154,6 +160,8 @@ void xf_sw_end_paint(rdpContext* context)
                        }
 
                        XFlush(xfi->display);
+
+                       ReleaseMutex(xfi->mutex);
                }
        }
        else
@@ -166,7 +174,11 @@ void xf_sw_end_paint(rdpContext* context)
                w = gdi->primary->hdc->hwnd->invalid->w;
                h = gdi->primary->hdc->hwnd->invalid->h;
 
+               WaitForSingleObject(xfi->mutex, INFINITE);
+
                xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1);
+
+               ReleaseMutex(xfi->mutex);
        }
 }
 
@@ -178,6 +190,8 @@ void xf_sw_desktop_resize(rdpContext* context)
        xfi = ((xfContext*) context)->xfi;
        settings = xfi->instance->settings;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (xfi->fullscreen != TRUE)
        {
                rdpGdi* gdi = context->gdi;
@@ -191,12 +205,15 @@ void xf_sw_desktop_resize(rdpContext* context)
                                        (char*) gdi->primary_buffer, gdi->width, gdi->height, xfi->scanline_pad, 0);
                }
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 void xf_hw_begin_paint(rdpContext* context)
 {
        xfInfo* xfi;
        xfi = ((xfContext*) context)->xfi;
+
        xfi->hdc->hwnd->invalid->null = 1;
        xfi->hdc->hwnd->ninvalid = 0;
 }
@@ -219,7 +236,11 @@ void xf_hw_end_paint(rdpContext* context)
                w = xfi->hdc->hwnd->invalid->w;
                h = xfi->hdc->hwnd->invalid->h;
 
+               WaitForSingleObject(xfi->mutex, INFINITE);
+
                xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1);
+
+               ReleaseMutex(xfi->mutex);
        }
 }
 
@@ -232,6 +253,8 @@ void xf_hw_desktop_resize(rdpContext* context)
        xfi = ((xfContext*) context)->xfi;
        settings = xfi->instance->settings;
 
+       WaitForSingleObject(xfi->mutex, INFINITE);
+
        if (xfi->fullscreen != TRUE)
        {
                xfi->width = settings->DesktopWidth;
@@ -258,9 +281,10 @@ void xf_hw_desktop_resize(rdpContext* context)
                XSetFunction(xfi->display, xfi->gc, GXcopy);
                XSetFillStyle(xfi->display, xfi->gc, FillSolid);
                XSetForeground(xfi->display, xfi->gc, 0);
-               XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
-                       0, 0, xfi->width, xfi->height);
+               XFillRectangle(xfi->display, xfi->drawable, xfi->gc, 0, 0, xfi->width, xfi->height);
        }
+
+       ReleaseMutex(xfi->mutex);
 }
 
 BOOL xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
@@ -275,19 +299,35 @@ BOOL xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* w
 
 BOOL xf_process_x_events(freerdp* instance)
 {
+       BOOL status;
        XEvent xevent;
+       int pending_status;
        xfInfo* xfi = ((xfContext*) instance->context)->xfi;
 
-       while (XPending(xfi->display))
+       status = TRUE;
+       pending_status = TRUE;
+
+       while (pending_status)
        {
-               memset(&xevent, 0, sizeof(xevent));
-               XNextEvent(xfi->display, &xevent);
+               WaitForSingleObject(xfi->mutex, INFINITE);
 
-               if (xf_event_process(instance, &xevent) != TRUE)
-                       return FALSE;
+               pending_status = XPending(xfi->display);
+
+               ReleaseMutex(xfi->mutex);
+
+               if (pending_status)
+               {
+                       ZeroMemory(&xevent, sizeof(xevent));
+
+                       XNextEvent(xfi->display, &xevent);
+                       status = xf_event_process(instance, &xevent);
+
+                       if (!status)
+                               return status;
+               }
        }
 
-       return TRUE;
+       return status;
 }
 
 void xf_create_window(xfInfo* xfi)
@@ -296,7 +336,7 @@ void xf_create_window(xfInfo* xfi)
        char* win_title;
        int width, height;
 
-       memset(&xevent, 0x00, sizeof(xevent));
+       ZeroMemory(&xevent, sizeof(xevent));
 
        width = xfi->width;
        height = xfi->height;
@@ -384,7 +424,7 @@ BOOL xf_get_pixmap_info(xfInfo* xfi)
        }
        XFree(pfs);
 
-       memset(&template, 0, sizeof(template));
+       ZeroMemory(&template, sizeof(template));
        template.class = TrueColor;
        template.screen = xfi->screen_number;
 
@@ -553,12 +593,12 @@ BOOL xf_pre_connect(freerdp* instance)
        if (settings->AuthenticationOnly)
        {
                /* Check --authonly has a username and password. */
-               if (settings->Username == NULL )
+               if (settings->Username == NULL)
                {
                        fprintf(stderr, "--authonly, but no -u username. Please provide one.\n");
                        exit(1);
                }
-               if (settings->Password == NULL )
+               if (settings->Password == NULL)
                {
                        fprintf(stderr, "--authonly, but no -p password. Please provide one.\n");
                        exit(1);
@@ -568,6 +608,9 @@ BOOL xf_pre_connect(freerdp* instance)
                return TRUE;
        }
 
+       //if (!XInitThreads())
+       //      printf("warning: XInitThreads() failure\n");
+
        xfi->display = XOpenDisplay(NULL);
 
        if (xfi->display == NULL)
@@ -750,7 +793,7 @@ BOOL xf_post_connect(freerdp* instance)
 
        xf_create_window(xfi);
 
-       memset(&gcv, 0, sizeof(gcv));
+       ZeroMemory(&gcv, sizeof(gcv));
        xfi->modifier_map = XGetModifierMapping(xfi->display);
 
        xfi->gc = XCreateGC(xfi->display, xfi->drawable, GCGraphicsExposures, &gcv);
@@ -966,11 +1009,11 @@ void xf_window_free(xfInfo* xfi)
 
        if (context != NULL)
        {
-                       cache_free(context->cache);
-                       context->cache = NULL;
+               cache_free(context->cache);
+               context->cache = NULL;
 
-                       rail_free(context->rail);
-                       context->rail = NULL;
+               rail_free(context->rail);
+               context->rail = NULL;
        }
 
        if (xfi->rfx_context) 
@@ -1005,12 +1048,74 @@ void xf_free(xfInfo* xfi)
        free(xfi);
 }
 
+void* xf_update_thread(void* arg)
+{
+       wMessage message;
+       wMessageQueue* queue;
+       freerdp* instance = (freerdp*) arg;
+
+       queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
+
+       while (MessageQueue_Wait(queue))
+       {
+               if (MessageQueue_Peek(queue, &message, TRUE))
+               {
+                       if (!freerdp_message_queue_process_message(instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message))
+                               break;
+               }
+       }
+
+       return NULL;
+}
+
+void* xf_input_thread(void* arg)
+{
+       int status;
+       xfInfo* xfi;
+       HANDLE event;
+       XEvent xevent;
+       freerdp* instance = (freerdp*) arg;
+
+       xfi = ((xfContext*) instance->context)->xfi;
+
+       event = CreateFileDescriptorEvent(NULL, TRUE, FALSE, xfi->xfds);
+
+       while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
+       {
+               WaitForSingleObject(xfi->mutex, INFINITE);
+
+               status = XPending(xfi->display);
+
+               ReleaseMutex(xfi->mutex);
+
+               if (status)
+               {
+                       ZeroMemory(&xevent, sizeof(xevent));
+
+                       WaitForSingleObject(xfi->mutex, INFINITE);
+
+                       XNextEvent(xfi->display, &xevent);
+                       status = xf_event_process(instance, &xevent);
+
+                       ReleaseMutex(xfi->mutex);
+
+                       if (!status)
+                               break;
+               }
+       }
+
+       printf("Closed from X\n");
+       xfi->disconnect = TRUE;
+
+       return NULL;
+}
+
 /** Main loop for the rdp connection.
  *  It will be run from the thread's entry point (thread_func()).
  *  It initiates the connection, and will continue to run until the session ends,
  *  processing events as they are received.
  *  @param instance - pointer to the rdp_freerdp structure that contains the session's settings
- *  @return A code from the enum XF_EXIT_CODE (0 if successfull)
+ *  @return A code from the enum XF_EXIT_CODE (0 if successful)
  */
 int xfreerdp_run(freerdp* instance)
 {
@@ -1026,12 +1131,15 @@ int xfreerdp_run(freerdp* instance)
        void* wfds[32];
        fd_set rfds_set;
        fd_set wfds_set;
-       int fd_update_event;
-       HANDLE update_event;
        int fd_input_event;
        HANDLE input_event;
        int select_status;
+       BOOL async_update;
+       BOOL async_input;
+       HANDLE update_thread;
+       HANDLE input_thread;
        rdpChannels* channels;
+       rdpSettings* settings;
        struct timeval timeout;
 
        ZeroMemory(rfds, sizeof(rfds));
@@ -1056,19 +1164,26 @@ int xfreerdp_run(freerdp* instance)
 
        xfi = ((xfContext*) instance->context)->xfi;
        channels = instance->context->channels;
+       settings = instance->context->settings;
 
-       fd_update_event = -1;
-       update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
+       async_update = settings->AsyncUpdate;
+       async_input = settings->AsyncInput;
 
-       if (update_event)
-               fd_update_event = GetEventFileDescriptor(update_event);
+       xfi->mutex = CreateMutex(NULL, FALSE, NULL);
 
-       fd_input_event = -1;
-       input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
+       if (async_update)
+       {
+               update_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_update_thread, instance, 0, NULL);
+       }
 
-       if (input_event)
+       if (async_input)
+       {
+               input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
                fd_input_event = GetEventFileDescriptor(input_event);
 
+               input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL);
+       }
+
        while (!xfi->disconnect && !freerdp_shall_disconnect(instance))
        {
                rcount = 0;
@@ -1080,24 +1195,27 @@ int xfreerdp_run(freerdp* instance)
                        ret = XF_EXIT_CONN_FAILED;
                        break;
                }
+
                if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
                {
                        printf("Failed to get channel manager file descriptor\n");
                        ret = XF_EXIT_CONN_FAILED;
                        break;
                }
-               if (xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
+
+               if (!async_input)
                {
-                       printf("Failed to get xfreerdp file descriptor\n");
-                       ret = XF_EXIT_CONN_FAILED;
-                       break;
+                       if (xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
+                       {
+                               printf("Failed to get xfreerdp file descriptor\n");
+                               ret = XF_EXIT_CONN_FAILED;
+                               break;
+                       }
                }
-
-               if (fd_update_event > 0)
-                       rfds[rcount++] = (void*) (long) fd_update_event;
-
-               if (fd_input_event > 0)
+               else
+               {
                        rfds[rcount++] = (void*) (long) fd_input_event;
+               }
 
                max_fds = 0;
                FD_ZERO(&rfds_set);
@@ -1128,10 +1246,8 @@ int xfreerdp_run(freerdp* instance)
                else if (select_status == -1)
                {
                        /* these are not really errors */
-                       if (!((errno == EAGAIN) ||
-                               (errno == EWOULDBLOCK) ||
-                               (errno == EINPROGRESS) ||
-                               (errno == EINTR))) /* signal occurred */
+                       if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) ||
+                               (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */
                        {
                                printf("xfreerdp_run: select failed\n");
                                break;
@@ -1143,46 +1259,66 @@ int xfreerdp_run(freerdp* instance)
                        printf("Failed to check FreeRDP file descriptor\n");
                        break;
                }
-               if (xf_process_x_events(instance) != TRUE)
-               {
-                       printf("Closed from X\n");
-                       break;
-               }
+
                if (freerdp_channels_check_fds(channels, instance) != TRUE)
                {
                        printf("Failed to check channel manager file descriptor\n");
                        break;
                }
-               xf_process_channel_event(channels, instance);
 
-               if (fd_update_event > 0)
-                       freerdp_message_queue_process_pending_messages(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
+               xf_process_channel_event(channels, instance);
 
-               if (fd_input_event > 0)
+               if (!async_input)
+               {
+                       if (xf_process_x_events(instance) != TRUE)
+                       {
+                               printf("Closed from X\n");
+                               break;
+                       }
+               }
+               else
+               {
                        freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE);
+               }
+       }
+
+       if (async_update)
+       {
+               wMessageQueue* update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
+               MessageQueue_PostQuit(update_queue, 0);
+               WaitForSingleObject(update_thread, INFINITE);
+               CloseHandle(update_thread);
        }
 
-       FILE *fin = fopen("/tmp/tsmf.tid", "rt");
-       if(fin)
+       FILE* fin = fopen("/tmp/tsmf.tid", "rt");
+
+       if (fin)
        {
+               FILE* fin1;
                int thid = 0;
+               int timeout;
+
                fscanf(fin, "%d", &thid);
                fclose(fin);
+
                pthread_kill((pthread_t) (size_t) thid, SIGUSR1);
 
-               FILE *fin1 = fopen("/tmp/tsmf.tid", "rt");
-               int timeout = 5;
+               fin1 = fopen("/tmp/tsmf.tid", "rt");
+               timeout = 5;
+
                while (fin1)
                {
                        fclose(fin1);
                        sleep(1);
                        timeout--;
+
                        if (timeout <= 0)
                        {
                                unlink("/tmp/tsmf.tid");
                                pthread_kill((pthread_t) (size_t) thid, SIGKILL);
                                break;
                        }
+
                        fin1 = fopen("/tmp/tsmf.tid", "rt");
                }
        }
index 19b7399..6f12db2 100644 (file)
@@ -114,6 +114,7 @@ struct xf_info
        BOOL disconnect;
        HCLRCONV clrconv;
        Window parent_window;
+       HANDLE mutex;
 
        HGDI_DC hdc;
        BOOL sw_gdi;
index 72f1a14..5d799f1 100644 (file)
@@ -194,9 +194,10 @@ xfInfo* xf_info_init()
         */
        xfi->use_xshm = FALSE;
 
-       xfi->display = XOpenDisplay(NULL);
+       if (!XInitThreads())
+               printf("warning: XInitThreads() failure\n");
 
-       XInitThreads();
+       xfi->display = XOpenDisplay(NULL);
 
        if (xfi->display == NULL)
        {