From 25f66d2e6d2290c3e251982a1850da4d7d59b32f Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Mon, 1 Dec 2014 11:56:44 +0100 Subject: [PATCH] xfreerdp: added smart sizing, mt gesture fixes - removed setting ScalingFactor - added settings SmartSizingWidth and SmartSizingHeight - changed option /smart-sizing to optionally support x - consolidated transformation of input event coordinates - rdp8 gfx ignored scaling and panning offsets: fixed - never resize window on panning/pinching - simplified keyboard multitouch gesture debugging emulation - disabled keyboard multitouch gesture emulation debug code via define --- client/X11/xf_client.c | 263 +++++++++++++++++++---------------- client/X11/xf_event.c | 114 ++++++++------- client/X11/xf_event.h | 2 + client/X11/xf_gfx.c | 14 +- client/X11/xf_input.c | 235 ++++++++++++++----------------- client/X11/xf_keyboard.c | 194 +++++++++----------------- client/X11/xf_window.c | 17 ++- client/X11/xfreerdp.h | 13 +- client/common/cmdline.c | 16 ++- include/freerdp/event.h | 13 +- include/freerdp/settings.h | 11 +- libfreerdp/common/settings.c | 44 ++---- libfreerdp/core/freerdp.c | 2 +- 13 files changed, 456 insertions(+), 482 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 1d1535979..2b066509f 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -31,6 +31,7 @@ #ifdef WITH_XRENDER #include +#include #endif #ifdef WITH_XI @@ -49,11 +50,6 @@ #include #endif -#ifdef WITH_XRENDER -#include -#include -#endif - #include #include @@ -107,38 +103,9 @@ 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) -{ #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; @@ -146,19 +113,53 @@ void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h) XRenderPictFormat *picFormat; double xScalingFactor; double yScalingFactor; + int x2; + int y2; - if (xfc->currentWidth <= 0 || xfc->currentHeight <= 0) { + if (xfc->scaledWidth <= 0 || xfc->scaledHeight <= 0) + { WLog_ERR(TAG, "the current window dimensions are invalid"); return; } - if (xfc->originalWidth <= 0 || xfc->originalHeight <= 0) { - WLog_ERR(TAG, "the original window dimensions are invalid"); + if (xfc->width <= 0 || xfc->height <= 0) + { + WLog_ERR(TAG, "the window dimensions are invalid"); return; } - xScalingFactor = xfc->originalWidth / (double)xfc->currentWidth; - yScalingFactor = xfc->originalHeight / (double)xfc->currentHeight; + 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); @@ -178,22 +179,43 @@ void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h) transform.matrix[2][1] = XDoubleToFixed(0.0); transform.matrix[2][2] = XDoubleToFixed(1.0); - if ((w != 0) && (h != 0)) - { - int x2 = x + w; - int 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; - } + /* 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, 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 + + +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); } void xf_sw_begin_paint(rdpContext* context) @@ -232,14 +254,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); - } - 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); } @@ -259,14 +274,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); - } - 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); @@ -338,14 +346,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); - } - 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); } @@ -370,14 +371,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); - } - 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); @@ -500,6 +494,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) { @@ -516,6 +514,30 @@ void xf_create_window(xfContext* xfc) sprintf(windowTitle, "FreeRDP: %s:%i", xfc->settings->ServerHostname, xfc->settings->ServerPort); } +#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; + } + width = WidthOfScreen(xfc->screen); + height = HeightOfScreen(xfc->screen); + } + 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); @@ -535,23 +557,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"); @@ -988,16 +1003,16 @@ 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->originalHeight; - 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 (settings->RemoteApplicationMode) xfc->remote_app = TRUE; @@ -1603,32 +1618,41 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e) } } -static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e) +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, xfc->originalWidth, xfc->originalHeight); + xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); } /** @@ -1705,7 +1729,8 @@ 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); + PubSub_SubscribeZoomingChange(context->pubSub, (pZoomingChangeEventHandler) xf_ZoomingChangeEventHandler); + PubSub_SubscribePanningChange(context->pubSub, (pPanningChangeEventHandler) xf_PanningChangeEventHandler); return 0; } diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index a90978e5e..c7899d45b 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,27 +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); - } - 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; } @@ -250,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); @@ -357,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 @@ -446,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); @@ -641,7 +640,28 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) xfAppWindow* appWindow; if (!app) + { +#ifdef WITH_XRENDER + if (xfc->settings->SmartSizing && event->xconfigure.window == xfc->window->handle) + { + if (xfc->window->width != event->xconfigure.width || + xfc->window->height != event->xconfigure.height) + { + xfc->window->width = event->xconfigure.width; + xfc->window->height = event->xconfigure.height; + if (!xfc->fullscreen) + { + xfc->scaledWidth = xfc->window->width; + xfc->scaledHeight = xfc->window->height; + } + xfc->offset_x = 0; + xfc->offset_y = 0; + xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height); + } + } +#endif return TRUE; + } appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); @@ -753,12 +773,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))) { @@ -770,7 +790,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, @@ -794,7 +814,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, @@ -827,7 +847,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; @@ -906,7 +926,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_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 0249c739c..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, xfc->originalWidth, xfc->originalHeight); - + 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, xfc->originalWidth, xfc->originalHeight); - + 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 a1c8d4333..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,141 +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, xfc->originalWidth, xfc->originalHeight); - 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, xfc->originalWidth, xfc->originalHeight); - 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 222cd00a6..3ca460902 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; @@ -250,8 +249,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); -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 f1f964070..69079cb2e 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/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/settings.h b/include/freerdp/settings.h index a53c14d32..1adcf36dd 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -661,7 +661,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 @@ -1068,8 +1069,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 */ @@ -1453,9 +1455,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/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)