20#include <freerdp/config.h>
22#include <freerdp/gdi/gdi.h>
24#include "sdl_pointer.hpp"
25#include "sdl_context.hpp"
26#include "sdl_touch.hpp"
27#include "sdl_utils.hpp"
29#include <SDL3/SDL_mouse.h>
34 SDL_Cursor* cursor =
nullptr;
35 SDL_Surface* image =
nullptr;
39 sdlPointer(
const sdlPointer& other) =
delete;
40 sdlPointer(sdlPointer&& other) =
delete;
41 auto operator=(
const sdlPointer& other) =
delete;
42 auto operator=(sdlPointer&& other) =
delete;
43 ~sdlPointer() =
delete;
45 bool update(rdpContext* context)
50 size = 4ull * pointer.width * pointer.height;
51 winpr_aligned_free(data);
52 data =
static_cast<BYTE*
>(winpr_aligned_malloc(size, 16));
57 return freerdp_image_copy_from_pointer_data(
58 data, context->gdi->dstFormat, 0, 0, 0, pointer.width, pointer.height,
59 pointer.xorMaskData, pointer.lengthXorMask, pointer.andMaskData, pointer.lengthAndMask,
60 pointer.xorBpp, &context->gdi->palette);
64[[nodiscard]]
static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer)
66 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
68 WINPR_ASSERT(context);
72 return ptr->update(context);
75static void sdl_Pointer_Clear(sdlPointer* ptr)
78 SDL_DestroyCursor(ptr->cursor);
79 SDL_DestroySurface(ptr->image);
80 ptr->cursor =
nullptr;
84static void sdl_Pointer_Free(WINPR_ATTR_UNUSED rdpContext* context, rdpPointer* pointer)
86 sdl_Pointer_FreeCopy(pointer);
89void sdl_Pointer_FreeCopy(rdpPointer* pointer)
91 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
96 sdl_Pointer_Clear(ptr);
97 winpr_aligned_free(ptr->data);
101[[nodiscard]]
static BOOL sdl_Pointer_SetDefault(rdpContext* context)
103 WINPR_UNUSED(context);
105 return sdl_push_user_event(SDL_EVENT_USER_POINTER_DEFAULT);
108[[nodiscard]]
static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer)
110 WINPR_UNUSED(context);
111 return sdl_push_user_event(SDL_EVENT_USER_POINTER_SET, pointer);
118 auto context = sdl->context();
119 auto pointer = sdl->cursor();
120 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
124 rdpGdi* gdi = context->gdi;
127 auto ix =
static_cast<float>(pointer->xPos);
128 auto iy =
static_cast<float>(pointer->yPos);
129 auto isw =
static_cast<float>(pointer->width);
130 auto ish =
static_cast<float>(pointer->height);
132 auto window = SDL_GetMouseFocus();
134 return sdl_Pointer_SetDefault(context);
136 const Uint32
id = SDL_GetWindowID(window);
138 const SDL_FRect orig{ ix, iy, isw, ish };
139 auto pos = sdl->pixelToScreen(
id, orig);
140 WLog_Print(sdl->getWLog(), WLOG_DEBUG,
"cursor scale: pixel:%s, display:%s",
141 sdl::utils::toString(orig).c_str(), sdl::utils::toString(pos).c_str());
143 sdl_Pointer_Clear(ptr);
146 SDL_CreateSurface(
static_cast<int>(orig.w),
static_cast<int>(orig.h), sdl->pixelFormat());
149 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_CreateSurface failed");
153 auto data =
static_cast<const BYTE*
>(ptr->data);
156 if (!SDL_LockSurface(ptr->image))
158 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_LockSurface failed");
162 auto pixels =
static_cast<BYTE*
>(ptr->image->pixels);
163 const BOOL rc = freerdp_image_scale(
164 pixels, gdi->dstFormat,
static_cast<UINT32
>(ptr->image->pitch), 0, 0,
165 static_cast<UINT32
>(ptr->image->w),
static_cast<UINT32
>(ptr->image->h), data,
166 gdi->dstFormat, 0, 0, 0,
static_cast<UINT32
>(isw),
static_cast<UINT32
>(ish));
167 SDL_UnlockSurface(ptr->image);
170 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"freerdp_image_scale failed");
177 auto fw = sdl->getFirstWindow();
180 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"sdl->getFirstWindow() nullptr");
184 const auto hidpi_scale =
185 sdl->pixelToScreen(fw->id(), SDL_FPoint{ static_cast<float>(ptr->image->w),
186 static_cast<float>(ptr->image->h) });
187 std::unique_ptr<SDL_Surface, void (*)(SDL_Surface*)> normal{
188 SDL_CreateSurface(
static_cast<int>(hidpi_scale.x),
static_cast<int>(hidpi_scale.y),
193 if (!SDL_BlitSurfaceScaled(ptr->image,
nullptr, normal.get(),
nullptr,
194 SDL_ScaleMode::SDL_SCALEMODE_LINEAR))
196 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_BlitSurfaceScaled failed");
199 if (!SDL_AddSurfaceAlternateImage(normal.get(), ptr->image))
201 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_AddSurfaceAlternateImage failed");
206 SDL_CreateColorCursor(normal.get(),
static_cast<int>(pos.x),
static_cast<int>(pos.y));
209 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_CreateColorCursor(display:%s, pixel:%s} failed",
210 sdl::utils::toString(pos).c_str(), sdl::utils::toString(orig).c_str());
214 if (!SDL_SetCursor(ptr->cursor))
216 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_SetCursor failed");
219 if (!SDL_ShowCursor())
221 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_ShowCursor failed");
224 sdl->setHasCursor(
true);
228[[nodiscard]]
static BOOL sdl_Pointer_SetNull(rdpContext* context)
230 WINPR_UNUSED(context);
232 return sdl_push_user_event(SDL_EVENT_USER_POINTER_NULL);
235[[nodiscard]]
static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
237 WINPR_UNUSED(context);
238 WINPR_ASSERT(context);
240 return sdl_push_user_event(SDL_EVENT_USER_POINTER_POSITION, x, y);
243bool sdl_register_pointer(rdpGraphics* graphics)
245 const rdpPointer pointer = {
sizeof(sdlPointer),
250 sdl_Pointer_SetDefault,
251 sdl_Pointer_SetPosition,
263 graphics_register_pointer(graphics, &pointer);
267rdpPointer* sdl_Pointer_Copy(
const rdpPointer* pointer)
269 auto ptr =
reinterpret_cast<const sdlPointer*
>(pointer);
273 auto copy =
static_cast<sdlPointer*
>(calloc(1,
sizeof(sdlPointer)));
277 copy->pointer.xPos = pointer->xPos;
278 copy->pointer.yPos = pointer->yPos;
279 copy->pointer.width = pointer->width;
280 copy->pointer.height = pointer->height;
281 copy->pointer.xorBpp = pointer->xorBpp;
284 copy->data =
static_cast<BYTE*
>(winpr_aligned_malloc(ptr->size, 32));
290 copy->size = ptr->size;
291 memcpy(copy->data, ptr->data, copy->size);
293 return ©->pointer;