Merge pull request #2240 from nfedera/fix-2014-12-01-01
xfreerdp: pinch/pan fixes and smart-sizing
This commit is contained in:
commit
c17a831367
@ -4,6 +4,8 @@
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
|
||||
* Copyright 2014 Thincast Technologies GmbH
|
||||
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
|
||||
*
|
||||
* 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 <X11/extensions/Xrender.h>
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_XI
|
||||
@ -47,10 +50,6 @@
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_XRENDER
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#endif
|
||||
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
#include <errno.h>
|
||||
@ -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,55 @@ 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
|
||||
|
||||
|
||||
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)
|
||||
@ -222,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, 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 +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, 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);
|
||||
@ -328,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, 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 +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, 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);
|
||||
@ -490,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)
|
||||
{
|
||||
@ -506,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);
|
||||
@ -525,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");
|
||||
@ -978,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->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 (settings->RemoteApplicationMode)
|
||||
xfc->remote_app = TRUE;
|
||||
|
||||
@ -1593,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, 0, 0, FALSE);
|
||||
xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1695,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;
|
||||
}
|
||||
|
@ -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,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);
|
||||
|
||||
@ -754,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)))
|
||||
{
|
||||
@ -771,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,
|
||||
@ -795,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,
|
||||
@ -828,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;
|
||||
@ -907,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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -3,6 +3,8 @@
|
||||
* X11 GDI
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Thincast Technologies GmbH
|
||||
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
|
||||
*
|
||||
* 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);
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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, 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);
|
||||
|
||||
|
@ -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, "<title>", 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")
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user