opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
app.h
Go to the documentation of this file.
1#pragma once
2
15
16#include <concepts>
17#include <filesystem>
18#include <functional>
19#include <future>
20#include <initializer_list>
21#include <memory>
22#include <optional>
23#include <span>
24#include <string>
25#include <string_view>
26#include <typeinfo>
27#include <utility>
28
29namespace osc { class AppMetadata; }
30namespace osc { class AppSettings; }
31namespace osc { class Cursor; }
32namespace osc { class Event; }
33namespace osc { class FileDialogResponse; }
34namespace osc { class Widget; }
35
36namespace osc
37{
38 class AppPrivate;
39
40 // top-level application class
41 //
42 // the top-level osc process holds one copy of this class, which maintains all
43 // application-wide systems (windowing, event pumping, timers, graphics,
44 // logging, etc.)
45 class App {
46 public:
47
48 template<std::destructible T, typename... Args>
49 requires std::constructible_from<T, Args&&...>
50 static std::shared_ptr<T> singleton(Args&&... args)
51 {
52 const auto singleton_constructor = [args_tuple = std::make_tuple(std::forward<Args>(args)...)]() mutable -> std::shared_ptr<void>
53 {
54 return std::apply([](auto&&... inner_args) -> std::shared_ptr<void>
55 {
56 return std::make_shared<T>(std::forward<Args>(inner_args)...);
57 }, std::move(args_tuple));
58 };
59
60 return std::static_pointer_cast<T>(App::upd().upd_singleton(typeid(T), singleton_constructor));
61 }
62
63 // returns the currently-active application global
64 static App& upd();
65 static const App& get();
66 static App* try_upd();
67 static const App* try_get();
68
69 static const AppSettings& settings();
71
72 // returns a full filesystem path to a (runtime- and configuration-dependent) application resource,
73 // or `std::nullopt` if the `ResourcePath` cannot be resolved to a filesystem location.
74 static std::optional<std::filesystem::path> resource_filepath(const ResourcePath&);
75
76 // returns the contents of a runtime resource in the `resources/` dir as a string
77 static std::string slurp(const ResourcePath&);
78
79 // returns an opened stream to the given application resource
81
82 // returns the top- (application-)level resource loader
84
85 // Convenience function that initializes an instance of `App` according to the target
86 // platform's requirements and immediately starts showing the given `TWidget` according
87 // to the target platform's main application loop requirements.
88 //
89 // This function should only be called once per-process, and should be the last statement
90 // in the application's `main` function (i.e. `return App::main(...)` from `main`), because
91 // the target platform might have unusual lifetime behavior (e.g. web browsers may continue
92 // to run after `main` has completed).
93 template<std::derived_from<Widget> TWidget, typename... Args>
94 requires std::constructible_from<TWidget, Args&&...>
95 static int main(const AppMetadata& metadata, Args&&... args)
96 {
97 // Pack the `TWidget` constructor arguments into a type-erased `std::function` and defer
98 // to the internal implementation.
99 return main_internal(metadata, [args_tuple = std::make_tuple(std::forward<Args>(args)...)]() mutable -> std::unique_ptr<Widget>
100 {
101 return std::apply([](auto&&... inner_args) -> std::unique_ptr<Widget>
102 {
103 return std::make_unique<TWidget>(std::forward<Args>(inner_args)...);
104 }, std::move(args_tuple));
105 });
106 }
107
108 // constructs an `App` from a default-constructed `AppMetadata`
110
111 // constructs an app by initializing it from a settings at the default app settings location
112 //
113 // this also sets the currently-active application global (i.e. `App::upd()` and `App::get()` will work)
114 explicit App(const AppMetadata&);
115 App(const App&) = delete;
120
121 // returns the application's metadata (name, organization, repo URL, version, etc.)
123
124 // returns a human-readable (i.e. may be long-form) representation of the application name
126
127 // returns a string representation of the name of the application, its version, and
128 // its build id (usually useful for logging, file headers, etc.)
130
131 // If running on a filesystem, returns the filesystem path of the calling
132 // process's executable. Otherwise, returns `std::nullopt`.
134
135 // returns the filesystem path to a (usually, writable) user-specific directory for the
136 // application
138
143 {
144 setup_main_loop(std::make_unique<TWidget>(std::forward<Args>(args)...));
145 }
148
149 // Adds `event`, with the widget `receiver` as the receiver of `event`, to the event
150 // queue and returns immediately.
151 //
152 // When the event is popped off the event queue, it is processed as-if by calling
153 // `notify(receiver, *event)`. See the documentation for `notify` for a detailed
154 // description of event processing.
155 static void post_event(Widget& receiver, std::unique_ptr<Event> event);
156 template<std::derived_from<Event> TEvent, typename... Args>
157 requires std::constructible_from<TEvent, Args&&...>
158 static void post_event(Widget& receiver, Args&&... args)
159 {
160 return post_event(receiver, std::make_unique<TEvent>(std::forward<Args>(args)...));
161 }
162
163 // Immediately sends `event` to `receiver` as-if by calling `return receiver.on_event(event)`.
164 //
165 // This application-level event handler behaves differently from directly calling
166 // `receiver.on_event(event)` because it also handles event propagation. The implementation
167 // will call `Widget::on_event(Event&)` for each `Widget` from `receiver` to the root widget
168 // until either a widget in that chain returns `true` or `event.propagates()` is `false`.
170 template<std::derived_from<Event> TEvent, typename... Args>
171 requires std::constructible_from<TEvent, Args&&...>
172 static bool notify(Widget& receiver, Args&&... args)
173 {
174 TEvent event{std::forward<Args>(args)...};
175 return notify(receiver, event);
176 }
177
178 // Sets the currently active widget, creates an application loop, then starts showing
179 // the supplied widget
180 //
181 // this function only returns once the active widget calls `app.request_quit()`, or an exception
182 // is thrown. Use `set_widget` in combination with `handle_one_frame` if you want to use your
183 // own application loop
184 //
185 // this is effectively sugar over:
186 //
187 // set_widget(...);
188 // setup_main_loop();
189 // while (true) {
190 // do_main_loop_step(...);
191 // }
192 // teardown_main_loop();
193 //
194 // which you may need to write yourself if your loop is external (e.g. from a browser's event queue)
195 void show(std::unique_ptr<Widget>);
196
197 // constructs `TWidget` with `Args` and starts `show`ing it
198 template<std::derived_from<Widget> TWidget, typename... Args>
199 requires std::constructible_from<TWidget, Args&&...>
200 void show(Args&&... args)
201 {
202 show(std::make_unique<TWidget>(std::forward<Args>(args)...));
203 }
204
205 // requests that the application's main window transitions to a new
206 // top-level widget
207 //
208 // this is merely a *request* that the `App` will fulfill at a later
209 // time (usually, after it's done handling some part of the top-level
210 // application loop)
211 //
212 // When the App decides it's ready to transition to the new widget, it will:
213 //
214 // - unmount the current widget
215 // - destroy the current widget
216 // - mount the new widget
217 // - make the new widget the current top-level widget
218 void request_transition(std::unique_ptr<Widget>);
219
220 // constructs `TWidget` with `Args` then requests that the app transitions to it
221 template<std::derived_from<Widget> TWidget, typename... Args>
222 requires std::constructible_from<TWidget, Args&&...>
224 {
225 request_transition(std::make_unique<TWidget>(std::forward<Args>(args)...));
226 }
227
228 // requests that the app quits
229 //
230 // this is merely a *request* that the `App` will fulfill at a later
231 // time (usually, after it's done handling some part of the top-level
232 // application loop)
234
235 // Requests that the given function is executed on the main thread.
236 //
237 // Main thread means "the thread that's responsible for pumping the main event queue".
238 // Usually, this is whichever thread is calling `show` or `do_main_loop_step`. The
239 // callback may NOT be called if the application quits, or is destructed before being
240 // able to process all events.
241 void request_invoke_on_main_thread(std::function<void()>);
242
243 // Gets/sets the directory that should be shown to the user if a call to one of the
244 // `prompt_user*` files does not provide an `initial_directory_to_show`. If this
245 // fallback isn't provided, the implementation will fall back to whatever the
246 // OS's default behavior is (typically, it remembers the user's last usage).
247 //
248 // This fallback is activated until a call to `prompt_user*` is made without the
249 // user cancelling out of the dialog (i.e. if the user cancels then this fallback
250 // will remain in-place).
251 std::optional<std::filesystem::path> prompt_initial_directory_to_show_fallback();
252 void set_prompt_initial_directory_to_show_fallback(std::optional<std::filesystem::path>);
253
254 // Prompts the user to select file(s) that they would like to open.
255 //
256 // - `callback` is called from the ui thread by the implementation when the user chooses
257 // a file, cancels, or there's an error. It is implementation-defined whether `callback`
258 // is called immediately or as part of pumping the application event queue. `callback`
259 // may not be called if the application quits/destructs prematurely.
260 //
261 // - `filters` should be a sequence of permitted `FileDialogFilter`s, which will constrain
262 // which files the user can select in the dialog in an implementation-defined way.
263 //
264 // - `initial_directory_to_show` should be a filesystem path to a directory that should
265 // initially be shown to the user. If it isn't provided, then an implementation-defined
266 // directory will be shown (e.g. based on previous user choices, OS defaults, etc.).
268 std::function<void(FileDialogResponse&&)> callback,
269 std::span<const FileDialogFilter> filters = {},
270 std::optional<std::filesystem::path> initial_directory_to_show = std::nullopt,
271 bool allow_many = false
272 );
274 std::function<void(FileDialogResponse&&)> callback,
275 std::initializer_list<const FileDialogFilter> filters = {},
276 std::optional<std::filesystem::path> initial_directory_to_show = std::nullopt,
277 bool allow_many = false)
278 {
280 std::move(callback),
281 std::span<const FileDialogFilter>{filters},
282 std::move(initial_directory_to_show),
284 );
285 }
286
287 // Prompts the user to select a single existing directory.
288 //
289 // - `callback` is called from the ui thread by the implementation when the user chooses
290 // a file, cancels, or there's an error. It is implementation-defined whether `callback`
291 // is called immediately or as part of pumping the application event queue. `callback` may
292 // not be called if the application quits/destructs prematurely.
293 //
294 // - `initial_directory_to_show` should be a filesystem path to a directory that should
295 // initially be shown to the user. If it isn't provided, then an implementation-defined
296 // directory will be shown (e.g. based on previous user choices, OS defaults, etc.).
297 //
298 // - `allow_many` indicates whether the user can select multiple directories. However, not
299 // all implementations support this option.
301 std::function<void(FileDialogResponse&&)> callback,
302 std::optional<std::filesystem::path> initial_directory_to_show = std::nullopt,
303 bool allow_many = false
304 );
305
306 // Prompts the user to select a new or existing filesystem path where they would like
307 // to save a file.
308 //
309 // - `callback` is called from the main thread by the implementation when the user chooses
310 // a file, cancels or there's an error. It is implementation-defined whether `callback` is
311 // called immediately, or as part of pumping the application event queue `callback` may
312 // not be called if the application quits/destructs prematurely.
313 //
314 // - `filters` should be a sequence of permitted `FileDialogFilter`s, which will constrain
315 // which file extensions the user can use in the dialog in an implementation-defined way.
316 //
317 // - `initial_directory_to_show` should be a filesystem path to a directory that should
318 // initially be shown to the user. If it isn't provided, then an implementation-defined
319 // directory will be shown (e.g. based on previous user choices, OS defaults, etc.).
321 std::function<void(FileDialogResponse&&)> callback,
322 std::span<const FileDialogFilter> filters = {},
323 std::optional<std::filesystem::path> initial_directory_to_show = std::nullopt
324 );
326 std::function<void(FileDialogResponse&&)> callback,
327 std::initializer_list<const FileDialogFilter> filters = {},
328 std::optional<std::filesystem::path> initial_directory_to_show = std::nullopt)
329 {
331 std::move(callback),
332 std::span{filters},
334 );
335 }
336
337 // Prompts a user to select a new or existing filesystem path where they would like
338 // to save the file, with the option to file to have a specific extension - even if the
339 // user types a filename without the extension into the dialog.
340 //
341 // - `callback` is called when either the user selects a file or cancels out of the dialog.
342 // If provided, the given path will always end with the specified extension. `std::nullopt`
343 // is sent through the callback when the user cancels out of the dialog.
344 //
345 // - `maybe_extension` can be `std::nullopt`, meaning "don't filter by extension", or a single
346 // extension (e.g. "blend").
347 //
348 // - `maybe_initial_directory_to_open` can be `std::nullopt`, meaning "use a system-defined default"
349 // or a directory to initially show to the user when the prompt opens.
351 std::function<void(std::optional<std::filesystem::path>)> callback,
352 std::optional<std::string_view> maybe_extension = std::nullopt,
353 std::optional<std::filesystem::path> initial_directory_to_show = std::nullopt
354 );
355
356 // Pushes the given cursor onto the application-wide cursor stack, making it
357 // the currently-active cursor until it is either popped, via `pop_cursor_override`,
358 // or another cursor is pushed.
361
362 // returns the ID of the main window
364
365 // Returns the dimensions of the main application window in device-independent pixels.
367
368 // Requests that the main window dimensions are set to the given dimensions in
369 // device-independent pixels.
370 //
371 // This is only a request. Therefore, it is not guaranteed that `main_window_dimensions`
372 // returns the dimensions passed to this function.
374
375 // Returns the dimensions of the main application window in physical pixels.
377
378 // Returns the ratio of the resolution in physical pixels to the resolution of
379 // device-independent pixels.
380 //
381 // E.g. a high DPI monitor might return `2.0f`, which means "two physical pixels
382 // along X and Y map to one device-independent pixel".
383 //
384 // Related (other libraries):
385 //
386 // - https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
387 // - https://doc.qt.io/qt-6/highdpi.html
388 // - https://doc.qt.io/qt-6/qwindow.html#devicePixelRatio
389 // - https://github.com/libsdl-org/SDL/blob/main/docs/README-highdpi.md
391
392 // returns `true` if the main application window is minimized
394
395 // Enables/disables "grabbing" the mouse cursor in the main window, which constrains
396 // the location of the cursor to the edges of the main window.
399
400 // Enables/disables relative mouse mode for the main window.
401 //
402 // While the window has focus and relative mouse mode is enabled:
403 //
404 // - The cursor is hidden
405 // - The mouse's position is constrained to the window
406 // - The event system will still emit `MouseEvent`s with a relative `delta`, even
407 // if the mouse cursor is at the edge of the window.
410
411 // Returns the confinement rectangle of the main window in screen space
412 // in device-independent pixels, or `std::nullopt` if there is no
413 // confinement.
414 std::optional<Rect> main_window_mouse_confinement() const;
415
416 // Sets the confinement rectangle of the main window to `confinement_rect`.
417 //
418 // - If provided, `confinement_rect` should be defined in screen space in device-independent
419 // pixels. For best behavior (OS-dependent), it should be completely inside the OS window
420 // by at least one device-independent pixel.
421 // - If `std::nullopt`, disables the current confinement rectangle (if active).
423
424 // Sets the confinement rectangle to a 1x1 device-independent pixel rectangle
425 // at `confinement_point`.
426 //
427 // - If provided, `confinement_point` should be defined in screen space in device-independent
428 // pixels. For best behavior (OS-dependent), it should be completely inside the OS window
429 // by at least one device-independent pixel.
430 // - If `std::nullopt`, disables the current confinement rectangle (if active).
432
433 // Disables the current confinement rectangle (if active).
435
436 // if the main window is focused with the mouse, returns the current position
437 // of the mouse in screen space in device-independent pixels.
438 //
439 // otherwise, returns `std::nullopt`.
440 std::optional<Vector2> main_window_mouse_position() const;
441
442 // Returns `true` if the main window is showing (i.e. not hidden).
444
445 // Sets if the main window is showing (`true`) or hidden (`false`).
446 //
447 // Note: on some OSes (e.g. macOS), the window state will not change
448 // until the event queue is pumped (e.g. because of a pending OS
449 // animation). Therefore, this function should be called either when
450 // the main thread is still pumping the event queue or when the
451 // caller is capable of calling `process_events()` (potentially,
452 // multiple times) afterwards.
454
455 // Focus the main application window, which usually brings it to
456 // the foreground and gives it keyboard focus.
458
459 // sets the rectangle, defined in screen space and device-independent pixels that's,
460 // used to type unicode text inputs.
461 //
462 // native input methods can place a window with word suggestions near the input
463 // in the main window, without covering the text that's being inputted, this
464 // indicates to the operating system where the input rectangle is so that it
465 // can place and operating-system-defined overlay in the correct position.
467
468 // makes the main window fullscreen, but still composited with the desktop (so-called
469 // 'windowed maximized' in games)
471
472 // makes the main window windowed (as opposed to fullscreen)
474
475 // sets the main window's subtitle (e.g. document name)
476 void set_main_window_subtitle(std::optional<std::string_view>);
477
478 // add an annotation to the current frame with the given `label`
479 // and position in screen space and device-independent pixels.
480 //
481 // the annotation is added to the data returned by `App::request_screenshot_of_main_window`
482 void main_window_add_frame_annotation(std::string_view label, const Rect& screen_rect);
483
484 // returns a future that asynchronously yields an annotated screenshot of the
485 // next frame of the main application window
486 //
487 // client code can submit annotations with `App::add_frame_annotation`
488 std::future<Screenshot> main_window_request_screenshot();
489
490 // fill all pixels in the main window with the given color
492
493 // returns `true` if the given window has input focus
495
496 // returns the ID of the window, if any, that currently has the user's keyboard focus.
497 //
498 // a default-constructed `WindowID` is returned if no window has keyboard focus.
500
501 // start accepting unicode text input events for the given window
502 //
503 // it's usually necessary to call `set_unicode_input_rect` before calling this, so that
504 // the text input UI is placed correctly.
506
507 // stop accepting unicode text input events for the given window
509
510 // Returns the highest ratio of physical pixels to device-independent pixels
511 // supported by all currently-accessible video displays.
512 //
513 // Returns `1.0f` as a fallback if no video displays can be queried.
515
516 // returns the recommended number of antialiasing samples that 3D rendering
517 // code should use when rendering directly to the main application window (based
518 // on user settings, etc.)
520
521 // sets the recommended number of antialiasing samples that 3D rendering code
522 // should use when rendering directly to the main application window.
523 //
524 // throws if `samples > max_anti_aliasing_level()`
526
527 // returns the maximum number of antialiasing samples that the graphics backend supports
529
530 // returns true if the application is in debug mode
531 //
532 // other parts of the application can use this to decide whether to render
533 // extra debug elements, etc.
534 bool debug_mode() const;
535 void set_debug_mode(bool);
536
537 // returns true if VSYNC has been enabled in the graphics backend
538 bool vsync_enabled() const;
540
541 // returns human-readable strings representing (parts of) the currently-active graphics backend (e.g. OpenGL)
546
547 // returns the number of times this `App` has drawn a frame to the main application
548 // window.
549 size_t num_frames_drawn() const;
550
551 // returns the time at which this `App` started up (arbitrary timepoint, don't assume 0)
553
554 // returns `frame_start_time() - startup_time()`
556
557 // returns the time at which the current frame started being drawn
559
560 // returns the time delta between when the current frame started and when the previous
561 // frame started
563
564 // makes main application loop wait, rather than poll, the event queue
565 //
566 // By default, `App` polls the event queue and renders as often as possible. This
567 // method makes the main application wait until at least one event is processed from
568 // the event queue.
569 //
570 // Rendering this way is *much* more power efficient (especially handy on TDP-limited devices
571 // like laptops), but top-level widgets *must* ensure the application keeps moving forward by
572 // calling methods like `request_redraw` or by adding events into the event queue.
577 void request_redraw(); // threadsafe: puts a redraw request into the event queue.
578
579 // Processes pending events in the event queue. Manually calling this
580 // can be necessary to pump the event queue when the main thread is not
581 // running the main application loop.
583
584 private:
585 static int main_internal(const AppMetadata& metadata, const std::function<std::unique_ptr<Widget>()>& widget_ctor);
586
587 // returns the top- (application-)level resource loader
588 ResourceLoader& upd_resource_loader();
589
590 // returns the contents of a runtime resource in the `resources/` dir as a string
591 std::string slurp_resource(const ResourcePath&);
592
593 // returns an opened stream to the given resource
594 ResourceStream go_open_resource(const ResourcePath&);
595
596 // returns a full filesystem path to runtime resource in `resources/` dir
597 std::optional<std::filesystem::path> get_resource_filepath(const ResourcePath&) const;
598
599 // try and retrieve a singleton that has the same lifetime as the app
600 std::shared_ptr<void> upd_singleton(const std::type_info&, const std::function<std::shared_ptr<void>()>&);
601
602 // returns the current application configuration
603 const AppSettings& settings_internal() const;
604 AppSettings& upd_settings_internal();
605
606 std::unique_ptr<AppPrivate> impl_;
607 };
608}
Definition anti_aliasing_level.h:11
Definition app_main_loop_status.h:10
Definition app_metadata.h:11
Definition app_settings.h:14
Definition app.h:45
const AppMetadata & metadata() const
std::string graphics_backend_vendor_string() const
static const App & get()
WindowID main_window_id() const
static bool notify(Widget &receiver, Event &event)
AppClock::time_point startup_time() const
AppMainLoopStatus do_main_loop_step()
std::string application_name_with_version_and_buildid() const
bool vsync_enabled() const
App(const AppMetadata &)
void set_main_loop_waiting(bool)
void prompt_user_to_save_file_async(std::function< void(FileDialogResponse &&)> callback, std::span< const FileDialogFilter > filters={}, std::optional< std::filesystem::path > initial_directory_to_show=std::nullopt)
void set_main_window_mouse_confinement(std::nullopt_t)
std::string graphics_backend_renderer_string() const
static const App * try_get()
void show(std::unique_ptr< Widget >)
std::string human_readable_name() const
void prompt_user_to_select_directory_async(std::function< void(FileDialogResponse &&)> callback, std::optional< std::filesystem::path > initial_directory_to_show=std::nullopt, bool allow_many=false)
static ResourceLoader & resource_loader()
static void post_event(Widget &receiver, Args &&... args)
Definition app.h:158
bool main_window_showing() const
std::future< Screenshot > main_window_request_screenshot()
void stop_text_input(WindowID)
void focus_main_window()
static App & upd()
void main_window_clear(const Color &=Color::clear())
bool is_main_loop_waiting() const
static AppSettings & upd_settings()
void prompt_user_to_select_file_async(std::function< void(FileDialogResponse &&)> callback, std::initializer_list< const FileDialogFilter > filters={}, std::optional< std::filesystem::path > initial_directory_to_show=std::nullopt, bool allow_many=false)
Definition app.h:273
void set_main_window_mouse_confinement(std::optional< Rect > confinement_rect)
float highest_device_pixel_ratio() const
void make_main_loop_waiting()
void set_main_window_mouse_confinement(std::optional< Vector2 > confinement_point)
std::string graphics_backend_version_string() const
void pop_cursor_override()
bool has_input_focus(WindowID) const
static std::shared_ptr< T > singleton(Args &&... args)
Definition app.h:50
Vector2i main_window_pixel_dimensions() const
static bool notify(Widget &receiver, Args &&... args)
Definition app.h:172
void request_transition(Args &&... args)
Definition app.h:223
Vector2 main_window_dimensions() const
bool main_window_grabbing() const
void set_main_window_grabbing(bool)
AntiAliasingLevel max_anti_aliasing_level() const
float main_window_device_pixel_ratio() const
void start_text_input(WindowID)
void set_debug_mode(bool)
std::optional< Rect > main_window_mouse_confinement() const
void make_main_window_windowed()
static void post_event(Widget &receiver, std::unique_ptr< Event > event)
bool debug_mode() const
AntiAliasingLevel anti_aliasing_level() const
App(App &&) noexcept=delete
void make_main_window_fullscreen()
void request_redraw()
void set_main_window_dimensions(Vector2)
void show(Args &&... args)
Definition app.h:200
void process_events()
static ResourceStream open_resource(const ResourcePath &)
void set_main_window_unicode_input_rect(const Rect &screen_rect)
void push_cursor_override(const Cursor &)
void set_main_window_relative_mouse_mode(bool)
void set_vsync_enabled(bool)
void main_window_add_frame_annotation(std::string_view label, const Rect &screen_rect)
void set_prompt_initial_directory_to_show_fallback(std::optional< std::filesystem::path >)
const std::filesystem::path & user_data_directory() const
AppClock::duration frame_delta_since_startup() const
void prompt_user_to_save_file_async(std::function< void(FileDialogResponse &&)> callback, std::initializer_list< const FileDialogFilter > filters={}, std::optional< std::filesystem::path > initial_directory_to_show=std::nullopt)
Definition app.h:325
static std::optional< std::filesystem::path > resource_filepath(const ResourcePath &)
void request_invoke_on_main_thread(std::function< void()>)
void set_main_window_subtitle(std::optional< std::string_view >)
std::optional< std::filesystem::path > prompt_initial_directory_to_show_fallback()
void prompt_user_to_save_file_with_extension_async(std::function< void(std::optional< std::filesystem::path >)> callback, std::optional< std::string_view > maybe_extension=std::nullopt, std::optional< std::filesystem::path > initial_directory_to_show=std::nullopt)
AppClock::time_point frame_start_time() const
void prompt_user_to_select_file_async(std::function< void(FileDialogResponse &&)> callback, std::span< const FileDialogFilter > filters={}, std::optional< std::filesystem::path > initial_directory_to_show=std::nullopt, bool allow_many=false)
void teardown_main_loop()
void setup_main_loop(std::unique_ptr< Widget >)
void request_transition(std::unique_ptr< Widget >)
std::optional< std::filesystem::path > executable_directory() const
void request_quit()
void set_anti_aliasing_level(AntiAliasingLevel)
static int main(const AppMetadata &metadata, Args &&... args)
Definition app.h:95
void make_main_loop_polling()
void set_main_window_showing(bool)
AppClock::duration frame_delta_since_last_frame() const
size_t num_frames_drawn() const
WindowID get_keyboard_focus() const
std::optional< Vector2 > main_window_mouse_position() const
bool is_main_window_minimized() const
bool main_window_relative_mouse_mode() const
static const AppSettings & settings()
std::string graphics_backend_shading_language_version_string() const
App(const App &)=delete
static App * try_upd()
static std::string slurp(const ResourcePath &)
Definition cursor.h:7
Definition event.h:13
Definition file_dialog_response.h:18
Definition rect.h:17
Definition resource_loader.h:24
Definition resource_path.h:12
Definition resource_stream.h:11
Definition widget.h:26
Definition window_id.h:7
Definition custom_decoration_generator.h:5
constexpr U to(T &&value)
Definition conversion.h:56
std::chrono::time_point< AppClock > time_point
Definition app_clock.h:13
std::chrono::duration< rep, period > duration
Definition app_clock.h:12
static constexpr Rgba clear()
Definition rgba.h:29