mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-25 18:29:51 +01:00
seatmgr: Add a grab class
This commit is contained in:
parent
9bf894052c
commit
c92dfdf0e4
12 changed files with 269 additions and 188 deletions
|
@ -1025,6 +1025,11 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) {
|
||||||
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
|
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
|
||||||
return;
|
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;
|
const auto PLASTSURF = m_pLastFocus;
|
||||||
|
|
||||||
// Unfocus last surface if should
|
// Unfocus last surface if should
|
||||||
|
|
|
@ -136,6 +136,8 @@ void CLayerSurface::onMap() {
|
||||||
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained());
|
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained());
|
||||||
|
|
||||||
if (GRABSFOCUS) {
|
if (GRABSFOCUS) {
|
||||||
|
// TODO: use the new superb really very cool grab
|
||||||
|
g_pSeatManager->setGrab(nullptr);
|
||||||
g_pInputManager->releaseAllMouseButtons();
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
g_pCompositor->focusSurface(surface.wlr());
|
g_pCompositor->focusSurface(surface.wlr());
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ void CPopup::initAllSignals() {
|
||||||
listeners.reposition = m_pResource->events.reposition.registerListener([this](std::any d) { this->onReposition(); });
|
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.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.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.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.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)); });
|
listeners.newPopup = m_pResource->surface->events.newPopup.registerListener([this](std::any d) { this->onNewPopup(std::any_cast<SP<CXDGPopupResource>>(d)); });
|
||||||
|
@ -65,8 +66,9 @@ void CPopup::onDestroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::onMap() {
|
void CPopup::onMap() {
|
||||||
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
|
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
|
||||||
const auto COORDS = coordsGlobal();
|
const auto COORDS = coordsGlobal();
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS);
|
||||||
|
|
||||||
CBox box;
|
CBox box;
|
||||||
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
|
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
|
||||||
|
@ -79,8 +81,9 @@ void CPopup::onMap() {
|
||||||
|
|
||||||
m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
|
m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
|
||||||
|
|
||||||
unconstrain();
|
//unconstrain();
|
||||||
sendScale();
|
sendScale();
|
||||||
|
wlr_surface_send_enter(m_pResource->surface->surface, PMONITOR->output);
|
||||||
|
|
||||||
if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
|
if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
|
||||||
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
|
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
|
||||||
|
@ -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};
|
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);
|
m_pResource->applyPositioning(box, COORDS - PMONITOR->vecPosition);
|
||||||
wlr_surface_send_enter(m_pResource->surface->surface, PMONITOR->output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CPopup::coordsRelativeToParent() {
|
Vector2D CPopup::coordsRelativeToParent() {
|
||||||
|
@ -190,8 +192,6 @@ Vector2D CPopup::coordsRelativeToParent() {
|
||||||
CPopup* current = this;
|
CPopup* current = this;
|
||||||
offset -= current->m_pResource->surface->current.geometry.pos();
|
offset -= current->m_pResource->surface->current.geometry.pos();
|
||||||
|
|
||||||
offset -= m_pResource->surface->current.geometry.pos();
|
|
||||||
|
|
||||||
while (current->m_pParent && current->m_pResource) {
|
while (current->m_pParent && current->m_pResource) {
|
||||||
|
|
||||||
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
|
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
|
||||||
|
@ -293,11 +293,15 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!allowsInput) {
|
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))
|
if (BOX.containsPoint(globalCoords))
|
||||||
return p;
|
return p;
|
||||||
} else {
|
} 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))
|
if (REGION.containsPoint(globalCoords))
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ class CPopup {
|
||||||
CHyprSignalListener map;
|
CHyprSignalListener map;
|
||||||
CHyprSignalListener unmap;
|
CHyprSignalListener unmap;
|
||||||
CHyprSignalListener commit;
|
CHyprSignalListener commit;
|
||||||
|
CHyprSignalListener dismissed;
|
||||||
CHyprSignalListener reposition;
|
CHyprSignalListener reposition;
|
||||||
} listeners;
|
} listeners;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
void CSeatManager::onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot) {
|
||||||
if (!state.pointerFocusResource || !seatResource || seatResource->client() != state.pointerFocusResource->client()) {
|
if (!state.pointerFocusResource || !seatResource || seatResource->client() != state.pointerFocusResource->client()) {
|
||||||
Debug::log(LOG, "[seatmgr] Rejecting a setCursor because the client ain't in focus");
|
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) {
|
SP<CWLSeatResource> CSeatManager::seatResourceForClient(wl_client* client) {
|
||||||
return PROTO::seat->seatResourceForClient(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 IPointer;
|
||||||
class IKeyboard;
|
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 {
|
class CSeatManager {
|
||||||
public:
|
public:
|
||||||
CSeatManager();
|
CSeatManager();
|
||||||
|
@ -76,6 +107,9 @@ class CSeatManager {
|
||||||
WP<IPointer> mouse;
|
WP<IPointer> mouse;
|
||||||
WP<IKeyboard> keyboard;
|
WP<IKeyboard> keyboard;
|
||||||
|
|
||||||
|
void setGrab(SP<CSeatGrab> grab); // nullptr removes
|
||||||
|
SP<CSeatGrab> seatGrab;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SSeatResourceContainer {
|
struct SSeatResourceContainer {
|
||||||
SSeatResourceContainer(SP<CWLSeatResource>);
|
SSeatResourceContainer(SP<CWLSeatResource>);
|
||||||
|
@ -92,6 +126,8 @@ class CSeatManager {
|
||||||
void onNewSeatResource(SP<CWLSeatResource> resource);
|
void onNewSeatResource(SP<CWLSeatResource> resource);
|
||||||
SP<SSeatResourceContainer> containerForResource(SP<CWLSeatResource> seatResource);
|
SP<SSeatResourceContainer> containerForResource(SP<CWLSeatResource> seatResource);
|
||||||
|
|
||||||
|
void refocusGrab();
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CHyprSignalListener newSeatResource;
|
CHyprSignalListener newSeatResource;
|
||||||
} listeners;
|
} listeners;
|
||||||
|
@ -101,6 +137,7 @@ class CSeatManager {
|
||||||
DYNLISTENER(touchSurfaceDestroy);
|
DYNLISTENER(touchSurfaceDestroy);
|
||||||
|
|
||||||
friend struct SSeatResourceContainer;
|
friend struct SSeatResourceContainer;
|
||||||
|
friend class CSeatGrab;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline UP<CSeatManager> g_pSeatManager;
|
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)
|
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0)
|
||||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());
|
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 (!foundSurface) {
|
||||||
if (!m_bEmptyFocusCursorSet) {
|
if (!m_bEmptyFocusCursorSet) {
|
||||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) {
|
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)
|
if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor.get() && PMON)
|
||||||
g_pCompositor->setActiveMonitor(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) {
|
void CInputManager::processMouseDownKill(const IPointer::SButtonEvent& e) {
|
||||||
|
|
|
@ -187,10 +187,12 @@ class CInputManager {
|
||||||
void releaseAllMouseButtons();
|
void releaseAllMouseButtons();
|
||||||
|
|
||||||
// for some bugs in follow mouse 0
|
// for some bugs in follow mouse 0
|
||||||
bool m_bLastFocusOnLS = false;
|
bool m_bLastFocusOnLS = false;
|
||||||
|
|
||||||
bool m_bLastFocusOnIMEPopup = false;
|
bool m_bLastFocusOnIMEPopup = false;
|
||||||
|
|
||||||
|
// for hard input e.g. clicks
|
||||||
|
bool m_bHardInput = false;
|
||||||
|
|
||||||
// for hiding cursor on touch
|
// for hiding cursor on touch
|
||||||
bool m_bLastInputTouch = false;
|
bool m_bLastInputTouch = false;
|
||||||
|
|
||||||
|
|
|
@ -7,119 +7,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
|
||||||
// static void focus_grab_pointer_enter(wlr_seat_pointer_grab* grab, wlr_surface* surface, double sx, double sy) {
|
#define LOGM PROTO::focusGrab->protoLog
|
||||||
// if (static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(surface))
|
|
||||||
// wlr_seat_pointer_enter(grab->seat, surface, sx, sy);
|
|
||||||
// else
|
|
||||||
// wlr_seat_pointer_clear_focus(grab->seat);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_pointer_clear_focus(wlr_seat_pointer_grab* grab) {
|
|
||||||
// wlr_seat_pointer_clear_focus(grab->seat);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_pointer_motion(wlr_seat_pointer_grab* grab, uint32_t time, double sx, double sy) {
|
|
||||||
// wlr_seat_pointer_send_motion(grab->seat, time, sx, sy);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static uint32_t focus_grab_pointer_button(wlr_seat_pointer_grab* grab, uint32_t time, uint32_t button, wl_pointer_button_state state) {
|
|
||||||
// uint32_t serial = wlr_seat_pointer_send_button(grab->seat, time, button, state);
|
|
||||||
|
|
||||||
// if (serial)
|
|
||||||
// return serial;
|
|
||||||
// else {
|
|
||||||
// static_cast<CFocusGrab*>(grab->data)->finish(true);
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_pointer_axis(wlr_seat_pointer_grab* grab, uint32_t time, enum wl_pointer_axis orientation, double value, int32_t value_discrete,
|
|
||||||
// enum wl_pointer_axis_source source, enum wl_pointer_axis_relative_direction relative_direction) {
|
|
||||||
// wlr_seat_pointer_send_axis(grab->seat, time, orientation, value, value_discrete, source, relative_direction);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_pointer_frame(wlr_seat_pointer_grab* grab) {
|
|
||||||
// wlr_seat_pointer_send_frame(grab->seat);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_pointer_cancel(wlr_seat_pointer_grab* grab) {
|
|
||||||
// static_cast<CFocusGrab*>(grab->data)->finish(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static const wlr_pointer_grab_interface focus_grab_pointer_impl = {
|
|
||||||
// .enter = focus_grab_pointer_enter,
|
|
||||||
// .clear_focus = focus_grab_pointer_clear_focus,
|
|
||||||
// .motion = focus_grab_pointer_motion,
|
|
||||||
// .button = focus_grab_pointer_button,
|
|
||||||
// .axis = focus_grab_pointer_axis,
|
|
||||||
// .frame = focus_grab_pointer_frame,
|
|
||||||
// .cancel = focus_grab_pointer_cancel,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// static void focus_grab_keyboard_enter(wlr_seat_keyboard_grab* grab, wlr_surface* surface, const uint32_t keycodes[], size_t num_keycodes, const wlr_keyboard_modifiers* modifiers) {
|
|
||||||
// if (static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(surface))
|
|
||||||
// wlr_seat_keyboard_enter(grab->seat, surface, keycodes, num_keycodes, modifiers);
|
|
||||||
|
|
||||||
// // otherwise the last grabbed window should retain keyboard focus.
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_keyboard_clear_focus(wlr_seat_keyboard_grab* grab) {
|
|
||||||
// static_cast<CFocusGrab*>(grab->data)->finish(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_keyboard_key(wlr_seat_keyboard_grab* grab, uint32_t time, uint32_t key, uint32_t state) {
|
|
||||||
// wlr_seat_keyboard_send_key(grab->seat, time, key, state);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_keyboard_modifiers(wlr_seat_keyboard_grab* grab, const wlr_keyboard_modifiers* modifiers) {
|
|
||||||
// wlr_seat_keyboard_send_modifiers(grab->seat, modifiers);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_keyboard_cancel(wlr_seat_keyboard_grab* grab) {
|
|
||||||
// static_cast<CFocusGrab*>(grab->data)->finish(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static const wlr_keyboard_grab_interface focus_grab_keyboard_impl = {
|
|
||||||
// .enter = focus_grab_keyboard_enter,
|
|
||||||
// .clear_focus = focus_grab_keyboard_clear_focus,
|
|
||||||
// .key = focus_grab_keyboard_key,
|
|
||||||
// .modifiers = focus_grab_keyboard_modifiers,
|
|
||||||
// .cancel = focus_grab_keyboard_cancel,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// static uint32_t focus_grab_touch_down(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) {
|
|
||||||
// if (!static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(point->surface))
|
|
||||||
// return 0;
|
|
||||||
|
|
||||||
// return wlr_seat_touch_send_down(grab->seat, point->surface, time, point->touch_id, point->sx, point->sy);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_touch_up(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) {
|
|
||||||
// wlr_seat_touch_send_up(grab->seat, time, point->touch_id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_touch_motion(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) {
|
|
||||||
// wlr_seat_touch_send_motion(grab->seat, time, point->touch_id, point->sx, point->sy);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_touch_enter(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) {}
|
|
||||||
|
|
||||||
// static void focus_grab_touch_frame(wlr_seat_touch_grab* grab) {
|
|
||||||
// wlr_seat_touch_send_frame(grab->seat);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void focus_grab_touch_cancel(wlr_seat_touch_grab* grab) {
|
|
||||||
// static_cast<CFocusGrab*>(grab->data)->finish(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static const wlr_touch_grab_interface focus_grab_touch_impl = {
|
|
||||||
// .down = focus_grab_touch_down,
|
|
||||||
// .up = focus_grab_touch_up,
|
|
||||||
// .motion = focus_grab_touch_motion,
|
|
||||||
// .enter = focus_grab_touch_enter,
|
|
||||||
// .frame = focus_grab_touch_frame,
|
|
||||||
// .cancel = focus_grab_touch_cancel,
|
|
||||||
// };
|
|
||||||
|
|
||||||
CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, wlr_surface* surface) {
|
CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, wlr_surface* surface) {
|
||||||
hyprListener_surfaceDestroy.initCallback(
|
hyprListener_surfaceDestroy.initCallback(
|
||||||
|
@ -134,14 +22,10 @@ CFocusGrab::CFocusGrab(SP<CHyprlandFocusGrabV1> resource_) : resource(resource_)
|
||||||
if (!resource->resource())
|
if (!resource->resource())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// m_sPointerGrab.interface = &focus_grab_pointer_impl;
|
grab = makeShared<CSeatGrab>();
|
||||||
// m_sPointerGrab.data = this;
|
grab->keyboard = true;
|
||||||
|
grab->pointer = true;
|
||||||
// m_sKeyboardGrab.interface = &focus_grab_keyboard_impl;
|
grab->setCallback([this]() { finish(true); });
|
||||||
// m_sKeyboardGrab.data = this;
|
|
||||||
|
|
||||||
// m_sTouchGrab.interface = &focus_grab_touch_impl;
|
|
||||||
// m_sTouchGrab.data = this;
|
|
||||||
|
|
||||||
resource->setDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); });
|
resource->setDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); });
|
||||||
resource->setOnDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); });
|
resource->setOnDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); });
|
||||||
|
@ -168,21 +52,8 @@ bool CFocusGrab::isSurfaceComitted(wlr_surface* surface) {
|
||||||
|
|
||||||
void CFocusGrab::start() {
|
void CFocusGrab::start() {
|
||||||
if (!m_bGrabActive) {
|
if (!m_bGrabActive) {
|
||||||
// wlr_seat_pointer_start_grab(g_pCompositor->m_sSeat.seat, &m_sPointerGrab);
|
|
||||||
// wlr_seat_keyboard_start_grab(g_pCompositor->m_sSeat.seat, &m_sKeyboardGrab);
|
|
||||||
// wlr_seat_touch_start_grab(g_pCompositor->m_sSeat.seat, &m_sTouchGrab);
|
|
||||||
m_bGrabActive = true;
|
m_bGrabActive = true;
|
||||||
|
g_pSeatManager->setGrab(grab);
|
||||||
// Ensure the grab ends if another grab begins, including from xdg_popup::grab.
|
|
||||||
|
|
||||||
// hyprListener_pointerGrabStarted.initCallback(
|
|
||||||
// &g_pCompositor->m_sSeat.seat->events.pointer_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab");
|
|
||||||
|
|
||||||
// hyprListener_keyboardGrabStarted.initCallback(
|
|
||||||
// &g_pCompositor->m_sSeat.seat->events.keyboard_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab");
|
|
||||||
|
|
||||||
// hyprListener_touchGrabStarted.initCallback(
|
|
||||||
// &g_pCompositor->m_sSeat.seat->events.touch_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure new surfaces are focused if under the mouse when comitted.
|
// Ensure new surfaces are focused if under the mouse when comitted.
|
||||||
|
@ -193,59 +64,39 @@ void CFocusGrab::start() {
|
||||||
void CFocusGrab::finish(bool sendCleared) {
|
void CFocusGrab::finish(bool sendCleared) {
|
||||||
if (m_bGrabActive) {
|
if (m_bGrabActive) {
|
||||||
m_bGrabActive = false;
|
m_bGrabActive = false;
|
||||||
// hyprListener_pointerGrabStarted.removeCallback();
|
|
||||||
// hyprListener_keyboardGrabStarted.removeCallback();
|
|
||||||
// hyprListener_touchGrabStarted.removeCallback();
|
|
||||||
|
|
||||||
// Only clear grabs that belong to this focus grab. When superseded by another grab
|
if (g_pSeatManager->seatGrab == grab) {
|
||||||
// or xdg_popup grab we might not own the current grab.
|
g_pSeatManager->setGrab(nullptr);
|
||||||
|
}
|
||||||
bool hadGrab = false;
|
|
||||||
// if (g_pCompositor->m_sSeat.seat->pointer_state.grab == &m_sPointerGrab) {
|
|
||||||
// wlr_seat_pointer_end_grab(g_pCompositor->m_sSeat.seat);
|
|
||||||
// hadGrab = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (g_pCompositor->m_sSeat.seat->keyboard_state.grab == &m_sKeyboardGrab) {
|
|
||||||
// wlr_seat_keyboard_end_grab(g_pCompositor->m_sSeat.seat);
|
|
||||||
// hadGrab = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (g_pCompositor->m_sSeat.seat->touch_state.grab == &m_sTouchGrab) {
|
|
||||||
// wlr_seat_touch_end_grab(g_pCompositor->m_sSeat.seat);
|
|
||||||
// hadGrab = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
grab->clear();
|
||||||
m_mSurfaces.clear();
|
m_mSurfaces.clear();
|
||||||
|
|
||||||
if (sendCleared)
|
if (sendCleared)
|
||||||
resource->sendCleared();
|
resource->sendCleared();
|
||||||
|
|
||||||
// Ensure surfaces under the mouse when the grab ends get focus.
|
|
||||||
if (hadGrab)
|
|
||||||
g_pInputManager->refocus();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFocusGrab::addSurface(wlr_surface* surface) {
|
void CFocusGrab::addSurface(wlr_surface* surface) {
|
||||||
auto iter = m_mSurfaces.find(surface);
|
auto iter = m_mSurfaces.find(surface);
|
||||||
if (iter == m_mSurfaces.end())
|
if (iter == m_mSurfaces.end()) {
|
||||||
m_mSurfaces.emplace(surface, std::make_unique<CFocusGrabSurfaceState>(this, surface));
|
m_mSurfaces.emplace(surface, std::make_unique<CFocusGrabSurfaceState>(this, surface));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFocusGrab::removeSurface(wlr_surface* surface) {
|
void CFocusGrab::removeSurface(wlr_surface* surface) {
|
||||||
auto iter = m_mSurfaces.find(surface);
|
auto iter = m_mSurfaces.find(surface);
|
||||||
if (iter != m_mSurfaces.end()) {
|
if (iter != m_mSurfaces.end()) {
|
||||||
if (iter->second->state == CFocusGrabSurfaceState::PendingAddition)
|
if (iter->second->state == CFocusGrabSurfaceState::PendingAddition) {
|
||||||
m_mSurfaces.erase(iter);
|
m_mSurfaces.erase(iter);
|
||||||
else
|
} else
|
||||||
iter->second->state = CFocusGrabSurfaceState::PendingRemoval;
|
iter->second->state = CFocusGrabSurfaceState::PendingRemoval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFocusGrab::eraseSurface(wlr_surface* surface) {
|
void CFocusGrab::eraseSurface(wlr_surface* surface) {
|
||||||
removeSurface(surface);
|
removeSurface(surface);
|
||||||
commit();
|
commit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFocusGrab::refocusKeyboard() {
|
void CFocusGrab::refocusKeyboard() {
|
||||||
|
@ -264,22 +115,26 @@ void CFocusGrab::refocusKeyboard() {
|
||||||
if (surface)
|
if (surface)
|
||||||
g_pCompositor->focusSurface(surface);
|
g_pCompositor->focusSurface(surface);
|
||||||
else
|
else
|
||||||
Debug::log(ERR, "CFocusGrab::refocusKeyboard called with no committed surfaces. This should never happen.");
|
LOGM(ERR, "CFocusGrab::refocusKeyboard called with no committed surfaces. This should never happen.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFocusGrab::commit() {
|
void CFocusGrab::commit(bool removeOnly) {
|
||||||
auto surfacesChanged = false;
|
auto surfacesChanged = false;
|
||||||
auto anyComitted = false;
|
auto anyComitted = false;
|
||||||
for (auto iter = m_mSurfaces.begin(); iter != m_mSurfaces.end();) {
|
for (auto iter = m_mSurfaces.begin(); iter != m_mSurfaces.end();) {
|
||||||
switch (iter->second->state) {
|
switch (iter->second->state) {
|
||||||
case CFocusGrabSurfaceState::PendingRemoval:
|
case CFocusGrabSurfaceState::PendingRemoval:
|
||||||
|
grab->remove(iter->first);
|
||||||
iter = m_mSurfaces.erase(iter);
|
iter = m_mSurfaces.erase(iter);
|
||||||
surfacesChanged = true;
|
surfacesChanged = true;
|
||||||
continue;
|
continue;
|
||||||
case CFocusGrabSurfaceState::PendingAddition:
|
case CFocusGrabSurfaceState::PendingAddition:
|
||||||
iter->second->state = CFocusGrabSurfaceState::Comitted;
|
if (!removeOnly) {
|
||||||
surfacesChanged = true;
|
iter->second->state = CFocusGrabSurfaceState::Comitted;
|
||||||
anyComitted = true;
|
grab->add(iter->first);
|
||||||
|
surfacesChanged = true;
|
||||||
|
anyComitted = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CFocusGrabSurfaceState::Comitted: anyComitted = true; break;
|
case CFocusGrabSurfaceState::Comitted: anyComitted = true; break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CFocusGrab;
|
class CFocusGrab;
|
||||||
|
class CSeatGrab;
|
||||||
|
|
||||||
class CFocusGrabSurfaceState {
|
class CFocusGrabSurfaceState {
|
||||||
public:
|
public:
|
||||||
|
@ -40,14 +41,13 @@ class CFocusGrab {
|
||||||
void removeSurface(wlr_surface* surface);
|
void removeSurface(wlr_surface* surface);
|
||||||
void eraseSurface(wlr_surface* surface);
|
void eraseSurface(wlr_surface* surface);
|
||||||
void refocusKeyboard();
|
void refocusKeyboard();
|
||||||
void commit();
|
void commit(bool removeOnly = false);
|
||||||
|
|
||||||
SP<CHyprlandFocusGrabV1> resource;
|
SP<CHyprlandFocusGrabV1> resource;
|
||||||
std::unordered_map<wlr_surface*, UP<CFocusGrabSurfaceState>> m_mSurfaces;
|
std::unordered_map<wlr_surface*, UP<CFocusGrabSurfaceState>> m_mSurfaces;
|
||||||
// wlr_seat_pointer_grab m_sPointerGrab;
|
SP<CSeatGrab> grab;
|
||||||
// wlr_seat_keyboard_grab m_sKeyboardGrab;
|
|
||||||
// wlr_seat_touch_grab m_sTouchGrab;
|
bool m_bGrabActive = false;
|
||||||
bool m_bGrabActive = false;
|
|
||||||
|
|
||||||
DYNLISTENER(pointerGrabStarted);
|
DYNLISTENER(pointerGrabStarted);
|
||||||
DYNLISTENER(keyboardGrabStarted);
|
DYNLISTENER(keyboardGrabStarted);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "XDGShell.hpp"
|
#include "XDGShell.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
#include "../managers/SeatManager.hpp"
|
||||||
|
#include "core/Seat.hpp"
|
||||||
|
|
||||||
#define LOGM PROTO::xdgShell->protoLog
|
#define LOGM PROTO::xdgShell->protoLog
|
||||||
|
|
||||||
|
@ -14,12 +16,14 @@ CXDGPopupResource::CXDGPopupResource(SP<CXdgPopup> resource_, SP<CXDGSurfaceReso
|
||||||
resource->setDestroy([this](CXdgPopup* r) {
|
resource->setDestroy([this](CXdgPopup* r) {
|
||||||
if (surface && surface->mapped)
|
if (surface && surface->mapped)
|
||||||
surface->events.unmap.emit();
|
surface->events.unmap.emit();
|
||||||
|
PROTO::xdgShell->onPopupDestroy(self);
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
PROTO::xdgShell->destroyResource(this);
|
PROTO::xdgShell->destroyResource(this);
|
||||||
});
|
});
|
||||||
resource->setOnDestroy([this](CXdgPopup* r) {
|
resource->setOnDestroy([this](CXdgPopup* r) {
|
||||||
if (surface && surface->mapped)
|
if (surface && surface->mapped)
|
||||||
surface->events.unmap.emit();
|
surface->events.unmap.emit();
|
||||||
|
PROTO::xdgShell->onPopupDestroy(self);
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
PROTO::xdgShell->destroyResource(this);
|
PROTO::xdgShell->destroyResource(this);
|
||||||
});
|
});
|
||||||
|
@ -34,11 +38,29 @@ CXDGPopupResource::CXDGPopupResource(SP<CXdgPopup> resource_, SP<CXDGSurfaceReso
|
||||||
events.reposition.emit();
|
events.reposition.emit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
resource->setGrab([this](CXdgPopup* r, wl_resource* seat, uint32_t serial) {
|
||||||
|
LOGM(LOG, "xdg_popup {:x} requests grab", (uintptr_t)this);
|
||||||
|
listeners.pointerFocus.reset();
|
||||||
|
PROTO::xdgShell->addOrStartGrab(self.lock());
|
||||||
|
});
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
taken = true;
|
taken = true;
|
||||||
|
|
||||||
|
// this will be removed if the popup takes a grab.
|
||||||
|
// transient (non-grabbing popups) sometimes wouldn't be dismissed by the app
|
||||||
|
// as a result of either a hl bug or an app bug
|
||||||
|
// and stay on the screen annoying the user.
|
||||||
|
listeners.pointerFocus = g_pSeatManager->events.pointerFocusChange.registerListener([this](std::any data) {
|
||||||
|
if (g_pSeatManager->state.pointerFocusResource && g_pSeatManager->state.pointerFocusResource->client() == resource->client())
|
||||||
|
return;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CXDGPopupResource::~CXDGPopupResource() {
|
CXDGPopupResource::~CXDGPopupResource() {
|
||||||
|
PROTO::xdgShell->onPopupDestroy(self);
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +107,7 @@ void CXDGPopupResource::configure(const CBox& box) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXDGPopupResource::done() {
|
void CXDGPopupResource::done() {
|
||||||
|
events.dismissed.emit();
|
||||||
resource->sendPopupDone();
|
resource->sendPopupDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +682,10 @@ wl_client* CXDGWMBase::client() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CXDGShellProtocol::CXDGShellProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
CXDGShellProtocol::CXDGShellProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||||
;
|
grab = makeShared<CSeatGrab>();
|
||||||
|
grab->keyboard = true;
|
||||||
|
grab->pointer = true;
|
||||||
|
grab->setCallback([this]() { grabbed.clear(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXDGShellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
void CXDGShellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||||
|
@ -695,3 +721,39 @@ void CXDGShellProtocol::destroyResource(CXDGToplevelResource* resource) {
|
||||||
void CXDGShellProtocol::destroyResource(CXDGPopupResource* resource) {
|
void CXDGShellProtocol::destroyResource(CXDGPopupResource* resource) {
|
||||||
std::erase_if(m_vPopups, [&](const auto& other) { return other.get() == resource; });
|
std::erase_if(m_vPopups, [&](const auto& other) { return other.get() == resource; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::addOrStartGrab(SP<CXDGPopupResource> popup) {
|
||||||
|
if (!grabOwner) {
|
||||||
|
grabOwner = popup;
|
||||||
|
grabbed.clear();
|
||||||
|
grab->clear();
|
||||||
|
grab->add(popup->surface->surface);
|
||||||
|
if (popup->parent)
|
||||||
|
grab->add(popup->parent->surface);
|
||||||
|
g_pSeatManager->setGrab(grab);
|
||||||
|
grabbed.emplace_back(popup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
grabbed.emplace_back(popup);
|
||||||
|
|
||||||
|
grab->add(popup->surface->surface);
|
||||||
|
|
||||||
|
if (popup->parent)
|
||||||
|
grab->add(popup->parent->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::onPopupDestroy(WP<CXDGPopupResource> popup) {
|
||||||
|
if (popup == grabOwner) {
|
||||||
|
g_pSeatManager->setGrab(nullptr);
|
||||||
|
for (auto& g : grabbed) {
|
||||||
|
g->done();
|
||||||
|
}
|
||||||
|
grabbed.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::erase(grabbed, popup);
|
||||||
|
if (popup->surface)
|
||||||
|
grab->remove(popup->surface->surface);
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ class CXDGPopupResource {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CSignal reposition;
|
CSignal reposition;
|
||||||
|
CSignal dismissed;
|
||||||
CSignal destroy; // only the role
|
CSignal destroy; // only the role
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
|
@ -76,6 +77,11 @@ class CXDGPopupResource {
|
||||||
Vector2D accumulateParentOffset();
|
Vector2D accumulateParentOffset();
|
||||||
|
|
||||||
CXDGPositionerRules positionerRules;
|
CXDGPositionerRules positionerRules;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
// only connected if no grab.
|
||||||
|
CHyprSignalListener pointerFocus;
|
||||||
|
} listeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CXDGToplevelResource {
|
class CXDGToplevelResource {
|
||||||
|
@ -198,10 +204,10 @@ class CXDGPositionerResource {
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
SXDGPositionerState state;
|
SXDGPositionerState state;
|
||||||
|
|
||||||
WP<CXDGWMBase> owner;
|
WP<CXDGWMBase> owner;
|
||||||
WP<CXDGPositionerResource> self;
|
WP<CXDGPositionerResource> self;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CXdgPositioner> resource;
|
SP<CXdgPositioner> resource;
|
||||||
|
@ -244,6 +250,14 @@ class CXDGShellProtocol : public IWaylandProtocol {
|
||||||
std::vector<SP<CXDGToplevelResource>> m_vToplevels;
|
std::vector<SP<CXDGToplevelResource>> m_vToplevels;
|
||||||
std::vector<SP<CXDGPopupResource>> m_vPopups;
|
std::vector<SP<CXDGPopupResource>> m_vPopups;
|
||||||
|
|
||||||
|
// current popup grab
|
||||||
|
WP<CXDGPopupResource> grabOwner;
|
||||||
|
SP<CSeatGrab> grab;
|
||||||
|
std::vector<WP<CXDGPopupResource>> grabbed;
|
||||||
|
|
||||||
|
void addOrStartGrab(SP<CXDGPopupResource> popup);
|
||||||
|
void onPopupDestroy(WP<CXDGPopupResource> popup);
|
||||||
|
|
||||||
friend class CXDGWMBase;
|
friend class CXDGWMBase;
|
||||||
friend class CXDGPositionerResource;
|
friend class CXDGPositionerResource;
|
||||||
friend class CXDGSurfaceResource;
|
friend class CXDGSurfaceResource;
|
||||||
|
|
Loading…
Reference in a new issue