FreeRDP
Loading...
Searching...
No Matches
sdl_connection_dialog_wrapper.cpp
1
21#include <sstream>
22
23#include <freerdp/freerdp.h>
24#include <freerdp/settings.h>
25#include <freerdp/log.h>
26
27#include "../sdl_utils.hpp"
28#include "sdl_connection_dialog.hpp"
29#include "sdl_connection_dialog_wrapper.hpp"
30
34
35SdlConnectionDialogWrapper::~SdlConnectionDialogWrapper() = default;
36
37void SdlConnectionDialogWrapper::create(rdpContext* context)
38{
39 const auto enabled =
40 freerdp_settings_get_bool(context->settings, FreeRDP_UseCommonStdioCallbacks);
41 _connection_dialog.reset();
42 if (!enabled)
43 _connection_dialog = std::make_unique<SDLConnectionDialog>(context);
44}
45
46void SdlConnectionDialogWrapper::destroy()
47{
48 _connection_dialog.reset();
49}
50
51bool SdlConnectionDialogWrapper::isRunning() const
52{
53 std::unique_lock lock(_mux);
54 /* Messages are queued here and handled on the main thread, so the dialog is still busy
55 * while the queue is not empty. Without this the event loop can leave before an error
56 * pushed by the RDP thread was ever shown. */
57 if (!_queue.empty())
58 return true;
59 if (!_connection_dialog)
60 return false;
61 return _connection_dialog->running();
62}
63
64bool SdlConnectionDialogWrapper::isVisible() const
65{
66 std::unique_lock lock(_mux);
67 if (!_connection_dialog)
68 return false;
69 return _connection_dialog->visible();
70}
71
72bool SdlConnectionDialogWrapper::handleEvent(const SDL_Event& event)
73{
74 std::unique_lock lock(_mux);
75 if (!_connection_dialog)
76 return false;
77 return _connection_dialog->handle(event);
78}
79
80WINPR_ATTR_FORMAT_ARG(1, 0)
81static std::string format(WINPR_FORMAT_ARG const char* fmt, va_list ap)
82{
83 va_list ap1 = {};
84 va_copy(ap1, ap);
85 const int size = vsnprintf(nullptr, 0, fmt, ap1);
86 va_end(ap1);
87
88 if (size < 0)
89 return "";
90
91 std::string msg;
92 msg.resize(static_cast<size_t>(size) + 1);
93
94 va_list ap2 = {};
95 va_copy(ap2, ap);
96 std::ignore = vsnprintf(msg.data(), msg.size(), fmt, ap2);
97 va_end(ap2);
98 return msg;
99}
100
101void SdlConnectionDialogWrapper::setTitle(const char* fmt, ...)
102{
103 va_list ap = {};
104 va_start(ap, fmt);
105 setTitle(format(fmt, ap));
106 va_end(ap);
107}
108
109void SdlConnectionDialogWrapper::setTitle(const std::string& title)
110{
111 push(EventArg{ title });
112}
113
114void SdlConnectionDialogWrapper::showInfo(const char* fmt, ...)
115{
116 va_list ap = {};
117 va_start(ap, fmt);
118 showInfo(format(fmt, ap));
119 va_end(ap);
120}
121
122void SdlConnectionDialogWrapper::showInfo(const std::string& info)
123{
124 show(MSG_INFO, info);
125}
126
127void SdlConnectionDialogWrapper::showWarn(const char* fmt, ...)
128{
129 va_list ap = {};
130 va_start(ap, fmt);
131 showWarn(format(fmt, ap));
132 va_end(ap);
133}
134
135void SdlConnectionDialogWrapper::showWarn(const std::string& info)
136{
137 show(MSG_WARN, info);
138}
139
140void SdlConnectionDialogWrapper::showError(const char* fmt, ...)
141{
142 va_list ap = {};
143 va_start(ap, fmt);
144 showError(format(fmt, ap));
145 va_end(ap);
146}
147
148void SdlConnectionDialogWrapper::showError(const std::string& error)
149{
150 show(MSG_ERROR, error);
151}
152
153void SdlConnectionDialogWrapper::show(SdlConnectionDialogWrapper::MsgType type,
154 const std::string& msg)
155{
156 push({ type, msg, true });
157}
158
159void SdlConnectionDialogWrapper::show(bool visible)
160{
161 push(EventArg{ visible });
162}
163
164void SdlConnectionDialogWrapper::handleShow()
165{
166 std::unique_lock lock(_mux);
167 while (!_queue.empty())
168 {
169 auto arg = _queue.front();
170 _queue.pop();
171
172 if (arg.hasTitle() && _connection_dialog)
173 {
174 std::ignore = _connection_dialog->setTitle(arg.title().c_str());
175 }
176
177 if (arg.hasType() && arg.hasMessage())
178 {
179 switch (arg.type())
180 {
181 case SdlConnectionDialogWrapper::MSG_INFO:
182 if (_connection_dialog)
183 std::ignore = _connection_dialog->showInfo(arg.message().c_str());
184 else
185 WLog_Print(_log, WLOG_INFO, "%s", arg.message().c_str());
186 break;
187 case SdlConnectionDialogWrapper::MSG_WARN:
188 if (_connection_dialog)
189 std::ignore = _connection_dialog->showWarn(arg.message().c_str());
190 else
191 WLog_Print(_log, WLOG_WARN, "%s", arg.message().c_str());
192 break;
193 case SdlConnectionDialogWrapper::MSG_ERROR:
194 if (_connection_dialog)
195 std::ignore = _connection_dialog->showError(arg.message().c_str());
196 else
197 WLog_Print(_log, WLOG_ERROR, "%s", arg.message().c_str());
198 break;
199 default:
200 break;
201 }
202 }
203
204 if (arg.hasVisibility() && _connection_dialog)
205 {
206 if (arg.visible())
207 std::ignore = _connection_dialog->show();
208 else
209 std::ignore = _connection_dialog->hide();
210 }
211 }
212}
213
214void SdlConnectionDialogWrapper::push(EventArg&& arg)
215{
216 {
217 std::unique_lock lock(_mux);
218 _queue.push(std::move(arg));
219 }
220
221 auto rc = SDL_RunOnMainThread(
222 [](void* user)
223 {
224 auto dlg = static_cast<SdlConnectionDialogWrapper*>(user);
225 dlg->handleShow();
226 },
227 this, false);
228 if (!rc)
229 SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "[%s] SDL_RunOnMainThread failed with %s",
230 __func__, SDL_GetError());
231}
232
233SdlConnectionDialogWrapper::EventArg::EventArg(bool visible) : _visible(visible), _mask(8)
234{
235}
236
237SdlConnectionDialogWrapper::EventArg::EventArg(const std::string& title) : _title(title), _mask(1)
238{
239}
240
241SdlConnectionDialogWrapper::EventArg::EventArg(MsgType type, const std::string& msg, bool visible)
242 : _message(msg), _type(type), _visible(visible), _mask(14)
243{
244}
245
246bool SdlConnectionDialogWrapper::EventArg::hasTitle() const
247{
248 return _mask & 0x01;
249}
250
251const std::string& SdlConnectionDialogWrapper::EventArg::title() const
252{
253 return _title;
254}
255
256bool SdlConnectionDialogWrapper::EventArg::hasMessage() const
257{
258 return _mask & 0x02;
259}
260
261const std::string& SdlConnectionDialogWrapper::EventArg::message() const
262{
263 return _message;
264}
265
266bool SdlConnectionDialogWrapper::EventArg::hasType() const
267{
268 return _mask & 0x04;
269}
270
271SdlConnectionDialogWrapper::MsgType SdlConnectionDialogWrapper::EventArg::type() const
272{
273 return _type;
274}
275
276bool SdlConnectionDialogWrapper::EventArg::hasVisibility() const
277{
278 return _mask & 0x08;
279}
280
281bool SdlConnectionDialogWrapper::EventArg::visible() const
282{
283 return _visible;
284}
285
286std::string SdlConnectionDialogWrapper::EventArg::str() const
287{
288 std::stringstream ss;
289 ss << "{ title:" << _title << ", message:" << _message << ", type:" << _type
290 << ", visible:" << _visible << ", mask:" << _mask << "}";
291 return ss.str();
292}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.