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>
40[[nodiscard]]
static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer)
42 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
44 WINPR_ASSERT(context);
48 rdpGdi* gdi = context->gdi;
51 ptr->size = 4ull * pointer->width * pointer->height;
52 ptr->data = winpr_aligned_malloc(ptr->size, 16);
57 auto data =
static_cast<BYTE*
>(ptr->data);
58 if (!freerdp_image_copy_from_pointer_data(
59 data, gdi->dstFormat, 0, 0, 0, pointer->width, pointer->height, pointer->xorMaskData,
60 pointer->lengthXorMask, pointer->andMaskData, pointer->lengthAndMask, pointer->xorBpp,
61 &context->gdi->palette))
63 winpr_aligned_free(ptr->data);
71static void sdl_Pointer_Clear(sdlPointer* ptr)
74 SDL_DestroyCursor(ptr->cursor);
75 SDL_DestroySurface(ptr->image);
76 ptr->cursor =
nullptr;
80static void sdl_Pointer_Free(rdpContext* context, rdpPointer* pointer)
82 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
83 WINPR_UNUSED(context);
87 sdl_Pointer_Clear(ptr);
88 winpr_aligned_free(ptr->data);
93[[nodiscard]]
static BOOL sdl_Pointer_SetDefault(rdpContext* context)
95 WINPR_UNUSED(context);
97 return sdl_push_user_event(SDL_EVENT_USER_POINTER_DEFAULT);
100[[nodiscard]]
static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer)
102 WINPR_UNUSED(context);
103 return sdl_push_user_event(SDL_EVENT_USER_POINTER_SET, pointer);
110 auto context = sdl->context();
111 auto pointer = sdl->cursor();
112 auto ptr =
reinterpret_cast<sdlPointer*
>(pointer);
116 rdpGdi* gdi = context->gdi;
119 auto ix =
static_cast<float>(pointer->xPos);
120 auto iy =
static_cast<float>(pointer->yPos);
121 auto isw =
static_cast<float>(pointer->width);
122 auto ish =
static_cast<float>(pointer->height);
124 auto window = SDL_GetMouseFocus();
126 return sdl_Pointer_SetDefault(context);
128 const Uint32
id = SDL_GetWindowID(window);
130 const SDL_FRect orig{ ix, iy, isw, ish };
131 auto pos = sdl->pixelToScreen(
id, orig);
132 WLog_Print(sdl->getWLog(), WLOG_DEBUG,
"cursor scale: pixel:%s, display:%s",
133 sdl::utils::toString(orig).c_str(), sdl::utils::toString(pos).c_str());
135 sdl_Pointer_Clear(ptr);
138 SDL_CreateSurface(
static_cast<int>(orig.w),
static_cast<int>(orig.h), sdl->pixelFormat());
141 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_CreateSurface failed");
145 if (!SDL_LockSurface(ptr->image))
147 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_LockSurface failed");
151 auto pixels =
static_cast<BYTE*
>(ptr->image->pixels);
152 auto data =
static_cast<const BYTE*
>(ptr->data);
153 const BOOL rc = freerdp_image_scale(
154 pixels, gdi->dstFormat,
static_cast<UINT32
>(ptr->image->pitch), 0, 0,
155 static_cast<UINT32
>(ptr->image->w),
static_cast<UINT32
>(ptr->image->h), data,
156 gdi->dstFormat, 0, 0, 0,
static_cast<UINT32
>(isw),
static_cast<UINT32
>(ish));
157 SDL_UnlockSurface(ptr->image);
160 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"freerdp_image_scale failed");
166 auto fw = sdl->getFirstWindow();
169 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"sdl->getFirstWindow() nullptr");
173 const auto hidpi_scale =
174 sdl->pixelToScreen(fw->id(), SDL_FPoint{ static_cast<float>(ptr->image->w),
175 static_cast<float>(ptr->image->h) });
176 std::unique_ptr<SDL_Surface, void (*)(SDL_Surface*)> normal{
177 SDL_CreateSurface(
static_cast<int>(hidpi_scale.x),
static_cast<int>(hidpi_scale.y),
182 if (!SDL_BlitSurfaceScaled(ptr->image,
nullptr, normal.get(),
nullptr,
183 SDL_ScaleMode::SDL_SCALEMODE_LINEAR))
185 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_BlitSurfaceScaled failed");
188 if (!SDL_AddSurfaceAlternateImage(normal.get(), ptr->image))
190 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_AddSurfaceAlternateImage failed");
195 SDL_CreateColorCursor(normal.get(),
static_cast<int>(pos.x),
static_cast<int>(pos.y));
198 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_CreateColorCursor(display:%s, pixel:%s} failed",
199 sdl::utils::toString(pos).c_str(), sdl::utils::toString(orig).c_str());
203 if (!SDL_SetCursor(ptr->cursor))
205 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_SetCursor failed");
208 if (!SDL_ShowCursor())
210 WLog_Print(sdl->getWLog(), WLOG_ERROR,
"SDL_ShowCursor failed");
213 sdl->setHasCursor(
true);
217[[nodiscard]]
static BOOL sdl_Pointer_SetNull(rdpContext* context)
219 WINPR_UNUSED(context);
221 return sdl_push_user_event(SDL_EVENT_USER_POINTER_NULL);
224[[nodiscard]]
static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
226 WINPR_UNUSED(context);
227 WINPR_ASSERT(context);
229 return sdl_push_user_event(SDL_EVENT_USER_POINTER_POSITION, x, y);
232bool sdl_register_pointer(rdpGraphics* graphics)
234 const rdpPointer pointer = {
sizeof(sdlPointer),
239 sdl_Pointer_SetDefault,
240 sdl_Pointer_SetPosition,
252 graphics_register_pointer(graphics, &pointer);