mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-26 07:26:00 +01:00
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:
parent
af9440152e
commit
7a5234a0cc
7 changed files with 100 additions and 21 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue