22#include <freerdp/config.h>
26#include <winpr/assert.h>
27#include <winpr/sysinfo.h>
28#include <freerdp/freerdp.h>
35#include <freerdp/event.h>
39static HWND g_focus_hWnd =
nullptr;
40static HWND g_main_hWnd =
nullptr;
41static HWND g_parent_hWnd =
nullptr;
43#define RESIZE_MIN_DELAY 200
45static BOOL wf_scale_blt(wfContext* wfc, HDC hdc,
int x,
int y,
int w,
int h, HDC hdcSrc,
int x1,
47static BOOL wf_scale_mouse_event(wfContext* wfc, UINT16 flags, INT32 x, INT32 y);
48#if (_WIN32_WINNT >= 0x0500)
49static BOOL wf_scale_mouse_event_ex(wfContext* wfc, UINT16 flags, UINT16 buttonMask, INT32 x,
53static BOOL g_flipping_in = FALSE;
54static BOOL g_flipping_out = FALSE;
56static BOOL g_keystates[256] = WINPR_C_ARRAY_INIT;
60static BOOL ctrl_down(
void)
62 return g_keystates[RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)];
65static BOOL alt_ctrl_down(
void)
67 const BOOL altDown = g_keystates[RDP_SCANCODE_CODE(RDP_SCANCODE_LMENU)];
68 return altDown && ctrl_down();
74static void release_ctrl_alt(rdpInput* input)
76 const UINT32 keys[] = { RDP_SCANCODE_LCONTROL, RDP_SCANCODE_RCONTROL, RDP_SCANCODE_LMENU,
79 for (
size_t x = 0; x < ARRAYSIZE(keys); x++)
81 freerdp_input_send_keyboard_event_ex(input, FALSE, FALSE, keys[x]);
82 g_keystates[RDP_SCANCODE_CODE(keys[x])] = FALSE;
86LRESULT CALLBACK wf_ll_kbd_proc(
int nCode, WPARAM wParam, LPARAM lParam)
88 DWORD ext_proc_id = 0;
90 wfContext* wfc =
nullptr;
96 DEBUG_KBD(
"Low-level keyboard hook, hWnd %X nCode %X wParam %X", g_focus_hWnd, nCode, wParam);
100 if (!alt_ctrl_down())
101 g_flipping_in = FALSE;
102 else if ((nCode == HC_ACTION) && ((wParam == WM_KEYUP) || (wParam == WM_SYSKEYUP)))
105 const PKBDLLHOOKSTRUCT up = (PKBDLLHOOKSTRUCT)lParam;
106 g_keystates[up->scanCode & 0xFF] = FALSE;
109 return CallNextHookEx(
nullptr, nCode, wParam, lParam);
112 if (g_parent_hWnd && g_main_hWnd)
114 wfc = (wfContext*)GetWindowLongPtr(g_main_hWnd, GWLP_USERDATA);
115 GUITHREADINFO gui_thread_info;
116 gui_thread_info.cbSize =
sizeof(GUITHREADINFO);
117 HWND fg_win_hwnd = GetForegroundWindow();
118 DWORD fg_win_thread_id = GetWindowThreadProcessId(fg_win_hwnd, &ext_proc_id);
119 BOOL result = GetGUIThreadInfo(fg_win_thread_id, &gui_thread_info);
120 if (gui_thread_info.hwndFocus != wfc->hWndParent)
122 g_focus_hWnd =
nullptr;
123 return CallNextHookEx(
nullptr, nCode, wParam, lParam);
126 g_focus_hWnd = g_main_hWnd;
129 if (g_focus_hWnd && (nCode == HC_ACTION))
138 wfc = (wfContext*)GetWindowLongPtr(g_focus_hWnd, GWLP_USERDATA);
139 p = (PKBDLLHOOKSTRUCT)lParam;
144 input = wfc->common.context.input;
145 rdp_scancode = MAKE_RDP_SCANCODE((BYTE)p->scanCode, p->flags & LLKHF_EXTENDED);
146 keystate = g_keystates[p->scanCode & 0xFF];
152 g_keystates[p->scanCode & 0xFF] = TRUE;
157 g_keystates[p->scanCode & 0xFF] = FALSE;
160 DEBUG_KBD(
"keydown %d scanCode 0x%08lX flags 0x%08lX vkCode 0x%08lX",
161 (wParam == WM_KEYDOWN), p->scanCode, p->flags, p->vkCode);
163 if (wfc->fullscreen_toggle && (p->vkCode == VK_RETURN || p->vkCode == VK_CANCEL))
167 if ((wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN))
169 release_ctrl_alt(input);
170 wf_toggle_fullscreen(wfc);
176 if (rdp_scancode == RDP_SCANCODE_NUMLOCK_EXTENDED)
179 DEBUG_KBD(
"hack: NumLock (x45) should not be extended");
180 rdp_scancode = RDP_SCANCODE_NUMLOCK;
182 else if (rdp_scancode == RDP_SCANCODE_NUMLOCK)
186 if (wParam == WM_KEYDOWN)
188 DEBUG_KBD(
"Pause, sent as Ctrl+NumLock");
189 freerdp_input_send_keyboard_event_ex(input, TRUE, FALSE,
190 RDP_SCANCODE_LCONTROL);
191 freerdp_input_send_keyboard_event_ex(input, TRUE, FALSE,
192 RDP_SCANCODE_NUMLOCK);
193 freerdp_input_send_keyboard_event_ex(input, FALSE, FALSE,
194 RDP_SCANCODE_LCONTROL);
195 freerdp_input_send_keyboard_event_ex(input, FALSE, FALSE,
196 RDP_SCANCODE_NUMLOCK);
200 DEBUG_KBD(
"Pause up");
205 else if (rdp_scancode == RDP_SCANCODE_RSHIFT_EXTENDED)
207 DEBUG_KBD(
"right shift (x36) should not be extended");
208 rdp_scancode = RDP_SCANCODE_RSHIFT;
211 freerdp_input_send_keyboard_event_ex(input, !(p->flags & LLKHF_UP), keystate,
215 if (g_flipping_out && !alt_ctrl_down())
217 g_flipping_out = FALSE;
218 g_focus_hWnd =
nullptr;
221 if (p->vkCode == VK_NUMLOCK || p->vkCode == VK_CAPITAL || p->vkCode == VK_SCROLL ||
222 p->vkCode == VK_KANA)
224 "lock keys are processed on client side too to toggle their indicators");
236 if (!alt_ctrl_down())
238 g_flipping_out = FALSE;
239 g_focus_hWnd =
nullptr;
243 return CallNextHookEx(
nullptr, nCode, wParam, lParam);
246void wf_event_focus_in(wfContext* wfc)
252 input = wfc->common.context.input;
255 if (GetKeyState(VK_NUMLOCK))
256 syncFlags |= KBD_SYNC_NUM_LOCK;
258 if (GetKeyState(VK_CAPITAL))
259 syncFlags |= KBD_SYNC_CAPS_LOCK;
261 if (GetKeyState(VK_SCROLL))
262 syncFlags |= KBD_SYNC_SCROLL_LOCK;
264 if (GetKeyState(VK_KANA))
265 syncFlags |= KBD_SYNC_KANA_LOCK;
267 input->FocusInEvent(input, syncFlags);
270 ScreenToClient(wfc->hwnd, &pt);
271 GetClientRect(wfc->hwnd, &rc);
273 if (pt.x >= rc.left && pt.x < rc.right && pt.y >= rc.top && pt.y < rc.bottom)
274 input->MouseEvent(input, PTR_FLAGS_MOVE, (UINT16)pt.x, (UINT16)pt.y);
277static BOOL wf_event_process_WM_MOUSEWHEEL(wfContext* wfc, HWND hWnd, UINT Msg, WPARAM wParam,
278 LPARAM lParam, BOOL horizontal, INT32 x, INT32 y)
286 input = wfc->common.context.input;
289 DefWindowProc(hWnd, Msg, wParam, lParam);
290 delta = ((
signed short)HIWORD(wParam));
293 flags |= PTR_FLAGS_HWHEEL;
295 flags |= PTR_FLAGS_WHEEL;
299 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
301 delta = 0x100 + delta;
305 return wf_scale_mouse_event(wfc, flags, x, y);
308static void wf_sizing(wfContext* wfc, WPARAM wParam, LPARAM lParam)
310 rdpSettings* settings = wfc->common.context.settings;
318 rect = (LPRECT)wParam;
324 case WMSZ_BOTTOMRIGHT:
328 (rect->right - rect->left) /
338 (rect->bottom - rect->top) /
342 case WMSZ_BOTTOMLEFT:
347 (rect->bottom - rect->top) /
354static void wf_send_resize(wfContext* wfc)
357 int targetWidth = wfc->client_width;
358 int targetHeight = wfc->client_height;
359 rdpSettings* settings = wfc->common.context.settings;
362 wfc->disp !=
nullptr)
364 if (GetTickCount64() - wfc->lastSentDate > RESIZE_MIN_DELAY)
368 GetWindowRect(wfc->hwnd, &windowRect);
369 targetWidth = windowRect.right - windowRect.left;
370 targetHeight = windowRect.bottom - windowRect.top;
377 layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY;
378 layout.Top = layout.Left = 0;
379 layout.Width = targetWidth;
380 layout.Height = targetHeight;
383 layout.DesktopScaleFactor =
385 layout.DeviceScaleFactor =
387 layout.PhysicalWidth = targetWidth;
388 layout.PhysicalHeight = targetHeight;
390 if (IFCALLRESULT(CHANNEL_RC_OK, wfc->disp->SendMonitorLayout, wfc->disp, 1,
391 &layout) != CHANNEL_RC_OK)
393 WLog_ERR(
"",
"SendMonitorLayout failed.");
399 wfc->lastSentDate = GetTickCount64();
404LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
406 HDC hdc = WINPR_C_ARRAY_INIT;
407 PAINTSTRUCT ps = WINPR_C_ARRAY_INIT;
408 BOOL processed = FALSE;
409 RECT windowRect = WINPR_C_ARRAY_INIT;
410 MINMAXINFO* minmax =
nullptr;
411 SCROLLINFO si = WINPR_C_ARRAY_INIT;
413 LONG_PTR ptr = GetWindowLongPtr(hWnd, GWLP_USERDATA);
414 wfContext* wfc = (wfContext*)ptr;
418 rdpInput* input = wfc->common.context.input;
419 rdpSettings* settings = wfc->common.context.settings;
421 if (!g_parent_hWnd && wfc->hWndParent)
422 g_parent_hWnd = wfc->hWndParent;
425 g_main_hWnd = wfc->hwnd;
430 if (!wfc->disablewindowtracking)
432 int x = (int)(
short)LOWORD(lParam);
433 int y = (int)(
short)HIWORD(lParam);
440 case WM_GETMINMAXINFO:
449 minmax = (MINMAXINFO*)lParam;
455 if (!wfc->fullscreen)
458 minmax->ptMaxTrackSize.x =
461 minmax->ptMaxTrackSize.y =
470 wf_sizing(wfc, lParam, wParam);
474 GetWindowRect(wfc->hwnd, &windowRect);
476 if (!wfc->fullscreen)
478 wfc->client_width = LOWORD(lParam);
479 wfc->client_height = HIWORD(lParam);
480 wfc->client_x = windowRect.left;
481 wfc->client_y = windowRect.top;
485 wfc->wasMaximized = TRUE;
489 if (wfc->client_width && wfc->client_height)
491 wf_size_scrollbars(wfc, LOWORD(lParam), HIWORD(lParam));
495 if (wParam == SIZE_MAXIMIZED && !wfc->fullscreen)
497 SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, windowRect.right - windowRect.left,
498 windowRect.bottom - windowRect.top,
499 SWP_NOMOVE | SWP_FRAMECHANGED);
500 wfc->wasMaximized = TRUE;
503 else if (wParam == SIZE_RESTORED && !wfc->fullscreen && wfc->wasMaximized)
505 wfc->wasMaximized = FALSE;
508 else if (wParam == SIZE_MINIMIZED)
510 g_focus_hWnd =
nullptr;
516 case WM_EXITSIZEMOVE:
517 wf_size_scrollbars(wfc, wfc->client_width, wfc->client_height);
527 hdc = BeginPaint(hWnd, &ps);
528 const int x = ps.rcPaint.left;
529 const int y = ps.rcPaint.top;
530 const int w = ps.rcPaint.right - ps.rcPaint.left + 1;
531 const int h = ps.rcPaint.bottom - ps.rcPaint.top + 1;
532 wf_scale_blt(wfc, hdc, x, y, w, h, wfc->primary->hdc,
533 x - wfc->offset_x + wfc->xCurrentScroll,
534 y - wfc->offset_y + wfc->yCurrentScroll, SRCCOPY);
538#if (_WIN32_WINNT >= 0x0500)
541 wf_scale_mouse_event_ex(wfc, PTR_XFLAGS_DOWN, GET_XBUTTON_WPARAM(wParam),
542 GET_X_LPARAM(lParam) - wfc->offset_x,
543 GET_Y_LPARAM(lParam) - wfc->offset_y);
547 wf_scale_mouse_event_ex(wfc, 0, GET_XBUTTON_WPARAM(wParam),
548 GET_X_LPARAM(lParam) - wfc->offset_x,
549 GET_Y_LPARAM(lParam) - wfc->offset_y);
554 wf_scale_mouse_event(wfc, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3,
555 GET_X_LPARAM(lParam) - wfc->offset_x,
556 GET_Y_LPARAM(lParam) - wfc->offset_y);
560 wf_scale_mouse_event(wfc, PTR_FLAGS_BUTTON3, GET_X_LPARAM(lParam) - wfc->offset_x,
561 GET_Y_LPARAM(lParam) - wfc->offset_y);
565 wf_scale_mouse_event(wfc, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1,
566 GET_X_LPARAM(lParam) - wfc->offset_x,
567 GET_Y_LPARAM(lParam) - wfc->offset_y);
568 SetCapture(wfc->hwnd);
572 wf_scale_mouse_event(wfc, PTR_FLAGS_BUTTON1, GET_X_LPARAM(lParam) - wfc->offset_x,
573 GET_Y_LPARAM(lParam) - wfc->offset_y);
578 wf_scale_mouse_event(wfc, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2,
579 GET_X_LPARAM(lParam) - wfc->offset_x,
580 GET_Y_LPARAM(lParam) - wfc->offset_y);
584 wf_scale_mouse_event(wfc, PTR_FLAGS_BUTTON2, GET_X_LPARAM(lParam) - wfc->offset_x,
585 GET_Y_LPARAM(lParam) - wfc->offset_y);
589 wf_scale_mouse_event(wfc, PTR_FLAGS_MOVE, GET_X_LPARAM(lParam) - wfc->offset_x,
590 GET_Y_LPARAM(lParam) - wfc->offset_y);
592#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
595 wf_event_process_WM_MOUSEWHEEL(wfc, hWnd, Msg, wParam, lParam, FALSE,
596 GET_X_LPARAM(lParam) - wfc->offset_x,
597 GET_Y_LPARAM(lParam) - wfc->offset_y);
600#if (_WIN32_WINNT >= 0x0600)
603 wf_event_process_WM_MOUSEWHEEL(wfc, hWnd, Msg, wParam, lParam, TRUE,
604 GET_X_LPARAM(lParam) - wfc->offset_x,
605 GET_Y_LPARAM(lParam) - wfc->offset_y);
610 if (LOWORD(lParam) == HTCLIENT)
611 SetCursor(wfc->cursor);
613 DefWindowProc(hWnd, Msg, wParam, lParam);
623 switch (LOWORD(wParam))
627 xNewPos = wfc->xCurrentScroll - 50;
632 xNewPos = wfc->xCurrentScroll + 50;
637 xNewPos = wfc->xCurrentScroll - 5;
642 xNewPos = wfc->xCurrentScroll + 5;
646 case SB_THUMBPOSITION:
647 xNewPos = HIWORD(wParam);
652 xNewPos = HIWORD(wParam);
656 xNewPos = wfc->xCurrentScroll;
660 xNewPos = MAX(0, xNewPos);
661 xNewPos = MIN(wfc->xMaxScroll, xNewPos);
664 if (xNewPos == wfc->xCurrentScroll)
668 xDelta = xNewPos - wfc->xCurrentScroll;
670 wfc->xCurrentScroll = xNewPos;
675 ScrollWindowEx(wfc->hwnd, -xDelta, -yDelta, (CONST RECT*)
nullptr,
676 (CONST RECT*)
nullptr, (HRGN)
nullptr, (PRECT)
nullptr,
678 UpdateWindow(wfc->hwnd);
680 si.cbSize =
sizeof(si);
682 si.nPos = wfc->xCurrentScroll;
683 SetScrollInfo(wfc->hwnd, SB_HORZ, &si, TRUE);
693 switch (LOWORD(wParam))
697 yNewPos = wfc->yCurrentScroll - 50;
702 yNewPos = wfc->yCurrentScroll + 50;
707 yNewPos = wfc->yCurrentScroll - 5;
712 yNewPos = wfc->yCurrentScroll + 5;
716 case SB_THUMBPOSITION:
717 yNewPos = HIWORD(wParam);
722 yNewPos = HIWORD(wParam);
726 yNewPos = wfc->yCurrentScroll;
730 yNewPos = MAX(0, yNewPos);
731 yNewPos = MIN(wfc->yMaxScroll, yNewPos);
734 if (yNewPos == wfc->yCurrentScroll)
738 yDelta = yNewPos - wfc->yCurrentScroll;
740 wfc->yCurrentScroll = yNewPos;
745 ScrollWindowEx(wfc->hwnd, -xDelta, -yDelta, (CONST RECT*)
nullptr,
746 (CONST RECT*)
nullptr, (HRGN)
nullptr, (PRECT)
nullptr,
748 UpdateWindow(wfc->hwnd);
750 si.cbSize =
sizeof(si);
752 si.nPos = wfc->yCurrentScroll;
753 SetScrollInfo(wfc->hwnd, SB_VERT, &si, TRUE);
759 if (wParam == SYSCOMMAND_ID_SMARTSIZING)
761 HMENU hMenu = GetSystemMenu(wfc->hwnd, FALSE);
764 CheckMenuItem(hMenu, SYSCOMMAND_ID_SMARTSIZING,
770 SetWindowPos(wfc->hwnd, HWND_TOP, -1, -1,
779 wf_size_scrollbars(wfc, wfc->client_width, wfc->client_height);
783 else if (wParam == SYSCOMMAND_ID_REQUEST_CONTROL)
785 freerdp_client_encomsp_set_control(wfc->common.encomsp, TRUE);
787 else if (((wParam & 0xfff0) == SC_MAXIMIZE) && wfc->fullscreen_toggle &&
791 wf_toggle_fullscreen(wfc);
816 PostQuitMessage(WM_QUIT);
820 DEBUG_KBD(
"getting focus %X", hWnd);
826 g_flipping_in = TRUE;
829 freerdp_set_focus(wfc->common.context.instance);
830 wf_event_focus_in(wfc);
837 if (g_focus_hWnd == hWnd && wfc && !wfc->fullscreen)
839 DEBUG_KBD(
"losing focus %X", hWnd);
842 g_flipping_out = TRUE;
844 g_focus_hWnd =
nullptr;
851 int activate = (int)(
short)LOWORD(wParam);
852 BOOL minimized_flag = (BOOL)HIWORD(wParam);
854 if (activate != WA_INACTIVE && !minimized_flag)
857 g_flipping_in = TRUE;
864 g_flipping_out = TRUE;
866 g_focus_hWnd =
nullptr;
871 return DefWindowProc(hWnd, Msg, wParam, lParam);
878BOOL wf_scale_blt(wfContext* wfc, HDC hdc,
int x,
int y,
int w,
int h, HDC hdcSrc,
int x1,
int y1,
881 UINT32 ww, wh, dw, dh;
884 rdpSettings* settings = wfc->common.context.settings;
885 WINPR_ASSERT(settings);
887 if (!wfc->client_width)
890 if (!wfc->client_height)
893 ww = wfc->client_width;
894 wh = wfc->client_height;
905 (ww == dw && wh == dh))
907 return BitBlt(hdc, x, y, w, h, wfc->primary->hdc, x1, y1, SRCCOPY);
911 SetStretchBltMode(hdc, HALFTONE);
912 SetBrushOrgEx(hdc, 0, 0,
nullptr);
913 return StretchBlt(hdc, 0, 0, ww, wh, wfc->primary->hdc, 0, 0, dw, dh, SRCCOPY);
919static BOOL wf_scale_mouse_pos(wfContext* wfc, INT32 x, INT32 y, UINT16* px, UINT16* py)
922 rdpSettings* settings;
924 if (!wfc || !px || !py)
927 settings = wfc->common.context.settings;
932 if (!wfc->client_width)
935 if (!wfc->client_height)
938 ww = wfc->client_width;
939 wh = wfc->client_height;
945 x += wfc->xCurrentScroll;
946 y += wfc->yCurrentScroll;
950 x = x * dw / ww + wfc->xCurrentScroll;
951 y = y * dh / wh + wfc->yCurrentScroll;
954 *px = MIN(UINT16_MAX, MAX(0, x));
955 *py = MIN(UINT16_MAX, MAX(0, y));
960static BOOL wf_pub_mouse_event(wfContext* wfc, UINT16 flags, UINT16 x, UINT16 y)
962 MouseEventEventArgs eventArgs = WINPR_C_ARRAY_INIT;
964 eventArgs.flags = flags;
967 return PubSub_OnMouseEvent(wfc->common.context.pubSub, &wfc->common.context, &eventArgs) >= 0;
970static BOOL wf_scale_mouse_event(wfContext* wfc, UINT16 flags, INT32 x, INT32 y)
976 if (!wf_scale_mouse_pos(wfc, x, y, &px, &py))
980 if (!freerdp_client_send_button_event(&wfc->common, FALSE, flags, px, py))
983 return wf_pub_mouse_event(wfc, flags, px, py);
986#if (_WIN32_WINNT >= 0x0500)
987static BOOL wf_scale_mouse_event_ex(wfContext* wfc, UINT16 flags, UINT16 buttonMask, INT32 x,
994 if (buttonMask & XBUTTON1)
995 flags |= PTR_XFLAGS_BUTTON1;
997 if (buttonMask & XBUTTON2)
998 flags |= PTR_XFLAGS_BUTTON2;
1000 if (!wf_scale_mouse_pos(wfc, x, y, &px, &py))
1004 if (!freerdp_client_send_extended_button_event(&wfc->common, FALSE, flags, px, py))
1007 return wf_pub_mouse_event(wfc, flags, px, py);
1011BOOL wf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags)
1013 wfContext* wfc = (wfContext*)context;
1014 BYTE keyState[256] = WINPR_C_ARRAY_INIT;
1016 if (!wfc || !GetKeyboardState(keyState))
1019 if (led_flags & KBD_SYNC_NUM_LOCK)
1020 keyState[VK_NUMLOCK] |= 1;
1022 keyState[VK_NUMLOCK] &= ~1;
1024 if (led_flags & KBD_SYNC_CAPS_LOCK)
1025 keyState[VK_CAPITAL] |= 1;
1027 keyState[VK_CAPITAL] &= ~1;
1029 if (led_flags & KBD_SYNC_SCROLL_LOCK)
1030 keyState[VK_SCROLL] |= 1;
1032 keyState[VK_SCROLL] &= ~1;
1034 if (led_flags & KBD_SYNC_KANA_LOCK)
1035 keyState[VK_KANA] |= 1;
1037 keyState[VK_KANA] &= ~1;
1039 return SetKeyboardState(keyState);
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 UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 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.