Skip to content

Commit

Permalink
seatmgr: Add a grab class
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed May 14, 2024
1 parent 0cfdde3 commit fc72df8
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 188 deletions.
5 changes: 5 additions & 0 deletions src/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,11 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) {
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
return;

if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(pSurface)) {
Debug::log(LOG, "surface {:x} won't receive kb focus becuase grab rejected it", (uintptr_t)pSurface);
return;
}

const auto PLASTSURF = m_pLastFocus;

// Unfocus last surface if should
Expand Down
2 changes: 2 additions & 0 deletions src/desktop/LayerSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ void CLayerSurface::onMap() {
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained());

if (GRABSFOCUS) {
// TODO: use the new superb really very cool grab
g_pSeatManager->setGrab(nullptr);
g_pInputManager->releaseAllMouseButtons();
g_pCompositor->focusSurface(surface.wlr());

Expand Down
20 changes: 12 additions & 8 deletions src/desktop/Popup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void CPopup::initAllSignals() {
listeners.reposition = m_pResource->events.reposition.registerListener([this](std::any d) { this->onReposition(); });
listeners.map = m_pResource->surface->events.map.registerListener([this](std::any d) { this->onMap(); });
listeners.unmap = m_pResource->surface->events.unmap.registerListener([this](std::any d) { this->onUnmap(); });
listeners.dismissed = m_pResource->surface->events.unmap.registerListener([this](std::any d) { this->onUnmap(); });
listeners.destroy = m_pResource->surface->events.destroy.registerListener([this](std::any d) { this->onDestroy(); });
listeners.commit = m_pResource->surface->events.commit.registerListener([this](std::any d) { this->onCommit(); });
listeners.newPopup = m_pResource->surface->events.newPopup.registerListener([this](std::any d) { this->onNewPopup(std::any_cast<SP<CXDGPopupResource>>(d)); });
Expand All @@ -65,8 +66,9 @@ void CPopup::onDestroy() {
}

void CPopup::onMap() {
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
const auto COORDS = coordsGlobal();
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
const auto COORDS = coordsGlobal();
const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS);

CBox box;
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
Expand All @@ -79,8 +81,9 @@ void CPopup::onMap() {

m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);

unconstrain();
//unconstrain();
sendScale();
wlr_surface_send_enter(m_pResource->surface->surface, PMONITOR->output);

if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
Expand Down Expand Up @@ -178,7 +181,6 @@ void CPopup::unconstrain() {

CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
m_pResource->applyPositioning(box, COORDS - PMONITOR->vecPosition);
wlr_surface_send_enter(m_pResource->surface->surface, PMONITOR->output);
}

Vector2D CPopup::coordsRelativeToParent() {
Expand All @@ -190,8 +192,6 @@ Vector2D CPopup::coordsRelativeToParent() {
CPopup* current = this;
offset -= current->m_pResource->surface->current.geometry.pos();

offset -= m_pResource->surface->current.geometry.pos();

while (current->m_pParent && current->m_pResource) {

offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
Expand Down Expand Up @@ -293,11 +293,15 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
continue;

if (!allowsInput) {
const auto BOX = CBox{p->coordsGlobal(), p->size()};
const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{};
const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size();

const auto BOX = CBox{p->coordsGlobal() + offset, size};
if (BOX.containsPoint(globalCoords))
return p;
} else {
const auto REGION = CRegion{&p->m_sWLSurface.wlr()->current.input}.translate(p->coordsGlobal());
const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{};
const auto REGION = CRegion{&p->m_sWLSurface.wlr()->current.input}.translate(p->coordsGlobal() + offset);
if (REGION.containsPoint(globalCoords))
return p;
}
Expand Down
1 change: 1 addition & 0 deletions src/desktop/Popup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class CPopup {
CHyprSignalListener map;
CHyprSignalListener unmap;
CHyprSignalListener commit;
CHyprSignalListener dismissed;
CHyprSignalListener reposition;
} listeners;

Expand Down
73 changes: 73 additions & 0 deletions src/managers/SeatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,40 @@ void CSeatManager::sendTouchOrientation(int32_t id, double angle) {
}
}

void CSeatManager::refocusGrab() {
if (!seatGrab)
return;

if (seatGrab->surfs.size() > 0) {
// try to find a surf in focus first
const auto MOUSE = g_pInputManager->getMouseCoordsInternal();
for (auto& s : seatGrab->surfs) {
auto hlSurf = CWLSurface::surfaceFromWlr(s);
if (!hlSurf)
continue;

auto b = hlSurf->getSurfaceBoxGlobal();
if (!b.has_value())
continue;

if (!b->containsPoint(MOUSE))
continue;

if (seatGrab->keyboard)
setKeyboardFocus(s);
if (seatGrab->pointer)
setPointerFocus(s, MOUSE - b->pos());
return;
}

wlr_surface* surf = seatGrab->surfs.at(0);
if (seatGrab->keyboard)
setKeyboardFocus(surf);
if (seatGrab->pointer)
setPointerFocus(surf, {});
}
}

void CSeatManager::onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot) {
if (!state.pointerFocusResource || !seatResource || seatResource->client() != state.pointerFocusResource->client()) {
Debug::log(LOG, "[seatmgr] Rejecting a setCursor because the client ain't in focus");
Expand All @@ -389,3 +423,42 @@ void CSeatManager::onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial
SP<CWLSeatResource> CSeatManager::seatResourceForClient(wl_client* client) {
return PROTO::seat->seatResourceForClient(client);
}

void CSeatManager::setGrab(SP<CSeatGrab> grab) {
if (seatGrab) {
auto oldGrab = seatGrab;
seatGrab.reset();
g_pInputManager->refocus();
if (oldGrab->onEnd)
oldGrab->onEnd();
}

if (!grab)
return;

seatGrab = grab;

refocusGrab();
}

bool CSeatGrab::accepts(wlr_surface* surf) {
return std::find(surfs.begin(), surfs.end(), surf) != surfs.end();
}

void CSeatGrab::add(wlr_surface* surf) {
surfs.push_back(surf);
}

void CSeatGrab::remove(wlr_surface* surf) {
std::erase(surfs, surf);
if ((keyboard && g_pSeatManager->state.keyboardFocus == surf) || (pointer && g_pSeatManager->state.pointerFocus == surf))
g_pSeatManager->refocusGrab();
}

void CSeatGrab::setCallback(std::function<void()> onEnd_) {
onEnd = onEnd_;
}

void CSeatGrab::clear() {
surfs.clear();
}
37 changes: 37 additions & 0 deletions src/managers/SeatManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,37 @@ class CWLSeatResource;
class IPointer;
class IKeyboard;

/*
A seat grab defines a restricted set of surfaces that can be focused.
Only one grab can be active at a time
when a grab is removed, refocus() will happen
Different from a constraint.
When first set with setGrab, SeatManager will try to find a surface that is at the mouse pointer to focus,
from first added to last added. If none are, first is focused.
*/
class CSeatGrab {
public:
bool accepts(wlr_surface* surf);
void add(wlr_surface* surf);
void remove(wlr_surface* surf);
void setCallback(std::function<void()> onEnd_);
void clear();

bool keyboard = false;
bool pointer = false;
bool touch = false;

bool removeOnInput = true; // on hard input e.g. click outside, remove

private:
std::vector<wlr_surface*> surfs; // read-only
std::function<void()> onEnd;
friend class CSeatManager;
};

class CSeatManager {
public:
CSeatManager();
Expand Down Expand Up @@ -76,6 +107,9 @@ class CSeatManager {
WP<IPointer> mouse;
WP<IKeyboard> keyboard;

void setGrab(SP<CSeatGrab> grab); // nullptr removes
SP<CSeatGrab> seatGrab;

private:
struct SSeatResourceContainer {
SSeatResourceContainer(SP<CWLSeatResource>);
Expand All @@ -92,6 +126,8 @@ class CSeatManager {
void onNewSeatResource(SP<CWLSeatResource> resource);
SP<SSeatResourceContainer> containerForResource(SP<CWLSeatResource> seatResource);

void refocusGrab();

struct {
CHyprSignalListener newSeatResource;
} listeners;
Expand All @@ -101,6 +137,7 @@ class CSeatManager {
DYNLISTENER(touchSurfaceDestroy);

friend struct SSeatResourceContainer;
friend class CSeatGrab;
};

inline UP<CSeatManager> g_pSeatManager;
26 changes: 26 additions & 0 deletions src/managers/input/InputManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,26 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0)
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());

// grabs
if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(foundSurface)) {
if (m_bHardInput || refocus) {
g_pSeatManager->setGrab(nullptr);
return; // setGrab will refocus
} else {
// we need to grab the last surface.
foundSurface = g_pSeatManager->state.pointerFocus;

auto HLSurface = CWLSurface::surfaceFromWlr(foundSurface);

if (HLSurface) {
const auto BOX = HLSurface->getSurfaceBoxGlobal();

if (BOX.has_value())
surfacePos = BOX->pos();
}
}
}

if (!foundSurface) {
if (!m_bEmptyFocusCursorSet) {
if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) {
Expand Down Expand Up @@ -678,6 +698,12 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) {

if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor.get() && PMON)
g_pCompositor->setActiveMonitor(PMON);

if (g_pSeatManager->seatGrab && e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
m_bHardInput = true;
simulateMouseMovement();
m_bHardInput = false;
}
}

void CInputManager::processMouseDownKill(const IPointer::SButtonEvent& e) {
Expand Down
6 changes: 4 additions & 2 deletions src/managers/input/InputManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,12 @@ class CInputManager {
void releaseAllMouseButtons();

// for some bugs in follow mouse 0
bool m_bLastFocusOnLS = false;

bool m_bLastFocusOnLS = false;
bool m_bLastFocusOnIMEPopup = false;

// for hard input e.g. clicks
bool m_bHardInput = false;

// for hiding cursor on touch
bool m_bLastInputTouch = false;

Expand Down
Loading

0 comments on commit fc72df8

Please sign in to comment.