diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2024-07-21 13:09:54 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-21 13:09:54 +0200 |
| commit | 016da234d0e852de3ef20eb2e89ac58d2a85f6e7 (patch) | |
| tree | 496085987176551b0794fffc069877d44943e2f1 /src/managers | |
| parent | f642fb97df5c69267a03452533de383ff8023570 (diff) | |
Core: Move to aquamarine (#6608)
Moves Hyprland from wlroots to aquamarine for the backend.
---------
Signed-off-by: Vaxry <vaxry@vaxry.net>
Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
Co-authored-by: Jan Beich <jbeich@FreeBSD.org>
Co-authored-by: vaxerski <vaxerski@users.noreply.github.com>
Co-authored-by: UjinT34 <41110182+UjinT34@users.noreply.github.com>
Co-authored-by: Tom Englund <tomenglund26@gmail.com>
Co-authored-by: Ikalco <73481042+ikalco@users.noreply.github.com>
Co-authored-by: diniamo <diniamo53@gmail.com>
Diffstat (limited to 'src/managers')
| -rw-r--r-- | src/managers/AnimationManager.cpp | 2 | ||||
| -rw-r--r-- | src/managers/CursorManager.cpp | 303 | ||||
| -rw-r--r-- | src/managers/CursorManager.hpp | 70 | ||||
| -rw-r--r-- | src/managers/KeybindManager.cpp | 61 | ||||
| -rw-r--r-- | src/managers/KeybindManager.hpp | 1 | ||||
| -rw-r--r-- | src/managers/PointerManager.cpp | 283 | ||||
| -rw-r--r-- | src/managers/PointerManager.hpp | 54 | ||||
| -rw-r--r-- | src/managers/ProtocolManager.cpp | 20 | ||||
| -rw-r--r-- | src/managers/SeatManager.cpp | 10 | ||||
| -rw-r--r-- | src/managers/eventLoop/EventLoopManager.cpp | 15 | ||||
| -rw-r--r-- | src/managers/eventLoop/EventLoopManager.hpp | 16 | ||||
| -rw-r--r-- | src/managers/input/InputManager.cpp | 232 | ||||
| -rw-r--r-- | src/managers/input/InputManager.hpp | 23 | ||||
| -rw-r--r-- | src/managers/input/Tablets.cpp | 53 |
14 files changed, 570 insertions, 573 deletions
diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 677b2109..dcc7a45f 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -259,7 +259,7 @@ void CAnimationManager::tick() { // manually schedule a frame if (PMONITOR) - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } // do it here, because if this alters the animation vars deque we would be in trouble above. diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index daa4f4be..3a13d10b 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -3,10 +3,11 @@ #include "../config/ConfigValue.hpp" #include "PointerManager.hpp" #include "../xwayland/XWayland.hpp" +#include <cstring> +#include "../helpers/CursorShapes.hpp" extern "C" { -#include <wlr/interfaces/wlr_buffer.h> -#include <wlr/types/wlr_xcursor_manager.h> +#include <X11/Xcursor/Xcursor.h> } static int cursorAnimTimer(void* data) { @@ -45,8 +46,7 @@ CCursorManager::CCursorManager() { if (m_iSize == 0) m_iSize = 24; - m_pWLRXCursorMgr = wlr_xcursor_manager_create(getenv("XCURSOR_THEME"), m_iSize); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); + xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "", m_iSize * std::ceil(m_fCursorScale)); m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr); @@ -56,9 +56,6 @@ CCursorManager::CCursorManager() { } CCursorManager::~CCursorManager() { - if (m_pWLRXCursorMgr) - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); - if (m_pAnimationTimer) wl_event_source_remove(m_pAnimationTimer); } @@ -67,54 +64,61 @@ void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; }); } -static void cursorBufferDestroy(struct wlr_buffer* wlr_buffer) { - CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); - g_pCursorManager->dropBufferRef(buffer->parent); +CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + surface = surf; + size = size_; + stride = cairo_image_surface_get_stride(surf); } -static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t flags, void** data, uint32_t* format, size_t* stride) { - CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); +CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + pixelData = pixelData_; + size = size_; + stride = 4 * size_.x; +} - if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) - return false; +CCursorManager::CCursorBuffer::~CCursorBuffer() { + ; +} - *data = buffer->pixelData ? buffer->pixelData : cairo_image_surface_get_data(buffer->surface); - *stride = buffer->stride; - *format = DRM_FORMAT_ARGB8888; - return true; +Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } -static void cursorBufferEndDataPtr(struct wlr_buffer* wlr_buffer) { +Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { ; } -// -static const wlr_buffer_impl bufferImpl = { - .destroy = cursorBufferDestroy, - .begin_data_ptr_access = cursorBufferBeginDataPtr, - .end_data_ptr_access = cursorBufferEndDataPtr, -}; +bool CCursorManager::CCursorBuffer::isSynchronous() { + return true; +} -CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { - wlrBuffer.surface = surf; - wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); - wlrBuffer.parent = this; - wlrBuffer.stride = cairo_image_surface_get_stride(surf); +bool CCursorManager::CCursorBuffer::good() { + return true; } -CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { - wlrBuffer.pixelData = pixelData; - wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); - wlrBuffer.parent = this; - wlrBuffer.stride = 4 * size_.x; +Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() { + Aquamarine::SSHMAttrs attrs; + attrs.success = true; + attrs.format = DRM_FORMAT_ARGB8888; + attrs.size = size; + attrs.stride = stride; + return attrs; } -CCursorManager::CCursorBuffer::~CCursorBuffer() { - ; // will be freed in .destroy +std::tuple<uint8_t*, uint32_t, size_t> CCursorManager::CCursorBuffer::beginDataPtr(uint32_t flags) { + return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride}; } -wlr_buffer* CCursorManager::getCursorBuffer() { - return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr; +void CCursorManager::CCursorBuffer::endDataPtr() { + ; +} + +SP<Aquamarine::IBuffer> CCursorManager::getCursorBuffer() { + return !m_vCursorBuffers.empty() ? m_vCursorBuffers.back() : nullptr; } void CCursorManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot) { @@ -127,34 +131,24 @@ void CCursorManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotsp } void CCursorManager::setXCursor(const std::string& name) { - if (!m_pWLRXCursorMgr) { - g_pPointerManager->resetCursorImage(); - return; - } - float scale = std::ceil(m_fCursorScale); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, scale); - auto xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, name.c_str(), scale); - if (!xcursor) { - Debug::log(ERR, "XCursor has no shape {}, retrying with left-ptr", name); - xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left-ptr", scale); - } - - if (!xcursor || !xcursor->images[0]) { - Debug::log(ERR, "XCursor is broken. F this garbage."); + if (!xcursor.themeLoaded) { + Debug::log(ERR, "XCursor failed to find theme in setXCursor"); g_pPointerManager->resetCursorImage(); return; } - auto image = xcursor->images[0]; + auto& icon = xcursor.defaultCursor; + // try to get an icon we know if we have one + if (xcursor.cursors.contains(name)) + icon = xcursor.cursors.at(name); - m_vCursorBuffers.emplace_back( - std::make_unique<CCursorBuffer>(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); + m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>((uint8_t*)icon->pixels.data(), icon->size, icon->hotspot)); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon->hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) - wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; } @@ -196,14 +190,14 @@ void CCursorManager::setCursorFromName(const std::string& name) { } } - m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface, - Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, - Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); + m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface, + Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, + Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale, m_fCursorScale); if (m_vCursorBuffers.size() > 1) - wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; @@ -225,7 +219,7 @@ void CCursorManager::tickAnimatedCursor() { if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) m_iCurrentAnimationFrame = 0; - m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>( + m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>( m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface, Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size}, Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY})); @@ -256,10 +250,9 @@ void CCursorManager::setXWaylandCursor() { if (CURSOR.surface) { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); - } else if (const auto XCURSOR = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left_ptr", 1); XCURSOR) { - g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {(int)XCURSOR->images[0]->width, (int)XCURSOR->images[0]->height}, - {(double)XCURSOR->images[0]->hotspot_x, (double)XCURSOR->images[0]->hotspot_y}); - } else + } else if (xcursor.themeLoaded) + g_pXWayland->setCursor((uint8_t*)xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot); + else Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); } @@ -284,7 +277,7 @@ void CCursorManager::updateTheme() { for (auto& m : g_pCompositor->m_vMonitors) { m->forceFullFrames = 5; - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } } @@ -303,37 +296,163 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", name); - if (m_pWLRXCursorMgr) - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); + xcursor.loadTheme(name, size); + + m_szTheme = name; + m_iSize = size; + updateTheme(); + return true; +} + +// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c +// however modified to fit wayland cursor shape names better. +// _ -> - +// clang-format off +static std::array<const char*, 77> XCURSOR_STANDARD_NAMES = { + "X_cursor", + "default", // arrow + "ns-resize", // based-arrow-down + "ns-resize", // based-arrow-up + "boat", + "bogosity", + "sw-resize", // bottom-left-corner + "se-resize", // bottom-right-corner + "s-resize", // bottom-side + "bottom-tee", + "box-spiral", + "center-ptr", + "circle", + "clock", + "coffee-mug", + "cross", + "cross-reverse", + "crosshair", + "diamond-cross", + "dot", + "dotbox", + "double-arrow", + "draft-large", + "draft-small", + "draped-box", + "exchange", + "move", // fleur + "gobbler", + "gumby", + "pointer", // hand1 + "grabbing", // hand2 + "heart", + "icon", + "iron-cross", + "default", // left-ptr + "w-resize", // left-side + "left-tee", + "leftbutton", + "ll-angle", + "lr-angle", + "man", + "middlebutton", + "mouse", + "pencil", + "pirate", + "plus", + "help", // question-arrow + "right-ptr", + "e-resize", // right-side + "right-tee", + "rightbutton", + "rtl-logo", + "sailboat", + "ns-resize", // sb-down-arrow + "ew-resize", // sb-h-double-arrow + "ew-resize", // sb-left-arrow + "ew-resize", // sb-right-arrow + "n-resize", // sb-up-arrow + "s-resize", // sb-v-double-arrow + "shuttle", + "sizing", + "spider", + "spraycan", + "star", + "target", + "cell", // tcross + "nw-resize", // top-left-arrow + "nw-resize", // top-left-corner + "ne-resize", // top-right-corner + "n-resize", // top-side + "top-tee", + "trek", + "ul-angle", + "umbrella", + "ur-angle", + "wait", // watch + "text", // xterm +}; +// clang-format on - m_pWLRXCursorMgr = wlr_xcursor_manager_create(name.empty() ? "" : name.c_str(), size); - bool xSuccess = wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0) == 1; +void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) { + if (lastLoadSize == size && themeName == name) + return; - // this basically checks if xcursor changed used theme to default but better - bool diffTheme = false; - wlr_xcursor_manager_theme* theme; - wl_list_for_each(theme, &m_pWLRXCursorMgr->scaled_themes, link) { - if (std::string{theme->theme->name} != name) { - diffTheme = true; - break; + lastLoadSize = size; + themeLoaded = false; + themeName = name.empty() ? "default" : name; + + auto img = XcursorShapeLoadImage(2, themeName.c_str(), size); + + if (!img) { + Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", themeName); + size = 24; + img = XcursorShapeLoadImage(2, themeName.c_str(), size); + if (!img) { + Debug::log(ERR, "XCursor failed finding theme \"{}\".", themeName); + return; } } - if (xSuccess && !diffTheme) { - m_szTheme = name; - m_iSize = size; - updateTheme(); - return true; - } + defaultCursor = makeShared<SXCursor>(); + defaultCursor->size = {(int)img->width, (int)img->height}; + defaultCursor->hotspot = {(int)img->xhot, (int)img->yhot}; - Debug::log(ERR, "X also failed loading theme \"{}\", falling back to previous theme.", name); + defaultCursor->pixels.resize(img->width * img->height); + std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height * sizeof(uint32_t)); - m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.c_str(), hcLogger); + themeLoaded = true; - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); - m_pWLRXCursorMgr = wlr_xcursor_manager_create(m_szTheme.c_str(), m_iSize); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); + XcursorImageDestroy(img); - updateTheme(); - return false; + // gather as many shapes as we can find. + cursors.clear(); + + for (auto& shape : CURSOR_SHAPE_NAMES) { + int id = -1; + for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { + if (XCURSOR_STANDARD_NAMES.at(i) == std::string{shape}) { + id = i; + break; + } + } + + if (id < 0) { + Debug::log(LOG, "XCursor has no shape {}, skipping", shape); + continue; + } + + auto xImage = XcursorShapeLoadImage(id << 1 /* wtf xcursor? */, themeName.c_str(), size); + + if (!xImage) { + Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); + continue; + } + + auto xcursor = makeShared<SXCursor>(); + xcursor->size = {(int)xImage->width, (int)xImage->height}; + xcursor->hotspot = {(int)xImage->xhot, (int)xImage->yhot}; + + xcursor->pixels.resize(xImage->width * xImage->height); + std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); + + cursors.emplace(std::string{shape}, xcursor); + + XcursorImageDestroy(xImage); + } } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 3ee98ca6..4324dfb4 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -6,47 +6,51 @@ #include "../includes.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" +#include "../macros.hpp" +#include <aquamarine/buffer/Buffer.hpp> -struct wlr_buffer; -struct wlr_xcursor_manager; class CWLSurface; +AQUAMARINE_FORWARD(IBuffer); + class CCursorManager { public: CCursorManager(); ~CCursorManager(); - wlr_buffer* getCursorBuffer(); + SP<Aquamarine::IBuffer> getCursorBuffer(); - void setCursorFromName(const std::string& name); - void setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot); - void setXCursor(const std::string& name); + void setCursorFromName(const std::string& name); + void setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot); + void setXCursor(const std::string& name); - bool changeTheme(const std::string& name, const int size); - void updateTheme(); - SCursorImageData dataFor(const std::string& name); // for xwayland - void setXWaylandCursor(); + bool changeTheme(const std::string& name, const int size); + void updateTheme(); + SCursorImageData dataFor(const std::string& name); // for xwayland + void setXWaylandCursor(); - void tickAnimatedCursor(); + void tickAnimatedCursor(); - class CCursorBuffer { + class CCursorBuffer : public Aquamarine::IBuffer { public: CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot); CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot); ~CCursorBuffer(); - struct SCursorWlrBuffer { - wlr_buffer base; - cairo_surface_t* surface = nullptr; - bool dropped = false; - CCursorBuffer* parent = nullptr; - uint8_t* pixelData = nullptr; - size_t stride = 0; - } wlrBuffer; + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual void update(const Hyprutils::Math::CRegion& damage); + virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good(); + virtual Aquamarine::SSHMAttrs shm(); + virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags); + virtual void endDataPtr(); private: - Vector2D size; - Vector2D hotspot; + Vector2D hotspot; + cairo_surface_t* surface = nullptr; + uint8_t* pixelData = nullptr; + size_t stride = 0; friend class CCursorManager; }; @@ -56,7 +60,7 @@ class CCursorManager { bool m_bOurBufferConnected = false; private: - std::vector<std::unique_ptr<CCursorBuffer>> m_vCursorBuffers; + std::vector<SP<CCursorBuffer>> m_vCursorBuffers; std::unique_ptr<Hyprcursor::CHyprcursorManager> m_pHyprcursor; @@ -70,8 +74,24 @@ class CCursorManager { int m_iCurrentAnimationFrame = 0; Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; - // xcursor fallback - wlr_xcursor_manager* m_pWLRXCursorMgr = nullptr; + // gangsta bootleg XCursor impl. Whenever Hyprland has to use + // an xcursor, just use the pointer. + struct SXCursor { + Vector2D size; + Vector2D hotspot; + std::vector<uint32_t> pixels; // XPixel is a u32 + }; + + struct SXCursorManager { + void loadTheme(const std::string& name, int size); + + int lastLoadSize = 0; + + bool themeLoaded = false; + std::string themeName = ""; + SP<SXCursor> defaultCursor; + std::unordered_map<std::string, SP<SXCursor>> cursors; + } xcursor; }; inline std::unique_ptr<CCursorManager> g_pCursorManager;
\ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index eb8a3232..e9dfd1ae 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -4,10 +4,12 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "../devices/IKeyboard.hpp" #include "KeybindManager.hpp" #include "PointerManager.hpp" #include "Compositor.hpp" #include "TokenManager.hpp" +#include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" @@ -15,6 +17,7 @@ #include <iterator> #include <string> #include <string_view> +#include <cstring> #include <hyprutils/string/String.hpp> using namespace Hyprutils::String; @@ -157,37 +160,37 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { uint32_t modMask = 0; std::transform(mods.begin(), mods.end(), mods.begin(), ::toupper); if (mods.contains("SHIFT")) - modMask |= WLR_MODIFIER_SHIFT; + modMask |= HL_MODIFIER_SHIFT; if (mods.contains("CAPS")) - modMask |= WLR_MODIFIER_CAPS; + modMask |= HL_MODIFIER_CAPS; if (mods.contains("CTRL") || mods.contains("CONTROL")) - modMask |= WLR_MODIFIER_CTRL; + modMask |= HL_MODIFIER_CTRL; if (mods.contains("ALT") || mods.contains("MOD1")) - modMask |= WLR_MODIFIER_ALT; + modMask |= HL_MODIFIER_ALT; if (mods.contains("MOD2")) - modMask |= WLR_MODIFIER_MOD2; + modMask |= HL_MODIFIER_MOD2; if (mods.contains("MOD3")) - modMask |= WLR_MODIFIER_MOD3; - if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4")) - modMask |= WLR_MODIFIER_LOGO; + modMask |= HL_MODIFIER_MOD3; + if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4") || mods.contains("META")) + modMask |= HL_MODIFIER_META; if (mods.contains("MOD5")) - modMask |= WLR_MODIFIER_MOD5; + modMask |= HL_MODIFIER_MOD5; return modMask; } uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) { switch (keycode - 8) { - case KEY_LEFTMETA: return WLR_MODIFIER_LOGO; - case KEY_RIGHTMETA: return WLR_MODIFIER_LOGO; - case KEY_LEFTSHIFT: return WLR_MODIFIER_SHIFT; - case KEY_RIGHTSHIFT: return WLR_MODIFIER_SHIFT; - case KEY_LEFTCTRL: return WLR_MODIFIER_CTRL; - case KEY_RIGHTCTRL: return WLR_MODIFIER_CTRL; - case KEY_LEFTALT: return WLR_MODIFIER_ALT; - case KEY_RIGHTALT: return WLR_MODIFIER_ALT; - case KEY_CAPSLOCK: return WLR_MODIFIER_CAPS; - case KEY_NUMLOCK: return WLR_MODIFIER_MOD2; + case KEY_LEFTMETA: return HL_MODIFIER_META; + case KEY_RIGHTMETA: return HL_MODIFIER_META; + case KEY_LEFTSHIFT: return HL_MODIFIER_SHIFT; + case KEY_RIGHTSHIFT: return HL_MODIFIER_SHIFT; + case KEY_LEFTCTRL: return HL_MODIFIER_CTRL; + case KEY_RIGHTCTRL: return HL_MODIFIER_CTRL; + case KEY_LEFTALT: return HL_MODIFIER_ALT; + case KEY_RIGHTALT: return HL_MODIFIER_ALT; + case KEY_CAPSLOCK: return HL_MODIFIER_CAPS; + case KEY_NUMLOCK: return HL_MODIFIER_MOD2; default: return 0; } } @@ -366,8 +369,8 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE); - const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbStaticState : m_pXKBTranslationState, KEYCODE); + const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) return true; @@ -554,7 +557,7 @@ int repeatKeyHandler(void* data) { Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); DISPATCHER->second((*ppActiveKeybind)->arg); - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->wlr()->repeat_info.rate); + wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate); return 0; } @@ -786,7 +789,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // beyond this point, return true to not handle anything else. // we'll avoid printing shit to active windows. - if (g_pCompositor->m_sWLRSession) { + if (g_pCompositor->m_pAqBackend->hasSession()) { const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; // vtnr is bugged for some reason. @@ -810,8 +813,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY); - wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); - return true; + g_pCompositor->m_pAqBackend->session->switchVT(TTY); } return true; @@ -893,6 +895,7 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { for (auto& e : HLENV) { setenv(e.first.c_str(), e.second.c_str(), 1); } + setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1); close(socket[0]); close(socket[1]); execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); @@ -1659,7 +1662,7 @@ void CKeybindManager::renameWorkspace(std::string args) { } void CKeybindManager::exitHyprland(std::string argz) { - g_pCompositor->m_bExitTriggered = true; + g_pEventLoopManager->doLater([]() { g_pCompositor->cleanup(); }); } void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { @@ -2121,8 +2124,8 @@ void CKeybindManager::sendshortcut(std::string args) { const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY); if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) { - xkb_keymap* km = KB->wlr()->keymap; - xkb_state* ks = KB->xkbTranslationState; + xkb_keymap* km = KB->xkbKeymap; + xkb_state* ks = KB->xkbState; xkb_keycode_t keycode_min, keycode_max; keycode_min = xkb_keymap_min_keycode(km); @@ -2259,7 +2262,7 @@ void CKeybindManager::dpms(std::string arg) { if (!port.empty() && m->szName != port) continue; - wlr_output_state_set_enabled(m->state.wlr(), enable); + m->output->state->setEnabled(enable); m->dpmsStatus = enable; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 2a256760..284280cd 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -6,6 +6,7 @@ #include "../Compositor.hpp" #include <unordered_map> #include <functional> +#include <xkbcommon/xkbcommon.h> #include "../devices/IPointer.hpp" class CInputManager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 7090645f..cf10db71 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -6,133 +6,8 @@ #include "../protocols/core/Compositor.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" -#include <wlr/interfaces/wlr_output.h> -#include <wlr/render/interface.h> -#include <wlr/render/wlr_renderer.h> - -// TODO: make nicer -// this will come with the eventual rewrite of wlr_drm, etc... -static bool wlr_drm_format_intersect(wlr_drm_format* dst, const wlr_drm_format* a, const wlr_drm_format* b) { - ASSERT(a->format == b->format); - - size_t capacity = a->len < b->len ? a->len : b->len; - uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * capacity); - if (!modifiers) - return false; - - struct wlr_drm_format fmt = { - .format = a->format, - .len = 0, - .capacity = capacity, - .modifiers = modifiers, - }; - - for (size_t i = 0; i < a->len; i++) { - for (size_t j = 0; j < b->len; j++) { - if (a->modifiers[i] == b->modifiers[j]) { - ASSERT(fmt.len < fmt.capacity); - fmt.modifiers[fmt.len++] = a->modifiers[i]; - break; - } - } - } - - wlr_drm_format_finish(dst); - *dst = fmt; - return true; -} - -static bool wlr_drm_format_copy(wlr_drm_format* dst, const wlr_drm_format* src) { - ASSERT(src->len <= src->capacity); - - uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * src->len); - if (!modifiers) - return false; - - memcpy(modifiers, src->modifiers, sizeof(*modifiers) * src->len); - - wlr_drm_format_finish(dst); - dst->capacity = src->len; - dst->len = src->len; - dst->format = src->format; - dst->modifiers = modifiers; - return true; -} - -static const wlr_drm_format_set* wlr_renderer_get_render_formats(wlr_renderer* r) { - if (!r->impl->get_render_formats) - return nullptr; - - return r->impl->get_render_formats(r); -} - -static bool output_pick_format(wlr_output* output, const wlr_drm_format_set* display_formats, wlr_drm_format* format, uint32_t fmt) { - - const wlr_drm_format_set* render_formats = wlr_renderer_get_render_formats(g_pCompositor->m_sWLRRenderer); - if (render_formats == NULL) { - wlr_log(WLR_ERROR, "Failed to get render formats"); - return false; - } - - const wlr_drm_format* render_format = wlr_drm_format_set_get(render_formats, fmt); - if (render_format == NULL) { - wlr_log(WLR_DEBUG, "Renderer doesn't support format 0x%" PRIX32, fmt); - return false; - } - - if (display_formats != NULL) { - const wlr_drm_format* display_format = wlr_drm_format_set_get(display_formats, fmt); - if (display_format == NULL) { - wlr_log(WLR_DEBUG, "Output doesn't support format 0x%" PRIX32, fmt); - return false; - } - if (!wlr_drm_format_intersect(format, display_format, render_format)) { - wlr_log(WLR_DEBUG, - "Failed to intersect display and render " - "modifiers for format 0x%" PRIX32 " on output %s", - fmt, output->name); - return false; - } - } else { - // The output can display any format - if (!wlr_drm_format_copy(format, render_format)) - return false; - } - - if (format->len == 0) { - wlr_drm_format_finish(format); - wlr_log(WLR_DEBUG, "Failed to pick output format"); - return false; - } - - return true; -} - -static bool output_pick_cursor_format(struct wlr_output* output, struct wlr_drm_format* format) { - struct wlr_allocator* allocator = output->allocator; - ASSERT(allocator != NULL); - - const struct wlr_drm_format_set* display_formats = NULL; - if (output->impl->get_cursor_formats) { - display_formats = output->impl->get_cursor_formats(output, allocator->buffer_caps); - if (display_formats == NULL) { - wlr_log(WLR_DEBUG, "Failed to get cursor display formats"); - return false; - } - } - - // Note: taken from https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4596/diffs#diff-content-e3ea164da86650995728d70bd118f6aa8c386797 - // If this fails to find a shared modifier try to use a linear - // modifier. This avoids a scenario where the hardware cannot render to - // linear textures but only linear textures are supported for cursors, - // as is the case with Nvidia and VmWare GPUs - if (!output_pick_format(output, display_formats, format, DRM_FORMAT_ARGB8888)) { - // Clear the format as output_pick_format doesn't zero it - memset(format, 0, sizeof(*format)); - return output_pick_format(output, NULL, format, DRM_FORMAT_ARGB8888); - } - return true; -} +#include <cstring> +#include <gbm.h> CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { @@ -201,6 +76,11 @@ void CPointerManager::unlockSoftwareForMonitor(SP<CMonitor> mon) { updateCursorBackend(); } +bool CPointerManager::softwareLockedFor(SP<CMonitor> mon) { + auto state = stateFor(mon); + return state->softwareLocks > 0 || state->hardwareFailed; +} + Vector2D CPointerManager::position() { return pointerPos; } @@ -216,7 +96,7 @@ SP<CPointerManager::SMonitorPointerState> CPointerManager::stateFor(SP<CMonitor> return *it; } -void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale) { +void CPointerManager::setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale) { damageIfSoftware(); if (buf == currentCursorImage.pBuffer) { if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) { @@ -232,10 +112,8 @@ void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, resetCursorImage(false); if (buf) { - currentCursorImage.size = {buf->width, buf->height}; - currentCursorImage.pBuffer = wlr_buffer_lock(buf); - - currentCursorImage.hyprListener_destroyBuffer.initCallback(&buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager"); + currentCursorImage.size = buf->size; + currentCursorImage.pBuffer = buf; } currentCursorImage.hotspot = hotspot; @@ -317,8 +195,8 @@ void CPointerManager::recheckEnteredOutputs() { // if we are using hw cursors, prevent // the cursor from being stuck at the last point. // if we are leaving it, move it to narnia. - if (!s->hardwareFailed && s->monitor->output->impl->move_cursor) - s->monitor->output->impl->move_cursor(s->monitor->output, -1337, -420); + if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) + s->monitor->output->moveCursor({-1337, -420}); if (!currentCursorImage.surface) continue; @@ -339,16 +217,11 @@ void CPointerManager::resetCursorImage(bool apply) { currentCursorImage.destroySurface.reset(); currentCursorImage.commitSurface.reset(); currentCursorImage.surface.reset(); - } else if (currentCursorImage.pBuffer) { - wlr_buffer_unlock(currentCursorImage.pBuffer); - currentCursorImage.hyprListener_destroyBuffer.removeCallback(); + } else if (currentCursorImage.pBuffer) currentCursorImage.pBuffer = nullptr; - } - if (currentCursorImage.pBufferTexture) { - wlr_texture_destroy(currentCursorImage.pBufferTexture); - currentCursorImage.pBufferTexture = nullptr; - } + if (currentCursorImage.bufferTex) + currentCursorImage.bufferTex = nullptr; currentCursorImage.scale = 1.F; currentCursorImage.hotspot = {0, 0}; @@ -370,9 +243,8 @@ void CPointerManager::resetCursorImage(bool apply) { } if (ms->cursorFrontBuffer) { - if (ms->monitor->output->impl->set_cursor) - ms->monitor->output->impl->set_cursor(ms->monitor->output, nullptr, 0, 0); - wlr_buffer_unlock(ms->cursorFrontBuffer); + if (ms->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER) + ms->monitor->output->setCursor(nullptr, {}); ms->cursorFrontBuffer = nullptr; } } @@ -418,18 +290,18 @@ void CPointerManager::onCursorMoved() { continue; const auto CURSORPOS = getCursorPosForMonitor(m); - m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y); + m->output->moveCursor(CURSORPOS); } } bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerState> state) { auto output = state->monitor->output; - if (!output->impl->set_cursor) + if (!(output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) return false; const auto CURSORPOS = getCursorPosForMonitor(state->monitor.lock()); - state->monitor->output->impl->move_cursor(state->monitor->output, CURSORPOS.x, CURSORPOS.y); + state->monitor->output->moveCursor(CURSORPOS); auto texture = getCurrentCursorTexture(); @@ -459,64 +331,62 @@ bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerS return success; } -bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf) { - if (!state->monitor->output->impl->set_cursor) +bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf) { + if (!(state->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) return false; const auto HOTSPOT = transformedHotspot(state->monitor.lock()); Debug::log(TRACE, "[pointer] hw transformed hotspot for {}: {}", state->monitor->szName, HOTSPOT); - if (!state->monitor->output->impl->set_cursor(state->monitor->output, buf, HOTSPOT.x, HOTSPOT.y)) + if (!state->monitor->output->setCursor(buf, HOTSPOT)) return false; - wlr_buffer_unlock(state->cursorFrontBuffer); state->cursorFrontBuffer = buf; - g_pCompositor->scheduleFrameForMonitor(state->monitor.get()); - - if (buf) - wlr_buffer_lock(buf); + g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } -wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) { +SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) { auto output = state->monitor->output; - int w = currentCursorImage.size.x, h = currentCursorImage.size.y; - if (output->impl->get_cursor_size) { - output->impl->get_cursor_size(output, &w, &h); - - if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) { - Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h); - return nullptr; - } - } + auto maxSize = output->cursorPlaneSize(); + auto cursorSize = currentCursorImage.size; - if (w <= 0 || h <= 0) { - Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, w, h); + if (maxSize == Vector2D{}) return nullptr; - } - if (!output->cursor_swapchain || Vector2D{w, h} != Vector2D{output->cursor_swapchain->width, output->cursor_swapchain->height}) { - wlr_drm_format fmt = {0}; - if (!output_pick_cursor_format(output, &fmt)) { - Debug::log(TRACE, "Failed to pick cursor format"); + if (maxSize != Vector2D{-1, -1}) { + if (cursorSize.x > maxSize.x || cursorSize.y > maxSize.y) { + Debug::log(TRACE, "hardware cursor too big! {} > {}", currentCursorImage.size, maxSize); return nullptr; } + } else + maxSize = cursorSize; + + if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { - wlr_swapchain_destroy(output->cursor_swapchain); - output->cursor_swapchain = wlr_swapchain_create(output->allocator, w, h, &fmt); - wlr_drm_format_finish(&fmt); + if (!state->monitor->cursorSwapchain) + state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend()); - if (!output->cursor_swapchain) { - Debug::log(TRACE, "Failed to create cursor swapchain"); + auto options = state->monitor->cursorSwapchain->currentOptions(); + options.size = maxSize; + options.length = 2; + options.scanout = true; + options.cursor = true; + options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; + // We do not set the format. If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, + // but if it's set, we don't wanna change it. + + if (!state->monitor->cursorSwapchain->reconfigure(options)) { + Debug::log(TRACE, "Failed to reconfigure cursor swapchain"); return nullptr; } } - wlr_buffer* buf = wlr_swapchain_acquire(output->cursor_swapchain, nullptr); + auto buf = state->monitor->cursorSwapchain->next(nullptr); if (!buf) { Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain"); return nullptr; @@ -525,16 +395,45 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPo CRegion damage = {0, 0, INT16_MAX, INT16_MAX}; g_pHyprRenderer->makeEGLCurrent(); - g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); // has to be set cuz allocs + g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); + + auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); + if (!RBO) { + Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); + static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:allow_dumb_copy"); + if (!*PDUMB) + return nullptr; + + auto bufData = buf->beginDataPtr(0); + auto bufPtr = std::get<0>(bufData); + + // clear buffer + memset(bufPtr, 0, std::get<2>(bufData)); + + auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer; + + if (texBuffer) { + auto textAttrs = texBuffer->shm(); + auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); + auto texPtr = std::get<0>(texData); + Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride); + // copy cursor texture + for (int i = 0; i < texBuffer->shm().size.y; i++) + memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride); + } + + buf->endDataPtr(); + + return buf; + } - const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888); RBO->bind(); g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO); g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; - Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, Vector2D{w, h}, + Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize, currentCursorImage.scale, state->monitor->scale, xbox.size()); g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F); @@ -543,9 +442,7 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPo glFlush(); g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; - g_pHyprRenderer->onRenderbufferDestroy(RBO); - - wlr_buffer_unlock(buf); + g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); return buf; } @@ -579,7 +476,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* box.x = std::round(box.x); box.y = std::round(box.y); - g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F); + g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F, 0, false, false, currentCursorImage.waitTimeline, currentCursorImage.waitPoint); if (currentCursorImage.surface) currentCursorImage.surface->resource()->frame(now); @@ -587,17 +484,19 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* Vector2D CPointerManager::getCursorPosForMonitor(SP<CMonitor> pMonitor) { return CBox{pointerPos - pMonitor->vecPosition, {0, 0}} - //.transform(pMonitor->transform, pMonitor->vecTransformedSize.x / pMonitor->scale, pMonitor->vecTransformedSize.y / pMonitor->scale) + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x / pMonitor->scale, + pMonitor->vecTransformedSize.y / pMonitor->scale) .pos() * pMonitor->scale; } Vector2D CPointerManager::transformedHotspot(SP<CMonitor> pMonitor) { - if (!pMonitor->output->cursor_swapchain) + if (!pMonitor->cursorSwapchain) return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}} - .transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height) + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x, + pMonitor->cursorSwapchain->currentOptions().size.y) .pos(); } @@ -799,10 +698,8 @@ SP<CTexture> CPointerManager::getCurrentCursorTexture() { return nullptr; if (currentCursorImage.pBuffer) { - if (!currentCursorImage.pBufferTexture) { - currentCursorImage.pBufferTexture = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, currentCursorImage.pBuffer); - currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBufferTexture); - } + if (!currentCursorImage.bufferTex) + currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBuffer); return currentCursorImage.bufferTex; } diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index da639340..cf4f1a94 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -6,13 +6,15 @@ #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" +#include "../helpers/sync/SyncTimeline.hpp" #include <tuple> class CMonitor; -struct wlr_input_device; class IHID; class CTexture; +AQUAMARINE_FORWARD(IBuffer); + /* The naming here is a bit confusing. CPointerManager manages the _position_ and _displaying_ of the cursor, @@ -37,7 +39,7 @@ class CPointerManager { void move(const Vector2D& deltaLogical); void warpAbsolute(Vector2D abs, SP<IHID> dev); - void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale); + void setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale); void setCursorSurface(SP<CWLSurface> buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); @@ -47,6 +49,7 @@ class CPointerManager { void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); + bool softwareLockedFor(SP<CMonitor> pMonitor); void renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */); @@ -135,45 +138,42 @@ class CPointerManager { } currentMonitorLayout; struct { - wlr_buffer* pBuffer = nullptr; - SP<CTexture> bufferTex; - WP<CWLSurface> surface; - wlr_texture* pBufferTexture = nullptr; - - Vector2D hotspot; - Vector2D size; - float scale = 1.F; - - CHyprSignalListener destroySurface; - CHyprSignalListener commitSurface; - DYNLISTENER(destroyBuffer); + SP<Aquamarine::IBuffer> pBuffer; + SP<CTexture> bufferTex; + WP<CWLSurface> surface; + + Vector2D hotspot; + Vector2D size; + float scale = 1.F; + + CHyprSignalListener destroySurface; + CHyprSignalListener commitSurface; + SP<CSyncTimeline> waitTimeline = nullptr; + uint64_t waitPoint = 0; } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors Vector2D pointerPos = {0, 0}; struct SMonitorPointerState { SMonitorPointerState(SP<CMonitor> m) : monitor(m) {} - ~SMonitorPointerState() { - if (cursorFrontBuffer) - wlr_buffer_unlock(cursorFrontBuffer); - } + ~SMonitorPointerState() {} - WP<CMonitor> monitor; + WP<CMonitor> monitor; - int softwareLocks = 0; - bool hardwareFailed = false; - CBox box; // logical - bool entered = false; - bool hwApplied = false; + int softwareLocks = 0; + bool hardwareFailed = false; + CBox box; // logical + bool entered = false; + bool hwApplied = false; - wlr_buffer* cursorFrontBuffer = nullptr; + SP<Aquamarine::IBuffer> cursorFrontBuffer; }; std::vector<SP<SMonitorPointerState>> monitorStates; SP<SMonitorPointerState> stateFor(SP<CMonitor> mon); bool attemptHardwareCursor(SP<SMonitorPointerState> state); - wlr_buffer* renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture); - bool setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf); + SP<Aquamarine::IBuffer> renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture); + bool setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf); struct { SP<HOOK_CALLBACK_FN> monitorAdded; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 74cebd0c..387cac8f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -1,5 +1,7 @@ #include "ProtocolManager.hpp" +#include "../config/ConfigValue.hpp" + #include "../protocols/TearingControl.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/XDGOutput.hpp" @@ -35,6 +37,8 @@ #include "../protocols/Viewporter.hpp" #include "../protocols/MesaDRM.hpp" #include "../protocols/LinuxDMABUF.hpp" +#include "../protocols/DRMLease.hpp" +#include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -45,6 +49,10 @@ #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" +#include "../Compositor.hpp" + +#include <aquamarine/buffer/Buffer.hpp> +#include <aquamarine/backend/Backend.hpp> void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { const bool ISMIRROR = pMonitor->isMirror(); @@ -65,6 +73,8 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { CProtocolManager::CProtocolManager() { + static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("experimental:explicit_sync"); + // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { auto M = std::any_cast<CMonitor*>(param); @@ -131,6 +141,16 @@ CProtocolManager::CProtocolManager() { PROTO::primarySelection = std::make_unique<CPrimarySelectionProtocol>(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique<CXWaylandShellProtocol>(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + if (b->type() != Aquamarine::AQ_BACKEND_DRM) + continue; + + PROTO::lease = std::make_unique<CDRMLeaseProtocol>(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + if (*PENABLEEXPLICIT) + PROTO::sync = std::make_unique<CDRMSyncobjProtocol>(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); + break; + } + if (g_pHyprOpenGL->getDRMFormats().size() > 0) { PROTO::mesaDRM = std::make_unique<CMesaDRMProtocol>(&wl_drm_interface, 2, "MesaDRM"); PROTO::linuxDma = std::make_unique<CLinuxDMABufV1Protocol>(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 6589c4bf..801ae55a 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -94,8 +94,8 @@ void CSeatManager::setKeyboard(SP<IKeyboard> KEEB) { } void CSeatManager::updateActiveKeyboardData() { - if (keyboard && keyboard->wlr()) - PROTO::seat->updateRepeatInfo(keyboard->wlr()->repeat_info.rate, keyboard->wlr()->repeat_info.delay); + if (keyboard) + PROTO::seat->updateRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay); PROTO::seat->updateKeymap(); } @@ -103,7 +103,7 @@ void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) { if (state.keyboardFocus == surf) return; - if (!keyboard || !keyboard->wlr()) { + if (!keyboard) { Debug::log(ERR, "BUG THIS: setKeyboardFocus without a valid keyboard set"); return; } @@ -144,7 +144,7 @@ void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) { continue; k->sendEnter(surf); - k->sendMods(keyboard->wlr()->modifiers.depressed, keyboard->wlr()->modifiers.latched, keyboard->wlr()->modifiers.locked, keyboard->wlr()->modifiers.group); + k->sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group); } } @@ -196,7 +196,7 @@ void CSeatManager::setPointerFocus(SP<CWLSurfaceResource> surf, const Vector2D& return; } - if (!mouse || !mouse->wlr()) { + if (!mouse) { Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set"); return; } diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 0d1b0223..ed7a4f72 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -1,5 +1,6 @@ #include "EventLoopManager.hpp" #include "../../debug/Log.hpp" +#include "../../Compositor.hpp" #include <algorithm> #include <limits> @@ -7,6 +8,8 @@ #include <sys/timerfd.h> #include <time.h> +#include <aquamarine/backend/Backend.hpp> + #define TIMESPEC_NSEC_PER_SEC 1000000000L CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { @@ -25,9 +28,21 @@ static int timerWrite(int fd, uint32_t mask, void* data) { return 1; } +static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { + auto POLLFD = (Aquamarine::SPollFD*)data; + POLLFD->onSignal(); + return 1; +} + void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); + aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + for (auto& fd : aqPollFDs) { + m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); + fd->onSignal(); // dispatch outstanding + } + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 0b2f9578..39d8bbeb 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -7,6 +7,10 @@ #include "EventLoopTimer.hpp" +namespace Aquamarine { + struct SPollFD; +}; + class CEventLoopManager { public: CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop); @@ -33,9 +37,10 @@ class CEventLoopManager { private: struct { - wl_event_loop* loop = nullptr; - wl_display* display = nullptr; - wl_event_source* eventSource = nullptr; + wl_event_loop* loop = nullptr; + wl_display* display = nullptr; + wl_event_source* eventSource = nullptr; + std::vector<wl_event_source*> aqEventSources; } m_sWayland; struct { @@ -43,7 +48,10 @@ class CEventLoopManager { int timerfd = -1; } m_sTimers; - SIdleData m_sIdle; + SIdleData m_sIdle; + std::vector<SP<Aquamarine::SPollFD>> aqPollFDs; + + friend class CSyncTimeline; }; inline std::unique_ptr<CEventLoopManager> g_pEventLoopManager;
\ No newline at end of file diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 23e183d0..255023b9 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1,6 +1,6 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" -#include "wlr/types/wlr_switch.h" +#include <aquamarine/output/Output.hpp> #include <cstdint> #include <ranges> #include "../../config/ConfigValue.hpp" @@ -28,6 +28,8 @@ #include "../../managers/PointerManager.hpp" #include "../../managers/SeatManager.hpp" +#include <aquamarine/input/Input.hpp> + CInputManager::CInputManager() { m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { if (!cursorImageUnlocked()) @@ -189,8 +191,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); - if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule) + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); PHLWINDOW forcedFocus = m_pForcedFocus.lock(); @@ -372,8 +374,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); - if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get()); + if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); // grabs if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(foundSurface)) { @@ -843,8 +845,8 @@ Vector2D CInputManager::getMouseCoordsInternal() { return g_pPointerManager->position(); } -void CInputManager::newKeyboard(wlr_input_device* keyboard) { - const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(wlr_keyboard_from_input_device(keyboard))); +void CInputManager::newKeyboard(SP<Aquamarine::IKeyboard> keyboard) { + const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(keyboard)); setupKeyboard(PNEWKEYBOARD); @@ -856,14 +858,14 @@ void CInputManager::newVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keyboard) setupKeyboard(PNEWKEYBOARD); - Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard->wlr()); + Debug::log(LOG, "New virtual keyboard created at {:x}", (uintptr_t)PNEWKEYBOARD.get()); } void CInputManager::setupKeyboard(SP<IKeyboard> keeb) { m_vHIDs.push_back(keeb); try { - keeb->hlName = getNameForNewDevice(keeb->wlr()->base.name); + keeb->hlName = getNameForNewDevice(keeb->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Keyboard had no name???"); // logic error } @@ -962,83 +964,12 @@ void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) { // we can ignore those and just apply } - wlr_keyboard_set_repeat_info(pKeyboard->wlr(), std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); - - pKeyboard->repeatDelay = REPEATDELAY; - pKeyboard->repeatRate = REPEATRATE; + pKeyboard->repeatRate = std::max(0, REPEATRATE); + pKeyboard->repeatDelay = std::max(0, REPEATDELAY); pKeyboard->numlockOn = NUMLOCKON; pKeyboard->xkbFilePath = FILEPATH; - xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; - - pKeyboard->currentRules.rules = RULES; - pKeyboard->currentRules.model = MODEL; - pKeyboard->currentRules.variant = VARIANT; - pKeyboard->currentRules.options = OPTIONS; - pKeyboard->currentRules.layout = LAYOUT; - - const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - - if (!CONTEXT) { - Debug::log(ERR, "applyConfigToKeyboard: CONTEXT null??"); - return; - } - - Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model, - rules.options); - - xkb_keymap* KEYMAP = NULL; - - if (!FILEPATH.empty()) { - auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath); - - if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE) - Debug::log(ERR, "Cannot open input:kb_file= file for reading"); - else { - KEYMAP = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - fclose(KEYMAPFILE); - } - } - - if (!KEYMAP) - KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - - if (!KEYMAP) { - g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + - ", layout: " + LAYOUT + " )"); - - Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, - rules.options); - memset(&rules, 0, sizeof(rules)); - - pKeyboard->currentRules.rules = ""; - pKeyboard->currentRules.model = ""; - pKeyboard->currentRules.variant = ""; - pKeyboard->currentRules.options = ""; - pKeyboard->currentRules.layout = "us"; - - KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - } - - wlr_keyboard_set_keymap(pKeyboard->wlr(), KEYMAP); - - pKeyboard->updateXKBTranslationState(); - - wlr_keyboard_modifiers wlrMods = {0}; - - if (NUMLOCKON == 1) { - // lock numlock - const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM); - - if (IDX != XKB_MOD_INVALID) - wlrMods.locked |= (uint32_t)1 << IDX; - } - - if (wlrMods.locked != 0) - wlr_keyboard_notify_modifiers(pKeyboard->wlr(), 0, 0, wlrMods.locked, 0); - - xkb_keymap_unref(KEYMAP); - xkb_context_unref(CONTEXT); + pKeyboard->setKeymap(IKeyboard::SStringRuleNames{LAYOUT, MODEL, VARIANT, OPTIONS, RULES}); const auto LAYOUTSTR = pKeyboard->getActiveLayout(); @@ -1053,11 +984,11 @@ void CInputManager::newVirtualMouse(SP<CVirtualPointerV1Resource> mouse) { setupMouse(PMOUSE); - Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr()); + Debug::log(LOG, "New virtual mouse created"); } -void CInputManager::newMouse(wlr_input_device* mouse) { - const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(wlr_pointer_from_input_device(mouse))); +void CInputManager::newMouse(SP<Aquamarine::IPointer> mouse) { + const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(mouse)); setupMouse(PMOUSE); @@ -1068,13 +999,13 @@ void CInputManager::setupMouse(SP<IPointer> mauz) { m_vHIDs.push_back(mauz); try { - mauz->hlName = getNameForNewDevice(mauz->wlr()->base.name); + mauz->hlName = getNameForNewDevice(mauz->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Mouse had no name???"); // logic error } - if (wlr_input_device_is_libinput(&mauz->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&mauz->wlr()->base); + if (mauz->aq() && mauz->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = mauz->aq()->getLibinputHandle(); Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV), @@ -1120,8 +1051,8 @@ void CInputManager::setPointerConfigs() { } } - if (wlr_input_device_is_libinput(&m->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base); + if (m->aq() && m->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = m->aq()->getLibinputHandle(); double touchw = 0, touchh = 0; const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && @@ -1261,16 +1192,14 @@ static void removeFromHIDs(WP<IHID> hid) { } void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) { - if (pKeyboard->xkbTranslationState) - xkb_state_unref(pKeyboard->xkbTranslationState); - pKeyboard->xkbTranslationState = nullptr; + Debug::log(LOG, "Keyboard at {:x} removed", (uintptr_t)pKeyboard.get()); std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); if (m_vKeyboards.size() > 0) { bool found = false; for (auto& k : m_vKeyboards | std::views::reverse) { - if (!k->wlr()) + if (!k) continue; g_pSeatManager->setKeyboard(k); @@ -1287,6 +1216,8 @@ void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) { } void CInputManager::destroyPointer(SP<IPointer> mouse) { + Debug::log(LOG, "Pointer at {:x} removed", (uintptr_t)mouse.get()); + std::erase_if(m_vPointers, [mouse](const auto& other) { return other == mouse; }); g_pSeatManager->setMouse(m_vPointers.size() > 0 ? m_vPointers.front() : nullptr); @@ -1333,20 +1264,7 @@ void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) { if (!pKeyboard) return; - auto keyboard = pKeyboard->wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) - return; - - uint32_t leds = 0; - for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) - leds |= (1 << i); - } - - for (auto& k : m_vKeyboards) { - k->updateLEDs(leds); - } + pKeyboard->updateLEDs(); } void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) { @@ -1374,7 +1292,7 @@ void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) { const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(pKeyboard->wlr()); + IME->setKeyboard(pKeyboard); IME->sendKey(e.timeMs, e.keycode, e.state); } else { g_pSeatManager->setKeyboard(pKeyboard); @@ -1392,15 +1310,14 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) { const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); const auto ALLMODS = accumulateModsFromAllKBs(); - const auto PWLRKB = pKeyboard->wlr(); - auto MODS = PWLRKB->modifiers; + auto MODS = pKeyboard->modifiersState; MODS.depressed = ALLMODS; const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(PWLRKB); + IME->setKeyboard(pKeyboard); IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); } else { g_pSeatManager->setKeyboard(pKeyboard); @@ -1409,12 +1326,12 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) { updateKeyboardsLeds(pKeyboard); - if (PWLRKB->modifiers.group != pKeyboard->activeLayout) { - pKeyboard->activeLayout = PWLRKB->modifiers.group; + if (pKeyboard->modifiersState.group != pKeyboard->activeLayout) { + pKeyboard->activeLayout = pKeyboard->modifiersState.group; const auto LAYOUT = pKeyboard->getActiveLayout(); - pKeyboard->updateXKBTranslationState(); + Debug::log(LOG, "LAYOUT CHANGED TO {} GROUP {}", LAYOUT, MODS.group); g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUT}); EMIT_HOOK_EVENT("activeLayout", (std::vector<std::any>{pKeyboard, LAYOUT})); @@ -1524,10 +1441,10 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; - if (!kb->enabled || !kb->wlr()) + if (!kb->enabled) continue; - finalMask |= wlr_keyboard_get_modifiers(kb->wlr()); + finalMask |= kb->getModifiers(); } return finalMask; @@ -1543,12 +1460,12 @@ void CInputManager::disableAllKeyboards(bool virt) { } } -void CInputManager::newTouchDevice(wlr_input_device* pDevice) { - const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(wlr_touch_from_input_device(pDevice))); +void CInputManager::newTouchDevice(SP<Aquamarine::ITouch> pDevice) { + const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(pDevice)); m_vHIDs.push_back(PNEWDEV); try { - PNEWDEV->hlName = getNameForNewDevice(pDevice->name); + PNEWDEV->hlName = getNameForNewDevice(PNEWDEV->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Touch Device had no name???"); // logic error } @@ -1572,8 +1489,8 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) { void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) { auto setConfig = [&](SP<ITouch> PTOUCHDEV) -> void { - if (wlr_input_device_is_libinput(&PTOUCHDEV->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&PTOUCHDEV->wlr()->base); + if (dev->aq() && dev->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = dev->aq()->getLibinputHandle(); const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled"); const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; @@ -1589,11 +1506,12 @@ void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) { bool bound = !output.empty() && output != STRVAL_EMPTY; const bool AUTODETECT = output == "[[Auto]]"; if (!bound && AUTODETECT) { - const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; - if (DEFAULTOUTPUT) { - output = DEFAULTOUTPUT; - bound = true; - } + // FIXME: + // const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; + // if (DEFAULTOUTPUT) { + // output = DEFAULTOUTPUT; + // bound = true; + // } } PTOUCHDEV->boundOutput = bound ? output : ""; const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr; @@ -1617,9 +1535,9 @@ void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) { void CInputManager::setTabletConfigs() { for (auto& t : m_vTablets) { - if (wlr_input_device_is_libinput(&t->wlr()->base)) { + if (t->aq()->getLibinputHandle()) { const auto NAME = t->hlName; - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&t->wlr()->base); + const auto LIBINPUTDEV = t->aq()->getLibinputHandle(); const auto RELINPUT = g_pConfigManager->getDeviceInt(NAME, "relative_input", "input:tablet:relative_input"); t->relativeInput = RELINPUT; @@ -1647,51 +1565,37 @@ void CInputManager::setTabletConfigs() { const auto ACTIVE_AREA_SIZE = g_pConfigManager->getDeviceVec(NAME, "active_area_size", "input:tablet:active_area_size"); const auto ACTIVE_AREA_POS = g_pConfigManager->getDeviceVec(NAME, "active_area_position", "input:tablet:active_area_position"); if (ACTIVE_AREA_SIZE.x != 0 || ACTIVE_AREA_SIZE.y != 0) { - t->activeArea = CBox{ACTIVE_AREA_POS.x / t->wlr()->width_mm, ACTIVE_AREA_POS.y / t->wlr()->height_mm, (ACTIVE_AREA_POS.x + ACTIVE_AREA_SIZE.x) / t->wlr()->width_mm, - (ACTIVE_AREA_POS.y + ACTIVE_AREA_SIZE.y) / t->wlr()->height_mm}; + t->activeArea = CBox{ACTIVE_AREA_POS.x / t->aq()->physicalSize.x, ACTIVE_AREA_POS.y / t->aq()->physicalSize.y, + (ACTIVE_AREA_POS.x + ACTIVE_AREA_SIZE.x) / t->aq()->physicalSize.x, (ACTIVE_AREA_POS.y + ACTIVE_AREA_SIZE.y) / t->aq()->physicalSize.y}; } } } } -void CInputManager::newSwitch(wlr_input_device* pDevice) { - const auto PNEWDEV = &m_lSwitches.emplace_back(); - PNEWDEV->pWlrDevice = pDevice; - - Debug::log(LOG, "New switch with name \"{}\" added", pDevice->name); +void CInputManager::newSwitch(SP<Aquamarine::ISwitch> pDevice) { + const auto PNEWDEV = &m_lSwitches.emplace_back(); + PNEWDEV->pDevice = pDevice; - PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) { destroySwitch((SSwitchDevice*)owner); }, PNEWDEV, "SwitchDevice"); + Debug::log(LOG, "New switch with name \"{}\" added", pDevice->getName()); - const auto PSWITCH = wlr_switch_from_input_device(pDevice); + PNEWDEV->listeners.destroy = pDevice->events.destroy.registerListener([this, PNEWDEV](std::any d) { destroySwitch(PNEWDEV); }); - PNEWDEV->hyprListener_toggle.initCallback( - &PSWITCH->events.toggle, - [&](void* owner, void* data) { - const auto PDEVICE = (SSwitchDevice*)owner; - const auto NAME = std::string(PDEVICE->pWlrDevice->name); - const auto E = (wlr_switch_toggle_event*)data; + PNEWDEV->listeners.fire = pDevice->events.fire.registerListener([PNEWDEV](std::any d) { + const auto NAME = PNEWDEV->pDevice->getName(); + const auto E = std::any_cast<Aquamarine::ISwitch::SFireEvent>(d); - if (PDEVICE->status != -1 && PDEVICE->status == E->switch_state) - return; - - Debug::log(LOG, "Switch {} fired, triggering binds.", NAME); + Debug::log(LOG, "Switch {} fired, triggering binds.", NAME); - g_pKeybindManager->onSwitchEvent(NAME); + g_pKeybindManager->onSwitchEvent(NAME); - switch (E->switch_state) { - case WLR_SWITCH_STATE_ON: - Debug::log(LOG, "Switch {} turn on, triggering binds.", NAME); - g_pKeybindManager->onSwitchOnEvent(NAME); - break; - case WLR_SWITCH_STATE_OFF: - Debug::log(LOG, "Switch {} turn off, triggering binds.", NAME); - g_pKeybindManager->onSwitchOffEvent(NAME); - break; - } - - PDEVICE->status = E->switch_state; - }, - PNEWDEV, "SwitchDevice"); + if (E.enable) { + Debug::log(LOG, "Switch {} turn on, triggering binds.", NAME); + g_pKeybindManager->onSwitchOnEvent(NAME); + } else { + Debug::log(LOG, "Switch {} turn off, triggering binds.", NAME); + g_pKeybindManager->onSwitchOffEvent(NAME); + } + }); } void CInputManager::destroySwitch(SSwitchDevice* pDevice) { diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 85ae6197..ebf00b2d 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -18,6 +18,14 @@ class CVirtualKeyboardV1Resource; class CVirtualPointerV1Resource; class IKeyboard; +AQUAMARINE_FORWARD(IPointer); +AQUAMARINE_FORWARD(IKeyboard); +AQUAMARINE_FORWARD(ITouch); +AQUAMARINE_FORWARD(ISwitch); +AQUAMARINE_FORWARD(ITablet); +AQUAMARINE_FORWARD(ITabletTool); +AQUAMARINE_FORWARD(ITabletPad); + enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL @@ -82,15 +90,14 @@ class CInputManager { void onKeyboardKey(std::any, SP<IKeyboard>); void onKeyboardMod(SP<IKeyboard>); - void newKeyboard(wlr_input_device*); + void newKeyboard(SP<Aquamarine::IKeyboard>); void newVirtualKeyboard(SP<CVirtualKeyboardV1Resource>); - void newMouse(wlr_input_device*); + void newMouse(SP<Aquamarine::IPointer>); void newVirtualMouse(SP<CVirtualPointerV1Resource>); - void newTouchDevice(wlr_input_device*); - void newSwitch(wlr_input_device*); - void newTabletTool(wlr_tablet_tool*); - void newTabletPad(wlr_input_device*); - void newTablet(wlr_input_device*); + void newTouchDevice(SP<Aquamarine::ITouch>); + void newSwitch(SP<Aquamarine::ISwitch>); + void newTabletPad(SP<Aquamarine::ITabletPad>); + void newTablet(SP<Aquamarine::ITablet>); void destroyTouchDevice(SP<ITouch>); void destroyKeyboard(SP<IKeyboard>); void destroyPointer(SP<IPointer>); @@ -232,7 +239,7 @@ class CInputManager { void mouseMoveUnified(uint32_t, bool refocus = false); - SP<CTabletTool> ensureTabletToolPresent(wlr_tablet_tool*); + SP<CTabletTool> ensureTabletToolPresent(SP<Aquamarine::ITabletTool>); void applyConfigToKeyboard(SP<IKeyboard>); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index f1157e4b..5e50e851 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -62,7 +62,7 @@ static void refocusTablet(SP<CTablet> tab, SP<CTabletTool> tool, bool motion = f if (!motion) return; - if (LASTHLSURFACE->constraint() && tool->wlr()->type != WLR_TABLET_TOOL_TYPE_MOUSE) { + if (LASTHLSURFACE->constraint() && tool->aq()->type != Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE) { // cursor logic will completely break here as the cursor will be locked. // let's just "map" the desired position to the constraint area. @@ -102,7 +102,7 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { Vector2D delta = {std::isnan(dx) ? 0.0 : dx, std::isnan(dy) ? 0.0 : dy}; switch (e.tool->type) { - case WLR_TABLET_TOOL_TYPE_MOUSE: { + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE: { g_pPointerManager->move(delta); break; } @@ -205,12 +205,12 @@ void CInputManager::onTabletProximity(CTablet::SProximityEvent e) { PROTO::idle->onActivity(); } -void CInputManager::newTablet(wlr_input_device* pDevice) { - const auto PNEWTABLET = m_vTablets.emplace_back(CTablet::create(wlr_tablet_from_input_device(pDevice))); +void CInputManager::newTablet(SP<Aquamarine::ITablet> pDevice) { + const auto PNEWTABLET = m_vTablets.emplace_back(CTablet::create(pDevice)); m_vHIDs.push_back(PNEWTABLET); try { - PNEWTABLET->hlName = deviceNameToInternalString(pDevice->name); + PNEWTABLET->hlName = deviceNameToInternalString(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -227,28 +227,32 @@ void CInputManager::newTablet(wlr_input_device* pDevice) { setTabletConfigs(); } -SP<CTabletTool> CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) { - if (pTool->data == nullptr) { - const auto PTOOL = m_vTabletTools.emplace_back(CTabletTool::create(pTool)); - m_vHIDs.push_back(PTOOL); - - PTOOL->events.destroy.registerStaticListener( - [this](void* owner, std::any d) { - auto TOOL = ((CTabletTool*)owner)->self; - destroyTabletTool(TOOL.lock()); - }, - PTOOL.get()); +SP<CTabletTool> CInputManager::ensureTabletToolPresent(SP<Aquamarine::ITabletTool> pTool) { + + for (auto& t : m_vTabletTools) { + if (t->aq() == pTool) + return t; } - return CTabletTool::fromWlr(pTool); + const auto PTOOL = m_vTabletTools.emplace_back(CTabletTool::create(pTool)); + m_vHIDs.push_back(PTOOL); + + PTOOL->events.destroy.registerStaticListener( + [this](void* owner, std::any d) { + auto TOOL = ((CTabletTool*)owner)->self; + destroyTabletTool(TOOL.lock()); + }, + PTOOL.get()); + + return PTOOL; } -void CInputManager::newTabletPad(wlr_input_device* pDevice) { - const auto PNEWPAD = m_vTabletPads.emplace_back(CTabletPad::create(wlr_tablet_pad_from_input_device(pDevice))); +void CInputManager::newTabletPad(SP<Aquamarine::ITabletPad> pDevice) { + const auto PNEWPAD = m_vTabletPads.emplace_back(CTabletPad::create(pDevice)); m_vHIDs.push_back(PNEWPAD); try { - PNEWPAD->hlName = deviceNameToInternalString(pDevice->name); + PNEWPAD->hlName = deviceNameToInternalString(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Pad had no name???"); // logic error } @@ -259,7 +263,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { destroyTabletPad(PAD.lock()); }, PNEWPAD.get()); - PNEWPAD->padEvents.button.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.button.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast<CTabletPad::SButtonEvent>(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); @@ -267,26 +271,25 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { PROTO::tablet->buttonPad(PPAD, E.button, E.timeMs, E.down); }, PNEWPAD.get()); - PNEWPAD->padEvents.strip.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.strip.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast<CTabletPad::SStripEvent>(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); PROTO::tablet->strip(PPAD, E.strip, E.position, E.finger, E.timeMs); }, PNEWPAD.get()); - PNEWPAD->padEvents.ring.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.ring.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast<CTabletPad::SRingEvent>(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); PROTO::tablet->ring(PPAD, E.ring, E.position, E.finger, E.timeMs); }, PNEWPAD.get()); - PNEWPAD->padEvents.attach.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.attach.registerStaticListener([](void* owner, std::any e) { const auto PPAD = ((CTabletPad*)owner)->self.lock(); const auto TOOL = std::any_cast<SP<CTabletTool>>(e); PPAD->parent = TOOL; }, PNEWPAD.get()); - // clang-format on } |
