From 46dab01bcc47b2e29f36cd4d35d04091e4134a67 Mon Sep 17 00:00:00 2001 From: Mozzarella32 <143010987+Mozzarella32@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:22:50 +0200 Subject: [PATCH] renderer: add more uniforms to the screen shader (#11986) These are: pointer_shape from the cursor-shape-v1 protocol prepared for v2, along with left_ptr...bottom_right_corner and killing (Hyprland specific) pointer_shape_previous with pointer_switch_time to blend between shapes pointer_size scaled size as used by the normal cursor pointer_pressed_positions[32] with pointer_pressed_times[32] and pointer_pressed_killed(32 bits) for click/touch animations and if they killed something pointer_inactive_timeout with pointer_last_active to smoothly fade the pointer out pointer_hidden to hide it when the cursor is hidden (excluding by cursor:invisible as this config value can be used to turn off the normal cursor, which is useful when drawing it with the screen shader) --- src/helpers/CursorShapes.hpp | 2 +- src/macros.hpp | 3 + src/managers/CursorManager.cpp | 4 + src/managers/CursorManager.hpp | 2 + src/managers/input/InputManager.cpp | 5 +- src/managers/input/Touch.cpp | 2 + src/render/OpenGL.cpp | 154 ++++++++++++++++++++++++---- src/render/OpenGL.hpp | 6 ++ src/render/Renderer.cpp | 41 +++++++- src/render/Renderer.hpp | 9 +- src/render/Shader.hpp | 12 +++ 11 files changed, 215 insertions(+), 25 deletions(-) diff --git a/src/helpers/CursorShapes.hpp b/src/helpers/CursorShapes.hpp index 6f3c8a0ea..cb95cd8b0 100644 --- a/src/helpers/CursorShapes.hpp +++ b/src/helpers/CursorShapes.hpp @@ -40,4 +40,4 @@ constexpr std::array CURSOR_SHAPE_NAMES = { "zoom-in", "zoom-out", }; -// clang-format on \ No newline at end of file +// clang-format on diff --git a/src/macros.hpp b/src/macros.hpp index 851f1ca35..7fa25cfb3 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -31,6 +31,9 @@ #define MIN_WINDOW_SIZE 20.0 +// max value 32 because killed is a int uniform +#define POINTER_PRESSED_HISTORY_LENGTH 32 + #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ inline wl_listener listen_##name = {.notify = listener_##name} diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 442da4432..d2905a1e3 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -342,3 +342,7 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { void CCursorManager::syncGsettings() { m_xcursor->syncGsettings(); } + +float CCursorManager::getScaledSize() const { + return m_size * m_cursorScale; +} diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 03420dab4..dd3238af4 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -55,6 +55,8 @@ class CCursorManager { void tickAnimatedCursor(); + float getScaledSize() const; + private: bool m_ourBufferConnected = false; std::vector> m_cursorBuffers; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 63e081543..ae355b4b2 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../../config/ConfigValue.hpp" #include "../../config/ConfigManager.hpp" #include "../../desktop/Window.hpp" @@ -716,7 +717,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { case CLICKMODE_DEFAULT: Debug::log(LOG, "SetClickMode: DEFAULT"); m_clickBehavior = CLICKMODE_DEFAULT; - g_pHyprRenderer->setCursorFromName("left_ptr"); + g_pHyprRenderer->setCursorFromName("left_ptr", true); break; case CLICKMODE_KILL: @@ -728,7 +729,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { refocus(); // set cursor - g_pHyprRenderer->setCursorFromName("crosshair"); + g_pHyprRenderer->setCursorFromName("crosshair", true); break; default: break; } diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 2d3842f90..631bd569a 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -124,6 +124,8 @@ void CInputManager::onTouchUp(ITouch::SUpEvent e) { void CInputManager::onTouchMove(ITouch::SMotionEvent e) { m_lastInputTouch = true; + m_lastCursorMovement.reset(); + EMIT_HOOK_EVENT_CANCELLABLE("touchMove", e); if (g_pUnifiedWorkspaceSwipe->isGestureInProgress()) { // Do nothing if this is using a different finger. diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 3c30c4a1e..436ba26c4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -9,6 +9,7 @@ #include "Renderer.hpp" #include "../Compositor.hpp" #include "../helpers/MiscFunctions.hpp" +#include "../helpers/CursorShapes.hpp" #include "../config/ConfigValue.hpp" #include "../config/ConfigManager.hpp" #include "../managers/PointerManager.hpp" @@ -20,6 +21,7 @@ #include "../managers/HookSystemManager.hpp" #include "../managers/input/InputManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" +#include "../managers/CursorManager.hpp" #include "../helpers/fs/FsUtils.hpp" #include "../helpers/MainLoopExecutor.hpp" #include "debug/HyprNotificationOverlay.hpp" @@ -30,6 +32,8 @@ #include "pass/ClearPassElement.hpp" #include "render/Shader.hpp" #include "AsyncResourceGatherer.hpp" +#include +#include #include #include #include @@ -381,6 +385,50 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmRenderNode.fd > m_globalTimer.reset(); pushMonitorTransformEnabled(false); + + static auto addLastPressToHistory = [this](const Vector2D& pos, bool killing, bool touch) { + // shift the new pos and time in + std::ranges::rotate(m_pressedHistoryPositions, m_pressedHistoryPositions.end() - 1); + m_pressedHistoryPositions[0] = pos; + + std::ranges::rotate(m_pressedHistoryTimers, m_pressedHistoryTimers.end() - 1); + m_pressedHistoryTimers[0].reset(); + + // shift killed flag in + m_pressedHistoryKilled <<= 1; + m_pressedHistoryKilled |= killing ? 1 : 0; +#if POINTER_PRESSED_HISTORY_LENGTH < 32 + m_pressedHistoryKilled &= (1 >> POINTER_PRESSED_HISTORY_LENGTH) - 1; +#endif + + // shift touch flag in + m_pressedHistoryTouched <<= 1; + m_pressedHistoryTouched |= touch ? 1 : 0; +#if POINTER_PRESSED_HISTORY_LENGTH < 32 + m_pressedHistoryTouched &= (1 >> POINTER_PRESSED_HISTORY_LENGTH) - 1; +#endif + }; + + static auto P2 = g_pHookSystem->hookDynamic("mouseButton", [](void* self, SCallbackInfo& info, std::any e) { + auto E = std::any_cast(e); + + if (E.state != WL_POINTER_BUTTON_STATE_PRESSED) + return; + + addLastPressToHistory(g_pInputManager->getMouseCoordsInternal(), g_pInputManager->getClickMode() == CLICKMODE_KILL, false); + }); + + static auto P3 = g_pHookSystem->hookDynamic("touchDown", [](void* self, SCallbackInfo& info, std::any e) { + auto E = std::any_cast(e); + + auto PMONITOR = g_pCompositor->getMonitorFromName(!E.device->m_boundOutput.empty() ? E.device->m_boundOutput : ""); + + PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_lastMonitor.lock(); + + const auto TOUCH_COORDS = PMONITOR->m_position + (E.pos * PMONITOR->m_size); + + addLastPressToHistory(TOUCH_COORDS, g_pInputManager->getClickMode() == CLICKMODE_KILL, true); + }); } CHyprOpenGLImpl::~CHyprOpenGLImpl() { @@ -1240,30 +1288,59 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { return; } - m_finalScreenShader.uniformLocations[SHADER_POINTER] = glGetUniformLocation(m_finalScreenShader.program, "pointer_position"); - m_finalScreenShader.uniformLocations[SHADER_PROJ] = glGetUniformLocation(m_finalScreenShader.program, "proj"); - m_finalScreenShader.uniformLocations[SHADER_TEX] = glGetUniformLocation(m_finalScreenShader.program, "tex"); - m_finalScreenShader.uniformLocations[SHADER_TIME] = glGetUniformLocation(m_finalScreenShader.program, "time"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_HIDDEN] = glGetUniformLocation(m_finalScreenShader.program, "pointer_hidden"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_KILLING] = glGetUniformLocation(m_finalScreenShader.program, "pointer_killing"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_SHAPE] = glGetUniformLocation(m_finalScreenShader.program, "pointer_shape"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_SHAPE_PREVIOUS] = glGetUniformLocation(m_finalScreenShader.program, "pointer_shape_previous"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_SWITCH_TIME] = glGetUniformLocation(m_finalScreenShader.program, "pointer_switch_time"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_POSITIONS] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_positions"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_TIMES] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_times"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_KILLED] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_killed"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_TOUCHED] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_touched"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_INACTIVE_TIMEOUT] = glGetUniformLocation(m_finalScreenShader.program, "pointer_inactive_timeout"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_LAST_ACTIVE] = glGetUniformLocation(m_finalScreenShader.program, "pointer_last_active"); + m_finalScreenShader.uniformLocations[SHADER_POINTER_SIZE] = glGetUniformLocation(m_finalScreenShader.program, "pointer_size"); + m_finalScreenShader.uniformLocations[SHADER_POINTER] = glGetUniformLocation(m_finalScreenShader.program, "pointer_position"); + m_finalScreenShader.uniformLocations[SHADER_PROJ] = glGetUniformLocation(m_finalScreenShader.program, "proj"); + m_finalScreenShader.uniformLocations[SHADER_TEX] = glGetUniformLocation(m_finalScreenShader.program, "tex"); + m_finalScreenShader.uniformLocations[SHADER_TIME] = glGetUniformLocation(m_finalScreenShader.program, "time"); if (m_finalScreenShader.uniformLocations[SHADER_TIME] != -1) m_finalScreenShader.initialTime = m_globalTimer.getSeconds(); m_finalScreenShader.uniformLocations[SHADER_WL_OUTPUT] = glGetUniformLocation(m_finalScreenShader.program, "wl_output"); m_finalScreenShader.uniformLocations[SHADER_FULL_SIZE] = glGetUniformLocation(m_finalScreenShader.program, "screen_size"); if (m_finalScreenShader.uniformLocations[SHADER_FULL_SIZE] == -1) m_finalScreenShader.uniformLocations[SHADER_FULL_SIZE] = glGetUniformLocation(m_finalScreenShader.program, "screenSize"); - if (m_finalScreenShader.uniformLocations[SHADER_TIME] != -1 && *PDT != 0 && !g_pHyprRenderer->m_crashingInProgress) { - // The screen shader uses the "time" uniform - // Since the screen shader could change every frame, damage tracking *needs* to be disabled - g_pConfigManager->addParseError("Screen shader: Screen shader uses uniform 'time', which requires debug:damage_tracking to be switched off.\n" - "WARNING: Disabling damage tracking will *massively* increase GPU utilization!"); - } m_finalScreenShader.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(m_finalScreenShader.program, "texcoord"); m_finalScreenShader.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(m_finalScreenShader.program, "pos"); - if (m_finalScreenShader.uniformLocations[SHADER_POINTER] != -1 && *PDT != 0 && !g_pHyprRenderer->m_crashingInProgress) { - // The screen shader uses the "pointer_position" uniform + + static auto uniformRequireNoDamage = [this](eShaderUniform uniform, const std::string& name) { + if (*PDT == 0) + return; + if (m_finalScreenShader.uniformLocations[uniform] == -1) + return; + + // The screen shader uses the uniform // Since the screen shader could change every frame, damage tracking *needs* to be disabled - g_pConfigManager->addParseError("Screen shader: Screen shader uses uniform 'pointerPosition', which requires debug:damage_tracking to be switched off.\n" - "WARNING: Disabling damage tracking will *massively* increase GPU utilization!"); - } + g_pConfigManager->addParseError(std::format("Screen shader: Screen shader uses uniform '{}', which requires debug:damage_tracking to be switched off.\n" + "WARNING:(Disabling damage tracking will *massively* increase GPU utilization!", + name)); + }; + + // Allow glitch shader to use time uniform whighout damage tracking + if (!g_pHyprRenderer->m_crashingInProgress) + uniformRequireNoDamage(SHADER_TIME, "time"); + + uniformRequireNoDamage(SHADER_POINTER, "pointer_position"); + uniformRequireNoDamage(SHADER_POINTER_PRESSED_POSITIONS, "pointer_pressed_positions"); + uniformRequireNoDamage(SHADER_POINTER_PRESSED_TIMES, "pointer_pressed_times"); + uniformRequireNoDamage(SHADER_POINTER_PRESSED_KILLED, "pointer_pressed_killed"); + uniformRequireNoDamage(SHADER_POINTER_PRESSED_TOUCHED, "pointer_pressed_touched"); + uniformRequireNoDamage(SHADER_POINTER_LAST_ACTIVE, "pointer_last_active"); + uniformRequireNoDamage(SHADER_POINTER_HIDDEN, "pointer_hidden"); + uniformRequireNoDamage(SHADER_POINTER_KILLING, "pointer_killing"); + uniformRequireNoDamage(SHADER_POINTER_SHAPE, "pointer_shape"); + uniformRequireNoDamage(SHADER_POINTER_SHAPE_PREVIOUS, "pointer_shape_previous"); + m_finalScreenShader.createVao(); } @@ -1539,9 +1616,10 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c CBox newBox = box; m_renderData.renderModif.applyToBox(newBox); - static const auto PDT = CConfigValue("debug:damage_tracking"); - static const auto PPASS = CConfigValue("render:cm_fs_passthrough"); - static const auto PENABLECM = CConfigValue("render:cm_enabled"); + static const auto PDT = CConfigValue("debug:damage_tracking"); + static const auto PPASS = CConfigValue("render:cm_fs_passthrough"); + static const auto PENABLECM = CConfigValue("render:cm_enabled"); + static const auto PCURSORTIMEOUT = CConfigValue("cursor:inactive_timeout"); // get the needed transform for this texture const bool TRANSFORMS_MATCH = wlTransformToHyprutils(m_renderData.pMonitor->m_transform) == tex->m_transform; // FIXME: combine them properly!!! @@ -1639,6 +1717,12 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c if (usingFinalShader) { shader->setUniformInt(SHADER_WL_OUTPUT, m_renderData.pMonitor->m_id); shader->setUniformFloat2(SHADER_FULL_SIZE, m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y); + shader->setUniformFloat(SHADER_POINTER_INACTIVE_TIMEOUT, *PCURSORTIMEOUT); + shader->setUniformInt(SHADER_POINTER_HIDDEN, g_pHyprRenderer->m_cursorHiddenByCondition); + shader->setUniformInt(SHADER_POINTER_KILLING, g_pInputManager->getClickMode() == CLICKMODE_KILL); + shader->setUniformInt(SHADER_POINTER_SHAPE, g_pHyprRenderer->m_lastCursorData.shape); + shader->setUniformInt(SHADER_POINTER_SHAPE_PREVIOUS, g_pHyprRenderer->m_lastCursorData.shapePrevious); + shader->setUniformFloat(SHADER_POINTER_SIZE, g_pCursorManager->getScaledSize()); } if (usingFinalShader && *PDT == 0) { @@ -1646,9 +1730,41 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c Vector2D p = ((g_pInputManager->getMouseCoordsInternal() - pMonitor->m_position) * pMonitor->m_scale); p = p.transform(wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize); shader->setUniformFloat2(SHADER_POINTER, p.x / pMonitor->m_pixelSize.x, p.y / pMonitor->m_pixelSize.y); - } else if (usingFinalShader) + + std::vector pressedPos = m_pressedHistoryPositions | std::views::transform([&](const Vector2D& vec) { + Vector2D pPressed = ((vec - pMonitor->m_position) * pMonitor->m_scale); + pPressed = pPressed.transform(wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize); + return std::array{pPressed.x / pMonitor->m_pixelSize.x, pPressed.y / pMonitor->m_pixelSize.y}; + }) | + std::views::join | std::ranges::to>(); + + shader->setUniform2fv(SHADER_POINTER_PRESSED_POSITIONS, pressedPos.size(), pressedPos); + + std::vector pressedTime = + m_pressedHistoryTimers | std::views::transform([](const CTimer& timer) { return timer.getSeconds(); }) | std::ranges::to>(); + + shader->setUniform1fv(SHADER_POINTER_PRESSED_TIMES, pressedTime.size(), pressedTime); + + shader->setUniformInt(SHADER_POINTER_PRESSED_KILLED, m_pressedHistoryKilled); + shader->setUniformInt(SHADER_POINTER_PRESSED_TOUCHED, m_pressedHistoryTouched); + + shader->setUniformFloat(SHADER_POINTER_LAST_ACTIVE, g_pInputManager->m_lastCursorMovement.getSeconds()); + shader->setUniformFloat(SHADER_POINTER_SWITCH_TIME, g_pHyprRenderer->m_lastCursorData.switchedTimer.getSeconds()); + + } else if (usingFinalShader) { shader->setUniformFloat2(SHADER_POINTER, 0.f, 0.f); + static const std::vector pressedPosDefault(POINTER_PRESSED_HISTORY_LENGTH * 2uz, 0.f); + static const std::vector pressedTimeDefault(POINTER_PRESSED_HISTORY_LENGTH, 0.f); + + shader->setUniform2fv(SHADER_POINTER_PRESSED_POSITIONS, pressedPosDefault.size(), pressedPosDefault); + shader->setUniform1fv(SHADER_POINTER_PRESSED_TIMES, pressedTimeDefault.size(), pressedTimeDefault); + shader->setUniformInt(SHADER_POINTER_PRESSED_KILLED, 0); + + shader->setUniformFloat(SHADER_POINTER_LAST_ACTIVE, 0.f); + shader->setUniformFloat(SHADER_POINTER_SWITCH_TIME, 0.f); + } + if (CRASHING) { shader->setUniformFloat(SHADER_DISTORT, g_pHyprRenderer->m_crashingDistort); shader->setUniformFloat2(SHADER_FULL_SIZE, m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index a6dbd3393..45ed28dd4 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -390,6 +390,12 @@ class CHyprOpenGLImpl { void initMissingAssetTexture(); void requestBackgroundResource(); + // for the final shader + std::array m_pressedHistoryTimers = {}; + std::array m_pressedHistoryPositions = {}; + GLint m_pressedHistoryKilled = 0; + GLint m_pressedHistoryTouched = 0; + // std::optional> getModsForFormat(EGLint format); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e4b4bf5e8..446c4bc4d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -26,6 +26,7 @@ #include "../hyprerror/HyprError.hpp" #include "../debug/HyprDebugOverlay.hpp" #include "../debug/HyprNotificationOverlay.hpp" +#include "helpers/CursorShapes.hpp" #include "helpers/Monitor.hpp" #include "pass/TexPassElement.hpp" #include "pass/ClearPassElement.hpp" @@ -2042,6 +2043,42 @@ void CHyprRenderer::setCursorFromName(const std::string& name, bool force) { return; m_lastCursorData.name = name; + + static auto getShapeOrDefault = [](std::string_view name) -> wpCursorShapeDeviceV1Shape { + const auto it = std::ranges::find(CURSOR_SHAPE_NAMES, name); + + if (it == CURSOR_SHAPE_NAMES.end()) { + // clang-format off + static const auto overrites = std::unordered_map { + {"top_side", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE}, + {"bottom_side", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE}, + {"left_side", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE}, + {"right_side", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE}, + {"top_left_corner", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE}, + {"bottom_left_corner", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE}, + {"top_right_corner", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE}, + {"bottom_right_corner", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE}, + }; + // clang-format on + + if (overrites.contains(name)) + return overrites.at(name); + + return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT; + } + + return sc(std::distance(CURSOR_SHAPE_NAMES.begin(), it)); + }; + + const auto newShape = getShapeOrDefault(name); + + if (newShape != m_lastCursorData.shape) { + m_lastCursorData.shapePrevious = m_lastCursorData.shape; + m_lastCursorData.switchedTimer.reset(); + } + + m_lastCursorData.shape = newShape; + m_lastCursorData.surf.reset(); if (m_cursorHidden && !force) @@ -2066,7 +2103,9 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (*PCURSORTIMEOUT > 0) m_cursorHiddenConditions.hiddenOnTimeout = *PCURSORTIMEOUT < g_pInputManager->m_lastCursorMovement.getSeconds(); - const bool HIDE = m_cursorHiddenConditions.hiddenOnTimeout || m_cursorHiddenConditions.hiddenOnTouch || m_cursorHiddenConditions.hiddenOnKeyboard || (*PINVISIBLE != 0); + m_cursorHiddenByCondition = m_cursorHiddenConditions.hiddenOnTimeout || m_cursorHiddenConditions.hiddenOnTouch || m_cursorHiddenConditions.hiddenOnKeyboard; + + const bool HIDE = m_cursorHiddenByCondition || (*PINVISIBLE != 0); if (HIDE == m_cursorHidden) return; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 511eeb9b1..1980984d2 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -9,6 +9,7 @@ #include "../helpers/time/Timer.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/time/Time.hpp" +#include "../../protocols/cursor-shape-v1.hpp" struct SMonitorRule; class CWorkspace; @@ -108,8 +109,11 @@ class CHyprRenderer { std::vector m_usedAsyncBuffers; struct { - int hotspotX = 0; - int hotspotY = 0; + int hotspotX = 0; + int hotspotY = 0; + wpCursorShapeDeviceV1Shape shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT; + wpCursorShapeDeviceV1Shape shapePrevious = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT; + CTimer switchedTimer; std::optional> surf; std::string name; } m_lastCursorData; @@ -139,6 +143,7 @@ class CHyprRenderer { bool shouldBlur(WP p); bool m_cursorHidden = false; + bool m_cursorHiddenByCondition = false; bool m_cursorHasSurface = false; SP m_currentRenderbuffer = nullptr; SP m_currentBuffer = nullptr; diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 780b7fa8b..4f5456426 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -63,6 +63,18 @@ enum eShaderUniform : uint8_t { SHADER_BRIGHTNESS, SHADER_NOISE, SHADER_POINTER, + SHADER_POINTER_SHAPE, + SHADER_POINTER_SWITCH_TIME, + SHADER_POINTER_SHAPE_PREVIOUS, + SHADER_POINTER_PRESSED_POSITIONS, + SHADER_POINTER_HIDDEN, + SHADER_POINTER_KILLING, + SHADER_POINTER_PRESSED_TIMES, + SHADER_POINTER_PRESSED_KILLED, + SHADER_POINTER_PRESSED_TOUCHED, + SHADER_POINTER_INACTIVE_TIMEOUT, + SHADER_POINTER_LAST_ACTIVE, + SHADER_POINTER_SIZE, SHADER_LAST, };