1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "slint_internal.h" |
7 | |
8 | #ifndef SLINT_FEATURE_FREESTANDING |
9 | # include <thread> |
10 | # include <iostream> |
11 | #endif |
12 | |
13 | namespace slint { |
14 | #if !defined(DOXYGEN) |
15 | namespace platform { |
16 | class SkiaRenderer; |
17 | class SoftwareRenderer; |
18 | } |
19 | #endif |
20 | |
21 | namespace private_api { |
22 | /// Internal function that checks that the API that must be called from the main |
23 | /// thread is indeed called from the main thread, or abort the program otherwise |
24 | /// |
25 | /// Most API should be called from the main thread. When using thread one must |
26 | /// use slint::invoke_from_event_loop |
27 | inline void assert_main_thread() |
28 | { |
29 | #ifndef SLINT_FEATURE_FREESTANDING |
30 | # ifndef NDEBUG |
31 | static auto main_thread_id = std::this_thread::get_id(); |
32 | if (main_thread_id != std::this_thread::get_id()) { |
33 | std::cerr << "A function that should be only called from the main thread was called from a " |
34 | "thread." |
35 | << std::endl; |
36 | std::cerr << "Most API should be called from the main thread. When using thread one must " |
37 | "use slint::invoke_from_event_loop." |
38 | << std::endl; |
39 | std::abort(); |
40 | } |
41 | # endif |
42 | #endif |
43 | } |
44 | |
45 | using ItemTreeRc = vtable::VRc<cbindgen_private::ItemTreeVTable>; |
46 | using slint::LogicalPosition; |
47 | |
48 | class WindowAdapterRc |
49 | { |
50 | public: |
51 | explicit WindowAdapterRc(cbindgen_private::WindowAdapterRcOpaque adopted_inner) |
52 | { |
53 | assert_main_thread(); |
54 | cbindgen_private::slint_windowrc_clone(source: &adopted_inner, target: &inner); |
55 | } |
56 | WindowAdapterRc() { cbindgen_private::slint_windowrc_init(out: &inner); } |
57 | ~WindowAdapterRc() { cbindgen_private::slint_windowrc_drop(handle: &inner); } |
58 | WindowAdapterRc(const WindowAdapterRc &other) : WindowAdapterRc(other.inner) { } |
59 | WindowAdapterRc(WindowAdapterRc &&) = delete; |
60 | WindowAdapterRc &operator=(WindowAdapterRc &&) = delete; |
61 | WindowAdapterRc &operator=(const WindowAdapterRc &other) |
62 | { |
63 | assert_main_thread(); |
64 | if (this != &other) { |
65 | cbindgen_private::slint_windowrc_drop(handle: &inner); |
66 | cbindgen_private::slint_windowrc_clone(source: &other.inner, target: &inner); |
67 | } |
68 | return *this; |
69 | } |
70 | |
71 | void show() const { slint_windowrc_show(handle: &inner); } |
72 | void hide() const { slint_windowrc_hide(handle: &inner); } |
73 | bool is_visible() const { return slint_windowrc_is_visible(handle: &inner); } |
74 | |
75 | float scale_factor() const { return slint_windowrc_get_scale_factor(handle: &inner); } |
76 | void set_scale_factor(float value) const { slint_windowrc_set_scale_factor(handle: &inner, value); } |
77 | |
78 | cbindgen_private::ColorScheme color_scheme() const |
79 | { |
80 | return slint_windowrc_color_scheme(&inner); |
81 | } |
82 | bool () const |
83 | { |
84 | return slint_windowrc_supports_native_menu_bar(&inner); |
85 | } |
86 | |
87 | template<typename Component, typename SubMenu, typename Activated> |
88 | void (Component component, SubMenu , Activated activated) const |
89 | { |
90 | if (!supports_native_menu_bar()) { |
91 | return; |
92 | } |
93 | struct |
94 | { |
95 | Component component; |
96 | SubMenu ; |
97 | Activated activated; |
98 | }; |
99 | static cbindgen_private::MenuVTable = { |
100 | .drop = [](auto data) { delete reinterpret_cast<MenuWrapper *>(data.instance); }, |
101 | .sub_menu = |
102 | [](auto data, const cbindgen_private::MenuEntry *entry, |
103 | slint::SharedVector<cbindgen_private::MenuEntry> *result) { |
104 | auto wrapper = reinterpret_cast<MenuWrapper *>(data.instance); |
105 | auto model = wrapper->submenu(wrapper->component, entry); |
106 | result->clear(); |
107 | if (model) { |
108 | auto count = model->row_count(); |
109 | for (size_t i = 0; i < count; ++i) { |
110 | result->push_back(*model->row_data(i)); |
111 | } |
112 | } |
113 | }, |
114 | .activate = |
115 | [](auto data, const cbindgen_private::MenuEntry *entry) { |
116 | auto wrapper = reinterpret_cast<MenuWrapper *>(data.instance); |
117 | wrapper->activated(wrapper->component, *entry); |
118 | }, |
119 | }; |
120 | auto instance = new MenuWrapper { component, std::move(submenu), std::move(activated) }; |
121 | cbindgen_private::slint_windowrc_setup_native_menu_bar(&inner, &menu_vtable, instance); |
122 | } |
123 | |
124 | bool text_input_focused() const { return slint_windowrc_get_text_input_focused(handle: &inner); } |
125 | void set_text_input_focused(bool value) const |
126 | { |
127 | slint_windowrc_set_text_input_focused(handle: &inner, value); |
128 | } |
129 | |
130 | template<typename Component, typename ItemArray> |
131 | void unregister_item_tree(Component *c, ItemArray items) const |
132 | { |
133 | cbindgen_private::slint_unregister_item_tree( |
134 | component: vtable::VRef<cbindgen_private::ItemTreeVTable> { &Component::static_vtable, c }, |
135 | item_array: items, window_handle: &inner); |
136 | } |
137 | |
138 | void set_focus_item(const ItemTreeRc &component_rc, uint32_t item_index, bool set_focus) |
139 | { |
140 | cbindgen_private::ItemRc item_rc { .item_tree: component_rc, .index: item_index }; |
141 | cbindgen_private::slint_windowrc_set_focus_item(&inner, &item_rc, set_focus); |
142 | } |
143 | |
144 | void set_component(const cbindgen_private::ItemTreeWeak &weak) const |
145 | { |
146 | auto item_tree_rc = (*weak.lock()).into_dyn(); |
147 | slint_windowrc_set_component(handle: &inner, component: &item_tree_rc); |
148 | } |
149 | |
150 | template<typename Component, typename Parent, typename PosGetter> |
151 | uint32_t (const Parent *parent_component, PosGetter pos, |
152 | cbindgen_private::PopupClosePolicy close_policy, |
153 | cbindgen_private::ItemRc parent_item) const |
154 | { |
155 | auto = Component::create(parent_component); |
156 | auto p = pos(popup); |
157 | auto = popup.into_dyn(); |
158 | auto id = cbindgen_private::slint_windowrc_show_popup(handle: &inner, popup: &popup_dyn, position: p, close_on_click: close_policy, |
159 | parent_item: &parent_item, false); |
160 | popup->user_init(); |
161 | return id; |
162 | } |
163 | |
164 | void (uint32_t ) const |
165 | { |
166 | if (popup_id > 0) { |
167 | cbindgen_private::slint_windowrc_close_popup(&inner, popup_id); |
168 | } |
169 | } |
170 | |
171 | template<typename Component, typename SharedGlobals, typename InitFn> |
172 | uint32_t (SharedGlobals *globals, LogicalPosition pos, |
173 | cbindgen_private::ItemRc , InitFn init) const |
174 | { |
175 | // if (cbindgen_private::slint_windowrc_show_native_context_menu(....)) { return } |
176 | |
177 | auto = Component::create(globals); |
178 | init(&*popup); |
179 | auto = popup.into_dyn(); |
180 | auto id = cbindgen_private::slint_windowrc_show_popup( |
181 | &inner, &popup_dyn, pos, cbindgen_private::PopupClosePolicy::CloseOnClickOutside, |
182 | &context_menu_rc, true); |
183 | popup->user_init(); |
184 | return id; |
185 | } |
186 | |
187 | template<std::invocable<RenderingState, GraphicsAPI> F> |
188 | std::optional<SetRenderingNotifierError> set_rendering_notifier(F callback) const |
189 | { |
190 | auto actual_cb = [](RenderingState state, GraphicsAPI graphics_api, void *data) { |
191 | (*reinterpret_cast<F *>(data))(state, graphics_api); |
192 | }; |
193 | SetRenderingNotifierError err; |
194 | if (cbindgen_private::slint_windowrc_set_rendering_notifier( |
195 | handle: &inner, callback: actual_cb, |
196 | drop_user_data: [](void *user_data) { delete reinterpret_cast<F *>(user_data); }, |
197 | user_data: new F(std::move(callback)), error: &err)) { |
198 | return {}; |
199 | } else { |
200 | return err; |
201 | } |
202 | } |
203 | |
204 | // clang-format off |
205 | template<std::invocable F> |
206 | requires(std::is_convertible_v<std::invoke_result_t<F>, CloseRequestResponse>) |
207 | void on_close_requested(F callback) const |
208 | // clang-format on |
209 | { |
210 | auto actual_cb = [](void *data) { return (*reinterpret_cast<F *>(data))(); }; |
211 | cbindgen_private::slint_windowrc_on_close_requested( |
212 | handle: &inner, callback: actual_cb, drop_user_data: [](void *user_data) { delete reinterpret_cast<F *>(user_data); }, |
213 | user_data: new F(std::move(callback))); |
214 | } |
215 | |
216 | void request_redraw() const { cbindgen_private::slint_windowrc_request_redraw(handle: &inner); } |
217 | |
218 | slint::PhysicalPosition position() const |
219 | { |
220 | slint::PhysicalPosition pos; |
221 | cbindgen_private::slint_windowrc_position(handle: &inner, pos: &pos); |
222 | return pos; |
223 | } |
224 | |
225 | void set_logical_position(const slint::LogicalPosition &pos) |
226 | { |
227 | cbindgen_private::slint_windowrc_set_logical_position(handle: &inner, pos: &pos); |
228 | } |
229 | |
230 | void set_physical_position(const slint::PhysicalPosition &pos) |
231 | { |
232 | cbindgen_private::slint_windowrc_set_physical_position(handle: &inner, pos: &pos); |
233 | } |
234 | |
235 | slint::PhysicalSize size() const |
236 | { |
237 | return slint::PhysicalSize(cbindgen_private::slint_windowrc_size(handle: &inner)); |
238 | } |
239 | |
240 | void set_logical_size(const slint::LogicalSize &size) |
241 | { |
242 | cbindgen_private::slint_windowrc_set_logical_size(handle: &inner, size: &size); |
243 | } |
244 | |
245 | void set_physical_size(const slint::PhysicalSize &size) |
246 | { |
247 | cbindgen_private::slint_windowrc_set_physical_size(handle: &inner, size: &size); |
248 | } |
249 | |
250 | /// Send a pointer event to this window |
251 | void dispatch_pointer_event(const cbindgen_private::MouseEvent &event) |
252 | { |
253 | private_api::assert_main_thread(); |
254 | cbindgen_private::slint_windowrc_dispatch_pointer_event(handle: &inner, event); |
255 | } |
256 | |
257 | /// Registers a font by the specified path. The path must refer to an existing |
258 | /// TrueType font. |
259 | /// \returns an empty optional on success, otherwise an error string |
260 | inline std::optional<SharedString> register_font_from_path(const SharedString &path) |
261 | { |
262 | SharedString maybe_err; |
263 | cbindgen_private::slint_register_font_from_path(win: &inner, path: &path, error_str: &maybe_err); |
264 | if (!maybe_err.empty()) { |
265 | return maybe_err; |
266 | } else { |
267 | return {}; |
268 | } |
269 | } |
270 | |
271 | /// Registers a font by the data. The data must be valid TrueType font data. |
272 | /// \returns an empty optional on success, otherwise an error string |
273 | inline std::optional<SharedString> register_font_from_data(const uint8_t *data, std::size_t len) |
274 | { |
275 | SharedString maybe_err; |
276 | cbindgen_private::slint_register_font_from_data( |
277 | win: &inner, data: { const_cast<uint8_t *>(data), len }, error_str: &maybe_err); |
278 | if (!maybe_err.empty()) { |
279 | return maybe_err; |
280 | } else { |
281 | return {}; |
282 | } |
283 | } |
284 | |
285 | /// Registers a bitmap font for use with the software renderer. |
286 | inline void register_bitmap_font(const cbindgen_private::BitmapFont &font) |
287 | { |
288 | cbindgen_private::slint_register_bitmap_font(win: &inner, font_data: &font); |
289 | } |
290 | |
291 | inline float default_font_size() const |
292 | { |
293 | return cbindgen_private::slint_windowrc_default_font_size(&inner); |
294 | } |
295 | |
296 | /// \private |
297 | const cbindgen_private::WindowAdapterRcOpaque &handle() const { return inner; } |
298 | |
299 | private: |
300 | friend class slint::platform::SkiaRenderer; |
301 | friend class slint::platform::SoftwareRenderer; |
302 | cbindgen_private::WindowAdapterRcOpaque inner; |
303 | }; |
304 | |
305 | } |
306 | |
307 | /// This class represents a window towards the windowing system, that's used to render the |
308 | /// scene of a component. It provides API to control windowing system specific aspects such |
309 | /// as the position on the screen. |
310 | class Window |
311 | { |
312 | public: |
313 | /// \private |
314 | /// Internal function used by the generated code to construct a new instance of this |
315 | /// public API wrapper. |
316 | explicit Window(const private_api::WindowAdapterRc &windowrc) : inner(windowrc) { } |
317 | Window(const Window &other) = delete; |
318 | Window &operator=(const Window &other) = delete; |
319 | Window(Window &&other) = delete; |
320 | Window &operator=(Window &&other) = delete; |
321 | /// Destroys this window. Window instances are explicitly shared and reference counted. |
322 | /// If this window instance is the last one referencing the window towards the windowing |
323 | /// system, then it will also become hidden and destroyed. |
324 | ~Window() = default; |
325 | |
326 | /// Shows the window on the screen. An additional strong reference on the |
327 | /// associated component is maintained while the window is visible. |
328 | /// |
329 | /// Call hide() to make the window invisible again, and drop the additional |
330 | /// strong reference. |
331 | void show() |
332 | { |
333 | private_api::assert_main_thread(); |
334 | inner.show(); |
335 | } |
336 | /// Hides the window, so that it is not visible anymore. The additional strong |
337 | /// reference on the associated component, that was created when show() was called, is |
338 | /// dropped. |
339 | void hide() |
340 | { |
341 | private_api::assert_main_thread(); |
342 | inner.hide(); |
343 | } |
344 | |
345 | /// Returns the visibility state of the window. This function can return false even if you |
346 | /// previously called show() on it, for example if the user minimized the window. |
347 | bool is_visible() const |
348 | { |
349 | private_api::assert_main_thread(); |
350 | return inner.is_visible(); |
351 | } |
352 | |
353 | /// This function allows registering a callback that's invoked during the different phases of |
354 | /// rendering. This allows custom rendering on top or below of the scene. |
355 | /// |
356 | /// The provided callback must be callable with a slint::RenderingState and the |
357 | /// slint::GraphicsAPI argument. |
358 | /// |
359 | /// On success, the function returns a std::optional without value. On error, the function |
360 | /// returns the error code as value in the std::optional. |
361 | template<std::invocable<RenderingState, GraphicsAPI> F> |
362 | std::optional<SetRenderingNotifierError> set_rendering_notifier(F &&callback) const |
363 | { |
364 | private_api::assert_main_thread(); |
365 | return inner.set_rendering_notifier(std::forward<F>(callback)); |
366 | } |
367 | |
368 | /// This function allows registering a callback that's invoked when the user tries to close |
369 | /// a window. |
370 | /// The callback has to return a CloseRequestResponse. |
371 | // clang-format off |
372 | template<std::invocable F> |
373 | requires(std::is_convertible_v<std::invoke_result_t<F>, CloseRequestResponse>) |
374 | void on_close_requested(F &&callback) const |
375 | // clang-format on |
376 | { |
377 | private_api::assert_main_thread(); |
378 | return inner.on_close_requested(std::forward<F>(callback)); |
379 | } |
380 | |
381 | /// This function issues a request to the windowing system to redraw the contents of the window. |
382 | void request_redraw() const |
383 | { |
384 | private_api::assert_main_thread(); |
385 | inner.request_redraw(); |
386 | } |
387 | |
388 | /// Returns the position of the window on the screen, in physical screen coordinates and |
389 | /// including a window frame (if present). |
390 | slint::PhysicalPosition position() const |
391 | { |
392 | private_api::assert_main_thread(); |
393 | return inner.position(); |
394 | } |
395 | |
396 | /// Sets the position of the window on the screen, in physical screen coordinates and including |
397 | /// a window frame (if present). |
398 | /// Note that on some windowing systems, such as Wayland, this functionality is not available. |
399 | void set_position(const slint::LogicalPosition &pos) |
400 | { |
401 | private_api::assert_main_thread(); |
402 | inner.set_logical_position(pos); |
403 | } |
404 | /// Sets the position of the window on the screen, in physical screen coordinates and including |
405 | /// a window frame (if present). |
406 | /// Note that on some windowing systems, such as Wayland, this functionality is not available. |
407 | void set_position(const slint::PhysicalPosition &pos) |
408 | { |
409 | private_api::assert_main_thread(); |
410 | inner.set_physical_position(pos); |
411 | } |
412 | |
413 | /// Returns the size of the window on the screen, in physical screen coordinates and excluding |
414 | /// a window frame (if present). |
415 | slint::PhysicalSize size() const |
416 | { |
417 | private_api::assert_main_thread(); |
418 | return inner.size(); |
419 | } |
420 | |
421 | /// Resizes the window to the specified size on the screen, in logical pixels and excluding |
422 | /// a window frame (if present). |
423 | void set_size(const slint::LogicalSize &size) |
424 | { |
425 | private_api::assert_main_thread(); |
426 | inner.set_logical_size(size); |
427 | } |
428 | /// Resizes the window to the specified size on the screen, in physical pixels and excluding |
429 | /// a window frame (if present). |
430 | void set_size(const slint::PhysicalSize &size) |
431 | { |
432 | private_api::assert_main_thread(); |
433 | inner.set_physical_size(size); |
434 | } |
435 | |
436 | /// This function returns the scale factor that allows converting between logical and |
437 | /// physical pixels. |
438 | float scale_factor() const |
439 | { |
440 | private_api::assert_main_thread(); |
441 | return inner.scale_factor(); |
442 | } |
443 | |
444 | /// Returns if the window is currently fullscreen |
445 | bool is_fullscreen() const |
446 | { |
447 | private_api::assert_main_thread(); |
448 | return cbindgen_private::slint_windowrc_is_fullscreen(handle: &inner.handle()); |
449 | } |
450 | /// Set or unset the window to display fullscreen. |
451 | void set_fullscreen(bool fullscreen) |
452 | { |
453 | private_api::assert_main_thread(); |
454 | cbindgen_private::slint_windowrc_set_fullscreen(handle: &inner.handle(), value: fullscreen); |
455 | } |
456 | |
457 | /// Returns if the window is currently maximized |
458 | bool is_maximized() const |
459 | { |
460 | private_api::assert_main_thread(); |
461 | return cbindgen_private::slint_windowrc_is_maximized(handle: &inner.handle()); |
462 | } |
463 | /// Maximize or unmaximize the window. |
464 | void set_maximized(bool maximized) |
465 | { |
466 | private_api::assert_main_thread(); |
467 | cbindgen_private::slint_windowrc_set_maximized(handle: &inner.handle(), value: maximized); |
468 | } |
469 | |
470 | /// Returns if the window is currently minimized |
471 | bool is_minimized() const |
472 | { |
473 | private_api::assert_main_thread(); |
474 | return cbindgen_private::slint_windowrc_is_minimized(handle: &inner.handle()); |
475 | } |
476 | /// Minimize or unminimze the window. |
477 | void set_minimized(bool minimized) |
478 | { |
479 | private_api::assert_main_thread(); |
480 | cbindgen_private::slint_windowrc_set_minimized(handle: &inner.handle(), value: minimized); |
481 | } |
482 | |
483 | /// Dispatch a key press event to the scene. |
484 | /// |
485 | /// Use this when you're implementing your own backend and want to forward user input events. |
486 | /// |
487 | /// The \a text is the unicode representation of the key. |
488 | void dispatch_key_press_event(const SharedString &text) |
489 | { |
490 | private_api::assert_main_thread(); |
491 | cbindgen_private::slint_windowrc_dispatch_key_event( |
492 | handle: &inner.handle(), event_type: cbindgen_private::KeyEventType::KeyPressed, text: &text, repeat: false); |
493 | } |
494 | |
495 | /// Dispatch an auto-repeated key press event to the scene. |
496 | /// |
497 | /// Use this when you're implementing your own backend and want to forward user input events. |
498 | /// |
499 | /// The \a text is the unicode representation of the key. |
500 | void dispatch_key_press_repeat_event(const SharedString &text) |
501 | { |
502 | private_api::assert_main_thread(); |
503 | cbindgen_private::slint_windowrc_dispatch_key_event( |
504 | handle: &inner.handle(), event_type: cbindgen_private::KeyEventType::KeyPressed, text: &text, repeat: true); |
505 | } |
506 | |
507 | /// Dispatch a key release event to the scene. |
508 | /// |
509 | /// Use this when you're implementing your own backend and want to forward user input events. |
510 | /// |
511 | /// The \a text is the unicode representation of the key. |
512 | void dispatch_key_release_event(const SharedString &text) |
513 | { |
514 | private_api::assert_main_thread(); |
515 | cbindgen_private::slint_windowrc_dispatch_key_event( |
516 | handle: &inner.handle(), event_type: cbindgen_private::KeyEventType::KeyReleased, text: &text, repeat: false); |
517 | } |
518 | |
519 | /// Dispatches a pointer or mouse press event to the scene. |
520 | /// |
521 | /// Use this function when you're implementing your own backend and want to forward user |
522 | /// pointer/mouse events. |
523 | /// |
524 | /// \a pos represents the logical position of the pointer relative to the window. |
525 | /// \a button is the button that was pressed. |
526 | void dispatch_pointer_press_event(LogicalPosition pos, PointerEventButton button) |
527 | { |
528 | private_api::assert_main_thread(); |
529 | using slint::cbindgen_private::MouseEvent; |
530 | MouseEvent event { .tag = MouseEvent::Tag::Pressed, |
531 | .pressed = MouseEvent::Pressed_Body { .position = { .x: pos.x, .y: pos.y }, |
532 | .button = button, |
533 | .click_count = 0 } }; |
534 | inner.dispatch_pointer_event(event); |
535 | } |
536 | /// Dispatches a pointer or mouse release event to the scene. |
537 | /// |
538 | /// Use this function when you're implementing your own backend and want to forward user |
539 | /// pointer/mouse events. |
540 | /// |
541 | /// \a pos represents the logical position of the pointer relative to the window. |
542 | /// \a button is the button that was released. |
543 | void dispatch_pointer_release_event(LogicalPosition pos, PointerEventButton button) |
544 | { |
545 | private_api::assert_main_thread(); |
546 | using slint::cbindgen_private::MouseEvent; |
547 | MouseEvent event { .tag = MouseEvent::Tag::Released, |
548 | .released = MouseEvent::Released_Body { .position = { .x: pos.x, .y: pos.y }, |
549 | .button = button, |
550 | .click_count = 0 } }; |
551 | inner.dispatch_pointer_event(event); |
552 | } |
553 | /// Dispatches a pointer exit event to the scene. |
554 | /// |
555 | /// Use this function when you're implementing your own backend and want to forward user |
556 | /// pointer/mouse events. |
557 | /// |
558 | /// This event is triggered when the pointer exits the window. |
559 | void dispatch_pointer_exit_event() |
560 | { |
561 | private_api::assert_main_thread(); |
562 | using slint::cbindgen_private::MouseEvent; |
563 | MouseEvent event { .tag = MouseEvent::Tag::Exit, .moved = {} }; |
564 | inner.dispatch_pointer_event(event); |
565 | } |
566 | |
567 | /// Dispatches a pointer move event to the scene. |
568 | /// |
569 | /// Use this function when you're implementing your own backend and want to forward user |
570 | /// pointer/mouse events. |
571 | /// |
572 | /// \a pos represents the logical position of the pointer relative to the window. |
573 | void dispatch_pointer_move_event(LogicalPosition pos) |
574 | { |
575 | private_api::assert_main_thread(); |
576 | using slint::cbindgen_private::MouseEvent; |
577 | MouseEvent event { .tag = MouseEvent::Tag::Moved, |
578 | .moved = MouseEvent::Moved_Body { .position = { .x: pos.x, .y: pos.y } } }; |
579 | inner.dispatch_pointer_event(event); |
580 | } |
581 | |
582 | /// Dispatches a scroll (or wheel) event to the scene. |
583 | /// |
584 | /// Use this function when you're implementing your own backend and want to forward user wheel |
585 | /// events. |
586 | /// |
587 | /// \a parameter represents the logical position of the pointer relative to the window. |
588 | /// \a delta_x and \a delta_y represent the scroll delta values in the X and Y |
589 | /// directions in logical pixels. |
590 | void dispatch_pointer_scroll_event(LogicalPosition pos, float delta_x, float delta_y) |
591 | { |
592 | private_api::assert_main_thread(); |
593 | using slint::cbindgen_private::MouseEvent; |
594 | MouseEvent event { .tag = MouseEvent::Tag::Wheel, |
595 | .wheel = MouseEvent::Wheel_Body { .position = { .x: pos.x, .y: pos.y }, |
596 | .delta_x = delta_x, |
597 | .delta_y = delta_y } }; |
598 | inner.dispatch_pointer_event(event); |
599 | } |
600 | |
601 | /// Set the logical size of this window after a resize event |
602 | /// |
603 | /// The backend must send this event to ensure that the `width` and `height` property of the |
604 | /// root Window element are properly set. |
605 | void dispatch_resize_event(slint::LogicalSize s) |
606 | { |
607 | private_api::assert_main_thread(); |
608 | using slint::cbindgen_private::WindowEvent; |
609 | WindowEvent event { .resized = |
610 | WindowEvent::Resized_Body { .tag = WindowEvent::Tag::Resized, |
611 | .size = { .width: s.width, .height: s.height } } }; |
612 | cbindgen_private::slint_windowrc_dispatch_event(handle: &inner.handle(), event: &event); |
613 | } |
614 | |
615 | /// The window's scale factor has changed. This can happen for example when the display's |
616 | /// resolution changes, the user selects a new scale factor in the system settings, or the |
617 | /// window is moved to a different screen. Platform implementations should dispatch this event |
618 | /// also right after the initial window creation, to set the initial scale factor the windowing |
619 | /// system provided for the window. |
620 | void dispatch_scale_factor_change_event(float factor) |
621 | { |
622 | private_api::assert_main_thread(); |
623 | using slint::cbindgen_private::WindowEvent; |
624 | WindowEvent event { .scale_factor_changed = WindowEvent::ScaleFactorChanged_Body { |
625 | .tag = WindowEvent::Tag::ScaleFactorChanged, |
626 | .scale_factor = factor } }; |
627 | cbindgen_private::slint_windowrc_dispatch_event(handle: &inner.handle(), event: &event); |
628 | } |
629 | |
630 | /// The Window was activated or de-activated. |
631 | /// |
632 | /// The backend should dispatch this event with true when the window gains focus |
633 | /// and false when the window loses focus. |
634 | void dispatch_window_active_changed_event(bool active) |
635 | { |
636 | private_api::assert_main_thread(); |
637 | using slint::cbindgen_private::WindowEvent; |
638 | WindowEvent event { .window_active_changed = WindowEvent::WindowActiveChanged_Body { |
639 | .tag = WindowEvent::Tag::WindowActiveChanged, ._0 = active } }; |
640 | cbindgen_private::slint_windowrc_dispatch_event(handle: &inner.handle(), event: &event); |
641 | } |
642 | |
643 | /// The user requested to close the window. |
644 | /// |
645 | /// The backend should send this event when the user tries to close the window,for example by |
646 | /// pressing the close button. |
647 | /// |
648 | /// This will have the effect of invoking the callback set in Window::on_close_requested() and |
649 | /// then hiding the window depending on the return value of the callback. |
650 | void dispatch_close_requested_event() |
651 | { |
652 | private_api::assert_main_thread(); |
653 | using slint::cbindgen_private::WindowEvent; |
654 | WindowEvent event { .tag = WindowEvent::Tag::CloseRequested }; |
655 | cbindgen_private::slint_windowrc_dispatch_event(handle: &inner.handle(), event: &event); |
656 | } |
657 | |
658 | /// Returns true if there is an animation currently active on any property in the Window. |
659 | bool has_active_animations() const |
660 | { |
661 | private_api::assert_main_thread(); |
662 | return cbindgen_private::slint_windowrc_has_active_animations(handle: &inner.handle()); |
663 | } |
664 | |
665 | /// Takes a snapshot of the window contents and returns it as RGBA8 encoded pixel buffer. |
666 | /// |
667 | /// Note that this function may be slow to call as it may need to re-render the scene. |
668 | std::optional<SharedPixelBuffer<Rgba8Pixel>> take_snapshot() const |
669 | { |
670 | SharedPixelBuffer<Rgba8Pixel> result; |
671 | if (cbindgen_private::slint_windowrc_take_snapshot(&inner.handle(), &result.m_data, |
672 | &result.m_width, &result.m_height)) { |
673 | return result; |
674 | } else { |
675 | return {}; |
676 | } |
677 | } |
678 | |
679 | /// \private |
680 | private_api::WindowAdapterRc &window_handle() { return inner; } |
681 | /// \private |
682 | const private_api::WindowAdapterRc &window_handle() const { return inner; } |
683 | |
684 | private: |
685 | private_api::WindowAdapterRc inner; |
686 | }; |
687 | |
688 | } |
689 | |