hyprland/focus_grab: wait for surface creation if null

Fixes an occasional crash with QWaylandWindow::surface() returning null.
This commit is contained in:
outfoxxed 2024-08-20 16:41:04 -07:00
parent fe1d15e8f6
commit f95e7dbaf6
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
3 changed files with 37 additions and 7 deletions

View file

@ -19,18 +19,34 @@ FocusGrab::~FocusGrab() {
bool FocusGrab::isActive() const { return this->active; } bool FocusGrab::isActive() const { return this->active; }
void FocusGrab::addWindow(QWindow* window) { void FocusGrab::addWindow(QWindow* window) {
auto tryAddWayland = [this](QWaylandWindow* waylandWindow) {
if (waylandWindow->surface()) {
this->addWaylandWindow(waylandWindow);
this->sync();
} else {
QObject::connect(
waylandWindow,
&QWaylandWindow::surfaceCreated,
this,
[this, waylandWindow]() {
this->addWaylandWindow(waylandWindow);
this->sync();
}
);
}
};
if (auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle())) { if (auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle())) {
this->addWaylandWindow(waylandWindow); tryAddWayland(waylandWindow);
} else { } else {
QObject::connect(window, &QWindow::visibleChanged, this, [this, window]() { QObject::connect(window, &QWindow::visibleChanged, this, [this, window, tryAddWayland]() {
if (window->isVisible()) { if (window->isVisible()) {
if (window->handle() == nullptr) { if (window->handle() == nullptr) {
window->create(); window->create();
} }
auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle()); auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle());
this->addWaylandWindow(waylandWindow); tryAddWayland(waylandWindow);
this->sync();
} }
}); });
} }
@ -53,6 +69,8 @@ void FocusGrab::addWaylandWindow(QWaylandWindow* window) {
} }
void FocusGrab::sync() { void FocusGrab::sync() {
if (this->transactionActive) return;
if (this->commitRequired) { if (this->commitRequired) {
this->commit(); this->commit();
this->commitRequired = false; this->commitRequired = false;
@ -70,6 +88,13 @@ void FocusGrab::sync() {
} }
} }
void FocusGrab::startTransaction() { this->transactionActive = true; }
void FocusGrab::completeTransaction() {
this->transactionActive = false;
this->sync();
}
void FocusGrab::hyprland_focus_grab_v1_cleared() { void FocusGrab::hyprland_focus_grab_v1_cleared() {
this->active = false; this->active = false;
emit this->cleared(); emit this->cleared();

View file

@ -28,6 +28,8 @@ public:
void addWindow(QWindow* window); void addWindow(QWindow* window);
void removeWindow(QWindow* window); void removeWindow(QWindow* window);
void sync(); void sync();
void startTransaction();
void completeTransaction();
signals: signals:
void activated(); void activated();
@ -40,6 +42,7 @@ private:
QList<QWaylandWindow*> pendingAdditions; QList<QWaylandWindow*> pendingAdditions;
bool commitRequired = false; bool commitRequired = false;
bool transactionActive = false;
bool active = false; bool active = false;
}; };

View file

@ -74,13 +74,13 @@ void HyprlandFocusGrab::tryActivate() {
QObject::connect(this->grab, &FocusGrab::activated, this, &HyprlandFocusGrab::onGrabActivated); QObject::connect(this->grab, &FocusGrab::activated, this, &HyprlandFocusGrab::onGrabActivated);
QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared); QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared);
this->grab->startTransaction();
for (auto* proxy: this->trackedProxies) { for (auto* proxy: this->trackedProxies) {
if (proxy->backingWindow() != nullptr) { if (proxy->backingWindow() != nullptr) {
this->grab->addWindow(proxy->backingWindow()); this->grab->addWindow(proxy->backingWindow());
} }
} }
this->grab->completeTransaction();
this->grab->sync();
} }
void HyprlandFocusGrab::syncWindows() { void HyprlandFocusGrab::syncWindows() {
@ -99,6 +99,8 @@ void HyprlandFocusGrab::syncWindows() {
} }
} }
if (this->grab) this->grab->startTransaction();
for (auto* oldWindow: this->trackedProxies) { for (auto* oldWindow: this->trackedProxies) {
if (!newProxy.contains(oldWindow)) { if (!newProxy.contains(oldWindow)) {
QObject::disconnect(oldWindow, nullptr, this, nullptr); QObject::disconnect(oldWindow, nullptr, this, nullptr);
@ -125,7 +127,7 @@ void HyprlandFocusGrab::syncWindows() {
} }
this->trackedProxies = newProxy; this->trackedProxies = newProxy;
if (this->grab != nullptr) this->grab->sync(); if (this->grab) this->grab->completeTransaction();
} }
} // namespace qs::hyprland } // namespace qs::hyprland