FreeRDP
Loading...
Searching...
No Matches
wlfreerdp.c
1
22#include <math.h>
23#include <stdio.h>
24#include <errno.h>
25#include <locale.h>
26#include <float.h>
27
28#include <winpr/sysinfo.h>
29#include <winpr/cast.h>
30
31#include <freerdp/client/cmdline.h>
32#include <freerdp/channels/channels.h>
33#include <freerdp/gdi/gdi.h>
34#include <freerdp/client.h>
35#include <freerdp/utils/signal.h>
36#include <freerdp/locale/keyboard.h>
37#include <freerdp/client/aad_helper.h>
38
39#include <linux/input.h>
40
41#include <uwac/uwac.h>
42
43#include "wlfreerdp.h"
44#include "wlf_input.h"
45#include "wlf_cliprdr.h"
46#include "wlf_disp.h"
47#include "wlf_channels.h"
48#include "wlf_pointer.h"
49
50#define TAG CLIENT_TAG("wayland")
51
52static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw, INT32 ih)
53{
54 BOOL res = FALSE;
55 rdpGdi* gdi = nullptr;
56 char* data = nullptr;
57 UwacSize geometry = WINPR_C_ARRAY_INIT;
58 size_t stride = 0;
59 UwacReturnCode rc = UWAC_ERROR_INTERNAL;
60 RECTANGLE_16 area = WINPR_C_ARRAY_INIT;
61
62 if (!context_w)
63 return FALSE;
64
65 if ((ix < 0) || (iy < 0) || (iw < 0) || (ih < 0))
66 return FALSE;
67
68 EnterCriticalSection(&context_w->critical);
69 UINT32 x = WINPR_ASSERTING_INT_CAST(UINT16, ix);
70 UINT32 y = WINPR_ASSERTING_INT_CAST(UINT16, iy);
71 UINT32 w = WINPR_ASSERTING_INT_CAST(UINT16, iw);
72 UINT32 h = WINPR_ASSERTING_INT_CAST(UINT16, ih);
73 rc = UwacWindowGetDrawingBufferGeometry(context_w->window, &geometry, &stride);
74 data = UwacWindowGetDrawingBuffer(context_w->window);
75
76 if (!data || (rc != UWAC_SUCCESS))
77 goto fail;
78
79 gdi = context_w->common.context.gdi;
80
81 if (!gdi)
82 goto fail;
83
84 /* Ignore output if the surface size does not match. */
85 if (((INT64)x > geometry.width) || ((INT64)y > geometry.height))
86 {
87 res = TRUE;
88 goto fail;
89 }
90
91 area.left = WINPR_ASSERTING_INT_CAST(UINT16, x);
92 area.top = WINPR_ASSERTING_INT_CAST(UINT16, y);
93 area.right = WINPR_ASSERTING_INT_CAST(UINT16, x + w);
94 area.bottom = WINPR_ASSERTING_INT_CAST(UINT16, y + h);
95
96 if (!wlf_copy_image(
97 gdi->primary_buffer, gdi->stride, WINPR_ASSERTING_INT_CAST(size_t, gdi->width),
98 WINPR_ASSERTING_INT_CAST(size_t, gdi->height), data, stride,
99 WINPR_ASSERTING_INT_CAST(size_t, geometry.width),
100 WINPR_ASSERTING_INT_CAST(size_t, geometry.height), &area,
101 freerdp_settings_get_bool(context_w->common.context.settings, FreeRDP_SmartSizing)))
102 goto fail;
103
104 if (!wlf_scale_coordinates(&context_w->common.context, &x, &y, FALSE))
105 goto fail;
106
107 if (!wlf_scale_coordinates(&context_w->common.context, &w, &h, FALSE))
108 goto fail;
109
110 if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS)
111 goto fail;
112
113 if (UwacWindowSubmitBuffer(context_w->window, false) != UWAC_SUCCESS)
114 goto fail;
115
116 res = TRUE;
117fail:
118 LeaveCriticalSection(&context_w->critical);
119 return res;
120}
121
122static BOOL wl_end_paint(rdpContext* context)
123{
124 if (!context || !context->gdi || !context->gdi->primary)
125 return FALSE;
126
127 rdpGdi* gdi = context->gdi;
128 HGDI_DC hdc = gdi->primary->hdc;
129 WINPR_ASSERT(hdc);
130 if (!hdc->hwnd)
131 return TRUE;
132
133 HGDI_WND hwnd = hdc->hwnd;
134 WINPR_ASSERT(hwnd->invalid || (hwnd->ninvalid == 0));
135
136 if (hwnd->invalid->null)
137 return TRUE;
138
139 const INT32 x = hwnd->invalid->x;
140 const INT32 y = hwnd->invalid->y;
141 const INT32 w = hwnd->invalid->w;
142 const INT32 h = hwnd->invalid->h;
143 wlfContext* context_w = (wlfContext*)context;
144 if (!wl_update_buffer(context_w, x, y, w, h))
145 {
146 return FALSE;
147 }
148
149 hwnd->invalid->null = TRUE;
150 hwnd->ninvalid = 0;
151 return TRUE;
152}
153
154static BOOL wl_refresh_display(wlfContext* context)
155{
156 rdpGdi* gdi = nullptr;
157
158 if (!context || !context->common.context.gdi)
159 return FALSE;
160
161 gdi = context->common.context.gdi;
162 return wl_update_buffer(context, 0, 0, gdi->width, gdi->height);
163}
164
165static BOOL wl_resize_display(rdpContext* context)
166{
167 wlfContext* wlc = (wlfContext*)context;
168 rdpGdi* gdi = context->gdi;
169 rdpSettings* settings = context->settings;
170
171 if (!gdi_resize(gdi, freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
172 freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)))
173 return FALSE;
174
175 return wl_refresh_display(wlc);
176}
177
178static BOOL wl_pre_connect(freerdp* instance)
179{
180 rdpSettings* settings = nullptr;
181 wlfContext* context = nullptr;
182 const UwacOutput* output = nullptr;
183 UwacSize resolution;
184
185 if (!instance)
186 return FALSE;
187
188 context = (wlfContext*)instance->context;
189 WINPR_ASSERT(context);
190
191 settings = instance->context->settings;
192 WINPR_ASSERT(settings);
193
194 if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE))
195 return FALSE;
196
197 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
198 return FALSE;
199 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_WAYLAND))
200 return FALSE;
201 if (PubSub_SubscribeChannelConnected(instance->context->pubSub,
202 wlf_OnChannelConnectedEventHandler) < 0)
203 return FALSE;
204 if (PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
205 wlf_OnChannelDisconnectedEventHandler) < 0)
206 return FALSE;
207
208 if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
209 {
210 // Use the resolution of the first display output
211 output = UwacDisplayGetOutput(context->display, 0);
212
213 if ((output != nullptr) && (UwacOutputGetResolution(output, &resolution) == UWAC_SUCCESS))
214 {
215 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
216 (UINT32)resolution.width))
217 return FALSE;
218 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
219 (UINT32)resolution.height))
220 return FALSE;
221 }
222 else
223 {
224 WLog_WARN(TAG, "Failed to get output resolution! Check your display settings");
225 }
226 }
227
228 return TRUE;
229}
230
231static BOOL wl_post_connect(freerdp* instance)
232{
233 if (!instance || !instance->context)
234 return FALSE;
235
236 wlfContext* context = (wlfContext*)instance->context;
237 WINPR_ASSERT(context);
238
239 rdpSettings* settings = instance->context->settings;
240 WINPR_ASSERT(settings);
241
242 const char* title = "FreeRDP";
243 const char* wtitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
244 if (wtitle)
245 title = wtitle;
246
247 const char* app_id = "wlfreerdp";
248 const char* wmclass = freerdp_settings_get_string(settings, FreeRDP_WmClass);
249 if (wmclass)
250 app_id = wmclass;
251
252 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
253 return FALSE;
254
255 rdpGdi* gdi = instance->context->gdi;
256
257 if (!gdi || (gdi->width < 0) || (gdi->height < 0))
258 return FALSE;
259
260 if (!wlf_register_pointer(instance->context->graphics))
261 return FALSE;
262
263 UINT32 w = (UINT32)gdi->width;
264 UINT32 h = (UINT32)gdi->height;
265
266 if (freerdp_settings_get_bool(settings, FreeRDP_SmartSizing) && !context->fullscreen)
267 {
268 const UINT32 sw = freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingWidth);
269 if (sw > 0)
270 w = sw;
271
272 const UINT32 sh = freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingHeight);
273 if (sh > 0)
274 h = sh;
275 }
276
277 context->window = UwacCreateWindowShm(context->display, w, h, WL_SHM_FORMAT_XRGB8888);
278
279 if (!context->window)
280 return FALSE;
281
282 UwacWindowSetFullscreenState(
283 context->window, nullptr,
284 freerdp_settings_get_bool(instance->context->settings, FreeRDP_Fullscreen));
285 UwacWindowSetTitle(context->window, title);
286 UwacWindowSetAppId(context->window, app_id);
287 UwacWindowSetOpaqueRegion(context->window, 0, 0, w, h);
288 instance->context->update->EndPaint = wl_end_paint;
289 instance->context->update->DesktopResize = wl_resize_display;
290 const char* KeyboardRemappingList =
291 freerdp_settings_get_string(instance->context->settings, FreeRDP_KeyboardRemappingList);
292
293 context->remap_table = freerdp_keyboard_remap_string_to_list(KeyboardRemappingList);
294 if (!context->remap_table)
295 return FALSE;
296
297 if (!(context->disp = wlf_disp_new(context)))
298 return FALSE;
299
300 context->clipboard = wlf_clipboard_new(context);
301
302 if (!context->clipboard)
303 return FALSE;
304
305 return wl_refresh_display(context);
306}
307
308static void wl_post_disconnect(freerdp* instance)
309{
310 if (!instance)
311 return;
312
313 if (!instance->context)
314 return;
315
316 wlfContext* context = (wlfContext*)instance->context;
317 gdi_free(instance);
318 wlf_clipboard_free(context->clipboard);
319 wlf_disp_free(context->disp);
320
321 if (context->window)
322 UwacDestroyWindow(&context->window);
323 freerdp_keyboard_remap_free(context->remap_table);
324 context->remap_table = nullptr;
325}
326
327static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
328{
329 UwacEvent event;
330 wlfContext* context = nullptr;
331
332 if (UwacDisplayDispatch(display, 1) < 0)
333 return FALSE;
334
335 context = (wlfContext*)instance->context;
336
337 while (UwacHasEvent(display))
338 {
339 if (UwacNextEvent(display, &event) != UWAC_SUCCESS)
340 return FALSE;
341
342 /*printf("UWAC event type %d\n", event.type);*/
343 switch (event.type)
344 {
345 case UWAC_EVENT_NEW_SEAT:
346 context->seat = event.seat_new.seat;
347 break;
348
349 case UWAC_EVENT_REMOVED_SEAT:
350 context->seat = nullptr;
351 break;
352
353 case UWAC_EVENT_FRAME_DONE:
354 {
355 EnterCriticalSection(&context->critical);
356 UwacReturnCode r = UwacWindowSubmitBuffer(context->window, false);
357 LeaveCriticalSection(&context->critical);
358 if (r != UWAC_SUCCESS)
359 return FALSE;
360 }
361 break;
362
363 case UWAC_EVENT_POINTER_ENTER:
364 if (!wlf_handle_pointer_enter(instance, &event.mouse_enter_leave))
365 return FALSE;
366
367 break;
368
369 case UWAC_EVENT_POINTER_LEAVE:
370 if (!wlf_handle_pointer_leave(instance, &event.mouse_enter_leave))
371 return FALSE;
372
373 break;
374
375 case UWAC_EVENT_POINTER_MOTION:
376 if (!wlf_handle_pointer_motion(instance, &event.mouse_motion))
377 return FALSE;
378
379 break;
380
381 case UWAC_EVENT_POINTER_BUTTONS:
382 if (!wlf_handle_pointer_buttons(instance, &event.mouse_button))
383 return FALSE;
384
385 break;
386
387 case UWAC_EVENT_POINTER_AXIS:
388 if (!wlf_handle_pointer_axis(instance, &event.mouse_axis))
389 return FALSE;
390 break;
391
392 case UWAC_EVENT_POINTER_AXIS_DISCRETE:
393 if (!wlf_handle_pointer_axis_discrete(instance, &event.mouse_axis))
394 return FALSE;
395 break;
396
397 case UWAC_EVENT_POINTER_FRAME:
398 if (!wlf_handle_pointer_frame(instance, &event.mouse_frame))
399 return FALSE;
400 break;
401 case UWAC_EVENT_POINTER_SOURCE:
402 if (!wlf_handle_pointer_source(instance, &event.mouse_source))
403 return FALSE;
404 break;
405
406 case UWAC_EVENT_KEY:
407 if (!wlf_handle_key(instance, &event.key))
408 return FALSE;
409
410 break;
411
412 case UWAC_EVENT_TOUCH_UP:
413 if (!wlf_handle_touch_up(instance, &event.touchUp))
414 return FALSE;
415
416 break;
417
418 case UWAC_EVENT_TOUCH_DOWN:
419 if (!wlf_handle_touch_down(instance, &event.touchDown))
420 return FALSE;
421
422 break;
423
424 case UWAC_EVENT_TOUCH_MOTION:
425 if (!wlf_handle_touch_motion(instance, &event.touchMotion))
426 return FALSE;
427
428 break;
429
430 case UWAC_EVENT_KEYBOARD_ENTER:
431 if (freerdp_settings_get_bool(instance->context->settings, FreeRDP_GrabKeyboard))
432 UwacSeatInhibitShortcuts(event.keyboard_enter_leave.seat, true);
433
434 if (!wlf_keyboard_enter(instance, &event.keyboard_enter_leave))
435 return FALSE;
436
437 break;
438
439 case UWAC_EVENT_KEYBOARD_MODIFIERS:
440 if (!wlf_keyboard_modifiers(instance, &event.keyboard_modifiers))
441 return FALSE;
442
443 break;
444
445 case UWAC_EVENT_CONFIGURE:
446 if (!wlf_disp_handle_configure(context->disp, event.configure.width,
447 event.configure.height))
448 return FALSE;
449
450 if (!wl_refresh_display(context))
451 return FALSE;
452
453 break;
454
455 case UWAC_EVENT_CLIPBOARD_AVAILABLE:
456 case UWAC_EVENT_CLIPBOARD_OFFER:
457 case UWAC_EVENT_CLIPBOARD_SELECT:
458 if (!wlf_cliprdr_handle_event(context->clipboard, &event.clipboard))
459 return FALSE;
460
461 break;
462
463 case UWAC_EVENT_CLOSE:
464 context->closed = TRUE;
465
466 break;
467
468 default:
469 break;
470 }
471 }
472
473 return TRUE;
474}
475
476static BOOL handle_window_events(freerdp* instance)
477{
478 return instance != nullptr;
479}
480
481static int wlfreerdp_run(freerdp* instance)
482{
483 wlfContext* context = nullptr;
484 HANDLE handles[MAXIMUM_WAIT_OBJECTS] = WINPR_C_ARRAY_INIT;
485 DWORD status = WAIT_ABANDONED;
486
487 if (!instance)
488 return -1;
489
490 context = (wlfContext*)instance->context;
491
492 if (!context)
493 return -1;
494
495 if (!freerdp_connect(instance))
496 {
497 WLog_Print(context->log, WLOG_ERROR, "Failed to connect");
498 return -1;
499 }
500
501 while (!freerdp_shall_disconnect_context(instance->context))
502 {
503 DWORD count = 0;
504 handles[count++] = context->displayHandle;
505 count += freerdp_get_event_handles(instance->context, &handles[count],
506 ARRAYSIZE(handles) - count);
507
508 if (count <= 2)
509 {
510 WLog_Print(context->log, WLOG_ERROR, "Failed to get FreeRDP file descriptor");
511 break;
512 }
513
514 status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
515
516 if (WAIT_FAILED == status)
517 {
518 WLog_Print(context->log, WLOG_ERROR, "WaitForMultipleObjects failed");
519 break;
520 }
521
522 if (!handle_uwac_events(instance, context->display))
523 {
524 WLog_Print(context->log, WLOG_ERROR, "error handling UWAC events");
525 break;
526 }
527
528 if (context->closed)
529 {
530 WLog_Print(context->log, WLOG_INFO, "Closed from Wayland");
531 break;
532 }
533
534 if (freerdp_check_event_handles(instance->context) != TRUE)
535 {
536 if (client_auto_reconnect_ex(instance, handle_window_events))
537 continue;
538 else
539 {
540 /*
541 * Indicate an unsuccessful connection attempt if reconnect
542 * did not succeed and no other error was specified.
543 */
544 if (freerdp_error_info(instance) == 0)
545 status = 42;
546 }
547
548 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
549 WLog_Print(context->log, WLOG_ERROR, "Failed to check FreeRDP file descriptor");
550
551 break;
552 }
553 }
554
555 freerdp_disconnect(instance);
556 return WINPR_ASSERTING_INT_CAST(int, status);
557}
558
559static BOOL wlf_client_global_init(void)
560{
561 // NOLINTNEXTLINE(concurrency-mt-unsafe)
562 (void)setlocale(LC_ALL, "");
563
564 return (freerdp_handle_signals() == 0);
565}
566
567static void wlf_client_global_uninit(void)
568{
569}
570
571static int wlf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
572{
573 wlfContext* wlf = nullptr;
574 const char* str_data = freerdp_get_logon_error_info_data(data);
575 const char* str_type = freerdp_get_logon_error_info_type(type);
576
577 if (!instance || !instance->context)
578 return -1;
579
580 wlf = (wlfContext*)instance->context;
581 WLog_Print(wlf->log, WLOG_INFO, "Logon Error Info %s [%s]", str_data, str_type);
582 return 1;
583}
584
585static void wlf_client_free(freerdp* instance, rdpContext* context)
586{
587 wlfContext* wlf = (wlfContext*)instance->context;
588
589 if (!context)
590 return;
591
592 if (wlf->display)
593 UwacCloseDisplay(&wlf->display);
594
595 if (wlf->displayHandle)
596 (void)CloseHandle(wlf->displayHandle);
597 ArrayList_Free(wlf->events);
598 DeleteCriticalSection(&wlf->critical);
599}
600
601static void* uwac_event_clone(const void* val)
602{
603 UwacEvent* copy = nullptr;
604 const UwacEvent* ev = (const UwacEvent*)val;
605
606 copy = calloc(1, sizeof(UwacEvent));
607 if (!copy)
608 return nullptr;
609 *copy = *ev;
610 return copy;
611}
612
613static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
614{
615 wObject* obj = nullptr;
616 UwacReturnCode status = UWAC_ERROR_INTERNAL;
617 wlfContext* wfl = (wlfContext*)context;
618
619 if (!instance || !context)
620 return FALSE;
621
622 instance->PreConnect = wl_pre_connect;
623 instance->PostConnect = wl_post_connect;
624 instance->PostDisconnect = wl_post_disconnect;
625 instance->LogonErrorInfo = wlf_logon_error_info;
626 instance->GetAccessToken = client_failsafe_get_access_token;
627 wfl->log = WLog_Get(TAG);
628 wfl->display = UwacOpenDisplay(nullptr, &status);
629
630 if (!wfl->display || (status != UWAC_SUCCESS) || !wfl->log)
631 return FALSE;
632
633 wfl->displayHandle = CreateFileDescriptorEvent(nullptr, FALSE, FALSE,
634 UwacDisplayGetFd(wfl->display), WINPR_FD_READ);
635
636 if (!wfl->displayHandle)
637 return FALSE;
638
639 wfl->events = ArrayList_New(FALSE);
640 if (!wfl->events)
641 return FALSE;
642
643 obj = ArrayList_Object(wfl->events);
644 obj->fnObjectNew = uwac_event_clone;
645 obj->fnObjectFree = free;
646
647 InitializeCriticalSection(&wfl->critical);
648
649 return TRUE;
650}
651
652static int wfl_client_start(rdpContext* context)
653{
654 WINPR_UNUSED(context);
655 return 0;
656}
657
658static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
659{
660 WINPR_ASSERT(pEntryPoints);
661 ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
662 pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
663 pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
664 pEntryPoints->GlobalInit = wlf_client_global_init;
665 pEntryPoints->GlobalUninit = wlf_client_global_uninit;
666 pEntryPoints->ContextSize = sizeof(wlfContext);
667 pEntryPoints->ClientNew = wlf_client_new;
668 pEntryPoints->ClientFree = wlf_client_free;
669 pEntryPoints->ClientStart = wfl_client_start;
670 pEntryPoints->ClientStop = freerdp_client_common_stop;
671 return 0;
672}
673
674int main(int argc, char* argv[])
675{
676 int rc = -1;
677 int status = 0;
678 RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
679 rdpContext* context = nullptr;
680 rdpSettings* settings = nullptr;
681 wlfContext* wlc = nullptr;
682
683 freerdp_client_warn_deprecated(argc, argv);
684
685 RdpClientEntry(&clientEntryPoints);
686 context = freerdp_client_context_new(&clientEntryPoints);
687 if (!context)
688 goto fail;
689 wlc = (wlfContext*)context;
690 settings = context->settings;
691
692 status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE);
693 if (status)
694 {
695 rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
696
697 if (freerdp_settings_get_bool(settings, FreeRDP_ListMonitors))
698 wlf_list_monitors(wlc);
699
700 goto fail;
701 }
702
703 if (freerdp_client_start(context) != 0)
704 goto fail;
705
706 rc = wlfreerdp_run(context->instance);
707
708 if (freerdp_client_stop(context) != 0)
709 rc = -1;
710
711fail:
712 freerdp_client_context_free(context);
713 return rc;
714}
715
716BOOL wlf_copy_image(const void* src, size_t srcStride, size_t srcWidth, size_t srcHeight, void* dst,
717 size_t dstStride, size_t dstWidth, size_t dstHeight, const RECTANGLE_16* area,
718 BOOL scale)
719{
720 BOOL rc = FALSE;
721
722 if (!src || !dst || !area)
723 return FALSE;
724
725 if (scale)
726 {
727 WINPR_ASSERT(dstStride <= UINT32_MAX);
728 WINPR_ASSERT(dstWidth <= UINT32_MAX);
729 WINPR_ASSERT(dstHeight <= UINT32_MAX);
730 WINPR_ASSERT(srcStride <= UINT32_MAX);
731 WINPR_ASSERT(srcWidth <= UINT32_MAX);
732 WINPR_ASSERT(srcHeight <= UINT32_MAX);
733 return freerdp_image_scale(dst, PIXEL_FORMAT_BGRA32, (UINT32)dstStride, 0, 0,
734 (UINT32)dstWidth, (UINT32)dstHeight, src, PIXEL_FORMAT_BGRA32,
735 (UINT32)srcStride, 0, 0, (UINT32)srcWidth, (UINT32)srcHeight);
736 }
737 else
738 {
739 const size_t baseSrcOffset = 1ULL * area->top * srcStride + 4ULL * area->left;
740 const size_t baseDstOffset = 1ULL * area->top * dstStride + 4ULL * area->left;
741 const size_t width = MIN((size_t)area->right - area->left, dstWidth - area->left);
742 const size_t height = MIN((size_t)area->bottom - area->top, dstHeight - area->top);
743 const BYTE* psrc = (const BYTE*)src;
744 BYTE* pdst = (BYTE*)dst;
745
746 for (size_t i = 0; i < height; i++)
747 {
748 const size_t srcOffset = i * srcStride + baseSrcOffset;
749 const size_t dstOffset = i * dstStride + baseDstOffset;
750 memcpy(&pdst[dstOffset], &psrc[srcOffset], width * 4);
751 }
752
753 rc = TRUE;
754 }
755
756 return rc;
757}
758
759BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP)
760{
761 wlfContext* wlf = (wlfContext*)context;
762 UwacSize geometry = WINPR_C_ARRAY_INIT;
763
764 if (!context || !px || !py || !context->gdi)
765 return FALSE;
766
767 if (!freerdp_settings_get_bool(context->settings, FreeRDP_SmartSizing))
768 return TRUE;
769
770 rdpGdi* gdi = context->gdi;
771
772 if (UwacWindowGetDrawingBufferGeometry(wlf->window, &geometry, nullptr) != UWAC_SUCCESS)
773 return FALSE;
774
775 const double sx = 1.0 * geometry.width / (double)gdi->width;
776 const double sy = 1.0 * geometry.height / (double)gdi->height;
777
778 if (!fromLocalToRDP)
779 {
780 *px *= (UINT32)lround(sx);
781 *py *= (UINT32)lround(sy);
782 }
783 else
784 {
785 *px /= (UINT32)lround(sx);
786 *py /= (UINT32)lround(sy);
787 }
788
789 return TRUE;
790}
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew
Definition collections.h:54