From e7683cd94edabf6d6b59f6f2bbbf3e271960b394 Mon Sep 17 00:00:00 2001 From: James Grogan Date: Fri, 11 Nov 2022 15:51:37 +0000 Subject: [PATCH] Prep for image support in windows. --- src/ui_elements/CMakeLists.txt | 2 +- .../desktop_elements/IPlatformWindow.h | 13 +++ src/ui_elements/desktop_elements/Window.cpp | 40 ++++++++++ src/ui_elements/desktop_elements/Window.h | 14 ++++ src/windows/CMakeLists.txt | 2 +- src/windows/ui_interfaces/x11/XcbImage.cpp | 0 src/windows/ui_interfaces/x11/XcbImage.h | 6 ++ .../ui_interfaces/x11/XcbInterface.cpp | 21 +++-- src/windows/ui_interfaces/x11/XcbInterface.h | 1 - src/windows/ui_interfaces/x11/XcbWindow.cpp | 70 ++++++++++++++-- src/windows/ui_interfaces/x11/XcbWindow.h | 28 ++++++- .../ui_interfaces/x11/XcbWindowInterface.cpp | 80 ------------------- .../ui_interfaces/x11/XcbWindowInterface.h | 30 ------- 13 files changed, 172 insertions(+), 135 deletions(-) create mode 100644 src/windows/ui_interfaces/x11/XcbImage.cpp create mode 100644 src/windows/ui_interfaces/x11/XcbImage.h delete mode 100644 src/windows/ui_interfaces/x11/XcbWindowInterface.cpp delete mode 100644 src/windows/ui_interfaces/x11/XcbWindowInterface.h diff --git a/src/ui_elements/CMakeLists.txt b/src/ui_elements/CMakeLists.txt index b0bc14d..98c871c 100644 --- a/src/ui_elements/CMakeLists.txt +++ b/src/ui_elements/CMakeLists.txt @@ -33,7 +33,7 @@ target_include_directories(ui_elements PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/ui_events" "${CMAKE_CURRENT_SOURCE_DIR}/desktop_elements" ) -target_link_libraries(ui_elements PUBLIC core geometry visual_elements) +target_link_libraries(ui_elements PUBLIC core geometry visual_elements image) set_property(TARGET ui_elements PROPERTY FOLDER src) diff --git a/src/ui_elements/desktop_elements/IPlatformWindow.h b/src/ui_elements/desktop_elements/IPlatformWindow.h index 4b419da..73e5835 100644 --- a/src/ui_elements/desktop_elements/IPlatformWindow.h +++ b/src/ui_elements/desktop_elements/IPlatformWindow.h @@ -2,10 +2,23 @@ #include +namespace mt +{ + class Screen; +} + class IPlatformWindow { public: virtual ~IPlatformWindow() = default; + + virtual void show() const = 0; + + virtual void map() const = 0; + + virtual void clear() const = 0; + + virtual void paint(mt::Screen* screen) const = 0; }; using IPlatformWindowPtr = std::unique_ptr; diff --git a/src/ui_elements/desktop_elements/Window.cpp b/src/ui_elements/desktop_elements/Window.cpp index fa833ee..bf04950 100644 --- a/src/ui_elements/desktop_elements/Window.cpp +++ b/src/ui_elements/desktop_elements/Window.cpp @@ -5,6 +5,8 @@ #include "MouseEvent.h" #include "VisualLayer.h" #include "KeyboardEvent.h" +#include "Image.h" +#include "Screen.h" namespace mt { @@ -12,6 +14,7 @@ namespace mt Window::Window() :mWidth(800), mHeight(600), + mBackingImage(std::make_unique(mWidth, mHeight)), mWidget(Widget::Create()) { mWidget->setBounds(mWidth, mHeight); @@ -93,4 +96,41 @@ void Window::SetPlatformWindow(IPlatformWindowPtr window) mPlatformWindow = std::move(window); } +Image* Window::getBackingImage() const +{ + return mBackingImage.get(); +} + +void Window::map() +{ + if (mPlatformWindow) + { + mPlatformWindow->map(); + } +} + +void Window::show() +{ + if (mPlatformWindow) + { + mPlatformWindow->show(); + } +} + +void Window::doPaint(mt::Screen* screen) +{ + if (mPlatformWindow) + { + mPlatformWindow->paint(screen); + } +} + +void Window::clear() +{ + if (mPlatformWindow) + { + mPlatformWindow->clear(); + } +} + } diff --git a/src/ui_elements/desktop_elements/Window.h b/src/ui_elements/desktop_elements/Window.h index 7f1cf49..63c1661 100644 --- a/src/ui_elements/desktop_elements/Window.h +++ b/src/ui_elements/desktop_elements/Window.h @@ -9,12 +9,15 @@ class PaintEvent; class MouseEvent; class KeyboardEvent; class VisualLayer; +class Image; class IPlatformWindow; using IPlatformWindowPtr = std::unique_ptr; namespace mt { +class Screen; + class Window { @@ -48,12 +51,23 @@ public: void SetPlatformWindow(IPlatformWindowPtr window); + Image* getBackingImage() const; + + void map(); + + void show(); + + void doPaint(mt::Screen* screen); + + void clear(); + private: int mHandle {-1}; WidgetUPtr mWidget {nullptr}; unsigned mWidth {800}; unsigned mHeight {600}; IPlatformWindowPtr mPlatformWindow {nullptr}; + std::unique_ptr mBackingImage; }; } diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt index a083e81..be6135c 100644 --- a/src/windows/CMakeLists.txt +++ b/src/windows/CMakeLists.txt @@ -11,7 +11,7 @@ if(UNIX) ui_interfaces/x11/XcbEventInterface.cpp ui_interfaces/x11/XcbWindow.cpp ui_interfaces/x11/XcbScreen.cpp - ui_interfaces/x11/XcbWindowInterface.cpp + ui_interfaces/x11/XcbImage.cpp ui_interfaces/x11/XcbLayerInterface.cpp ui_interfaces/x11/XcbTextInterface.cpp ui_interfaces/x11/XcbKeyboard.cpp diff --git a/src/windows/ui_interfaces/x11/XcbImage.cpp b/src/windows/ui_interfaces/x11/XcbImage.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/windows/ui_interfaces/x11/XcbImage.h b/src/windows/ui_interfaces/x11/XcbImage.h new file mode 100644 index 0000000..b0ba112 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbImage.h @@ -0,0 +1,6 @@ +#pragma once + +class XcbImage +{ + +}; diff --git a/src/windows/ui_interfaces/x11/XcbInterface.cpp b/src/windows/ui_interfaces/x11/XcbInterface.cpp index 12e1453..a787225 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.cpp +++ b/src/windows/ui_interfaces/x11/XcbInterface.cpp @@ -15,7 +15,6 @@ #include "XcbWindow.h" #include "XcbLayerInterface.h" #include "XcbEventInterface.h" -#include "XcbWindowInterface.h" #include "GlxInterface.h" #include "FileLogger.h" @@ -25,8 +24,7 @@ XcbInterface::XcbInterface(DesktopManager* desktopManager, bool useHardware) mConnection(nullptr), mX11Display(), mGlxInterface(), - mXcbEventInterface(XcbEventInterface::Create()), - mXcbWindowInterface(XcbWindowInterface::Create()) + mXcbEventInterface(XcbEventInterface::Create()) { } @@ -45,7 +43,6 @@ void XcbInterface::initialize() { initializeOpenGl(); } - mDesktopManager->SetKeyboard(XcbKeyboard::Create()); } @@ -117,10 +114,10 @@ void XcbInterface::createOpenGlDrawable(mt::Window* window) return; } - if (!mGlxInterface->SetupWindow(mX11Display, xcb_window->GetHandle())) + if (!mGlxInterface->SetupWindow(mX11Display, xcb_window->getHandle())) { MLOG_ERROR("Failed to set up OpenGL Drawable"); - xcb_destroy_window(mConnection, xcb_window->GetHandle()); + xcb_destroy_window(mConnection, xcb_window->getHandle()); } } @@ -146,12 +143,12 @@ void XcbInterface::createGraphicsContext() void XcbInterface::mapWindow(mt::Window* window) { - mXcbWindowInterface->Map(window, mConnection); + window->map(); } void XcbInterface::showWindow(mt::Window* window) { - mXcbWindowInterface->Show(window, mConnection); + window->show(); if (mUseHardwareRendering) { @@ -170,7 +167,7 @@ uint32_t XcbInterface::getEventMask() void XcbInterface::addWindow(mt::Window* window) { auto screen = mDesktopManager->GetDefaultScreen(); - mXcbWindowInterface->Add(window, mConnection, screen, getEventMask()); + XcbWindow::add(window, mConnection, screen, getEventMask()); } void XcbInterface::onPaint() @@ -179,8 +176,8 @@ void XcbInterface::onPaint() auto mainWindow = mDesktopManager->GetWindowManager()->GetMainWindow(); auto defaultScreen = mDesktopManager->GetDefaultScreen(); - auto xcb_screen = dynamic_cast(defaultScreen->GetPlatformScreen()); - mXcbWindowInterface->Paint(mainWindow, mConnection, xcb_screen->GetNativeScreen(), xcb_screen->GetGraphicsContext()); + + mainWindow->doPaint(defaultScreen); } void XcbInterface::onExposeEvent(xcb_expose_event_t* event) @@ -265,7 +262,7 @@ void XcbInterface::onEventsDispatched() { mDesktopManager->SetIsModified(false); auto mainWindow = mDesktopManager->GetWindowManager()->GetMainWindow(); - mXcbWindowInterface->Clear(mainWindow, mConnection); + mainWindow->clear(); } } diff --git a/src/windows/ui_interfaces/x11/XcbInterface.h b/src/windows/ui_interfaces/x11/XcbInterface.h index a4e1294..d4ec561 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.h +++ b/src/windows/ui_interfaces/x11/XcbInterface.h @@ -60,5 +60,4 @@ private: _XDisplay* mX11Display; GlxInterfacePtr mGlxInterface; XcbEventInterfacePtr mXcbEventInterface {nullptr}; - XcbWindowInterfacePtr mXcbWindowInterface {nullptr}; }; diff --git a/src/windows/ui_interfaces/x11/XcbWindow.cpp b/src/windows/ui_interfaces/x11/XcbWindow.cpp index 4fb6230..511c555 100644 --- a/src/windows/ui_interfaces/x11/XcbWindow.cpp +++ b/src/windows/ui_interfaces/x11/XcbWindow.cpp @@ -1,22 +1,80 @@ #include "XcbWindow.h" -XcbWindow::XcbWindow(int hwnd) - : mHandle(hwnd) +#include "Window.h" +#include "XcbLayerInterface.h" +#include "XcbScreen.h" +#include "XcbImage.h" +#include "Screen.h" + +#include + +XcbWindow::XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection) + : mHandle(hwnd), + mWindow(window), + mBackingImage(std::make_unique()), + mConnection(connection) { } -std::unique_ptr XcbWindow::Create(int hwnd) +void XcbWindow::add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask) { - return std::make_unique(hwnd); + if (!screen) + { + return; + } + auto xcb_screen = dynamic_cast(screen->GetPlatformScreen()); + + const auto hwnd = xcb_generate_id(connection); + const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + const uint32_t values[2] = {xcb_screen->GetNativeScreen()->white_pixel, eventMask}; + xcb_create_window (connection, /* connection */ + XCB_COPY_FROM_PARENT, /* depth */ + hwnd, /* window Id */ + xcb_screen->GetNativeScreen()->root, /* parent window */ + 0, 0, /* x, y */ + window->GetWidth(), window->GetHeight(), /* width, height */ + 10, /* border_width */ + XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */ + xcb_screen->GetNativeScreen()->root_visual, /* visual */ + mask, values ); /* masks */ + + auto xcb_window = std::make_unique(window, hwnd, connection); + window->SetPlatformWindow(std::move(xcb_window)); } -int XcbWindow::GetHandle() const +int XcbWindow::getHandle() const { return mHandle; } -unsigned XcbWindow::GetGraphicsContext() const +unsigned XcbWindow::getGraphicsContext() const { return mGraphicsContext; } + +void XcbWindow::show() const +{ + map(); +} + +void XcbWindow::paint(mt::Screen* screen) const +{ + auto xcb_screen = dynamic_cast(screen->GetPlatformScreen()); + for(const auto& layer : mWindow->GetLayers()) + { + XcbLayerInterface::AddLayer(mConnection, xcb_screen->GetNativeScreen(), mHandle, xcb_screen->GetGraphicsContext(), layer); + } +} + +void XcbWindow::clear() const +{ + xcb_clear_area(mConnection, 1, mHandle, 0, 0, mWindow->GetWidth(), mWindow->GetHeight()); + xcb_flush(mConnection); +} + +void XcbWindow::map() const +{ + xcb_map_window(mConnection, mHandle); + xcb_flush(mConnection); +} diff --git a/src/windows/ui_interfaces/x11/XcbWindow.h b/src/windows/ui_interfaces/x11/XcbWindow.h index 0df187a..0a6a774 100644 --- a/src/windows/ui_interfaces/x11/XcbWindow.h +++ b/src/windows/ui_interfaces/x11/XcbWindow.h @@ -2,20 +2,40 @@ #include "IPlatformWindow.h" +class XcbImage; +struct xcb_connection_t; + +namespace mt +{ + class Window; +} + class XcbWindow : public IPlatformWindow { public: - XcbWindow(int hwnd); + XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection); virtual ~XcbWindow() = default; - static std::unique_ptr Create(int hwnd); + static void add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask); - int GetHandle() const; - unsigned GetGraphicsContext() const; + int getHandle() const; + unsigned getGraphicsContext() const; + + void show() const override; + + void paint(mt::Screen* screen) const override; + + void clear() const override; + + void map() const override; private: + int mHandle{-1}; unsigned mGraphicsContext {0}; + mt::Window* mWindow{nullptr}; + xcb_connection_t* mConnection{nullptr}; + std::unique_ptr mBackingImage; }; using XcbWindowPtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/XcbWindowInterface.cpp b/src/windows/ui_interfaces/x11/XcbWindowInterface.cpp deleted file mode 100644 index 00cd0c5..0000000 --- a/src/windows/ui_interfaces/x11/XcbWindowInterface.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "XcbWindowInterface.h" - -#include "Window.h" -#include "XcbWindow.h" -#include "Screen.h" -#include "XcbScreen.h" -#include "XcbLayerInterface.h" - -#include - -std::unique_ptr XcbWindowInterface::Create() -{ - return std::make_unique(); -} - -void XcbWindowInterface::Add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask) const -{ - if (!connection || !screen || !window) - { - return; - } - auto xcb_screen = dynamic_cast(screen->GetPlatformScreen()); - - auto hwnd = xcb_generate_id(connection); - uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - uint32_t values[2] = {xcb_screen->GetNativeScreen()->white_pixel, eventMask}; - xcb_create_window (connection, /* connection */ - XCB_COPY_FROM_PARENT, /* depth */ - hwnd, /* window Id */ - xcb_screen->GetNativeScreen()->root, /* parent window */ - 0, 0, /* x, y */ - window->GetWidth(), window->GetHeight(), /* width, height */ - 10, /* border_width */ - XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */ - xcb_screen->GetNativeScreen()->root_visual, /* visual */ - mask, values ); /* masks */ - - auto xcb_window = XcbWindow::Create(hwnd); - window->SetPlatformWindow(std::move(xcb_window)); -} - -void XcbWindowInterface::Show(mt::Window* window, xcb_connection_t* connection) const -{ - Map(window, connection); -} - -void XcbWindowInterface::Paint(mt::Window* window, xcb_connection_t* connection, xcb_screen_t* screen, unsigned gc) const -{ - if (!window) - { - return; - } - auto xcb_window = dynamic_cast(window->GetPlatformWindow()); - for(const auto& layer : window->GetLayers()) - { - XcbLayerInterface::AddLayer(connection, screen, xcb_window->GetHandle(), gc, layer); - } -} - -void XcbWindowInterface::Clear(mt::Window* window, xcb_connection_t* connection) const -{ - if (!window) - { - return; - } - auto xcb_window = dynamic_cast(window->GetPlatformWindow()); - xcb_clear_area(connection, 1, xcb_window->GetHandle(), 0, 0, window->GetWidth(), window->GetHeight()); - xcb_flush(connection); -} - -void XcbWindowInterface::Map(mt::Window* window, xcb_connection_t* connection) const -{ - if (!connection or !window) - { - return; - } - auto xcb_window = dynamic_cast(window->GetPlatformWindow()); - xcb_map_window(connection, xcb_window->GetHandle()); - xcb_flush(connection); -} diff --git a/src/windows/ui_interfaces/x11/XcbWindowInterface.h b/src/windows/ui_interfaces/x11/XcbWindowInterface.h deleted file mode 100644 index cfa71f5..0000000 --- a/src/windows/ui_interfaces/x11/XcbWindowInterface.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -namespace mt -{ -class Window; -class Screen; -} -struct xcb_connection_t; -struct xcb_screen_t; - -class XcbWindowInterface -{ -public: - - static std::unique_ptr Create(); - - void Add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask) const; - - void Show(mt::Window* window, xcb_connection_t* connection) const; - - void Paint(mt::Window* window, xcb_connection_t* connection, xcb_screen_t* screen, unsigned gc) const; - - void Clear(mt::Window* window, xcb_connection_t* connection) const; - - void Map(mt::Window* window, xcb_connection_t* connection) const; -}; - -using XcbWindowInterfacePtr = std::unique_ptr;