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)