diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4772f73d8..d666d1f6b 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -4,6 +4,8 @@ * * Copyright 2013 Marc-Andre Moreau * Copyright 2013 Corey Clayton + * Copyright 2014 Thincast Technologies GmbH + * Copyright 2014 Norbert Federa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +31,7 @@ #ifdef WITH_XRENDER #include +#include #endif #ifdef WITH_XI @@ -47,10 +50,6 @@ #include #endif -#ifdef WITH_XRENDER -#include -#endif - #include #include @@ -104,44 +103,63 @@ static const size_t password_size = 512; -void xf_transform_window(xfContext* xfc) -{ - int ret; - int w; - int h; - long supplied; - Atom hints_atom; - XSizeHints *size_hints = NULL; - hints_atom = XInternAtom(xfc->display, "WM_SIZE_HINTS", 1); - ret = XGetWMSizeHints(xfc->display, xfc->window->handle, size_hints, &supplied, hints_atom); - if (ret == 0) - size_hints = XAllocSizeHints(); - w = (xfc->originalWidth * xfc->settings->ScalingFactor) + xfc->offset_x; - h = (xfc->originalHeight * xfc->settings->ScalingFactor) + xfc->offset_y; - if (w < 1) - w = 1; - if (h < 1) - h = 1; - if (size_hints) - { - size_hints->flags |= PMinSize | PMaxSize; - size_hints->min_width = size_hints->max_width = w; - size_hints->min_height = size_hints->max_height = h; - XSetWMNormalHints(xfc->display, xfc->window->handle, size_hints); - XResizeWindow(xfc->display, xfc->window->handle, w, h); - XFree(size_hints); - } -} - -void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale) -{ #ifdef WITH_XRENDER +static void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h) +{ XTransform transform; Picture windowPicture; Picture primaryPicture; XRenderPictureAttributes pa; XRenderPictFormat *picFormat; - XRectangle xr; + double xScalingFactor; + double yScalingFactor; + int x2; + int y2; + + if (xfc->scaledWidth <= 0 || xfc->scaledHeight <= 0) + { + WLog_ERR(TAG, "the current window dimensions are invalid"); + return; + } + + if (xfc->width <= 0 || xfc->height <= 0) + { + WLog_ERR(TAG, "the window dimensions are invalid"); + return; + } + + if (!w || !h) + { + WLog_ERR(TAG, "invalid width and/or height specified"); + return; + } + + xScalingFactor = xfc->width / (double)xfc->scaledWidth; + yScalingFactor = xfc->height / (double)xfc->scaledHeight; + + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + XSetForeground(xfc->display, xfc->gc, 0); + + /* Black out possible space between desktop and window borders */ + { + XRectangle box1 = { 0, 0, xfc->window->width, xfc->window->height }; + XRectangle box2 = { xfc->offset_x, xfc->offset_y, xfc->scaledWidth, xfc->scaledHeight }; + Region reg1 = XCreateRegion(); + Region reg2 = XCreateRegion(); + + XUnionRectWithRegion( &box1, reg1, reg1); + XUnionRectWithRegion( &box2, reg2, reg2); + + if (XSubtractRegion(reg1, reg2, reg1) && !XEmptyRegion(reg1)) + { + XSetRegion( xfc->display, xfc->gc, reg1); + XFillRectangle(xfc->display, xfc->window->handle, xfc->gc, 0, 0, xfc->window->width, xfc->window->height); + XSetClipMask(xfc->display, xfc->gc, None); + } + + XDestroyRegion(reg1); + XDestroyRegion(reg2); + } picFormat = XRenderFindStandardFormat(xfc->display, PictStandardRGB24); @@ -149,41 +167,89 @@ void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scal primaryPicture = XRenderCreatePicture(xfc->display, xfc->primary, picFormat, CPSubwindowMode, &pa); windowPicture = XRenderCreatePicture(xfc->display, xfc->window->handle, picFormat, CPSubwindowMode, &pa); - transform.matrix[0][0] = XDoubleToFixed(1); - transform.matrix[0][1] = XDoubleToFixed(0); - transform.matrix[0][2] = XDoubleToFixed(0); - transform.matrix[1][0] = XDoubleToFixed(0); - transform.matrix[1][1] = XDoubleToFixed(1); - transform.matrix[1][2] = XDoubleToFixed(0); - transform.matrix[2][0] = XDoubleToFixed(0); - transform.matrix[2][1] = XDoubleToFixed(0); - transform.matrix[2][2] = XDoubleToFixed(xfc->settings->ScalingFactor); + XRenderSetPictureFilter(xfc->display, primaryPicture, FilterBilinear, 0, 0); - if ((w != 0) && (h != 0)) - { - if (scale) - { - xr.x = x * xfc->settings->ScalingFactor; - xr.y = y * xfc->settings->ScalingFactor; - xr.width = (w+1) * xfc->settings->ScalingFactor; - xr.height = (h+1) * xfc->settings->ScalingFactor; - } - else - { - xr.x = x; - xr.y = y; - xr.width = w; - xr.height = h; - } + transform.matrix[0][0] = XDoubleToFixed(xScalingFactor); + transform.matrix[0][1] = XDoubleToFixed(0.0); + transform.matrix[0][2] = XDoubleToFixed(0.0); + transform.matrix[1][0] = XDoubleToFixed(0.0); + transform.matrix[1][1] = XDoubleToFixed(yScalingFactor); + transform.matrix[1][2] = XDoubleToFixed(0.0); + transform.matrix[2][0] = XDoubleToFixed(0.0); + transform.matrix[2][1] = XDoubleToFixed(0.0); + transform.matrix[2][2] = XDoubleToFixed(1.0); - XRenderSetPictureClipRectangles(xfc->display, primaryPicture, 0, 0, &xr, 1); - } + /* calculate and fix up scaled coordinates */ + x2 = x + w; + y2 = y + h; + x = floor(x / xScalingFactor) - 1; + y = floor(y / yScalingFactor) - 1; + w = ceil(x2 / xScalingFactor) + 1 - x; + h = ceil(y2 / yScalingFactor) + 1 - y; XRenderSetPictureTransform(xfc->display, primaryPicture, &transform); - XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, xfc->offset_x, xfc->offset_y, xfc->currentWidth, xfc->currentHeight); + XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, x, y, 0, 0, xfc->offset_x + x, xfc->offset_y + y, w, h); XRenderFreePicture(xfc->display, primaryPicture); XRenderFreePicture(xfc->display, windowPicture); +} + +BOOL xf_picture_transform_required(xfContext* xfc) +{ + if (xfc->offset_x || xfc->offset_y || + xfc->scaledWidth != xfc->width || + xfc->scaledHeight != xfc->height) + { + return TRUE; + } + return FALSE; +} +#endif /* WITH_XRENDER defined */ + +void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h) +{ +#ifdef WITH_XRENDER + if (xf_picture_transform_required(xfc)) { + xf_draw_screen_scaled(xfc, x, y, w, h); + return; + } #endif + 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) @@ -222,14 +288,7 @@ void xf_sw_end_paint(rdpContext* context) XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) - { - xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); - } - else - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); - } + xf_draw_screen(xfc, x, y, w, h); xf_unlock_x11(xfc, FALSE); } @@ -249,14 +308,7 @@ void xf_sw_end_paint(rdpContext* context) XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) - { - xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); - } - else - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); - } + xf_draw_screen(xfc, x, y, w, h); } XFlush(xfc->display); @@ -284,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); } @@ -328,14 +382,7 @@ void xf_hw_end_paint(rdpContext* context) xf_lock_x11(xfc, FALSE); - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) - { - xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); - } - else - { - XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, x, y, w, h, x, y); - } + xf_draw_screen(xfc, x, y, w, h); xf_unlock_x11(xfc, FALSE); } @@ -360,14 +407,7 @@ void xf_hw_end_paint(rdpContext* context) w = cinvalid[i].w; h = cinvalid[i].h; - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) - { - xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); - } - else - { - XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, x, y, w, h, x, y); - } + xf_draw_screen(xfc, x, y, w, h); } XFlush(xfc->display); @@ -395,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); } @@ -490,6 +506,10 @@ void xf_create_window(xfContext* xfc) xfc->attribs.colormap = xfc->colormap; xfc->attribs.bit_gravity = NorthWestGravity; xfc->attribs.win_gravity = NorthWestGravity; +#ifdef WITH_XRENDER + xfc->offset_x = 0; + xfc->offset_y = 0; +#endif if (xfc->settings->WindowTitle) { @@ -506,6 +526,34 @@ 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->window) + { + xfc->settings->SmartSizingWidth = xfc->window->width; + xfc->settings->SmartSizingHeight = xfc->window->height; + } + } + else + { + if (xfc->settings->SmartSizingWidth) + width = xfc->settings->SmartSizingWidth; + if (xfc->settings->SmartSizingHeight) + height = xfc->settings->SmartSizingHeight; + } + xfc->scaledWidth = width; + xfc->scaledHeight = height; + } +#endif xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height, xfc->settings->Decorations); free(windowTitle); @@ -525,23 +573,16 @@ void xf_create_window(xfContext* xfc) void xf_toggle_fullscreen(xfContext* xfc) { - Pixmap contents = 0; WindowStateChangeEventArgs e; xf_lock_x11(xfc, TRUE); - contents = XCreatePixmap(xfc->display, xfc->window->handle, xfc->width, xfc->height, xfc->depth); - - XCopyArea(xfc->display, xfc->primary, contents, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0); XDestroyWindow(xfc->display, xfc->window->handle); xfc->fullscreen = (xfc->fullscreen) ? FALSE : TRUE; xf_create_window(xfc); - XCopyArea(xfc->display, contents, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0); - XFreePixmap(xfc->display, contents); - xf_unlock_x11(xfc, TRUE); EventArgsInit(&e, "xfreerdp"); @@ -766,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 } /** @@ -978,16 +1031,31 @@ BOOL xf_post_connect(freerdp *instance) xfc->hdc = gdi_CreateDC(flags, xfc->bpp); } - xfc->originalWidth = settings->DesktopWidth; - xfc->originalHeight = settings->DesktopHeight; - xfc->currentWidth = xfc->originalWidth; - xfc->currentHeight = xfc->originalWidth; - xfc->settings->ScalingFactor = 1.0; - xfc->offset_x = 0; - xfc->offset_y = 0; xfc->width = settings->DesktopWidth; xfc->height = settings->DesktopHeight; +#ifdef WITH_XRENDER + xfc->scaledWidth = xfc->width; + xfc->scaledHeight = xfc->height; + xfc->offset_x = 0; + 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; @@ -1593,33 +1661,44 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e) } } -static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e) +#ifdef WITH_XRENDER +static void xf_ZoomingChangeEventHandler(rdpContext* context, ZoomingChangeEventArgs* e) +{ + xfContext* xfc = (xfContext*) context; + int w = xfc->scaledWidth + e->dx; + int h = xfc->scaledHeight + e->dy; + + if (e->dx == 0 && e->dy == 0) + return; + + if (w < 10) + w = 10; + + if (h < 10) + h = 10; + + if (w == xfc->scaledWidth && h == xfc->scaledHeight) + return; + + xfc->scaledWidth = w; + xfc->scaledHeight = h; + + xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); +} + +static void xf_PanningChangeEventHandler(rdpContext* context, PanningChangeEventArgs* e) { xfContext* xfc = (xfContext*) context; - xfc->settings->ScalingFactor += e->ScalingFactor; + if (e->dx == 0 && e->dy == 0) + return; - if (xfc->settings->ScalingFactor > 1.2) - xfc->settings->ScalingFactor = 1.2; + xfc->offset_x += e->dx; + xfc->offset_y += e->dy; - if (xfc->settings->ScalingFactor < 0.8) - xfc->settings->ScalingFactor = 0.8; - - xfc->currentWidth = xfc->originalWidth * xfc->settings->ScalingFactor; - xfc->currentHeight = xfc->originalHeight * xfc->settings->ScalingFactor; - - xf_transform_window(xfc); - - { - ResizeWindowEventArgs ev; - EventArgsInit(&ev, "xfreerdp"); - ev.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor; - ev.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor; - PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &ev); - } - - xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE); + xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); } +#endif /** * Client Interface @@ -1695,7 +1774,11 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context) xfc->settings = instance->context->settings; PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler); - PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler); + +#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 3348bacc3..ff4c0d27a 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -178,15 +178,42 @@ int xf_event_execute_action_script(xfContext* xfc, XEvent* event) return 1; } +void xf_event_adjust_coordinates(xfContext* xfc, int* x, int *y) +{ + if (!xfc->remote_app) + { +#ifdef WITH_XRENDER + if (xf_picture_transform_required(xfc)) + { + double xScalingFactor = xfc->width / (double)xfc->scaledWidth; + double yScalingFactor = xfc->height / (double)xfc->scaledHeight; + *x = (int)((*x - xfc->offset_x) * xScalingFactor); + *y = (int)((*y - xfc->offset_y) * yScalingFactor); + } +#endif + } + CLAMP_COORDINATES(*x, *y); +} + static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) { int x, y; int w, h; - - x = event->xexpose.x; - y = event->xexpose.y; - w = event->xexpose.width; - h = event->xexpose.height; + + if (!app && (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)) + { + x = 0; + y = 0; + w = xfc->width; + h = xfc->height; + } + else + { + x = event->xexpose.x; + y = event->xexpose.y; + w = event->xexpose.width; + h = event->xexpose.height; + } if (xfc->gfx) { @@ -196,28 +223,20 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) if (!app) { - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) - { - xf_draw_screen_scaled(xfc, x - xfc->offset_x, - y - xfc->offset_y, w, h, FALSE); - } - else - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); - } + xf_draw_screen(xfc, x, y, w, h); } else { xfAppWindow* appWindow; - + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - + if (appWindow) { xf_UpdateWindowArea(xfc, appWindow, x, y, w, h); } } - + return TRUE; } @@ -251,14 +270,8 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win RootWindowOfScreen(xfc->screen), x, y, &x, &y, &childWindow); } - - /* Take scaling in to consideration */ - if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) ) - { - x = (int)((x - xfc->offset_x) * (1.0 / xfc->settings->ScalingFactor) ); - y = (int)((y - xfc->offset_y) * (1.0 / xfc->settings->ScalingFactor) ); - } - CLAMP_COORDINATES(x,y); + + xf_event_adjust_coordinates(xfc, &x, &y); input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); @@ -358,16 +371,8 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window win } - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) - || (xfc->offset_y)) - { - x = (int) ((x - xfc->offset_x) - * (1.0 / xfc->settings->ScalingFactor)); - y = (int) ((y - xfc->offset_y) - * (1.0 / xfc->settings->ScalingFactor)); - } + xf_event_adjust_coordinates(xfc, &x, &y); - CLAMP_COORDINATES(x,y); if (extended) input->ExtendedMouseEvent(input, flags, x, y); else @@ -447,14 +452,7 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w x, y, &x, &y, &childWindow); } - - if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) - { - x = (int) ((x - xfc->offset_x) * (1.0 / xfc->settings->ScalingFactor)); - y = (int) ((y - xfc->offset_y) * (1.0 / xfc->settings->ScalingFactor)); - } - - CLAMP_COORDINATES(x,y); + xf_event_adjust_coordinates(xfc, &x, &y); if (extended) input->ExtendedMouseEvent(input, flags, x, y); @@ -642,7 +640,33 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) xfAppWindow* appWindow; if (!app) + { + 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) + { + if (!xfc->fullscreen) + { + xfc->scaledWidth = xfc->window->width; + xfc->scaledHeight = xfc->window->height; + } + xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); + } + else + { + xfc->scaledWidth = xfc->width; + xfc->scaledHeight = xfc->height; + } +#endif + } return TRUE; + } appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); @@ -754,12 +778,12 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) if (app) { xfAppWindow* appWindow; - + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); if (!appWindow) return TRUE; - + if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) || (((Atom) event->xproperty.atom == xfc->WM_STATE) && (event->xproperty.state != PropertyDelete))) { @@ -771,7 +795,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) unsigned long nitems; unsigned long bytes; unsigned char* prop; - + if ((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) { status = xf_GetWindowProperty(xfc, event->xproperty.window, @@ -795,7 +819,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) XFree(prop); } } - + if ((Atom) event->xproperty.atom == xfc->WM_STATE) { status = xf_GetWindowProperty(xfc, event->xproperty.window, @@ -828,7 +852,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) appWindow->rail_state = WINDOW_SHOW; xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE); } - } + } } return TRUE; @@ -907,7 +931,7 @@ static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, XEv case LMS_TERMINATING: /* Already sent RDP end move to server. Allow events to pass. */ break; - } + } return FALSE; } diff --git a/client/X11/xf_event.h b/client/X11/xf_event.h index 4198ab2f2..577650fe7 100644 --- a/client/X11/xf_event.h +++ b/client/X11/xf_event.h @@ -31,6 +31,8 @@ void xf_event_action_script_free(xfContext* xfc); BOOL xf_event_process(freerdp* instance, XEvent* event); void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...); +void xf_event_adjust_coordinates(xfContext* xfc, int* x, int *y); + BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app); BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app); BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app); diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 94f91ec77..0b3880817 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -3,6 +3,8 @@ * X11 GDI * * Copyright 2011 Marc-Andre Moreau + * Copyright 2014 Thincast Technologies GmbH + * Copyright 2014 Norbert Federa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -440,10 +442,6 @@ void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XFillRectangle(xfc->display, xfc->drawable, xfc->gc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); - } gdi_InvalidateRegion(xfc->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); } @@ -531,11 +529,6 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) if (xfc->drawing == xfc->primary) { - XSetFunction(xfc->display, xfc->gc, GXcopy); - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, patblt->nLeftRect, patblt->nTopRect); - } gdi_InvalidateRegion(xfc->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); } @@ -557,19 +550,6 @@ void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - if (xfc->unobscured) - { - XCopyArea(xfc->display, xfc->drawable, xfc->drawable, xfc->gc, scrblt->nXSrc, scrblt->nYSrc, - scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect); - } - } - else - { - XSetFunction(xfc->display, xfc->gc, GXcopy); - XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect); - } gdi_InvalidateRegion(xfc->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight); } @@ -597,13 +577,6 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XFillRectangle(xfc->display, xfc->drawable, xfc->gc, - opaque_rect->nLeftRect, opaque_rect->nTopRect, - opaque_rect->nWidth, opaque_rect->nHeight); - } - gdi_InvalidateRegion(xfc->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight); } @@ -636,12 +609,6 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XFillRectangle(xfc->display, xfc->drawable, xfc->gc, - rectangle->left, rectangle->top, - rectangle->width, rectangle->height); - } gdi_InvalidateRegion(xfc->hdc, rectangle->left, rectangle->top, rectangle->width, rectangle->height); } } @@ -672,24 +639,15 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XDrawLine(xfc->display, xfc->drawable, xfc->gc, - line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd); - } - int width, height; + int x, y, w, h; - width = line_to->nXStart - line_to->nXEnd; - height = line_to->nYStart - line_to->nYEnd; + x = MIN(line_to->nXStart, line_to->nXEnd); + y = MIN(line_to->nYStart, line_to->nYEnd); - if (width < 0) - width *= (-1); - - if (height < 0) - height *= (-1); - - gdi_InvalidateRegion(xfc->hdc, line_to->nXStart, line_to->nYStart, width, height); + w = abs(line_to->nXEnd - line_to->nXStart) + 1; + h = abs(line_to->nYEnd - line_to->nYStart) + 1; + gdi_InvalidateRegion(xfc->hdc, x, y, w, h); } XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -697,16 +655,51 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) xf_unlock_x11(xfc, FALSE); } +static void xf_gdi_invalidate_poly_region(xfContext* xfc, XPoint* points, int npoints, BOOL autoclose) +{ + int i, x, y, x1, y1, x2, y2, w, h; + + x1 = points[0].x; + y1 = points[0].y; + + for (i = 1; i <= npoints; i++) + { + if (i == npoints) + { + if (!autoclose) + break; + + x2 = points[0].x; + y2 = points[0].y; + + if (x2 == points[0].x && y2 == points[0].y) + break; + } + else + { + x2 = points[i].x + x1; + y2 = points[i].y + y1; + } + + x = MIN(x1, x2); + y = MIN(y1, y2); + + w = abs(x2 - x1) + 1; + h = abs(y2 - y1) + 1; + + x1 = x2; + y1 = y2; + + gdi_InvalidateRegion(xfc->hdc, x, y, w, h); + } +} + void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) { int i; - int x, y; - int x1, y1; - int x2, y2; int npoints; UINT32 color; XPoint* points; - int width, height; xfContext* xfc = (xfContext*) context; xf_lock_x11(xfc, FALSE); @@ -733,29 +726,7 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XDrawLines(xfc->display, xfc->drawable, xfc->gc, points, npoints, CoordModePrevious); - } - x1 = points[0].x; - y1 = points[0].y; - - for (i = 1; i < npoints; i++) - { - x2 = points[i].x + x1; - y2 = points[i].y + y1; - - x = (x2 < x1) ? x2 : x1; - width = (x2 > x1) ? x2 - x1 : x1 - x2; - - y = (y2 < y1) ? y2 : y1; - height = (y2 > y1) ? y2 - y1 : y1 - y2; - - x1 = x2; - y1 = y2; - - gdi_InvalidateRegion(xfc->hdc, x, y, width, height); - } + xf_gdi_invalidate_poly_region(xfc, points, npoints, FALSE); } XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -780,13 +751,6 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XCopyArea(xfc->display, bitmap->pixmap, xfc->drawable, xfc->gc, - memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight, - memblt->nLeftRect, memblt->nTopRect); - } - gdi_InvalidateRegion(xfc->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight); } @@ -852,12 +816,6 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) if (xfc->drawing == xfc->primary) { - if (!xfc->remote_app) - { - XCopyArea(xfc->display, bitmap->pixmap, xfc->drawable, xfc->gc, - mem3blt->nXSrc, mem3blt->nYSrc, mem3blt->nWidth, mem3blt->nHeight, - mem3blt->nLeftRect, mem3blt->nTopRect); - } gdi_InvalidateRegion(xfc->hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth, mem3blt->nHeight); } @@ -919,8 +877,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) if (xfc->drawing == xfc->primary) { - XFillPolygon(xfc->display, xfc->drawable, xfc->gc, - points, npoints, Complex, CoordModePrevious); + xf_gdi_invalidate_poly_region(xfc, points, npoints, TRUE); } XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -981,20 +938,6 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) XSetFillStyle(xfc->display, xfc->gc, FillTiled); XSetTile(xfc->display, xfc->gc, pattern); - XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y); - - XFillPolygon(xfc->display, xfc->drawing, xfc->gc, - points, npoints, Complex, CoordModePrevious); - - if (xfc->drawing == xfc->primary) - { - XFillPolygon(xfc->display, xfc->drawable, xfc->gc, - points, npoints, Complex, CoordModePrevious); - } - - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetTSOrigin(xfc->display, xfc->gc, 0, 0); - XFreePixmap(xfc->display, pattern); } else { @@ -1009,20 +952,20 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled); XSetStipple(xfc->display, xfc->gc, pattern); - XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y); + } - XFillPolygon(xfc->display, xfc->drawing, xfc->gc, - points, npoints, Complex, CoordModePrevious); + XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y); - if (xfc->drawing == xfc->primary) - { - XFillPolygon(xfc->display, xfc->drawable, xfc->gc, - points, npoints, Complex, CoordModePrevious); - } + XFillPolygon(xfc->display, xfc->drawing, xfc->gc, + points, npoints, Complex, CoordModePrevious); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetTSOrigin(xfc->display, xfc->gc, 0, 0); - XFreePixmap(xfc->display, pattern); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + XSetTSOrigin(xfc->display, xfc->gc, 0, 0); + XFreePixmap(xfc->display, pattern); + + if (xfc->drawing == xfc->primary) + { + xf_gdi_invalidate_poly_region(xfc, points, npoints, TRUE); } } else @@ -1174,18 +1117,12 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) XFree(image); } - /* Copy the updated region from backstore to the window. */ + /* Invalidate the updated region */ for (i = 0; i < message->numRects; i++) { tx = message->rects[i].x + cmd->destLeft; ty = message->rects[i].y + cmd->destTop; - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, - tx, ty, message->rects[i].width, message->rects[i].height, tx, ty); - } - xf_gdi_surface_update_frame(xfc, tx, ty, message->rects[i].width, message->rects[i].height); } @@ -1224,13 +1161,6 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) XFree(image); - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - cmd->destLeft, cmd->destTop, cmd->width, cmd->height, - cmd->destLeft, cmd->destTop); - } - xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height); XSetClipMask(xfc->display, xfc->gc, None); @@ -1263,13 +1193,6 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) cmd->width, cmd->height); XFree(image); - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - cmd->destLeft, cmd->destTop, - cmd->width, cmd->height, cmd->destLeft, cmd->destTop); - } - xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height); XSetClipMask(xfc->display, xfc->gc, None); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index f94551054..cb91efb7b 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -84,8 +84,20 @@ int xf_OutputUpdate(xfContext* xfc) surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL); } - XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, +#ifdef WITH_XRENDER + if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures) + { + XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, extents->left, extents->top, extents->left, extents->top, width, height); + + xf_draw_screen(xfc, extents->left, extents->top, width, height); + } + else +#endif + { + XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, + extents->left, extents->top, extents->left, extents->top, width, height); + } } region16_clear(&(xfc->invalidRegion)); diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 75bc950af..67958cbd8 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -57,7 +57,7 @@ typedef struct touch_contact double pos_y; double last_x; double last_y; - + } touchContact; touchContact contacts[MAX_CONTACTS]; @@ -87,7 +87,7 @@ const char* xf_input_get_class_string(int class) return "XIScrollClass"; else if (class == XITouchClass) return "XITouchClass"; - + return "XIUnknownClass"; } @@ -104,71 +104,71 @@ int xf_input_init(xfContext* xfc, Window window) XIEventMask evmasks[64]; int opcode, event, error; BYTE masks[8][XIMaskLen(XI_LASTEVENT)]; - + z_vector = 0; px_vector = 0; py_vector = 0; - + nmasks = 0; ndevices = 0; active_contacts = 0; ZeroMemory(contacts, sizeof(touchContact) * MAX_CONTACTS); - + if (!XQueryExtension(xfc->display, "XInputExtension", &opcode, &event, &error)) { WLog_WARN(TAG, "XInput extension not available."); return -1; } - + xfc->XInputOpcode = opcode; - + XIQueryVersion(xfc->display, &major, &minor); - + if (major * 1000 + minor < 2002) { WLog_WARN(TAG, "Server does not support XI 2.2"); return -1; } - + if (xfc->settings->MultiTouchInput) xfc->use_xinput = TRUE; - + info = XIQueryDevice(xfc->display, XIAllDevices, &ndevices); - + for (i = 0; i < ndevices; i++) { BOOL touch = FALSE; XIDeviceInfo* dev = &info[i]; - + for (j = 0; j < dev->num_classes; j++) { XIAnyClassInfo* class = dev->classes[j]; XITouchClassInfo* t = (XITouchClassInfo*) class; - + if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) && (strcmp(dev->name, "Virtual core pointer") != 0)) { touch = TRUE; } } - + for (j = 0; j < dev->num_classes; j++) { XIAnyClassInfo* class = dev->classes[j]; XITouchClassInfo* t = (XITouchClassInfo*) class; - + if (xfc->settings->MultiTouchInput) { WLog_INFO(TAG, "%s (%d) \"%s\" id: %d", xf_input_get_class_string(class->type), class->type, dev->name, dev->deviceid); } - + evmasks[nmasks].mask = masks[nmasks]; evmasks[nmasks].mask_len = sizeof(masks[0]); ZeroMemory(masks[nmasks], sizeof(masks[0])); evmasks[nmasks].deviceid = dev->deviceid; - + if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) && (strcmp(dev->name, "Virtual core pointer") != 0)) { @@ -178,13 +178,13 @@ int xf_input_init(xfContext* xfc, Window window) dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", dev->deviceid, t->mode, t->num_touches); } - + XISetMask(masks[nmasks], XI_TouchBegin); XISetMask(masks[nmasks], XI_TouchUpdate); XISetMask(masks[nmasks], XI_TouchEnd); nmasks++; } - + if (xfc->use_xinput) { if (!touch && (class->type == XIButtonClass) && strcmp(dev->name, "Virtual core pointer")) @@ -204,17 +204,17 @@ int xf_input_init(xfContext* xfc, Window window) if (nmasks > 0) xstatus = XISelectEvents(xfc->display, window, evmasks, nmasks); - + return 0; } BOOL xf_input_is_duplicate(XGenericEventCookie* cookie) { XIDeviceEvent* event; - + event = cookie->data; - - + + if ( (lastEvent.time == event->time) && (lastEvType == cookie->evtype) && (lastEvent.detail == event->detail) && @@ -223,18 +223,18 @@ BOOL xf_input_is_duplicate(XGenericEventCookie* cookie) { return TRUE; } - + return FALSE; } void xf_input_save_last_event(XGenericEventCookie* cookie) { XIDeviceEvent* event; - + event = cookie->data; - + lastEvType = cookie->evtype; - + lastEvent.time = event->time; lastEvent.detail = event->detail; lastEvent.event_x = event->event_x; @@ -245,30 +245,30 @@ void xf_input_detect_pan(xfContext* xfc) { double dx[2]; double dy[2]; - + double px; double py; - + double dist_x; double dist_y; - + if (active_contacts != 2) { return; } - + dx[0] = contacts[0].pos_x - contacts[0].last_x; dx[1] = contacts[1].pos_x - contacts[1].last_x; - + dy[0] = contacts[0].pos_y - contacts[0].last_y; dy[1] = contacts[1].pos_y - contacts[1].last_y; - + px = fabs(dx[0]) < fabs(dx[1]) ? dx[0] : dx[1]; py = fabs(dy[0]) < fabs(dy[1]) ? dy[0] : dy[1]; - + px_vector += px; py_vector += py; - + dist_x = fabs(contacts[0].pos_x - contacts[1].pos_x); dist_y = fabs(contacts[0].pos_y - contacts[1].pos_y); @@ -276,18 +276,17 @@ void xf_input_detect_pan(xfContext* xfc) { if (px_vector > PAN_THRESHOLD) { - { PanningChangeEventArgs e; - + EventArgsInit(&e, "xfreerdp"); - e.XPan = 5; - e.YPan = 0; + e.dx = 5; + e.dy = 0; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); } - + px_vector = 0; - + px_vector = 0; py_vector = 0; z_vector = 0; @@ -296,38 +295,38 @@ void xf_input_detect_pan(xfContext* xfc) { { PanningChangeEventArgs e; - + EventArgsInit(&e, "xfreerdp"); - e.XPan = -5; - e.YPan = 0; + e.dx = -5; + e.dy = 0; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); } - + px_vector = 0; - + px_vector = 0; py_vector = 0; z_vector = 0; } - + } - + if (dist_x > MIN_FINGER_DIST) { - + if (py_vector > PAN_THRESHOLD) { { PanningChangeEventArgs e; - + EventArgsInit(&e, "xfreerdp"); - e.XPan = 0; - e.YPan = 5; + e.dx = 0; + e.dy = 5; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); } - + py_vector = 0; - + px_vector = 0; py_vector = 0; z_vector = 0; @@ -336,15 +335,15 @@ void xf_input_detect_pan(xfContext* xfc) { { PanningChangeEventArgs e; - + EventArgsInit(&e, "xfreerdp"); - e.XPan = 0; - e.YPan = -5; + e.dx = 0; + e.dy = -5; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); } - + py_vector = 0; - + px_vector = 0; py_vector = 0; z_vector = 0; @@ -356,20 +355,20 @@ void xf_input_detect_pinch(xfContext* xfc) { double dist; double zoom; - + double delta; - ResizeWindowEventArgs e; - + ZoomingChangeEventArgs e; + if (active_contacts != 2) { firstDist = -1.0; return; } - + /* first calculate the distance */ dist = sqrt(pow(contacts[1].pos_x - contacts[0].last_x, 2.0) + pow(contacts[1].pos_y - contacts[0].last_y, 2.0)); - + /* if this is the first 2pt touch */ if (firstDist <= 0) { @@ -377,7 +376,7 @@ void xf_input_detect_pinch(xfContext* xfc) lastDist = firstDist; scale_cnt = 0; z_vector = 0; - + px_vector = 0; py_vector = 0; z_vector = 0; @@ -385,58 +384,38 @@ void xf_input_detect_pinch(xfContext* xfc) else { delta = lastDist - dist; - + if(delta > 1.0) delta = 1.0; if(delta < -1.0) delta = -1.0; - + /* compare the current distance to the first one */ zoom = (dist / firstDist); - + z_vector += delta; - + lastDist = dist; - + if (z_vector > ZOOM_THRESHOLD) { - xfc->settings->ScalingFactor -= 0.05; - - if (xfc->settings->ScalingFactor < 0.8) - xfc->settings->ScalingFactor = 0.8; - EventArgsInit(&e, "xfreerdp"); - e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor; - e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor; - - xf_transform_window(xfc); - PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e); - xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE); - + e.dx = e.dy = -10; + PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); + z_vector = 0; - px_vector = 0; py_vector = 0; z_vector = 0; } - + if (z_vector < -ZOOM_THRESHOLD) { - xfc->settings->ScalingFactor += 0.05; - - if (xfc->settings->ScalingFactor > 1.2) - xfc->settings->ScalingFactor = 1.2; - EventArgsInit(&e, "xfreerdp"); - e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor; - e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor; - - xf_transform_window(xfc); - PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e); - xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE); - + e.dx = e.dy = 10; + PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); + z_vector = 0; - px_vector = 0; py_vector = 0; z_vector = 0; @@ -447,7 +426,7 @@ void xf_input_detect_pinch(xfContext* xfc) void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event) { int i; - + for (i = 0; i < MAX_CONTACTS; i++) { if (contacts[i].id == 0) @@ -456,7 +435,7 @@ void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event) contacts[i].count = 1; contacts[i].pos_x = event->event_x; contacts[i].pos_y = event->event_y; - + active_contacts++; break; } @@ -476,10 +455,10 @@ void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event) contacts[i].last_y = contacts[i].pos_y; contacts[i].pos_x = event->event_x; contacts[i].pos_y = event->event_y; - + xf_input_detect_pinch(xfc); xf_input_detect_pan(xfc); - + break; } } @@ -495,7 +474,7 @@ void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event) { contacts[i].id = 0; contacts[i].count = 0; - + active_contacts--; break; } @@ -505,9 +484,9 @@ void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event) int xf_input_handle_event_local(xfContext* xfc, XEvent* event) { XGenericEventCookie* cookie = &event->xcookie; - + XGetEventData(xfc->display, cookie); - + if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode)) { switch (cookie->evtype) @@ -517,27 +496,27 @@ int xf_input_handle_event_local(xfContext* xfc, XEvent* event) xf_input_touch_begin(xfc, cookie->data); xf_input_save_last_event(cookie); break; - + case XI_TouchUpdate: if (xf_input_is_duplicate(cookie) == FALSE) xf_input_touch_update(xfc, cookie->data); xf_input_save_last_event(cookie); break; - + case XI_TouchEnd: if (xf_input_is_duplicate(cookie) == FALSE) xf_input_touch_end(xfc, cookie->data); xf_input_save_last_event(cookie); break; - + default: WLog_ERR(TAG, "unhandled xi type= %d", cookie->evtype); break; } } - + XFreeEventData(xfc->display,cookie); - + return 0; } @@ -610,16 +589,18 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype) int touchId; int contactId; RdpeiClientContext* rdpei = xfc->rdpei; - + if (!rdpei) return 0; - + xf_input_hide_cursor(xfc); touchId = event->detail; x = (int) event->event_x; y = (int) event->event_y; - + + xf_event_adjust_coordinates(xfc, &x, &y); + if (evtype == XI_TouchBegin) { WLog_DBG(TAG, "TouchBegin: %d", touchId); @@ -635,7 +616,7 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype) WLog_DBG(TAG, "TouchEnd: %d", touchId); contactId = rdpei->TouchEnd(rdpei, touchId, x, y); } - + return 0; } @@ -646,33 +627,33 @@ int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype) switch (evtype) { case XI_ButtonPress: - + xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y, event->detail, event->event, xfc->remote_app); break; - + case XI_ButtonRelease: - + xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y, event->detail, event->event, xfc->remote_app); break; - + case XI_Motion: - + xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y, event->detail, event->event, xfc->remote_app); break; } - + return 0; } int xf_input_handle_event_remote(xfContext* xfc, XEvent* event) { XGenericEventCookie* cookie = &event->xcookie; - + XGetEventData(xfc->display, cookie); - + if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode)) { switch (cookie->evtype) @@ -680,23 +661,23 @@ int xf_input_handle_event_remote(xfContext* xfc, XEvent* event) case XI_TouchBegin: xf_input_touch_remote(xfc, cookie->data, XI_TouchBegin); break; - + case XI_TouchUpdate: xf_input_touch_remote(xfc, cookie->data, XI_TouchUpdate); break; - + case XI_TouchEnd: xf_input_touch_remote(xfc, cookie->data, XI_TouchEnd); break; - + default: xf_input_event(xfc, cookie->data, cookie->evtype); break; } } - + XFreeEventData(xfc->display,cookie); - + return 0; } @@ -716,7 +697,7 @@ int xf_input_handle_event(xfContext* xfc, XEvent* event) { return xf_input_handle_event_remote(xfc, event); } - + if (xfc->settings->MultiTouchGestures) { return xf_input_handle_event_local(xfc, event); diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index ac0c6df55..218a48501 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -447,15 +447,15 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) if(xfc->fullscreen_toggle) { - if (keysym == XK_Return) - { - if (mod.Ctrl && mod.Alt) - { - /* Ctrl-Alt-Enter: toggle full screen */ - xf_toggle_fullscreen(xfc); - return TRUE; - } - } + if (keysym == XK_Return) + { + if (mod.Ctrl && mod.Alt) + { + /* Ctrl-Alt-Enter: toggle full screen */ + xf_toggle_fullscreen(xfc); + return TRUE; + } + } } if ((keysym == XK_c) || (keysym == XK_C)) @@ -468,140 +468,81 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) } } - if (keysym == XK_period) +#if 0 /* set to 1 to enable multi touch gesture simulation via keyboard */ +#ifdef WITH_XRENDER + if (!xfc->remote_app && xfc->settings->MultiTouchGestures) { if (mod.Ctrl && mod.Alt) { - /* Zoom In (scale larger) */ + int pdx = 0; + int pdy = 0; + int zdx = 0; + int zdy = 0; - double s = xfc->settings->ScalingFactor; - - s += 0.1; - - if (s > 2.0) - s = 2.0; - - xfc->settings->ScalingFactor = s; - - xfc->currentWidth = xfc->originalWidth * s; - xfc->currentHeight = xfc->originalHeight * s; - - xf_transform_window(xfc); - + switch(keysym) { - ResizeWindowEventArgs e; - - EventArgsInit(&e, "xfreerdp"); - e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor; - e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor; - PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e); + case XK_0: /* Ctrl-Alt-0: Reset scaling and panning */ + xfc->scaledWidth = xfc->width; + xfc->scaledHeight = xfc->height; + xfc->offset_x = 0; + xfc->offset_y = 0; + if (!xfc->fullscreen && (xfc->width != xfc->window->width || + xfc->height != xfc->window->height)) + { + xf_ResizeDesktopWindow(xfc, xfc->window, xfc->width, xfc->height); + } + xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); + return TRUE; + + case XK_1: /* Ctrl-Alt-1: Zoom in */ + zdx = zdy = 10; + break; + + case XK_2: /* Ctrl-Alt-2: Zoom out */ + zdx = zdy = -10; + break; + + case XK_3: /* Ctrl-Alt-3: Pan left */ + pdx = -10; + break; + + case XK_4: /* Ctrl-Alt-4: Pan right */ + pdx = 10; + break; + + case XK_5: /* Ctrl-Alt-5: Pan up */ + pdy = -10; + break; + + case XK_6: /* Ctrl-Alt-6: Pan up */ + pdy = 10; + break; } - xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE); - return TRUE; - } - } - - if (keysym == XK_comma) - { - if (mod.Ctrl && mod.Alt) - { - /* Zoom Out (scale smaller) */ - double s = xfc->settings->ScalingFactor; - - s -= 0.1; - - if (s < 0.5) - s = 0.5; - - xfc->settings->ScalingFactor = s; - - xfc->currentWidth = xfc->originalWidth * s; - xfc->currentHeight = xfc->originalHeight * s; - - xf_transform_window(xfc); - - { - ResizeWindowEventArgs e; - - EventArgsInit(&e, "xfreerdp"); - e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor; - e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor; - PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e); - } - - xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE); - return TRUE; - } - } - - if (keysym == XK_KP_4) - { - if (mod.Ctrl && mod.Alt) - { - + if (pdx != 0 || pdy != 0) { PanningChangeEventArgs e; - EventArgsInit(&e, "xfreerdp"); - e.XPan = -5; - e.YPan = 0; + e.dx = pdx; + e.dy = pdy; PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + return TRUE; } - - return TRUE; - } - } - - if (keysym == XK_KP_6) - { - if (mod.Ctrl && mod.Alt) - { - + + if (zdx != 0 || zdy != 0) { - PanningChangeEventArgs e; - + ZoomingChangeEventArgs e; EventArgsInit(&e, "xfreerdp"); - e.XPan = 5; - e.YPan = 0; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + e.dx = zdx; + e.dy = zdy; + PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); + return TRUE; } - return TRUE; } } - - if (keysym == XK_KP_8) - { - if (mod.Ctrl && mod.Alt) - { - { - PanningChangeEventArgs e; - - EventArgsInit(&e, "xfreerdp"); - e.XPan = 0; - e.YPan = -5; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); - } - return TRUE; - } - } - - if (keysym == XK_KP_2) - { - if (mod.Ctrl && mod.Alt) - { - { - PanningChangeEventArgs e; - - EventArgsInit(&e, "xfreerdp"); - e.XPan = 0; - e.YPan = 5; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); - } - return TRUE; - } - } - +#endif /* WITH_XRENDER defined */ +#endif /* pinch/zoom/pan simulation */ + return FALSE; } diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 752fb4620..c4629251c 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -397,7 +397,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig { XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); } - + XStoreName(xfc->display, window->handle, name); } @@ -412,11 +412,20 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int hei if (size_hints) { size_hints->flags = PMinSize | PMaxSize; - size_hints->min_width = size_hints->max_width = xfc->width; - size_hints->min_height = size_hints->max_height = xfc->height; + + size_hints->min_width = size_hints->max_width = width; + size_hints->min_height = size_hints->max_height = height; + +#ifdef WITH_XRENDER + if (xfc->settings->SmartSizing) + { + size_hints->min_width = size_hints->min_height = 1; + size_hints->max_width = size_hints->max_height = 16384; + } +#endif XSetWMNormalHints(xfc->display, window->handle, size_hints); - XResizeWindow(xfc->display, window->handle, xfc->width, xfc->height); + XResizeWindow(xfc->display, window->handle, width, height); XFree(size_hints); } } diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index cda774e97..75dcd84e6 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -132,15 +132,14 @@ struct xf_context UINT16 frame_x2; UINT16 frame_y2; - int originalWidth; - int originalHeight; - int currentWidth; - int currentHeight; int XInputOpcode; - BOOL enableScaling; +#ifdef WITH_XRENDER + int scaledWidth; + int scaledHeight; int offset_x; int offset_y; +#endif BOOL focused; BOOL use_xinput; @@ -196,6 +195,7 @@ struct xf_context wHashTable* railWindows; BOOL xkbAvailable; + BOOL xrenderAvailable; }; void xf_create_window(xfContext* xfc); @@ -250,8 +250,8 @@ enum XF_EXIT_CODE void xf_lock_x11(xfContext* xfc, BOOL display); void xf_unlock_x11(xfContext* xfc, BOOL display); -void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale); -void xf_transform_window(xfContext* xfc); +BOOL xf_picture_transform_required(xfContext* xfc); +void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h); FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index a731c31dd..a34531763 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -66,7 +66,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List detected monitors" }, { "t", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "title", "Window title" }, { "decorations", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueTrue, -1, NULL, "Window decorations" }, - { "smart-sizing", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Scale remote desktop to window size" }, + { "smart-sizing", COMMAND_LINE_VALUE_OPTIONAL, "<width>x<height>", NULL, NULL, -1, NULL, "Scale remote desktop to window size" }, { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "addin", "Addin" }, { "vc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Static virtual channel" }, { "dvc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Dynamic virtual channel" }, @@ -1344,7 +1344,19 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "smart-sizing") { - settings->SmartSizing = arg->Value ? TRUE : FALSE; + settings->SmartSizing = TRUE; + + if (arg->Value) + { + str = _strdup(arg->Value); + if ((p = strchr(str, 'x'))) + { + *p = '\0'; + settings->SmartSizingWidth = atoi(str); + settings->SmartSizingHeight = atoi(&p[1]); + } + free(str); + } } CommandLineSwitchCase(arg, "bpp") { diff --git a/include/freerdp/codec/audio.h b/include/freerdp/codec/audio.h index 384ce1f7c..d797f84f3 100644 --- a/include/freerdp/codec/audio.h +++ b/include/freerdp/codec/audio.h @@ -186,6 +186,10 @@ typedef struct AUDIO_FORMAT AUDIO_FORMAT; * Audio Format Functions */ +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API UINT32 rdpsnd_compute_audio_time_length(AUDIO_FORMAT* format, int size); FREERDP_API char* rdpsnd_get_audio_tag_string(UINT16 wFormatTag); @@ -195,4 +199,8 @@ FREERDP_API void rdpsnd_print_audio_formats(AUDIO_FORMAT* formats, UINT16 count) FREERDP_API void rdpsnd_free_audio_formats(AUDIO_FORMAT* formats, UINT16 count); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CODEC_AUDIO_H */ diff --git a/include/freerdp/codec/interleaved.h b/include/freerdp/codec/interleaved.h index d96cfbde9..205bc4456 100644 --- a/include/freerdp/codec/interleaved.h +++ b/include/freerdp/codec/interleaved.h @@ -38,6 +38,10 @@ struct _BITMAP_INTERLEAVED_CONTEXT wStream* bts; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* palette); @@ -49,5 +53,9 @@ FREERDP_API int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* int FREERDP_API BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor); FREERDP_API void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CODEC_INTERLEAVED_H */ diff --git a/include/freerdp/codec/jpeg.h b/include/freerdp/codec/jpeg.h index 637cdc62d..197f0b410 100644 --- a/include/freerdp/codec/jpeg.h +++ b/include/freerdp/codec/jpeg.h @@ -23,6 +23,14 @@ #include <freerdp/api.h> #include <freerdp/types.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API BOOL jpeg_decompress(BYTE* input, BYTE* output, int width, int height, int size, int bpp); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CODEC_JPEG_H */ diff --git a/include/freerdp/codec/planar.h b/include/freerdp/codec/planar.h index 4f2861a07..64b741d1b 100644 --- a/include/freerdp/codec/planar.h +++ b/include/freerdp/codec/planar.h @@ -97,6 +97,10 @@ struct _BITMAP_PLANAR_CONTEXT BYTE* TempBuffer; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]); FREERDP_API BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize); FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane); @@ -113,5 +117,9 @@ FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* conte FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BOOL vFlip); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CODEC_PLANAR_H */ diff --git a/include/freerdp/codecs.h b/include/freerdp/codecs.h index 2f1e4d4ab..0e8b2f41d 100644 --- a/include/freerdp/codecs.h +++ b/include/freerdp/codecs.h @@ -55,11 +55,19 @@ struct rdp_codecs BITMAP_INTERLEAVED_CONTEXT* interleaved; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags); FREERDP_API int freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags); FREERDP_API rdpCodecs* codecs_new(rdpContext* context); FREERDP_API void codecs_free(rdpCodecs* codecs); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CODECS_H */ diff --git a/include/freerdp/crypto/ber.h b/include/freerdp/crypto/ber.h index 59e1cceea..546b19c39 100644 --- a/include/freerdp/crypto/ber.h +++ b/include/freerdp/crypto/ber.h @@ -52,6 +52,10 @@ #define BER_PC(_pc) (_pc ? BER_CONSTRUCT : BER_PRIMITIVE) +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API BOOL ber_read_length(wStream* s, int* length); FREERDP_API int ber_write_length(wStream* s, int length); FREERDP_API int _ber_sizeof_length(int length); @@ -81,4 +85,8 @@ FREERDP_API int ber_write_integer(wStream* s, UINT32 value); FREERDP_API BOOL ber_read_integer_length(wStream* s, int* length); FREERDP_API int ber_sizeof_integer(UINT32 value); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_BER_H */ diff --git a/include/freerdp/crypto/certificate.h b/include/freerdp/crypto/certificate.h index d634c90f4..537829615 100644 --- a/include/freerdp/crypto/certificate.h +++ b/include/freerdp/crypto/certificate.h @@ -47,6 +47,10 @@ struct rdp_certificate_store rdpCertificateData* certificate_data; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint); FREERDP_API void certificate_data_free(rdpCertificateData* certificate_data); FREERDP_API rdpCertificateStore* certificate_store_new(rdpSettings* settings); @@ -55,4 +59,8 @@ FREERDP_API void certificate_store_free(rdpCertificateStore* certificate_store); FREERDP_API int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); FREERDP_API void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_CERTIFICATE_H */ diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index e642debff..f69963032 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -74,6 +74,10 @@ struct crypto_cert_struct X509 * px509; }; +#ifdef __cplusplus + extern "C" { +#endif + #define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH typedef struct crypto_sha1_struct* CryptoSha1; @@ -146,4 +150,8 @@ FREERDP_API void crypto_nonce(BYTE* nonce, int size); FREERDP_API char* crypto_base64_encode(const BYTE* data, int length); FREERDP_API void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_H */ diff --git a/include/freerdp/crypto/der.h b/include/freerdp/crypto/der.h index 20ace5f1b..3e75a4d39 100644 --- a/include/freerdp/crypto/der.h +++ b/include/freerdp/crypto/der.h @@ -22,6 +22,10 @@ #include <freerdp/crypto/er.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int _der_skip_length(int length); FREERDP_API int der_write_length(wStream* s, int length); FREERDP_API int der_get_content_length(int length); @@ -32,4 +36,8 @@ FREERDP_API int der_skip_contextual_tag(int length); FREERDP_API int der_write_contextual_tag(wStream* s, BYTE tag, int length, BOOL pc); FREERDP_API void der_write_octet_string(wStream* s, BYTE* oct_str, int length); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_DER_H */ diff --git a/include/freerdp/crypto/er.h b/include/freerdp/crypto/er.h index 91110e184..5fab63de3 100644 --- a/include/freerdp/crypto/er.h +++ b/include/freerdp/crypto/er.h @@ -56,6 +56,10 @@ #define ER_PC(_pc) (_pc ? ER_CONSTRUCT : ER_PRIMITIVE) +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API void er_read_length(wStream* s, int* length); FREERDP_API int er_write_length(wStream* s, int length, BOOL flag); FREERDP_API int _er_skip_length(int length); @@ -87,4 +91,8 @@ FREERDP_API int er_write_integer(wStream* s, INT32 value); FREERDP_API BOOL er_read_integer_length(wStream* s, int* length); FREERDP_API int er_skip_integer(INT32 value); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_ER_H */ diff --git a/include/freerdp/crypto/per.h b/include/freerdp/crypto/per.h index 60487a81a..e53cabb4f 100644 --- a/include/freerdp/crypto/per.h +++ b/include/freerdp/crypto/per.h @@ -24,6 +24,10 @@ #include <winpr/stream.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API BOOL per_read_length(wStream* s, UINT16* length); FREERDP_API void per_write_length(wStream* s, int length); FREERDP_API BOOL per_read_choice(wStream* s, BYTE* choice); @@ -47,4 +51,8 @@ FREERDP_API void per_write_octet_string(wStream* s, BYTE* oct_str, int length, i FREERDP_API BOOL per_read_numeric_string(wStream* s, int min); FREERDP_API void per_write_numeric_string(wStream* s, BYTE* num_str, int length, int min); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_PER_H */ diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h index fcc06d2e5..0d03279d7 100644 --- a/include/freerdp/crypto/tls.h +++ b/include/freerdp/crypto/tls.h @@ -83,6 +83,10 @@ struct rdp_tls BOOL isGatewayTransport; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int tls_connect(rdpTls* tls, BIO *underlying); FREERDP_API BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file); FREERDP_API BOOL tls_disconnect(rdpTls* tls); @@ -101,4 +105,8 @@ FREERDP_API BOOL tls_print_error(char* func, SSL* connection, int value); FREERDP_API rdpTls* tls_new(rdpSettings* settings); FREERDP_API void tls_free(rdpTls* tls); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CRYPTO_TLS_H */ diff --git a/include/freerdp/event.h b/include/freerdp/event.h index 0100d6988..fbe5e8507 100644 --- a/include/freerdp/event.h +++ b/include/freerdp/event.h @@ -43,19 +43,20 @@ DEFINE_EVENT_BEGIN(ResizeWindow) DEFINE_EVENT_END(ResizeWindow) DEFINE_EVENT_BEGIN(PanningChange) - int XPan; - int YPan; + int dx; + int dy; DEFINE_EVENT_END(PanningChange) -DEFINE_EVENT_BEGIN(ScalingFactorChange) - double ScalingFactor; -DEFINE_EVENT_END(ScalingFactorChange) +DEFINE_EVENT_BEGIN(ZoomingChange) + int dx; + int dy; +DEFINE_EVENT_END(ZoomingChange) DEFINE_EVENT_BEGIN(LocalResizeWindow) int width; int height; DEFINE_EVENT_END(LocalResizeWindow) - + DEFINE_EVENT_BEGIN(EmbedWindow) BOOL embed; void* handle; diff --git a/include/freerdp/gdi/16bpp.h b/include/freerdp/gdi/16bpp.h index 25cb21cc0..afa10d2da 100644 --- a/include/freerdp/gdi/16bpp.h +++ b/include/freerdp/gdi/16bpp.h @@ -26,6 +26,10 @@ typedef int (*pLineTo_16bpp)(HGDI_DC hdc, int nXEnd, int nYEnd); +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API UINT16 gdi_get_color_16bpp(HGDI_DC hdc, GDI_COLOR color); FREERDP_API int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); @@ -33,4 +37,8 @@ FREERDP_API int BitBlt_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth FREERDP_API int PatBlt_16bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); FREERDP_API int LineTo_16bpp(HGDI_DC hdc, int nXEnd, int nYEnd); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_16BPP_H */ diff --git a/include/freerdp/gdi/32bpp.h b/include/freerdp/gdi/32bpp.h index f33a42802..cb9139701 100644 --- a/include/freerdp/gdi/32bpp.h +++ b/include/freerdp/gdi/32bpp.h @@ -26,6 +26,10 @@ typedef int (*pLineTo_32bpp)(HGDI_DC hdc, int nXEnd, int nYEnd); +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API UINT32 gdi_get_color_32bpp(HGDI_DC hdc, GDI_COLOR color); FREERDP_API int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); @@ -33,4 +37,8 @@ FREERDP_API int BitBlt_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth FREERDP_API int PatBlt_32bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); FREERDP_API int LineTo_32bpp(HGDI_DC hdc, int nXEnd, int nYEnd); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_32BPP_H */ diff --git a/include/freerdp/gdi/8bpp.h b/include/freerdp/gdi/8bpp.h index 31b64bb9a..b609eacd0 100644 --- a/include/freerdp/gdi/8bpp.h +++ b/include/freerdp/gdi/8bpp.h @@ -26,6 +26,10 @@ typedef int (*pLineTo_8bpp)(HGDI_DC hdc, int nXEnd, int nYEnd); +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API BYTE gdi_get_color_8bpp(HGDI_DC hdc, GDI_COLOR color); FREERDP_API int FillRect_8bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); @@ -33,4 +37,8 @@ FREERDP_API int BitBlt_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, FREERDP_API int PatBlt_8bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); FREERDP_API int LineTo_8bpp(HGDI_DC hdc, int nXEnd, int nYEnd); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_8BPP_H */ diff --git a/include/freerdp/gdi/bitmap.h b/include/freerdp/gdi/bitmap.h index 976bb0b9d..c34713c6c 100644 --- a/include/freerdp/gdi/bitmap.h +++ b/include/freerdp/gdi/bitmap.h @@ -23,6 +23,10 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API GDI_COLOR gdi_GetPixel(HGDI_DC hdc, int nXPos, int nYPos); FREERDP_API GDI_COLOR gdi_SetPixel(HGDI_DC hdc, int X, int Y, GDI_COLOR crColor); FREERDP_API BYTE gdi_GetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y); @@ -40,4 +44,8 @@ FREERDP_API int gdi_BitBlt(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, typedef int (*p_BitBlt)(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_BITMAP_H */ diff --git a/include/freerdp/gdi/brush.h b/include/freerdp/gdi/brush.h index 10b81cb40..5313664a8 100644 --- a/include/freerdp/gdi/brush.h +++ b/include/freerdp/gdi/brush.h @@ -23,11 +23,19 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor); FREERDP_API HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp); FREERDP_API HGDI_BRUSH gdi_CreateHatchBrush(HGDI_BITMAP hbmp); FREERDP_API int gdi_PatBlt(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); +#ifdef __cplusplus + } +#endif + typedef int (*p_PatBlt)(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); #endif /* FREERDP_GDI_BRUSH_H */ diff --git a/include/freerdp/gdi/clipping.h b/include/freerdp/gdi/clipping.h index 0b2c4762e..75470f6e8 100644 --- a/include/freerdp/gdi/clipping.h +++ b/include/freerdp/gdi/clipping.h @@ -23,9 +23,17 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int gdi_SetClipRgn(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight); FREERDP_API HGDI_RGN gdi_GetClipRgn(HGDI_DC hdc); FREERDP_API int gdi_SetNullClipRgn(HGDI_DC hdc); FREERDP_API int gdi_ClipCoords(HGDI_DC hdc, int *x, int *y, int *w, int *h, int *srcx, int *srcy); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_CLIPPING_H */ diff --git a/include/freerdp/gdi/dc.h b/include/freerdp/gdi/dc.h index ed6963e76..5c66903a6 100644 --- a/include/freerdp/gdi/dc.h +++ b/include/freerdp/gdi/dc.h @@ -23,6 +23,10 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API HGDI_DC gdi_GetDC(void); FREERDP_API HGDI_DC gdi_CreateDC(UINT32 flags, int bpp); FREERDP_API HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc); @@ -30,4 +34,8 @@ FREERDP_API HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject); FREERDP_API int gdi_DeleteObject(HGDIOBJECT hgdiobject); FREERDP_API int gdi_DeleteDC(HGDI_DC hdc); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_DC_H */ diff --git a/include/freerdp/gdi/drawing.h b/include/freerdp/gdi/drawing.h index d1b99b8ed..536ea3053 100644 --- a/include/freerdp/gdi/drawing.h +++ b/include/freerdp/gdi/drawing.h @@ -23,6 +23,10 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int gdi_GetROP2(HGDI_DC hdc); FREERDP_API int gdi_SetROP2(HGDI_DC hdc, int fnDrawMode); FREERDP_API GDI_COLOR gdi_GetBkColor(HGDI_DC hdc); @@ -31,4 +35,8 @@ FREERDP_API int gdi_GetBkMode(HGDI_DC hdc); FREERDP_API int gdi_SetBkMode(HGDI_DC hdc, int iBkMode); FREERDP_API GDI_COLOR gdi_SetTextColor(HGDI_DC hdc, GDI_COLOR crColor); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_DRAWING_H */ diff --git a/include/freerdp/gdi/line.h b/include/freerdp/gdi/line.h index bd30cc412..18014cfd5 100644 --- a/include/freerdp/gdi/line.h +++ b/include/freerdp/gdi/line.h @@ -23,12 +23,20 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int gdi_LineTo(HGDI_DC hdc, int nXEnd, int nYEnd); FREERDP_API int gdi_PolylineTo(HGDI_DC hdc, GDI_POINT *lppt, int cCount); FREERDP_API int gdi_Polyline(HGDI_DC hdc, GDI_POINT *lppt, int cPoints); FREERDP_API int gdi_PolyPolyline(HGDI_DC hdc, GDI_POINT *lppt, int *lpdwPolyPoints, int cCount); FREERDP_API int gdi_MoveToEx(HGDI_DC hdc, int X, int Y, HGDI_POINT lpPoint); +#ifdef __cplusplus + } +#endif + typedef int (*p_LineTo)(HGDI_DC hdc, int nXEnd, int nYEnd); #endif /* FREERDP_GDI_LINE_H */ diff --git a/include/freerdp/gdi/palette.h b/include/freerdp/gdi/palette.h index 8ed2ec1c1..bca284977 100644 --- a/include/freerdp/gdi/palette.h +++ b/include/freerdp/gdi/palette.h @@ -23,7 +23,15 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API HGDI_PALETTE gdi_CreatePalette(HGDI_PALETTE palette); FREERDP_API HGDI_PALETTE gdi_GetSystemPalette(void); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_PALETTE_H */ diff --git a/include/freerdp/gdi/pen.h b/include/freerdp/gdi/pen.h index cc4904439..c4b5a7e59 100644 --- a/include/freerdp/gdi/pen.h +++ b/include/freerdp/gdi/pen.h @@ -23,9 +23,17 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API HGDI_PEN gdi_CreatePen(int fnPenStyle, int nWidth, int crColor); FREERDP_API BYTE gdi_GetPenColor_8bpp(HGDI_PEN pen); FREERDP_API UINT16 gdi_GetPenColor_16bpp(HGDI_PEN pen); FREERDP_API UINT32 gdi_GetPenColor_32bpp(HGDI_PEN pen); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_PEN_H */ diff --git a/include/freerdp/gdi/region.h b/include/freerdp/gdi/region.h index 093545131..be3269150 100644 --- a/include/freerdp/gdi/region.h +++ b/include/freerdp/gdi/region.h @@ -23,6 +23,10 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API HGDI_RGN gdi_CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); FREERDP_API HGDI_RECT gdi_CreateRect(int xLeft, int yTop, int xRight, int yBottom); FREERDP_API void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn); @@ -42,4 +46,8 @@ FREERDP_API int gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src); FREERDP_API int gdi_PtInRect(HGDI_RECT rc, int x, int y); FREERDP_API int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_REGION_H */ diff --git a/include/freerdp/gdi/shape.h b/include/freerdp/gdi/shape.h index 1fdf9abb0..9b96324dd 100644 --- a/include/freerdp/gdi/shape.h +++ b/include/freerdp/gdi/shape.h @@ -23,6 +23,10 @@ #include <freerdp/api.h> #include <freerdp/gdi/gdi.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API int gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); FREERDP_API int gdi_FillRect(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); FREERDP_API int gdi_Polygon(HGDI_DC hdc, GDI_POINT *lpPoints, int nCount); @@ -31,4 +35,8 @@ FREERDP_API int gdi_Rectangle(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRig typedef int (*p_FillRect)(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_GDI_SHAPE_H */ diff --git a/include/freerdp/locale/locale.h b/include/freerdp/locale/locale.h index c36c1027b..d2b767b0a 100644 --- a/include/freerdp/locale/locale.h +++ b/include/freerdp/locale/locale.h @@ -230,8 +230,16 @@ #define YORUBA 0x046A #define ZULU 0x0435 +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API DWORD freerdp_get_system_locale_id(void); FREERDP_API const char* freerdp_get_system_locale_name_from_id(DWORD localeId); FREERDP_API int freerdp_detect_keyboard_layout_from_system_locale(DWORD* keyboardLayoutId); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_LOCALE_H */ diff --git a/include/freerdp/locale/timezone.h b/include/freerdp/locale/timezone.h index d4d14a25d..1d062c8f1 100644 --- a/include/freerdp/locale/timezone.h +++ b/include/freerdp/locale/timezone.h @@ -24,6 +24,14 @@ #include <freerdp/types.h> #include <freerdp/settings.h> +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API void freerdp_time_zone_detect(TIME_ZONE_INFO* clientTimeZone); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_LOCALE_TIMEZONE_H */ diff --git a/include/freerdp/metrics.h b/include/freerdp/metrics.h index 5b453ceb1..8706aa31d 100644 --- a/include/freerdp/metrics.h +++ b/include/freerdp/metrics.h @@ -31,10 +31,18 @@ struct rdp_metrics double TotalCompressionRatio; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API double metrics_write_bytes(rdpMetrics* metrics, UINT32 UncompressedBytes, UINT32 CompressedBytes); FREERDP_API rdpMetrics* metrics_new(rdpContext* context); FREERDP_API void metrics_free(rdpMetrics* metrics); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_METRICS_H */ diff --git a/include/freerdp/server/cliprdr.h b/include/freerdp/server/cliprdr.h index c7d881c6b..dd41b930c 100644 --- a/include/freerdp/server/cliprdr.h +++ b/include/freerdp/server/cliprdr.h @@ -47,7 +47,15 @@ struct _cliprdr_server_context CliprdrServerPrivate* priv; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API CliprdrServerContext* cliprdr_server_context_new(HANDLE vcm); FREERDP_API void cliprdr_server_context_free(CliprdrServerContext* context); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_H */ diff --git a/include/freerdp/server/drdynvc.h b/include/freerdp/server/drdynvc.h index 9b41126de..be1693a76 100644 --- a/include/freerdp/server/drdynvc.h +++ b/include/freerdp/server/drdynvc.h @@ -44,7 +44,15 @@ struct _drdynvc_client_context DrdynvcServerPrivate* priv; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm); FREERDP_API void drdynvc_server_context_free(DrdynvcServerContext* context); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_H */ diff --git a/include/freerdp/server/encomsp.h b/include/freerdp/server/encomsp.h index dd1f9eba9..a5037e628 100644 --- a/include/freerdp/server/encomsp.h +++ b/include/freerdp/server/encomsp.h @@ -71,7 +71,15 @@ struct _encomsp_server_context EncomspServerPrivate* priv; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API EncomspServerContext* encomsp_server_context_new(HANDLE vcm); FREERDP_API void encomsp_server_context_free(EncomspServerContext* context); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CHANNEL_SERVER_ENCOMSP_H */ diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h index 3fe23e869..af9c3c46e 100644 --- a/include/freerdp/server/rdpdr.h +++ b/include/freerdp/server/rdpdr.h @@ -45,7 +45,15 @@ struct _rdpdr_server_context RdpdrServerPrivate* priv; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm); FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CHANNEL_SERVER_RDPDR_H */ diff --git a/include/freerdp/server/remdesk.h b/include/freerdp/server/remdesk.h index b2c3f118c..c817a199d 100644 --- a/include/freerdp/server/remdesk.h +++ b/include/freerdp/server/remdesk.h @@ -47,8 +47,16 @@ struct _remdesk_server_context RemdeskServerPrivate* priv; }; +#ifdef __cplusplus + extern "C" { +#endif + FREERDP_API RemdeskServerContext* remdesk_server_context_new(HANDLE vcm); FREERDP_API void remdesk_server_context_free(RemdeskServerContext* context); +#ifdef __cplusplus + } +#endif + #endif /* FREERDP_CHANNEL_SERVER_REMDESK_H */ diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index ca358f11e..ce914b119 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -664,7 +664,8 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_SmartSizing 1551 #define FreeRDP_XPan 1552 #define FreeRDP_YPan 1553 -#define FreeRDP_ScalingFactor 1554 +#define FreeRDP_SmartSizingWidth 1554 +#define FreeRDP_SmartSizingHeight 1555 #define FreeRDP_SoftwareGdi 1601 #define FreeRDP_LocalConnection 1602 #define FreeRDP_AuthenticationOnly 1603 @@ -1074,8 +1075,9 @@ struct rdp_settings ALIGN64 BOOL SmartSizing; /* 1551 */ ALIGN64 int XPan; /* 1552 */ ALIGN64 int YPan; /* 1553 */ - ALIGN64 double ScalingFactor; /* 1554 */ - UINT64 padding1601[1601 - 1555]; /* 1555 */ + ALIGN64 UINT32 SmartSizingWidth; /* 1554 */ + ALIGN64 UINT32 SmartSizingHeight; /* 1555 */ + UINT64 padding1601[1601 - 1556]; /* 1556 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ @@ -1459,9 +1461,6 @@ FREERDP_API int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 p FREERDP_API char* freerdp_get_param_string(rdpSettings* settings, int id); FREERDP_API int freerdp_set_param_string(rdpSettings* settings, int id, const char* param); -FREERDP_API double freerdp_get_param_double(rdpSettings* settings, int id); -FREERDP_API int freerdp_set_param_double(rdpSettings* settings, int id, double param); - #ifdef __cplusplus } #endif diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index f93423a27..d9c986668 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -1281,7 +1281,7 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param) case FreeRDP_SmartSizing: settings->SmartSizing = param; - break; + break; case FreeRDP_MouseMotion: settings->MouseMotion = param; @@ -1834,6 +1834,12 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id) case FreeRDP_DynamicChannelArraySize: return settings->DynamicChannelArraySize; + case FreeRDP_SmartSizingWidth: + return settings->SmartSizingWidth; + + case FreeRDP_SmartSizingHeight: + return settings->SmartSizingHeight; + default: WLog_ERR(TAG, "freerdp_get_param_uint32: unknown id: %d", id); return 0; @@ -2167,7 +2173,7 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param) /* Mark field as modified */ settings->SettingsModified[id] = 1; - + return 0; } @@ -2199,7 +2205,7 @@ int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 param) /* Mark field as modified */ settings->SettingsModified[id] = 1; - + return 0; } @@ -2587,35 +2593,3 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param) return 0; } - -double freerdp_get_param_double(rdpSettings* settings, int id) -{ - switch (id) - { - case FreeRDP_ScalingFactor: - return settings->ScalingFactor; - - default: - WLog_ERR(TAG, "unknown id: %d", id); - return 0; - } -} - -int freerdp_set_param_double(rdpSettings* settings, int id, double param) -{ - switch (id) - { - case FreeRDP_ScalingFactor: - settings->ScalingFactor = param; - break; - - default: - return -1; - } - - /* Mark field as modified */ - settings->SettingsModified[id] = 1; - - return 0; -} - diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index fa53f44d4..acd0d2741 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -449,6 +449,8 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) if (status < 0) goto end; + rdp->do_crypt_license = TRUE; + /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(settings->ClientRandom, rdp)) goto end; diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index fd17baf2d..a08702456 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -385,7 +385,7 @@ static wEventType FreeRDP_Events[] = DEFINE_EVENT_ENTRY(LocalResizeWindow) DEFINE_EVENT_ENTRY(EmbedWindow) DEFINE_EVENT_ENTRY(PanningChange) - DEFINE_EVENT_ENTRY(ScalingFactorChange) + DEFINE_EVENT_ENTRY(ZoomingChange) DEFINE_EVENT_ENTRY(ErrorInfo) DEFINE_EVENT_ENTRY(Terminate) DEFINE_EVENT_ENTRY(ConnectionResult) diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index dd6f1d5c9..8b69c6131 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -441,7 +441,7 @@ BOOL transport_bio_buffered_drain(BIO *bio) return status >= 0; } -void tcp_get_ip_address(rdpTcp* tcp) +void freerdp_tcp_get_ip_address(rdpTcp* tcp) { BYTE* ip; socklen_t length; @@ -467,7 +467,7 @@ void tcp_get_ip_address(rdpTcp* tcp) tcp->settings->ClientAddress = _strdup(tcp->ip_address); } -void tcp_get_mac_address(rdpTcp* tcp) +void freerdp_tcp_get_mac_address(rdpTcp* tcp) { #ifdef LINUX BYTE* mac; @@ -531,7 +531,7 @@ int uds_connect(const char* path) #endif } -BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) +BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) { int status; UINT32 option_value; @@ -678,8 +678,8 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) SetEventFileDescriptor(tcp->event, tcp->sockfd); - tcp_get_ip_address(tcp); - tcp_get_mac_address(tcp); + freerdp_tcp_get_ip_address(tcp); + freerdp_tcp_get_mac_address(tcp); option_value = 1; option_len = sizeof(option_value); @@ -708,7 +708,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) if (!tcp->ipcSocket) { - if (!tcp_set_keep_alive_mode(tcp)) + if (!freerdp_tcp_set_keep_alive_mode(tcp)) return FALSE; } @@ -724,7 +724,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) return TRUE; } -BOOL tcp_disconnect(rdpTcp* tcp) +BOOL freerdp_tcp_disconnect(rdpTcp* tcp) { if (tcp->sockfd != -1) { @@ -737,7 +737,7 @@ BOOL tcp_disconnect(rdpTcp* tcp) return TRUE; } -BOOL tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking) +BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking) { #ifndef _WIN32 int flags; @@ -784,7 +784,7 @@ BOOL tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking) return TRUE; } -BOOL tcp_set_keep_alive_mode(rdpTcp* tcp) +BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp) { #ifndef _WIN32 UINT32 option_value; @@ -844,7 +844,7 @@ BOOL tcp_set_keep_alive_mode(rdpTcp* tcp) return TRUE; } -int tcp_attach(rdpTcp* tcp, int sockfd) +int freerdp_tcp_attach(rdpTcp* tcp, int sockfd) { tcp->sockfd = sockfd; SetEventFileDescriptor(tcp->event, tcp->sockfd); @@ -881,7 +881,7 @@ int tcp_attach(rdpTcp* tcp, int sockfd) return 0; } -HANDLE tcp_get_event_handle(rdpTcp* tcp) +HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp) { if (!tcp) return NULL; @@ -889,7 +889,7 @@ HANDLE tcp_get_event_handle(rdpTcp* tcp) return tcp->event; } -int tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds) +int freerdp_tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds) { int status; @@ -927,7 +927,7 @@ int tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds) return status; } -int tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds) +int freerdp_tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds) { int status; @@ -965,7 +965,7 @@ int tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds) return status; } -rdpTcp* tcp_new(rdpSettings* settings) +rdpTcp* freerdp_tcp_new(rdpSettings* settings) { rdpTcp* tcp; @@ -998,7 +998,7 @@ out_free: return NULL; } -void tcp_free(rdpTcp* tcp) +void freerdp_tcp_free(rdpTcp* tcp) { if (!tcp) return; diff --git a/libfreerdp/core/tcp.h b/libfreerdp/core/tcp.h index bfb0f8d00..d2dd6340c 100644 --- a/libfreerdp/core/tcp.h +++ b/libfreerdp/core/tcp.h @@ -58,18 +58,18 @@ struct rdp_tcp HANDLE event; }; -BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout); -BOOL tcp_disconnect(rdpTcp* tcp); -int tcp_read(rdpTcp* tcp, BYTE* data, int length); -int tcp_write(rdpTcp* tcp, BYTE* data, int length); -int tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds); -int tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds); -BOOL tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking); -BOOL tcp_set_keep_alive_mode(rdpTcp* tcp); -int tcp_attach(rdpTcp* tcp, int sockfd); -HANDLE tcp_get_event_handle(rdpTcp* tcp); +BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout); +BOOL freerdp_tcp_disconnect(rdpTcp* tcp); +int freerdp_tcp_read(rdpTcp* tcp, BYTE* data, int length); +int freerdp_tcp_write(rdpTcp* tcp, BYTE* data, int length); +int freerdp_tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds); +int freerdp_tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds); +BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking); +BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp); +int freerdp_tcp_attach(rdpTcp* tcp, int sockfd); +HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp); -rdpTcp* tcp_new(rdpSettings* settings); -void tcp_free(rdpTcp* tcp); +rdpTcp* freerdp_tcp_new(rdpSettings* settings); +void freerdp_tcp_free(rdpTcp* tcp); #endif /* __TCP_H */ diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 5154c198b..fc2158a12 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -71,7 +71,7 @@ wStream* transport_send_stream_init(rdpTransport* transport, int size) void transport_attach(rdpTransport* transport, int sockfd) { - tcp_attach(transport->TcpIn, sockfd); + freerdp_tcp_attach(transport->TcpIn, sockfd); transport->SplitInputOutput = FALSE; transport->TcpOut = transport->TcpIn; transport->frontBio = transport->TcpIn->bufferedBio; @@ -443,14 +443,14 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por { transport->layer = TRANSPORT_LAYER_TSG; transport->SplitInputOutput = TRUE; - transport->TcpOut = tcp_new(settings); + transport->TcpOut = freerdp_tcp_new(settings); - if (!tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort, timeout) || - !tcp_set_blocking_mode(transport->TcpIn, FALSE)) + if (!freerdp_tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort, timeout) || + !freerdp_tcp_set_blocking_mode(transport->TcpIn, FALSE)) return FALSE; - if (!tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort, timeout) || - !tcp_set_blocking_mode(transport->TcpOut, FALSE)) + if (!freerdp_tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort, timeout) || + !freerdp_tcp_set_blocking_mode(transport->TcpOut, FALSE)) return FALSE; if (!transport_tsg_connect(transport, hostname, port)) @@ -460,7 +460,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por } else { - status = tcp_connect(transport->TcpIn, hostname, port, timeout); + status = freerdp_tcp_connect(transport->TcpIn, hostname, port, timeout); transport->SplitInputOutput = FALSE; transport->TcpOut = transport->TcpIn; transport->frontBio = transport->TcpIn->bufferedBio; @@ -554,11 +554,11 @@ static int transport_wait_for_read(rdpTransport* transport) if (tcpIn->readBlocked) { - return tcp_wait_read(tcpIn, 10); + return freerdp_tcp_wait_read(tcpIn, 10); } else if (tcpIn->writeBlocked) { - return tcp_wait_write(tcpIn, 10); + return freerdp_tcp_wait_write(tcpIn, 10); } USleep(1000); @@ -572,11 +572,11 @@ static int transport_wait_for_write(rdpTransport* transport) if (tcpOut->writeBlocked) { - return tcp_wait_write(tcpOut, 10); + return freerdp_tcp_wait_write(tcpOut, 10); } else if (tcpOut->readBlocked) { - return tcp_wait_read(tcpOut, 10); + return freerdp_tcp_wait_read(tcpOut, 10); } USleep(1000); @@ -942,12 +942,12 @@ void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount) void transport_get_read_handles(rdpTransport* transport, HANDLE* events, DWORD* count) { - events[*count] = tcp_get_event_handle(transport->TcpIn); + events[*count] = freerdp_tcp_get_event_handle(transport->TcpIn); (*count)++; if (transport->SplitInputOutput) { - events[*count] = tcp_get_event_handle(transport->TcpOut); + events[*count] = freerdp_tcp_get_event_handle(transport->TcpOut); (*count)++; } @@ -1067,12 +1067,12 @@ BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking) if (transport->SplitInputOutput) { - status &= tcp_set_blocking_mode(transport->TcpIn, blocking); - status &= tcp_set_blocking_mode(transport->TcpOut, blocking); + status &= freerdp_tcp_set_blocking_mode(transport->TcpIn, blocking); + status &= freerdp_tcp_set_blocking_mode(transport->TcpOut, blocking); } else { - status &= tcp_set_blocking_mode(transport->TcpIn, blocking); + status &= freerdp_tcp_set_blocking_mode(transport->TcpIn, blocking); } if (transport->layer == TRANSPORT_LAYER_TSG || transport->layer == TRANSPORT_LAYER_TSG_TLS) @@ -1166,7 +1166,7 @@ rdpTransport* transport_new(rdpSettings* settings) if (!transport->log) goto out_free; - transport->TcpIn = tcp_new(settings); + transport->TcpIn = freerdp_tcp_new(settings); if (!transport->TcpIn) goto out_free; @@ -1217,7 +1217,7 @@ out_free_receivebuffer: out_free_receivepool: StreamPool_Free(transport->ReceivePool); out_free_tcpin: - tcp_free(transport->TcpIn); + freerdp_tcp_free(transport->TcpIn); out_free: free(transport); return NULL; @@ -1247,10 +1247,10 @@ void transport_free(rdpTransport* transport) transport->TlsOut = NULL; if (transport->TcpIn) - tcp_free(transport->TcpIn); + freerdp_tcp_free(transport->TcpIn); if (transport->TcpOut != transport->TcpIn) - tcp_free(transport->TcpOut); + freerdp_tcp_free(transport->TcpOut); transport->TcpIn = NULL; transport->TcpOut = NULL; diff --git a/winpr/include/winpr/timezone.h b/winpr/include/winpr/timezone.h index 14480d025..ce917dc4c 100644 --- a/winpr/include/winpr/timezone.h +++ b/winpr/include/winpr/timezone.h @@ -25,6 +25,10 @@ #include <winpr/windows.h> +#ifdef __cplusplus +extern "C" { +#endif + #ifndef _WIN32 typedef struct _TIME_ZONE_INFORMATION @@ -91,5 +95,9 @@ WINPR_API DWORD GetDynamicTimeZoneInformationEffectiveYears(const PDYNAMIC_TIME_ #endif +#ifdef __cplusplus +} +#endif + #endif /* WINPR_TIMEZONE_H */ diff --git a/winpr/libwinpr/handle/CMakeLists.txt b/winpr/libwinpr/handle/CMakeLists.txt index d58ff5a37..09ea2f13d 100644 --- a/winpr/libwinpr/handle/CMakeLists.txt +++ b/winpr/libwinpr/handle/CMakeLists.txt @@ -2,6 +2,7 @@ # libwinpr-handle cmake build script # # Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> +# Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +16,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -winpr_module_add(handle.c handle.h) +winpr_module_add(handle.c handle.h nonehandle.c nonehandle.h) if(${CMAKE_SYSTEM_NAME} MATCHES SunOS) winpr_library_add(rt) diff --git a/winpr/libwinpr/handle/handle.c b/winpr/libwinpr/handle/handle.c index ff02aea9b..5f236ca17 100644 --- a/winpr/libwinpr/handle/handle.c +++ b/winpr/libwinpr/handle/handle.c @@ -3,6 +3,7 @@ * Handle Management * * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -127,14 +128,7 @@ BOOL CloseHandle(HANDLE hObject) LeaveCriticalSection(&_HandleCloseCbsLock); - if (Type == HANDLE_TYPE_PROCESS) - { - WINPR_PROCESS* process; - process = (WINPR_PROCESS*) Object; - free(process); - return TRUE; - } - else if (Type == HANDLE_TYPE_MUTEX) + if (Type == HANDLE_TYPE_MUTEX) { WINPR_MUTEX* mutex; mutex = (WINPR_MUTEX*) Object; diff --git a/winpr/libwinpr/handle/nonehandle.c b/winpr/libwinpr/handle/nonehandle.c new file mode 100644 index 000000000..5a8b2be11 --- /dev/null +++ b/winpr/libwinpr/handle/nonehandle.c @@ -0,0 +1,74 @@ +/** + * WinPR: Windows Portable Runtime + * NoneHandle a.k.a. brathandle should be used where a handle is needed, but + * functionality is not implemented yet or not implementable. + * + * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "nonehandle.h" + +#ifndef _WIN32 + +#include <pthread.h> + +static HANDLE_CLOSE_CB _NoneHandleCloseCb; +static pthread_once_t none_initialized = PTHREAD_ONCE_INIT; + +static BOOL NoneHandleCloseHandle(HANDLE handle) +{ + WINPR_NONE_HANDLE* none = (WINPR_NONE_HANDLE*) handle; + free(none); + return TRUE; +} + +static BOOL NoneHandleIsHandle(HANDLE handle) +{ + WINPR_NONE_HANDLE* none = (WINPR_NONE_HANDLE*) handle; + + if (!none || none->Type != HANDLE_TYPE_NONE) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + return TRUE; +} + +static void NoneHandleInitialize(void) +{ + _NoneHandleCloseCb.IsHandled = NoneHandleIsHandle; + _NoneHandleCloseCb.CloseHandle = NoneHandleCloseHandle; + RegisterHandleCloseCb(&_NoneHandleCloseCb); +} + +HANDLE CreateNoneHandle() +{ + WINPR_NONE_HANDLE* none; + none = (WINPR_NONE_HANDLE*) calloc(1, sizeof(WINPR_NONE_HANDLE)); + + if (!none) + return NULL; + + pthread_once(&none_initialized, NoneHandleInitialize); + + return (HANDLE)none; +} + +#endif diff --git a/winpr/libwinpr/handle/nonehandle.h b/winpr/libwinpr/handle/nonehandle.h new file mode 100644 index 000000000..1aa509888 --- /dev/null +++ b/winpr/libwinpr/handle/nonehandle.h @@ -0,0 +1,40 @@ +/** + * WinPR: Windows Portable Runtime + * NoneHandle a.k.a. brathandle should be used where a handle is needed, but + * functionality is not implemented yet or not implementable. + * + * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_NONE_HANDLE_PRIVATE_H +#define WINPR_NONE_HANDLE_PRIVATE_H + +#ifndef _WIN32 + +#include <winpr/handle.h> +#include "handle.h" + +struct winpr_none_handle +{ + WINPR_HANDLE_DEF(); +}; + +typedef struct winpr_none_handle WINPR_NONE_HANDLE; + +HANDLE CreateNoneHandle(); + +#endif /*_WIN32*/ + +#endif /* WINPR_NONE_HANDLE_PRIVATE_H */ diff --git a/winpr/libwinpr/thread/process.c b/winpr/libwinpr/thread/process.c index 4f5adc026..624904ab7 100644 --- a/winpr/libwinpr/thread/process.c +++ b/winpr/libwinpr/thread/process.c @@ -3,6 +3,7 @@ * Process Thread Functions * * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +23,7 @@ #endif #include <winpr/handle.h> +#include "../handle/nonehandle.h" #include <winpr/thread.h> #include <fcntl.h> @@ -78,6 +80,9 @@ #include "../handle/handle.h" #include "../security/security.h" +static HANDLE_CLOSE_CB _ProcessHandleCloseCb; +static pthread_once_t process_initialized = PTHREAD_ONCE_INIT; + char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock) { char* p; @@ -172,6 +177,8 @@ char* FindApplicationPath(char* application) return filename; } +HANDLE CreateProcessHandle(pid_t pid); + BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, @@ -183,8 +190,8 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, LPSTR* pArgs = NULL; char** envp = NULL; char* filename = NULL; - WINPR_THREAD* thread; - WINPR_PROCESS* process; + HANDLE thread; + HANDLE process; WINPR_ACCESS_TOKEN* token; LPTCH lpszEnvironmentBlock; BOOL ret = FALSE; @@ -273,36 +280,22 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, /* parent process */ } - process = (WINPR_PROCESS*) malloc(sizeof(WINPR_PROCESS)); + process = CreateProcessHandle(pid); if (!process) { goto finish; } - ZeroMemory(process, sizeof(WINPR_PROCESS)); - - WINPR_HANDLE_SET_TYPE(process, HANDLE_TYPE_PROCESS); - - process->pid = pid; - process->status = 0; - process->dwExitCode = 0; - - thread = (WINPR_THREAD*) malloc(sizeof(WINPR_THREAD)); - - ZeroMemory(thread, sizeof(WINPR_THREAD)); + thread = CreateNoneHandle(); if (!thread) { goto finish; } - WINPR_HANDLE_SET_TYPE(thread, HANDLE_TYPE_THREAD); - - thread->mainProcess = TRUE; - - lpProcessInformation->hProcess = (HANDLE) process; - lpProcessInformation->hThread = (HANDLE) thread; + lpProcessInformation->hProcess = process; + lpProcessInformation->hThread = thread; lpProcessInformation->dwProcessId = (DWORD) pid; lpProcessInformation->dwThreadId = (DWORD) pid; @@ -462,5 +455,49 @@ BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode) return TRUE; } + +static BOOL ProcessHandleCloseHandle(HANDLE handle) +{ + WINPR_PROCESS* process = (WINPR_PROCESS*) handle; + free(process); + return TRUE; +} + +static BOOL ProcessHandleIsHandle(HANDLE handle) +{ + WINPR_PROCESS* process = (WINPR_PROCESS*) handle; + + if (!process || process->Type != HANDLE_TYPE_PROCESS) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + return TRUE; +} + +static void ProcessHandleInitialize(void) +{ + _ProcessHandleCloseCb.IsHandled = ProcessHandleIsHandle; + _ProcessHandleCloseCb.CloseHandle = ProcessHandleCloseHandle; + RegisterHandleCloseCb(&_ProcessHandleCloseCb); +} + +HANDLE CreateProcessHandle(pid_t pid) +{ + WINPR_PROCESS* process; + process = (WINPR_PROCESS*) calloc(1, sizeof(WINPR_PROCESS)); + + if (!process) + return NULL; + + pthread_once(&process_initialized, ProcessHandleInitialize); + process->pid = pid; + process->Type = HANDLE_TYPE_PROCESS; + + return (HANDLE)process; +} + + #endif