input: better cursor image infrastructure

Improves handling of cursor images/surfaces
Fixes an issue with decos and cursors
Fixes #3471
This commit is contained in:
Vaxry 2023-10-29 18:09:05 +00:00
parent af9440152e
commit 7a5234a0cc
7 changed files with 100 additions and 21 deletions

View file

@ -171,6 +171,10 @@ wlr_box CWindow::getWindowInputBox() {
return finalBox; return finalBox;
} }
wlr_box CWindow::getWindowMainSurfaceBox() {
return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y};
}
SWindowDecorationExtents CWindow::getFullWindowReservedArea() { SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
SWindowDecorationExtents extents; SWindowDecorationExtents extents;

View file

@ -339,6 +339,7 @@ class CWindow {
wlr_box getFullWindowBoundingBox(); wlr_box getFullWindowBoundingBox();
SWindowDecorationExtents getFullWindowExtents(); SWindowDecorationExtents getFullWindowExtents();
wlr_box getWindowInputBox(); wlr_box getWindowInputBox();
wlr_box getWindowMainSurfaceBox();
wlr_box getWindowIdealBoundingBoxIgnoreReserved(); wlr_box getWindowIdealBoundingBoxIgnoreReserved();
void updateWindowDecos(); void updateWindowDecos();
pid_t getPID(); pid_t getPID();

View file

@ -64,6 +64,8 @@ void CWLSurface::destroy() {
g_pCompositor->m_pLastFocus = nullptr; g_pCompositor->m_pLastFocus = nullptr;
if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface) if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
g_pInputManager->m_pLastMouseSurface = nullptr; g_pInputManager->m_pLastMouseSurface = nullptr;
if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
g_pInputManager->setCursorImageOverride("left_ptr");
m_pWLRSurface = nullptr; m_pWLRSurface = nullptr;

View file

@ -301,9 +301,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (g_pHyprRenderer->m_bHasARenderedCursor) { if (g_pHyprRenderer->m_bHasARenderedCursor) {
// TODO: maybe wrap? // TODO: maybe wrap?
if (m_ecbClickBehavior == CLICKMODE_KILL) if (m_ecbClickBehavior == CLICKMODE_KILL)
g_pHyprRenderer->setCursorFromName("crosshair"); setCursorImageOverride("crosshair");
else else
g_pHyprRenderer->setCursorFromName("left_ptr"); setCursorImageOverride("left_ptr");
} }
m_bEmptyFocusCursorSet = true; m_bEmptyFocusCursorSet = true;
@ -355,6 +355,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
return; return;
} }
if (pFoundWindow && foundSurface == pFoundWindow->m_pWLSurface.wlr() && !m_bCursorImageOverridden) {
const auto BOX = pFoundWindow->getWindowMainSurfaceBox();
if (!VECINRECT(mouseCoords, BOX.x, BOX.y, BOX.x + BOX.width, BOX.y + BOX.height))
setCursorImageOverride("left_ptr");
else
restoreCursorIconToApp();
}
if (pFoundWindow) { if (pFoundWindow) {
// change cursor icon if hovering over border // change cursor icon if hovering over border
if (*PRESIZEONBORDER && *PRESIZECURSORICON) { if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
@ -460,25 +468,65 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor) if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor)
return; return;
// cursorSurfaceInfo.pSurface = e->surface; if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
m_sCursorSurfaceInfo.wlSurface.unassign();
// if (e->surface) { if (e->surface) {
// hyprListener_CursorSurfaceDestroy.removeCallback(); m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
// hyprListener_CursorSurfaceDestroy.initCallback( m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
// &e->surface->events.destroy, [&](void* owner, void* data) { cursorSurfaceInfo.pSurface = nullptr; }, this, "InputManager"); m_sCursorSurfaceInfo.hidden = false;
// cursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y}; } else {
// } m_sCursorSurfaceInfo.vHotspot = {};
m_sCursorSurfaceInfo.hidden = true;
}
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) m_sCursorSurfaceInfo.name = "";
m_sCursorSurfaceInfo.inUse = true;
g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y); g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y);
}
} }
void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) { void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) {
if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked()) if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked())
return; return;
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
g_pHyprRenderer->setCursorFromName(wlr_cursor_shape_v1_name(e->shape)); m_sCursorSurfaceInfo.wlSurface.unassign();
m_sCursorSurfaceInfo.vHotspot = {};
m_sCursorSurfaceInfo.name = wlr_cursor_shape_v1_name(e->shape);
m_sCursorSurfaceInfo.hidden = false;
m_sCursorSurfaceInfo.inUse = true;
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
}
}
void CInputManager::restoreCursorIconToApp() {
if (m_sCursorSurfaceInfo.inUse)
return;
if (m_sCursorSurfaceInfo.hidden) {
g_pHyprRenderer->setCursorSurface(nullptr, 0, 0);
return;
}
if (m_sCursorSurfaceInfo.name.empty()) {
if (m_sCursorSurfaceInfo.wlSurface.exists())
g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface.wlr(), m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y);
} else {
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
}
m_sCursorSurfaceInfo.inUse = true;
}
void CInputManager::setCursorImageOverride(const std::string& name) {
if (m_bCursorImageOverridden)
return;
m_sCursorSurfaceInfo.inUse = false;
g_pHyprRenderer->setCursorFromName(name);
} }
bool CInputManager::cursorImageUnlocked() { bool CInputManager::cursorImageUnlocked() {
@ -1487,7 +1535,8 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
void CInputManager::setCursorImageUntilUnset(std::string name) { void CInputManager::setCursorImageUntilUnset(std::string name) {
g_pHyprRenderer->setCursorFromName(name.c_str()); g_pHyprRenderer->setCursorFromName(name.c_str());
m_bCursorImageOverridden = true; m_bCursorImageOverridden = true;
m_sCursorSurfaceInfo.inUse = false;
} }
void CInputManager::unsetCursorImage() { void CInputManager::unsetCursorImage() {
@ -1495,8 +1544,7 @@ void CInputManager::unsetCursorImage() {
return; return;
m_bCursorImageOverridden = false; m_bCursorImageOverridden = false;
if (!g_pHyprRenderer->m_bWindowRequestedCursorHide) restoreCursorIconToApp();
g_pHyprRenderer->setCursorFromName("left_ptr");
} }
std::string CInputManager::deviceNameToInternalString(std::string in) { std::string CInputManager::deviceNameToInternalString(std::string in) {

View file

@ -229,15 +229,22 @@ class CInputManager {
void setBorderCursorIcon(eBorderIconDirection); void setBorderCursorIcon(eBorderIconDirection);
void setCursorIconOnBorder(CWindow* w); void setCursorIconOnBorder(CWindow* w);
// temporary. Obeys setUntilUnset.
void setCursorImageOverride(const std::string& name);
// cursor surface // cursor surface
// struct cursorSI { struct cursorSI {
// wlr_surface* pSurface = nullptr; bool hidden = false; // null surface = hidden
// Vector2D vHotspot; CWLSurface wlSurface;
// bool bUsed = false; Vector2D vHotspot;
// } cursorSurfaceInfo; std::string name; // if not empty, means set by name.
// DYNLISTENER(CursorSurfaceDestroy); bool inUse = false;
} m_sCursorSurfaceInfo;
void restoreCursorIconToApp(); // no-op if restored
friend class CKeybindManager; friend class CKeybindManager;
friend class CWLSurface;
}; };
inline std::unique_ptr<CInputManager> g_pInputManager; inline std::unique_ptr<CInputManager> g_pInputManager;

View file

@ -1940,11 +1940,23 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY) { void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY) {
m_bCursorHasSurface = surf; m_bCursorHasSurface = surf;
if (surf == m_sLastCursorData.surf)
return;
m_sLastCursorData.name = "";
m_sLastCursorData.surf = surf;
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY);
} }
void CHyprRenderer::setCursorFromName(const std::string& name) { void CHyprRenderer::setCursorFromName(const std::string& name) {
m_bCursorHasSurface = true; m_bCursorHasSurface = true;
if (name == m_sLastCursorData.name)
return;
m_sLastCursorData.name = name;
m_sLastCursorData.surf = nullptr;
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str());
} }

View file

@ -83,6 +83,11 @@ class CHyprRenderer {
CTimer m_tRenderTimer; CTimer m_tRenderTimer;
struct {
wlr_surface* surf = nullptr;
std::string name;
} m_sLastCursorData;
private: private:
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*); void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*);
void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)