FreeRDP
Loading...
Searching...
No Matches
SDL2/sdl_pointer.cpp
1
20#include <freerdp/config.h>
21
22#include <freerdp/gdi/gdi.h>
23
24#include "sdl_pointer.hpp"
25#include "sdl_freerdp.hpp"
26#include "sdl_touch.hpp"
27#include "sdl_utils.hpp"
28
29#include <SDL_mouse.h>
30
31using sdlPointer = struct
32{
33 rdpPointer pointer;
34 SDL_Cursor* cursor;
35 SDL_Surface* image;
36 size_t size;
37 void* data;
38};
39
40static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer)
41{
42 auto ptr = reinterpret_cast<sdlPointer*>(pointer);
43
44 WINPR_ASSERT(context);
45 if (!ptr)
46 return FALSE;
47
48 rdpGdi* gdi = context->gdi;
49 WINPR_ASSERT(gdi);
50
51 ptr->size = 4ull * pointer->width * pointer->height;
52 ptr->data = winpr_aligned_malloc(ptr->size, 16);
53
54 if (!ptr->data)
55 return FALSE;
56
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))
62 {
63 winpr_aligned_free(ptr->data);
64 ptr->data = nullptr;
65 return FALSE;
66 }
67
68 return TRUE;
69}
70
71static void sdl_Pointer_Clear(sdlPointer* ptr)
72{
73 WINPR_ASSERT(ptr);
74 SDL_FreeCursor(ptr->cursor);
75 SDL_FreeSurface(ptr->image);
76 ptr->cursor = nullptr;
77 ptr->image = nullptr;
78}
79
80static void sdl_Pointer_Free(rdpContext* context, rdpPointer* pointer)
81{
82 auto ptr = reinterpret_cast<sdlPointer*>(pointer);
83 WINPR_UNUSED(context);
84
85 if (ptr)
86 {
87 sdl_Pointer_Clear(ptr);
88 winpr_aligned_free(ptr->data);
89 ptr->data = nullptr;
90 }
91}
92
93static BOOL sdl_Pointer_SetDefault(rdpContext* context)
94{
95 WINPR_UNUSED(context);
96
97 return sdl_push_user_event(SDL_USEREVENT_POINTER_DEFAULT);
98}
99
100static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer)
101{
102 auto sdl = get_context(context);
103
104 return sdl_push_user_event(SDL_USEREVENT_POINTER_SET, pointer, sdl);
105}
106
107BOOL sdl_Pointer_Set_Process(SDL_UserEvent* uptr)
108{
109 INT32 w = 0;
110 INT32 h = 0;
111 INT32 x = 0;
112 INT32 y = 0;
113 INT32 sw = 0;
114 INT32 sh = 0;
115
116 WINPR_ASSERT(uptr);
117
118 auto sdl = static_cast<SdlContext*>(uptr->data2);
119 WINPR_ASSERT(sdl);
120
121 auto context = sdl->context();
122 auto ptr = static_cast<sdlPointer*>(uptr->data1);
123 WINPR_ASSERT(ptr);
124
125 rdpPointer* pointer = &ptr->pointer;
126
127 rdpGdi* gdi = context->gdi;
128 WINPR_ASSERT(gdi);
129
130 x = static_cast<INT32>(pointer->xPos);
131 y = static_cast<INT32>(pointer->yPos);
132 sw = w = static_cast<INT32>(pointer->width);
133 sh = h = static_cast<INT32>(pointer->height);
134
135 SDL_Window* window = SDL_GetMouseFocus();
136 if (!window)
137 return sdl_Pointer_SetDefault(context);
138
139 const Uint32 id = SDL_GetWindowID(window);
140
141 if (!sdl_scale_coordinates(sdl, id, &x, &y, FALSE, FALSE) ||
142 !sdl_scale_coordinates(sdl, id, &sw, &sh, FALSE, FALSE))
143 return FALSE;
144
145 sdl_Pointer_Clear(ptr);
146
147 const DWORD bpp = FreeRDPGetBitsPerPixel(gdi->dstFormat);
148 ptr->image =
149 SDL_CreateRGBSurfaceWithFormat(0, sw, sh, static_cast<int>(bpp), sdl->sdl_pixel_format);
150 if (!ptr->image)
151 return FALSE;
152
153 SDL_LockSurface(ptr->image);
154 auto pixels = static_cast<BYTE*>(ptr->image->pixels);
155 auto data = static_cast<const BYTE*>(ptr->data);
156 const BOOL rc = freerdp_image_scale(
157 pixels, gdi->dstFormat, static_cast<UINT32>(ptr->image->pitch), 0, 0,
158 static_cast<UINT32>(ptr->image->w), static_cast<UINT32>(ptr->image->h), data,
159 gdi->dstFormat, 0, 0, 0, static_cast<UINT32>(w), static_cast<UINT32>(h));
160 SDL_UnlockSurface(ptr->image);
161 if (!rc)
162 return FALSE;
163
164 ptr->cursor = SDL_CreateColorCursor(ptr->image, x, y);
165 if (!ptr->cursor)
166 return FALSE;
167
168 SDL_SetCursor(ptr->cursor);
169 SDL_ShowCursor(SDL_ENABLE);
170 return TRUE;
171}
172
173static BOOL sdl_Pointer_SetNull(rdpContext* context)
174{
175 WINPR_UNUSED(context);
176
177 return sdl_push_user_event(SDL_USEREVENT_POINTER_NULL);
178}
179
180static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
181{
182 WINPR_UNUSED(context);
183 WINPR_ASSERT(context);
184
185 return sdl_push_user_event(SDL_USEREVENT_POINTER_POSITION, x, y);
186}
187
188BOOL sdl_register_pointer(rdpGraphics* graphics)
189{
190 const rdpPointer pointer = { sizeof(sdlPointer),
191 sdl_Pointer_New,
192 sdl_Pointer_Free,
193 sdl_Pointer_Set,
194 sdl_Pointer_SetNull,
195 sdl_Pointer_SetDefault,
196 sdl_Pointer_SetPosition,
197 {},
198 0,
199 0,
200 0,
201 0,
202 0,
203 0,
204 0,
205 nullptr,
206 nullptr,
207 {} };
208 graphics_register_pointer(graphics, &pointer);
209 return TRUE;
210}