22#include "sdl_connection_dialog.hpp" 
   23#include "../sdl_utils.hpp" 
   24#include "../sdl_freerdp.hpp" 
   25#include "res/sdl2_resource_manager.hpp" 
   27static const SDL_Color backgroundcolor = { 0x38, 0x36, 0x35, 0xff };
 
   28static const SDL_Color textcolor = { 0xd1, 0xcf, 0xcd, 0xff };
 
   29static const SDL_Color infocolor = { 0x43, 0xe0, 0x0f, 0x60 };
 
   30static const SDL_Color warncolor = { 0xcd, 0xca, 0x35, 0x60 };
 
   31static const SDL_Color errorcolor = { 0xf7, 0x22, 0x30, 0x60 };
 
   33static const Uint32 vpadding = 5;
 
   34static const Uint32 hpadding = 5;
 
   36SDLConnectionDialog::SDLConnectionDialog(rdpContext* context) : _context(context)
 
   38  SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
 
   42SDLConnectionDialog::~SDLConnectionDialog()
 
   49bool SDLConnectionDialog::visible()
 const 
   51  if (!_window || !_renderer)
 
   54  auto flags = SDL_GetWindowFlags(_window);
 
   55  return (flags & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) == 0;
 
   58bool SDLConnectionDialog::setTitle(
const char* fmt, ...)
 
   60  std::lock_guard lock(_mux);
 
   63  _title = print(fmt, ap);
 
   66  return show(MSG_NONE);
 
   69bool SDLConnectionDialog::showInfo(
const char* fmt, ...)
 
   73  auto rc = show(MSG_INFO, fmt, ap);
 
   78bool SDLConnectionDialog::showWarn(
const char* fmt, ...)
 
   82  auto rc = show(MSG_WARN, fmt, ap);
 
   87bool SDLConnectionDialog::showError(
const char* fmt, ...)
 
   91  auto rc = show(MSG_ERROR, fmt, ap);
 
   98bool SDLConnectionDialog::show()
 
  100  std::lock_guard lock(_mux);
 
  101  return show(_type_active);
 
  104bool SDLConnectionDialog::hide()
 
  106  std::lock_guard lock(_mux);
 
  107  return show(MSG_DISCARD);
 
  110bool SDLConnectionDialog::running()
 const 
  112  std::lock_guard lock(_mux);
 
  116bool SDLConnectionDialog::update()
 
  118  std::lock_guard lock(_mux);
 
  124      _type_active = _type;
 
  134        SDL_SetWindowTitle(_window, _title.c_str());
 
  142bool SDLConnectionDialog::setModal()
 
  146    auto sdl = get_context(_context);
 
  147    if (sdl->windows.empty())
 
  150    auto parent = sdl->windows.begin()->second.window();
 
  151    SDL_SetWindowModalFor(_window, parent);
 
  152    SDL_RaiseWindow(_window);
 
  157bool SDLConnectionDialog::clearWindow(SDL_Renderer* renderer)
 
  161  const int drc = SDL_SetRenderDrawColor(renderer, backgroundcolor.r, backgroundcolor.g,
 
  162                                         backgroundcolor.b, backgroundcolor.a);
 
  163  if (widget_log_error(drc, 
"SDL_SetRenderDrawColor"))
 
  166  const int rcls = SDL_RenderClear(renderer);
 
  167  return !widget_log_error(rcls, 
"SDL_RenderClear");
 
  170bool SDLConnectionDialog::update(SDL_Renderer* renderer)
 
  172  std::lock_guard lock(_mux);
 
  176  if (!clearWindow(renderer))
 
  179  for (
auto& btn : _list)
 
  181    if (!btn.widget.update_text(renderer, _msg, btn.fgcolor, btn.bgcolor))
 
  185  if (!_buttons.update(renderer))
 
  188  SDL_RenderPresent(renderer);
 
  192bool SDLConnectionDialog::wait(
bool ignoreRdpContext)
 
  196    if (!ignoreRdpContext)
 
  198      if (freerdp_shall_disconnect_context(_context))
 
  201    std::this_thread::yield();
 
  206bool SDLConnectionDialog::handle(
const SDL_Event& event)
 
  211    windowID = SDL_GetWindowID(_window);
 
  216    case SDL_USEREVENT_RETRY_DIALOG:
 
  226        auto& ev = 
reinterpret_cast<const SDL_KeyboardEvent&
>(event);
 
  228        switch (event.key.keysym.sym)
 
  234            if (event.type == SDL_KEYUP)
 
  236              freerdp_abort_event(_context);
 
  241            _buttons.set_highlight_next();
 
  247        return windowID == ev.windowID;
 
  250    case SDL_MOUSEMOTION:
 
  253        auto& ev = 
reinterpret_cast<const SDL_MouseMotionEvent&
>(event);
 
  255        _buttons.set_mouseover(event.button.x, event.button.y);
 
  257        return windowID == ev.windowID;
 
  260    case SDL_MOUSEBUTTONDOWN:
 
  261    case SDL_MOUSEBUTTONUP:
 
  264        auto& ev = 
reinterpret_cast<const SDL_MouseButtonEvent&
>(event);
 
  267        auto button = _buttons.get_selected(event.button);
 
  270          if (event.type == SDL_MOUSEBUTTONUP)
 
  272            freerdp_abort_event(_context);
 
  277        return windowID == ev.windowID;
 
  283        auto& ev = 
reinterpret_cast<const SDL_MouseWheelEvent&
>(event);
 
  285        return windowID == ev.windowID;
 
  292        auto& ev = 
