diff options
Diffstat (limited to 'src/managers/CursorManager.cpp')
| -rw-r--r-- | src/managers/CursorManager.cpp | 345 |
1 files changed, 173 insertions, 172 deletions
diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 9b574901..3f3a25f6 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -17,11 +17,61 @@ static void hcLogger(enum eHyprcursorLogLevel level, char* message) { Debug::log(NONE, "[hc] {}", message); } +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); +} + +CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + pixelData = pixelData_; + size = size_; + stride = 4 * size_.x; +} + +Aquamarine::eBufferCapability CCursorBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +Aquamarine::eBufferType CCursorBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +void CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { + ; +} + +bool CCursorBuffer::isSynchronous() { + return true; +} + +bool CCursorBuffer::good() { + return true; +} + +Aquamarine::SSHMAttrs CCursorBuffer::shm() { + Aquamarine::SSHMAttrs attrs; + attrs.success = true; + attrs.format = DRM_FORMAT_ARGB8888; + attrs.size = size; + attrs.stride = stride; + return attrs; +} + +std::tuple<uint8_t*, uint32_t, size_t> CCursorBuffer::beginDataPtr(uint32_t flags) { + return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride}; +} + +void CCursorBuffer::endDataPtr() { + ; +} + CCursorManager::CCursorManager() { - m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); - m_pXcursor = std::make_unique<CXCursorManager>(); + m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); + m_pXcursor = std::make_unique<CXCursorManager>(); + static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); - if (m_pHyprcursor->valid()) { + if (m_pHyprcursor->valid() && *PUSEHYPRCURSOR) { // find default size. First, HYPRCURSOR_SIZE then default to 24 auto const* SIZE = getenv("HYPRCURSOR_SIZE"); if (SIZE) { @@ -48,10 +98,12 @@ CCursorManager::CCursorManager() { Debug::log(WARN, "XCURSOR_SIZE size not set, defaulting to size 24"); m_iSize = 24; } - - m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); } + // since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config + // and then later is disabled. + m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); + m_pAnimationTimer = makeShared<CEventLoopTimer>(std::nullopt, cursorAnimTimer, this); g_pEventLoopManager->addTimer(m_pAnimationTimer); @@ -65,63 +117,9 @@ CCursorManager::~CCursorManager() { g_pEventLoopManager->removeTimer(m_pAnimationTimer); m_pAnimationTimer.reset(); } -} - -void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { - std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; }); -} - -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); -} - -CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { - pixelData = pixelData_; - size = size_; - stride = 4 * size_.x; -} - -CCursorManager::CCursorBuffer::~CCursorBuffer() { - ; -} - -Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() { - return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; -} - -Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() { - return Aquamarine::eBufferType::BUFFER_TYPE_SHM; -} - -void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { - ; -} - -bool CCursorManager::CCursorBuffer::isSynchronous() { - return true; -} -bool CCursorManager::CCursorBuffer::good() { - return true; -} - -Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() { - Aquamarine::SSHMAttrs attrs; - attrs.success = true; - attrs.format = DRM_FORMAT_ARGB8888; - attrs.size = size; - attrs.stride = stride; - return attrs; -} - -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}; -} - -void CCursorManager::CCursorBuffer::endDataPtr() { - ; + if (m_pHyprcursor->valid() && m_sCurrentStyleInfo.size > 0) + m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); } SP<Aquamarine::IBuffer> CCursorManager::getCursorBuffer() { @@ -137,91 +135,101 @@ void CCursorManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotsp m_bOurBufferConnected = false; } -void CCursorManager::setXCursor(const std::string& name) { - float scale = std::ceil(m_fCursorScale); - - auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); - auto& icon = xcursor->images.front(); - - m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot)); - - g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon.hotspot / scale, scale); +void CCursorManager::setCursorBuffer(SP<CCursorBuffer> buf, const Vector2D& hotspot, const float& scale) { + m_vCursorBuffers.emplace_back(buf); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), hotspot, scale); if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); + std::erase_if(m_vCursorBuffers, [this](const auto& buf) { return buf.get() == m_vCursorBuffers.front().get(); }); - m_currentXcursor = xcursor; m_bOurBufferConnected = true; +} - if (m_currentXcursor->images.size() > 1) { - // animated - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_currentXcursor->images[0].delay)); - m_iCurrentAnimationFrame = 0; +void CCursorManager::setAnimationTimer(const int& frame, const int& delay) { + if (delay > 0) { + // arm + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(delay)); } else { // disarm m_pAnimationTimer->updateTimeout(std::nullopt); } + + m_iCurrentAnimationFrame = frame; } void CCursorManager::setCursorFromName(const std::string& name) { static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); - if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR) { - setXCursor(name); - return; - } + auto setXCursor = [this](auto const& name) { + float scale = std::ceil(m_fCursorScale); - m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo); + auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); + auto& icon = xcursor->images.front(); + auto buf = makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); + setCursorBuffer(buf, icon.hotspot / scale, scale); - if (m_sCurrentCursorShapeData.images.size() < 1) { - // try with '_' first (old hc, etc) - std::string newName = name; - std::replace(newName.begin(), newName.end(), '-', '_'); + m_currentXcursor = xcursor; - m_sCurrentCursorShapeData = m_pHyprcursor->getShape(newName.c_str(), m_sCurrentStyleInfo); - } + int delay = 0; + int frame = 0; + if (m_currentXcursor->images.size() > 1) + delay = m_currentXcursor->images[frame].delay; - if (m_sCurrentCursorShapeData.images.size() < 1) { - // fallback to a default if available - constexpr const std::array<const char*, 3> fallbackShapes = {"default", "left_ptr", "left-ptr"}; + setAnimationTimer(frame, delay); + }; - for (auto& s : fallbackShapes) { - m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); + auto setHyprCursor = [this](auto const& name) { + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo); - if (m_sCurrentCursorShapeData.images.size() > 0) - break; + if (m_sCurrentCursorShapeData.images.size() < 1) { + // try with '_' first (old hc, etc) + std::string newName = name; + std::replace(newName.begin(), newName.end(), '-', '_'); + + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(newName.c_str(), m_sCurrentStyleInfo); } if (m_sCurrentCursorShapeData.images.size() < 1) { - Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName"); - setXCursor(name); - return; + // fallback to a default if available + constexpr const std::array<const char*, 3> fallbackShapes = {"default", "left_ptr", "left-ptr"}; + + for (auto& s : fallbackShapes) { + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); + + if (m_sCurrentCursorShapeData.images.size() > 0) + break; + } + + if (m_sCurrentCursorShapeData.images.size() < 1) { + Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName"); + return false; + } } - } - 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})); + auto buf = + 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}); + auto hotspot = Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale; + setCursorBuffer(buf, hotspot, m_fCursorScale); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale, - m_fCursorScale); - if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); + int delay = 0; + int frame = 0; + if (m_sCurrentCursorShapeData.images.size() > 1) + delay = m_sCurrentCursorShapeData.images[frame].delay; - m_bOurBufferConnected = true; + setAnimationTimer(frame, delay); + return true; + }; - if (m_sCurrentCursorShapeData.images.size() > 1) { - // animated - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_sCurrentCursorShapeData.images[0].delay)); - m_iCurrentAnimationFrame = 0; - } else { - // disarm - m_pAnimationTimer->updateTimeout(std::nullopt); - } + if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR || !setHyprCursor(name)) + setXCursor(name); } void CCursorManager::tickAnimatedCursor() { - if (!m_pHyprcursor->valid() && m_currentXcursor->images.size() > 1 && m_bOurBufferConnected) { + if (!m_bOurBufferConnected) + return; + + if (!m_pHyprcursor->valid() && m_currentXcursor->images.size() > 1) { m_iCurrentAnimationFrame++; if ((size_t)m_iCurrentAnimationFrame >= m_currentXcursor->images.size()) @@ -229,39 +237,24 @@ void CCursorManager::tickAnimatedCursor() { float scale = std::ceil(m_fCursorScale); auto& icon = m_currentXcursor->images.at(m_iCurrentAnimationFrame); - m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot)); - - g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon.hotspot / scale, scale); - - if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); + auto buf = makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); + setCursorBuffer(buf, icon.hotspot / scale, scale); + setAnimationTimer(m_iCurrentAnimationFrame, m_currentXcursor->images[m_iCurrentAnimationFrame].delay); + } else if (m_sCurrentCursorShapeData.images.size() > 1) { + m_iCurrentAnimationFrame++; - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_currentXcursor->images[m_iCurrentAnimationFrame].delay)); + if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) + m_iCurrentAnimationFrame = 0; - return; + auto hotspot = + Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale; + auto buf = 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}); + setCursorBuffer(buf, hotspot, m_fCursorScale); + setAnimationTimer(m_iCurrentAnimationFrame, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay); } - - if (m_sCurrentCursorShapeData.images.size() < 2 || !m_bOurBufferConnected) - return; - - m_iCurrentAnimationFrame++; - if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) - m_iCurrentAnimationFrame = 0; - - 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})); - - g_pPointerManager->setCursorBuffer( - getCursorBuffer(), - Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale, - m_fCursorScale); - - if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); - - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay)); } SCursorImageData CCursorManager::dataFor(const std::string& name) { @@ -278,11 +271,12 @@ SCursorImageData CCursorManager::dataFor(const std::string& name) { } void CCursorManager::setXWaylandCursor() { - const auto CURSOR = dataFor("left_ptr"); - if (CURSOR.surface) { + static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); + const auto CURSOR = dataFor("left_ptr"); + if (CURSOR.surface && *PUSEHYPRCURSOR) 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 { + else { auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale)); auto& icon = xcursor->images.front(); @@ -291,21 +285,25 @@ void CCursorManager::setXWaylandCursor() { } void CCursorManager::updateTheme() { - float highestScale = 1.0; + static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); + float highestScale = 1.0; for (auto& m : g_pCompositor->m_vMonitors) { if (m->scale > highestScale) highestScale = m->scale; } - if (m_sCurrentStyleInfo.size && m_pHyprcursor->valid()) - m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); + m_fCursorScale = highestScale; - m_sCurrentStyleInfo.size = std::round(m_iSize * highestScale); - m_fCursorScale = highestScale; + if (*PUSEHYPRCURSOR) { + if (m_sCurrentStyleInfo.size > 0 && m_pHyprcursor->valid()) + m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); - if (m_pHyprcursor->valid()) - m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo); + m_sCurrentStyleInfo.size = std::round(m_iSize * highestScale); + + if (m_pHyprcursor->valid()) + m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo); + } setCursorFromName("left_ptr"); @@ -316,24 +314,27 @@ void CCursorManager::updateTheme() { } bool CCursorManager::changeTheme(const std::string& name, const int size) { - auto options = Hyprcursor::SManagerOptions(); - options.logFn = hcLogger; - options.allowDefaultFallback = false; - - m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(name.empty() ? "" : name.c_str(), options); - if (m_pHyprcursor->valid()) { - m_szTheme = name; - m_iSize = size; - updateTheme(); - return true; - } - - Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", name); - - m_pXcursor->loadTheme(name, size); + static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); + m_szTheme = name.empty() ? "" : name; + m_iSize = size <= 0 ? 24 : size; + auto xcursor_theme = getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default"; + + if (*PUSEHYPRCURSOR) { + auto options = Hyprcursor::SManagerOptions(); + options.logFn = hcLogger; + options.allowDefaultFallback = false; + m_szTheme = name.empty() ? "" : name; + m_iSize = size; + + m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); + if (!m_pHyprcursor->valid()) { + Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); + m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); + } + } else + m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); - m_szTheme = name; - m_iSize = size; updateTheme(); + return true; }
\ No newline at end of file |
