FreeRDP
Loading...
Searching...
No Matches
SdlInputWidgetPairList Class Reference

#include <sdl_input_widget_pair_list.hpp>

Inheritance diagram for SdlInputWidgetPairList:
Collaboration diagram for SdlInputWidgetPairList:

Public Member Functions

 SdlInputWidgetPairList (const std::string &title, const std::vector< std::string > &labels, const std::vector< std::string > &initial, const std::vector< Uint32 > &flags, ssize_t selected=-1)
 
 SdlInputWidgetPairList (const SdlInputWidgetPairList &other)=delete
 
 SdlInputWidgetPairList (SdlInputWidgetPairList &&other)=delete
 
SdlInputWidgetPairList & operator= (const SdlInputWidgetPairList &other)=delete
 
SdlInputWidgetPairList & operator= (SdlInputWidgetPairList &&other)=delete
 
int run (std::vector< std::string > &result)
 
void parent (SDL_Window *parent)
 
- Public Member Functions inherited from SdlWidgetList
 SdlWidgetList (const SdlWidgetList &other)=delete
 
 SdlWidgetList (SdlWidgetList &&other)=delete
 
SdlWidgetList & operator= (const SdlWidgetList &other)=delete
 
SdlWidgetList & operator= (SdlWidgetList &&other)=delete
 
virtual bool reset (const std::string &title, size_t width, size_t height)
 
virtual bool visible () const
 

Protected Member Functions

bool updateInternal () override
 
ssize_t get_index (const SDL_MouseButtonEvent &button)
 
- Protected Member Functions inherited from SdlWidgetList
bool update ()
 
virtual bool clearWindow ()
 

Additional Inherited Members

- Protected Attributes inherited from SdlWidgetList
std::shared_ptr< SDL_Window > _window
 
std::shared_ptr< SDL_Renderer > _renderer
 
SdlButtonList _buttons
 
SDL_Color _backgroundcolor { 0x38, 0x36, 0x35, 0xff }
 

Detailed Description

FreeRDP: A Remote Desktop Protocol Implementation SDL Client helper dialogs

Copyright 2025 Armin Novak armin.nosp@m..nov.nosp@m.ak@th.nosp@m.inca.nosp@m.st.co.nosp@m.m Copyright 2025 Thincast Technologies GmbH

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Definition at line 30 of file sdl_input_widget_pair_list.hpp.

Constructor & Destructor Documentation

◆ SdlInputWidgetPairList()

SdlInputWidgetPairList::SdlInputWidgetPairList ( const std::string &  title,
const std::vector< std::string > &  labels,
const std::vector< std::string > &  initial,
const std::vector< Uint32 > &  flags,
ssize_t  selected = -1 
)

Definition at line 32 of file sdl_input_widget_pair_list.cpp.

36{
37 assert(labels.size() == initial.size());
38 assert(labels.size() == flags.size());
39 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
40 const std::vector<std::string> buttonlabels = { "accept", "cancel" };
41
42 const size_t widget_width = 300;
43 const size_t widget_height = 50;
44
45 const size_t total_width = widget_width + widget_width;
46 const size_t input_height = labels.size() * (widget_height + vpadding) + vpadding;
47 const size_t total_height = input_height + widget_height;
48 assert(total_width <= INT32_MAX);
49 assert(total_height <= INT32_MAX);
50
51 if (reset(title, total_width, total_height))
52 {
53 for (size_t x = 0; x < labels.size(); x++)
54 {
55 auto widget =
56 std::make_shared<SdlInputWidgetPair>(_renderer, labels.at(x), initial.at(x),
57 flags.at(x), x, widget_width, widget_height);
58 m_list.emplace_back(widget);
59 }
60
61 std::ignore = _buttons.populate(
62 _renderer, buttonlabels, buttonids, total_width, static_cast<Sint32>(input_height),
63 static_cast<Sint32>(widget_width), static_cast<Sint32>(widget_height));
64 _buttons.set_highlight(0);
65 m_currentActiveTextInput = selected;
66 }
67}

◆ ~SdlInputWidgetPairList()

SdlInputWidgetPairList::~SdlInputWidgetPairList ( )
override

Definition at line 114 of file sdl_input_widget_pair_list.cpp.

115{
116 m_list.clear();
117 _buttons.clear();
118}

Member Function Documentation

◆ get_index()

ssize_t SdlInputWidgetPairList::get_index ( const SDL_MouseButtonEvent &  button)
protected

Definition at line 131 of file sdl_input_widget_pair_list.cpp.

132{
133 const auto x = button.x;
134 const auto y = button.y;
135 for (size_t i = 0; i < m_list.size(); i++)
136 {
137 auto& cur = m_list.at(i);
138 auto r = cur->input_rect();
139
140 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
141 return WINPR_ASSERTING_INT_CAST(ssize_t, i);
142 }
143 return -1;
144}

◆ parent()

void SdlInputWidgetPairList::parent ( SDL_Window *  parent)

Definition at line 340 of file sdl_input_widget_pair_list.cpp.

341{
342 if (!parent)
343 return;
344 SDL_SetWindowParent(_window.get(), parent);
345 SDL_SetWindowModal(_window.get(), true);
346}

◆ run()

int SdlInputWidgetPairList::run ( std::vector< std::string > &  result)

Definition at line 146 of file sdl_input_widget_pair_list.cpp.

