From e8d78d6476751ca69b9a9349c62f3e79a17ed4b7 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Mon, 20 Feb 2023 19:38:14 -0800 Subject: [PATCH 1/9] feature: implement xcb for windowing Signed-off-by: Michael Pollind --- 3rdparty/CMakeLists.txt | 2 + include/nbl/core/string/StringLiteral.h | 5 + include/nbl/ui/CClipboardManagerXcb.h | 63 +++++ include/nbl/ui/CCursorControlXcb.h | 34 +++ include/nbl/ui/CWindowManagerXcb.h | 95 +++++++ include/nbl/ui/CWindowXcb.h | 85 ++++++ include/nbl/ui/IWindowXcb.h | 87 ++++++ include/nbl/ui/XcbConnection.h | 111 ++++++++ include/nbl/ui/declarations.h | 3 +- include/nbl/ui/definitions.h | 12 +- include/nbl/video/CVulkanConnection.h | 4 + include/nbl/video/surface/CSurfaceVulkan.h | 19 +- src/nbl/CMakeLists.txt | 20 +- src/nbl/ui/CClipboardManagerXcb.cpp | 165 ++++++++++++ src/nbl/ui/CCursorControlXcb.cpp | 51 ++++ src/nbl/ui/CWindowXcb.cpp | 296 +++++++++++++++++++++ src/nbl/ui/XcbConnection.cpp | 60 +++++ src/nbl/video/CSurfaceVulkan.cpp | 24 ++ src/nbl/video/CVulkanConnection.cpp | 2 + 19 files changed, 1127 insertions(+), 11 deletions(-) create mode 100644 include/nbl/ui/CClipboardManagerXcb.h create mode 100644 include/nbl/ui/CCursorControlXcb.h create mode 100644 include/nbl/ui/CWindowManagerXcb.h create mode 100644 include/nbl/ui/CWindowXcb.h create mode 100644 include/nbl/ui/IWindowXcb.h create mode 100644 include/nbl/ui/XcbConnection.h create mode 100644 src/nbl/ui/CClipboardManagerXcb.cpp create mode 100644 src/nbl/ui/CCursorControlXcb.cpp create mode 100644 src/nbl/ui/CWindowXcb.cpp create mode 100644 src/nbl/ui/XcbConnection.cpp diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 9787686d7a..fcc0c1d0df 100755 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -40,6 +40,8 @@ set(VOLK_PULL_IN_VULKAN OFF CACHE INTERNAL "" FORCE) # Needed to make sure vulka if (WIN32) set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_WIN32_KHR) +elseif(UNIX AND NOT ANDROID AND NOT APPLE) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_XCB_KHR) endif() add_subdirectory(volk volk EXCLUDE_FROM_ALL) diff --git a/include/nbl/core/string/StringLiteral.h b/include/nbl/core/string/StringLiteral.h index e79fd044b8..28978aec1a 100644 --- a/include/nbl/core/string/StringLiteral.h +++ b/include/nbl/core/string/StringLiteral.h @@ -17,6 +17,11 @@ struct StringLiteral std::copy_n(str, N, value); } + // the size includes the null terminator + constexpr size_t size() const { + return N; + } + char value[N]; }; diff --git a/include/nbl/ui/CClipboardManagerXcb.h b/include/nbl/ui/CClipboardManagerXcb.h new file mode 100644 index 0000000000..0b0b74d13a --- /dev/null +++ b/include/nbl/ui/CClipboardManagerXcb.h @@ -0,0 +1,63 @@ +#ifndef _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ +#define _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ + +#include +#include +#include +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/core/decl/Types.h" +#include "nbl/ui/IClipboardManager.h" +#include "nbl/ui/XcbConnection.h" + +namespace nbl::ui +{ + +// details on XCB clipboard protocol: https://tronche.com/gui/x/icccm/sec-2.html#s-2 +class NBL_API2 CClipboardManagerXcb final : public IClipboardManager +{ + using base_t = IClipboardManager; + public: + inline CClipboardManagerXcb(core::smart_refctd_ptr&& connect): + m_xcbConnection(std::move(connect)) {} + + virtual std::string getClipboardText() override; + virtual bool setClipboardText(const std::string_view& data) override; + + void process(const IWindowXcb* window, xcb_generic_event_t* event); + private: + core::smart_refctd_ptr m_xcbConnection; + + xcb_window_t getClipboardWindow(); + + struct { + std::string m_data; + std::vector m_formats; + } m_stagedClipboard; + + std::mutex m_clipboardMutex; + std::condition_variable m_clipboardResponseCV; + std::string m_clipboardResponse; + // bool ready = false; + + XcbConnection::XCBAtomToken m_CLIPBOARD; + XcbConnection::XCBAtomToken m_TARGETS; + XcbConnection::XCBAtomToken m_INCR; + + + XcbConnection::XCBAtomToken m_formatUTF8_0; + XcbConnection::XCBAtomToken m_formatUTF8_1; + XcbConnection::XCBAtomToken m_formatUTF8_2; + XcbConnection::XCBAtomToken m_formatGTK; + XcbConnection::XCBAtomToken m_formatString; + XcbConnection::XCBAtomToken m_formatText; + XcbConnection::XCBAtomToken m_formatTextPlain; + + +}; + +} + +#endif + +#endif \ No newline at end of file diff --git a/include/nbl/ui/CCursorControlXcb.h b/include/nbl/ui/CCursorControlXcb.h new file mode 100644 index 0000000000..5c6506829e --- /dev/null +++ b/include/nbl/ui/CCursorControlXcb.h @@ -0,0 +1,34 @@ +#ifndef __NBL_SYSTEM_C_CURSOR_CONTROL_XCB_H_INCLUDED__ +#define __NBL_SYSTEM_C_CURSOR_CONTROL_XCB_H_INCLUDED__ + + +#include "nbl/ui/ICursorControl.h" +#include "nbl/ui/XcbConnection.h" + +#ifdef _NBL_PLATFORM_LINUX_ + +namespace nbl::ui +{ +class NBL_API2 CCursorControlXcb final : public ICursorControl +{ + core::smart_refctd_ptr m_xcbConnection; + + public: + inline CCursorControlXcb( + core::smart_refctd_ptr&& xcbConnection) : + m_xcbConnection(std::move(xcbConnection)) {} + + void setVisible(bool visible) override; + bool isVisible() const override; + + void setPosition(SPosition pos) override; + void setRelativePosition(IWindow* window, SRelativePosition pos) override; + + SPosition getPosition() override; + SRelativePosition getRelativePosition(IWindow* window) override; +}; +} + +#endif + +#endif \ No newline at end of file diff --git a/include/nbl/ui/CWindowManagerXcb.h b/include/nbl/ui/CWindowManagerXcb.h new file mode 100644 index 0000000000..39da3eeee6 --- /dev/null +++ b/include/nbl/ui/CWindowManagerXcb.h @@ -0,0 +1,95 @@ +#ifndef C_WINDOW_MANAGER_XCB +#define C_WINDOW_MANAGER_XCB + +#ifdef _NBL_PLATFORM_LINUX_ +#include "nbl/core/decl/Types.h" + +#include "nbl/system/DefaultFuncPtrLoader.h" + +#include "nbl/ui/IWindow.h" +#include "nbl/ui/IWindowManager.h" + +#include +#include +#include + +#include +#include +#include + +namespace nbl::ui +{ + +NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(Xcb, system::DefaultFuncPtrLoader, + xcb_destroy_window, + xcb_generate_id, + xcb_create_window, + xcb_connect, + xcb_disconnect, + xcb_map_window, + xcb_get_setup, + xcb_setup_roots_iterator, + xcb_flush, + xcb_intern_atom, + xcb_intern_atom_reply, + xcb_unmap_window, + xcb_get_property, + xcb_get_property_reply, + xcb_get_property_value_length, + xcb_change_property, + xcb_configure_window_checked, + xcb_get_property_value, + xcb_wait_for_event, + xcb_send_event, + xcb_request_check, + xcb_delete_property, + xcb_change_window_attributes, + xcb_warp_pointer, + xcb_query_pointer, + xcb_query_pointer_reply, + xcb_get_selection_owner_reply, + xcb_get_selection_owner +); + +NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(XcbIcccm, system::DefaultFuncPtrLoader, + xcb_icccm_set_wm_hints, + xcb_icccm_size_hints_set_size, + xcb_icccm_size_hints_set_min_size, + xcb_icccm_size_hints_set_max_size, + xcb_icccm_set_wm_normal_hints +); + +class CWindowManagerXcb : public IWindowManager +{ +public: + + virtual bool setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) override; + virtual bool setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) override; + virtual bool setWindowRotation_impl(IWindow* window, bool landscape) override; + virtual bool setWindowVisible_impl(IWindow* window, bool visible) override; + virtual bool setWindowMaximized_impl(IWindow* window, bool maximized) override; + + inline SDisplayInfo getPrimaryDisplayInfo() const override final { + return SDisplayInfo(); + } + + CWindowManagerXcb(); + ~CWindowManagerXcb() override = default; + + virtual core::smart_refctd_ptr createWindow(IWindow::SCreationParams&& creationParams) override; + + virtual void destroyWindow(IWindow* wnd) override final {} + + const Xcb& getXcbFunctionTable() const { return m_xcb; } + const XcbIcccm& getXcbIcccmFunctionTable() const { return m_xcbIcccm; } + +private: + + Xcb m_xcb = Xcb("xcb"); // function tables + XcbIcccm m_xcbIcccm = XcbIcccm("xcb-icccm"); +}; + + +} +#endif +#endif \ No newline at end of file diff --git a/include/nbl/ui/CWindowXcb.h b/include/nbl/ui/CWindowXcb.h new file mode 100644 index 0000000000..4fb5032cae --- /dev/null +++ b/include/nbl/ui/CWindowXcb.h @@ -0,0 +1,85 @@ +#ifndef __C_WINDOW_XCB_H_INCLUDED__ +#define __C_WINDOW_XCB_H_INCLUDED__ + +#include + +#include "nbl/core/decl/smart_refctd_ptr.h" +#include "nbl/ui/CClipboardManagerXcb.h" +#include "nbl/ui/IWindowXcb.h" +#include "nbl/ui/XcbConnection.h" + +namespace nbl::ui +{ + +class CCursorControlXcb; +class CWindowManagerXcb; +class CClipboardManagerXcb; + +class NBL_API2 CWindowXcb final : public IWindowXcb +{ + +public: + CWindowXcb(core::smart_refctd_ptr&& winManager, SCreationParams&& params); + ~CWindowXcb(); + + // Display* getDisplay() const override { return m_dpy; } + xcb_window_t getXcbWindow() const override { return m_xcbWindow; } + xcb_connection_t* getXcbConnection() const override { + return m_xcbConnection->getRawConnection(); + } + + virtual IClipboardManager* getClipboardManager() override; + virtual ICursorControl* getCursorControl() override; + virtual IWindowManager* getManager() override; + + virtual bool setWindowSize_impl(uint32_t width, uint32_t height) override; + virtual bool setWindowPosition_impl(int32_t x, int32_t y) override; + virtual bool setWindowRotation_impl(bool landscape) override; + virtual bool setWindowVisible_impl(bool visible) override; + virtual bool setWindowMaximized_impl(bool maximized) override; + + virtual void setCaption(const std::string_view& caption) override; + +private: + CWindowXcb(core::smart_refctd_ptr&& sys, uint32_t _w, uint32_t _h, E_CREATE_FLAGS _flags); + + core::smart_refctd_ptr m_windowManager; + core::smart_refctd_ptr m_xcbConnection; + core::smart_refctd_ptr m_cursorControl; + core::smart_refctd_ptr m_clipboardManager; + + class CDispatchThread final : public system::IThreadHandler + { + public: + + inline CDispatchThread(CWindowXcb& window); + inline ~CDispatchThread() { + } + + void init(); + void exit(); + void work(lock_t& lock); + + inline bool wakeupPredicate() const { return true; } + inline bool continuePredicate() const { return true; } + private: + CWindowXcb& m_window; + // xcb_connection_t* m_connection = nullptr; + friend class CWindowXcb; + } m_dispatcher; + + xcb_window_t m_xcbWindow = 0; + + XcbConnection::XCBAtomToken m_WM_DELETE_WINDOW; + XcbConnection::XCBAtomToken m_WM_PROTOCOLS; + XcbConnection::XCBAtomToken m_NET_WM_PING; + + XcbConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_VERT; + XcbConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_HORZ; + XcbConnection::XCBAtomToken m_NET_WM_STATE_FULLSCREEN; + +}; + +} + +#endif diff --git a/include/nbl/ui/IWindowXcb.h b/include/nbl/ui/IWindowXcb.h new file mode 100644 index 0000000000..b9afdfda5d --- /dev/null +++ b/include/nbl/ui/IWindowXcb.h @@ -0,0 +1,87 @@ +#ifndef __NBL_I_WINDOW_XCB_H_INCLUDED__ +#define __NBL_I_WINDOW_XCB_H_INCLUDED__ + +#include "nbl/core/util/bitflag.h" +#include "nbl/ui/IWindow.h" +#include "nbl/ui/XcbConnection.h" +#include + +#ifdef _NBL_PLATFORM_LINUX_ + +namespace nbl::ui +{ + +class NBL_API2 IWindowXcb : public IWindow +{ + protected: + virtual ~IWindowXcb() = default; + inline IWindowXcb(SCreationParams&& params) : IWindow(std::move(params)) {} + + public: + using IWindow::IWindow; + + const void* getNativeHandle() const { return nullptr; } + virtual xcb_window_t getXcbWindow() const = 0; + // virtual xcb_window_t getXcbRootWindow() const = 0; + virtual xcb_connection_t* getXcbConnection() const = 0; + + virtual bool setWindowSize_impl(uint32_t width, uint32_t height) = 0; + virtual bool setWindowPosition_impl(int32_t x, int32_t y) = 0; + virtual bool setWindowRotation_impl(bool landscape) = 0; + virtual bool setWindowVisible_impl(bool visible) = 0; + virtual bool setWindowMaximized_impl(bool maximized) = 0; + + static XcbConnection::MotifWmHints fetchMotifMWHints(IWindow::E_CREATE_FLAGS flags) { + core::bitflag motifFlags(XcbConnection::MWM_HINTS_NONE); + core::bitflag motifFunctions(XcbConnection::MWM_FUNC_NONE); + core::bitflag motifDecorations(XcbConnection::MWM_DECOR_NONE); + motifFlags |= XcbConnection::MWM_HINTS_DECORATIONS; + + if (flags & IWindow::ECF_BORDERLESS) { + motifDecorations |= XcbConnection::MWM_DECOR_ALL; + } else { + motifDecorations |= XcbConnection::MWM_DECOR_BORDER; + motifDecorations |= XcbConnection::MWM_DECOR_RESIZEH; + motifDecorations |= XcbConnection::MWM_DECOR_TITLE; + + // minimize button + if(flags & IWindow::ECF_MINIMIZED) { + motifDecorations |= XcbConnection::MWM_DECOR_MINIMIZE; + motifFunctions |= XcbConnection::MWM_FUNC_MINIMIZE; + } + + // maximize button + if(flags & IWindow::ECF_MAXIMIZED) { + motifDecorations |= XcbConnection::MWM_DECOR_MAXIMIZE; + motifFunctions |= XcbConnection::MWM_FUNC_MAXIMIZE; + } + + // close button + motifFunctions |= XcbConnection::MWM_FUNC_CLOSE; + } + + if(motifFunctions.value != XcbConnection::MWM_FUNC_NONE) { + motifFlags |= XcbConnection::MWM_HINTS_FUNCTIONS; + motifFunctions |= XcbConnection::MWM_FUNC_RESIZE; + motifFunctions |= XcbConnection::MWM_FUNC_MOVE; + } else { + motifFunctions = XcbConnection::MWM_FUNC_ALL; + } + + XcbConnection::MotifWmHints hints; + hints.flags = motifFlags.value; + hints.functions = motifFunctions.value; + hints.decorations = motifDecorations.value; + hints.input_mode = 0; + hints.status = 0; + return hints; + + } + +}; + +} + +#endif + +#endif \ No newline at end of file diff --git a/include/nbl/ui/XcbConnection.h b/include/nbl/ui/XcbConnection.h new file mode 100644 index 0000000000..fd635e0e6f --- /dev/null +++ b/include/nbl/ui/XcbConnection.h @@ -0,0 +1,111 @@ +#ifndef C_XCB_CONNECTION_XCB +#define C_XCB_CONNECTION_XCB + +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/core/decl/Types.h" +#include "nbl/core/string/StringLiteral.h" +#include "nbl/core/decl/smart_refctd_ptr.h" +#include "nbl/ui/CWindowManagerXcb.h" + +#include +#include +#include + +#include + +namespace nbl::ui +{ + +class XcbConnection : public core::IReferenceCounted { +public: + template + struct XCBAtomToken { + xcb_atom_t token = 0; + bool fetched = false; + }; + + XcbConnection(core::smart_refctd_ptr&& windowManager); + virtual ~XcbConnection() override; + + template + inline xcb_atom_t resolveXCBAtom(XCBAtomToken& token, bool only_if_exists = true, bool forced = false) const { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + if(token.fetched && !forced) { + return token.token; + } + token.fetched = true; + size_t size = Name.size() - 1; // -1 to remove the null terminator + xcb_intern_atom_cookie_t cookie = xcb.pxcb_intern_atom(m_connection, only_if_exists, size, Name.value); + if(xcb_intern_atom_reply_t* reply = xcb.pxcb_intern_atom_reply(m_connection, cookie, nullptr)) { + token.token = reply->atom; + free(reply); + return token.token; + } + return token.token; + } + + void setNetMWState(xcb_window_t rootWindow, xcb_window_t window, bool set, xcb_atom_t first, xcb_atom_t second = XCB_NONE) const; + + enum MotifFlags: uint32_t { + MWM_HINTS_NONE = 0, + MWM_HINTS_FUNCTIONS = (1L << 0), + MWM_HINTS_DECORATIONS = (1L << 1), + MWM_HINTS_INPUT_MODE = (1L << 2), + MWM_HINTS_STATUS = (1L << 3), + }; + + enum MotifFunctions: uint32_t { + MWM_FUNC_NONE = 0, + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), + }; + + enum MotifDecorations: uint32_t { + MWM_DECOR_NONE = 0, + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), + }; + + // insane magic in xcb for window hinting good luck finding documentation + // https://fossies.org/linux/motif/lib/Xm/MwmUtil.h + struct MotifWmHints { + MotifFlags flags = MotifFlags::MWM_HINTS_NONE; + MotifFunctions functions = MotifFunctions::MWM_FUNC_NONE; + MotifDecorations decorations = MotifDecorations::MWM_DECOR_NONE; + uint32_t input_mode = 0; // unused + uint32_t status = 0; // unused + }; + void setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const; + + inline xcb_connection_t* getRawConnection() const { + return m_connection; + } + + const Xcb& getXcbFunctionTable() const { return m_windowManager->getXcbFunctionTable(); } + const XcbIcccm& getXcbIcccmFunctionTable() const { return m_windowManager->getXcbIcccmFunctionTable(); } + + const xcb_screen_t* primaryScreen(); + +private: + core::smart_refctd_ptr m_windowManager; + xcb_connection_t* m_connection = nullptr; + + mutable XcbConnection::XCBAtomToken m_NET_WM_STATE; + mutable XcbConnection::XCBAtomToken m_MOTIF_WM_HINTS; +}; + +} // namespace nbl::ui + +#endif + +#endif // C_XCB_HANDLER_XCB diff --git a/include/nbl/ui/declarations.h b/include/nbl/ui/declarations.h index 4a2bce9552..939f09834f 100644 --- a/include/nbl/ui/declarations.h +++ b/include/nbl/ui/declarations.h @@ -13,6 +13,7 @@ #elif defined(_NBL_BUILD_WITH_WAYLAND) && defined(_NBL_TEST_WAYLAND) # include "nbl/ui/CWindowManagerWayland.h" #elif defined(_NBL_PLATFORM_LINUX_) +# include "nbl/ui/CWindowManagerXcb.h" #endif // TODO more platforms (android) // clipboards @@ -22,4 +23,4 @@ #include "nbl/ui/IInputEventChannel.h" -#endif \ No newline at end of file +#endif diff --git a/include/nbl/ui/definitions.h b/include/nbl/ui/definitions.h index 1eab60d597..fdf82547a9 100644 --- a/include/nbl/ui/definitions.h +++ b/include/nbl/ui/definitions.h @@ -1,10 +1,18 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_UI_DEFINITIONS_H_INCLUDED_ -#define _NBL_UI_DEFINITIONS_H_INCLUDED_ + +#ifndef __NBL_UI_DEFINITIONS_H_INCLUDED__ +#define __NBL_UI_DEFINITIONS_H_INCLUDED__ // dependencies #include "nbl/system/definitions.h" +// windows +#include "nbl/ui/CWindowManagerWin32.h" +#include "nbl/ui/CWindowManagerXcb.h" + +#include "nbl/ui/CWindowWin32.h" +#include "nbl/ui/CWindowXcb.h" + #endif \ No newline at end of file diff --git a/include/nbl/video/CVulkanConnection.h b/include/nbl/video/CVulkanConnection.h index 71b8e02e8c..7e24309452 100644 --- a/include/nbl/video/CVulkanConnection.h +++ b/include/nbl/video/CVulkanConnection.h @@ -6,6 +6,10 @@ #if defined(_NBL_PLATFORM_WINDOWS_) # include "nbl/ui/IWindowWin32.h" +#elif defined(_NBL_PLATFORM_LINUX_) +# include "nbl/ui/IWindowXcb.h" +#else +# error "Unsupported platform" #endif #include diff --git a/include/nbl/video/surface/CSurfaceVulkan.h b/include/nbl/video/surface/CSurfaceVulkan.h index 203f580f67..a4fe736b9d 100644 --- a/include/nbl/video/surface/CSurfaceVulkan.h +++ b/include/nbl/video/surface/CSurfaceVulkan.h @@ -3,6 +3,7 @@ #include "BuildConfigOptions.h" +#include "nbl/ui/IWindowXcb.h" #include "nbl/video/surface/ISurface.h" #include "nbl/video/CVulkanConnection.h" @@ -45,9 +46,21 @@ class NBL_API2 CSurfaceVulkanWin32 final : public CSurface create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window); }; -#elif defined _NBL_PLATFORM_LINUX_ -// TODO: later, not this week -#elif defined _NBL_PLATFORM_ANDROID_ +#elif defined(_NBL_PLATFORM_LINUX_) +class NBL_API2 CSurfaceVulkanXcb final : public CSurface +{ + using this_t = CSurfaceVulkanXcb; + using base_t = CSurface; +public: + inline CSurfaceVulkanXcb(core::smart_refctd_ptr&& window, core::smart_refctd_ptr&& api, VkSurfaceKHR surf) : + base_t(std::move(window), std::move(api), surf) + { + } + + static core::smart_refctd_ptr create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window); +}; + +#elif defined(_NBL_PLATFORM_ANDROID_) // TODO: later, not this week #endif } diff --git a/src/nbl/CMakeLists.txt b/src/nbl/CMakeLists.txt index 878d658ae3..fc6f72504e 100755 --- a/src/nbl/CMakeLists.txt +++ b/src/nbl/CMakeLists.txt @@ -170,7 +170,6 @@ set(NBL_SYSTEM_SOURCES ${NBL_ROOT_PATH}/src/nbl/system/CAPKResourcesArchive.cpp ${NBL_ROOT_PATH}/src/nbl/system/ISystem.cpp ${NBL_ROOT_PATH}/src/nbl/system/IFileArchive.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CColoredStdoutLoggerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CStdoutLoggerAndroid.cpp ${NBL_ROOT_PATH}/src/nbl/system/CFileViewVirtualAllocatorWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CFileViewVirtualAllocatorPOSIX.cpp @@ -178,13 +177,21 @@ set(NBL_SYSTEM_SOURCES ${NBL_ROOT_PATH}/src/nbl/system/CFileWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CFilePOSIX.cpp ${NBL_ROOT_PATH}/src/nbl/system/CSystemWin32.cpp + ${NBL_ROOT_PATH}/src/nbl/system/ISystemPOSIX.cpp ${NBL_ROOT_PATH}/src/nbl/system/CSystemAndroid.cpp ${NBL_ROOT_PATH}/src/nbl/system/ISystemPOSIX.cpp + ${NBL_ROOT_PATH}/src/nbl/system/CSystemWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CSystemLinux.cpp ) set(NBL_UI_SOURCES ${NBL_ROOT_PATH}/src/nbl/ui/CWindowWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXcb.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/XcbConnection.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlWin32.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerWin32.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerXcb.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlXcb.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerAndroid.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CGraphicalApplicationAndroid.cpp ) @@ -555,10 +562,9 @@ endif() # Linux Display Systems if (UNIX AND NOT ANDROID AND NOT APPLE) - target_include_directories(Nabla PUBLIC - ${X11_INCLUDE_DIR} - X11_Xrandr_INCLUDE_PATH - ${X11_xf86vmode_INCLUDE_PATH} + target_include_directories(Nabla PUBLIC + ${X11_xcb_INCLUDE_PATH} + ${X11_xcb_icccm_INCLUDE_PATH} ) endif() @@ -569,6 +575,10 @@ target_link_libraries(Nabla PRIVATE volk) if(WIN32) target_compile_definitions(Nabla PRIVATE VK_USE_PLATFORM_WIN32_KHR) endif() +if(UNIX AND NOT ANDROID AND NOT APPLE) + target_compile_definitions(Nabla PRIVATE VK_USE_PLATFORM_XCB_KHR) +endif() + # CUDA if (NBL_COMPILE_WITH_CUDA) target_include_directories(Nabla PUBLIC ${CUDAToolkit_INCLUDE_DIRS}) diff --git a/src/nbl/ui/CClipboardManagerXcb.cpp b/src/nbl/ui/CClipboardManagerXcb.cpp new file mode 100644 index 0000000000..95f1da3f60 --- /dev/null +++ b/src/nbl/ui/CClipboardManagerXcb.cpp @@ -0,0 +1,165 @@ + +#include "nbl/ui/XcbConnection.h" +#include +#include +#include +#include +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/ui/CClipboardManagerXcb.h" + +namespace nbl::ui +{ + std::string CClipboardManagerXcb::getClipboardText() { + { + std::unique_lock lk(m_clipboardMutex); + m_clipboardResponseCV.wait_until(lk, std::chrono::system_clock::now() + std::chrono::seconds(1)); + } + std::lock_guard lk(m_clipboardMutex); + std::string response = std::move(m_clipboardResponse); + m_clipboardResponse = std::string(); + return response; + } + + xcb_window_t CClipboardManagerXcb::getClipboardWindow() { + const auto& xcb = m_xcbConnection->getXcbFunctionTable(); + xcb_window_t window = 0; + auto cookie = xcb.pxcb_get_selection_owner(m_xcbConnection->getRawConnection(), + m_xcbConnection->resolveXCBAtom(m_CLIPBOARD)); + if(xcb_get_selection_owner_reply_t* reply = + xcb.pxcb_get_selection_owner_reply(m_xcbConnection->getRawConnection(), cookie, nullptr)) { + core::SRAIIBasedExiter exitReply([reply]() -> void { + free(reply); + }); + return reply->owner; + } + return 0; + + } + bool CClipboardManagerXcb::setClipboardText(const std::string_view& data) { + std::lock_guard lk(m_clipboardMutex); + m_stagedClipboard.m_data = data; + m_stagedClipboard.m_formats = { + m_xcbConnection->resolveXCBAtom(m_formatUTF8_0), + m_xcbConnection->resolveXCBAtom(m_formatUTF8_1), + m_xcbConnection->resolveXCBAtom(m_formatUTF8_2), + m_xcbConnection->resolveXCBAtom(m_formatGTK), + m_xcbConnection->resolveXCBAtom(m_formatString), + m_xcbConnection->resolveXCBAtom(m_formatText), + m_xcbConnection->resolveXCBAtom(m_formatTextPlain) + }; + return true; + } + + void CClipboardManagerXcb::process(const IWindowXcb* window, xcb_generic_event_t* event) { + const auto& xcb = m_xcbConnection->getXcbFunctionTable(); + + auto TARGETS = m_xcbConnection->resolveXCBAtom(m_TARGETS); + + switch(event->response_type & ~0x80) { + // XCB_ATOM + // Somone is requesting the clipboard data + case XCB_SELECTION_REQUEST: { + auto* sne = reinterpret_cast(event); + if(sne->requestor == window->getXcbWindow()) { + if(sne->target == TARGETS) { + std::vector targets; + { + std::lock_guard lk(m_clipboardMutex); + for(auto& format : m_stagedClipboard.m_formats) { + targets.push_back(format); + } + } + targets.push_back(m_xcbConnection->resolveXCBAtom(m_TARGETS)); + xcb.pxcb_change_property( + m_xcbConnection->getRawConnection(), + XCB_PROP_MODE_REPLACE, + sne->requestor, + sne->property, + XCB_ATOM, + 8*sizeof(xcb_atom_t), + targets.size(), + &targets[0]); + } else { + std::lock_guard lk(m_clipboardMutex); + xcb.pxcb_change_property( + m_xcbConnection->getRawConnection(), + XCB_PROP_MODE_REPLACE, + sne->requestor, + sne->property, + sne->target, + 8, + m_stagedClipboard.m_data.size(), + m_stagedClipboard.m_data.data()); + } + } + + // Notify the "requestor" that we've already updated the property. + xcb_selection_notify_event_t notify; + notify.response_type = XCB_SELECTION_NOTIFY; + notify.pad0 = 0; + notify.sequence = 0; + notify.time = sne->time; + notify.requestor = sne->requestor; + notify.selection = sne->selection; + notify.target = sne->target; + notify.property = sne->property; + + xcb.pxcb_send_event(m_xcbConnection->getRawConnection(), false, + sne->requestor, + XCB_EVENT_MASK_NO_EVENT, // SelectionNotify events go without mask + (const char*)¬ify); + + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + break; + } + // Someone else has new content in the clipboard, so is + // notifying us that we should delete our data now. + case XCB_SELECTION_CLEAR: { + auto* sne = reinterpret_cast(event); + if (sne->selection == m_xcbConnection->resolveXCBAtom(m_CLIPBOARD)) { + std::lock_guard lock(m_clipboardMutex); + m_stagedClipboard.m_formats = {}; + m_stagedClipboard.m_data = std::string(); + } + break; + } + // we've requested the clipboard data, and this is the reply + case XCB_SELECTION_NOTIFY: { + auto* sne = reinterpret_cast(event); + if(sne->requestor == window->getXcbWindow()){ + // xcb.pxcb_get_a + xcb_atom_t fieldType = XCB_ATOM; + if(sne->target != TARGETS) { + fieldType = sne->target; + } + xcb_get_property_cookie_t cookie = xcb.pxcb_get_property(m_xcbConnection->getRawConnection(), true, + sne->requestor, + sne->property, + fieldType, 0, 0x1fffffff); // 0x1fffffff = INT32_MAX / 4 + if(xcb_get_property_reply_t* reply = + xcb.pxcb_get_property_reply(m_xcbConnection->getRawConnection(), cookie, nullptr)) { + core::SRAIIBasedExiter exitReply([reply]() -> void { + free(reply); + }); + + if(reply->type == m_xcbConnection->resolveXCBAtom(m_INCR)) { + assert(false); // TODO + } else { + const auto* src = reinterpret_cast(xcb.pxcb_get_property_value(reply)); + size_t n = xcb.pxcb_get_property_value_length(reply); + { + std::lock_guard lk(m_clipboardMutex); + m_clipboardResponse = std::string(src, n); + } + m_clipboardResponseCV.notify_one(); + } + } + } + break; + } + } + } +} + +#endif \ No newline at end of file diff --git a/src/nbl/ui/CCursorControlXcb.cpp b/src/nbl/ui/CCursorControlXcb.cpp new file mode 100644 index 0000000000..74c03b572c --- /dev/null +++ b/src/nbl/ui/CCursorControlXcb.cpp @@ -0,0 +1,51 @@ + +#include "nbl/ui/XcbConnection.h" +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/ui/CCursorControlXcb.h" +#include "nbl/ui/IWindowXcb.h" + + +namespace nbl::ui +{ + void CCursorControlXcb::setVisible(bool visible) { + // TODO: implement + } + + bool CCursorControlXcb::isVisible() const { + return true; + } + + void CCursorControlXcb::setPosition(SPosition pos) { + auto& xcb = m_xcbConnection->getXcbFunctionTable(); + const auto* primaryScreen = m_xcbConnection->primaryScreen(); + xcb.pxcb_warp_pointer(m_xcbConnection->getRawConnection(), XCB_NONE, primaryScreen->root, 0, 0, 0, 0, pos.x, pos.y); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + } + void CCursorControlXcb::setRelativePosition(IWindow* window, SRelativePosition position) { + auto* windowXcb = static_cast(window); + auto& xcb = m_xcbConnection->getXcbFunctionTable(); + auto xcbWindow = windowXcb->getXcbWindow(); + + xcb.pxcb_warp_pointer(m_xcbConnection->getRawConnection(), XCB_NONE, xcbWindow, 0, 0, 0, 0, position.x, position.y); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + } + + CCursorControlXcb::SPosition CCursorControlXcb::getPosition() { + auto& xcb = m_xcbConnection->getXcbFunctionTable(); + xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_xcbConnection->getRawConnection(), m_xcbConnection->primaryScreen()->root); + if(auto reply = xcb.pxcb_query_pointer_reply(m_xcbConnection->getRawConnection(), token, nullptr)) { + core::SRAIIBasedExiter exitReply([&reply]() -> void { + free(reply); + }); + return {reply->root_x, reply->root_y}; + } + return {0, 0}; + } + + CCursorControlXcb::SRelativePosition CCursorControlXcb::getRelativePosition(IWindow* window) { + + return {0, 0}; + } +} +#endif diff --git a/src/nbl/ui/CWindowXcb.cpp b/src/nbl/ui/CWindowXcb.cpp new file mode 100644 index 0000000000..e7b3457cfb --- /dev/null +++ b/src/nbl/ui/CWindowXcb.cpp @@ -0,0 +1,296 @@ +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/core/decl/smart_refctd_ptr.h" +#include "nbl/core/string/StringLiteral.h" + +#include "nbl/system/DefaultFuncPtrLoader.h" + +#include "nbl/ui/IWindowXcb.h" +#include "nbl/ui/CWindowXcb.h" +#include "nbl/ui/CCursorControlXcb.h" +#include "nbl/ui/CClipboardManagerXcb.h" +#include "nbl/ui/CWindowManagerXcb.h" + +#include +#include +#include +#include +#include + +namespace nbl::ui { + +static bool checkXcbCookie(const Xcb& functionTable, xcb_connection_t* connection, xcb_void_cookie_t cookie) { + if (xcb_generic_error_t* error = functionTable.pxcb_request_check(connection, cookie)) + { + printf("XCB error: %d", error->error_code); + return false; + } + return true; +} + +CWindowXcb::CDispatchThread::CDispatchThread(CWindowXcb& window): + m_window(window) { +} + +void CWindowXcb::CDispatchThread::work(lock_t& lock){ + if(m_quit) { + return; + } + auto& xcb = m_window.m_windowManager->getXcbFunctionTable(); + auto& xcbConnection = m_window.m_xcbConnection; + + auto MW_DELETE_WINDOW = xcbConnection->resolveXCBAtom(m_window.m_WM_DELETE_WINDOW); + auto NET_WM_PING = xcbConnection->resolveXCBAtom(m_window.m_NET_WM_PING); + + if(auto event = xcb.pxcb_wait_for_event(xcbConnection->getRawConnection())) { + auto* eventCallback = m_window.getEventCallback(); + m_window.m_clipboardManager->process(&m_window, event); + switch (event->response_type & ~0x80) + { + case 0: { + xcb_generic_error_t* error = reinterpret_cast(event); + printf("XCB error: %d", error->error_code); + break; + } + case XCB_CONFIGURE_NOTIFY: { + xcb_configure_notify_event_t* cne = reinterpret_cast(event); + if(m_window.m_width != cne->width || + m_window.m_height != cne->height) { + eventCallback->onWindowResized(&m_window, cne->width, cne->height); + } + if(m_window.m_x != cne->x || + m_window.m_y != cne->y) { + eventCallback->onWindowMoved(&m_window, cne->x, cne->y); + } + break; + } + case XCB_DESTROY_WINDOW: { + xcb_destroy_window_request_t* dwr = reinterpret_cast(event); + if(dwr->window == m_window.m_xcbWindow) { + m_quit = true; + eventCallback->onWindowClosed(&m_window); + } + break; + } + case XCB_CLIENT_MESSAGE: { + xcb_client_message_event_t* cme = reinterpret_cast(event); + if(cme->data.data32[0] == MW_DELETE_WINDOW) { + xcb.pxcb_unmap_window(m_window.getXcbConnection(), m_window.m_xcbWindow); + xcb.pxcb_destroy_window(m_window.getXcbConnection(), m_window.m_xcbWindow); + xcb.pxcb_flush(m_window.getXcbConnection()); + m_window.m_xcbWindow = 0; + m_quit = true; // we need to quit the dispatch thread + eventCallback->onWindowClosed(&m_window); + } else if(cme->data.data32[0] == NET_WM_PING && cme->window != xcbConnection->primaryScreen()->root) { + xcb_client_message_event_t ev = *cme; + ev.response_type = XCB_CLIENT_MESSAGE; + ev.window = m_window.m_xcbWindow; + ev.type = NET_WM_PING; + xcb.pxcb_send_event(m_window.getXcbConnection(), 0, m_window.m_xcbWindow, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); + xcb.pxcb_flush(m_window.getXcbConnection()); + } + break; + } + } + free(event); + } +} + + +void CWindowXcb::CDispatchThread::init() +{ + +} + +void CWindowXcb::CDispatchThread::exit() +{ +} + +CWindowManagerXcb::CWindowManagerXcb() { +} + +core::smart_refctd_ptr CWindowManagerXcb::createWindow(IWindow::SCreationParams&& creationParams) +{ + std::string title = std::string(creationParams.windowCaption); + auto window = core::make_smart_refctd_ptr(core::smart_refctd_ptr(this), std::move(creationParams)); + window->setCaption(title); + return window; +} + +bool CWindowManagerXcb::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { + auto wnd = static_cast(window); + wnd->setWindowSize_impl(width, height); + return true; +} + +bool CWindowManagerXcb::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { + auto wnd = static_cast(window); + wnd->setWindowPosition_impl(x, y); + return true; +} + +bool CWindowManagerXcb::setWindowRotation_impl(IWindow* window, bool landscape) { + auto wnd = static_cast(window); + wnd->setWindowRotation_impl(landscape); + return true; +} + +bool CWindowManagerXcb::setWindowVisible_impl(IWindow* window, bool visible) { + auto wnd = static_cast(window); + wnd->setWindowVisible_impl(visible); + return true; +} + +bool CWindowManagerXcb::setWindowMaximized_impl(IWindow* window, bool maximized) { + auto wnd = static_cast(window); + wnd->setWindowMaximized_impl(maximized); + return true; +} + +CWindowXcb::CWindowXcb(core::smart_refctd_ptr&& winManager, SCreationParams&& params): + IWindowXcb(std::move(params)), + m_windowManager(winManager), + m_xcbConnection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), + m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), + m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), + m_dispatcher(*this) { + + auto& xcb = m_windowManager->getXcbFunctionTable(); + auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); + + m_xcbWindow = xcb.pxcb_generate_id(m_xcbConnection->getRawConnection()); + + const auto* primaryScreen = m_xcbConnection->primaryScreen(); + + uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + uint32_t valueList[] = { + primaryScreen->black_pixel, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE + }; + + xcb_void_cookie_t xcbCheckResult = xcb.pxcb_create_window( + m_xcbConnection->getRawConnection(), XCB_COPY_FROM_PARENT, m_xcbWindow, primaryScreen->root, + static_cast(m_x), + static_cast(m_y), + static_cast(m_width), + static_cast(m_height), 4, + XCB_WINDOW_CLASS_INPUT_OUTPUT, primaryScreen->root_visual, eventMask, + valueList); + + setWindowSize_impl(m_width, m_height); + + auto WM_DELETE_WINDOW = m_xcbConnection->resolveXCBAtom(m_WM_DELETE_WINDOW); + auto NET_WM_PING = m_xcbConnection->resolveXCBAtom(m_NET_WM_PING); + auto WM_PROTOCOLS = m_xcbConnection->resolveXCBAtom(m_WM_PROTOCOLS); + + const std::array atoms {WM_DELETE_WINDOW, NET_WM_PING}; + xcb.pxcb_change_property( + m_xcbConnection->getRawConnection(), + XCB_PROP_MODE_REPLACE, + m_xcbWindow, + WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); + + + auto motifHints = fetchMotifMWHints(getFlags().value); + m_xcbConnection->setMotifWmHints(m_xcbWindow, motifHints); + + if(isAlwaysOnTop()) { + XcbConnection::XCBAtomToken NET_WM_STATE_ABOVE; + m_xcbConnection->setNetMWState( + primaryScreen->root, + m_xcbWindow, false, m_xcbConnection->resolveXCBAtom(NET_WM_STATE_ABOVE)); + } + + xcb.pxcb_map_window(m_xcbConnection->getRawConnection(), m_xcbWindow); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + m_dispatcher.start(); +} + +CWindowXcb::~CWindowXcb() +{ +} + +IClipboardManager* CWindowXcb::getClipboardManager() { + return m_clipboardManager.get(); +} + +ICursorControl* CWindowXcb::getCursorControl() { + return m_cursorControl.get(); +} + +IWindowManager* CWindowXcb::getManager() { + return m_windowManager.get(); +} + +bool CWindowXcb::setWindowSize_impl(uint32_t width, uint32_t height) { + auto& xcb = m_windowManager->getXcbFunctionTable(); + auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); + + xcb_size_hints_t hints = {0}; + + xcbIccm.pxcb_icccm_size_hints_set_size(&hints, true, width, height); + if(!isResizable()) { + xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); + xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); + } + xcbIccm.pxcb_icccm_set_wm_normal_hints(m_xcbConnection->getRawConnection(), m_xcbWindow, &hints); + return true; +} + +bool CWindowXcb::setWindowPosition_impl(int32_t x, int32_t y) { + auto& xcb = m_windowManager->getXcbFunctionTable(); + + const int32_t values[] = { x, y }; + auto cookie = xcb.pxcb_configure_window_checked(m_xcbConnection->getRawConnection(), m_xcbWindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + bool check = checkXcbCookie(xcb, m_xcbConnection->getRawConnection(), cookie); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + assert(check); + return true; +} + +void CWindowXcb::setCaption(const std::string_view& caption) { + auto& xcb = m_windowManager->getXcbFunctionTable(); + + xcb.pxcb_change_property(m_xcbConnection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); +} + +bool CWindowXcb::setWindowRotation_impl(bool landscape) { + return true; +} + +bool CWindowXcb::setWindowVisible_impl( bool visible) { + auto& xcb = m_windowManager->getXcbFunctionTable(); + + if(visible) { + xcb.pxcb_map_window(m_xcbConnection->getRawConnection(), m_xcbWindow); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + } else { + xcb.pxcb_unmap_window(m_xcbConnection->getRawConnection(), m_xcbWindow); + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + } + return true; +} + +bool CWindowXcb::setWindowMaximized_impl(bool maximized) { + auto& xcb = m_windowManager->getXcbFunctionTable(); + const auto* primaryScreen = m_xcbConnection->primaryScreen(); + + m_xcbConnection->setNetMWState( + primaryScreen->root, + m_xcbWindow, maximized && !isBorderless(), m_xcbConnection->resolveXCBAtom(m_NET_WM_STATE_FULLSCREEN)); + + m_xcbConnection->setNetMWState( + primaryScreen->root, + m_xcbWindow, maximized && isBorderless(), + m_xcbConnection->resolveXCBAtom(m_NET_WM_STATE_MAXIMIZED_VERT), + m_xcbConnection->resolveXCBAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); + + xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + return true; +} + +} + +#endif \ No newline at end of file diff --git a/src/nbl/ui/XcbConnection.cpp b/src/nbl/ui/XcbConnection.cpp new file mode 100644 index 0000000000..fec7c7edad --- /dev/null +++ b/src/nbl/ui/XcbConnection.cpp @@ -0,0 +1,60 @@ +#include "nbl/ui/XcbConnection.h" + +#ifdef _NBL_PLATFORM_LINUX_ + +namespace nbl::ui +{ + XcbConnection::XcbConnection(core::smart_refctd_ptr&& windowManager): + m_windowManager(std::move(windowManager)) { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + m_connection = xcb.pxcb_connect(nullptr, nullptr); + } + + XcbConnection::~XcbConnection() { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + xcb.pxcb_disconnect(m_connection); + } + + void XcbConnection::setNetMWState(xcb_window_t rootWindow, xcb_window_t window, bool set, xcb_atom_t first, xcb_atom_t second) const { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.type = resolveXCBAtom(m_NET_WM_STATE); + event.window = window; + event.format = 32; + event.sequence = 0; + event.data.data32[0] = set ? 1l : 0l; + event.data.data32[1] = first; + event.data.data32[2] = second; + event.data.data32[3] = 1; + event.data.data32[4] = 0; + xcb.pxcb_send_event(m_connection, 0, rootWindow, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, reinterpret_cast(&event)); + + } + + + const xcb_screen_t* XcbConnection::primaryScreen() { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + const xcb_setup_t *setup = xcb.pxcb_get_setup(m_connection); + xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; + return screen; + } + + void XcbConnection::setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + + auto atomHint = resolveXCBAtom(m_MOTIF_WM_HINTS); + if(hint.flags != MotifFlags::MWM_HINTS_NONE) { + xcb.pxcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, window, + atomHint, + atomHint, 32, sizeof(MotifWmHints) / sizeof(uint32_t), &hint); + } else { + xcb.pxcb_delete_property(m_connection, window, atomHint); + } + } + +} + +#endif // _NBL_PLATFORM_LINUX_ \ No newline at end of file diff --git a/src/nbl/video/CSurfaceVulkan.cpp b/src/nbl/video/CSurfaceVulkan.cpp index 21fa60681b..15b5166970 100644 --- a/src/nbl/video/CSurfaceVulkan.cpp +++ b/src/nbl/video/CSurfaceVulkan.cpp @@ -143,5 +143,29 @@ namespace nbl::video return nullptr; } } +#elif defined(_NBL_PLATFORM_LINUX_) + + #include + core::smart_refctd_ptr CSurfaceVulkanXcb::create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window) + { + if(!api || !window) + return nullptr; + + VkXcbSurfaceCreateInfoKHR createInfo { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.connection = window->getXcbConnection(); + createInfo.window = window->getXcbWindow(); + VkSurfaceKHR vk_surface; + if (vkCreateXcbSurfaceKHR(api->getInternalObject(), &createInfo, nullptr, &vk_surface) == VK_SUCCESS) + { + auto retval = new this_t(std::move(window), std::move(api), vk_surface); + return core::smart_refctd_ptr(retval, core::dont_grab); + } + return nullptr; + } + + #endif + } \ No newline at end of file diff --git a/src/nbl/video/CVulkanConnection.cpp b/src/nbl/video/CVulkanConnection.cpp index a648fb613f..34c9497d90 100644 --- a/src/nbl/video/CVulkanConnection.cpp +++ b/src/nbl/video/CVulkanConnection.cpp @@ -151,6 +151,8 @@ namespace nbl::video insertToFeatureSetIfAvailable(VK_KHR_SURFACE_EXTENSION_NAME, "E_SWAPCHAIN_MODE::ESM_SURFACE flag for featureName"); #if defined(_NBL_PLATFORM_WINDOWS_) insertToFeatureSetIfAvailable(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, "E_SWAPCHAIN_MODE::ESM_SURFACE flag for featureName"); +#elif defined(_NBL_PLATFORM_LINUX_) + insertToFeatureSetIfAvailable(VK_KHR_XCB_SURFACE_EXTENSION_NAME, "E_SWAPCHAIN_MODE::ESM_SURFACE flag for featureName"); #endif } SFeatures enabledFeatures = featuresToEnable; From 0473315b05cde338322d099476727805575185ce Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Mon, 20 Feb 2023 19:38:14 -0800 Subject: [PATCH 2/9] chore: tweak class names for consistency Signed-off-by: Michael Pollind --- include/nbl/ui/CClipboardManagerXCB.h | 57 ++++++++++++++ include/nbl/ui/CClipboardManagerXcb.h | 63 --------------- ...CursorControlXcb.h => CCursorControlXCB.h} | 10 +-- ...WindowManagerXcb.h => CWindowManagerXCB.h} | 6 +- include/nbl/ui/{CWindowXcb.h => CWindowXCB.h} | 47 ++++++------ include/nbl/ui/{IWindowXcb.h => IWindowXCB.h} | 48 ++++++------ .../ui/{XcbConnection.h => XCBConnection.h} | 14 ++-- include/nbl/ui/declarations.h | 2 +- include/nbl/ui/definitions.h | 4 +- include/nbl/video/CVulkanConnection.h | 2 +- include/nbl/video/surface/CSurfaceVulkan.h | 10 +-- src/nbl/CMakeLists.txt | 6 +- ...anagerXcb.cpp => CClipboardManagerXCB.cpp} | 24 ++---- ...orControlXcb.cpp => CCursorControlXCB.cpp} | 20 ++--- src/nbl/ui/{CWindowXcb.cpp => CWindowXCB.cpp} | 76 +++++++++---------- .../{XcbConnection.cpp => XCBConnection.cpp} | 12 +-- src/nbl/video/CSurfaceVulkan.cpp | 2 +- 17 files changed, 191 insertions(+), 212 deletions(-) create mode 100644 include/nbl/ui/CClipboardManagerXCB.h delete mode 100644 include/nbl/ui/CClipboardManagerXcb.h rename include/nbl/ui/{CCursorControlXcb.h => CCursorControlXCB.h} (71%) rename include/nbl/ui/{CWindowManagerXcb.h => CWindowManagerXCB.h} (95%) rename include/nbl/ui/{CWindowXcb.h => CWindowXCB.h} (58%) rename include/nbl/ui/{IWindowXcb.h => IWindowXCB.h} (51%) rename include/nbl/ui/{XcbConnection.h => XCBConnection.h} (89%) rename src/nbl/ui/{CClipboardManagerXcb.cpp => CClipboardManagerXCB.cpp} (87%) rename src/nbl/ui/{CCursorControlXcb.cpp => CCursorControlXCB.cpp} (72%) rename src/nbl/ui/{CWindowXcb.cpp => CWindowXCB.cpp} (80%) rename src/nbl/ui/{XcbConnection.cpp => XCBConnection.cpp} (84%) diff --git a/include/nbl/ui/CClipboardManagerXCB.h b/include/nbl/ui/CClipboardManagerXCB.h new file mode 100644 index 0000000000..99b778e034 --- /dev/null +++ b/include/nbl/ui/CClipboardManagerXCB.h @@ -0,0 +1,57 @@ +#ifndef _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ +#define _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ + +#include +#include +#include +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/core/decl/Types.h" +#include "nbl/ui/IClipboardManager.h" +#include "nbl/ui/XCBConnection.h" + +namespace nbl::ui +{ + +// details on XCB clipboard protocol: https://tronche.com/gui/x/icccm/sec-2.html#s-2 +class NBL_API2 CClipboardManagerXCB final : public IClipboardManager +{ + using base_t = IClipboardManager; + public: + inline CClipboardManagerXCB(core::smart_refctd_ptr&& connect): + m_xcbConnection(std::move(connect)) {} + + virtual std::string getClipboardText() override; + virtual bool setClipboardText(const std::string_view& data) override; + + void process(const IWindowXCB* window, xcb_generic_event_t* event); + private: + core::smart_refctd_ptr m_xcbConnection; + + struct { + std::string m_data; + std::vector m_formats; + } m_stagedClipboard; + + std::mutex m_clipboardMutex; + std::condition_variable m_clipboardResponseCV; + std::string m_clipboardResponse; + + XCBConnection::XCBAtomToken m_CLIPBOARD; + XCBConnection::XCBAtomToken m_TARGETS; + XCBConnection::XCBAtomToken m_INCR; + + XCBConnection::XCBAtomToken m_formatUTF8_0; + XCBConnection::XCBAtomToken m_formatUTF8_1; + XCBConnection::XCBAtomToken m_formatUTF8_2; + XCBConnection::XCBAtomToken m_formatGTK; + XCBConnection::XCBAtomToken m_formatString; + XCBConnection::XCBAtomToken m_formatText; + XCBConnection::XCBAtomToken m_formatTextPlain; +}; + +} + +#endif + +#endif \ No newline at end of file diff --git a/include/nbl/ui/CClipboardManagerXcb.h b/include/nbl/ui/CClipboardManagerXcb.h deleted file mode 100644 index 0b0b74d13a..0000000000 --- a/include/nbl/ui/CClipboardManagerXcb.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ -#define _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ - -#include -#include -#include -#ifdef _NBL_PLATFORM_LINUX_ - -#include "nbl/core/decl/Types.h" -#include "nbl/ui/IClipboardManager.h" -#include "nbl/ui/XcbConnection.h" - -namespace nbl::ui -{ - -// details on XCB clipboard protocol: https://tronche.com/gui/x/icccm/sec-2.html#s-2 -class NBL_API2 CClipboardManagerXcb final : public IClipboardManager -{ - using base_t = IClipboardManager; - public: - inline CClipboardManagerXcb(core::smart_refctd_ptr&& connect): - m_xcbConnection(std::move(connect)) {} - - virtual std::string getClipboardText() override; - virtual bool setClipboardText(const std::string_view& data) override; - - void process(const IWindowXcb* window, xcb_generic_event_t* event); - private: - core::smart_refctd_ptr m_xcbConnection; - - xcb_window_t getClipboardWindow(); - - struct { - std::string m_data; - std::vector m_formats; - } m_stagedClipboard; - - std::mutex m_clipboardMutex; - std::condition_variable m_clipboardResponseCV; - std::string m_clipboardResponse; - // bool ready = false; - - XcbConnection::XCBAtomToken m_CLIPBOARD; - XcbConnection::XCBAtomToken m_TARGETS; - XcbConnection::XCBAtomToken m_INCR; - - - XcbConnection::XCBAtomToken m_formatUTF8_0; - XcbConnection::XCBAtomToken m_formatUTF8_1; - XcbConnection::XCBAtomToken m_formatUTF8_2; - XcbConnection::XCBAtomToken m_formatGTK; - XcbConnection::XCBAtomToken m_formatString; - XcbConnection::XCBAtomToken m_formatText; - XcbConnection::XCBAtomToken m_formatTextPlain; - - -}; - -} - -#endif - -#endif \ No newline at end of file diff --git a/include/nbl/ui/CCursorControlXcb.h b/include/nbl/ui/CCursorControlXCB.h similarity index 71% rename from include/nbl/ui/CCursorControlXcb.h rename to include/nbl/ui/CCursorControlXCB.h index 5c6506829e..3286e39dd8 100644 --- a/include/nbl/ui/CCursorControlXcb.h +++ b/include/nbl/ui/CCursorControlXCB.h @@ -3,19 +3,19 @@ #include "nbl/ui/ICursorControl.h" -#include "nbl/ui/XcbConnection.h" +#include "nbl/ui/XCBConnection.h" #ifdef _NBL_PLATFORM_LINUX_ namespace nbl::ui { -class NBL_API2 CCursorControlXcb final : public ICursorControl +class NBL_API2 CCursorControlXCB final : public ICursorControl { - core::smart_refctd_ptr m_xcbConnection; + core::smart_refctd_ptr m_xcbConnection; public: - inline CCursorControlXcb( - core::smart_refctd_ptr&& xcbConnection) : + inline CCursorControlXCB( + core::smart_refctd_ptr&& xcbConnection) : m_xcbConnection(std::move(xcbConnection)) {} void setVisible(bool visible) override; diff --git a/include/nbl/ui/CWindowManagerXcb.h b/include/nbl/ui/CWindowManagerXCB.h similarity index 95% rename from include/nbl/ui/CWindowManagerXcb.h rename to include/nbl/ui/CWindowManagerXCB.h index 39da3eeee6..93b4d5c385 100644 --- a/include/nbl/ui/CWindowManagerXcb.h +++ b/include/nbl/ui/CWindowManagerXCB.h @@ -59,7 +59,7 @@ NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(XcbIcccm, system::DefaultFuncPt xcb_icccm_set_wm_normal_hints ); -class CWindowManagerXcb : public IWindowManager +class CWindowManagerXCB : public IWindowManager { public: @@ -73,8 +73,8 @@ class CWindowManagerXcb : public IWindowManager return SDisplayInfo(); } - CWindowManagerXcb(); - ~CWindowManagerXcb() override = default; + CWindowManagerXCB(); + ~CWindowManagerXCB() override = default; virtual core::smart_refctd_ptr createWindow(IWindow::SCreationParams&& creationParams) override; diff --git a/include/nbl/ui/CWindowXcb.h b/include/nbl/ui/CWindowXCB.h similarity index 58% rename from include/nbl/ui/CWindowXcb.h rename to include/nbl/ui/CWindowXCB.h index 4fb5032cae..f7edec98e2 100644 --- a/include/nbl/ui/CWindowXcb.h +++ b/include/nbl/ui/CWindowXCB.h @@ -4,23 +4,23 @@ #include #include "nbl/core/decl/smart_refctd_ptr.h" -#include "nbl/ui/CClipboardManagerXcb.h" -#include "nbl/ui/IWindowXcb.h" -#include "nbl/ui/XcbConnection.h" +#include "nbl/ui/CClipboardManagerXCB.h" +#include "nbl/ui/IWindowXCB.h" +#include "nbl/ui/XCBConnection.h" namespace nbl::ui { -class CCursorControlXcb; -class CWindowManagerXcb; -class CClipboardManagerXcb; +class CCursorControlXCB; +class CWindowManagerXCB; +class CClipboardManagerXCB; -class NBL_API2 CWindowXcb final : public IWindowXcb +class NBL_API2 CWindowXCB final : public IWindowXCB { public: - CWindowXcb(core::smart_refctd_ptr&& winManager, SCreationParams&& params); - ~CWindowXcb(); + CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params); + ~CWindowXCB(); // Display* getDisplay() const override { return m_dpy; } xcb_window_t getXcbWindow() const override { return m_xcbWindow; } @@ -41,18 +41,18 @@ class NBL_API2 CWindowXcb final : public IWindowXcb virtual void setCaption(const std::string_view& caption) override; private: - CWindowXcb(core::smart_refctd_ptr&& sys, uint32_t _w, uint32_t _h, E_CREATE_FLAGS _flags); + CWindowXCB(core::smart_refctd_ptr&& sys, uint32_t _w, uint32_t _h, E_CREATE_FLAGS _flags); - core::smart_refctd_ptr m_windowManager; - core::smart_refctd_ptr m_xcbConnection; - core::smart_refctd_ptr m_cursorControl; - core::smart_refctd_ptr m_clipboardManager; + core::smart_refctd_ptr m_windowManager; + core::smart_refctd_ptr m_xcbConnection; + core::smart_refctd_ptr m_cursorControl; + core::smart_refctd_ptr m_clipboardManager; class CDispatchThread final : public system::IThreadHandler { public: - inline CDispatchThread(CWindowXcb& window); + inline CDispatchThread(CWindowXCB& window); inline ~CDispatchThread() { } @@ -63,20 +63,19 @@ class NBL_API2 CWindowXcb final : public IWindowXcb inline bool wakeupPredicate() const { return true; } inline bool continuePredicate() const { return true; } private: - CWindowXcb& m_window; - // xcb_connection_t* m_connection = nullptr; - friend class CWindowXcb; + CWindowXCB& m_window; + friend class CWindowXCB; } m_dispatcher; xcb_window_t m_xcbWindow = 0; - XcbConnection::XCBAtomToken m_WM_DELETE_WINDOW; - XcbConnection::XCBAtomToken m_WM_PROTOCOLS; - XcbConnection::XCBAtomToken m_NET_WM_PING; + XCBConnection::XCBAtomToken m_WM_DELETE_WINDOW; + XCBConnection::XCBAtomToken m_WM_PROTOCOLS; + XCBConnection::XCBAtomToken m_NET_WM_PING; - XcbConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_VERT; - XcbConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_HORZ; - XcbConnection::XCBAtomToken m_NET_WM_STATE_FULLSCREEN; + XCBConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_VERT; + XCBConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_HORZ; + XCBConnection::XCBAtomToken m_NET_WM_STATE_FULLSCREEN; }; diff --git a/include/nbl/ui/IWindowXcb.h b/include/nbl/ui/IWindowXCB.h similarity index 51% rename from include/nbl/ui/IWindowXcb.h rename to include/nbl/ui/IWindowXCB.h index b9afdfda5d..84a3d14c8e 100644 --- a/include/nbl/ui/IWindowXcb.h +++ b/include/nbl/ui/IWindowXCB.h @@ -3,7 +3,7 @@ #include "nbl/core/util/bitflag.h" #include "nbl/ui/IWindow.h" -#include "nbl/ui/XcbConnection.h" +#include "nbl/ui/XCBConnection.h" #include #ifdef _NBL_PLATFORM_LINUX_ @@ -11,11 +11,11 @@ namespace nbl::ui { -class NBL_API2 IWindowXcb : public IWindow +class NBL_API2 IWindowXCB : public IWindow { protected: - virtual ~IWindowXcb() = default; - inline IWindowXcb(SCreationParams&& params) : IWindow(std::move(params)) {} + virtual ~IWindowXCB() = default; + inline IWindowXCB(SCreationParams&& params) : IWindow(std::move(params)) {} public: using IWindow::IWindow; @@ -31,44 +31,44 @@ class NBL_API2 IWindowXcb : public IWindow virtual bool setWindowVisible_impl(bool visible) = 0; virtual bool setWindowMaximized_impl(bool maximized) = 0; - static XcbConnection::MotifWmHints fetchMotifMWHints(IWindow::E_CREATE_FLAGS flags) { - core::bitflag motifFlags(XcbConnection::MWM_HINTS_NONE); - core::bitflag motifFunctions(XcbConnection::MWM_FUNC_NONE); - core::bitflag motifDecorations(XcbConnection::MWM_DECOR_NONE); - motifFlags |= XcbConnection::MWM_HINTS_DECORATIONS; + static XCBConnection::MotifWmHints fetchMotifMWHints(IWindow::E_CREATE_FLAGS flags) { + core::bitflag motifFlags(XCBConnection::MWM_HINTS_NONE); + core::bitflag motifFunctions(XCBConnection::MWM_FUNC_NONE); + core::bitflag motifDecorations(XCBConnection::MWM_DECOR_NONE); + motifFlags |= XCBConnection::MWM_HINTS_DECORATIONS; if (flags & IWindow::ECF_BORDERLESS) { - motifDecorations |= XcbConnection::MWM_DECOR_ALL; + motifDecorations |= XCBConnection::MWM_DECOR_ALL; } else { - motifDecorations |= XcbConnection::MWM_DECOR_BORDER; - motifDecorations |= XcbConnection::MWM_DECOR_RESIZEH; - motifDecorations |= XcbConnection::MWM_DECOR_TITLE; + motifDecorations |= XCBConnection::MWM_DECOR_BORDER; + motifDecorations |= XCBConnection::MWM_DECOR_RESIZEH; + motifDecorations |= XCBConnection::MWM_DECOR_TITLE; // minimize button if(flags & IWindow::ECF_MINIMIZED) { - motifDecorations |= XcbConnection::MWM_DECOR_MINIMIZE; - motifFunctions |= XcbConnection::MWM_FUNC_MINIMIZE; + motifDecorations |= XCBConnection::MWM_DECOR_MINIMIZE; + motifFunctions |= XCBConnection::MWM_FUNC_MINIMIZE; } // maximize button if(flags & IWindow::ECF_MAXIMIZED) { - motifDecorations |= XcbConnection::MWM_DECOR_MAXIMIZE; - motifFunctions |= XcbConnection::MWM_FUNC_MAXIMIZE; + motifDecorations |= XCBConnection::MWM_DECOR_MAXIMIZE; + motifFunctions |= XCBConnection::MWM_FUNC_MAXIMIZE; } // close button - motifFunctions |= XcbConnection::MWM_FUNC_CLOSE; + motifFunctions |= XCBConnection::MWM_FUNC_CLOSE; } - if(motifFunctions.value != XcbConnection::MWM_FUNC_NONE) { - motifFlags |= XcbConnection::MWM_HINTS_FUNCTIONS; - motifFunctions |= XcbConnection::MWM_FUNC_RESIZE; - motifFunctions |= XcbConnection::MWM_FUNC_MOVE; + if(motifFunctions.value != XCBConnection::MWM_FUNC_NONE) { + motifFlags |= XCBConnection::MWM_HINTS_FUNCTIONS; + motifFunctions |= XCBConnection::MWM_FUNC_RESIZE; + motifFunctions |= XCBConnection::MWM_FUNC_MOVE; } else { - motifFunctions = XcbConnection::MWM_FUNC_ALL; + motifFunctions = XCBConnection::MWM_FUNC_ALL; } - XcbConnection::MotifWmHints hints; + XCBConnection::MotifWmHints hints; hints.flags = motifFlags.value; hints.functions = motifFunctions.value; hints.decorations = motifDecorations.value; diff --git a/include/nbl/ui/XcbConnection.h b/include/nbl/ui/XCBConnection.h similarity index 89% rename from include/nbl/ui/XcbConnection.h rename to include/nbl/ui/XCBConnection.h index fd635e0e6f..847a809fe7 100644 --- a/include/nbl/ui/XcbConnection.h +++ b/include/nbl/ui/XCBConnection.h @@ -6,7 +6,7 @@ #include "nbl/core/decl/Types.h" #include "nbl/core/string/StringLiteral.h" #include "nbl/core/decl/smart_refctd_ptr.h" -#include "nbl/ui/CWindowManagerXcb.h" +#include "nbl/ui/CWindowManagerXCB.h" #include #include @@ -17,7 +17,7 @@ namespace nbl::ui { -class XcbConnection : public core::IReferenceCounted { +class XCBConnection : public core::IReferenceCounted { public: template struct XCBAtomToken { @@ -25,8 +25,8 @@ class XcbConnection : public core::IReferenceCounted { bool fetched = false; }; - XcbConnection(core::smart_refctd_ptr&& windowManager); - virtual ~XcbConnection() override; + XCBConnection(core::smart_refctd_ptr&& windowManager); + virtual ~XCBConnection() override; template inline xcb_atom_t resolveXCBAtom(XCBAtomToken& token, bool only_if_exists = true, bool forced = false) const { @@ -97,11 +97,11 @@ class XcbConnection : public core::IReferenceCounted { const xcb_screen_t* primaryScreen(); private: - core::smart_refctd_ptr m_windowManager; + core::smart_refctd_ptr m_windowManager; xcb_connection_t* m_connection = nullptr; - mutable XcbConnection::XCBAtomToken m_NET_WM_STATE; - mutable XcbConnection::XCBAtomToken m_MOTIF_WM_HINTS; + mutable XCBConnection::XCBAtomToken m_NET_WM_STATE; + mutable XCBConnection::XCBAtomToken m_MOTIF_WM_HINTS; }; } // namespace nbl::ui diff --git a/include/nbl/ui/declarations.h b/include/nbl/ui/declarations.h index 939f09834f..72947d82f4 100644 --- a/include/nbl/ui/declarations.h +++ b/include/nbl/ui/declarations.h @@ -13,7 +13,7 @@ #elif defined(_NBL_BUILD_WITH_WAYLAND) && defined(_NBL_TEST_WAYLAND) # include "nbl/ui/CWindowManagerWayland.h" #elif defined(_NBL_PLATFORM_LINUX_) -# include "nbl/ui/CWindowManagerXcb.h" +# include "nbl/ui/CWindowManagerXCB.h" #endif // TODO more platforms (android) // clipboards diff --git a/include/nbl/ui/definitions.h b/include/nbl/ui/definitions.h index fdf82547a9..9d1d4afbc9 100644 --- a/include/nbl/ui/definitions.h +++ b/include/nbl/ui/definitions.h @@ -10,9 +10,9 @@ // windows #include "nbl/ui/CWindowManagerWin32.h" -#include "nbl/ui/CWindowManagerXcb.h" +#include "nbl/ui/CWindowManagerXCB.h" #include "nbl/ui/CWindowWin32.h" -#include "nbl/ui/CWindowXcb.h" +#include "nbl/ui/CWindowXCB.h" #endif \ No newline at end of file diff --git a/include/nbl/video/CVulkanConnection.h b/include/nbl/video/CVulkanConnection.h index 7e24309452..0d03a4b0ee 100644 --- a/include/nbl/video/CVulkanConnection.h +++ b/include/nbl/video/CVulkanConnection.h @@ -7,7 +7,7 @@ #if defined(_NBL_PLATFORM_WINDOWS_) # include "nbl/ui/IWindowWin32.h" #elif defined(_NBL_PLATFORM_LINUX_) -# include "nbl/ui/IWindowXcb.h" +# include "nbl/ui/IWindowXCB.h" #else # error "Unsupported platform" #endif diff --git a/include/nbl/video/surface/CSurfaceVulkan.h b/include/nbl/video/surface/CSurfaceVulkan.h index a4fe736b9d..0ff4dc29fe 100644 --- a/include/nbl/video/surface/CSurfaceVulkan.h +++ b/include/nbl/video/surface/CSurfaceVulkan.h @@ -3,7 +3,7 @@ #include "BuildConfigOptions.h" -#include "nbl/ui/IWindowXcb.h" +#include "nbl/ui/IWindowXCB.h" #include "nbl/video/surface/ISurface.h" #include "nbl/video/CVulkanConnection.h" @@ -47,17 +47,17 @@ class NBL_API2 CSurfaceVulkanWin32 final : public CSurface create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window); }; #elif defined(_NBL_PLATFORM_LINUX_) -class NBL_API2 CSurfaceVulkanXcb final : public CSurface +class NBL_API2 CSurfaceVulkanXcb final : public CSurface { using this_t = CSurfaceVulkanXcb; - using base_t = CSurface; + using base_t = CSurface; public: - inline CSurfaceVulkanXcb(core::smart_refctd_ptr&& window, core::smart_refctd_ptr&& api, VkSurfaceKHR surf) : + inline CSurfaceVulkanXcb(core::smart_refctd_ptr&& window, core::smart_refctd_ptr&& api, VkSurfaceKHR surf) : base_t(std::move(window), std::move(api), surf) { } - static core::smart_refctd_ptr create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window); + static core::smart_refctd_ptr create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window); }; #elif defined(_NBL_PLATFORM_ANDROID_) diff --git a/src/nbl/CMakeLists.txt b/src/nbl/CMakeLists.txt index fc6f72504e..d9b777594d 100755 --- a/src/nbl/CMakeLists.txt +++ b/src/nbl/CMakeLists.txt @@ -187,11 +187,11 @@ set(NBL_UI_SOURCES ${NBL_ROOT_PATH}/src/nbl/ui/CWindowWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXcb.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/XcbConnection.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/XCBConnection.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerXcb.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlXcb.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerXCB.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlXCB.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerAndroid.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CGraphicalApplicationAndroid.cpp ) diff --git a/src/nbl/ui/CClipboardManagerXcb.cpp b/src/nbl/ui/CClipboardManagerXCB.cpp similarity index 87% rename from src/nbl/ui/CClipboardManagerXcb.cpp rename to src/nbl/ui/CClipboardManagerXCB.cpp index 95f1da3f60..bfcfa33e2a 100644 --- a/src/nbl/ui/CClipboardManagerXcb.cpp +++ b/src/nbl/ui/CClipboardManagerXCB.cpp @@ -1,16 +1,16 @@ -#include "nbl/ui/XcbConnection.h" +#include "nbl/ui/XCBConnection.h" #include #include #include #include #ifdef _NBL_PLATFORM_LINUX_ -#include "nbl/ui/CClipboardManagerXcb.h" +#include "nbl/ui/CClipboardManagerXCB.h" namespace nbl::ui { - std::string CClipboardManagerXcb::getClipboardText() { + std::string CClipboardManagerXCB::getClipboardText() { { std::unique_lock lk(m_clipboardMutex); m_clipboardResponseCV.wait_until(lk, std::chrono::system_clock::now() + std::chrono::seconds(1)); @@ -21,22 +21,8 @@ namespace nbl::ui return response; } - xcb_window_t CClipboardManagerXcb::getClipboardWindow() { - const auto& xcb = m_xcbConnection->getXcbFunctionTable(); - xcb_window_t window = 0; - auto cookie = xcb.pxcb_get_selection_owner(m_xcbConnection->getRawConnection(), - m_xcbConnection->resolveXCBAtom(m_CLIPBOARD)); - if(xcb_get_selection_owner_reply_t* reply = - xcb.pxcb_get_selection_owner_reply(m_xcbConnection->getRawConnection(), cookie, nullptr)) { - core::SRAIIBasedExiter exitReply([reply]() -> void { - free(reply); - }); - return reply->owner; - } - return 0; - } - bool CClipboardManagerXcb::setClipboardText(const std::string_view& data) { + bool CClipboardManagerXCB::setClipboardText(const std::string_view& data) { std::lock_guard lk(m_clipboardMutex); m_stagedClipboard.m_data = data; m_stagedClipboard.m_formats = { @@ -51,7 +37,7 @@ namespace nbl::ui return true; } - void CClipboardManagerXcb::process(const IWindowXcb* window, xcb_generic_event_t* event) { + void CClipboardManagerXCB::process(const IWindowXCB* window, xcb_generic_event_t* event) { const auto& xcb = m_xcbConnection->getXcbFunctionTable(); auto TARGETS = m_xcbConnection->resolveXCBAtom(m_TARGETS); diff --git a/src/nbl/ui/CCursorControlXcb.cpp b/src/nbl/ui/CCursorControlXCB.cpp similarity index 72% rename from src/nbl/ui/CCursorControlXcb.cpp rename to src/nbl/ui/CCursorControlXCB.cpp index 74c03b572c..8404504391 100644 --- a/src/nbl/ui/CCursorControlXcb.cpp +++ b/src/nbl/ui/CCursorControlXCB.cpp @@ -1,29 +1,29 @@ -#include "nbl/ui/XcbConnection.h" +#include "nbl/ui/XCBConnection.h" #ifdef _NBL_PLATFORM_LINUX_ -#include "nbl/ui/CCursorControlXcb.h" -#include "nbl/ui/IWindowXcb.h" +#include "nbl/ui/CCursorControlXCB.h" +#include "nbl/ui/IWindowXCB.h" namespace nbl::ui { - void CCursorControlXcb::setVisible(bool visible) { + void CCursorControlXCB::setVisible(bool visible) { // TODO: implement } - bool CCursorControlXcb::isVisible() const { + bool CCursorControlXCB::isVisible() const { return true; } - void CCursorControlXcb::setPosition(SPosition pos) { + void CCursorControlXCB::setPosition(SPosition pos) { auto& xcb = m_xcbConnection->getXcbFunctionTable(); const auto* primaryScreen = m_xcbConnection->primaryScreen(); xcb.pxcb_warp_pointer(m_xcbConnection->getRawConnection(), XCB_NONE, primaryScreen->root, 0, 0, 0, 0, pos.x, pos.y); xcb.pxcb_flush(m_xcbConnection->getRawConnection()); } - void CCursorControlXcb::setRelativePosition(IWindow* window, SRelativePosition position) { - auto* windowXcb = static_cast(window); + void CCursorControlXCB::setRelativePosition(IWindow* window, SRelativePosition position) { + auto* windowXcb = static_cast(window); auto& xcb = m_xcbConnection->getXcbFunctionTable(); auto xcbWindow = windowXcb->getXcbWindow(); @@ -31,7 +31,7 @@ namespace nbl::ui xcb.pxcb_flush(m_xcbConnection->getRawConnection()); } - CCursorControlXcb::SPosition CCursorControlXcb::getPosition() { + CCursorControlXCB::SPosition CCursorControlXCB::getPosition() { auto& xcb = m_xcbConnection->getXcbFunctionTable(); xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_xcbConnection->getRawConnection(), m_xcbConnection->primaryScreen()->root); if(auto reply = xcb.pxcb_query_pointer_reply(m_xcbConnection->getRawConnection(), token, nullptr)) { @@ -43,7 +43,7 @@ namespace nbl::ui return {0, 0}; } - CCursorControlXcb::SRelativePosition CCursorControlXcb::getRelativePosition(IWindow* window) { + CCursorControlXCB::SRelativePosition CCursorControlXCB::getRelativePosition(IWindow* window) { return {0, 0}; } diff --git a/src/nbl/ui/CWindowXcb.cpp b/src/nbl/ui/CWindowXCB.cpp similarity index 80% rename from src/nbl/ui/CWindowXcb.cpp rename to src/nbl/ui/CWindowXCB.cpp index e7b3457cfb..f4ea8ddf9b 100644 --- a/src/nbl/ui/CWindowXcb.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -5,11 +5,11 @@ #include "nbl/system/DefaultFuncPtrLoader.h" -#include "nbl/ui/IWindowXcb.h" -#include "nbl/ui/CWindowXcb.h" -#include "nbl/ui/CCursorControlXcb.h" -#include "nbl/ui/CClipboardManagerXcb.h" -#include "nbl/ui/CWindowManagerXcb.h" +#include "nbl/ui/IWindowXCB.h" +#include "nbl/ui/CWindowXCB.h" +#include "nbl/ui/CCursorControlXCB.h" +#include "nbl/ui/CClipboardManagerXCB.h" +#include "nbl/ui/CWindowManagerXCB.h" #include #include @@ -28,11 +28,11 @@ static bool checkXcbCookie(const Xcb& functionTable, xcb_connection_t* connectio return true; } -CWindowXcb::CDispatchThread::CDispatchThread(CWindowXcb& window): +CWindowXCB::CDispatchThread::CDispatchThread(CWindowXCB& window): m_window(window) { } -void CWindowXcb::CDispatchThread::work(lock_t& lock){ +void CWindowXCB::CDispatchThread::work(lock_t& lock){ if(m_quit) { return; } @@ -97,62 +97,62 @@ void CWindowXcb::CDispatchThread::work(lock_t& lock){ } -void CWindowXcb::CDispatchThread::init() +void CWindowXCB::CDispatchThread::init() { } -void CWindowXcb::CDispatchThread::exit() +void CWindowXCB::CDispatchThread::exit() { } -CWindowManagerXcb::CWindowManagerXcb() { +CWindowManagerXCB::CWindowManagerXCB() { } -core::smart_refctd_ptr CWindowManagerXcb::createWindow(IWindow::SCreationParams&& creationParams) +core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreationParams&& creationParams) { std::string title = std::string(creationParams.windowCaption); - auto window = core::make_smart_refctd_ptr(core::smart_refctd_ptr(this), std::move(creationParams)); + auto window = core::make_smart_refctd_ptr(core::smart_refctd_ptr(this), std::move(creationParams)); window->setCaption(title); return window; } -bool CWindowManagerXcb::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { - auto wnd = static_cast(window); +bool CWindowManagerXCB::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { + auto wnd = static_cast(window); wnd->setWindowSize_impl(width, height); return true; } -bool CWindowManagerXcb::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { - auto wnd = static_cast(window); +bool CWindowManagerXCB::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { + auto wnd = static_cast(window); wnd->setWindowPosition_impl(x, y); return true; } -bool CWindowManagerXcb::setWindowRotation_impl(IWindow* window, bool landscape) { - auto wnd = static_cast(window); +bool CWindowManagerXCB::setWindowRotation_impl(IWindow* window, bool landscape) { + auto wnd = static_cast(window); wnd->setWindowRotation_impl(landscape); return true; } -bool CWindowManagerXcb::setWindowVisible_impl(IWindow* window, bool visible) { - auto wnd = static_cast(window); +bool CWindowManagerXCB::setWindowVisible_impl(IWindow* window, bool visible) { + auto wnd = static_cast(window); wnd->setWindowVisible_impl(visible); return true; } -bool CWindowManagerXcb::setWindowMaximized_impl(IWindow* window, bool maximized) { - auto wnd = static_cast(window); +bool CWindowManagerXCB::setWindowMaximized_impl(IWindow* window, bool maximized) { + auto wnd = static_cast(window); wnd->setWindowMaximized_impl(maximized); return true; } -CWindowXcb::CWindowXcb(core::smart_refctd_ptr&& winManager, SCreationParams&& params): - IWindowXcb(std::move(params)), +CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params): + IWindowXCB(std::move(params)), m_windowManager(winManager), - m_xcbConnection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), - m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), - m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), + m_xcbConnection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), + m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), + m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), m_dispatcher(*this) { auto& xcb = m_windowManager->getXcbFunctionTable(); @@ -196,7 +196,7 @@ CWindowXcb::CWindowXcb(core::smart_refctd_ptr&& winManager, S m_xcbConnection->setMotifWmHints(m_xcbWindow, motifHints); if(isAlwaysOnTop()) { - XcbConnection::XCBAtomToken NET_WM_STATE_ABOVE; + XCBConnection::XCBAtomToken NET_WM_STATE_ABOVE; m_xcbConnection->setNetMWState( primaryScreen->root, m_xcbWindow, false, m_xcbConnection->resolveXCBAtom(NET_WM_STATE_ABOVE)); @@ -207,23 +207,23 @@ CWindowXcb::CWindowXcb(core::smart_refctd_ptr&& winManager, S m_dispatcher.start(); } -CWindowXcb::~CWindowXcb() +CWindowXCB::~CWindowXCB() { } -IClipboardManager* CWindowXcb::getClipboardManager() { +IClipboardManager* CWindowXCB::getClipboardManager() { return m_clipboardManager.get(); } -ICursorControl* CWindowXcb::getCursorControl() { +ICursorControl* CWindowXCB::getCursorControl() { return m_cursorControl.get(); } -IWindowManager* CWindowXcb::getManager() { +IWindowManager* CWindowXCB::getManager() { return m_windowManager.get(); } -bool CWindowXcb::setWindowSize_impl(uint32_t width, uint32_t height) { +bool CWindowXCB::setWindowSize_impl(uint32_t width, uint32_t height) { auto& xcb = m_windowManager->getXcbFunctionTable(); auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); @@ -238,7 +238,7 @@ bool CWindowXcb::setWindowSize_impl(uint32_t width, uint32_t height) { return true; } -bool CWindowXcb::setWindowPosition_impl(int32_t x, int32_t y) { +bool CWindowXCB::setWindowPosition_impl(int32_t x, int32_t y) { auto& xcb = m_windowManager->getXcbFunctionTable(); const int32_t values[] = { x, y }; @@ -249,18 +249,18 @@ bool CWindowXcb::setWindowPosition_impl(int32_t x, int32_t y) { return true; } -void CWindowXcb::setCaption(const std::string_view& caption) { +void CWindowXCB::setCaption(const std::string_view& caption) { auto& xcb = m_windowManager->getXcbFunctionTable(); xcb.pxcb_change_property(m_xcbConnection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); xcb.pxcb_flush(m_xcbConnection->getRawConnection()); } -bool CWindowXcb::setWindowRotation_impl(bool landscape) { +bool CWindowXCB::setWindowRotation_impl(bool landscape) { return true; } -bool CWindowXcb::setWindowVisible_impl( bool visible) { +bool CWindowXCB::setWindowVisible_impl( bool visible) { auto& xcb = m_windowManager->getXcbFunctionTable(); if(visible) { @@ -273,7 +273,7 @@ bool CWindowXcb::setWindowVisible_impl( bool visible) { return true; } -bool CWindowXcb::setWindowMaximized_impl(bool maximized) { +bool CWindowXCB::setWindowMaximized_impl(bool maximized) { auto& xcb = m_windowManager->getXcbFunctionTable(); const auto* primaryScreen = m_xcbConnection->primaryScreen(); diff --git a/src/nbl/ui/XcbConnection.cpp b/src/nbl/ui/XCBConnection.cpp similarity index 84% rename from src/nbl/ui/XcbConnection.cpp rename to src/nbl/ui/XCBConnection.cpp index fec7c7edad..703cbdcd4e 100644 --- a/src/nbl/ui/XcbConnection.cpp +++ b/src/nbl/ui/XCBConnection.cpp @@ -1,21 +1,21 @@ -#include "nbl/ui/XcbConnection.h" +#include "nbl/ui/XCBConnection.h" #ifdef _NBL_PLATFORM_LINUX_ namespace nbl::ui { - XcbConnection::XcbConnection(core::smart_refctd_ptr&& windowManager): + XCBConnection::XCBConnection(core::smart_refctd_ptr&& windowManager): m_windowManager(std::move(windowManager)) { const auto& xcb = m_windowManager->getXcbFunctionTable(); m_connection = xcb.pxcb_connect(nullptr, nullptr); } - XcbConnection::~XcbConnection() { + XCBConnection::~XCBConnection() { const auto& xcb = m_windowManager->getXcbFunctionTable(); xcb.pxcb_disconnect(m_connection); } - void XcbConnection::setNetMWState(xcb_window_t rootWindow, xcb_window_t window, bool set, xcb_atom_t first, xcb_atom_t second) const { + void XCBConnection::setNetMWState(xcb_window_t rootWindow, xcb_window_t window, bool set, xcb_atom_t first, xcb_atom_t second) const { const auto& xcb = m_windowManager->getXcbFunctionTable(); xcb_client_message_event_t event; @@ -35,14 +35,14 @@ namespace nbl::ui } - const xcb_screen_t* XcbConnection::primaryScreen() { + const xcb_screen_t* XCBConnection::primaryScreen() { const auto& xcb = m_windowManager->getXcbFunctionTable(); const xcb_setup_t *setup = xcb.pxcb_get_setup(m_connection); xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; return screen; } - void XcbConnection::setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const { + void XCBConnection::setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const { const auto& xcb = m_windowManager->getXcbFunctionTable(); auto atomHint = resolveXCBAtom(m_MOTIF_WM_HINTS); diff --git a/src/nbl/video/CSurfaceVulkan.cpp b/src/nbl/video/CSurfaceVulkan.cpp index 15b5166970..49cded60eb 100644 --- a/src/nbl/video/CSurfaceVulkan.cpp +++ b/src/nbl/video/CSurfaceVulkan.cpp @@ -146,7 +146,7 @@ namespace nbl::video #elif defined(_NBL_PLATFORM_LINUX_) #include - core::smart_refctd_ptr CSurfaceVulkanXcb::create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window) + core::smart_refctd_ptr CSurfaceVulkanXcb::create(core::smart_refctd_ptr&& api, core::smart_refctd_ptr&& window) { if(!api || !window) return nullptr; From 21d91f7ab3e623e5bd62434d01003514fd598df3 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 1 Mar 2023 19:43:14 -0800 Subject: [PATCH 3/9] cleanup Signed-off-by: Michael Pollind --- include/nbl/ui/CClipboardManagerXCB.h | 29 +++++------ include/nbl/ui/CCursorControlXCB.h | 14 ++--- include/nbl/ui/CWindowManagerXCB.h | 1 - include/nbl/ui/CWindowXCB.h | 17 +++--- include/nbl/ui/IClipboardManagerXCB.h | 28 ++++++++++ include/nbl/ui/IWindowXCB.h | 7 +-- include/nbl/ui/XCBConnection.h | 2 +- src/nbl/ui/CClipboardManagerXCB.cpp | 60 ++++++++++------------ src/nbl/ui/CCursorControlXCB.cpp | 38 ++++++++------ src/nbl/ui/CWindowXCB.cpp | 74 +++++++++++++-------------- src/nbl/ui/XCBConnection.cpp | 4 +- 11 files changed, 151 insertions(+), 123 deletions(-) create mode 100644 include/nbl/ui/IClipboardManagerXCB.h diff --git a/include/nbl/ui/CClipboardManagerXCB.h b/include/nbl/ui/CClipboardManagerXCB.h index 99b778e034..a65693160f 100644 --- a/include/nbl/ui/CClipboardManagerXCB.h +++ b/include/nbl/ui/CClipboardManagerXCB.h @@ -1,41 +1,36 @@ #ifndef _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ #define _NBL_UI_C_CLIPBOARD_MANAGER_XCB_INCLUDED_ -#include -#include -#include #ifdef _NBL_PLATFORM_LINUX_ #include "nbl/core/decl/Types.h" -#include "nbl/ui/IClipboardManager.h" +#include "nbl/ui/IClipboardManagerXCB.h" #include "nbl/ui/XCBConnection.h" - namespace nbl::ui { +class IWindowXCB; +class XCBConnection; + // details on XCB clipboard protocol: https://tronche.com/gui/x/icccm/sec-2.html#s-2 -class NBL_API2 CClipboardManagerXCB final : public IClipboardManager +class NBL_API2 CClipboardManagerXCB final : public IClipboardManagerXCB { - using base_t = IClipboardManager; public: inline CClipboardManagerXCB(core::smart_refctd_ptr&& connect): - m_xcbConnection(std::move(connect)) {} + IClipboardManagerXCB(), + m_connection(std::move(connect)) {} virtual std::string getClipboardText() override; virtual bool setClipboardText(const std::string_view& data) override; - void process(const IWindowXCB* window, xcb_generic_event_t* event); + void process(const IWindowXCB* window, xcb_generic_event_t* event) override; private: - core::smart_refctd_ptr m_xcbConnection; - - struct { - std::string m_data; - std::vector m_formats; - } m_stagedClipboard; - + core::smart_refctd_ptr m_connection; std::mutex m_clipboardMutex; std::condition_variable m_clipboardResponseCV; - std::string m_clipboardResponse; + std::string m_clipboardResponse; // data sent to the clipboard by another application + + std::string m_savedClipboard; // data saved to the clipboard for another application to read XCBConnection::XCBAtomToken m_CLIPBOARD; XCBConnection::XCBAtomToken m_TARGETS; diff --git a/include/nbl/ui/CCursorControlXCB.h b/include/nbl/ui/CCursorControlXCB.h index 3286e39dd8..1976948f50 100644 --- a/include/nbl/ui/CCursorControlXCB.h +++ b/include/nbl/ui/CCursorControlXCB.h @@ -1,22 +1,20 @@ #ifndef __NBL_SYSTEM_C_CURSOR_CONTROL_XCB_H_INCLUDED__ #define __NBL_SYSTEM_C_CURSOR_CONTROL_XCB_H_INCLUDED__ +#ifdef _NBL_PLATFORM_LINUX_ #include "nbl/ui/ICursorControl.h" -#include "nbl/ui/XCBConnection.h" - -#ifdef _NBL_PLATFORM_LINUX_ namespace nbl::ui { + +class XCBConnection; class NBL_API2 CCursorControlXCB final : public ICursorControl { - core::smart_refctd_ptr m_xcbConnection; - public: inline CCursorControlXCB( - core::smart_refctd_ptr&& xcbConnection) : - m_xcbConnection(std::move(xcbConnection)) {} + core::smart_refctd_ptr&& xcbConnection) : + m_connection(std::move(xcbConnection)) {} void setVisible(bool visible) override; bool isVisible() const override; @@ -26,6 +24,8 @@ class NBL_API2 CCursorControlXCB final : public ICursorControl SPosition getPosition() override; SRelativePosition getRelativePosition(IWindow* window) override; + private: + core::smart_refctd_ptr m_connection; }; } diff --git a/include/nbl/ui/CWindowManagerXCB.h b/include/nbl/ui/CWindowManagerXCB.h index 93b4d5c385..688c84b852 100644 --- a/include/nbl/ui/CWindowManagerXCB.h +++ b/include/nbl/ui/CWindowManagerXCB.h @@ -84,7 +84,6 @@ class CWindowManagerXCB : public IWindowManager const XcbIcccm& getXcbIcccmFunctionTable() const { return m_xcbIcccm; } private: - Xcb m_xcb = Xcb("xcb"); // function tables XcbIcccm m_xcbIcccm = XcbIcccm("xcb-icccm"); }; diff --git a/include/nbl/ui/CWindowXCB.h b/include/nbl/ui/CWindowXCB.h index f7edec98e2..80acf1a753 100644 --- a/include/nbl/ui/CWindowXCB.h +++ b/include/nbl/ui/CWindowXCB.h @@ -1,19 +1,20 @@ #ifndef __C_WINDOW_XCB_H_INCLUDED__ #define __C_WINDOW_XCB_H_INCLUDED__ -#include - #include "nbl/core/decl/smart_refctd_ptr.h" -#include "nbl/ui/CClipboardManagerXCB.h" +#include "nbl/ui/IClipboardManagerXCB.h" #include "nbl/ui/IWindowXCB.h" #include "nbl/ui/XCBConnection.h" +#include + namespace nbl::ui { -class CCursorControlXCB; class CWindowManagerXCB; -class CClipboardManagerXCB; +class XCBConnection; +class CCursorControlXCB; +class IClipboardManagerXCB; class NBL_API2 CWindowXCB final : public IWindowXCB { @@ -25,7 +26,7 @@ class NBL_API2 CWindowXCB final : public IWindowXCB // Display* getDisplay() const override { return m_dpy; } xcb_window_t getXcbWindow() const override { return m_xcbWindow; } xcb_connection_t* getXcbConnection() const override { - return m_xcbConnection->getRawConnection(); + return m_connection->getRawConnection(); } virtual IClipboardManager* getClipboardManager() override; @@ -44,9 +45,9 @@ class NBL_API2 CWindowXCB final : public IWindowXCB CWindowXCB(core::smart_refctd_ptr&& sys, uint32_t _w, uint32_t _h, E_CREATE_FLAGS _flags); core::smart_refctd_ptr m_windowManager; - core::smart_refctd_ptr m_xcbConnection; + core::smart_refctd_ptr m_connection; core::smart_refctd_ptr m_cursorControl; - core::smart_refctd_ptr m_clipboardManager; + core::smart_refctd_ptr m_clipboardManager; class CDispatchThread final : public system::IThreadHandler { diff --git a/include/nbl/ui/IClipboardManagerXCB.h b/include/nbl/ui/IClipboardManagerXCB.h new file mode 100644 index 0000000000..8c853545a6 --- /dev/null +++ b/include/nbl/ui/IClipboardManagerXCB.h @@ -0,0 +1,28 @@ +#ifndef _NBL_UI_I_CLIPBOARD_MANAGER_XCB_INCLUDED_ +#define _NBL_UI_I_CLIPBOARD_MANAGER_XCB_INCLUDED_ + +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/ui/IClipboardManager.h" + +namespace nbl::ui +{ +class XCBConnection; + +// details on XCB clipboard protocol: https://tronche.com/gui/x/icccm/sec-2.html#s-2 +class NBL_API2 IClipboardManagerXCB : public IClipboardManager +{ + public: + IClipboardManagerXCB() : IClipboardManager() {} + virtual ~IClipboardManagerXCB() = default; + + virtual std::string getClipboardText() = 0; + virtual bool setClipboardText(const std::string_view& data) = 0; + virtual void process(const IWindowXCB* window, xcb_generic_event_t* event) = 0; +}; + +} + +#endif + +#endif \ No newline at end of file diff --git a/include/nbl/ui/IWindowXCB.h b/include/nbl/ui/IWindowXCB.h index 84a3d14c8e..6a278c6776 100644 --- a/include/nbl/ui/IWindowXCB.h +++ b/include/nbl/ui/IWindowXCB.h @@ -1,12 +1,14 @@ #ifndef __NBL_I_WINDOW_XCB_H_INCLUDED__ #define __NBL_I_WINDOW_XCB_H_INCLUDED__ +#ifdef _NBL_PLATFORM_LINUX_ + #include "nbl/core/util/bitflag.h" + #include "nbl/ui/IWindow.h" #include "nbl/ui/XCBConnection.h" -#include -#ifdef _NBL_PLATFORM_LINUX_ +#include namespace nbl::ui { @@ -22,7 +24,6 @@ class NBL_API2 IWindowXCB : public IWindow const void* getNativeHandle() const { return nullptr; } virtual xcb_window_t getXcbWindow() const = 0; - // virtual xcb_window_t getXcbRootWindow() const = 0; virtual xcb_connection_t* getXcbConnection() const = 0; virtual bool setWindowSize_impl(uint32_t width, uint32_t height) = 0; diff --git a/include/nbl/ui/XCBConnection.h b/include/nbl/ui/XCBConnection.h index 847a809fe7..1ffdb8bf5d 100644 --- a/include/nbl/ui/XCBConnection.h +++ b/include/nbl/ui/XCBConnection.h @@ -29,7 +29,7 @@ class XCBConnection : public core::IReferenceCounted { virtual ~XCBConnection() override; template - inline xcb_atom_t resolveXCBAtom(XCBAtomToken& token, bool only_if_exists = true, bool forced = false) const { + inline xcb_atom_t resolveAtom(XCBAtomToken& token, bool only_if_exists = true, bool forced = false) const { const auto& xcb = m_windowManager->getXcbFunctionTable(); if(token.fetched && !forced) { return token.token; diff --git a/src/nbl/ui/CClipboardManagerXCB.cpp b/src/nbl/ui/CClipboardManagerXCB.cpp index bfcfa33e2a..3aeeaeba41 100644 --- a/src/nbl/ui/CClipboardManagerXCB.cpp +++ b/src/nbl/ui/CClipboardManagerXCB.cpp @@ -1,12 +1,12 @@ +#include "nbl/ui/CClipboardManagerXCB.h" #include "nbl/ui/XCBConnection.h" + #include #include #include -#include -#ifdef _NBL_PLATFORM_LINUX_ -#include "nbl/ui/CClipboardManagerXCB.h" +#include namespace nbl::ui { @@ -24,23 +24,14 @@ namespace nbl::ui bool CClipboardManagerXCB::setClipboardText(const std::string_view& data) { std::lock_guard lk(m_clipboardMutex); - m_stagedClipboard.m_data = data; - m_stagedClipboard.m_formats = { - m_xcbConnection->resolveXCBAtom(m_formatUTF8_0), - m_xcbConnection->resolveXCBAtom(m_formatUTF8_1), - m_xcbConnection->resolveXCBAtom(m_formatUTF8_2), - m_xcbConnection->resolveXCBAtom(m_formatGTK), - m_xcbConnection->resolveXCBAtom(m_formatString), - m_xcbConnection->resolveXCBAtom(m_formatText), - m_xcbConnection->resolveXCBAtom(m_formatTextPlain) - }; + m_savedClipboard = data; return true; } void CClipboardManagerXCB::process(const IWindowXCB* window, xcb_generic_event_t* event) { - const auto& xcb = m_xcbConnection->getXcbFunctionTable(); + const auto& xcb = m_connection->getXcbFunctionTable(); - auto TARGETS = m_xcbConnection->resolveXCBAtom(m_TARGETS); + auto TARGETS = m_connection->resolveAtom(m_TARGETS); switch(event->response_type & ~0x80) { // XCB_ATOM @@ -52,13 +43,21 @@ namespace nbl::ui std::vector targets; { std::lock_guard lk(m_clipboardMutex); - for(auto& format : m_stagedClipboard.m_formats) { + for(auto& format : { + m_connection->resolveAtom(m_formatUTF8_0), + m_connection->resolveAtom(m_formatUTF8_1), + m_connection->resolveAtom(m_formatUTF8_2), + m_connection->resolveAtom(m_formatGTK), + m_connection->resolveAtom(m_formatString), + m_connection->resolveAtom(m_formatText), + m_connection->resolveAtom(m_formatTextPlain) + }) { targets.push_back(format); } } - targets.push_back(m_xcbConnection->resolveXCBAtom(m_TARGETS)); + targets.push_back(m_connection->resolveAtom(m_TARGETS)); xcb.pxcb_change_property( - m_xcbConnection->getRawConnection(), + m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, sne->requestor, sne->property, @@ -69,14 +68,14 @@ namespace nbl::ui } else { std::lock_guard lk(m_clipboardMutex); xcb.pxcb_change_property( - m_xcbConnection->getRawConnection(), + m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, sne->requestor, sne->property, sne->target, 8, - m_stagedClipboard.m_data.size(), - m_stagedClipboard.m_data.data()); + m_savedClipboard.size(), + m_savedClipboard.data()); } } @@ -91,22 +90,21 @@ namespace nbl::ui notify.target = sne->target; notify.property = sne->property; - xcb.pxcb_send_event(m_xcbConnection->getRawConnection(), false, + xcb.pxcb_send_event(m_connection->getRawConnection(), false, sne->requestor, XCB_EVENT_MASK_NO_EVENT, // SelectionNotify events go without mask (const char*)¬ify); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_flush(m_connection->getRawConnection()); break; } // Someone else has new content in the clipboard, so is // notifying us that we should delete our data now. case XCB_SELECTION_CLEAR: { auto* sne = reinterpret_cast(event); - if (sne->selection == m_xcbConnection->resolveXCBAtom(m_CLIPBOARD)) { + if (sne->selection == m_connection->resolveAtom(m_CLIPBOARD)) { std::lock_guard lock(m_clipboardMutex); - m_stagedClipboard.m_formats = {}; - m_stagedClipboard.m_data = std::string(); + m_savedClipboard = std::string(); } break; } @@ -119,17 +117,17 @@ namespace nbl::ui if(sne->target != TARGETS) { fieldType = sne->target; } - xcb_get_property_cookie_t cookie = xcb.pxcb_get_property(m_xcbConnection->getRawConnection(), true, + xcb_get_property_cookie_t cookie = xcb.pxcb_get_property(m_connection->getRawConnection(), true, sne->requestor, sne->property, fieldType, 0, 0x1fffffff); // 0x1fffffff = INT32_MAX / 4 if(xcb_get_property_reply_t* reply = - xcb.pxcb_get_property_reply(m_xcbConnection->getRawConnection(), cookie, nullptr)) { + xcb.pxcb_get_property_reply(m_connection->getRawConnection(), cookie, nullptr)) { core::SRAIIBasedExiter exitReply([reply]() -> void { free(reply); }); - if(reply->type == m_xcbConnection->resolveXCBAtom(m_INCR)) { + if(reply->type == m_connection->resolveAtom(m_INCR)) { assert(false); // TODO } else { const auto* src = reinterpret_cast(xcb.pxcb_get_property_value(reply)); @@ -146,6 +144,4 @@ namespace nbl::ui } } } -} - -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/nbl/ui/CCursorControlXCB.cpp b/src/nbl/ui/CCursorControlXCB.cpp index 8404504391..c0e31761c2 100644 --- a/src/nbl/ui/CCursorControlXCB.cpp +++ b/src/nbl/ui/CCursorControlXCB.cpp @@ -1,11 +1,11 @@ -#include "nbl/ui/XCBConnection.h" +#include "nbl/ui/CCursorControlXCB.h" + #ifdef _NBL_PLATFORM_LINUX_ -#include "nbl/ui/CCursorControlXCB.h" +#include "nbl/ui/XCBConnection.h" #include "nbl/ui/IWindowXCB.h" - namespace nbl::ui { void CCursorControlXCB::setVisible(bool visible) { @@ -17,25 +17,26 @@ namespace nbl::ui } void CCursorControlXCB::setPosition(SPosition pos) { - auto& xcb = m_xcbConnection->getXcbFunctionTable(); - const auto* primaryScreen = m_xcbConnection->primaryScreen(); - xcb.pxcb_warp_pointer(m_xcbConnection->getRawConnection(), XCB_NONE, primaryScreen->root, 0, 0, 0, 0, pos.x, pos.y); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + auto& xcb = m_connection->getXcbFunctionTable(); + const auto* primaryScreen = m_connection->primaryScreen(); + xcb.pxcb_warp_pointer(m_connection->getRawConnection(), XCB_NONE, primaryScreen->root, 0, 0, 0, 0, pos.x, pos.y); + xcb.pxcb_flush(m_connection->getRawConnection()); } + void CCursorControlXCB::setRelativePosition(IWindow* window, SRelativePosition position) { auto* windowXcb = static_cast(window); - auto& xcb = m_xcbConnection->getXcbFunctionTable(); + auto& xcb = m_connection->getXcbFunctionTable(); auto xcbWindow = windowXcb->getXcbWindow(); - xcb.pxcb_warp_pointer(m_xcbConnection->getRawConnection(), XCB_NONE, xcbWindow, 0, 0, 0, 0, position.x, position.y); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_warp_pointer(m_connection->getRawConnection(), XCB_NONE, xcbWindow, 0, 0, 0, 0, position.x, position.y); + xcb.pxcb_flush(m_connection->getRawConnection()); } CCursorControlXCB::SPosition CCursorControlXCB::getPosition() { - auto& xcb = m_xcbConnection->getXcbFunctionTable(); - xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_xcbConnection->getRawConnection(), m_xcbConnection->primaryScreen()->root); - if(auto reply = xcb.pxcb_query_pointer_reply(m_xcbConnection->getRawConnection(), token, nullptr)) { - core::SRAIIBasedExiter exitReply([&reply]() -> void { + auto& xcb = m_connection->getXcbFunctionTable(); + xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_connection->getRawConnection(), m_connection->primaryScreen()->root); + if(auto reply = xcb.pxcb_query_pointer_reply(m_connection->getRawConnection(), token, nullptr)) { + core::SRAIIBasedExiter exitReply([reply]() -> void { free(reply); }); return {reply->root_x, reply->root_y}; @@ -44,7 +45,14 @@ namespace nbl::ui } CCursorControlXCB::SRelativePosition CCursorControlXCB::getRelativePosition(IWindow* window) { - + auto& xcb = m_connection->getXcbFunctionTable(); + xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_connection->getRawConnection(), m_connection->primaryScreen()->root); + if(auto reply = xcb.pxcb_query_pointer_reply(m_connection->getRawConnection(), token, nullptr)) { + core::SRAIIBasedExiter exitReply([reply]() -> void { + free(reply); + }); + return {static_cast(reply->win_x), static_cast(reply->win_y)}; + } return {0, 0}; } } diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index f4ea8ddf9b..395bb2281f 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -37,12 +37,12 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ return; } auto& xcb = m_window.m_windowManager->getXcbFunctionTable(); - auto& xcbConnection = m_window.m_xcbConnection; + auto& connection = m_window.m_connection; - auto MW_DELETE_WINDOW = xcbConnection->resolveXCBAtom(m_window.m_WM_DELETE_WINDOW); - auto NET_WM_PING = xcbConnection->resolveXCBAtom(m_window.m_NET_WM_PING); + auto MW_DELETE_WINDOW = connection->resolveAtom(m_window.m_WM_DELETE_WINDOW); + auto NET_WM_PING = connection->resolveAtom(m_window.m_NET_WM_PING); - if(auto event = xcb.pxcb_wait_for_event(xcbConnection->getRawConnection())) { + if(auto event = xcb.pxcb_wait_for_event(connection->getRawConnection())) { auto* eventCallback = m_window.getEventCallback(); m_window.m_clipboardManager->process(&m_window, event); switch (event->response_type & ~0x80) @@ -81,7 +81,7 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ m_window.m_xcbWindow = 0; m_quit = true; // we need to quit the dispatch thread eventCallback->onWindowClosed(&m_window); - } else if(cme->data.data32[0] == NET_WM_PING && cme->window != xcbConnection->primaryScreen()->root) { + } else if(cme->data.data32[0] == NET_WM_PING && cme->window != connection->primaryScreen()->root) { xcb_client_message_event_t ev = *cme; ev.response_type = XCB_CLIENT_MESSAGE; ev.window = m_window.m_xcbWindow; @@ -150,17 +150,17 @@ bool CWindowManagerXCB::setWindowMaximized_impl(IWindow* window, bool maximized) CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params): IWindowXCB(std::move(params)), m_windowManager(winManager), - m_xcbConnection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), - m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), - m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_xcbConnection))), + m_connection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), + m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), + m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), m_dispatcher(*this) { auto& xcb = m_windowManager->getXcbFunctionTable(); auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); - m_xcbWindow = xcb.pxcb_generate_id(m_xcbConnection->getRawConnection()); + m_xcbWindow = xcb.pxcb_generate_id(m_connection->getRawConnection()); - const auto* primaryScreen = m_xcbConnection->primaryScreen(); + const auto* primaryScreen = m_connection->primaryScreen(); uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; uint32_t valueList[] = { @@ -170,7 +170,7 @@ CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, S }; xcb_void_cookie_t xcbCheckResult = xcb.pxcb_create_window( - m_xcbConnection->getRawConnection(), XCB_COPY_FROM_PARENT, m_xcbWindow, primaryScreen->root, + m_connection->getRawConnection(), XCB_COPY_FROM_PARENT, m_xcbWindow, primaryScreen->root, static_cast(m_x), static_cast(m_y), static_cast(m_width), @@ -180,30 +180,30 @@ CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, S setWindowSize_impl(m_width, m_height); - auto WM_DELETE_WINDOW = m_xcbConnection->resolveXCBAtom(m_WM_DELETE_WINDOW); - auto NET_WM_PING = m_xcbConnection->resolveXCBAtom(m_NET_WM_PING); - auto WM_PROTOCOLS = m_xcbConnection->resolveXCBAtom(m_WM_PROTOCOLS); + auto WM_DELETE_WINDOW = m_connection->resolveAtom(m_WM_DELETE_WINDOW); + auto NET_WM_PING = m_connection->resolveAtom(m_NET_WM_PING); + auto WM_PROTOCOLS = m_connection->resolveAtom(m_WM_PROTOCOLS); const std::array atoms {WM_DELETE_WINDOW, NET_WM_PING}; xcb.pxcb_change_property( - m_xcbConnection->getRawConnection(), + m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_xcbWindow, WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); auto motifHints = fetchMotifMWHints(getFlags().value); - m_xcbConnection->setMotifWmHints(m_xcbWindow, motifHints); + m_connection->setMotifWmHints(m_xcbWindow, motifHints); if(isAlwaysOnTop()) { XCBConnection::XCBAtomToken NET_WM_STATE_ABOVE; - m_xcbConnection->setNetMWState( + m_connection->setNetMWState( primaryScreen->root, - m_xcbWindow, false, m_xcbConnection->resolveXCBAtom(NET_WM_STATE_ABOVE)); + m_xcbWindow, false, m_connection->resolveAtom(NET_WM_STATE_ABOVE)); } - xcb.pxcb_map_window(m_xcbConnection->getRawConnection(), m_xcbWindow); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_map_window(m_connection->getRawConnection(), m_xcbWindow); + xcb.pxcb_flush(m_connection->getRawConnection()); m_dispatcher.start(); } @@ -234,7 +234,7 @@ bool CWindowXCB::setWindowSize_impl(uint32_t width, uint32_t height) { xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); } - xcbIccm.pxcb_icccm_set_wm_normal_hints(m_xcbConnection->getRawConnection(), m_xcbWindow, &hints); + xcbIccm.pxcb_icccm_set_wm_normal_hints(m_connection->getRawConnection(), m_xcbWindow, &hints); return true; } @@ -242,9 +242,9 @@ bool CWindowXCB::setWindowPosition_impl(int32_t x, int32_t y) { auto& xcb = m_windowManager->getXcbFunctionTable(); const int32_t values[] = { x, y }; - auto cookie = xcb.pxcb_configure_window_checked(m_xcbConnection->getRawConnection(), m_xcbWindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); - bool check = checkXcbCookie(xcb, m_xcbConnection->getRawConnection(), cookie); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + auto cookie = xcb.pxcb_configure_window_checked(m_connection->getRawConnection(), m_xcbWindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + bool check = checkXcbCookie(xcb, m_connection->getRawConnection(), cookie); + xcb.pxcb_flush(m_connection->getRawConnection()); assert(check); return true; } @@ -252,8 +252,8 @@ bool CWindowXCB::setWindowPosition_impl(int32_t x, int32_t y) { void CWindowXCB::setCaption(const std::string_view& caption) { auto& xcb = m_windowManager->getXcbFunctionTable(); - xcb.pxcb_change_property(m_xcbConnection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_change_property(m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); + xcb.pxcb_flush(m_connection->getRawConnection()); } bool CWindowXCB::setWindowRotation_impl(bool landscape) { @@ -264,30 +264,30 @@ bool CWindowXCB::setWindowVisible_impl( bool visible) { auto& xcb = m_windowManager->getXcbFunctionTable(); if(visible) { - xcb.pxcb_map_window(m_xcbConnection->getRawConnection(), m_xcbWindow); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_map_window(m_connection->getRawConnection(), m_xcbWindow); + xcb.pxcb_flush(m_connection->getRawConnection()); } else { - xcb.pxcb_unmap_window(m_xcbConnection->getRawConnection(), m_xcbWindow); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_unmap_window(m_connection->getRawConnection(), m_xcbWindow); + xcb.pxcb_flush(m_connection->getRawConnection()); } return true; } bool CWindowXCB::setWindowMaximized_impl(bool maximized) { auto& xcb = m_windowManager->getXcbFunctionTable(); - const auto* primaryScreen = m_xcbConnection->primaryScreen(); + const auto* primaryScreen = m_connection->primaryScreen(); - m_xcbConnection->setNetMWState( + m_connection->setNetMWState( primaryScreen->root, - m_xcbWindow, maximized && !isBorderless(), m_xcbConnection->resolveXCBAtom(m_NET_WM_STATE_FULLSCREEN)); + m_xcbWindow, maximized && !isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_FULLSCREEN)); - m_xcbConnection->setNetMWState( + m_connection->setNetMWState( primaryScreen->root, m_xcbWindow, maximized && isBorderless(), - m_xcbConnection->resolveXCBAtom(m_NET_WM_STATE_MAXIMIZED_VERT), - m_xcbConnection->resolveXCBAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); + m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_VERT), + m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); - xcb.pxcb_flush(m_xcbConnection->getRawConnection()); + xcb.pxcb_flush(m_connection->getRawConnection()); return true; } diff --git a/src/nbl/ui/XCBConnection.cpp b/src/nbl/ui/XCBConnection.cpp index 703cbdcd4e..dece604089 100644 --- a/src/nbl/ui/XCBConnection.cpp +++ b/src/nbl/ui/XCBConnection.cpp @@ -20,7 +20,7 @@ namespace nbl::ui xcb_client_message_event_t event; event.response_type = XCB_CLIENT_MESSAGE; - event.type = resolveXCBAtom(m_NET_WM_STATE); + event.type = resolveAtom(m_NET_WM_STATE); event.window = window; event.format = 32; event.sequence = 0; @@ -45,7 +45,7 @@ namespace nbl::ui void XCBConnection::setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const { const auto& xcb = m_windowManager->getXcbFunctionTable(); - auto atomHint = resolveXCBAtom(m_MOTIF_WM_HINTS); + auto atomHint = resolveAtom(m_MOTIF_WM_HINTS); if(hint.flags != MotifFlags::MWM_HINTS_NONE) { xcb.pxcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, window, atomHint, From 78172bf1eddda5b0d6ce5241487f3b73f7e2d69c Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 4 Apr 2023 21:03:12 -0700 Subject: [PATCH 4/9] address some of the comments Signed-off-by: Michael Pollind --- include/nbl/ui/CWindowManagerXCB.h | 67 ++++------------- include/nbl/ui/CWindowXCB.h | 26 ++++--- include/nbl/ui/IWindowManagerXCB.h | 62 ++++++++++++++++ include/nbl/ui/IWindowXCB.h | 8 ++- include/nbl/ui/XCBConnection.h | 4 +- src/nbl/CMakeLists.txt | 1 + src/nbl/ui/CClipboardManagerXCB.cpp | 2 + src/nbl/ui/CWindowManagerXCB.cpp | 58 +++++++++++++++ src/nbl/ui/CWindowXCB.cpp | 107 +++++++--------------------- 9 files changed, 188 insertions(+), 147 deletions(-) create mode 100644 include/nbl/ui/IWindowManagerXCB.h create mode 100644 src/nbl/ui/CWindowManagerXCB.cpp diff --git a/include/nbl/ui/CWindowManagerXCB.h b/include/nbl/ui/CWindowManagerXCB.h index 688c84b852..ff3f28cc65 100644 --- a/include/nbl/ui/CWindowManagerXCB.h +++ b/include/nbl/ui/CWindowManagerXCB.h @@ -1,5 +1,5 @@ -#ifndef C_WINDOW_MANAGER_XCB -#define C_WINDOW_MANAGER_XCB +#ifndef _NBL_UI_C__WINDOWMANAGER_XCB_INCLUDED_ +#define _NBL_UI_C__WINDOWMANAGER_XCB_INCLUDED_ #ifdef _NBL_PLATFORM_LINUX_ #include "nbl/core/decl/Types.h" @@ -7,67 +7,24 @@ #include "nbl/system/DefaultFuncPtrLoader.h" #include "nbl/ui/IWindow.h" -#include "nbl/ui/IWindowManager.h" +#include "nbl/ui/IWindowManagerXCB.h" #include #include #include -#include -#include -#include - namespace nbl::ui { -NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(Xcb, system::DefaultFuncPtrLoader, - xcb_destroy_window, - xcb_generate_id, - xcb_create_window, - xcb_connect, - xcb_disconnect, - xcb_map_window, - xcb_get_setup, - xcb_setup_roots_iterator, - xcb_flush, - xcb_intern_atom, - xcb_intern_atom_reply, - xcb_unmap_window, - xcb_get_property, - xcb_get_property_reply, - xcb_get_property_value_length, - xcb_change_property, - xcb_configure_window_checked, - xcb_get_property_value, - xcb_wait_for_event, - xcb_send_event, - xcb_request_check, - xcb_delete_property, - xcb_change_window_attributes, - xcb_warp_pointer, - xcb_query_pointer, - xcb_query_pointer_reply, - xcb_get_selection_owner_reply, - xcb_get_selection_owner -); - -NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(XcbIcccm, system::DefaultFuncPtrLoader, - xcb_icccm_set_wm_hints, - xcb_icccm_size_hints_set_size, - xcb_icccm_size_hints_set_min_size, - xcb_icccm_size_hints_set_max_size, - xcb_icccm_set_wm_normal_hints -); - -class CWindowManagerXCB : public IWindowManager +class CWindowManagerXCB final : public IWindowManagerXCB { public: - - virtual bool setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) override; - virtual bool setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) override; - virtual bool setWindowRotation_impl(IWindow* window, bool landscape) override; - virtual bool setWindowVisible_impl(IWindow* window, bool visible) override; - virtual bool setWindowMaximized_impl(IWindow* window, bool maximized) override; + + bool setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) override; + bool setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) override; + bool setWindowRotation_impl(IWindow* window, bool landscape) override; + bool setWindowVisible_impl(IWindow* window, bool visible) override; + bool setWindowMaximized_impl(IWindow* window, bool maximized) override; inline SDisplayInfo getPrimaryDisplayInfo() const override final { return SDisplayInfo(); @@ -76,9 +33,9 @@ class CWindowManagerXCB : public IWindowManager CWindowManagerXCB(); ~CWindowManagerXCB() override = default; - virtual core::smart_refctd_ptr createWindow(IWindow::SCreationParams&& creationParams) override; + core::smart_refctd_ptr createWindow(IWindow::SCreationParams&& creationParams) override; - virtual void destroyWindow(IWindow* wnd) override final {} + void destroyWindow(IWindow* wnd) override final {} const Xcb& getXcbFunctionTable() const { return m_xcb; } const XcbIcccm& getXcbIcccmFunctionTable() const { return m_xcbIcccm; } diff --git a/include/nbl/ui/CWindowXCB.h b/include/nbl/ui/CWindowXCB.h index 80acf1a753..8ea36a11de 100644 --- a/include/nbl/ui/CWindowXCB.h +++ b/include/nbl/ui/CWindowXCB.h @@ -1,5 +1,5 @@ -#ifndef __C_WINDOW_XCB_H_INCLUDED__ -#define __C_WINDOW_XCB_H_INCLUDED__ +#ifndef _NBL_UI_C_WINDOW_XCB_H_INCLUDED_ +#define _NBL_UI_C_WINDOW_XCB_H_INCLUDED_ #include "nbl/core/decl/smart_refctd_ptr.h" #include "nbl/ui/IClipboardManagerXCB.h" @@ -23,8 +23,13 @@ class NBL_API2 CWindowXCB final : public IWindowXCB CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params); ~CWindowXCB(); + + const native_handle_t* getNativeHandle() const override { + return &m_handle; + } + // Display* getDisplay() const override { return m_dpy; } - xcb_window_t getXcbWindow() const override { return m_xcbWindow; } + xcb_window_t getXcbWindow() const override { return m_handle.m_window; } xcb_connection_t* getXcbConnection() const override { return m_connection->getRawConnection(); } @@ -52,13 +57,18 @@ class NBL_API2 CWindowXCB final : public IWindowXCB class CDispatchThread final : public system::IThreadHandler { public: + using base_t = system::IThreadHandler; + + inline CDispatchThread(CWindowXCB& window) : + base_t(base_t::start_on_construction_t {}), + m_window(window) { - inline CDispatchThread(CWindowXCB& window); + } inline ~CDispatchThread() { } - void init(); - void exit(); + inline void init() {} + inline void exit() {} void work(lock_t& lock); inline bool wakeupPredicate() const { return true; } @@ -67,8 +77,8 @@ class NBL_API2 CWindowXCB final : public IWindowXCB CWindowXCB& m_window; friend class CWindowXCB; } m_dispatcher; - - xcb_window_t m_xcbWindow = 0; + + native_handle_t m_handle = {{0}}; XCBConnection::XCBAtomToken m_WM_DELETE_WINDOW; XCBConnection::XCBAtomToken m_WM_PROTOCOLS; diff --git a/include/nbl/ui/IWindowManagerXCB.h b/include/nbl/ui/IWindowManagerXCB.h new file mode 100644 index 0000000000..3f1093ee83 --- /dev/null +++ b/include/nbl/ui/IWindowManagerXCB.h @@ -0,0 +1,62 @@ +#ifndef _NBL_UI_I_WINDOWMANAGER_XCB_INCLUDED_ +#define _NBL_UI_I_WINDOWMANAGER_XCB_INCLUDED_ + +#include "nbl/ui/IWindowManager.h" + +#ifdef _NBL_PLATFORM_LINUX_ + +#include +#include +#include + +namespace nbl::ui { + +class IWindowManagerXCB : public IWindowManager +{ + public: + NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(Xcb, system::DefaultFuncPtrLoader, + xcb_destroy_window, + xcb_generate_id, + xcb_create_window, + xcb_connect, + xcb_disconnect, + xcb_map_window, + xcb_get_setup, + xcb_setup_roots_iterator, + xcb_flush, + xcb_intern_atom, + xcb_intern_atom_reply, + xcb_unmap_window, + xcb_get_property, + xcb_get_property_reply, + xcb_get_property_value_length, + xcb_change_property, + xcb_configure_window_checked, + xcb_get_property_value, + xcb_wait_for_event, + xcb_send_event, + xcb_request_check, + xcb_delete_property, + xcb_change_window_attributes, + xcb_warp_pointer, + xcb_query_pointer, + xcb_query_pointer_reply, + xcb_get_selection_owner_reply, + xcb_get_selection_owner + ); + + NBL_SYSTEM_DECLARE_DYNAMIC_FUNCTION_CALLER_CLASS(XcbIcccm, system::DefaultFuncPtrLoader, + xcb_icccm_set_wm_hints, + xcb_icccm_size_hints_set_size, + xcb_icccm_size_hints_set_min_size, + xcb_icccm_size_hints_set_max_size, + xcb_icccm_set_wm_normal_hints + ); + + NBL_API2 static core::smart_refctd_ptr create(); +}; + +} // namespace nbl::ui + +#endif +#endif \ No newline at end of file diff --git a/include/nbl/ui/IWindowXCB.h b/include/nbl/ui/IWindowXCB.h index 6a278c6776..edbb73f76c 100644 --- a/include/nbl/ui/IWindowXCB.h +++ b/include/nbl/ui/IWindowXCB.h @@ -22,7 +22,13 @@ class NBL_API2 IWindowXCB : public IWindow public: using IWindow::IWindow; - const void* getNativeHandle() const { return nullptr; } + struct native_handle_t { + xcb_window_t m_window; + xcb_connection_t* m_connection; + }; + + virtual const native_handle_t* getNativeHandle() const = 0; + virtual xcb_window_t getXcbWindow() const = 0; virtual xcb_connection_t* getXcbConnection() const = 0; diff --git a/include/nbl/ui/XCBConnection.h b/include/nbl/ui/XCBConnection.h index 1ffdb8bf5d..f1fc5cf5ed 100644 --- a/include/nbl/ui/XCBConnection.h +++ b/include/nbl/ui/XCBConnection.h @@ -91,8 +91,8 @@ class XCBConnection : public core::IReferenceCounted { return m_connection; } - const Xcb& getXcbFunctionTable() const { return m_windowManager->getXcbFunctionTable(); } - const XcbIcccm& getXcbIcccmFunctionTable() const { return m_windowManager->getXcbIcccmFunctionTable(); } + const CWindowManagerXCB::Xcb& getXcbFunctionTable() const { return m_windowManager->getXcbFunctionTable(); } + const CWindowManagerXCB::XcbIcccm& getXcbIcccmFunctionTable() const { return m_windowManager->getXcbIcccmFunctionTable(); } const xcb_screen_t* primaryScreen(); diff --git a/src/nbl/CMakeLists.txt b/src/nbl/CMakeLists.txt index d9b777594d..a202b3eea7 100755 --- a/src/nbl/CMakeLists.txt +++ b/src/nbl/CMakeLists.txt @@ -188,6 +188,7 @@ set(NBL_UI_SOURCES ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXcb.cpp ${NBL_ROOT_PATH}/src/nbl/ui/XCBConnection.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerXCB.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerXCB.cpp diff --git a/src/nbl/ui/CClipboardManagerXCB.cpp b/src/nbl/ui/CClipboardManagerXCB.cpp index 3aeeaeba41..b8969e2968 100644 --- a/src/nbl/ui/CClipboardManagerXCB.cpp +++ b/src/nbl/ui/CClipboardManagerXCB.cpp @@ -33,6 +33,8 @@ namespace nbl::ui auto TARGETS = m_connection->resolveAtom(m_TARGETS); + const auto& native_handle = window->getNativeHandle(); + switch(event->response_type & ~0x80) { // XCB_ATOM // Somone is requesting the clipboard data diff --git a/src/nbl/ui/CWindowManagerXCB.cpp b/src/nbl/ui/CWindowManagerXCB.cpp new file mode 100644 index 0000000000..d41b871216 --- /dev/null +++ b/src/nbl/ui/CWindowManagerXCB.cpp @@ -0,0 +1,58 @@ +#include "nbl/ui/CWindowManagerXCB.h" + +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/ui/CWindowManagerXCB.h" +#include "nbl/ui/CWindowXCB.h" + +using namespace nbl; +using namespace nbl::ui; + +core::smart_refctd_ptr IWindowManagerXCB::create() +{ + return core::make_smart_refctd_ptr(); +} + + +CWindowManagerXCB::CWindowManagerXCB() { +} + +core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreationParams&& creationParams) +{ + std::string title = std::string(creationParams.windowCaption); + auto window = core::make_smart_refctd_ptr(core::smart_refctd_ptr(this), std::move(creationParams)); + window->setCaption(title); + return window; +} + +bool CWindowManagerXCB::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { + auto wnd = static_cast(window); + wnd->setWindowSize_impl(width, height); + return true; +} + +bool CWindowManagerXCB::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { + auto wnd = static_cast(window); + wnd->setWindowPosition_impl(x, y); + return true; +} + +bool CWindowManagerXCB::setWindowRotation_impl(IWindow* window, bool landscape) { + auto wnd = static_cast(window); + wnd->setWindowRotation_impl(landscape); + return true; +} + +bool CWindowManagerXCB::setWindowVisible_impl(IWindow* window, bool visible) { + auto wnd = static_cast(window); + wnd->setWindowVisible_impl(visible); + return true; +} + +bool CWindowManagerXCB::setWindowMaximized_impl(IWindow* window, bool maximized) { + auto wnd = static_cast(window); + wnd->setWindowMaximized_impl(maximized); + return true; +} + +#endif \ No newline at end of file diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index 395bb2281f..2e2772ef05 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -19,7 +19,7 @@ namespace nbl::ui { -static bool checkXcbCookie(const Xcb& functionTable, xcb_connection_t* connection, xcb_void_cookie_t cookie) { +static bool checkXcbCookie(const IWindowManagerXCB::Xcb& functionTable, xcb_connection_t* connection, xcb_void_cookie_t cookie) { if (xcb_generic_error_t* error = functionTable.pxcb_request_check(connection, cookie)) { printf("XCB error: %d", error->error_code); @@ -28,10 +28,6 @@ static bool checkXcbCookie(const Xcb& functionTable, xcb_connection_t* connectio return true; } -CWindowXCB::CDispatchThread::CDispatchThread(CWindowXCB& window): - m_window(window) { -} - void CWindowXCB::CDispatchThread::work(lock_t& lock){ if(m_quit) { return; @@ -66,7 +62,7 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } case XCB_DESTROY_WINDOW: { xcb_destroy_window_request_t* dwr = reinterpret_cast(event); - if(dwr->window == m_window.m_xcbWindow) { + if(dwr->window == m_window.m_handle.m_window) { m_quit = true; eventCallback->onWindowClosed(&m_window); } @@ -75,18 +71,18 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t* cme = reinterpret_cast(event); if(cme->data.data32[0] == MW_DELETE_WINDOW) { - xcb.pxcb_unmap_window(m_window.getXcbConnection(), m_window.m_xcbWindow); - xcb.pxcb_destroy_window(m_window.getXcbConnection(), m_window.m_xcbWindow); + xcb.pxcb_unmap_window(m_window.getXcbConnection(), m_window.m_handle.m_window); + xcb.pxcb_destroy_window(m_window.getXcbConnection(), m_window.m_handle.m_window); xcb.pxcb_flush(m_window.getXcbConnection()); - m_window.m_xcbWindow = 0; + m_window.m_handle.m_window = 0; m_quit = true; // we need to quit the dispatch thread eventCallback->onWindowClosed(&m_window); } else if(cme->data.data32[0] == NET_WM_PING && cme->window != connection->primaryScreen()->root) { xcb_client_message_event_t ev = *cme; ev.response_type = XCB_CLIENT_MESSAGE; - ev.window = m_window.m_xcbWindow; + ev.window = m_window.m_handle.m_window; ev.type = NET_WM_PING; - xcb.pxcb_send_event(m_window.getXcbConnection(), 0, m_window.m_xcbWindow, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); + xcb.pxcb_send_event(m_window.getXcbConnection(), 0, m_window.m_handle.m_window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); xcb.pxcb_flush(m_window.getXcbConnection()); } break; @@ -97,59 +93,9 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } -void CWindowXCB::CDispatchThread::init() -{ - -} - -void CWindowXCB::CDispatchThread::exit() -{ -} - -CWindowManagerXCB::CWindowManagerXCB() { -} - -core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreationParams&& creationParams) -{ - std::string title = std::string(creationParams.windowCaption); - auto window = core::make_smart_refctd_ptr(core::smart_refctd_ptr(this), std::move(creationParams)); - window->setCaption(title); - return window; -} - -bool CWindowManagerXCB::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { - auto wnd = static_cast(window); - wnd->setWindowSize_impl(width, height); - return true; -} - -bool CWindowManagerXCB::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { - auto wnd = static_cast(window); - wnd->setWindowPosition_impl(x, y); - return true; -} - -bool CWindowManagerXCB::setWindowRotation_impl(IWindow* window, bool landscape) { - auto wnd = static_cast(window); - wnd->setWindowRotation_impl(landscape); - return true; -} - -bool CWindowManagerXCB::setWindowVisible_impl(IWindow* window, bool visible) { - auto wnd = static_cast(window); - wnd->setWindowVisible_impl(visible); - return true; -} - -bool CWindowManagerXCB::setWindowMaximized_impl(IWindow* window, bool maximized) { - auto wnd = static_cast(window); - wnd->setWindowMaximized_impl(maximized); - return true; -} - CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params): IWindowXCB(std::move(params)), - m_windowManager(winManager), + m_windowManager(std::move(winManager)), m_connection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), @@ -158,7 +104,9 @@ CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, S auto& xcb = m_windowManager->getXcbFunctionTable(); auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); - m_xcbWindow = xcb.pxcb_generate_id(m_connection->getRawConnection()); + // m_handle.m_connection = m_connection->getRawConnection(); + m_handle.m_window = xcb.pxcb_generate_id(m_connection->getRawConnection()); + m_handle.m_connection = m_connection->getRawConnection(); const auto* primaryScreen = m_connection->primaryScreen(); @@ -170,7 +118,7 @@ CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, S }; xcb_void_cookie_t xcbCheckResult = xcb.pxcb_create_window( - m_connection->getRawConnection(), XCB_COPY_FROM_PARENT, m_xcbWindow, primaryScreen->root, + m_connection->getRawConnection(), XCB_COPY_FROM_PARENT, m_handle.m_window, primaryScreen->root, static_cast(m_x), static_cast(m_y), static_cast(m_width), @@ -188,23 +136,23 @@ CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, S xcb.pxcb_change_property( m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, - m_xcbWindow, + m_handle.m_window, WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); auto motifHints = fetchMotifMWHints(getFlags().value); - m_connection->setMotifWmHints(m_xcbWindow, motifHints); + m_connection->setMotifWmHints(m_handle.m_window, motifHints); if(isAlwaysOnTop()) { XCBConnection::XCBAtomToken NET_WM_STATE_ABOVE; m_connection->setNetMWState( primaryScreen->root, - m_xcbWindow, false, m_connection->resolveAtom(NET_WM_STATE_ABOVE)); + m_handle.m_window, false, m_connection->resolveAtom(NET_WM_STATE_ABOVE)); } - xcb.pxcb_map_window(m_connection->getRawConnection(), m_xcbWindow); + xcb.pxcb_map_window(m_connection->getRawConnection(), m_handle.m_window); xcb.pxcb_flush(m_connection->getRawConnection()); - m_dispatcher.start(); + } CWindowXCB::~CWindowXCB() @@ -230,11 +178,9 @@ bool CWindowXCB::setWindowSize_impl(uint32_t width, uint32_t height) { xcb_size_hints_t hints = {0}; xcbIccm.pxcb_icccm_size_hints_set_size(&hints, true, width, height); - if(!isResizable()) { - xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); - xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); - } - xcbIccm.pxcb_icccm_set_wm_normal_hints(m_connection->getRawConnection(), m_xcbWindow, &hints); + xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); + xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); + xcbIccm.pxcb_icccm_set_wm_normal_hints(m_connection->getRawConnection(), m_handle.m_window, &hints); return true; } @@ -242,17 +188,16 @@ bool CWindowXCB::setWindowPosition_impl(int32_t x, int32_t y) { auto& xcb = m_windowManager->getXcbFunctionTable(); const int32_t values[] = { x, y }; - auto cookie = xcb.pxcb_configure_window_checked(m_connection->getRawConnection(), m_xcbWindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + auto cookie = xcb.pxcb_configure_window_checked(m_connection->getRawConnection(), m_handle.m_window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); bool check = checkXcbCookie(xcb, m_connection->getRawConnection(), cookie); xcb.pxcb_flush(m_connection->getRawConnection()); - assert(check); return true; } void CWindowXCB::setCaption(const std::string_view& caption) { auto& xcb = m_windowManager->getXcbFunctionTable(); - xcb.pxcb_change_property(m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); + xcb.pxcb_change_property(m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_handle.m_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); xcb.pxcb_flush(m_connection->getRawConnection()); } @@ -264,10 +209,10 @@ bool CWindowXCB::setWindowVisible_impl( bool visible) { auto& xcb = m_windowManager->getXcbFunctionTable(); if(visible) { - xcb.pxcb_map_window(m_connection->getRawConnection(), m_xcbWindow); + xcb.pxcb_map_window(m_connection->getRawConnection(), m_handle.m_window); xcb.pxcb_flush(m_connection->getRawConnection()); } else { - xcb.pxcb_unmap_window(m_connection->getRawConnection(), m_xcbWindow); + xcb.pxcb_unmap_window(m_connection->getRawConnection(), m_handle.m_window); xcb.pxcb_flush(m_connection->getRawConnection()); } return true; @@ -279,11 +224,11 @@ bool CWindowXCB::setWindowMaximized_impl(bool maximized) { m_connection->setNetMWState( primaryScreen->root, - m_xcbWindow, maximized && !isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_FULLSCREEN)); + m_handle.m_window, maximized && !isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_FULLSCREEN)); m_connection->setNetMWState( primaryScreen->root, - m_xcbWindow, maximized && isBorderless(), + m_handle.m_window, maximized && isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_VERT), m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); From a5a9b04e816e97306da1ddbf3cf52f42b791ac0a Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 4 Apr 2023 21:58:01 -0700 Subject: [PATCH 5/9] remove getXcbWindow and getXcbConnection Signed-off-by: Michael Pollind --- include/nbl/ui/CWindowXCB.h | 7 ------- include/nbl/ui/IWindowXCB.h | 3 --- src/nbl/ui/CClipboardManagerXCB.cpp | 9 ++++----- src/nbl/ui/CCursorControlXCB.cpp | 7 ++++--- src/nbl/ui/CWindowXCB.cpp | 16 +++++++++------- src/nbl/video/CSurfaceVulkan.cpp | 6 ++++-- 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/include/nbl/ui/CWindowXCB.h b/include/nbl/ui/CWindowXCB.h index 8ea36a11de..055966f9bd 100644 --- a/include/nbl/ui/CWindowXCB.h +++ b/include/nbl/ui/CWindowXCB.h @@ -23,17 +23,10 @@ class NBL_API2 CWindowXCB final : public IWindowXCB CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params); ~CWindowXCB(); - const native_handle_t* getNativeHandle() const override { return &m_handle; } - // Display* getDisplay() const override { return m_dpy; } - xcb_window_t getXcbWindow() const override { return m_handle.m_window; } - xcb_connection_t* getXcbConnection() const override { - return m_connection->getRawConnection(); - } - virtual IClipboardManager* getClipboardManager() override; virtual ICursorControl* getCursorControl() override; virtual IWindowManager* getManager() override; diff --git a/include/nbl/ui/IWindowXCB.h b/include/nbl/ui/IWindowXCB.h index edbb73f76c..f52bf1267b 100644 --- a/include/nbl/ui/IWindowXCB.h +++ b/include/nbl/ui/IWindowXCB.h @@ -29,9 +29,6 @@ class NBL_API2 IWindowXCB : public IWindow virtual const native_handle_t* getNativeHandle() const = 0; - virtual xcb_window_t getXcbWindow() const = 0; - virtual xcb_connection_t* getXcbConnection() const = 0; - virtual bool setWindowSize_impl(uint32_t width, uint32_t height) = 0; virtual bool setWindowPosition_impl(int32_t x, int32_t y) = 0; virtual bool setWindowRotation_impl(bool landscape) = 0; diff --git a/src/nbl/ui/CClipboardManagerXCB.cpp b/src/nbl/ui/CClipboardManagerXCB.cpp index b8969e2968..ab8ce46d30 100644 --- a/src/nbl/ui/CClipboardManagerXCB.cpp +++ b/src/nbl/ui/CClipboardManagerXCB.cpp @@ -30,17 +30,16 @@ namespace nbl::ui void CClipboardManagerXCB::process(const IWindowXCB* window, xcb_generic_event_t* event) { const auto& xcb = m_connection->getXcbFunctionTable(); - + auto* windowHandle = window->getNativeHandle(); + assert(windowHandle && windowHandle->m_window != XCB_WINDOW_NONE && windowHandle->m_connection != nullptr); auto TARGETS = m_connection->resolveAtom(m_TARGETS); - const auto& native_handle = window->getNativeHandle(); - switch(event->response_type & ~0x80) { // XCB_ATOM // Somone is requesting the clipboard data case XCB_SELECTION_REQUEST: { auto* sne = reinterpret_cast(event); - if(sne->requestor == window->getXcbWindow()) { + if(sne->requestor == windowHandle->m_window) { if(sne->target == TARGETS) { std::vector targets; { @@ -113,7 +112,7 @@ namespace nbl::ui // we've requested the clipboard data, and this is the reply case XCB_SELECTION_NOTIFY: { auto* sne = reinterpret_cast(event); - if(sne->requestor == window->getXcbWindow()){ + if(sne->requestor == windowHandle->m_window){ // xcb.pxcb_get_a xcb_atom_t fieldType = XCB_ATOM; if(sne->target != TARGETS) { diff --git a/src/nbl/ui/CCursorControlXCB.cpp b/src/nbl/ui/CCursorControlXCB.cpp index c0e31761c2..3243acb580 100644 --- a/src/nbl/ui/CCursorControlXCB.cpp +++ b/src/nbl/ui/CCursorControlXCB.cpp @@ -26,9 +26,10 @@ namespace nbl::ui void CCursorControlXCB::setRelativePosition(IWindow* window, SRelativePosition position) { auto* windowXcb = static_cast(window); auto& xcb = m_connection->getXcbFunctionTable(); - auto xcbWindow = windowXcb->getXcbWindow(); - - xcb.pxcb_warp_pointer(m_connection->getRawConnection(), XCB_NONE, xcbWindow, 0, 0, 0, 0, position.x, position.y); + auto* handle = windowXcb->getNativeHandle(); + assert(handle && handle->m_window != XCB_WINDOW_NONE); + + xcb.pxcb_warp_pointer(m_connection->getRawConnection(), XCB_NONE, handle->m_window, 0, 0, 0, 0, position.x, position.y); xcb.pxcb_flush(m_connection->getRawConnection()); } diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index 2e2772ef05..edf056f5ab 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -34,6 +34,8 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } auto& xcb = m_window.m_windowManager->getXcbFunctionTable(); auto& connection = m_window.m_connection; + auto& windowHandle = m_window.m_handle; + auto MW_DELETE_WINDOW = connection->resolveAtom(m_window.m_WM_DELETE_WINDOW); auto NET_WM_PING = connection->resolveAtom(m_window.m_NET_WM_PING); @@ -62,7 +64,7 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } case XCB_DESTROY_WINDOW: { xcb_destroy_window_request_t* dwr = reinterpret_cast(event); - if(dwr->window == m_window.m_handle.m_window) { + if(dwr->window == windowHandle.m_window) { m_quit = true; eventCallback->onWindowClosed(&m_window); } @@ -71,10 +73,10 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t* cme = reinterpret_cast(event); if(cme->data.data32[0] == MW_DELETE_WINDOW) { - xcb.pxcb_unmap_window(m_window.getXcbConnection(), m_window.m_handle.m_window); - xcb.pxcb_destroy_window(m_window.getXcbConnection(), m_window.m_handle.m_window); - xcb.pxcb_flush(m_window.getXcbConnection()); - m_window.m_handle.m_window = 0; + xcb.pxcb_unmap_window(windowHandle.m_connection, windowHandle.m_window); + xcb.pxcb_destroy_window(windowHandle.m_connection, windowHandle.m_window); + xcb.pxcb_flush(windowHandle.m_connection); + windowHandle.m_window = 0; m_quit = true; // we need to quit the dispatch thread eventCallback->onWindowClosed(&m_window); } else if(cme->data.data32[0] == NET_WM_PING && cme->window != connection->primaryScreen()->root) { @@ -82,8 +84,8 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ ev.response_type = XCB_CLIENT_MESSAGE; ev.window = m_window.m_handle.m_window; ev.type = NET_WM_PING; - xcb.pxcb_send_event(m_window.getXcbConnection(), 0, m_window.m_handle.m_window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); - xcb.pxcb_flush(m_window.getXcbConnection()); + xcb.pxcb_send_event(windowHandle.m_connection, 0, m_window.m_handle.m_window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); + xcb.pxcb_flush(windowHandle.m_connection); } break; } diff --git a/src/nbl/video/CSurfaceVulkan.cpp b/src/nbl/video/CSurfaceVulkan.cpp index 49cded60eb..770b900a2d 100644 --- a/src/nbl/video/CSurfaceVulkan.cpp +++ b/src/nbl/video/CSurfaceVulkan.cpp @@ -151,11 +151,13 @@ namespace nbl::video if(!api || !window) return nullptr; + auto* handle = window->getNativeHandle(); + assert(handle && handle->m_window != XCB_WINDOW_NONE && handle->m_connection != nullptr); VkXcbSurfaceCreateInfoKHR createInfo { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; createInfo.pNext = nullptr; createInfo.flags = 0; - createInfo.connection = window->getXcbConnection(); - createInfo.window = window->getXcbWindow(); + createInfo.connection = handle->m_connection; + createInfo.window = handle->m_window; VkSurfaceKHR vk_surface; if (vkCreateXcbSurfaceKHR(api->getInternalObject(), &createInfo, nullptr, &vk_surface) == VK_SUCCESS) { From 0daeef13ba4d43534fbaaa146b94635478f0b483 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 5 Apr 2023 20:25:51 -0700 Subject: [PATCH 6/9] shuffled around implementation Signed-off-by: Michael Pollind --- include/nbl/ui/CClipboardManagerXCB.h | 52 ++---- include/nbl/ui/CCursorControlXCB.h | 6 +- include/nbl/ui/CWindowManagerXCB.h | 15 +- include/nbl/ui/CWindowXCB.h | 25 +-- include/nbl/ui/IWindowManagerXCB.h | 3 + include/nbl/ui/IWindowXCB.h | 64 +------ include/nbl/ui/XCBConnection.h | 111 ----------- include/nbl/ui/XCBHandle.h | 227 +++++++++++++++++++++++ src/nbl/CMakeLists.txt | 1 + src/nbl/ui/CClipboardManagerXCB.cpp | 254 +++++++++++++------------- src/nbl/ui/CCursorControlXCB.cpp | 56 +++--- src/nbl/ui/CWindowManagerXCB.cpp | 73 +++++++- src/nbl/ui/CWindowXCB.cpp | 193 ++++++++++--------- src/nbl/ui/XCBConnection.cpp | 60 ------ src/nbl/video/CSurfaceVulkan.cpp | 4 +- 15 files changed, 592 insertions(+), 552 deletions(-) delete mode 100644 include/nbl/ui/XCBConnection.h create mode 100644 include/nbl/ui/XCBHandle.h delete mode 100644 src/nbl/ui/XCBConnection.cpp diff --git a/include/nbl/ui/CClipboardManagerXCB.h b/include/nbl/ui/CClipboardManagerXCB.h index a65693160f..b7fa6f2d6a 100644 --- a/include/nbl/ui/CClipboardManagerXCB.h +++ b/include/nbl/ui/CClipboardManagerXCB.h @@ -5,7 +5,6 @@ #include "nbl/core/decl/Types.h" #include "nbl/ui/IClipboardManagerXCB.h" -#include "nbl/ui/XCBConnection.h" namespace nbl::ui { @@ -13,37 +12,26 @@ class IWindowXCB; class XCBConnection; // details on XCB clipboard protocol: https://tronche.com/gui/x/icccm/sec-2.html#s-2 -class NBL_API2 CClipboardManagerXCB final : public IClipboardManagerXCB -{ - public: - inline CClipboardManagerXCB(core::smart_refctd_ptr&& connect): - IClipboardManagerXCB(), - m_connection(std::move(connect)) {} - - virtual std::string getClipboardText() override; - virtual bool setClipboardText(const std::string_view& data) override; - - void process(const IWindowXCB* window, xcb_generic_event_t* event) override; - private: - core::smart_refctd_ptr m_connection; - std::mutex m_clipboardMutex; - std::condition_variable m_clipboardResponseCV; - std::string m_clipboardResponse; // data sent to the clipboard by another application - - std::string m_savedClipboard; // data saved to the clipboard for another application to read - - XCBConnection::XCBAtomToken m_CLIPBOARD; - XCBConnection::XCBAtomToken m_TARGETS; - XCBConnection::XCBAtomToken m_INCR; - - XCBConnection::XCBAtomToken m_formatUTF8_0; - XCBConnection::XCBAtomToken m_formatUTF8_1; - XCBConnection::XCBAtomToken m_formatUTF8_2; - XCBConnection::XCBAtomToken m_formatGTK; - XCBConnection::XCBAtomToken m_formatString; - XCBConnection::XCBAtomToken m_formatText; - XCBConnection::XCBAtomToken m_formatTextPlain; -}; +// class NBL_API2 CClipboardManagerXCB final : public IClipboardManagerXCB +// { +// public: +// inline CClipboardManagerXCB(core::smart_refctd_ptr&& connect): +// IClipboardManagerXCB(), +// m_connection(std::move(connect)) {} + +// virtual std::string getClipboardText() override; +// virtual bool setClipboardText(const std::string_view& data) override; + +// void process(const IWindowXCB* window, xcb_generic_event_t* event) override; +// private: +// core::smart_refctd_ptr m_connection; +// std::mutex m_clipboardMutex; +// std::condition_variable m_clipboardResponseCV; +// std::string m_clipboardResponse; // data sent to the clipboard by another application + +// std::string m_savedClipboard; // data saved to the clipboard for another application to read + +// }; } diff --git a/include/nbl/ui/CCursorControlXCB.h b/include/nbl/ui/CCursorControlXCB.h index 1976948f50..da6ef1e8cc 100644 --- a/include/nbl/ui/CCursorControlXCB.h +++ b/include/nbl/ui/CCursorControlXCB.h @@ -12,9 +12,7 @@ class XCBConnection; class NBL_API2 CCursorControlXCB final : public ICursorControl { public: - inline CCursorControlXCB( - core::smart_refctd_ptr&& xcbConnection) : - m_connection(std::move(xcbConnection)) {} + inline CCursorControlXCB() {} void setVisible(bool visible) override; bool isVisible() const override; @@ -25,7 +23,7 @@ class NBL_API2 CCursorControlXCB final : public ICursorControl SPosition getPosition() override; SRelativePosition getRelativePosition(IWindow* window) override; private: - core::smart_refctd_ptr m_connection; + // core::smart_refctd_ptr m_connection; }; } diff --git a/include/nbl/ui/CWindowManagerXCB.h b/include/nbl/ui/CWindowManagerXCB.h index ff3f28cc65..32ec08af22 100644 --- a/include/nbl/ui/CWindowManagerXCB.h +++ b/include/nbl/ui/CWindowManagerXCB.h @@ -2,24 +2,19 @@ #define _NBL_UI_C__WINDOWMANAGER_XCB_INCLUDED_ #ifdef _NBL_PLATFORM_LINUX_ -#include "nbl/core/decl/Types.h" -#include "nbl/system/DefaultFuncPtrLoader.h" +#include "nbl/core/decl/Types.h" #include "nbl/ui/IWindow.h" #include "nbl/ui/IWindowManagerXCB.h" -#include -#include -#include - namespace nbl::ui { class CWindowManagerXCB final : public IWindowManagerXCB { public: - + bool setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) override; bool setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) override; bool setWindowRotation_impl(IWindow* window, bool landscape) override; @@ -32,13 +27,13 @@ class CWindowManagerXCB final : public IWindowManagerXCB CWindowManagerXCB(); ~CWindowManagerXCB() override = default; - + core::smart_refctd_ptr createWindow(IWindow::SCreationParams&& creationParams) override; void destroyWindow(IWindow* wnd) override final {} - const Xcb& getXcbFunctionTable() const { return m_xcb; } - const XcbIcccm& getXcbIcccmFunctionTable() const { return m_xcbIcccm; } + const Xcb& getXcbFunctionTable() const override { return m_xcb; } + const XcbIcccm& getXcbIcccmFunctionTable() const override { return m_xcbIcccm; } private: Xcb m_xcb = Xcb("xcb"); // function tables diff --git a/include/nbl/ui/CWindowXCB.h b/include/nbl/ui/CWindowXCB.h index 055966f9bd..07c5e6fbc4 100644 --- a/include/nbl/ui/CWindowXCB.h +++ b/include/nbl/ui/CWindowXCB.h @@ -4,7 +4,7 @@ #include "nbl/core/decl/smart_refctd_ptr.h" #include "nbl/ui/IClipboardManagerXCB.h" #include "nbl/ui/IWindowXCB.h" -#include "nbl/ui/XCBConnection.h" +#include "nbl/ui/XCBHandle.h" #include @@ -20,7 +20,7 @@ class NBL_API2 CWindowXCB final : public IWindowXCB { public: - CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params); + CWindowXCB(native_handle_t&& handle, core::smart_refctd_ptr&& winManager, SCreationParams&& params); ~CWindowXCB(); const native_handle_t* getNativeHandle() const override { @@ -31,19 +31,19 @@ class NBL_API2 CWindowXCB final : public IWindowXCB virtual ICursorControl* getCursorControl() override; virtual IWindowManager* getManager() override; - virtual bool setWindowSize_impl(uint32_t width, uint32_t height) override; - virtual bool setWindowPosition_impl(int32_t x, int32_t y) override; - virtual bool setWindowRotation_impl(bool landscape) override; - virtual bool setWindowVisible_impl(bool visible) override; - virtual bool setWindowMaximized_impl(bool maximized) override; + virtual bool setWindowSize(uint32_t width, uint32_t height) override; + virtual bool setWindowPosition(int32_t x, int32_t y) override; + virtual bool setWindowRotation(bool landscape) override; + virtual bool setWindowVisible(bool visible) override; + virtual bool setWindowMaximized(bool maximized) override; virtual void setCaption(const std::string_view& caption) override; private: CWindowXCB(core::smart_refctd_ptr&& sys, uint32_t _w, uint32_t _h, E_CREATE_FLAGS _flags); + native_handle_t m_handle; core::smart_refctd_ptr m_windowManager; - core::smart_refctd_ptr m_connection; core::smart_refctd_ptr m_cursorControl; core::smart_refctd_ptr m_clipboardManager; @@ -70,16 +70,7 @@ class NBL_API2 CWindowXCB final : public IWindowXCB CWindowXCB& m_window; friend class CWindowXCB; } m_dispatcher; - - native_handle_t m_handle = {{0}}; - XCBConnection::XCBAtomToken m_WM_DELETE_WINDOW; - XCBConnection::XCBAtomToken m_WM_PROTOCOLS; - XCBConnection::XCBAtomToken m_NET_WM_PING; - - XCBConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_VERT; - XCBConnection::XCBAtomToken m_NET_WM_STATE_MAXIMIZED_HORZ; - XCBConnection::XCBAtomToken m_NET_WM_STATE_FULLSCREEN; }; diff --git a/include/nbl/ui/IWindowManagerXCB.h b/include/nbl/ui/IWindowManagerXCB.h index 3f1093ee83..9d9838c6db 100644 --- a/include/nbl/ui/IWindowManagerXCB.h +++ b/include/nbl/ui/IWindowManagerXCB.h @@ -53,7 +53,10 @@ class IWindowManagerXCB : public IWindowManager xcb_icccm_set_wm_normal_hints ); + NBL_API2 static core::smart_refctd_ptr create(); + virtual const Xcb& getXcbFunctionTable() const = 0; + virtual const XcbIcccm& getXcbIcccmFunctionTable() const = 0; }; } // namespace nbl::ui diff --git a/include/nbl/ui/IWindowXCB.h b/include/nbl/ui/IWindowXCB.h index f52bf1267b..75e9cad071 100644 --- a/include/nbl/ui/IWindowXCB.h +++ b/include/nbl/ui/IWindowXCB.h @@ -1,12 +1,12 @@ #ifndef __NBL_I_WINDOW_XCB_H_INCLUDED__ #define __NBL_I_WINDOW_XCB_H_INCLUDED__ +#include "nbl/ui/XCBHandle.h" #ifdef _NBL_PLATFORM_LINUX_ #include "nbl/core/util/bitflag.h" #include "nbl/ui/IWindow.h" -#include "nbl/ui/XCBConnection.h" #include @@ -24,68 +24,18 @@ class NBL_API2 IWindowXCB : public IWindow struct native_handle_t { xcb_window_t m_window; - xcb_connection_t* m_connection; + core::smart_refctd_ptr m_connection; }; virtual const native_handle_t* getNativeHandle() const = 0; - - virtual bool setWindowSize_impl(uint32_t width, uint32_t height) = 0; - virtual bool setWindowPosition_impl(int32_t x, int32_t y) = 0; - virtual bool setWindowRotation_impl(bool landscape) = 0; - virtual bool setWindowVisible_impl(bool visible) = 0; - virtual bool setWindowMaximized_impl(bool maximized) = 0; - - static XCBConnection::MotifWmHints fetchMotifMWHints(IWindow::E_CREATE_FLAGS flags) { - core::bitflag motifFlags(XCBConnection::MWM_HINTS_NONE); - core::bitflag motifFunctions(XCBConnection::MWM_FUNC_NONE); - core::bitflag motifDecorations(XCBConnection::MWM_DECOR_NONE); - motifFlags |= XCBConnection::MWM_HINTS_DECORATIONS; - - if (flags & IWindow::ECF_BORDERLESS) { - motifDecorations |= XCBConnection::MWM_DECOR_ALL; - } else { - motifDecorations |= XCBConnection::MWM_DECOR_BORDER; - motifDecorations |= XCBConnection::MWM_DECOR_RESIZEH; - motifDecorations |= XCBConnection::MWM_DECOR_TITLE; - - // minimize button - if(flags & IWindow::ECF_MINIMIZED) { - motifDecorations |= XCBConnection::MWM_DECOR_MINIMIZE; - motifFunctions |= XCBConnection::MWM_FUNC_MINIMIZE; - } - - // maximize button - if(flags & IWindow::ECF_MAXIMIZED) { - motifDecorations |= XCBConnection::MWM_DECOR_MAXIMIZE; - motifFunctions |= XCBConnection::MWM_FUNC_MAXIMIZE; - } - - // close button - motifFunctions |= XCBConnection::MWM_FUNC_CLOSE; - } - - if(motifFunctions.value != XCBConnection::MWM_FUNC_NONE) { - motifFlags |= XCBConnection::MWM_HINTS_FUNCTIONS; - motifFunctions |= XCBConnection::MWM_FUNC_RESIZE; - motifFunctions |= XCBConnection::MWM_FUNC_MOVE; - } else { - motifFunctions = XCBConnection::MWM_FUNC_ALL; - } - - XCBConnection::MotifWmHints hints; - hints.flags = motifFlags.value; - hints.functions = motifFunctions.value; - hints.decorations = motifDecorations.value; - hints.input_mode = 0; - hints.status = 0; - return hints; - - } - + virtual bool setWindowSize(uint32_t width, uint32_t height) = 0; + virtual bool setWindowPosition(int32_t x, int32_t y) = 0; + virtual bool setWindowRotation(bool landscape) = 0; + virtual bool setWindowVisible(bool visible) = 0; + virtual bool setWindowMaximized(bool maximized) = 0; }; } #endif - #endif \ No newline at end of file diff --git a/include/nbl/ui/XCBConnection.h b/include/nbl/ui/XCBConnection.h deleted file mode 100644 index f1fc5cf5ed..0000000000 --- a/include/nbl/ui/XCBConnection.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef C_XCB_CONNECTION_XCB -#define C_XCB_CONNECTION_XCB - -#ifdef _NBL_PLATFORM_LINUX_ - -#include "nbl/core/decl/Types.h" -#include "nbl/core/string/StringLiteral.h" -#include "nbl/core/decl/smart_refctd_ptr.h" -#include "nbl/ui/CWindowManagerXCB.h" - -#include -#include -#include - -#include - -namespace nbl::ui -{ - -class XCBConnection : public core::IReferenceCounted { -public: - template - struct XCBAtomToken { - xcb_atom_t token = 0; - bool fetched = false; - }; - - XCBConnection(core::smart_refctd_ptr&& windowManager); - virtual ~XCBConnection() override; - - template - inline xcb_atom_t resolveAtom(XCBAtomToken& token, bool only_if_exists = true, bool forced = false) const { - const auto& xcb = m_windowManager->getXcbFunctionTable(); - if(token.fetched && !forced) { - return token.token; - } - token.fetched = true; - size_t size = Name.size() - 1; // -1 to remove the null terminator - xcb_intern_atom_cookie_t cookie = xcb.pxcb_intern_atom(m_connection, only_if_exists, size, Name.value); - if(xcb_intern_atom_reply_t* reply = xcb.pxcb_intern_atom_reply(m_connection, cookie, nullptr)) { - token.token = reply->atom; - free(reply); - return token.token; - } - return token.token; - } - - void setNetMWState(xcb_window_t rootWindow, xcb_window_t window, bool set, xcb_atom_t first, xcb_atom_t second = XCB_NONE) const; - - enum MotifFlags: uint32_t { - MWM_HINTS_NONE = 0, - MWM_HINTS_FUNCTIONS = (1L << 0), - MWM_HINTS_DECORATIONS = (1L << 1), - MWM_HINTS_INPUT_MODE = (1L << 2), - MWM_HINTS_STATUS = (1L << 3), - }; - - enum MotifFunctions: uint32_t { - MWM_FUNC_NONE = 0, - MWM_FUNC_ALL = (1L << 0), - MWM_FUNC_RESIZE = (1L << 1), - MWM_FUNC_MOVE = (1L << 2), - MWM_FUNC_MINIMIZE = (1L << 3), - MWM_FUNC_MAXIMIZE = (1L << 4), - MWM_FUNC_CLOSE = (1L << 5), - }; - - enum MotifDecorations: uint32_t { - MWM_DECOR_NONE = 0, - MWM_DECOR_ALL = (1L << 0), - MWM_DECOR_BORDER = (1L << 1), - MWM_DECOR_RESIZEH = (1L << 2), - MWM_DECOR_TITLE = (1L << 3), - MWM_DECOR_MENU = (1L << 4), - MWM_DECOR_MINIMIZE = (1L << 5), - MWM_DECOR_MAXIMIZE = (1L << 6), - }; - - // insane magic in xcb for window hinting good luck finding documentation - // https://fossies.org/linux/motif/lib/Xm/MwmUtil.h - struct MotifWmHints { - MotifFlags flags = MotifFlags::MWM_HINTS_NONE; - MotifFunctions functions = MotifFunctions::MWM_FUNC_NONE; - MotifDecorations decorations = MotifDecorations::MWM_DECOR_NONE; - uint32_t input_mode = 0; // unused - uint32_t status = 0; // unused - }; - void setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const; - - inline xcb_connection_t* getRawConnection() const { - return m_connection; - } - - const CWindowManagerXCB::Xcb& getXcbFunctionTable() const { return m_windowManager->getXcbFunctionTable(); } - const CWindowManagerXCB::XcbIcccm& getXcbIcccmFunctionTable() const { return m_windowManager->getXcbIcccmFunctionTable(); } - - const xcb_screen_t* primaryScreen(); - -private: - core::smart_refctd_ptr m_windowManager; - xcb_connection_t* m_connection = nullptr; - - mutable XCBConnection::XCBAtomToken m_NET_WM_STATE; - mutable XCBConnection::XCBAtomToken m_MOTIF_WM_HINTS; -}; - -} // namespace nbl::ui - -#endif - -#endif // C_XCB_HANDLER_XCB diff --git a/include/nbl/ui/XCBHandle.h b/include/nbl/ui/XCBHandle.h new file mode 100644 index 0000000000..7ba65a7f9c --- /dev/null +++ b/include/nbl/ui/XCBHandle.h @@ -0,0 +1,227 @@ +#ifndef C_XCB_CONNECTION_XCB +#define C_XCB_CONNECTION_XCB + +#ifdef _NBL_PLATFORM_LINUX_ + +#include "nbl/core/decl/Types.h" +#include "nbl/core/string/StringLiteral.h" +#include "nbl/core/decl/smart_refctd_ptr.h" +#include "nbl/ui/IWindowManagerXCB.h" + +#include +#include +#include + +#include + +namespace nbl::ui::xcb +{ + class XCBHandle; + + enum MotifFlags: uint32_t { + MWM_HINTS_NONE = 0, + MWM_HINTS_FUNCTIONS = (1L << 0), + MWM_HINTS_DECORATIONS = (1L << 1), + MWM_HINTS_INPUT_MODE = (1L << 2), + MWM_HINTS_STATUS = (1L << 3), + }; + + enum MotifFunctions: uint32_t { + MWM_FUNC_NONE = 0, + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), + }; + + enum MotifDecorations: uint32_t { + MWM_DECOR_NONE = 0, + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), + }; + + // insane magic in xcb for window hinting good luck finding documentation + // https://fossies.org/linux/motif/lib/Xm/MwmUtil.h + struct MotifWmHints { + MotifFlags flags = MotifFlags::MWM_HINTS_NONE; + MotifFunctions functions = MotifFunctions::MWM_FUNC_NONE; + MotifDecorations decorations = MotifDecorations::MWM_DECOR_NONE; + uint32_t input_mode = 0; // unused + uint32_t status = 0; // unused + }; + + inline MotifWmHints createFlagsToMotifWmHints(IWindow::E_CREATE_FLAGS flags) { + core::bitflag motifFlags(MWM_HINTS_NONE); + core::bitflag motifFunctions(MWM_FUNC_NONE); + core::bitflag motifDecorations(MWM_DECOR_NONE); + motifFlags |= MWM_HINTS_DECORATIONS; + + if (flags & IWindow::ECF_BORDERLESS) { + motifDecorations |= MWM_DECOR_ALL; + } else { + motifDecorations |= MWM_DECOR_BORDER; + motifDecorations |= MWM_DECOR_RESIZEH; + motifDecorations |= MWM_DECOR_TITLE; + + // minimize button + if(flags & IWindow::ECF_MINIMIZED) { + motifDecorations |= MWM_DECOR_MINIMIZE; + motifFunctions |= MWM_FUNC_MINIMIZE; + } + + // maximize button + if(flags & IWindow::ECF_MAXIMIZED) { + motifDecorations |= MWM_DECOR_MAXIMIZE; + motifFunctions |= MWM_FUNC_MAXIMIZE; + } + + // close button + motifFunctions |= MWM_FUNC_CLOSE; + } + + if(motifFunctions.value != MWM_FUNC_NONE) { + motifFlags |= MWM_HINTS_FUNCTIONS; + motifFunctions |= MWM_FUNC_RESIZE; + motifFunctions |= MWM_FUNC_MOVE; + } else { + motifFunctions = MWM_FUNC_ALL; + } + + MotifWmHints hints; + hints.flags = motifFlags.value; + hints.functions = motifFunctions.value; + hints.decorations = motifDecorations.value; + hints.input_mode = 0; + hints.status = 0; + return hints; + } + + class XCBHandle final : public core::IReferenceCounted { + public: + template + struct AtomToken { + private: + AtomToken(XCBHandle& handle) : m_handle(handle) {} + XCBHandle& m_handle; + xcb_atom_t m_token = 0; + bool fetched = false; + public: + inline xcb_atom_t fetch(bool only_if_exists = true, + bool forced = false) { + const auto& xcb = m_handle.getXcbFunctionTable(); + if(fetched && !forced) { + return m_token; + } + fetched = true; + size_t size = Name.size() - 1; // -1 to remove the null terminator + xcb_intern_atom_cookie_t cookie = xcb.pxcb_intern_atom(m_handle, only_if_exists, size, Name.value); + if(xcb_intern_atom_reply_t* reply = xcb.pxcb_intern_atom_reply(m_handle, cookie, nullptr)) { + m_token = reply->atom; + free(reply); + return m_token; + } + return m_token; + } + + friend class XCBHandle; + }; + + XCBHandle(core::smart_refctd_ptr&& windowManager): + m_windowManager(std::move(windowManager)) { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + m_connection = xcb.pxcb_connect(nullptr, nullptr); + } + ~XCBHandle() { + if(m_connection) { + const auto& xcb = m_windowManager->getXcbFunctionTable(); + xcb.pxcb_disconnect(m_connection); + } + } + + inline IWindowManagerXCB* windowManager() const { return m_windowManager.get(); } + inline const IWindowManagerXCB::Xcb& getXcbFunctionTable() const { return m_windowManager->getXcbFunctionTable(); } + inline const IWindowManagerXCB::XcbIcccm& getXcbIcccmFunctionTable() const { return m_windowManager->getXcbIcccmFunctionTable(); } + inline operator xcb_connection_t*() { return m_connection; } + inline xcb_connection_t* getNativeHandle() { return m_connection; } + + + AtomToken WM_DELETE_WINDOW{*this}; + AtomToken WM_PROTOCOLS{*this}; + AtomToken _NET_WM_PING{*this}; + + AtomToken _NET_WM_STATE_MAXIMIZED_VERT{*this}; + AtomToken _NET_WM_STATE_MAXIMIZED_HORZ{*this}; + AtomToken _NET_WM_STATE_FULLSCREEN{*this}; + AtomToken _NET_WM_STATE{*this}; + AtomToken _MOTIF_WM_HINTS{*this}; + AtomToken NET_WM_STATE_ABOVE{*this}; + + AtomToken m_CLIPBOARD{*this}; + AtomToken m_TARGETS{*this}; + AtomToken m_INCR{*this}; + + AtomToken m_formatUTF8_0{*this}; + AtomToken m_formatUTF8_1{*this}; + AtomToken m_formatUTF8_2{*this}; + AtomToken m_formatGTK{*this}; + AtomToken m_formatString{*this}; + AtomToken m_formatText{*this}; + AtomToken m_formatTextPlain{*this}; + private: + core::smart_refctd_ptr m_windowManager; + xcb_connection_t* m_connection = nullptr; + }; + + inline void setMotifWmHints(XCBHandle& handle, xcb_window_t window, const MotifWmHints& hint) { + auto& xcb = handle.getXcbFunctionTable(); + + auto atomHint = handle._MOTIF_WM_HINTS.fetch(); + if(hint.flags != MotifFlags::MWM_HINTS_NONE) { + xcb.pxcb_change_property(handle.getNativeHandle(), XCB_PROP_MODE_REPLACE, window, + atomHint, + atomHint, 32, sizeof(MotifWmHints) / sizeof(uint32_t), &hint); + } else { + xcb.pxcb_delete_property(handle.getNativeHandle(), window, atomHint); + } + } + + inline void setNetMWState(XCBHandle& handle, xcb_window_t rootWindow, + xcb_window_t window, + bool set, + xcb_atom_t first, + xcb_atom_t second = XCB_NONE) { + auto& xcb = handle.getXcbFunctionTable(); + + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.type = handle._NET_WM_STATE.fetch(); + event.window = window; + event.format = 32; + event.sequence = 0; + event.data.data32[0] = set ? 1l : 0l; + event.data.data32[1] = first; + event.data.data32[2] = second; + event.data.data32[3] = 1; + event.data.data32[4] = 0; + xcb.pxcb_send_event(handle, 0, rootWindow, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, reinterpret_cast(&event)); + } + + inline const xcb_screen_t* primaryScreen(XCBHandle& handle) { + auto& xcb = handle.getXcbFunctionTable(); + const xcb_setup_t *setup = xcb.pxcb_get_setup(handle); + xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; + return screen; + } +} + + +#endif +#endif // C_XCB_HANDLER_XCB diff --git a/src/nbl/CMakeLists.txt b/src/nbl/CMakeLists.txt index a202b3eea7..1d1a6faa3c 100755 --- a/src/nbl/CMakeLists.txt +++ b/src/nbl/CMakeLists.txt @@ -185,6 +185,7 @@ set(NBL_SYSTEM_SOURCES ) set(NBL_UI_SOURCES ${NBL_ROOT_PATH}/src/nbl/ui/CWindowWin32.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXCB.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXcb.cpp ${NBL_ROOT_PATH}/src/nbl/ui/XCBConnection.cpp diff --git a/src/nbl/ui/CClipboardManagerXCB.cpp b/src/nbl/ui/CClipboardManagerXCB.cpp index ab8ce46d30..ae40c2ced8 100644 --- a/src/nbl/ui/CClipboardManagerXCB.cpp +++ b/src/nbl/ui/CClipboardManagerXCB.cpp @@ -1,6 +1,5 @@ #include "nbl/ui/CClipboardManagerXCB.h" -#include "nbl/ui/XCBConnection.h" #include #include @@ -10,139 +9,138 @@ namespace nbl::ui { - std::string CClipboardManagerXCB::getClipboardText() { - { - std::unique_lock lk(m_clipboardMutex); - m_clipboardResponseCV.wait_until(lk, std::chrono::system_clock::now() + std::chrono::seconds(1)); - } - std::lock_guard lk(m_clipboardMutex); - std::string response = std::move(m_clipboardResponse); - m_clipboardResponse = std::string(); - return response; - } + // std::string CClipboardManagerXCB::getClipboardText() { + // { + // std::unique_lock lk(m_clipboardMutex); + // m_clipboardResponseCV.wait_until(lk, std::chrono::system_clock::now() + std::chrono::seconds(1)); + // } + // std::lock_guard lk(m_clipboardMutex); + // std::string response = std::move(m_clipboardResponse); + // m_clipboardResponse = std::string(); + // return response; + // } - bool CClipboardManagerXCB::setClipboardText(const std::string_view& data) { - std::lock_guard lk(m_clipboardMutex); - m_savedClipboard = data; - return true; - } + // bool CClipboardManagerXCB::setClipboardText(const std::string_view& data) { + // std::lock_guard lk(m_clipboardMutex); + // m_savedClipboard = data; + // return true; + // } - void CClipboardManagerXCB::process(const IWindowXCB* window, xcb_generic_event_t* event) { - const auto& xcb = m_connection->getXcbFunctionTable(); - auto* windowHandle = window->getNativeHandle(); - assert(windowHandle && windowHandle->m_window != XCB_WINDOW_NONE && windowHandle->m_connection != nullptr); - auto TARGETS = m_connection->resolveAtom(m_TARGETS); + // void CClipboardManagerXCB::process(const IWindowXCB* window, xcb_generic_event_t* event) { + // const auto& xcb = m_connection->getXcbFunctionTable(); + // auto* windowHandle = window->getNativeHandle(); + // auto TARGETS = m_connection->resolveAtom(m_TARGETS); - switch(event->response_type & ~0x80) { - // XCB_ATOM - // Somone is requesting the clipboard data - case XCB_SELECTION_REQUEST: { - auto* sne = reinterpret_cast(event); - if(sne->requestor == windowHandle->m_window) { - if(sne->target == TARGETS) { - std::vector targets; - { - std::lock_guard lk(m_clipboardMutex); - for(auto& format : { - m_connection->resolveAtom(m_formatUTF8_0), - m_connection->resolveAtom(m_formatUTF8_1), - m_connection->resolveAtom(m_formatUTF8_2), - m_connection->resolveAtom(m_formatGTK), - m_connection->resolveAtom(m_formatString), - m_connection->resolveAtom(m_formatText), - m_connection->resolveAtom(m_formatTextPlain) - }) { - targets.push_back(format); - } - } - targets.push_back(m_connection->resolveAtom(m_TARGETS)); - xcb.pxcb_change_property( - m_connection->getRawConnection(), - XCB_PROP_MODE_REPLACE, - sne->requestor, - sne->property, - XCB_ATOM, - 8*sizeof(xcb_atom_t), - targets.size(), - &targets[0]); - } else { - std::lock_guard lk(m_clipboardMutex); - xcb.pxcb_change_property( - m_connection->getRawConnection(), - XCB_PROP_MODE_REPLACE, - sne->requestor, - sne->property, - sne->target, - 8, - m_savedClipboard.size(), - m_savedClipboard.data()); - } - } + // switch(event->response_type & ~0x80) { + // // XCB_ATOM + // // Somone is requesting the clipboard data + // case XCB_SELECTION_REQUEST: { + // auto* sne = reinterpret_cast(event); + // if(sne->requestor == windowHandle->m_window) { + // if(sne->target == TARGETS) { + // std::vector targets; + // { + // std::lock_guard lk(m_clipboardMutex); + // for(auto& format : { + // m_connection->resolveAtom(m_formatUTF8_0), + // m_connection->resolveAtom(m_formatUTF8_1), + // m_connection->resolveAtom(m_formatUTF8_2), + // m_connection->resolveAtom(m_formatGTK), + // m_connection->resolveAtom(m_formatString), + // m_connection->resolveAtom(m_formatText), + // m_connection->resolveAtom(m_formatTextPlain) + // }) { + // targets.push_back(format); + // } + // } + // targets.push_back(m_connection->resolveAtom(m_TARGETS)); + // xcb.pxcb_change_property( + // m_connection->getNativeHandle(), + // XCB_PROP_MODE_REPLACE, + // sne->requestor, + // sne->property, + // XCB_ATOM, + // 8*sizeof(xcb_atom_t), + // targets.size(), + // &targets[0]); + // } else { + // std::lock_guard lk(m_clipboardMutex); + // xcb.pxcb_change_property( + // m_connection->getNativeHandle(), + // XCB_PROP_MODE_REPLACE, + // sne->requestor, + // sne->property, + // sne->target, + // 8, + // m_savedClipboard.size(), + // m_savedClipboard.data()); + // } + // } - // Notify the "requestor" that we've already updated the property. - xcb_selection_notify_event_t notify; - notify.response_type = XCB_SELECTION_NOTIFY; - notify.pad0 = 0; - notify.sequence = 0; - notify.time = sne->time; - notify.requestor = sne->requestor; - notify.selection = sne->selection; - notify.target = sne->target; - notify.property = sne->property; + // // Notify the "requestor" that we've already updated the property. + // xcb_selection_notify_event_t notify; + // notify.response_type = XCB_SELECTION_NOTIFY; + // notify.pad0 = 0; + // notify.sequence = 0; + // notify.time = sne->time; + // notify.requestor = sne->requestor; + // notify.selection = sne->selection; + // notify.target = sne->target; + // notify.property = sne->property; - xcb.pxcb_send_event(m_connection->getRawConnection(), false, - sne->requestor, - XCB_EVENT_MASK_NO_EVENT, // SelectionNotify events go without mask - (const char*)¬ify); + // xcb.pxcb_send_event(m_connection->getNativeHandle(), false, + // sne->requestor, + // XCB_EVENT_MASK_NO_EVENT, // SelectionNotify events go without mask + // (const char*)¬ify); - xcb.pxcb_flush(m_connection->getRawConnection()); - break; - } - // Someone else has new content in the clipboard, so is - // notifying us that we should delete our data now. - case XCB_SELECTION_CLEAR: { - auto* sne = reinterpret_cast(event); - if (sne->selection == m_connection->resolveAtom(m_CLIPBOARD)) { - std::lock_guard lock(m_clipboardMutex); - m_savedClipboard = std::string(); - } - break; - } - // we've requested the clipboard data, and this is the reply - case XCB_SELECTION_NOTIFY: { - auto* sne = reinterpret_cast(event); - if(sne->requestor == windowHandle->m_window){ - // xcb.pxcb_get_a - xcb_atom_t fieldType = XCB_ATOM; - if(sne->target != TARGETS) { - fieldType = sne->target; - } - xcb_get_property_cookie_t cookie = xcb.pxcb_get_property(m_connection->getRawConnection(), true, - sne->requestor, - sne->property, - fieldType, 0, 0x1fffffff); // 0x1fffffff = INT32_MAX / 4 - if(xcb_get_property_reply_t* reply = - xcb.pxcb_get_property_reply(m_connection->getRawConnection(), cookie, nullptr)) { - core::SRAIIBasedExiter exitReply([reply]() -> void { - free(reply); - }); + // xcb.pxcb_flush(m_connection->getNativeHandle()); + // break; + // } + // // Someone else has new content in the clipboard, so is + // // notifying us that we should delete our data now. + // case XCB_SELECTION_CLEAR: { + // auto* sne = reinterpret_cast(event); + // if (sne->selection == m_connection->resolveAtom(m_CLIPBOARD)) { + // std::lock_guard lock(m_clipboardMutex); + // m_savedClipboard = std::string(); + // } + // break; + // } + // // we've requested the clipboard data, and this is the reply + // case XCB_SELECTION_NOTIFY: { + // auto* sne = reinterpret_cast(event); + // if(sne->requestor == windowHandle->m_window){ + // // xcb.pxcb_get_a + // xcb_atom_t fieldType = XCB_ATOM; + // if(sne->target != TARGETS) { + // fieldType = sne->target; + // } + // xcb_get_property_cookie_t cookie = xcb.pxcb_get_property(m_connection->getNativeHandle(), true, + // sne->requestor, + // sne->property, + // fieldType, 0, 0x1fffffff); // 0x1fffffff = INT32_MAX / 4 + // if(xcb_get_property_reply_t* reply = + // xcb.pxcb_get_property_reply(m_connection->getNativeHandle(), cookie, nullptr)) { + // core::SRAIIBasedExiter exitReply([reply]() -> void { + // free(reply); + // }); - if(reply->type == m_connection->resolveAtom(m_INCR)) { - assert(false); // TODO - } else { - const auto* src = reinterpret_cast(xcb.pxcb_get_property_value(reply)); - size_t n = xcb.pxcb_get_property_value_length(reply); - { - std::lock_guard lk(m_clipboardMutex); - m_clipboardResponse = std::string(src, n); - } - m_clipboardResponseCV.notify_one(); - } - } - } - break; - } - } - } + // if(reply->type == m_connection->resolveAtom(m_INCR)) { + // assert(false); // TODO + // } else { + // const auto* src = reinterpret_cast(xcb.pxcb_get_property_value(reply)); + // size_t n = xcb.pxcb_get_property_value_length(reply); + // { + // std::lock_guard lk(m_clipboardMutex); + // m_clipboardResponse = std::string(src, n); + // } + // m_clipboardResponseCV.notify_one(); + // } + // } + // } + // break; + // } + // } + // } } \ No newline at end of file diff --git a/src/nbl/ui/CCursorControlXCB.cpp b/src/nbl/ui/CCursorControlXCB.cpp index 3243acb580..9a6c1b28ef 100644 --- a/src/nbl/ui/CCursorControlXCB.cpp +++ b/src/nbl/ui/CCursorControlXCB.cpp @@ -3,7 +3,6 @@ #ifdef _NBL_PLATFORM_LINUX_ -#include "nbl/ui/XCBConnection.h" #include "nbl/ui/IWindowXCB.h" namespace nbl::ui @@ -17,43 +16,46 @@ namespace nbl::ui } void CCursorControlXCB::setPosition(SPosition pos) { - auto& xcb = m_connection->getXcbFunctionTable(); - const auto* primaryScreen = m_connection->primaryScreen(); - xcb.pxcb_warp_pointer(m_connection->getRawConnection(), XCB_NONE, primaryScreen->root, 0, 0, 0, 0, pos.x, pos.y); - xcb.pxcb_flush(m_connection->getRawConnection()); + // auto& xcb = m_connection->getXcbFunctionTable(); + // const auto* primaryScreen = m_connection->primaryScreen(); + // xcb.pxcb_warp_pointer(m_connection->getNativeHandle(), XCB_NONE, primaryScreen->root, 0, 0, 0, 0, pos.x, pos.y); + // xcb.pxcb_flush(m_connection->getNativeHandle()); } void CCursorControlXCB::setRelativePosition(IWindow* window, SRelativePosition position) { - auto* windowXcb = static_cast(window); - auto& xcb = m_connection->getXcbFunctionTable(); - auto* handle = windowXcb->getNativeHandle(); - assert(handle && handle->m_window != XCB_WINDOW_NONE); + // auto* windowXcb = static_cast(window); + // auto& xcb = m_connection->getXcbFunctionTable(); + // auto* handle = windowXcb->getNativeHandle(); + // assert(handle && handle->m_window != XCB_WINDOW_NONE); - xcb.pxcb_warp_pointer(m_connection->getRawConnection(), XCB_NONE, handle->m_window, 0, 0, 0, 0, position.x, position.y); - xcb.pxcb_flush(m_connection->getRawConnection()); + // xcb.pxcb_warp_pointer(m_connection->getNativeHandle(), XCB_NONE, handle->m_window, 0, 0, 0, 0, position.x, position.y); + // xcb.pxcb_flush(m_connection->getNativeHandle()); } CCursorControlXCB::SPosition CCursorControlXCB::getPosition() { - auto& xcb = m_connection->getXcbFunctionTable(); - xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_connection->getRawConnection(), m_connection->primaryScreen()->root); - if(auto reply = xcb.pxcb_query_pointer_reply(m_connection->getRawConnection(), token, nullptr)) { - core::SRAIIBasedExiter exitReply([reply]() -> void { - free(reply); - }); - return {reply->root_x, reply->root_y}; - } + // auto& xcb = m_connection->getXcbFunctionTable(); + // xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_connection->getNativeHandle(), m_connection->primaryScreen()->root); + // if(auto reply = xcb.pxcb_query_pointer_reply(m_connection->getNativeHandle(), token, nullptr)) { + // core::SRAIIBasedExiter exitReply([reply]() -> void { + // free(reply); + // }); + // return {reply->root_x, reply->root_y}; + // } return {0, 0}; } CCursorControlXCB::SRelativePosition CCursorControlXCB::getRelativePosition(IWindow* window) { - auto& xcb = m_connection->getXcbFunctionTable(); - xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_connection->getRawConnection(), m_connection->primaryScreen()->root); - if(auto reply = xcb.pxcb_query_pointer_reply(m_connection->getRawConnection(), token, nullptr)) { - core::SRAIIBasedExiter exitReply([reply]() -> void { - free(reply); - }); - return {static_cast(reply->win_x), static_cast(reply->win_y)}; - } + auto* xcbWidnow = static_cast(window); + auto* windowHandle = xcbWidnow->getNativeHandle(); + + // auto& xcb = m_connection->getXcbFunctionTable(); + // xcb_query_pointer_cookie_t token = xcb.pxcb_query_pointer(m_connection->getNativeHandle(), windowHandle->m_window); + // if(auto reply = xcb.pxcb_query_pointer_reply(m_connection->getNativeHandle(), token, nullptr)) { + // core::SRAIIBasedExiter exitReply([reply]() -> void { + // free(reply); + // }); + // return {static_cast(reply->win_x), static_cast(reply->win_y)}; + // } return {0, 0}; } } diff --git a/src/nbl/ui/CWindowManagerXCB.cpp b/src/nbl/ui/CWindowManagerXCB.cpp index d41b871216..5714c08554 100644 --- a/src/nbl/ui/CWindowManagerXCB.cpp +++ b/src/nbl/ui/CWindowManagerXCB.cpp @@ -13,45 +13,104 @@ core::smart_refctd_ptr IWindowManagerXCB::create() return core::make_smart_refctd_ptr(); } - CWindowManagerXCB::CWindowManagerXCB() { } + core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreationParams&& creationParams) { + // const auto* primaryScreen = m_connection.primaryScreen(); + IWindowXCB::native_handle_t windowHandle = { + 0, + core::make_smart_refctd_ptr(core::smart_refctd_ptr(this)) + }; + const auto* primaryScreen = xcb::primaryScreen(*windowHandle.m_connection); + windowHandle.m_window = m_xcb.pxcb_generate_id(*windowHandle.m_connection); + + uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + uint32_t valueList[] = { + primaryScreen->black_pixel, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE + }; + + xcb_void_cookie_t result = m_xcb.pxcb_create_window( + *windowHandle.m_connection, XCB_COPY_FROM_PARENT, windowHandle.m_window, primaryScreen->root, + static_cast(creationParams.x), + static_cast(creationParams.y), + static_cast(creationParams.width), + static_cast(creationParams.height), 4, + XCB_WINDOW_CLASS_INPUT_OUTPUT, primaryScreen->root_visual, eventMask, + valueList); + if(m_xcb.pxcb_request_check(*windowHandle.m_connection, result)) { + m_xcb.pxcb_destroy_window(*windowHandle.m_connection, windowHandle.m_window); + m_xcb.pxcb_flush(*windowHandle.m_connection); + return nullptr; + } + + const std::array atoms {windowHandle.m_connection->WM_DELETE_WINDOW.fetch(), windowHandle.m_connection->_NET_WM_PING.fetch()}; + m_xcb.pxcb_change_property( + *windowHandle.m_connection, + XCB_PROP_MODE_REPLACE, + windowHandle.m_window, + windowHandle.m_connection->WM_PROTOCOLS.fetch(), XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); + + auto motifHints = xcb::createFlagsToMotifWmHints(creationParams.flags); + xcb::setMotifWmHints(*windowHandle.m_connection, windowHandle.m_window, motifHints); + + if(creationParams.flags & IWindow::E_CREATE_FLAGS::ECF_ALWAYS_ON_TOP) { + xcb::setNetMWState(*windowHandle.m_connection, + primaryScreen->root, + windowHandle.m_window, + windowHandle.m_window, + windowHandle.m_connection->NET_WM_STATE_ABOVE.fetch()); + } + std::string title = std::string(creationParams.windowCaption); - auto window = core::make_smart_refctd_ptr(core::smart_refctd_ptr(this), std::move(creationParams)); + auto window = core::make_smart_refctd_ptr(std::move(windowHandle), core::smart_refctd_ptr(this), std::move(creationParams)); window->setCaption(title); return window; } bool CWindowManagerXCB::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { auto wnd = static_cast(window); - wnd->setWindowSize_impl(width, height); + wnd->setWindowSize(width, height); return true; } bool CWindowManagerXCB::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { auto wnd = static_cast(window); - wnd->setWindowPosition_impl(x, y); + wnd->setWindowPosition(x, y); return true; } bool CWindowManagerXCB::setWindowRotation_impl(IWindow* window, bool landscape) { auto wnd = static_cast(window); - wnd->setWindowRotation_impl(landscape); + auto* handle = wnd->getNativeHandle(); + return true; } bool CWindowManagerXCB::setWindowVisible_impl(IWindow* window, bool visible) { auto wnd = static_cast(window); - wnd->setWindowVisible_impl(visible); + auto* handle = wnd->getNativeHandle(); + // auto conn = handle->m_connection->getXcbFunctionTable(); + + // if(visible) { + // xcb.pxcb_map_window(m_connection->getNativeHandle(), m_handle.m_window); + // xcb.pxcb_flush(m_connection->getNativeHandle()); + // } else { + // xcb.pxcb_unmap_window(m_connection->getNativeHandle(), m_handle.m_window); + // xcb.pxcb_flush(m_connection->getNativeHandle()); + // } + + wnd->setWindowVisible(visible); return true; } bool CWindowManagerXCB::setWindowMaximized_impl(IWindow* window, bool maximized) { auto wnd = static_cast(window); - wnd->setWindowMaximized_impl(maximized); + wnd->setWindowMaximized(maximized); return true; } diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index edf056f5ab..5f57d9f5e0 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -8,7 +8,7 @@ #include "nbl/ui/IWindowXCB.h" #include "nbl/ui/CWindowXCB.h" #include "nbl/ui/CCursorControlXCB.h" -#include "nbl/ui/CClipboardManagerXCB.h" +// #include "nbl/ui/CClipboardManagerXCB.h" #include "nbl/ui/CWindowManagerXCB.h" #include @@ -33,16 +33,15 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ return; } auto& xcb = m_window.m_windowManager->getXcbFunctionTable(); - auto& connection = m_window.m_connection; + // auto& connection = m_window.m_handle; auto& windowHandle = m_window.m_handle; - - auto MW_DELETE_WINDOW = connection->resolveAtom(m_window.m_WM_DELETE_WINDOW); - auto NET_WM_PING = connection->resolveAtom(m_window.m_NET_WM_PING); + // auto MW_DELETE_WINDOW = xcb::resolveAtom(m_handle, m_window.m_WM_DELETE_WINDOW); + // auto NET_WM_PING = xcb::resolveAtom(m_handle, m_window.m_NET_WM_PING); - if(auto event = xcb.pxcb_wait_for_event(connection->getRawConnection())) { + if(auto event = xcb.pxcb_wait_for_event(*windowHandle.m_connection)) { auto* eventCallback = m_window.getEventCallback(); - m_window.m_clipboardManager->process(&m_window, event); + // m_window.m_clipboardManager->process(&m_window, event); switch (event->response_type & ~0x80) { case 0: { @@ -72,20 +71,20 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t* cme = reinterpret_cast(event); - if(cme->data.data32[0] == MW_DELETE_WINDOW) { - xcb.pxcb_unmap_window(windowHandle.m_connection, windowHandle.m_window); - xcb.pxcb_destroy_window(windowHandle.m_connection, windowHandle.m_window); - xcb.pxcb_flush(windowHandle.m_connection); + if(cme->data.data32[0] == windowHandle.m_connection->WM_DELETE_WINDOW.fetch()) { + xcb.pxcb_unmap_window(*windowHandle.m_connection, windowHandle.m_window); + xcb.pxcb_destroy_window(*windowHandle.m_connection, windowHandle.m_window); + xcb.pxcb_flush(*windowHandle.m_connection); windowHandle.m_window = 0; m_quit = true; // we need to quit the dispatch thread eventCallback->onWindowClosed(&m_window); - } else if(cme->data.data32[0] == NET_WM_PING && cme->window != connection->primaryScreen()->root) { + } else if(cme->data.data32[0] == windowHandle.m_connection->_NET_WM_PING.fetch() && cme->window != xcb::primaryScreen(*windowHandle.m_connection)->root) { xcb_client_message_event_t ev = *cme; ev.response_type = XCB_CLIENT_MESSAGE; ev.window = m_window.m_handle.m_window; - ev.type = NET_WM_PING; - xcb.pxcb_send_event(windowHandle.m_connection, 0, m_window.m_handle.m_window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); - xcb.pxcb_flush(windowHandle.m_connection); + ev.type = windowHandle.m_connection->_NET_WM_PING.fetch(); + xcb.pxcb_send_event(*windowHandle.m_connection, 0, m_window.m_handle.m_window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); + xcb.pxcb_flush(*windowHandle.m_connection); } break; } @@ -95,65 +94,65 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } -CWindowXCB::CWindowXCB(core::smart_refctd_ptr&& winManager, SCreationParams&& params): +CWindowXCB::CWindowXCB(native_handle_t&& handle, core::smart_refctd_ptr&& winManager, SCreationParams&& params): IWindowXCB(std::move(params)), + m_handle(std::move(handle)), m_windowManager(std::move(winManager)), - m_connection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), - m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), - m_clipboardManager(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), + // m_connection(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), + // m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), m_dispatcher(*this) { - auto& xcb = m_windowManager->getXcbFunctionTable(); - auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); - - // m_handle.m_connection = m_connection->getRawConnection(); - m_handle.m_window = xcb.pxcb_generate_id(m_connection->getRawConnection()); - m_handle.m_connection = m_connection->getRawConnection(); - - const auto* primaryScreen = m_connection->primaryScreen(); - - uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - uint32_t valueList[] = { - primaryScreen->black_pixel, - XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | - XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE - }; - - xcb_void_cookie_t xcbCheckResult = xcb.pxcb_create_window( - m_connection->getRawConnection(), XCB_COPY_FROM_PARENT, m_handle.m_window, primaryScreen->root, - static_cast(m_x), - static_cast(m_y), - static_cast(m_width), - static_cast(m_height), 4, - XCB_WINDOW_CLASS_INPUT_OUTPUT, primaryScreen->root_visual, eventMask, - valueList); - - setWindowSize_impl(m_width, m_height); + auto& xcb = m_handle.m_connection->getXcbFunctionTable(); + auto& xcbIccm = m_handle.m_connection->getXcbIcccmFunctionTable(); + + // // m_handle.m_connection = m_connection->getRawConnection(); + // // m_handle.m_window = xcb.pxcb_generate_id(m_connection->getNativeHandle()); + // // m_handle.m_connection = m_connection->getNativeHandle(); + + // const auto* primaryScreen = xcb::primaryScreen(m_handle.m_connection); + + // uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + // uint32_t valueList[] = { + // primaryScreen->black_pixel, + // XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + // XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE + // }; + + // xcb_void_cookie_t xcbCheckResult = xcb.pxcb_create_window( + // m_handle.m_connection, XCB_COPY_FROM_PARENT, m_handle.m_window, primaryScreen->root, + // static_cast(m_x), + // static_cast(m_y), + // static_cast(m_width), + // static_cast(m_height), 4, + // XCB_WINDOW_CLASS_INPUT_OUTPUT, primaryScreen->root_visual, eventMask, + // valueList); + + // setWindowSize(m_width, m_height); - auto WM_DELETE_WINDOW = m_connection->resolveAtom(m_WM_DELETE_WINDOW); - auto NET_WM_PING = m_connection->resolveAtom(m_NET_WM_PING); - auto WM_PROTOCOLS = m_connection->resolveAtom(m_WM_PROTOCOLS); + // auto WM_DELETE_WINDOW = xcb::resolveAtom(m_handle.m_connection, m_WM_DELETE_WINDOW); + // auto NET_WM_PING = xcb::resolveAtom(m_handle.m_connection, m_NET_WM_PING); + // auto WM_PROTOCOLS = xcb::resolveAtom(m_handle.m_connection, m_WM_PROTOCOLS); - const std::array atoms {WM_DELETE_WINDOW, NET_WM_PING}; - xcb.pxcb_change_property( - m_connection->getRawConnection(), - XCB_PROP_MODE_REPLACE, - m_handle.m_window, - WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); + // const std::array atoms {WM_DELETE_WINDOW, NET_WM_PING}; + // xcb.pxcb_change_property( + // m_handle.m_connection, + // XCB_PROP_MODE_REPLACE, + // m_handle.m_window, + // WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); - auto motifHints = fetchMotifMWHints(getFlags().value); - m_connection->setMotifWmHints(m_handle.m_window, motifHints); + // auto motifHints = XCBConnection::createFlagsToMotifWmHints(getFlags().value); + // xcb::setMotifWmHints(m_handle.m_window, motifHints); - if(isAlwaysOnTop()) { - XCBConnection::XCBAtomToken NET_WM_STATE_ABOVE; - m_connection->setNetMWState( - primaryScreen->root, - m_handle.m_window, false, m_connection->resolveAtom(NET_WM_STATE_ABOVE)); - } + // if(isAlwaysOnTop()) { + // XCBConnection::AtomToken NET_WM_STATE_ABOVE; + // m_connection->setNetMWState( + // primaryScreen->root, + // m_handle.m_window, false, m_connection->resolveAtom(NET_WM_STATE_ABOVE)); + // } - xcb.pxcb_map_window(m_connection->getRawConnection(), m_handle.m_window); - xcb.pxcb_flush(m_connection->getRawConnection()); + xcb.pxcb_map_window(*m_handle.m_connection, m_handle.m_window); + xcb.pxcb_flush(*m_handle.m_connection); } @@ -173,68 +172,68 @@ IWindowManager* CWindowXCB::getManager() { return m_windowManager.get(); } -bool CWindowXCB::setWindowSize_impl(uint32_t width, uint32_t height) { +bool CWindowXCB::setWindowSize(uint32_t width, uint32_t height) { auto& xcb = m_windowManager->getXcbFunctionTable(); auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); - xcb_size_hints_t hints = {0}; + // xcb_size_hints_t hints = {0}; - xcbIccm.pxcb_icccm_size_hints_set_size(&hints, true, width, height); - xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); - xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); - xcbIccm.pxcb_icccm_set_wm_normal_hints(m_connection->getRawConnection(), m_handle.m_window, &hints); + // xcbIccm.pxcb_icccm_size_hints_set_size(&hints, true, width, height); + // xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); + // xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); + // xcbIccm.pxcb_icccm_set_wm_normal_hints(m_connection->getNativeHandle(), m_handle.m_window, &hints); return true; } -bool CWindowXCB::setWindowPosition_impl(int32_t x, int32_t y) { +bool CWindowXCB::setWindowPosition(int32_t x, int32_t y) { auto& xcb = m_windowManager->getXcbFunctionTable(); - const int32_t values[] = { x, y }; - auto cookie = xcb.pxcb_configure_window_checked(m_connection->getRawConnection(), m_handle.m_window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); - bool check = checkXcbCookie(xcb, m_connection->getRawConnection(), cookie); - xcb.pxcb_flush(m_connection->getRawConnection()); + // const int32_t values[] = { x, y }; + // auto cookie = xcb.pxcb_configure_window_checked(m_connection->getNativeHandle(), m_handle.m_window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + // bool check = checkXcbCookie(xcb, m_connection->getNativeHandle(), cookie); + // xcb.pxcb_flush(m_connection->getNativeHandle()); return true; } void CWindowXCB::setCaption(const std::string_view& caption) { auto& xcb = m_windowManager->getXcbFunctionTable(); - xcb.pxcb_change_property(m_connection->getRawConnection(), XCB_PROP_MODE_REPLACE, m_handle.m_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); - xcb.pxcb_flush(m_connection->getRawConnection()); + // xcb.pxcb_change_property(m_connection->getNativeHandle(), XCB_PROP_MODE_REPLACE, m_handle.m_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); + // xcb.pxcb_flush(m_connection->getNativeHandle()); } -bool CWindowXCB::setWindowRotation_impl(bool landscape) { +bool CWindowXCB::setWindowRotation(bool landscape) { return true; } -bool CWindowXCB::setWindowVisible_impl( bool visible) { +bool CWindowXCB::setWindowVisible( bool visible) { auto& xcb = m_windowManager->getXcbFunctionTable(); - if(visible) { - xcb.pxcb_map_window(m_connection->getRawConnection(), m_handle.m_window); - xcb.pxcb_flush(m_connection->getRawConnection()); - } else { - xcb.pxcb_unmap_window(m_connection->getRawConnection(), m_handle.m_window); - xcb.pxcb_flush(m_connection->getRawConnection()); - } + // if(visible) { + // xcb.pxcb_map_window(m_connection->getNativeHandle(), m_handle.m_window); + // xcb.pxcb_flush(m_connection->getNativeHandle()); + // } else { + // xcb.pxcb_unmap_window(m_connection->getNativeHandle(), m_handle.m_window); + // xcb.pxcb_flush(m_connection->getNativeHandle()); + // } return true; } -bool CWindowXCB::setWindowMaximized_impl(bool maximized) { +bool CWindowXCB::setWindowMaximized(bool maximized) { auto& xcb = m_windowManager->getXcbFunctionTable(); - const auto* primaryScreen = m_connection->primaryScreen(); + // const auto* primaryScreen = m_connection->primaryScreen(); - m_connection->setNetMWState( - primaryScreen->root, - m_handle.m_window, maximized && !isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_FULLSCREEN)); + // m_connection->setNetMWState( + // primaryScreen->root, + // m_handle.m_window, maximized && !isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_FULLSCREEN)); - m_connection->setNetMWState( - primaryScreen->root, - m_handle.m_window, maximized && isBorderless(), - m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_VERT), - m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); + // m_connection->setNetMWState( + // primaryScreen->root, + // m_handle.m_window, maximized && isBorderless(), + // m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_VERT), + // m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); - xcb.pxcb_flush(m_connection->getRawConnection()); + // xcb.pxcb_flush(m_connection->getNativeHandle()); return true; } diff --git a/src/nbl/ui/XCBConnection.cpp b/src/nbl/ui/XCBConnection.cpp deleted file mode 100644 index dece604089..0000000000 --- a/src/nbl/ui/XCBConnection.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "nbl/ui/XCBConnection.h" - -#ifdef _NBL_PLATFORM_LINUX_ - -namespace nbl::ui -{ - XCBConnection::XCBConnection(core::smart_refctd_ptr&& windowManager): - m_windowManager(std::move(windowManager)) { - const auto& xcb = m_windowManager->getXcbFunctionTable(); - m_connection = xcb.pxcb_connect(nullptr, nullptr); - } - - XCBConnection::~XCBConnection() { - const auto& xcb = m_windowManager->getXcbFunctionTable(); - xcb.pxcb_disconnect(m_connection); - } - - void XCBConnection::setNetMWState(xcb_window_t rootWindow, xcb_window_t window, bool set, xcb_atom_t first, xcb_atom_t second) const { - const auto& xcb = m_windowManager->getXcbFunctionTable(); - - xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.type = resolveAtom(m_NET_WM_STATE); - event.window = window; - event.format = 32; - event.sequence = 0; - event.data.data32[0] = set ? 1l : 0l; - event.data.data32[1] = first; - event.data.data32[2] = second; - event.data.data32[3] = 1; - event.data.data32[4] = 0; - xcb.pxcb_send_event(m_connection, 0, rootWindow, - XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, reinterpret_cast(&event)); - - } - - - const xcb_screen_t* XCBConnection::primaryScreen() { - const auto& xcb = m_windowManager->getXcbFunctionTable(); - const xcb_setup_t *setup = xcb.pxcb_get_setup(m_connection); - xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; - return screen; - } - - void XCBConnection::setMotifWmHints(xcb_window_t window, const MotifWmHints& hint) const { - const auto& xcb = m_windowManager->getXcbFunctionTable(); - - auto atomHint = resolveAtom(m_MOTIF_WM_HINTS); - if(hint.flags != MotifFlags::MWM_HINTS_NONE) { - xcb.pxcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, window, - atomHint, - atomHint, 32, sizeof(MotifWmHints) / sizeof(uint32_t), &hint); - } else { - xcb.pxcb_delete_property(m_connection, window, atomHint); - } - } - -} - -#endif // _NBL_PLATFORM_LINUX_ \ No newline at end of file diff --git a/src/nbl/video/CSurfaceVulkan.cpp b/src/nbl/video/CSurfaceVulkan.cpp index 770b900a2d..22bf1b5353 100644 --- a/src/nbl/video/CSurfaceVulkan.cpp +++ b/src/nbl/video/CSurfaceVulkan.cpp @@ -152,11 +152,11 @@ namespace nbl::video return nullptr; auto* handle = window->getNativeHandle(); - assert(handle && handle->m_window != XCB_WINDOW_NONE && handle->m_connection != nullptr); + // assert(handle && handle->m_window != XCB_WINDOW_NONE && handle->m_connection != nullptr); VkXcbSurfaceCreateInfoKHR createInfo { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; createInfo.pNext = nullptr; createInfo.flags = 0; - createInfo.connection = handle->m_connection; + createInfo.connection = *handle->m_connection; createInfo.window = handle->m_window; VkSurfaceKHR vk_surface; if (vkCreateXcbSurfaceKHR(api->getInternalObject(), &createInfo, nullptr, &vk_surface) == VK_SUCCESS) From 57074d8e73e82c60bee5c36c05d347175d6d5827 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 5 Apr 2023 21:13:16 -0700 Subject: [PATCH 7/9] simplify interface Signed-off-by: Michael Pollind --- include/nbl/ui/XCBHandle.h | 349 +++++++++++++++---------------- src/nbl/ui/CWindowManagerXCB.cpp | 6 +- src/nbl/ui/CWindowXCB.cpp | 8 +- 3 files changed, 175 insertions(+), 188 deletions(-) diff --git a/include/nbl/ui/XCBHandle.h b/include/nbl/ui/XCBHandle.h index 7ba65a7f9c..a320e9fa2e 100644 --- a/include/nbl/ui/XCBHandle.h +++ b/include/nbl/ui/XCBHandle.h @@ -16,131 +16,135 @@ namespace nbl::ui::xcb { - class XCBHandle; + class XCBHandle; enum MotifFlags: uint32_t { - MWM_HINTS_NONE = 0, - MWM_HINTS_FUNCTIONS = (1L << 0), - MWM_HINTS_DECORATIONS = (1L << 1), - MWM_HINTS_INPUT_MODE = (1L << 2), - MWM_HINTS_STATUS = (1L << 3), - }; - - enum MotifFunctions: uint32_t { - MWM_FUNC_NONE = 0, - MWM_FUNC_ALL = (1L << 0), - MWM_FUNC_RESIZE = (1L << 1), - MWM_FUNC_MOVE = (1L << 2), - MWM_FUNC_MINIMIZE = (1L << 3), - MWM_FUNC_MAXIMIZE = (1L << 4), - MWM_FUNC_CLOSE = (1L << 5), - }; - - enum MotifDecorations: uint32_t { - MWM_DECOR_NONE = 0, - MWM_DECOR_ALL = (1L << 0), - MWM_DECOR_BORDER = (1L << 1), - MWM_DECOR_RESIZEH = (1L << 2), - MWM_DECOR_TITLE = (1L << 3), - MWM_DECOR_MENU = (1L << 4), - MWM_DECOR_MINIMIZE = (1L << 5), - MWM_DECOR_MAXIMIZE = (1L << 6), - }; + MWM_HINTS_NONE = 0, + MWM_HINTS_FUNCTIONS = (1L << 0), + MWM_HINTS_DECORATIONS = (1L << 1), + MWM_HINTS_INPUT_MODE = (1L << 2), + MWM_HINTS_STATUS = (1L << 3), + }; + + enum MotifFunctions: uint32_t { + MWM_FUNC_NONE = 0, + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), + }; + + enum MotifDecorations: uint32_t { + MWM_DECOR_NONE = 0, + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), + }; // insane magic in xcb for window hinting good luck finding documentation - // https://fossies.org/linux/motif/lib/Xm/MwmUtil.h - struct MotifWmHints { - MotifFlags flags = MotifFlags::MWM_HINTS_NONE; - MotifFunctions functions = MotifFunctions::MWM_FUNC_NONE; - MotifDecorations decorations = MotifDecorations::MWM_DECOR_NONE; - uint32_t input_mode = 0; // unused - uint32_t status = 0; // unused - }; - - inline MotifWmHints createFlagsToMotifWmHints(IWindow::E_CREATE_FLAGS flags) { - core::bitflag motifFlags(MWM_HINTS_NONE); - core::bitflag motifFunctions(MWM_FUNC_NONE); - core::bitflag motifDecorations(MWM_DECOR_NONE); - motifFlags |= MWM_HINTS_DECORATIONS; - - if (flags & IWindow::ECF_BORDERLESS) { - motifDecorations |= MWM_DECOR_ALL; - } else { - motifDecorations |= MWM_DECOR_BORDER; - motifDecorations |= MWM_DECOR_RESIZEH; - motifDecorations |= MWM_DECOR_TITLE; - - // minimize button - if(flags & IWindow::ECF_MINIMIZED) { - motifDecorations |= MWM_DECOR_MINIMIZE; - motifFunctions |= MWM_FUNC_MINIMIZE; - } - - // maximize button - if(flags & IWindow::ECF_MAXIMIZED) { - motifDecorations |= MWM_DECOR_MAXIMIZE; - motifFunctions |= MWM_FUNC_MAXIMIZE; - } - - // close button - motifFunctions |= MWM_FUNC_CLOSE; - } - - if(motifFunctions.value != MWM_FUNC_NONE) { - motifFlags |= MWM_HINTS_FUNCTIONS; - motifFunctions |= MWM_FUNC_RESIZE; - motifFunctions |= MWM_FUNC_MOVE; - } else { - motifFunctions = MWM_FUNC_ALL; - } - - MotifWmHints hints; - hints.flags = motifFlags.value; - hints.functions = motifFunctions.value; - hints.decorations = motifDecorations.value; - hints.input_mode = 0; - hints.status = 0; - return hints; - } - - class XCBHandle final : public core::IReferenceCounted { + // https://fossies.org/linux/motif/lib/Xm/MwmUtil.h + struct MotifWmHints { + MotifFlags flags = MotifFlags::MWM_HINTS_NONE; + MotifFunctions functions = MotifFunctions::MWM_FUNC_NONE; + MotifDecorations decorations = MotifDecorations::MWM_DECOR_NONE; + uint32_t input_mode = 0; // unused + uint32_t status = 0; // unused + }; + + inline MotifWmHints createFlagsToMotifWmHints(IWindow::E_CREATE_FLAGS flags) { + core::bitflag motifFlags(MWM_HINTS_NONE); + core::bitflag motifFunctions(MWM_FUNC_NONE); + core::bitflag motifDecorations(MWM_DECOR_NONE); + motifFlags |= MWM_HINTS_DECORATIONS; + + if (flags & IWindow::ECF_BORDERLESS) { + motifDecorations |= MWM_DECOR_ALL; + } else { + motifDecorations |= MWM_DECOR_BORDER; + motifDecorations |= MWM_DECOR_RESIZEH; + motifDecorations |= MWM_DECOR_TITLE; + + // minimize button + if(flags & IWindow::ECF_MINIMIZED) { + motifDecorations |= MWM_DECOR_MINIMIZE; + motifFunctions |= MWM_FUNC_MINIMIZE; + } + + // maximize button + if(flags & IWindow::ECF_MAXIMIZED) { + motifDecorations |= MWM_DECOR_MAXIMIZE; + motifFunctions |= MWM_FUNC_MAXIMIZE; + } + + // close button + motifFunctions |= MWM_FUNC_CLOSE; + } + + if(motifFunctions.value != MWM_FUNC_NONE) { + motifFlags |= MWM_HINTS_FUNCTIONS; + motifFunctions |= MWM_FUNC_RESIZE; + motifFunctions |= MWM_FUNC_MOVE; + } else { + motifFunctions = MWM_FUNC_ALL; + } + + MotifWmHints hints; + hints.flags = motifFlags.value; + hints.functions = motifFunctions.value; + hints.decorations = motifDecorations.value; + hints.input_mode = 0; + hints.status = 0; + return hints; + } + + class XCBHandle final : public core::IReferenceCounted { public: - template - struct AtomToken { - private: - AtomToken(XCBHandle& handle) : m_handle(handle) {} - XCBHandle& m_handle; - xcb_atom_t m_token = 0; - bool fetched = false; - public: - inline xcb_atom_t fetch(bool only_if_exists = true, - bool forced = false) { - const auto& xcb = m_handle.getXcbFunctionTable(); - if(fetched && !forced) { - return m_token; - } - fetched = true; - size_t size = Name.size() - 1; // -1 to remove the null terminator - xcb_intern_atom_cookie_t cookie = xcb.pxcb_intern_atom(m_handle, only_if_exists, size, Name.value); - if(xcb_intern_atom_reply_t* reply = xcb.pxcb_intern_atom_reply(m_handle, cookie, nullptr)) { - m_token = reply->atom; - free(reply); - return m_token; - } - return m_token; - } - - friend class XCBHandle; - }; - + struct XCBHandleToken { + private: + xcb_atom_t m_token = 0; + public: + inline operator xcb_atom_t() { return m_token;} + friend class XCBHandle; + }; + XCBHandle(core::smart_refctd_ptr&& windowManager): m_windowManager(std::move(windowManager)) { const auto& xcb = m_windowManager->getXcbFunctionTable(); m_connection = xcb.pxcb_connect(nullptr, nullptr); + + struct { + const char* name; + XCBHandleToken* token; + } handles[] = { + {"WM_DELETE_WINDOW", &WM_DELETE_WINDOW}, + {"WM_PROTOCOLS", &WM_PROTOCOLS}, + {"_NET_WM_PING", &_NET_WM_PING}, + {"_NET_WM_STATE_MAXIMIZED_VERT", &_NET_WM_STATE_MAXIMIZED_VERT}, + {"_NET_WM_STATE_MAXIMIZED_HORZ", &_NET_WM_STATE_MAXIMIZED_HORZ}, + {"_NET_WM_STATE_FULLSCREEN", &_NET_WM_STATE_FULLSCREEN}, + {"_NET_WM_STATE", &_NET_WM_STATE}, + {"_MOTIF_WM_HINTS", &_MOTIF_WM_HINTS}, + {"NET_WM_STATE_ABOVE", &NET_WM_STATE_ABOVE}, + }; + std::array cookies; + for(size_t i = 0; i < std::size(handles); ++i) { + cookies[i] = xcb.pxcb_intern_atom(m_connection, false, strlen(handles[i].name), handles[i].name); + } + for (size_t i = 0; i < std::size(handles); ++i) { + xcb_intern_atom_reply_t *reply = xcb.pxcb_intern_atom_reply(m_connection, cookies[i], nullptr); + handles[i].token->m_token = reply->atom; + free(reply); + } } ~XCBHandle() { if(m_connection) { - const auto& xcb = m_windowManager->getXcbFunctionTable(); + const auto& xcb = m_windowManager->getXcbFunctionTable(); xcb.pxcb_disconnect(m_connection); } } @@ -149,79 +153,64 @@ namespace nbl::ui::xcb inline const IWindowManagerXCB::Xcb& getXcbFunctionTable() const { return m_windowManager->getXcbFunctionTable(); } inline const IWindowManagerXCB::XcbIcccm& getXcbIcccmFunctionTable() const { return m_windowManager->getXcbIcccmFunctionTable(); } inline operator xcb_connection_t*() { return m_connection; } - inline xcb_connection_t* getNativeHandle() { return m_connection; } - - - AtomToken WM_DELETE_WINDOW{*this}; - AtomToken WM_PROTOCOLS{*this}; - AtomToken _NET_WM_PING{*this}; - - AtomToken _NET_WM_STATE_MAXIMIZED_VERT{*this}; - AtomToken _NET_WM_STATE_MAXIMIZED_HORZ{*this}; - AtomToken _NET_WM_STATE_FULLSCREEN{*this}; - AtomToken _NET_WM_STATE{*this}; - AtomToken _MOTIF_WM_HINTS{*this}; - AtomToken NET_WM_STATE_ABOVE{*this}; - - AtomToken m_CLIPBOARD{*this}; - AtomToken m_TARGETS{*this}; - AtomToken m_INCR{*this}; - - AtomToken m_formatUTF8_0{*this}; - AtomToken m_formatUTF8_1{*this}; - AtomToken m_formatUTF8_2{*this}; - AtomToken m_formatGTK{*this}; - AtomToken m_formatString{*this}; - AtomToken m_formatText{*this}; - AtomToken m_formatTextPlain{*this}; + inline xcb_connection_t* getNativeHandle() { return m_connection; } + + XCBHandleToken WM_DELETE_WINDOW; + XCBHandleToken WM_PROTOCOLS; + XCBHandleToken _NET_WM_PING; + + XCBHandleToken _NET_WM_STATE_MAXIMIZED_VERT; + XCBHandleToken _NET_WM_STATE_MAXIMIZED_HORZ; + XCBHandleToken _NET_WM_STATE_FULLSCREEN; + XCBHandleToken _NET_WM_STATE; + XCBHandleToken _MOTIF_WM_HINTS; + XCBHandleToken NET_WM_STATE_ABOVE; private: core::smart_refctd_ptr m_windowManager; xcb_connection_t* m_connection = nullptr; }; - inline void setMotifWmHints(XCBHandle& handle, xcb_window_t window, const MotifWmHints& hint) { - auto& xcb = handle.getXcbFunctionTable(); - - auto atomHint = handle._MOTIF_WM_HINTS.fetch(); - if(hint.flags != MotifFlags::MWM_HINTS_NONE) { - xcb.pxcb_change_property(handle.getNativeHandle(), XCB_PROP_MODE_REPLACE, window, - atomHint, - atomHint, 32, sizeof(MotifWmHints) / sizeof(uint32_t), &hint); - } else { - xcb.pxcb_delete_property(handle.getNativeHandle(), window, atomHint); - } - } - - inline void setNetMWState(XCBHandle& handle, xcb_window_t rootWindow, - xcb_window_t window, - bool set, - xcb_atom_t first, - xcb_atom_t second = XCB_NONE) { - auto& xcb = handle.getXcbFunctionTable(); - - xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.type = handle._NET_WM_STATE.fetch(); - event.window = window; - event.format = 32; - event.sequence = 0; - event.data.data32[0] = set ? 1l : 0l; - event.data.data32[1] = first; - event.data.data32[2] = second; - event.data.data32[3] = 1; - event.data.data32[4] = 0; - xcb.pxcb_send_event(handle, 0, rootWindow, - XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, reinterpret_cast(&event)); - } - - inline const xcb_screen_t* primaryScreen(XCBHandle& handle) { - auto& xcb = handle.getXcbFunctionTable(); - const xcb_setup_t *setup = xcb.pxcb_get_setup(handle); - xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; - return screen; - } -} + inline void setMotifWmHints(XCBHandle& handle, xcb_window_t window, const MotifWmHints& hint) { + auto& xcb = handle.getXcbFunctionTable(); + if(hint.flags != MotifFlags::MWM_HINTS_NONE) { + xcb.pxcb_change_property(handle.getNativeHandle(), XCB_PROP_MODE_REPLACE, window, + handle._MOTIF_WM_HINTS, + handle._MOTIF_WM_HINTS, 32, sizeof(MotifWmHints) / sizeof(uint32_t), &hint); + } else { + xcb.pxcb_delete_property(handle.getNativeHandle(), window, handle._MOTIF_WM_HINTS); + } + } + + inline void setNetMWState(XCBHandle& handle, xcb_window_t rootWindow, + xcb_window_t window, + bool set, + xcb_atom_t first, + xcb_atom_t second = XCB_NONE) { + auto& xcb = handle.getXcbFunctionTable(); + + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.type = handle._NET_WM_STATE; + event.window = window; + event.format = 32; + event.sequence = 0; + event.data.data32[0] = set ? 1l : 0l; + event.data.data32[1] = first; + event.data.data32[2] = second; + event.data.data32[3] = 1; + event.data.data32[4] = 0; + xcb.pxcb_send_event(handle, 0, rootWindow, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, reinterpret_cast(&event)); + } + + inline const xcb_screen_t* primaryScreen(XCBHandle& handle) { + auto& xcb = handle.getXcbFunctionTable(); + const xcb_setup_t *setup = xcb.pxcb_get_setup(handle); + xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; + return screen; + } +} #endif #endif // C_XCB_HANDLER_XCB diff --git a/src/nbl/ui/CWindowManagerXCB.cpp b/src/nbl/ui/CWindowManagerXCB.cpp index 5714c08554..df5530df5d 100644 --- a/src/nbl/ui/CWindowManagerXCB.cpp +++ b/src/nbl/ui/CWindowManagerXCB.cpp @@ -48,12 +48,12 @@ core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreati return nullptr; } - const std::array atoms {windowHandle.m_connection->WM_DELETE_WINDOW.fetch(), windowHandle.m_connection->_NET_WM_PING.fetch()}; + const std::array atoms {windowHandle.m_connection->WM_DELETE_WINDOW, windowHandle.m_connection->_NET_WM_PING}; m_xcb.pxcb_change_property( *windowHandle.m_connection, XCB_PROP_MODE_REPLACE, windowHandle.m_window, - windowHandle.m_connection->WM_PROTOCOLS.fetch(), XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); + windowHandle.m_connection->WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); auto motifHints = xcb::createFlagsToMotifWmHints(creationParams.flags); xcb::setMotifWmHints(*windowHandle.m_connection, windowHandle.m_window, motifHints); @@ -63,7 +63,7 @@ core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreati primaryScreen->root, windowHandle.m_window, windowHandle.m_window, - windowHandle.m_connection->NET_WM_STATE_ABOVE.fetch()); + windowHandle.m_connection->NET_WM_STATE_ABOVE); } std::string title = std::string(creationParams.windowCaption); diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index 5f57d9f5e0..41ea3e1aab 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -36,8 +36,6 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ // auto& connection = m_window.m_handle; auto& windowHandle = m_window.m_handle; - // auto MW_DELETE_WINDOW = xcb::resolveAtom(m_handle, m_window.m_WM_DELETE_WINDOW); - // auto NET_WM_PING = xcb::resolveAtom(m_handle, m_window.m_NET_WM_PING); if(auto event = xcb.pxcb_wait_for_event(*windowHandle.m_connection)) { auto* eventCallback = m_window.getEventCallback(); @@ -71,18 +69,18 @@ void CWindowXCB::CDispatchThread::work(lock_t& lock){ } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t* cme = reinterpret_cast(event); - if(cme->data.data32[0] == windowHandle.m_connection->WM_DELETE_WINDOW.fetch()) { + if(cme->data.data32[0] == windowHandle.m_connection->WM_DELETE_WINDOW) { xcb.pxcb_unmap_window(*windowHandle.m_connection, windowHandle.m_window); xcb.pxcb_destroy_window(*windowHandle.m_connection, windowHandle.m_window); xcb.pxcb_flush(*windowHandle.m_connection); windowHandle.m_window = 0; m_quit = true; // we need to quit the dispatch thread eventCallback->onWindowClosed(&m_window); - } else if(cme->data.data32[0] == windowHandle.m_connection->_NET_WM_PING.fetch() && cme->window != xcb::primaryScreen(*windowHandle.m_connection)->root) { + } else if(cme->data.data32[0] == windowHandle.m_connection->_NET_WM_PING && cme->window != xcb::primaryScreen(*windowHandle.m_connection)->root) { xcb_client_message_event_t ev = *cme; ev.response_type = XCB_CLIENT_MESSAGE; ev.window = m_window.m_handle.m_window; - ev.type = windowHandle.m_connection->_NET_WM_PING.fetch(); + ev.type = windowHandle.m_connection->_NET_WM_PING; xcb.pxcb_send_event(*windowHandle.m_connection, 0, m_window.m_handle.m_window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast(&ev)); xcb.pxcb_flush(*windowHandle.m_connection); } From 1ac729571dbf784b913da9a3ba44901405cca789 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 30 May 2023 18:09:28 -0700 Subject: [PATCH 8/9] updated window manager --- include/nbl/ui/CWindowXCB.h | 6 -- include/nbl/ui/IWindowXCB.h | 5 -- include/nbl/ui/XCBHandle.h | 11 +++ src/nbl/ui/CWindowManagerXCB.cpp | 55 +++++++++++---- src/nbl/ui/CWindowXCB.cpp | 115 +------------------------------ 5 files changed, 54 insertions(+), 138 deletions(-) diff --git a/include/nbl/ui/CWindowXCB.h b/include/nbl/ui/CWindowXCB.h index 07c5e6fbc4..9bd3d77872 100644 --- a/include/nbl/ui/CWindowXCB.h +++ b/include/nbl/ui/CWindowXCB.h @@ -31,12 +31,6 @@ class NBL_API2 CWindowXCB final : public IWindowXCB virtual ICursorControl* getCursorControl() override; virtual IWindowManager* getManager() override; - virtual bool setWindowSize(uint32_t width, uint32_t height) override; - virtual bool setWindowPosition(int32_t x, int32_t y) override; - virtual bool setWindowRotation(bool landscape) override; - virtual bool setWindowVisible(bool visible) override; - virtual bool setWindowMaximized(bool maximized) override; - virtual void setCaption(const std::string_view& caption) override; private: diff --git a/include/nbl/ui/IWindowXCB.h b/include/nbl/ui/IWindowXCB.h index 75e9cad071..8cad85701b 100644 --- a/include/nbl/ui/IWindowXCB.h +++ b/include/nbl/ui/IWindowXCB.h @@ -28,11 +28,6 @@ class NBL_API2 IWindowXCB : public IWindow }; virtual const native_handle_t* getNativeHandle() const = 0; - virtual bool setWindowSize(uint32_t width, uint32_t height) = 0; - virtual bool setWindowPosition(int32_t x, int32_t y) = 0; - virtual bool setWindowRotation(bool landscape) = 0; - virtual bool setWindowVisible(bool visible) = 0; - virtual bool setWindowMaximized(bool maximized) = 0; }; } diff --git a/include/nbl/ui/XCBHandle.h b/include/nbl/ui/XCBHandle.h index a320e9fa2e..a07a116d30 100644 --- a/include/nbl/ui/XCBHandle.h +++ b/include/nbl/ui/XCBHandle.h @@ -210,6 +210,17 @@ namespace nbl::ui::xcb xcb_screen_t *screen = xcb.pxcb_setup_roots_iterator(setup).data; return screen; } + + inline bool checkCookie(XCBHandle& handle, xcb_void_cookie_t cookie) { + auto& xcb = handle.getXcbFunctionTable(); + if (xcb_generic_error_t* error = xcb.pxcb_request_check(handle, cookie)) + { + printf("XCB error: %d", error->error_code); + return false; + } + return true; + } + } #endif diff --git a/src/nbl/ui/CWindowManagerXCB.cpp b/src/nbl/ui/CWindowManagerXCB.cpp index df5530df5d..c2ffbb22bb 100644 --- a/src/nbl/ui/CWindowManagerXCB.cpp +++ b/src/nbl/ui/CWindowManagerXCB.cpp @@ -19,7 +19,6 @@ CWindowManagerXCB::CWindowManagerXCB() { core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreationParams&& creationParams) { - // const auto* primaryScreen = m_connection.primaryScreen(); IWindowXCB::native_handle_t windowHandle = { 0, core::make_smart_refctd_ptr(core::smart_refctd_ptr(this)) @@ -74,19 +73,32 @@ core::smart_refctd_ptr CWindowManagerXCB::createWindow(IWindow::SCreati bool CWindowManagerXCB::setWindowSize_impl(IWindow* window, uint32_t width, uint32_t height) { auto wnd = static_cast(window); - wnd->setWindowSize(width, height); + auto* nativeHandle = wnd->getNativeHandle(); + + xcb_size_hints_t hints = {0}; + m_xcbIcccm.pxcb_icccm_size_hints_set_size(&hints, true, width, height); + m_xcbIcccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); + m_xcbIcccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); + m_xcbIcccm.pxcb_icccm_set_wm_normal_hints(*nativeHandle->m_connection, nativeHandle->m_window, &hints); return true; } bool CWindowManagerXCB::setWindowPosition_impl(IWindow* window, int32_t x, int32_t y) { auto wnd = static_cast(window); - wnd->setWindowPosition(x, y); - return true; + auto* nativeHandle = wnd->getNativeHandle(); + + const int32_t values[] = { x, y }; + auto cookie = m_xcb.pxcb_configure_window_checked(*nativeHandle->m_connection, nativeHandle->m_window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + bool check = xcb::checkCookie(*nativeHandle->m_connection, cookie); + m_xcb.pxcb_flush(*nativeHandle->m_connection); + + return check; } bool CWindowManagerXCB::setWindowRotation_impl(IWindow* window, bool landscape) { auto wnd = static_cast(window); - auto* handle = wnd->getNativeHandle(); + auto* nativeHandle = wnd->getNativeHandle(); + return true; } @@ -94,23 +106,36 @@ bool CWindowManagerXCB::setWindowRotation_impl(IWindow* window, bool landscape) bool CWindowManagerXCB::setWindowVisible_impl(IWindow* window, bool visible) { auto wnd = static_cast(window); auto* handle = wnd->getNativeHandle(); - // auto conn = handle->m_connection->getXcbFunctionTable(); - // if(visible) { - // xcb.pxcb_map_window(m_connection->getNativeHandle(), m_handle.m_window); - // xcb.pxcb_flush(m_connection->getNativeHandle()); - // } else { - // xcb.pxcb_unmap_window(m_connection->getNativeHandle(), m_handle.m_window); - // xcb.pxcb_flush(m_connection->getNativeHandle()); - // } + if(visible) { + m_xcb.pxcb_map_window(*handle->m_connection, handle->m_window); + m_xcb.pxcb_flush(*handle->m_connection); + } else { + m_xcb.pxcb_unmap_window(*handle->m_connection, handle->m_window); + m_xcb.pxcb_flush(*handle->m_connection); + } - wnd->setWindowVisible(visible); return true; } bool CWindowManagerXCB::setWindowMaximized_impl(IWindow* window, bool maximized) { auto wnd = static_cast(window); - wnd->setWindowMaximized(maximized); + auto* handle = wnd->getNativeHandle(); + const auto* primaryScreen = xcb::primaryScreen(*handle->m_connection); + + xcb::setNetMWState( + *handle->m_connection, + primaryScreen->root, + handle->m_window, maximized && !wnd->isBorderless(), handle->m_connection->_NET_WM_STATE_FULLSCREEN); + + xcb::setNetMWState( + *handle->m_connection, + primaryScreen->root, + handle->m_window, maximized && wnd->isBorderless(), + handle->m_connection->_NET_WM_STATE_MAXIMIZED_VERT, + handle->m_connection->_NET_WM_STATE_MAXIMIZED_HORZ); + + m_xcb.pxcb_flush(*handle->m_connection); return true; } diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index 41ea3e1aab..859b9769b4 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -8,7 +8,6 @@ #include "nbl/ui/IWindowXCB.h" #include "nbl/ui/CWindowXCB.h" #include "nbl/ui/CCursorControlXCB.h" -// #include "nbl/ui/CClipboardManagerXCB.h" #include "nbl/ui/CWindowManagerXCB.h" #include @@ -96,59 +95,11 @@ CWindowXCB::CWindowXCB(native_handle_t&& handle, core::smart_refctd_ptr(core::smart_refctd_ptr(m_windowManager))), - // m_cursorControl(core::make_smart_refctd_ptr(core::smart_refctd_ptr(m_connection))), m_dispatcher(*this) { auto& xcb = m_handle.m_connection->getXcbFunctionTable(); auto& xcbIccm = m_handle.m_connection->getXcbIcccmFunctionTable(); - // // m_handle.m_connection = m_connection->getRawConnection(); - // // m_handle.m_window = xcb.pxcb_generate_id(m_connection->getNativeHandle()); - // // m_handle.m_connection = m_connection->getNativeHandle(); - - // const auto* primaryScreen = xcb::primaryScreen(m_handle.m_connection); - - // uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - // uint32_t valueList[] = { - // primaryScreen->black_pixel, - // XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | - // XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE - // }; - - // xcb_void_cookie_t xcbCheckResult = xcb.pxcb_create_window( - // m_handle.m_connection, XCB_COPY_FROM_PARENT, m_handle.m_window, primaryScreen->root, - // static_cast(m_x), - // static_cast(m_y), - // static_cast(m_width), - // static_cast(m_height), 4, - // XCB_WINDOW_CLASS_INPUT_OUTPUT, primaryScreen->root_visual, eventMask, - // valueList); - - // setWindowSize(m_width, m_height); - - // auto WM_DELETE_WINDOW = xcb::resolveAtom(m_handle.m_connection, m_WM_DELETE_WINDOW); - // auto NET_WM_PING = xcb::resolveAtom(m_handle.m_connection, m_NET_WM_PING); - // auto WM_PROTOCOLS = xcb::resolveAtom(m_handle.m_connection, m_WM_PROTOCOLS); - - // const std::array atoms {WM_DELETE_WINDOW, NET_WM_PING}; - // xcb.pxcb_change_property( - // m_handle.m_connection, - // XCB_PROP_MODE_REPLACE, - // m_handle.m_window, - // WM_PROTOCOLS, XCB_ATOM_ATOM, 32, atoms.size(), atoms.data()); - - - // auto motifHints = XCBConnection::createFlagsToMotifWmHints(getFlags().value); - // xcb::setMotifWmHints(m_handle.m_window, motifHints); - - // if(isAlwaysOnTop()) { - // XCBConnection::AtomToken NET_WM_STATE_ABOVE; - // m_connection->setNetMWState( - // primaryScreen->root, - // m_handle.m_window, false, m_connection->resolveAtom(NET_WM_STATE_ABOVE)); - // } - xcb.pxcb_map_window(*m_handle.m_connection, m_handle.m_window); xcb.pxcb_flush(*m_handle.m_connection); @@ -170,71 +121,11 @@ IWindowManager* CWindowXCB::getManager() { return m_windowManager.get(); } -bool CWindowXCB::setWindowSize(uint32_t width, uint32_t height) { - auto& xcb = m_windowManager->getXcbFunctionTable(); - auto& xcbIccm = m_windowManager->getXcbIcccmFunctionTable(); - - // xcb_size_hints_t hints = {0}; - - // xcbIccm.pxcb_icccm_size_hints_set_size(&hints, true, width, height); - // xcbIccm.pxcb_icccm_size_hints_set_min_size(&hints, width, height); - // xcbIccm.pxcb_icccm_size_hints_set_max_size(&hints, width, height); - // xcbIccm.pxcb_icccm_set_wm_normal_hints(m_connection->getNativeHandle(), m_handle.m_window, &hints); - return true; -} - -bool CWindowXCB::setWindowPosition(int32_t x, int32_t y) { - auto& xcb = m_windowManager->getXcbFunctionTable(); - - // const int32_t values[] = { x, y }; - // auto cookie = xcb.pxcb_configure_window_checked(m_connection->getNativeHandle(), m_handle.m_window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); - // bool check = checkXcbCookie(xcb, m_connection->getNativeHandle(), cookie); - // xcb.pxcb_flush(m_connection->getNativeHandle()); - return true; -} - void CWindowXCB::setCaption(const std::string_view& caption) { - auto& xcb = m_windowManager->getXcbFunctionTable(); - - // xcb.pxcb_change_property(m_connection->getNativeHandle(), XCB_PROP_MODE_REPLACE, m_handle.m_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); - // xcb.pxcb_flush(m_connection->getNativeHandle()); -} - -bool CWindowXCB::setWindowRotation(bool landscape) { - return true; -} - -bool CWindowXCB::setWindowVisible( bool visible) { - auto& xcb = m_windowManager->getXcbFunctionTable(); - - // if(visible) { - // xcb.pxcb_map_window(m_connection->getNativeHandle(), m_handle.m_window); - // xcb.pxcb_flush(m_connection->getNativeHandle()); - // } else { - // xcb.pxcb_unmap_window(m_connection->getNativeHandle(), m_handle.m_window); - // xcb.pxcb_flush(m_connection->getNativeHandle()); - // } - return true; -} - -bool CWindowXCB::setWindowMaximized(bool maximized) { - auto& xcb = m_windowManager->getXcbFunctionTable(); - // const auto* primaryScreen = m_connection->primaryScreen(); - - // m_connection->setNetMWState( - // primaryScreen->root, - // m_handle.m_window, maximized && !isBorderless(), m_connection->resolveAtom(m_NET_WM_STATE_FULLSCREEN)); - - // m_connection->setNetMWState( - // primaryScreen->root, - // m_handle.m_window, maximized && isBorderless(), - // m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_VERT), - // m_connection->resolveAtom(m_NET_WM_STATE_MAXIMIZED_HORZ)); - - // xcb.pxcb_flush(m_connection->getNativeHandle()); - return true; + auto& xcb = m_handle.m_connection->getXcbFunctionTable(); + xcb.pxcb_change_property(*m_handle.m_connection, XCB_PROP_MODE_REPLACE, m_handle.m_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast(caption.size()), reinterpret_cast(caption.data())); + xcb.pxcb_flush(*m_handle.m_connection); } - } #endif \ No newline at end of file From 50353589f684e116b34cf070481a941cb9a79dd5 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 30 May 2023 18:44:47 -0700 Subject: [PATCH 9/9] cleanup Signed-off-by: Michael Pollind --- include/nbl/ui/CWindowXCB.h | 4 +--- src/nbl/CMakeLists.txt | 11 +++-------- src/nbl/ui/CWindowXCB.cpp | 4 ++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/include/nbl/ui/CWindowXCB.h b/include/nbl/ui/CWindowXCB.h index 9bd3d77872..47b6389e34 100644 --- a/include/nbl/ui/CWindowXCB.h +++ b/include/nbl/ui/CWindowXCB.h @@ -29,7 +29,7 @@ class NBL_API2 CWindowXCB final : public IWindowXCB virtual IClipboardManager* getClipboardManager() override; virtual ICursorControl* getCursorControl() override; - virtual IWindowManager* getManager() override; + virtual IWindowManager* getManager() const override; virtual void setCaption(const std::string_view& caption) override; @@ -64,8 +64,6 @@ class NBL_API2 CWindowXCB final : public IWindowXCB CWindowXCB& m_window; friend class CWindowXCB; } m_dispatcher; - - }; } diff --git a/src/nbl/CMakeLists.txt b/src/nbl/CMakeLists.txt index 1d1a6faa3c..00576d84c9 100755 --- a/src/nbl/CMakeLists.txt +++ b/src/nbl/CMakeLists.txt @@ -170,6 +170,7 @@ set(NBL_SYSTEM_SOURCES ${NBL_ROOT_PATH}/src/nbl/system/CAPKResourcesArchive.cpp ${NBL_ROOT_PATH}/src/nbl/system/ISystem.cpp ${NBL_ROOT_PATH}/src/nbl/system/IFileArchive.cpp + ${NBL_ROOT_PATH}/src/nbl/system/CColoredStdoutLoggerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CStdoutLoggerAndroid.cpp ${NBL_ROOT_PATH}/src/nbl/system/CFileViewVirtualAllocatorWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CFileViewVirtualAllocatorPOSIX.cpp @@ -177,21 +178,15 @@ set(NBL_SYSTEM_SOURCES ${NBL_ROOT_PATH}/src/nbl/system/CFileWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CFilePOSIX.cpp ${NBL_ROOT_PATH}/src/nbl/system/CSystemWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/system/ISystemPOSIX.cpp ${NBL_ROOT_PATH}/src/nbl/system/CSystemAndroid.cpp ${NBL_ROOT_PATH}/src/nbl/system/ISystemPOSIX.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CSystemWin32.cpp ${NBL_ROOT_PATH}/src/nbl/system/CSystemLinux.cpp ) set(NBL_UI_SOURCES ${NBL_ROOT_PATH}/src/nbl/ui/CWindowWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXCB.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CWindowXcb.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/XCBConnection.cpp + ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerXCB.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerWin32.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CClipboardManagerXCB.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CCursorControlXCB.cpp ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerAndroid.cpp @@ -564,7 +559,7 @@ endif() # Linux Display Systems if (UNIX AND NOT ANDROID AND NOT APPLE) - target_include_directories(Nabla PUBLIC + target_include_directories(Nabla PUBLIC ${X11_xcb_INCLUDE_PATH} ${X11_xcb_icccm_INCLUDE_PATH} ) diff --git a/src/nbl/ui/CWindowXCB.cpp b/src/nbl/ui/CWindowXCB.cpp index 859b9769b4..cd187d28c8 100644 --- a/src/nbl/ui/CWindowXCB.cpp +++ b/src/nbl/ui/CWindowXCB.cpp @@ -117,7 +117,7 @@ ICursorControl* CWindowXCB::getCursorControl() { return m_cursorControl.get(); } -IWindowManager* CWindowXCB::getManager() { +IWindowManager* CWindowXCB::getManager() const { return m_windowManager.get(); } @@ -128,4 +128,4 @@ void CWindowXCB::setCaption(const std::string_view& caption) { } } -#endif \ No newline at end of file +#endif