summaryrefslogtreecommitdiff
path: root/src/managers/CursorManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/managers/CursorManager.cpp')
-rw-r--r--src/managers/CursorManager.cpp345
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