HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gui_system.hpp
1// Copyright Take Vos 2020, 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "gui_window.hpp"
8#include "gui_window_win32.hpp"
9#include "gui_system_delegate.hpp"
10#include "../GFX/gfx_device.hpp"
11#include "../thread.hpp"
12#include "../unfair_recursive_mutex.hpp"
13#include "../event_queue.hpp"
14#include <span>
15#include <memory>
16#include <mutex>
17#include <thread>
18#include <vector>
19
20namespace tt {
21class gfx_system;
22class vertical_sync;
23class font_book;
24class theme_book;
25class keyboard_bindings;
26
30public:
31 static inline os_handle instance;
32
38
39
40 thread_id const thread_id;
41
51
52 virtual ~gui_system();
53
54 gui_system(const gui_system &) = delete;
55 gui_system &operator=(const gui_system &) = delete;
56 gui_system(gui_system &&) = delete;
57 gui_system &operator=(gui_system &&) = delete;
58
62 virtual void init() noexcept
63 {
64 if (auto delegate = _delegate.lock()) {
65 delegate->init(*this);
66 }
67 }
68
69 virtual void deinit() noexcept
70 {
71 if (auto delegate = _delegate.lock()) {
72 delegate->deinit(*this);
73 }
74 }
75
76 void set_delegate(std::weak_ptr<gui_system_delegate> delegate) noexcept
77 {
78 _delegate = std::move(delegate);
79 }
80
93 virtual int loop() = 0;
94
95 virtual void exit(int exit_code) = 0;
96
102 tt::event_queue const &event_queue() const noexcept
103 {
104 return *_event_queue;
105 }
106
109 void run_from_event_queue(std::invocable auto &&function) noexcept
110 {
111 event_queue().emplace(std::forward<decltype(function)>(function));
112 }
113
116 void run(std::invocable auto &&function) noexcept
117 {
118 if (is_gui_thread()) {
119 function();
120 } else {
121 run_from_event_queue(std::forward<decltype(function)>(function));
122 }
123 }
124
125 gui_window &add_window(std::unique_ptr<gui_window> window);
126
132 template<typename... Args>
133 gui_window &make_window(Args &&...args)
134 {
135 tt_axiom(is_gui_thread());
136
137 // XXX abstract away the _win32 part.
138 auto window = std::make_unique<gui_window_win32>(*this, std::forward<Args>(args)...);
139 window->init();
140
141 return add_window(std::move(window));
142 }
143
147
148 void render(utc_nanoseconds display_time_point)
149 {
150 tt_axiom(is_gui_thread());
151
152 for (auto &window : _windows) {
153 window->render(display_time_point);
154 if (window->is_closed()) {
155 window->deinit();
156 window = nullptr;
157 }
158 }
159 std::erase(_windows, nullptr);
160
161 ttlet num_windows = std::size(_windows);
162 if (num_windows == 0 && num_windows != _previous_num_windows) {
163 // If last_window_closed() creates a new window we should
164 // let it do that before entering the event queue again.
165 // win32 is a bit picky about running without windows.
166 if (auto delegate = _delegate.lock()) {
167 if (auto exit_code = delegate->last_window_closed(*this)) {
168 this->exit(*exit_code);
169 }
170 } else {
171 this->exit(0);
172 }
173 }
174 _previous_num_windows = num_windows;
175 }
176
179 [[nodiscard]] bool is_gui_thread() const noexcept
180 {
181 return thread_id == current_thread_id();
182 }
183
188 void set_theme(tt::theme const &new_theme) noexcept;
189
194 tt::theme const &theme() const noexcept;
195
196 void set_theme_mode(tt::theme_mode mode) noexcept;
197
200 void request_constrain() noexcept;
201
202protected:
204 std::shared_ptr<tt::event_queue> event_queue,
205 std::unique_ptr<gfx_system> gfx,
206 std::unique_ptr<tt::vertical_sync> vertical_sync,
207 std::unique_ptr<tt::font_book> font_book,
208 std::unique_ptr<tt::theme_book> theme_book,
209 std::unique_ptr<tt::keyboard_bindings> keyboard_bindings,
210 std::weak_ptr<gui_system_delegate> delegate = {}) noexcept;
211
218
219private:
221
223 size_t _previous_num_windows = 0;
224
228 tt::theme const *_theme = nullptr;
229};
230
231} // namespace tt
STL namespace.
Definition event_queue.hpp:40
Graphics system.
Definition gfx_system.hpp:21
Graphics system.
Definition gui_system.hpp:29
virtual void init() noexcept
Initialize after construction.
Definition gui_system.hpp:62
void set_theme(tt::theme const &new_theme) noexcept
Set the theme for the system.
void run(std::invocable auto &&function) noexcept
Run the function now or on from the GUI's event loop.
Definition gui_system.hpp:116
static std::unique_ptr< gui_system > make_unique(std::weak_ptr< gui_system_delegate > delegate={}) noexcept
Make a gui_system instance.
void run_from_event_queue(std::invocable auto &&function) noexcept
Run the function from the GUI's event queue.
Definition gui_system.hpp:109
ssize_t num_windows()
tt::theme const & theme() const noexcept
Get the theme.
gui_window & make_window(Args &&...args)
Create a new window.
Definition gui_system.hpp:133
tt::event_queue const & event_queue() const noexcept
Get the event queue.
Definition gui_system.hpp:102
bool is_gui_thread() const noexcept
Check if this thread is the same as the gui thread.
Definition gui_system.hpp:179
void request_constrain() noexcept
Request all windows to constrain.
virtual int loop()=0
Start the GUI event loop.
Definition gui_system_delegate.hpp:11
Definition gui_window.hpp:39
Definition keyboard_bindings.hpp:17
Definition theme.hpp:22
theme_book keeps track of multiple themes.
Definition theme_book.hpp:19
Definition vertical_sync.hpp:13
font_book keeps track of multiple fonts.
Definition font_book.hpp:30
T forward(T... args)
T move(T... args)