X11: Scale cursor when SmartSizing is on

This commit is contained in:
Nathan Loewen 2020-09-08 10:12:27 -05:00
parent cba6181154
commit f4f795f323
2 changed files with 164 additions and 25 deletions

View File

@ -226,13 +226,129 @@ static BOOL xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL pr
return TRUE;
}
static BOOL _xf_Pointer_GetCursorForCurrentScale(rdpContext* context, const rdpPointer* pointer,
Cursor* cursor)
{
#ifdef WITH_XCURSOR
UINT32 CursorFormat;
xfContext* xfc = (xfContext*)context;
xfPointer* xpointer = (xfPointer*)pointer;
XcursorImage ci;
rdpSettings* settings;
UINT32 xTargetSize;
UINT32 yTargetSize;
double xscale;
double yscale;
size_t size;
int cursorIndex = -1;
if (!context || !pointer || !context->gdi)
return FALSE;
settings = xfc->context.settings;
if (!settings)
return FALSE;
xscale = (settings->SmartSizing ? xfc->scaledWidth / (double)settings->DesktopWidth : 1);
yscale = (settings->SmartSizing ? xfc->scaledHeight / (double)settings->DesktopHeight : 1);
xTargetSize = pointer->width * xscale;
yTargetSize = pointer->height * yscale;
for (int i = 0; i < xpointer->nCursors; i++)
{
if (xpointer->cursorWidths[i] == xTargetSize && xpointer->cursorHeights[i] == yTargetSize)
{
cursorIndex = i;
}
}
if (cursorIndex == -1)
{
xf_lock_x11(xfc);
if (!xfc->invert)
CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_RGBA32 : PIXEL_FORMAT_ABGR32;
else
CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_ARGB32;
if (xpointer->nCursors == xpointer->mCursors)
{
xpointer->mCursors = (xpointer->mCursors == 0 ? 1 : xpointer->mCursors * 2);
if (!(xpointer->cursorWidths = (UINT32*)realloc(xpointer->cursorWidths,
sizeof(UINT32) * xpointer->mCursors)))
{
xf_unlock_x11(xfc);
return FALSE;
}
if (!(xpointer->cursorHeights = (UINT32*)realloc(xpointer->cursorHeights,
sizeof(UINT32) * xpointer->mCursors)))
{
xf_unlock_x11(xfc);
return FALSE;
}
if (!(xpointer->cursors =
(Cursor*)realloc(xpointer->cursors, sizeof(Cursor) * xpointer->mCursors)))
{
xf_unlock_x11(xfc);
return FALSE;
}
}
ZeroMemory(&ci, sizeof(ci));
ci.version = XCURSOR_IMAGE_VERSION;
ci.size = sizeof(ci);
ci.width = xTargetSize;
ci.height = yTargetSize;
ci.xhot = pointer->xPos * xscale;
ci.yhot = pointer->yPos * yscale;
size = ci.height * ci.width * GetBytesPerPixel(CursorFormat);
if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16)))
{
xf_unlock_x11(xfc);
return FALSE;
}
if (xscale != 1 || yscale != 1)
{
if (!freerdp_image_scale((BYTE*)ci.pixels, CursorFormat, 0, 0, 0, ci.width, ci.height,
(BYTE*)xpointer->cursorPixels, CursorFormat, 0, 0, 0,
pointer->width, pointer->height))
{
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
return FALSE;
}
}
else
{
ci.pixels = xpointer->cursorPixels;
}
cursorIndex = xpointer->nCursors;
xpointer->cursorWidths[cursorIndex] = ci.width;
xpointer->cursorHeights[cursorIndex] = ci.height;
xpointer->cursors[cursorIndex] = XcursorImageLoadCursor(xfc->display, &ci);
xpointer->nCursors += 1;
if (xscale != 1 || yscale != 1)
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
}
cursor[0] = xpointer->cursors[cursorIndex];
#endif
return TRUE;
}
/* Pointer Class */
static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
{
#ifdef WITH_XCURSOR
UINT32 CursorFormat;
size_t size;
XcursorImage ci;
xfContext* xfc = (xfContext*)context;
xfPointer* xpointer = (xfPointer*)pointer;
@ -244,35 +360,25 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
else
CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_ARGB32;
xf_lock_x11(xfc);
ZeroMemory(&ci, sizeof(ci));
ci.version = XCURSOR_IMAGE_VERSION;
ci.size = sizeof(ci);
ci.width = pointer->width;
ci.height = pointer->height;
ci.xhot = pointer->xPos;
ci.yhot = pointer->yPos;
size = ci.height * ci.width * GetBytesPerPixel(CursorFormat);
xpointer->nCursors = 0;
xpointer->mCursors = 0;
if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16)))
{
xf_unlock_x11(xfc);
size = pointer->height * pointer->width * GetBytesPerPixel(CursorFormat);
if (!(xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16)))
return FALSE;
}
if (!freerdp_image_copy_from_pointer_data(
(BYTE*)ci.pixels, CursorFormat, 0, 0, 0, pointer->width, pointer->height,
(BYTE*)xpointer->cursorPixels, CursorFormat, 0, 0, 0, pointer->width, pointer->height,
pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData,
pointer->lengthAndMask, pointer->xorBpp, &context->gdi->palette))
{
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
_aligned_free(xpointer->cursorPixels);
return FALSE;
}
xpointer->cursor = XcursorImageLoadCursor(xfc->display, &ci);
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
if (!_xf_Pointer_GetCursorForCurrentScale(context, pointer, &(xpointer->cursor)))
return FALSE;
#endif
return TRUE;
}
@ -281,10 +387,22 @@ static void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
{
#ifdef WITH_XCURSOR
xfContext* xfc = (xfContext*)context;
xfPointer* xpointer = (xfPointer*)pointer;
xf_lock_x11(xfc);
if (((xfPointer*)pointer)->cursor)
XFreeCursor(xfc->display, ((xfPointer*)pointer)->cursor);
_aligned_free(xpointer->cursorPixels);
free(xpointer->cursorWidths);
free(xpointer->cursorHeights);
for (int i = 0; i < xpointer->nCursors; i++)
{
XFreeCursor(xfc->display, xpointer->cursors[i]);
}
free(xpointer->cursors);
xpointer->nCursors = 0;
xpointer->mCursors = 0;
xf_unlock_x11(xfc);
#endif
@ -294,15 +412,18 @@ static BOOL xf_Pointer_Set(rdpContext* context, const rdpPointer* pointer)
{
#ifdef WITH_XCURSOR
xfContext* xfc = (xfContext*)context;
xf_lock_x11(xfc);
xfc->pointer = (xfPointer*)pointer;
/* in RemoteApp mode, window can be null if none has had focus */
if (xfc->window)
{
if (!_xf_Pointer_GetCursorForCurrentScale(context, pointer, &(xfc->pointer->cursor)))
return FALSE;
xf_lock_x11(xfc);
XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
xf_unlock_x11(xfc);
xf_unlock_x11(xfc);
}
#endif
return TRUE;
}

View File

@ -28,6 +28,10 @@
typedef struct xf_context xfContext;
#ifdef WITH_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
#include <freerdp/api.h>
#include "xf_window.h"
@ -48,6 +52,14 @@ typedef struct xf_context xfContext;
#include <freerdp/codec/progressive.h>
#include <freerdp/codec/region.h>
#if !defined(XcursorUInt)
typedef unsigned int XcursorUInt;
#endif
#if !defined(XcursorPixel)
typedef XcursorUInt XcursorPixel;
#endif
struct xf_FullscreenMonitors
{
UINT32 top;
@ -69,6 +81,12 @@ typedef struct xf_WorkArea xfWorkArea;
struct xf_pointer
{
rdpPointer pointer;
XcursorPixel* cursorPixels;
UINT32 nCursors;
UINT32 mCursors;
UINT32* cursorWidths;
UINT32* cursorHeights;
Cursor* cursors;
Cursor cursor;
};
typedef struct xf_pointer xfPointer;