core: trigger hover and onclick only for the currently focused surface

This commit is contained in:
Maximilian Seidler 2025-04-11 10:38:39 +02:00
parent ca073eda74
commit 1fdb3367cb
17 changed files with 111 additions and 76 deletions

View file

@ -139,3 +139,7 @@ void CSessionLockSurface::onCallback() {
render(); render();
} }
} }
SP<CCWlSurface> CSessionLockSurface::getWlSurface() {
return surface;
}

View file

@ -26,6 +26,7 @@ class CSessionLockSurface {
void render(); void render();
void onCallback(); void onCallback();
void onScaleUpdate(); void onScaleUpdate();
SP<CCWlSurface> getWlSurface();
private: private:
WP<COutput> m_outputRef; WP<COutput> m_outputRef;

View file

@ -53,8 +53,19 @@ void CSeatManager::registerSeat(SP<CCWlSeat> seat) {
m_pCursorShape->setShape(wpCursorShapeDeviceV1Shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); m_pCursorShape->setShape(wpCursorShapeDeviceV1Shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
g_pHyprlock->m_vLastEnterCoords = {wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)}; g_pHyprlock->m_vLastEnterCoords = {wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)};
for (const auto& POUTPUT : g_pHyprlock->m_vOutputs) {
if (!POUTPUT->m_sessionLockSurface)
continue;
const auto& PWLSURFACE = POUTPUT->m_sessionLockSurface->getWlSurface();
if (PWLSURFACE->resource() == surf)
g_pHyprlock->m_focusedOutput = POUTPUT;
}
}); });
m_pPointer->setLeave([](CCWlPointer* r, uint32_t serial, wl_proxy* surf) { g_pHyprlock->m_focusedOutput.reset(); });
m_pPointer->setButton([](CCWlPointer* r, uint32_t serial, uint32_t time, uint32_t button, wl_pointer_button_state state) { m_pPointer->setButton([](CCWlPointer* r, uint32_t serial, uint32_t time, uint32_t button, wl_pointer_button_state state) {
g_pHyprlock->onClick(button, state == WL_POINTER_BUTTON_STATE_PRESSED, g_pHyprlock->m_vMouseLocation); g_pHyprlock->onClick(button, state == WL_POINTER_BUTTON_STATE_PRESSED, g_pHyprlock->m_vMouseLocation);
}); });

View file

