diff options
-rw-r--r-- | include/cru/platform/gui/xcb/Cursor.h | 25 | ||||
-rw-r--r-- | include/cru/platform/gui/xcb/UiApplication.h | 5 | ||||
-rw-r--r-- | src/platform/gui/xcb/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/platform/gui/xcb/Cursor.cpp | 38 | ||||
-rw-r--r-- | src/platform/gui/xcb/UiApplication.cpp | 7 |
5 files changed, 66 insertions, 12 deletions
diff --git a/include/cru/platform/gui/xcb/Cursor.h b/include/cru/platform/gui/xcb/Cursor.h index d51c33c1..02ede7dd 100644 --- a/include/cru/platform/gui/xcb/Cursor.h +++ b/include/cru/platform/gui/xcb/Cursor.h @@ -5,17 +5,16 @@ #include "Base.h" #include <xcb/xcb.h> +#include <xcb/xcb_cursor.h> +#include <memory> +#include <string_view> +#include <unordered_map> namespace cru::platform::gui::xcb { class XcbUiApplication; + class XcbCursor : public XcbResource, public virtual ICursor { public: - /** - * Specification at - * https://www.x.org/archive/X11R7.7/doc/man/man3/Xcursor.3.xhtml. - */ - static XcbCursor* LoadXCursor(io::Stream* stream); - XcbCursor(XcbUiApplication* application, xcb_cursor_t cursor, bool auto_free); ~XcbCursor() override; @@ -28,6 +27,18 @@ class XcbCursor : public XcbResource, public virtual ICursor { }; class XcbCursorManager : public XcbResource, public virtual ICursorManager { - virtual std::shared_ptr<ICursor> GetSystemCursor(SystemCursorType type) = 0; + public: + explicit XcbCursorManager(XcbUiApplication* application); + ~XcbCursorManager() override; + + std::shared_ptr<ICursor> GetSystemCursor(SystemCursorType type) override; + + private: + std::shared_ptr<XcbCursor> LoadXCursor(std::string_view name); + + private: + XcbUiApplication* application_; + xcb_cursor_context_t* xcb_cursor_context_; + std::unordered_map<SystemCursorType, std::shared_ptr<XcbCursor>> cursors_; }; } // namespace cru::platform::gui::xcb diff --git a/include/cru/platform/gui/xcb/UiApplication.h b/include/cru/platform/gui/xcb/UiApplication.h index 4fa4ec8d..80995179 100644 --- a/include/cru/platform/gui/xcb/UiApplication.h +++ b/include/cru/platform/gui/xcb/UiApplication.h @@ -12,6 +12,7 @@ namespace cru::platform::gui::xcb { class XcbWindow; +class XcbCursorManager; class XcbUiApplication : public XcbResource, public virtual IUiApplication { friend XcbWindow; @@ -68,7 +69,7 @@ class XcbUiApplication : public XcbResource, public virtual IUiApplication { cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override; - virtual ICursorManager* GetCursorManager() = 0; + ICursorManager* GetCursorManager() override; virtual IClipboard* GetClipboard() = 0; @@ -105,5 +106,7 @@ class XcbUiApplication : public XcbResource, public virtual IUiApplication { bool is_quit_on_all_window_closed_; std::vector<XcbWindow*> windows_; + + XcbCursorManager* cursor_manager_; }; } // namespace cru::platform::gui::xcb diff --git a/src/platform/gui/xcb/CMakeLists.txt b/src/platform/gui/xcb/CMakeLists.txt index 15bf1a79..fa5cc0bf 100644 --- a/src/platform/gui/xcb/CMakeLists.txt +++ b/src/platform/gui/xcb/CMakeLists.txt @@ -1,5 +1,6 @@ find_library(LIBRARY_CAIRO cairo REQUIRED) find_library(LIBRARY_XCB xcb REQUIRED) +find_library(LIBRARY_XCB_CURSOR xcb-cursor REQUIRED) add_library(CruPlatformGuiXcb Cursor.cpp Keyboard.cpp @@ -8,5 +9,5 @@ add_library(CruPlatformGuiXcb ) target_link_libraries(CruPlatformGuiXcb PUBLIC CruPlatformGui CruPlatformGraphicsCairo - ${LIBRARY_XCB} ${LIBRARY_CAIRO} + ${LIBRARY_XCB} ${LIBRARY_XCB_CURSOR} ${LIBRARY_CAIRO} ) diff --git a/src/platform/gui/xcb/Cursor.cpp b/src/platform/gui/xcb/Cursor.cpp index 7bc73f6d..5582c6a6 100644 --- a/src/platform/gui/xcb/Cursor.cpp +++ b/src/platform/gui/xcb/Cursor.cpp @@ -1,12 +1,13 @@ #include "cru/platform/gui/xcb/Cursor.h" -#include "cru/base/Base.h" +#include "cru/base/Exception.h" +#include "cru/platform/gui/Cursor.h" #include "cru/platform/gui/xcb/UiApplication.h" #include <xcb/xcb.h> +#include <xcb/xcb_cursor.h> +#include <memory> namespace cru::platform::gui::xcb { -XcbCursor* XcbCursor::LoadXCursor(io::Stream* stream) { NotImplemented(); } - XcbCursor::XcbCursor(XcbUiApplication* application, xcb_cursor_t cursor, bool auto_free) : application_(application), cursor_(cursor), auto_free_(auto_free) {} @@ -19,4 +20,35 @@ XcbCursor::~XcbCursor() { xcb_cursor_t XcbCursor::GetXcbCursor() { return cursor_; } +XcbCursorManager::XcbCursorManager(XcbUiApplication* application) + : application_(application) { + auto code = xcb_cursor_context_new(application->GetXcbConnection(), + application->GetFirstXcbScreen(), + &xcb_cursor_context_); + if (code != 0) { + throw PlatformException("Failed to call xcb_cursor_context_new."); + } + + cursors_[SystemCursorType::Arrow] = + std::make_shared<XcbCursor>(application_, XCB_CURSOR_NONE, false); + cursors_[SystemCursorType::Hand] = LoadXCursor("pointer"); + cursors_[SystemCursorType::IBeam] = LoadXCursor("ibeam"); +} + +XcbCursorManager::~XcbCursorManager() { + xcb_cursor_context_free(xcb_cursor_context_); +} + +std::shared_ptr<ICursor> XcbCursorManager::GetSystemCursor( + SystemCursorType type) { + return cursors_[type]; +} + +std::shared_ptr<XcbCursor> XcbCursorManager::LoadXCursor( + std::string_view name) { + return std::make_shared<XcbCursor>( + application_, xcb_cursor_load_cursor(xcb_cursor_context_, name.data()), + true); +} + } // namespace cru::platform::gui::xcb diff --git a/src/platform/gui/xcb/UiApplication.cpp b/src/platform/gui/xcb/UiApplication.cpp index 74b20bd7..b95e669a 100644 --- a/src/platform/gui/xcb/UiApplication.cpp +++ b/src/platform/gui/xcb/UiApplication.cpp @@ -2,6 +2,7 @@ #include "cru/platform/graphics/cairo/CairoGraphicsFactory.h" #include "cru/platform/gui/Window.h" +#include "cru/platform/gui/xcb/Cursor.h" #include "cru/platform/gui/xcb/Window.h" #include <poll.h> @@ -30,9 +31,13 @@ XcbUiApplication::XcbUiApplication( const xcb_setup_t *setup = xcb_get_setup(connection); xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); this->screen_ = iter.data; + + cursor_manager_ = new XcbCursorManager(this); } XcbUiApplication::~XcbUiApplication() { + delete cursor_manager_; + xcb_disconnect(this->xcb_connection_); if (release_cairo_factory_) { delete cairo_factory_; @@ -137,6 +142,8 @@ XcbUiApplication::GetGraphicsFactory() { return cairo_factory_; } +ICursorManager *XcbUiApplication::GetCursorManager() { return cursor_manager_; } + IMenu *XcbUiApplication::GetApplicationMenu() { return nullptr; } void XcbUiApplication::RegisterWindow(XcbWindow *window) { |