22#include "sdl_connection_dialog.hpp"
23#include "../sdl_utils.hpp"
24#include "../sdl_freerdp.hpp"
25#include "res/sdl3_resource_manager.hpp"
27static const SDL_Color textcolor = { 0xd1, 0xcf, 0xcd, 0xff };
28static const SDL_Color infocolor = { 0x43, 0xe0, 0x0f, 0x60 };
29static const SDL_Color warncolor = { 0xcd, 0xca, 0x35, 0x60 };
30static const SDL_Color errorcolor = { 0xf7, 0x22, 0x30, 0x60 };
32static const Uint32 vpadding = 5;
33static const Uint32 hpadding = 5;
35SDLConnectionDialog::SDLConnectionDialog(rdpContext* context) : _context(context)
40SDLConnectionDialog::~SDLConnectionDialog()
46bool SDLConnectionDialog::setTitle(
const char* fmt, ...)
48 std::lock_guard lock(_mux);
51 _title = print(fmt, ap);
54 return show(SdlConnectionDialogWrapper::MSG_NONE);
57bool SDLConnectionDialog::showInfo(
const char* fmt, ...)
61 auto rc = show(SdlConnectionDialogWrapper::MSG_INFO, fmt, ap);
66bool SDLConnectionDialog::showWarn(
const char* fmt, ...)
70 auto rc = show(SdlConnectionDialogWrapper::MSG_WARN, fmt, ap);
75bool SDLConnectionDialog::showError(
const char* fmt, ...)
79 auto rc = show(SdlConnectionDialogWrapper::MSG_ERROR, fmt, ap);
86bool SDLConnectionDialog::show()
88 std::lock_guard lock(_mux);
89 return show(_type_active);
92bool SDLConnectionDialog::hide()
94 std::lock_guard lock(_mux);
95 return show(SdlConnectionDialogWrapper::MSG_DISCARD);
98bool SDLConnectionDialog::running()
const
100 std::lock_guard lock(_mux);
104bool SDLConnectionDialog::updateMsg(SdlConnectionDialogWrapper::MsgType type)
108 case SdlConnectionDialogWrapper::MSG_INFO:
109 case SdlConnectionDialogWrapper::MSG_WARN:
110 case SdlConnectionDialogWrapper::MSG_ERROR:
114 case SdlConnectionDialogWrapper::MSG_DISCARD:
121 SDL_SetWindowTitle(_window.get(), _title.c_str());
128bool SDLConnectionDialog::setModal()
132 auto sdl = get_context(_context);
133 if (sdl->windows.empty())
136 auto parent = sdl->windows.begin()->second.window();
137 SDL_SetWindowParent(_window.get(), parent);
138 SDL_SetWindowModal(_window.get(),
true);
139 SDL_RaiseWindow(_window.get());
144bool SDLConnectionDialog::updateInternal()
146 std::lock_guard lock(_mux);
147 for (
auto& btn : _list)
149 if (!btn.widget.update_text(_msg))
156bool SDLConnectionDialog::wait(
bool ignoreRdpContext)
160 if (!ignoreRdpContext)
162 if (freerdp_shall_disconnect_context(_context))
165 std::this_thread::yield();
170bool SDLConnectionDialog::handle(
const SDL_Event& event)
175 windowID = SDL_GetWindowID(_window.get());
180 case SDL_EVENT_USER_RETRY_DIALOG:
182 std::lock_guard lock(_mux);
183 auto type =
static_cast<SdlConnectionDialogWrapper::MsgType
>(
event.user.code);
184 return updateMsg(type);
190 case SDL_EVENT_KEY_DOWN:
191 case SDL_EVENT_KEY_UP:
194 auto& ev =
reinterpret_cast<const SDL_KeyboardEvent&
>(event);
196 switch (event.key.key)
202 if (event.type == SDL_EVENT_KEY_UP)
204 freerdp_abort_event(_context);
209 _buttons.set_highlight_next();
215 return windowID == ev.windowID;
218 case SDL_EVENT_MOUSE_MOTION:
221 auto& ev =
reinterpret_cast<const SDL_MouseMotionEvent&
>(event);
223 _buttons.set_mouseover(event.button.x, event.button.y);
225 return windowID == ev.windowID;
228 case SDL_EVENT_MOUSE_BUTTON_DOWN:
229 case SDL_EVENT_MOUSE_BUTTON_UP:
232 auto& ev =
reinterpret_cast<const SDL_MouseButtonEvent&
>(event);
235 auto button = _buttons.get_selected(event.button);
238 if (event.type == SDL_EVENT_MOUSE_BUTTON_UP)
240 freerdp_abort_event(_context);
245 return windowID == ev.windowID;
248 case SDL_EVENT_MOUSE_WHEEL:
251 auto& ev =
reinterpret_cast<const SDL_MouseWheelEvent&
>(event);
253 return windowID == ev.windowID;
256 case SDL_EVENT_FINGER_UP:
257 case SDL_EVENT_FINGER_DOWN:
260 auto& ev =
reinterpret_cast<const SDL_TouchFingerEvent&
>(event);
262 return windowID == ev.windowID;
266 if ((event.type >= SDL_EVENT_WINDOW_FIRST) && (event.type <= SDL_EVENT_WINDOW_LAST))
268 auto& ev =
reinterpret_cast<const SDL_WindowEvent&
>(event);
271 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
272 if (windowID == ev.windowID)
274 freerdp_abort_event(_context);
284 return windowID == ev.windowID;
290bool SDLConnectionDialog::visible()
const
292 std::lock_guard lock(_mux);
293 return SdlWidgetList::visible();
296bool SDLConnectionDialog::createWindow()
300 const size_t widget_height = 50;
301 const size_t widget_width = 600;
302 const size_t total_height = 300;
304 if (!reset(_title, widget_width, total_height))
309 SDL_Color res_bgcolor;
310 switch (_type_active)
312 case SdlConnectionDialogWrapper::MSG_INFO:
313 res_bgcolor = infocolor;
315 case SdlConnectionDialogWrapper::MSG_WARN:
316 res_bgcolor = warncolor;
318 case SdlConnectionDialogWrapper::MSG_ERROR:
319 res_bgcolor = errorcolor;
321 case SdlConnectionDialogWrapper::MSG_DISCARD:
323 res_bgcolor = _backgroundcolor;
327#if defined(WITH_SDL_IMAGE_DIALOGS)
328 std::string res_name;
329 switch (_type_active)
331 case SdlConnectionDialogWrapper::MSG_INFO:
332 res_name =
"icon_info.svg";
334 case SdlConnectionDialogWrapper::MSG_WARN:
335 res_name =
"icon_warning.svg";
337 case SdlConnectionDialogWrapper::MSG_ERROR:
338 res_name =
"icon_error.svg";
340 case SdlConnectionDialogWrapper::MSG_DISCARD:
346 const auto height = (total_height - 3ul * vpadding) / 2ul;
347 SDL_FRect iconRect{ hpadding, vpadding, widget_width / 4ul - 2ul * hpadding,
348 static_cast<float>(height) };
349 widget_cfg_t icon{ textcolor,
351 { _renderer, iconRect,
353 _list.emplace_back(std::move(icon));
355 iconRect.y +=
static_cast<float>(height);
357 widget_cfg_t logo{ textcolor,
359 { _renderer, iconRect,
361 "FreeRDP_Icon.svg") } };
362 _list.emplace_back(std::move(logo));
364 SDL_FRect rect = { widget_width / 4ul, vpadding, widget_width * 3ul / 4ul,
365 total_height - 3ul * vpadding - widget_height };
367 SDL_FRect rect = { hpadding, vpadding, widget_width - 2ul * hpadding,
368 total_height - 2ul * vpadding };
371 widget_cfg_t w{ textcolor, _backgroundcolor, { _renderer, rect } };
372 w.widget.set_wrap(
true, widget_width);
373 _list.emplace_back(std::move(w));
374 rect.y += widget_height + vpadding;
376 const std::vector<int> buttonids = { 1 };
377 const std::vector<std::string> buttonlabels = {
"cancel" };
378 _buttons.populate(_renderer, buttonlabels, buttonids, widget_width,
379 total_height - widget_height - vpadding,
380 static_cast<Sint32
>(widget_width / 2),
static_cast<Sint32
>(widget_height));
381 _buttons.set_highlight(0);
383 SDL_ShowWindow(_window.get());
384 SDL_RaiseWindow(_window.get());
389void SDLConnectionDialog::destroyWindow()
397bool SDLConnectionDialog::show(SdlConnectionDialogWrapper::MsgType type,
const char* fmt,
400 std::lock_guard lock(_mux);
401 _msg = print(fmt, ap);
405bool SDLConnectionDialog::show(SdlConnectionDialogWrapper::MsgType type)
407 if (SDL_IsMainThread())
408 return updateMsg(type);
410 return sdl_push_user_event(SDL_EVENT_USER_RETRY_DIALOG, type);
413std::string SDLConnectionDialog::print(
const char* fmt, va_list ap)
422 res.resize(WINPR_ASSERTING_INT_CAST(uint32_t, size));
426 WINPR_PRAGMA_DIAG_PUSH
427 WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL
428 size = vsnprintf(res.data(), res.size(), fmt, copy);
429 WINPR_PRAGMA_DIAG_POP
432 }
while ((size > 0) && (
static_cast<size_t>(size) > res.size()));
437bool SDLConnectionDialog::setTimer(Uint32 timeoutMS)
439 std::lock_guard lock(_mux);
442 _timer = SDL_AddTimer(timeoutMS, &SDLConnectionDialog::timeout,
this);
447void SDLConnectionDialog::resetTimer()
450 SDL_RemoveTimer(_timer);
454Uint32 SDLConnectionDialog::timeout(
void* pvthis, [[maybe_unused]] SDL_TimerID timerID,
455 [[maybe_unused]] Uint32 intervalMS)
459 self->_running =
false;
static SDL_IOStream * get(const std::string &type, const std::string &id)