@ -669,34 +669,37 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
} }
void CHyprlock::onClick(uint32_t button, bool down, const Vector2D& pos) { void CHyprlock::onClick(uint32_t button, bool down, const Vector2D& pos) {
for (auto& o : m_vOutputs) { if (!m_focusedOutput.lock())
if (!o->m_sessionLockSurface) return;
continue;
const auto widgets = g_pRenderer->getOrCreateWidgetsFor(*o->m_sessionLockSurface); // TODO: add the UNLIKELY marco from Hyprland
if (!m_focusedOutput->m_sessionLockSurface)
return;
const auto widgets = g_pRenderer->getOrCreateWidgetsFor(*m_focusedOutput->m_sessionLockSurface);
for (const auto& widget : widgets) { for (const auto& widget : widgets) {
if (widget->containsPoint(pos)) if (widget->containsPoint(pos))
widget->onClick(button, down, pos); widget->onClick(button, down, pos);
} }
} }
}
void CHyprlock::onHover(const Vector2D& pos) { void CHyprlock::onHover(const Vector2D& pos) {
if (!m_focusedOutput.lock())
return;
if (!m_focusedOutput->m_sessionLockSurface)
return;
bool outputNeedsRedraw = false;
bool cursorChanged = false; bool cursorChanged = false;
for (auto& o : m_vOutputs) { const auto widgets = g_pRenderer->getOrCreateWidgetsFor(*m_focusedOutput->m_sessionLockSurface);
if (!o->m_sessionLockSurface)
continue;
const auto widgets = g_pRenderer->getOrCreateWidgetsFor(*o->m_sessionLockSurface);
bool outputNeedsRedraw = false;
for (const auto& widget : widgets) { for (const auto& widget : widgets) {
const bool containsPoint = widget->containsPoint(pos); const bool CONTAINSPOINT = widget->containsPoint(pos);
const bool wasHovered = widget->isHovered(); const bool HOVERED = widget->isHovered();
if (containsPoint) { if (CONTAINSPOINT) {
if (!wasHovered) { if (!HOVERED) {
widget->setHover(true); widget->setHover(true);
widget->onHover(pos); widget->onHover(pos);
outputNeedsRedraw = true; outputNeedsRedraw = true;
@ -705,19 +708,17 @@ void CHyprlock::onHover(const Vector2D& pos) {
if (!cursorChanged) if (!cursorChanged)
cursorChanged = true; cursorChanged = true;
} else if (wasHovered) { } else if (HOVERED) {
widget->setHover(false); widget->setHover(false);
outputNeedsRedraw = true; outputNeedsRedraw = true;
} }
} }
if (outputNeedsRedraw) if (!cursorChanged)
o->m_sessionLockSurface->render();
}
if (!cursorChanged) {
g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
}
if (outputNeedsRedraw)
m_focusedOutput->m_sessionLockSurface->render();
} }
bool CHyprlock::acquireSessionLock() { bool CHyprlock::acquireSessionLock() {

View file

@ -99,6 +99,8 @@ class CHyprlock {
// //
std::chrono::system_clock::time_point m_tGraceEnds; std::chrono::system_clock::time_point m_tGraceEnds;
Vector2D m_vLastEnterCoords = {}; Vector2D m_vLastEnterCoords = {};
WP<COutput> m_focusedOutput;
Vector2D m_vMouseLocation = {}; Vector2D m_vMouseLocation = {};
std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr; std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr;

View file

@ -117,6 +117,6 @@ CFramebuffer::~CFramebuffer() {
release(); release();
} }
bool CFramebuffer::isAllocated() { bool CFramebuffer::isAllocated() const {
return m_iFb != (GLuint)-1; return m_iFb != (GLuint)-1;
} }

View file

@ -13,7 +13,7 @@ class CFramebuffer {
void bind() const; void bind() const;
void release(); void release();
void reset(); void reset();
bool isAllocated(); bool isAllocated() const;
Vector2D m_vSize; Vector2D m_vSize;

View file

@ -271,5 +271,5 @@ bool IWidget::isHovered() const {
} }
bool IWidget::containsPoint(const Vector2D& pos) const { bool IWidget::containsPoint(const Vector2D& pos) const {
return getBoundingBox().containsPoint(pos); return getBoundingBoxWl().containsPoint(pos);
} }

View file

@ -24,7 +24,7 @@ class IWidget {
static int roundingForBox(const CBox& box, int roundingConfig); static int roundingForBox(const CBox& box, int roundingConfig);
static int roundingForBorderBox(const CBox& borderBox, int roundingConfig, int thickness); static int roundingForBorderBox(const CBox& borderBox, int roundingConfig, int thickness);
virtual CBox getBoundingBox() const { virtual CBox getBoundingBoxWl() const {
return CBox(); return CBox();
}; };
virtual void onClick(uint32_t button, bool down, const Vector2D& pos) {} virtual void onClick(uint32_t button, bool down, const Vector2D& pos) {}

View file

@ -6,6 +6,7 @@
#include "../../config/ConfigDataValues.hpp" #include "../../config/ConfigDataValues.hpp"
#include <cmath> #include <cmath>
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include <hyprutils/math/Vector2D.hpp>
CImage::~CImage() { CImage::~CImage() {
reset(); reset();
@ -88,7 +89,7 @@ void CImage::configure(const std::unordered_map<std::string, std::any>& props, c
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding")); rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
border = std::any_cast<Hyprlang::INT>(props.at("border_size")); border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
color = *CGradientValueData::fromAnyPv(props.at("border_color")); color = *CGradientValueData::fromAnyPv(props.at("border_color"));
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport); configPos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
halign = std::any_cast<Hyprlang::STRING>(props.at("halign")); halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
valign = std::any_cast<Hyprlang::STRING>(props.at("valign")); valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate")); angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
@ -197,10 +198,10 @@ bool CImage::draw(const SRenderData& data) {
shadow.draw(data); shadow.draw(data);
const auto TEXPOS = posFromHVAlign(viewport, tex->m_vSize, pos, halign, valign, angle); pos = posFromHVAlign(viewport, tex->m_vSize, configPos, halign, valign, angle);
texbox.x = TEXPOS.x; texbox.x = pos.x;
texbox.y = TEXPOS.y; texbox.y = pos.y;
texbox.round(); texbox.round();
texbox.rot = angle; texbox.rot = angle;
@ -235,10 +236,14 @@ void CImage::renderUpdate() {
g_pHyprlock->renderOutput(stringPort); g_pHyprlock->renderOutput(stringPort);
} }
CBox CImage::getBoundingBox() const { CBox CImage::getBoundingBoxWl() const {
if (!asset) if (!imageFB.isAllocated())
return {pos.x, abs(pos.y - viewport.y), 0, 0}; return CBox{};
return {pos.x, abs(pos.y - viewport.y + asset->texture.m_vSize.y), asset->texture.m_vSize.x, asset->texture.m_vSize.y};
return {
Vector2D{pos.x, viewport.y - pos.y - imageFB.m_cTex.m_vSize.y},
imageFB.m_cTex.m_vSize,
};
} }
void CImage::onClick(uint32_t button, bool down, const Vector2D& pos) { void CImage::onClick(uint32_t button, bool down, const Vector2D& pos) {

View file

@ -24,7 +24,7 @@ class CImage : public IWidget {
virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput); virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput);
virtual bool draw(const SRenderData& data); virtual bool draw(const SRenderData& data);
virtual CBox getBoundingBox() const; virtual CBox getBoundingBoxWl() const;
virtual void onClick(uint32_t button, bool down, const Vector2D& pos); virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
virtual void onHover(const Vector2D& pos); virtual void onHover(const Vector2D& pos);
@ -45,6 +45,7 @@ class CImage : public IWidget {
double angle; double angle;
CGradientValueData color; CGradientValueData color;
Vector2D pos; Vector2D pos;
Vector2D configPos;
std::string halign, valign, path; std::string halign, valign, path;

View file

@ -174,10 +174,14 @@ void CLabel::renderUpdate() {
g_pHyprlock->renderOutput(outputStringPort); g_pHyprlock->renderOutput(outputStringPort);
} }
CBox CLabel::getBoundingBox() const { CBox CLabel::getBoundingBoxWl() const {
if (!asset) if (!asset)
return {pos.x, abs(pos.y - viewport.y), 0, 0}; return CBox{};
return {pos.x, abs(pos.y - viewport.y + asset->texture.m_vSize.y), asset->texture.m_vSize.x, asset->texture.m_vSize.y};
return {
Vector2D{pos.x, viewport.y - pos.y - asset->texture.m_vSize.y},
asset->texture.m_vSize,
};
} }
void CLabel::onClick(uint32_t button, bool down, const Vector2D& pos) { void CLabel::onClick(uint32_t button, bool down, const Vector2D& pos) {

View file

@ -21,7 +21,7 @@ class CLabel : public IWidget {
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput); virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
virtual bool draw(const SRenderData& data); virtual bool draw(const SRenderData& data);
virtual CBox getBoundingBox() const; virtual CBox getBoundingBoxWl() const;
virtual void onClick(uint32_t button, bool down, const Vector2D& pos); virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
virtual void onHover(const Vector2D& pos); virtual void onHover(const Vector2D& pos);

View file

@ -474,8 +474,11 @@ void CPasswordInputField::updateColors() {
colorState.font = fontTarget; colorState.font = fontTarget;
} }
CBox CPasswordInputField::getBoundingBox() const { CBox CPasswordInputField::getBoundingBoxWl() const {
return {pos.x, abs(pos.y - viewport.y + size->value().y), size->value().x, size->value().y}; return {
Vector2D{pos.x, viewport.y - pos.y - size->value().y},
size->value(),
};
} }
void CPasswordInputField::onHover(const Vector2D& pos) { void CPasswordInputField::onHover(const Vector2D& pos) {

View file

@ -24,7 +24,7 @@ class CPasswordInputField : public IWidget {
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput); virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
virtual bool draw(const SRenderData& data); virtual bool draw(const SRenderData& data);
virtual void onHover(const Vector2D& pos); virtual void onHover(const Vector2D& pos);
virtual CBox getBoundingBox() const; virtual CBox getBoundingBoxWl() const;
void reset(); void reset();
void onFadeOutTimer(); void onFadeOutTimer();

View file

@ -4,6 +4,7 @@
#include "../../core/hyprlock.hpp" #include "../../core/hyprlock.hpp"
#include <cmath> #include <cmath>
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include <sys/types.h>
void CShape::registerSelf(const SP<CShape>& self) { void CShape::registerSelf(const SP<CShape>& self) {
m_self = self; m_self = self;
@ -102,9 +103,11 @@ bool CShape::draw(const SRenderData& data) {
return data.opacity < 1.0; return data.opacity < 1.0;
} }
CBox CShape::getBoundingBoxWl() const {
CBox CShape::getBoundingBox() const { return {
return {pos.x, abs(pos.y - viewport.y + size.y), size.x, size.y}; Vector2D{pos.x, viewport.y - pos.y - size.y},
size,
};
} }
void CShape::onClick(uint32_t button, bool down, const Vector2D& pos) { void CShape::onClick(uint32_t button, bool down, const Vector2D& pos) {

View file

@ -18,7 +18,7 @@ class CShape : public IWidget {
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput); virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
virtual bool draw(const SRenderData& data); virtual bool draw(const SRenderData& data);
virtual CBox getBoundingBox() const; virtual CBox getBoundingBoxWl() const;
virtual void onClick(uint32_t button, bool down, const Vector2D& pos); virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
virtual void onHover(const Vector2D& pos); virtual void onHover(const Vector2D& pos);