seatmgr: Add a grab class
This commit is contained in:
parent
0cfdde3d1a
commit
fc72df8e58
12 changed files with 257 additions and 188 deletions
|
|
@ -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");
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -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>);
|
||||
|
|
@ -92,6 +126,8 @@ class CSeatManager {
|
|||
void onNewSeatResource(SP<CWLSeatResource> resource);
|
||||
SP<SSeatResourceContainer> containerForResource(SP<CWLSeatResource> seatResource);
|
||||
|
||||
void refocusGrab();
|
||||
|
||||
struct {
|
||||
CHyprSignalListener newSeatResource;
|
||||
} listeners;
|
||||
|
|
@ -101,6 +137,7 @@ class CSeatManager {
|
|||
DYNLISTENER(touchSurfaceDestroy);
|
||||
|
||||
friend struct SSeatResourceContainer;
|
||||
friend class CSeatGrab;
|
||||
};
|
||||
|
||||
inline UP<CSeatManager> g_pSeatManager;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue