From 0e443484d81da21da5c94b07a5ba273bfdc3c198 Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Wed, 3 Dec 2014 15:41:10 +0100 Subject: [PATCH] xfreerdp: smart-sizing and software-gdi fixes * fixed crash on server-initiated desktop resize and fullscreen toggle with /gdi:sw * implemented desktop resize for /gdi:sw * check for availibility of XRender extension and show error messages if a setting would require it * fixed compile error if xrender devel packages are missing * fixed bug with server-initiated desktop resize in fullscreen mode --- client/X11/xf_client.c | 136 ++++++++++++++++++++++++++++------------- client/X11/xf_event.c | 23 ++++--- client/X11/xfreerdp.h | 1 + 3 files changed, 107 insertions(+), 53 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 2b066509f..d666d1f6b 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -203,9 +203,7 @@ BOOL xf_picture_transform_required(xfContext* xfc) } return FALSE; } - -#endif - +#endif /* WITH_XRENDER defined */ void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h) { @@ -218,6 +216,42 @@ void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h) XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); } +static void xf_desktop_resize(rdpContext* context) +{ + rdpSettings* settings; + xfContext* xfc = (xfContext*) context; + settings = xfc->settings; + + if (xfc->primary) + { + BOOL same = (xfc->primary == xfc->drawing) ? TRUE : FALSE; + XFreePixmap(xfc->display, xfc->primary); + xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth); + if (same) + xfc->drawing = xfc->primary; + } + + if (!xfc->fullscreen) + { + if (xfc->window) + xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, settings->DesktopHeight); + } + else + { +#ifdef WITH_XRENDER + if (!xfc->settings->SmartSizing) + { + xfc->scaledWidth = xfc->width; + xfc->scaledHeight = xfc->height; + } +#endif + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + XSetForeground(xfc->display, xfc->gc, 0); + XFillRectangle(xfc->display, xfc->drawable, xfc->gc, 0, 0, xfc->window->width, xfc->window->height); + } +} + void xf_sw_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; @@ -302,20 +336,22 @@ void xf_sw_desktop_resize(rdpContext* context) xf_lock_x11(xfc, TRUE); - if (!xfc->fullscreen) + xfc->width = context->settings->DesktopWidth; + xfc->height = context->settings->DesktopHeight; + + gdi_resize(gdi, xfc->width, xfc->height); + + if (xfc->image) { - gdi_resize(gdi, xfc->width, xfc->height); + xfc->image->data = NULL; + XDestroyImage(xfc->image); - if (xfc->image) - { - xfc->image->data = NULL; - XDestroyImage(xfc->image); - - xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, - (char*) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0); - } + xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0); } + xf_desktop_resize(context); + xf_unlock_x11(xfc, TRUE); } @@ -399,39 +435,15 @@ void xf_hw_end_paint(rdpContext* context) void xf_hw_desktop_resize(rdpContext* context) { - BOOL same; - rdpSettings* settings; xfContext* xfc = (xfContext*) context; - settings = xfc->settings; + rdpSettings* settings = xfc->settings; xf_lock_x11(xfc, TRUE); - if (!xfc->fullscreen) - { - xfc->width = settings->DesktopWidth; - xfc->height = settings->DesktopHeight; + xfc->width = settings->DesktopWidth; + xfc->height = settings->DesktopHeight; - if (xfc->window) - xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, settings->DesktopHeight); - - if (xfc->primary) - { - same = (xfc->primary == xfc->drawing) ? TRUE : FALSE; - XFreePixmap(xfc->display, xfc->primary); - - xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth); - - if (same) - xfc->drawing = xfc->primary; - } - } - else - { - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetForeground(xfc->display, xfc->gc, 0); - XFillRectangle(xfc->display, xfc->drawable, xfc->gc, 0, 0, xfc->width, xfc->height); - } + xf_desktop_resize(context); xf_unlock_x11(xfc, TRUE); } @@ -514,18 +526,22 @@ void xf_create_window(xfContext* xfc) sprintf(windowTitle, "FreeRDP: %s:%i", xfc->settings->ServerHostname, xfc->settings->ServerPort); } + if (xfc->fullscreen) + { + width = WidthOfScreen(xfc->screen); + height = HeightOfScreen(xfc->screen); + } + #ifdef WITH_XRENDER if (xfc->settings->SmartSizing) { - if(xfc->fullscreen) + if (xfc->fullscreen) { if (xfc->window) { xfc->settings->SmartSizingWidth = xfc->window->width; xfc->settings->SmartSizingHeight = xfc->window->height; } - width = WidthOfScreen(xfc->screen); - height = HeightOfScreen(xfc->screen); } else { @@ -791,6 +807,18 @@ void xf_check_extensions(xfContext* context) { context->xkbAvailable = TRUE; } + +#ifdef WITH_XRENDER + { + int xrender_event_base; + int xrender_error_base; + if (XRenderQueryExtension (context->display, &xrender_event_base, + &xrender_error_base)) + { + context->xrenderAvailable = TRUE; + } + } +#endif } /** @@ -1013,6 +1041,21 @@ BOOL xf_post_connect(freerdp *instance) xfc->offset_y = 0; #endif + if (!xfc->xrenderAvailable) + { + if (settings->SmartSizing) + { + WLog_ERR(TAG, "XRender not available: disabling smart-sizing"); + settings->SmartSizing = FALSE; + } + + if (settings->MultiTouchGestures) + { + WLog_ERR(TAG, "XRender not available: disabling local multi-touch gestures"); + settings->MultiTouchGestures = FALSE; + } + } + if (settings->RemoteApplicationMode) xfc->remote_app = TRUE; @@ -1618,6 +1661,7 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e) } } +#ifdef WITH_XRENDER static void xf_ZoomingChangeEventHandler(rdpContext* context, ZoomingChangeEventArgs* e) { xfContext* xfc = (xfContext*) context; @@ -1654,6 +1698,7 @@ static void xf_PanningChangeEventHandler(rdpContext* context, PanningChangeEvent xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); } +#endif /** * Client Interface @@ -1729,8 +1774,11 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context) xfc->settings = instance->context->settings; PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler); + +#ifdef WITH_XRENDER PubSub_SubscribeZoomingChange(context->pubSub, (pZoomingChangeEventHandler) xf_ZoomingChangeEventHandler); PubSub_SubscribePanningChange(context->pubSub, (pPanningChangeEventHandler) xf_PanningChangeEventHandler); +#endif return 0; } diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index c7899d45b..ff4c0d27a 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -641,25 +641,30 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) if (!app) { -#ifdef WITH_XRENDER - if (xfc->settings->SmartSizing && event->xconfigure.window == xfc->window->handle) + if (xfc->window->width != event->xconfigure.width || + xfc->window->height != event->xconfigure.height) { - if (xfc->window->width != event->xconfigure.width || - xfc->window->height != event->xconfigure.height) + xfc->window->width = event->xconfigure.width; + xfc->window->height = event->xconfigure.height; +#ifdef WITH_XRENDER + xfc->offset_x = 0; + xfc->offset_y = 0; + if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures) { - xfc->window->width = event->xconfigure.width; - xfc->window->height = event->xconfigure.height; if (!xfc->fullscreen) { xfc->scaledWidth = xfc->window->width; xfc->scaledHeight = xfc->window->height; } - xfc->offset_x = 0; - xfc->offset_y = 0; xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); } - } + else + { + xfc->scaledWidth = xfc->width; + xfc->scaledHeight = xfc->height; + } #endif + } return TRUE; } diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 3ca460902..75dcd84e6 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -195,6 +195,7 @@ struct xf_context wHashTable* railWindows; BOOL xkbAvailable; + BOOL xrenderAvailable; }; void xf_create_window(xfContext* xfc);