147{
148 int res = -1;
149 ssize_t LastActiveTextInput = -1;
150 m_currentActiveTextInput = next(m_currentActiveTextInput);
151
152 if (!_window || !_renderer)
153 return -2;
154
155 if (!SDL_StartTextInput(_window.get()))
156 return -3;
157
158 std::optional<SDL_Event> forward;
159 try
160 {
161 bool running = true;
162 while (running)
163 {
164 if (!update())
165 throw std::exception();
166
167 SDL_Event event = {};
168 if (!SDL_WaitEventTimeout(&event, 30))
169 continue;
170 do
171 {
172 switch (event.type)
173 {
174 case SDL_EVENT_KEY_UP:
175 {
176 switch (event.key.key)
177 {
178 case SDLK_BACKSPACE:
179 {
180 auto cur = get(m_currentActiveTextInput);
181 if (cur)
182 {
183 if ((event.key.mod & SDL_KMOD_CTRL) != 0)
184 {
185 if (!cur->set_str(""))
186 throw std::exception();
187 }
188 else
189 {
190 if (!cur->remove_str(1))
191 throw std::exception();
192 }
193 }
194 }
195 break;
196 case SDLK_TAB:
197 m_currentActiveTextInput = next(m_currentActiveTextInput);
198 break;
199 case SDLK_RETURN:
200 case SDLK_RETURN2:
201 case SDLK_KP_ENTER:
202 running = false;
203 res = INPUT_BUTTON_ACCEPT;
204 break;
205 case SDLK_ESCAPE:
206 running = false;
207 res = INPUT_BUTTON_CANCEL;
208 break;
209 case SDLK_V:
210 if ((event.key.mod & SDL_KMOD_CTRL) != 0)
211 {
212 auto cur = get(m_currentActiveTextInput);
213 if (cur)
214 {
215 auto text = SDL_GetClipboardText();
216 if (!cur->set_str(text))
217 throw std::exception();
218 }
219 }
220 break;
221 default:
222 break;
223 }
224 }
225 break;
226 case SDL_EVENT_TEXT_INPUT:
227 {
228 auto cur = get(m_currentActiveTextInput);
229 if (cur)
230 {
231 if (!cur->append_str(event.text.text))
232 throw std::exception();
233 }
234 }
235 break;
236 case SDL_EVENT_MOUSE_MOTION:
237 {
238 auto TextInputIndex = get_index(event.button);
239 for (auto& cur : m_list)
240 {
241 cur->set_mouseover(false);
242 }
243 if (TextInputIndex >= 0)
244 {
245 auto& cur = m_list.at(static_cast<size_t>(TextInputIndex));
246 cur->set_mouseover(true);
247 }
248
249 _buttons.set_mouseover(event.button.x, event.button.y);
250 }
251 break;
252 case SDL_EVENT_MOUSE_BUTTON_DOWN:
253 {
254 auto val = get_index(event.button);
255 if (valid(val))
256 m_currentActiveTextInput = val;
257
258 auto button = _buttons.get_selected(event.button);
259 if (button)
260 {
261 running = false;
262 if (button->id() == INPUT_BUTTON_CANCEL)
263 res = INPUT_BUTTON_CANCEL;
264 else
265 res = INPUT_BUTTON_ACCEPT;
266 }
267 }
268 break;
269 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
270 /* Closing any window cancels the dialog. The event of another
271 * window is queued again once the dialog is done, so the main
272 * loop still handles it. */
273 if (event.window.windowID != SDL_GetWindowID(_window.get()))
274 forward = event;
275 res = INPUT_BUTTON_CANCEL;
276 running = false;
277 break;
278 case SDL_EVENT_WINDOW_OCCLUDED:
279 case SDL_EVENT_WINDOW_MINIMIZED:
280 case SDL_EVENT_WINDOW_DESTROYED:
281 /* Only events of our own window cancel the dialog. Hiding the
282 * connection dialog for this prompt destroys its window, and that
283 * event is still queued when this loop starts. */
284 if (event.window.windowID != SDL_GetWindowID(_window.get()))
285 break;
286 res = INPUT_BUTTON_CANCEL;
287 running = false;
288 break;
289 case SDL_EVENT_TERMINATING:
290 case SDL_EVENT_QUIT:
291 res = INPUT_BUTTON_CANCEL;
292 running = false;
293 break;
294 default:
295 break;
296 }
297 } while (running && SDL_PollEvent(&event));
298
299 if (LastActiveTextInput != m_currentActiveTextInput)
300 {
301 LastActiveTextInput = m_currentActiveTextInput;
302 }
303
304 for (auto& cur : m_list)
305 {
306 if (!cur->set_highlight(false))
307 throw std::exception();
308 }
309 auto cur = get(m_currentActiveTextInput);
310 if (cur)
311 {
312 if (!cur->set_highlight(true))
313 throw std::exception();
314 }
315 }
316
317 for (auto& cur : m_list)
318 result.push_back(cur->value());
319 }
320 catch (...)
321 {
322 res = -2;
323 }
324
325 /* Drop the input that was meant for the dialog, so it does not reach the session.
326 * Other events, such as window and clipboard events, are still handled. */
327 SDL_PumpEvents();
328 SDL_FlushEvents(SDL_EVENT_KEY_DOWN, SDL_EVENT_MOUSE_REMOVED);
329 SDL_FlushEvents(SDL_EVENT_FINGER_DOWN, SDL_EVENT_FINGER_CANCELED);
330 SDL_FlushEvents(SDL_EVENT_PEN_PROXIMITY_IN, SDL_EVENT_PEN_AXIS);
331 if (forward)
332 std::ignore = SDL_PushEvent(&*forward);
333
334 if (!SDL_StopTextInput(_window.get()))
335 return -4;
336
337 return res;
338}

◆ updateInternal()

bool SdlInputWidgetPairList::updateInternal ( )
overrideprotectedvirtual

Implements SdlWidgetList.

Definition at line 120 of file sdl_input_widget_pair_list.cpp.

121{
122 for (auto& btn : m_list)
123 {
124 if (!btn->update())
125 return false;
126 }
127
128 return true;
129}

The documentation for this class was generated from the following files: