22#include <freerdp/config.h>
24#include <freerdp/gdi/gdi.h>
26#include "sdl_pointer.hpp"
27#include "sdl_context.hpp"
28#include "sdl_touch.hpp"
29#include "sdl_utils.hpp"
31#include <SDL3/SDL_mouse.h>
36 SDL_Cursor* cursor =
nullptr;
37 SDL_Surface* image =
nullptr;
41 sdlPointer(
const sdlPointer& other) =
delete;
42 sdlPointer(sdlPointer&& other) =
delete;
43 auto operator=(
const sdlPointer& other) =
delete;
44 auto operator=(sdlPointer&& other) =
delete;
45 ~sdlPointer() =
delete;
47 bool update(rdpContext* context)
52 size = 4ull * pointer.width * pointer.height;
53 winpr_aligned_free(data);
54 data =
static_cast<BYTE*
>(winpr_aligned_malloc(size, 16));
59 return freerdp_image_copy_from_pointer_data(
60 data, context->gdi->dstFormat, 0, 0, 0, pointer.width, pointer.height,
61 pointer.xorMaskData, pointer.lengthXorMask, pointer.andMaskData, pointer.lengthAndMask,
62 pointer.xorBpp, &context->gdi->palette);
66[[nodiscard]]
static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer)
68 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
69 auto sdl = get_context(context);
72 std::unique_lock lock(
sdl->lock());
75 sdl->pointers().push_back(pointer);
77 return ptr->update(context);
80static void sdl_Pointer_Clear(sdlPointer* ptr)
83 SDL_DestroyCursor(ptr->cursor);
84 SDL_DestroySurface(ptr->image);
85 ptr->cursor =
nullptr;
89static void sdl_Pointer_Free(WINPR_ATTR_UNUSED rdpContext* context, rdpPointer* pointer)
91 auto sdl = get_context(context);
94 std::unique_lock lock(
sdl->lock());
95 auto it = std::remove(
sdl->pointers().begin(),
sdl->pointers().end(), pointer);
96 sdl->pointers().erase(it,
sdl->pointers().end());
98 sdl_Pointer_FreeCopy(pointer);
101void sdl_Pointer_FreeCopy(rdpPointer* pointer)
103 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
108 sdl_Pointer_Clear(ptr);
109 winpr_aligned_free(ptr->data);
113[[nodiscard]]
static BOOL sdl_Pointer_SetDefault(rdpContext* context)
115 WINPR_UNUSED(context);
117 return sdl_push_user_event(SDL_EVENT_USER_POINTER_DEFAULT);
120[[nodiscard]]
static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer)
122 WINPR_UNUSED(context);
123 return sdl_push_user_event(SDL_EVENT_USER_POINTER_SET, pointer);
130 std::unique_lock lock(
sdl->lock());
131 auto context =
sdl->context();
132 auto pointer =
sdl->cursor();
133 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
137 rdpGdi* gdi = context->gdi;
140 auto ix =
static_cast<float>(pointer->xPos);
141 auto iy =
static_cast<float>(pointer->yPos);
142 auto isw =
static_cast<float>(pointer->width);
143 auto ish =
static_cast<float>(pointer->height);
145 auto window = SDL_GetMouseFocus();
147 return sdl_Pointer_SetDefault(context);
149 const Uint32
id = SDL_GetWindowID(window);
151 const SDL_FRect orig{ ix, iy, isw, ish };
152 const auto pos =
sdl->pixelToScreen(
id, orig,
true);
153 WLog_Print(
sdl->getWLog(), WLOG_DEBUG,
"cursor scale: pixel:%s, display:%s",
154 sdl::utils::toString(orig).c_str(), sdl::utils::toString(pos).c_str());
156 sdl_Pointer_Clear(ptr);
159 SDL_CreateSurface(
static_cast<int>(orig.w),
static_cast<int>(orig.h),
sdl->pixelFormat());
162 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_CreateSurface failed");
166 auto data =
static_cast<const BYTE*
>(ptr->data);
169 if (!SDL_LockSurface(ptr->image))
171 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_LockSurface failed");
175 auto pixels =
static_cast<BYTE*
>(ptr->image->pixels);
176 const BOOL rc = freerdp_image_scale(
177 pixels, gdi->dstFormat,
static_cast<UINT32
>(ptr->image->pitch), 0, 0,
178 static_cast<UINT32
>(ptr->image->w),
static_cast<UINT32
>(ptr->image->h), data,
179 gdi->dstFormat, 0, 0, 0,
static_cast<UINT32
>(isw),
static_cast<UINT32
>(ish));
180 SDL_UnlockSurface(ptr->image);
183 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"freerdp_image_scale failed");
190 auto fw =
sdl->getFirstWindow();
193 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"sdl->getFirstWindow() nullptr");
197 const auto w =
static_cast<int>(pos.w);
198 const auto h =
static_cast<int>(pos.h);
199 std::unique_ptr<SDL_Surface, void (*)(SDL_Surface*)> normal{
200 SDL_CreateSurface(w, h, ptr->image->format), SDL_DestroySurface
203 if (!SDL_BlitSurfaceScaled(ptr->image,
nullptr, normal.get(),
nullptr,
204 SDL_ScaleMode::SDL_SCALEMODE_LINEAR))
206 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_BlitSurfaceScaled failed");
209 if (!SDL_AddSurfaceAlternateImage(normal.get(), ptr->image))
211 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_AddSurfaceAlternateImage failed");
215 auto x =
static_cast<int>(pos.x);
216 auto y =
static_cast<int>(pos.y);
222 ptr->cursor = SDL_CreateColorCursor(normal.get(), x, y);
225 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_CreateColorCursor(display:%s, pixel:%s} failed",
226 sdl::utils::toString(pos).c_str(), sdl::utils::toString(orig).c_str());
230 if (!SDL_SetCursor(ptr->cursor))
232 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_SetCursor failed");
235 if (!SDL_ShowCursor())
237 WLog_Print(
sdl->getWLog(), WLOG_ERROR,
"SDL_ShowCursor failed");
240 sdl->setHasCursor(
true);
244[[nodiscard]]
static BOOL sdl_Pointer_SetNull(rdpContext* context)
246 WINPR_UNUSED(context);
248 return sdl_push_user_event(SDL_EVENT_USER_POINTER_NULL);
251[[nodiscard]]
static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
253 WINPR_UNUSED(context);
254 WINPR_ASSERT(context);
256 return sdl_push_user_event(SDL_EVENT_USER_POINTER_POSITION, x, y);
259bool sdl_register_pointer(rdpGraphics* graphics)
261 const rdpPointer pointer = {
sizeof(sdlPointer),
266 sdl_Pointer_SetDefault,
267 sdl_Pointer_SetPosition,
279 graphics_register_pointer(graphics, &pointer);
283rdpPointer* sdl_Pointer_Copy(
const rdpPointer* pointer)
285 auto ptr =
reinterpret_cast<const sdlPointer*
>(pointer);
289 auto copy =
static_cast<sdlPointer*
>(calloc(1,
sizeof(sdlPointer)));
293 copy->pointer.xPos = pointer->xPos;
294 copy->pointer.yPos = pointer->yPos;
295 copy->pointer.width = pointer->width;
296 copy->pointer.height = pointer->height;
297 copy->pointer.xorBpp = pointer->xorBpp;
300 copy->data =
static_cast<BYTE*
>(winpr_aligned_malloc(ptr->size, 32));
306 copy->size = ptr->size;
307 memcpy(copy->data, ptr->data, copy->size);
309 return ©->pointer;