22 #include "sdl_connection_dialog.hpp"
23 #include "../sdl_utils.hpp"
24 #include "../sdl_freerdp.hpp"
25 #include "res/sdl3_resource_manager.hpp"
27 static const SDL_Color backgroundcolor = { 0x38, 0x36, 0x35, 0xff };
28 static const SDL_Color textcolor = { 0xd1, 0xcf, 0xcd, 0xff };
29 static const SDL_Color infocolor = { 0x43, 0xe0, 0x0f, 0x60 };
30 static const SDL_Color warncolor = { 0xcd, 0xca, 0x35, 0x60 };
31 static const SDL_Color errorcolor = { 0xf7, 0x22, 0x30, 0x60 };
33 static const Uint32 vpadding = 5;
34 static const Uint32 hpadding = 5;
36 SDLConnectionDialog::SDLConnectionDialog(rdpContext* context) : _context(context)
38 SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
42 SDLConnectionDialog::~SDLConnectionDialog()
49 bool SDLConnectionDialog::visible()
const
51 if (!_window || !_renderer)
54 auto flags = SDL_GetWindowFlags(_window);
55 return (flags & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) == 0;
58 bool SDLConnectionDialog::setTitle(
const char* fmt, ...)
60 std::lock_guard lock(_mux);
63 _title = print(fmt, ap);
66 return show(MSG_NONE);
69 bool SDLConnectionDialog::showInfo(
const char* fmt, ...)
73 auto rc = show(MSG_INFO, fmt, ap);
78 bool SDLConnectionDialog::showWarn(
const char* fmt, ...)
82 auto rc = show(MSG_WARN, fmt, ap);
87 bool SDLConnectionDialog::showError(
const char* fmt, ...)
91 auto rc = show(MSG_ERROR, fmt, ap);
98 bool SDLConnectionDialog::show()
100 std::lock_guard lock(_mux);
101 return show(_type_active);
104 bool SDLConnectionDialog::hide()
106 std::lock_guard lock(_mux);
107 return show(MSG_DISCARD);
110 bool SDLConnectionDialog::running()
const
112 std::lock_guard lock(_mux);
116 bool SDLConnectionDialog::update()
118 std::lock_guard lock(_mux);
124 _type_active = _type;
134 SDL_SetWindowTitle(_window, _title.c_str());
142 bool SDLConnectionDialog::setModal()
146 auto sdl = get_context(_context);
147 if (sdl->windows.empty())
150 auto parent = sdl->windows.begin()->second.window();
151 SDL_SetWindowParent(_window, parent);
152 SDL_SetWindowModal(_window,
true);
153 SDL_RaiseWindow(_window);
158 bool SDLConnectionDialog::clearWindow(SDL_Renderer* renderer)
162 const int drc = SDL_SetRenderDrawColor(renderer, backgroundcolor.r, backgroundcolor.g,
163 backgroundcolor.b, backgroundcolor.a);
164 if (widget_log_error(drc,
"SDL_SetRenderDrawColor"))
167 const int rcls = SDL_RenderClear(renderer);
168 return !widget_log_error(rcls,
"SDL_RenderClear");
171 bool SDLConnectionDialog::update(SDL_Renderer* renderer)
173 std::lock_guard lock(_mux);
177 if (!clearWindow(renderer))
180 for (
auto& btn : _list)
182 if (!btn.widget.update_text(renderer, _msg, btn.fgcolor, btn.bgcolor))
186 if (!_buttons.update(renderer))
189 SDL_RenderPresent(renderer);
193 bool SDLConnectionDialog::wait(
bool ignoreRdpContext)
197 if (!ignoreRdpContext)
199 if (freerdp_shall_disconnect_context(_context))
202 std::this_thread::yield();
207 bool SDLConnectionDialog::handle(
const SDL_Event& event)
212 windowID = SDL_GetWindowID(_window);
217 case SDL_EVENT_USER_RETRY_DIALOG:
223 case SDL_EVENT_KEY_DOWN:
224 case SDL_EVENT_KEY_UP:
227 auto& ev =
reinterpret_cast<const SDL_KeyboardEvent&
>(event);
229 switch (event.key.key)
235 if (event.type == SDL_EVENT_KEY_UP)
237 freerdp_abort_event(_context);
242 _buttons.set_highlight_next();
248 return windowID == ev.windowID;
251 case SDL_EVENT_MOUSE_MOTION:
254 auto& ev =
reinterpret_cast<const SDL_MouseMotionEvent&
>(event);
256 _buttons.set_mouseover(event.button.x, event.button.y);
258 return windowID == ev.windowID;
261 case SDL_EVENT_MOUSE_BUTTON_DOWN:
262 case SDL_EVENT_MOUSE_BUTTON_UP:
265 auto& ev =
reinterpret_cast<const SDL_MouseButtonEvent&
>(event);
268 auto button = _buttons.get_selected(event.button);
271 if (event.type == SDL_EVENT_MOUSE_BUTTON_UP)
273 freerdp_abort_event(_context);
278 return windowID == ev.windowID;
281 case SDL_EVENT_MOUSE_WHEEL:
284 auto& ev =
reinterpret_cast<const SDL_MouseWheelEvent&
>(event);
286 return windowID == ev.windowID;
289 case SDL_EVENT_FINGER_UP:
290 case SDL_EVENT_FINGER_DOWN:
293 auto& ev =
reinterpret_cast<const SDL_TouchFingerEvent&
>(event);
295 return windowID == ev.windowID;
299 if ((event.type >= SDL_EVENT_WINDOW_FIRST) && (event.type <= SDL_EVENT_WINDOW_LAST))
301 auto& ev =
reinterpret_cast<const SDL_WindowEvent&
>(event);
304 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
305 if (windowID == ev.windowID)
307 freerdp_abort_event(_context);
317 return windowID == ev.windowID;
323 bool SDLConnectionDialog::createWindow()
327 const int widget_height = 50;
328 const int widget_width = 600;
329 const int total_height = 300;
331 auto rc = SDL_CreateWindowAndRenderer(_title.c_str(), widget_width, total_height,
332 SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_MOUSE_FOCUS |
333 SDL_WINDOW_INPUT_FOCUS,
334 &_window, &_renderer);
337 widget_log_error(rc,
"SDL_CreateWindowAndRenderer");
342 SDL_Color res_bgcolor;
343 switch (_type_active)
346 res_bgcolor = infocolor;
349 res_bgcolor = warncolor;
352 res_bgcolor = errorcolor;
356 res_bgcolor = backgroundcolor;
360 #if defined(WITH_SDL_IMAGE_DIALOGS)
361 std::string res_name;
362 switch (_type_active)
365 res_name =
"icon_info.svg";
368 res_name =
"icon_warning.svg";
371 res_name =
"icon_error.svg";
379 int height = (total_height - 3ul * vpadding) / 2ul;
380 SDL_FRect iconRect{ hpadding, vpadding, widget_width / 4ul - 2ul * hpadding,
381 static_cast<float>(height) };
382 widget_cfg_t icon{ textcolor,
384 { _renderer, iconRect,
386 _list.emplace_back(std::move(icon));
388 iconRect.y +=
static_cast<float>(height);
390 widget_cfg_t logo{ textcolor,
392 { _renderer, iconRect,
394 "FreeRDP_Icon.svg") } };
395 _list.emplace_back(std::move(logo));
397 SDL_FRect rect = { widget_width / 4ul, vpadding, widget_width * 3ul / 4ul,
398 total_height - 3ul * vpadding - widget_height };
400 SDL_FRect rect = { hpadding, vpadding, widget_width - 2ul * hpadding,
401 total_height - 2ul * vpadding };
404 widget_cfg_t w{ textcolor, backgroundcolor, { _renderer, rect,
false } };
405 w.widget.set_wrap(
true, widget_width);
406 _list.emplace_back(std::move(w));
407 rect.y += widget_height + vpadding;
409 const std::vector<int> buttonids = { 1 };
410 const std::vector<std::string> buttonlabels = {
"cancel" };
411 _buttons.populate(_renderer, buttonlabels, buttonids, widget_width,
412 total_height - widget_height - vpadding,
413 static_cast<Sint32
>(widget_width / 2),
static_cast<Sint32
>(widget_height));
414 _buttons.set_highlight(0);
416 SDL_ShowWindow(_window);
417 SDL_RaiseWindow(_window);
422 void SDLConnectionDialog::destroyWindow()
426 SDL_DestroyRenderer(_renderer);
427 SDL_DestroyWindow(_window);
432 bool SDLConnectionDialog::show(MsgType type,
const char* fmt, va_list ap)
434 std::lock_guard lock(_mux);
435 _msg = print(fmt, ap);
439 bool SDLConnectionDialog::show(MsgType type)
442 return sdl_push_user_event(SDL_EVENT_USER_RETRY_DIALOG);
445 std::string SDLConnectionDialog::print(
const char* fmt, va_list ap)
458 WINPR_PRAGMA_DIAG_PUSH
459 WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL
460 size = vsnprintf(res.data(), res.size(), fmt, copy);
461 WINPR_PRAGMA_DIAG_POP
464 }
while ((size > 0) && (
static_cast<size_t>(size) > res.size()));
469 bool SDLConnectionDialog::setTimer(Uint32 timeoutMS)
471 std::lock_guard lock(_mux);
474 _timer = SDL_AddTimer(timeoutMS, &SDLConnectionDialog::timeout,
this);
479 void SDLConnectionDialog::resetTimer()
482 SDL_RemoveTimer(_timer);
486 Uint32 SDLConnectionDialog::timeout(
void* pvthis, SDL_TimerID timerID, Uint32 intervalMS)
490 ths->_running =
false;
494 SDLConnectionDialogHider::SDLConnectionDialogHider(freerdp* instance)
499 SDLConnectionDialogHider::SDLConnectionDialogHider(rdpContext* context)
504 SDLConnectionDialogHider::SDLConnectionDialogHider(
SDLConnectionDialog* dialog) : _dialog(dialog)
508 _visible = _dialog->visible();
516 SDLConnectionDialogHider::~SDLConnectionDialogHider()
518 if (_dialog && _visible)
528 return get(instance->context);
533 auto sdl = get_context(context);
536 return sdl->connection_dialog.get();
static SDL_IOStream * get(const std::string &type, const std::string &id)