diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index a9313c9..5a46b32 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,7 +1,6 @@ include(impl.cmake) qt_add_executable(PROJECT-NAME - src/api.cxx src/main.cxx src/main_window.cxx src/main_window.ui diff --git a/ui/src/api.cxx b/ui/src/api.cxx deleted file mode 100644 index a24b32c..0000000 --- a/ui/src/api.cxx +++ /dev/null @@ -1,16 +0,0 @@ -#include "api.hxx" - -#include -#include - -namespace ffi { -extern "C" ICore* rt4_viewport_create(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height); -} // namespace ffi - -BoxCore BoxCore::from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) { - if (!connection) - throw std::logic_error("attempt to use a null connection"); - if (!window) - throw std::logic_error("attempt to use a null window"); - return BoxCore{ffi::rt4_viewport_create(connection, window, width, height)}; -} diff --git a/ui/src/api.hxx b/ui/src/api.hxx index 71b16e7..e73e15c 100644 --- a/ui/src/api.hxx +++ b/ui/src/api.hxx @@ -10,7 +10,6 @@ class IBoxed { friend struct BoxDeleter; private: - ~IBoxed() = delete; virtual void destroy() = 0; }; @@ -44,8 +43,12 @@ public: virtual void redraw(const RedrawArgs& args) = 0; }; -class BoxCore : public Box { +class ICoreFactory : public IBoxed { +private: + virtual ICore* new_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) const = 0; + public: - using Box::Box; - static BoxCore from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height); + Box from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) const { + return Box{new_xcb(connection, window, width, height)}; + } }; diff --git a/ui/src/main.cxx b/ui/src/main.cxx index a0405ec..5488615 100644 --- a/ui/src/main.cxx +++ b/ui/src/main.cxx @@ -1,15 +1,31 @@ -#include "main_window.hxx" - #include -int main(int argc, char* argv[]) { +#include "api.hxx" +#include "main_window.hxx" + +extern "C" int run(int argc, char* argv[], ICoreFactory* factory) { // only X11 is supported so, use XCB unless overriden setenv("QT_QPA_PLATFORM", "xcb", 0); QApplication app(argc, argv); - auto w = new PROJECTNAME; + auto w = new PROJECTNAME(factory); w->show(); return app.exec(); } + +extern "C" ICore* rt4_viewport_create(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height); + +class CoreFactory : public ICoreFactory { +public: + void destroy() override {} + ICore* new_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) const override { + return rt4_viewport_create(connection, window, width, height); + } +}; + +int main(int argc, char* argv[]) { + CoreFactory factory; + return run(argc, argv, &factory); +} diff --git a/ui/src/main_window.cxx b/ui/src/main_window.cxx index 5640218..e00077d 100644 --- a/ui/src/main_window.cxx +++ b/ui/src/main_window.cxx @@ -2,10 +2,12 @@ #include "ui_main_window.h" -PROJECTNAME::PROJECTNAME(QWidget* parent) +PROJECTNAME::PROJECTNAME(const ICoreFactory* factory, QWidget* parent) : QMainWindow(parent), - m_ui(new Ui::MainWindow) { + m_ui(new Ui::MainWindow), + factory(factory) { m_ui->setupUi(this); + m_ui->viewport->setFactory(factory); updateView(); } diff --git a/ui/src/main_window.hxx b/ui/src/main_window.hxx index 13edb16..1b83e4f 100644 --- a/ui/src/main_window.hxx +++ b/ui/src/main_window.hxx @@ -3,6 +3,8 @@ #include +#include "api.hxx" + namespace Ui { class MainWindow; } @@ -11,7 +13,7 @@ class PROJECTNAME : public QMainWindow { Q_OBJECT public: - explicit PROJECTNAME(QWidget* parent = nullptr); + explicit PROJECTNAME(const ICoreFactory* factory, QWidget* parent = nullptr); ~PROJECTNAME() override; public slots: @@ -19,4 +21,5 @@ public slots: private: const std::unique_ptr m_ui; + const ICoreFactory* factory; }; diff --git a/ui/src/viewport.cxx b/ui/src/viewport.cxx index e681bd9..d42185d 100644 --- a/ui/src/viewport.cxx +++ b/ui/src/viewport.cxx @@ -14,6 +14,11 @@ Viewport::Viewport(QWidget* parent, Qt::WindowFlags f) Viewport::~Viewport() = default; +void Viewport::setFactory(const ICoreFactory* new_factory) { + factory = new_factory; + update(); +} + void Viewport::setView(RedrawArgs new_args) { args = new_args; update(); @@ -37,6 +42,8 @@ bool Viewport::event(QEvent* event) { void Viewport::paintEvent(QPaintEvent* event) { if (!core) recreate(); + if (!core) + return; core->redraw(args); } @@ -48,6 +55,9 @@ void Viewport::resizeEvent(QResizeEvent* event) { } void Viewport::recreate() try { + if (!factory) + return; + auto* app = qobject_cast(QApplication::instance()); if (!app) throw std::runtime_error("not a GUI application (WTF?)"); @@ -59,11 +69,9 @@ void Viewport::recreate() try { auto* xcb_connection = native->connection(); std::uint32_t x11_window = winId(); - fprintf(stderr, "connection %p, window %#08x\n", xcb_connection, x11_window); - const QSize device_size = size() * devicePixelRatio(); core.reset(); - core = BoxCore::from_xcb(xcb_connection, x11_window, device_size.width(), device_size.height()); + core = factory->from_xcb(xcb_connection, x11_window, device_size.width(), device_size.height()); } catch (const std::exception& e) { fprintf(stderr, "failed to recreate the viewport: %s", e.what()); } diff --git a/ui/src/viewport.hxx b/ui/src/viewport.hxx index 95839b9..90dfd97 100644 --- a/ui/src/viewport.hxx +++ b/ui/src/viewport.hxx @@ -12,6 +12,7 @@ public: ~Viewport() override; QPaintEngine* paintEngine() const override; + void setFactory(const ICoreFactory* new_factory); void setView(RedrawArgs new_args); protected: @@ -20,7 +21,8 @@ protected: void resizeEvent(QResizeEvent* event) override; private: - BoxCore core; + const ICoreFactory* factory = nullptr; + Box core; RedrawArgs args = {}; void recreate();