mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 16:05:58 +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;
|
||||
}
|
||||
|
||||
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 extents;
|
||||
|
||||
|
|
|
@ -339,6 +339,7 @@ class CWindow {
|
|||
wlr_box getFullWindowBoundingBox();
|
||||
SWindowDecorationExtents getFullWindowExtents();
|
||||
wlr_box getWindowInputBox();
|
||||
wlr_box getWindowMainSurfaceBox();
|
||||
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void updateWindowDecos();
|
||||
pid_t getPID();
|
||||
|
|
|
@ -64,6 +64,8 @@ void CWLSurface::destroy() {
|
|||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
||||
g_pInputManager->m_pLastMouseSurface = nullptr;
|
||||
if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
||||
g_pInputManager->setCursorImageOverride("left_ptr");
|
||||
|
||||
m_pWLRSurface = nullptr;
|
||||
|
||||
|
|
|
@ -301,9 +301,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
if (g_pHyprRenderer->m_bHasARenderedCursor) {
|
||||
// TODO: maybe wrap?
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL)
|
||||
g_pHyprRenderer->setCursorFromName("crosshair");
|
||||
setCursorImageOverride("crosshair");
|
||||
else
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
setCursorImageOverride("left_ptr");
|
||||
}
|
||||
|
||||
m_bEmptyFocusCursorSet = true;
|
||||
|
@ -355,6 +355,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
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) {
|
||||
// change cursor icon if hovering over border
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
||||
|
@ -460,25 +468,65 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
|
|||
if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor)
|
||||
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) {
|
||||
// hyprListener_CursorSurfaceDestroy.removeCallback();
|
||||
// hyprListener_CursorSurfaceDestroy.initCallback(
|
||||
// &e->surface->events.destroy, [&](void* owner, void* data) { cursorSurfaceInfo.pSurface = nullptr; }, this, "InputManager");
|
||||
// cursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
// }
|
||||
if (e->surface) {
|
||||
m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
|
||||
m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
m_sCursorSurfaceInfo.hidden = false;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) {
|
||||
if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked())
|
||||
return;
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
||||
g_pHyprRenderer->setCursorFromName(wlr_cursor_shape_v1_name(e->shape));
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
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() {
|
||||
|
@ -1487,7 +1535,8 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
|
|||
|
||||
void CInputManager::setCursorImageUntilUnset(std::string name) {
|
||||
g_pHyprRenderer->setCursorFromName(name.c_str());
|
||||
m_bCursorImageOverridden = true;
|
||||
m_bCursorImageOverridden = true;
|
||||
m_sCursorSurfaceInfo.inUse = false;
|
||||
}
|
||||
|
||||
void CInputManager::unsetCursorImage() {
|
||||
|
@ -1495,8 +1544,7 @@ void CInputManager::unsetCursorImage() {
|
|||
return;
|
||||
|
||||
m_bCursorImageOverridden = false;
|
||||
if (!g_pHyprRenderer->m_bWindowRequestedCursorHide)
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
restoreCursorIconToApp();
|
||||
}
|
||||
|
||||
std::string CInputManager::deviceNameToInternalString(std::string in) {
|
||||
|
|
|
@ -229,15 +229,22 @@ class CInputManager {
|
|||
void setBorderCursorIcon(eBorderIconDirection);
|
||||
void setCursorIconOnBorder(CWindow* w);
|
||||
|
||||
// temporary. Obeys setUntilUnset.
|
||||
void setCursorImageOverride(const std::string& name);
|
||||
|
||||
// cursor surface
|
||||
// struct cursorSI {
|
||||
// wlr_surface* pSurface = nullptr;
|
||||
// Vector2D vHotspot;
|
||||
// bool bUsed = false;
|
||||
// } cursorSurfaceInfo;
|
||||
// DYNLISTENER(CursorSurfaceDestroy);
|
||||
struct cursorSI {
|
||||
bool hidden = false; // null surface = hidden
|
||||
CWLSurface wlSurface;
|
||||
Vector2D vHotspot;
|
||||
std::string name; // if not empty, means set by name.
|
||||
bool inUse = false;
|
||||
} m_sCursorSurfaceInfo;
|
||||
|
||||
void restoreCursorIconToApp(); // no-op if restored
|
||||
|
||||
friend class CKeybindManager;
|
||||
friend class CWLSurface;
|
||||
};
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
void CHyprRenderer::setCursorFromName(const std::string& name) {
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,11 @@ class CHyprRenderer {
|
|||
|
||||
CTimer m_tRenderTimer;
|
||||
|
||||
struct {
|
||||
wlr_surface* surf = nullptr;
|
||||
std::string name;
|
||||
} m_sLastCursorData;
|
||||
|
||||
private:
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue