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;
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);
-
- if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16)))
- {
- xf_unlock_x11(xfc);
+ xpointer->nCursors = 0;
+ xpointer->mCursors = 0;
+
+ 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;
}
{
#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
{
#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;
}