reinterpret_cast<const SDL_TouchFingerEvent&
>(event);
 
  294#if SDL_VERSION_ATLEAST(2, 0, 18) 
  295        return windowID == ev.windowID;
 
  301    case SDL_WINDOWEVENT:
 
  303      auto& ev = 
reinterpret_cast<const SDL_WindowEvent&
>(event);
 
  306        case SDL_WINDOWEVENT_CLOSE:
 
  307          if (windowID == ev.windowID)
 
  309            freerdp_abort_event(_context);
 
  319      return windowID == ev.windowID;
 
  326bool SDLConnectionDialog::createWindow()
 
  330  const int widget_height = 50;
 
  331  const int widget_width = 600;
 
  332  const int total_height = 300;
 
  334  auto flags = WINPR_ASSERTING_INT_CAST(
 
  335      uint32_t, SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS);
 
  336  auto rc = SDL_CreateWindowAndRenderer(widget_width, total_height, flags, &_window, &_renderer);
 
  339    widget_log_error(rc, 
"SDL_CreateWindowAndRenderer");
 
  342  SDL_SetWindowTitle(_window, _title.c_str());
 
  345  SDL_Color res_bgcolor;
 
  346  switch (_type_active)
 
  349      res_bgcolor = infocolor;
 
  352      res_bgcolor = warncolor;
 
  355      res_bgcolor = errorcolor;
 
  359      res_bgcolor = backgroundcolor;
 
  363#if defined(WITH_SDL_IMAGE_DIALOGS) 
  364  std::string res_name;
 
  365  switch (_type_active)
 
  368      res_name = 
"icon_info.svg";
 
  371      res_name = 
"icon_warning.svg";
 
  374      res_name = 
"icon_error.svg";
 
  382  int height = (total_height - 3ul * vpadding) / 2ul;
 
  383  SDL_Rect iconRect{ hpadding, vpadding, widget_width / 4ul - 2ul * hpadding, height };
 
  384  widget_cfg_t icon{ textcolor,
 
  386                   { _renderer, iconRect,
 
  388  _list.emplace_back(std::move(icon));
 
  390  iconRect.y += height;
 
  392  widget_cfg_t logo{ textcolor,
 
  394                   { _renderer, iconRect,
 
  396                                              "FreeRDP_Icon.svg") } };
 
  397  _list.emplace_back(std::move(logo));
 
  399  SDL_Rect rect = { widget_width / 4ul, vpadding, widget_width * 3ul / 4ul,
 
  400                  total_height - 3ul * vpadding - widget_height };
 
  402  SDL_Rect rect = { hpadding, vpadding, widget_width - 2ul * hpadding,
 
  403                  total_height - 2ul * vpadding };
 
  406  widget_cfg_t w{ textcolor, backgroundcolor, { _renderer, rect, 
false } };
 
  407  w.widget.set_wrap(
true, widget_width);
 
  408  _list.emplace_back(std::move(w));
 
  409  rect.y += widget_height + vpadding;
 
  411  const std::vector<int> buttonids = { 1 };
 
  412  const std::vector<std::string> buttonlabels = { 
"cancel" };
 
  413  _buttons.populate(_renderer, buttonlabels, buttonids, widget_width,
 
  414                    total_height - widget_height - vpadding,
 
  415                    static_cast<Sint32
>(widget_width / 2), 
static_cast<Sint32
>(widget_height));
 
  416  _buttons.set_highlight(0);
 
  418  SDL_ShowWindow(_window);
 
  419  SDL_RaiseWindow(_window);
 
  424void SDLConnectionDialog::destroyWindow()
 
  428  SDL_DestroyRenderer(_renderer);
 
  429  SDL_DestroyWindow(_window);
 
  434bool SDLConnectionDialog::show(MsgType type, 
const char* fmt, va_list ap)
 
  436  std::lock_guard lock(_mux);
 
  437  _msg = print(fmt, ap);
 
  441bool SDLConnectionDialog::show(MsgType type)
 
  444  return sdl_push_user_event(SDL_USEREVENT_RETRY_DIALOG);
 
  447std::string SDLConnectionDialog::print(
const char* fmt, va_list ap)
 
  456      res.resize(WINPR_ASSERTING_INT_CAST(
size_t, size));
 
  460    WINPR_PRAGMA_DIAG_PUSH
 
  461    WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL
 
  462    size = vsnprintf(res.data(), res.size(), fmt, copy);
 
  463    WINPR_PRAGMA_DIAG_POP
 
  466  } 
while ((size > 0) && (
static_cast<size_t>(size) > res.size()));
 
  471bool SDLConnectionDialog::setTimer(Uint32 timeoutMS)
 
  473  std::lock_guard lock(_mux);
 
  476  _timer = SDL_AddTimer(timeoutMS, &SDLConnectionDialog::timeout, 
this);
 
  481void SDLConnectionDialog::resetTimer()
 
  484    SDL_RemoveTimer(_timer);
 
  488Uint32 SDLConnectionDialog::timeout([[maybe_unused]] Uint32 intervalMS, 
void* pvthis)
 
  492  self->_running = 
false;
 
  496SDLConnectionDialogHider::SDLConnectionDialogHider(freerdp* instance)
 
  501SDLConnectionDialogHider::SDLConnectionDialogHider(rdpContext* context)
 
  506SDLConnectionDialogHider::SDLConnectionDialogHider(
SDLConnectionDialog* dialog) : _dialog(dialog)
 
  510    _visible = _dialog->visible();
 
  518SDLConnectionDialogHider::~SDLConnectionDialogHider()
 
  520  if (_dialog && _visible)
 
  530  return get(instance->context);
 
  535  auto sdl = get_context(context);
 
  538  return sdl->connection_dialog.get();
 
static SDL_RWops * get(const std::string &type, const std::string &id)