20#include <freerdp/config.h> 
   22#include <freerdp/gdi/gdi.h> 
   24#include "sdl_pointer.hpp" 
   25#include "sdl_freerdp.hpp" 
   26#include "sdl_touch.hpp" 
   27#include "sdl_utils.hpp" 
   29#include <SDL3/SDL_mouse.h> 
   40static 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);
 
   70static void sdl_Pointer_Clear(sdlPointer* ptr)
 
   73  SDL_DestroyCursor(ptr->cursor);
 
   74  SDL_DestroySurface(ptr->image);
 
   75  ptr->cursor = 
nullptr;
 
   79static void sdl_Pointer_Free(rdpContext* context, rdpPointer* pointer)
 
   81  auto ptr = 
reinterpret_cast<sdlPointer*
>(pointer);
 
   82  WINPR_UNUSED(context);
 
   86    sdl_Pointer_Clear(ptr);
 
   87    winpr_aligned_free(ptr->data);
 
   92static BOOL sdl_Pointer_SetDefault(rdpContext* context)
 
   94  WINPR_UNUSED(context);
 
   96  return sdl_push_user_event(SDL_EVENT_USER_POINTER_DEFAULT);
 
   99static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer)
 
  101  WINPR_UNUSED(context);
 
  102  return sdl_push_user_event(SDL_EVENT_USER_POINTER_SET, pointer);
 
  112  auto context = sdl->context();
 
  113  auto pointer = sdl->cursor();
 
  114  auto ptr = 
reinterpret_cast<sdlPointer*
>(pointer);
 
  118  rdpGdi* gdi = context->gdi;
 
  121  auto x = 
static_cast<INT32
>(pointer->xPos);
 
  122  auto y = 
static_cast<INT32
>(pointer->yPos);
 
  123  auto sw = w = 
static_cast<INT32
>(pointer->width);
 
  124  auto sh = h = 
static_cast<INT32
>(pointer->height);
 
  126  SDL_Window* window = SDL_GetMouseFocus();
 
  128    return sdl_Pointer_SetDefault(context);
 
  130  const Uint32 
id = SDL_GetWindowID(window);
 
  132  if (!sdl_scale_coordinates(sdl, 
id, &x, &y, FALSE, FALSE) ||
 
  133      !sdl_scale_coordinates(sdl, 
id, &sw, &sh, FALSE, FALSE))
 
  136  sdl_Pointer_Clear(ptr);
 
  138  ptr->image = SDL_CreateSurface(sw, sh, sdl->sdl_pixel_format);
 
  142  SDL_LockSurface(ptr->image);
 
  143  auto pixels = 
static_cast<BYTE*
>(ptr->image->pixels);
 
  144  auto data = 
static_cast<const BYTE*
>(ptr->data);
 
  145  const BOOL rc = freerdp_image_scale(
 
  146      pixels, gdi->dstFormat, 
static_cast<UINT32
>(ptr->image->pitch), 0, 0,
 
  147      static_cast<UINT32
>(ptr->image->w), 
static_cast<UINT32
>(ptr->image->h), data,
 
  148      gdi->dstFormat, 0, 0, 0, 
static_cast<UINT32
>(w), 
static_cast<UINT32
>(h));
 
  149  SDL_UnlockSurface(ptr->image);
 
  155  auto it = sdl->windows.begin();
 
  156  if (it == sdl->windows.end())
 
  159  const auto hidpi_scale = SDL_GetWindowDisplayScale(it->second.window());
 
  160  auto normal = SDL_CreateSurface(
 
  161      static_cast<int>(
static_cast<float>(ptr->image->w) / hidpi_scale),
 
  162      static_cast<int>(
static_cast<float>(ptr->image->h) / hidpi_scale), ptr->image->format);
 
  164  SDL_BlitSurfaceScaled(ptr->image, 
nullptr, normal, 
nullptr,
 
  165                        SDL_ScaleMode::SDL_SCALEMODE_LINEAR);
 
  166  SDL_AddSurfaceAlternateImage(normal, ptr->image);
 
  168  ptr->cursor = SDL_CreateColorCursor(normal, x, y);
 
  172  SDL_DestroySurface(normal);
 
  174  SDL_SetCursor(ptr->cursor);
 
  176  sdl->setHasCursor(
true);
 
  180static BOOL sdl_Pointer_SetNull(rdpContext* context)
 
  182  WINPR_UNUSED(context);
 
  184  return sdl_push_user_event(SDL_EVENT_USER_POINTER_NULL);
 
  187static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
 
  189  WINPR_UNUSED(context);
 
  190  WINPR_ASSERT(context);
 
  192  return sdl_push_user_event(SDL_EVENT_USER_POINTER_POSITION, x, y);
 
  195BOOL sdl_register_pointer(rdpGraphics* graphics)
 
  197  const rdpPointer pointer = { 
sizeof(sdlPointer),
 
  202                             sdl_Pointer_SetDefault,
 
  203                             sdl_Pointer_SetPosition,
 
  215  graphics_register_pointer(graphics, &pointer);