diff --git a/meson.build b/meson.build index ddbbf42..5c5673a 100644 --- a/meson.build +++ b/meson.build @@ -26,6 +26,7 @@ raven_source_files = [ './src/Box.cpp', './src/Styles.cpp', './src/Painter.cpp', + './src/Application.cpp', './src/Window.cpp', './src/Widget.cpp', './src/SvgWidget.cpp', @@ -61,6 +62,7 @@ raven_header_files = [ './src/Styles.hpp', './src/Widget.hpp', './src/SvgWidget.hpp', + './src/Application.hpp', './src/Window.hpp' ] diff --git a/src/Application.cpp b/src/Application.cpp new file mode 100644 index 0000000..d3a2420 --- /dev/null +++ b/src/Application.cpp @@ -0,0 +1,55 @@ +#include "Application.hpp" +#include + +namespace Raven { + +void Application::add_window(std::shared_ptr window) { + m_windows.push_back(window); + update_fds(); +} + +void Application::update_fds() { + for (int i = 0; i < RAVEN_APPLICATION_MAX_WINDOWS; i++) { + m_fds[i].fd = -1; + m_fds[i].events = 0; + m_fds[i].revents = 0; + } + for (size_t i = 0; i < m_windows.size(); i++) { + m_fds[i].fd = m_windows[i]->file_descriptor(); + m_fds[i].events = POLL_IN; + } +} + +int Application::turn() { + if (m_fds_need_update) { + update_fds(); + m_fds_need_update = false; + } + if (poll(m_fds, m_windows.size(), -1) > 0) { + for (size_t i = 0; i < m_windows.size(); i++) { + if (m_fds[i].revents & POLLIN) { + m_windows[i]->run(false); + } + } + } else { + return 1; + } + return 0; +} + +int Application::run() { + // Make sure any pending events are dealt with before starting the loop + for (size_t i = 0; i < m_windows.size(); i++) { + m_windows[i]->run(false); + } + + for (;;) { + int ret = turn(); + if (ret != 0) { + return ret; + } + } + return 0; +} + +} \ No newline at end of file diff --git a/src/Application.hpp b/src/Application.hpp new file mode 100644 index 0000000..5a83563 --- /dev/null +++ b/src/Application.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include "Window.hpp" + +namespace Raven { + +#define RAVEN_APPLICATION_MAX_WINDOWS 1023 + +class Application { +public: + Application() {} + + void add_window(std::shared_ptr); + int turn(); + int run(); + + template + std::shared_ptr add_window(Args&&... args) { + std::shared_ptr child = std::make_shared(std::forward(args)...); + add_window(child); + return child; + } +private: + void update_fds(); + + std::vector> m_windows; + struct pollfd m_fds[RAVEN_APPLICATION_MAX_WINDOWS]; + bool m_fds_need_update { true }; +}; + +} \ No newline at end of file diff --git a/src/SvgWidget.hpp b/src/SvgWidget.hpp index 38a8a3d..332d093 100644 --- a/src/SvgWidget.hpp +++ b/src/SvgWidget.hpp @@ -5,7 +5,7 @@ #include "cairomm/enums.h" #include "cairomm/refptr.h" #include "cairomm/surface.h" -#include "raven/Widget.hpp" +#include "Widget.hpp" #include "librsvg/rsvg.h" namespace Raven { diff --git a/src/Window.cpp b/src/Window.cpp index 9620a4e..5dff2d3 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -69,6 +69,10 @@ bool Window::spawn_window() { return true; } +int Window::file_descriptor() { + return m_x_display ? XConnectionNumber(m_x_display) : -1; +} + bool Window::dispatch_to_main_widget(Event &event) { if (!m_main_widget) return false; @@ -157,7 +161,6 @@ void Window::swallow_batches() { void Window::run(bool block) { XEvent e; - bool is_loop_batch_started = false; swallow_batches(); @@ -167,9 +170,9 @@ void Window::run(bool block) { else break; - if (!is_loop_batch_started) { + if (!m_is_loop_batch_started) { start_batch(); - is_loop_batch_started = true; + m_is_loop_batch_started = true; } switch (e.type) { case MapNotify: { @@ -254,9 +257,9 @@ void Window::run(bool block) { callback(); m_microtasks.pop(); } - if (is_loop_batch_started) { + if (m_is_loop_batch_started) { end_batch(); - is_loop_batch_started = false; + m_is_loop_batch_started = false; } } } diff --git a/src/Window.hpp b/src/Window.hpp index ce11525..4783cb4 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -20,6 +20,8 @@ public: bool spawn_window(); void run(bool block); + int file_descriptor(); + void start_batch(); void end_batch(); void swallow_batches(); @@ -64,6 +66,7 @@ private: Box m_invalidated_area {0, 0, 0, 0}; bool m_did_relayout_during_batch { false }; std::queue> m_microtasks; + bool m_is_loop_batch_started { false }; Display *m_x_display { nullptr }; XIM m_xim { nullptr }; diff --git a/src/main.cpp b/src/main.cpp index bbed464..0a4c03f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include "Label.hpp" +#include "Application.hpp" #include "ColumnLayout.hpp" #include "ListView.hpp" #include "TextInput.hpp" @@ -20,10 +21,13 @@ #include int main() { - Raven::Window window {}; - window.spawn_window(); + Raven::Application application {}; + + auto window = application.add_window(); - auto main_widget = window.set_main_widget(); + window->spawn_window(); + + auto main_widget = window->set_main_widget(); auto main_widget_layout = main_widget->set_layout(Raven::Direction::Horizontal); main_widget_layout->set_margin(8); main_widget_layout->set_spacing(8); @@ -54,8 +58,6 @@ int main() { delete_button->set_style(&Raven::raised_button_style); delete_button->set_grows(true); - content->add("Edit an item"); - auto edit_row = content->add(); edit_row->set_style(&Raven::raised_widget_style); auto edit_row_layout = edit_row->set_layout(Raven::Direction::Horizontal); @@ -96,6 +98,5 @@ int main() { } list_view->elements_updated(); - window.run(true); - return 0; + return application.run(); }