Compare commits

..

No commits in common. "0cb62920a7ab0b199754c941046ae86e3a1c368d" and "6705e2da778d216e81dbdc3764a3f50e89bfd87d" have entirely different histories.

22 changed files with 197 additions and 160 deletions

View file

@ -1,17 +1,82 @@
name: Crash Report (v1) name: Crash Report (v1)
description: Quickshell has crashed (old) description: Quickshell has crashed
labels: ["unactionable"] labels: ["bug", "crash"]
body: body:
- type: markdown - type: textarea
id: crashinfo
attributes: attributes:
value: | label: General crash information
Thank you for taking the time to click the report button. description: |
At this point most of the worst issues in 0.2.1 and before have been fixed and we are Paste the contents of the `info.txt` file in your crash folder here.
preparing for a new release. Please do not submit this report. value: "<details> <summary>General information</summary>
- type: checkboxes
id: donotcheck
```
<Paste the contents of the file here inside of the triple backticks>
```
</details>"
validations:
required: true
- type: textarea
id: userinfo
attributes: attributes:
label: Read the text above. Do not submit the report. label: What caused the crash
options: description: |
- label: Yes I want this report to be deleted. Any information likely to help debug the crash. What were you doing when the crash occurred,
required: true what changes did you make, can you get it to happen again?
- type: textarea
id: dump
attributes:
label: Minidump
description: |
Attach `minidump.dmp.log` here. If it is too big to upload, compress it.
You may skip this step if quickshell crashed while processing a password
or other sensitive information. If you skipped it write why instead.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Log file
description: |
Attach `log.qslog.log` here. If it is too big to upload, compress it.
You can preview the log if you'd like using `quickshell read-log <path-to-log>`.
validations:
required: true
- type: textarea
id: config
attributes:
label: Configuration
description: |
Attach your configuration here, preferrably in full (not just one file).
Compress it into a zip, tar, etc.
This will help us reproduce the crash ourselves.
- type: textarea
id: bt
attributes:
label: Backtrace
description: |
If you have gdb installed and use systemd, or otherwise know how to get a backtrace,
we would appreciate one. (You may have gdb installed without knowing it)
1. Run `coredumpctl debug <pid>` where `pid` is the number shown after "Crashed process ID"
in the crash reporter.
2. Once it loads, type `bt -full` (then enter)
3. Copy the output and attach it as a file or in a spoiler.
- type: textarea
id: exe
attributes:
label: Executable
description: |
If the crash folder contains a executable.txt file, upload it here. If not you can ignore this field.
If it is too big to upload, compress it.
Note: executable.txt is the quickshell binary. It has a .txt extension due to github's limitations on
filetypes.

View file

@ -9,21 +9,21 @@ body:
description: | description: |
Any information likely to help debug the crash. What were you doing when the crash occurred, Any information likely to help debug the crash. What were you doing when the crash occurred,
what changes did you make, can you get it to happen again? what changes did you make, can you get it to happen again?
- type: upload - type: textarea
id: report id: report
attributes: attributes:
label: Report file label: Report file
description: Attach `report.txt` here. description: Attach `report.txt` here.
validations: validations:
required: true required: true
- type: upload - type: textarea
id: logs id: logs
attributes: attributes:
label: Log file label: Log file
description: | description: |
Attach `log.qslog.log` here. If it is too big to upload, compress it. Attach `log.qslog.log` here. If it is too big to upload, compress it.
You can preview the log if you'd like using `qs log <path-to-log> -r '*=true'`. You can preview the log if you'd like using `quickshell read-log <path-to-log>`.
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -31,7 +31,7 @@ body:
attributes: attributes:
label: Configuration label: Configuration
description: | description: |
Attach or link your configuration here, preferrably in full (not just one file). Attach your configuration here, preferrably in full (not just one file).
Compress it into a zip, tar, etc. Compress it into a zip, tar, etc.
This will help us reproduce the crash ourselves. This will help us reproduce the crash ourselves.

View file

@ -48,7 +48,6 @@ set shell id.
- Fixed volumes not initializing if a pipewire device was already loaded before its node. - Fixed volumes not initializing if a pipewire device was already loaded before its node.
- Fixed hyprland active toplevel not resetting after window closes. - Fixed hyprland active toplevel not resetting after window closes.
- Fixed hyprland ipc window names and titles being reversed. - Fixed hyprland ipc window names and titles being reversed.
- Fixed a hyprland ipc crash when refreshing toplevels before workspaces.
- Fixed missing signals for system tray item title and description updates. - Fixed missing signals for system tray item title and description updates.
- Fixed asynchronous loaders not working after reload. - Fixed asynchronous loaders not working after reload.
- Fixed asynchronous loaders not working before window creation. - Fixed asynchronous loaders not working before window creation.
@ -59,8 +58,6 @@ set shell id.
- Fixed ToplevelManager not clearing activeToplevel on deactivation. - Fixed ToplevelManager not clearing activeToplevel on deactivation.
- Desktop action order is now preserved. - Desktop action order is now preserved.
- Fixed partial socket reads in greetd and hyprland on slow machines. - Fixed partial socket reads in greetd and hyprland on slow machines.
- Worked around Qt bug causing crashes when plugging and unplugging monitors.
- Fixed HyprlandFocusGrab crashing if windows were destroyed after being passed to it.
## Packaging Changes ## Packaging Changes

View file

@ -31,9 +31,6 @@
#include <sys/sendfile.h> #include <sys/sendfile.h>
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#ifdef __FreeBSD__
#include <unistd.h>
#endif
#include "instanceinfo.hpp" #include "instanceinfo.hpp"
#include "logcat.hpp" #include "logcat.hpp"
@ -70,7 +67,7 @@ bool copyFileData(int sourceFd, int destFd, qint64 size) {
return true; return true;
#else #else
std::array<char, 64 * 1024> buffer = {}; std::array<char, 64 * 1024> buffer = {};
auto remaining = usize; auto remaining = totalTarget;
while (remaining > 0) { while (remaining > 0) {
auto chunk = std::min(remaining, buffer.size()); auto chunk = std::min(remaining, buffer.size());

View file

@ -18,6 +18,7 @@
#include <qwindow.h> #include <qwindow.h>
#include "../window/proxywindow.hpp" #include "../window/proxywindow.hpp"
#include "../window/windowinterface.hpp"
#include "iconprovider.hpp" #include "iconprovider.hpp"
#include "model.hpp" #include "model.hpp"
#include "platformmenu_p.hpp" #include "platformmenu_p.hpp"
@ -90,8 +91,10 @@ bool PlatformMenuEntry::display(QObject* parentWindow, int relativeX, int relati
} else if (parentWindow == nullptr) { } else if (parentWindow == nullptr) {
qCritical() << "Cannot display PlatformMenuEntry with null parent window."; qCritical() << "Cannot display PlatformMenuEntry with null parent window.";
return false; return false;
} else if (auto* proxy = ProxyWindowBase::forObject(parentWindow)) { } else if (auto* proxy = qobject_cast<ProxyWindowBase*>(parentWindow)) {
window = proxy->backingWindow(); window = proxy->backingWindow();
} else if (auto* interface = qobject_cast<WindowInterface*>(parentWindow)) {
window = interface->proxyWindow()->backingWindow();
} else { } else {
qCritical() << "PlatformMenuEntry.display() must be called with a window."; qCritical() << "PlatformMenuEntry.display() must be called with a window.";
return false; return false;

View file

@ -11,6 +11,7 @@
#include <qwindow.h> #include <qwindow.h>
#include "../window/proxywindow.hpp" #include "../window/proxywindow.hpp"
#include "../window/windowinterface.hpp"
#include "types.hpp" #include "types.hpp"
bool PopupAnchorState::operator==(const PopupAnchorState& other) const { bool PopupAnchorState::operator==(const PopupAnchorState& other) const {
@ -39,8 +40,10 @@ void PopupAnchor::setWindowInternal(QObject* window) {
} }
if (window) { if (window) {
if (auto* proxy = ProxyWindowBase::forObject(window)) { if (auto* proxy = qobject_cast<ProxyWindowBase*>(window)) {
this->bProxyWindow = proxy; this->bProxyWindow = proxy;
} else if (auto* interface = qobject_cast<WindowInterface*>(window)) {
this->bProxyWindow = interface->proxyWindow();
} else { } else {
qWarning() << "Tried to set popup anchor window to" << window qWarning() << "Tried to set popup anchor window to" << window
<< "which is not a quickshell window."; << "which is not a quickshell window.";

View file

@ -8,9 +8,6 @@
#include <qtmetamacros.h> #include <qtmetamacros.h>
#include <sys/signal.h> #include <sys/signal.h>
#include <sys/wait.h> #include <sys/wait.h>
#ifdef __FreeBSD__
#include <signal.h>
#endif
#include "../../core/logcat.hpp" #include "../../core/logcat.hpp"
#include "ipc.hpp" #include "ipc.hpp"

View file

@ -73,7 +73,6 @@ endfunction()
# ----- # -----
qt_add_library(quickshell-wayland STATIC qt_add_library(quickshell-wayland STATIC
wl_proxy_safe_deref.cpp
platformmenu.cpp platformmenu.cpp
popupanchor.cpp popupanchor.cpp
xdgshell.cpp xdgshell.cpp
@ -81,10 +80,6 @@ qt_add_library(quickshell-wayland STATIC
output_tracking.cpp output_tracking.cpp
) )
# required for wl_proxy_safe_deref
target_link_libraries(quickshell-wayland PRIVATE ${CMAKE_DL_LIBS})
target_link_options(quickshell PRIVATE "LINKER:--export-dynamic-symbol=wl_proxy_get_listener")
# required to make sure the constructor is linked # required to make sure the constructor is linked
add_library(quickshell-wayland-init OBJECT init.cpp) add_library(quickshell-wayland-init OBJECT init.cpp)

View file

@ -9,6 +9,7 @@
#include <qwindow.h> #include <qwindow.h>
#include "../../../window/proxywindow.hpp" #include "../../../window/proxywindow.hpp"
#include "../../../window/windowinterface.hpp"
#include "grab.hpp" #include "grab.hpp"
#include "manager.hpp" #include "manager.hpp"
@ -37,51 +38,8 @@ QObjectList HyprlandFocusGrab::windows() const { return this->windowObjects; }
void HyprlandFocusGrab::setWindows(QObjectList windows) { void HyprlandFocusGrab::setWindows(QObjectList windows) {
if (windows == this->windowObjects) return; if (windows == this->windowObjects) return;
if (this->grab) this->grab->startTransaction();
for (auto* obj: this->windowObjects) {
if (windows.contains(obj)) continue;
QObject::disconnect(obj, nullptr, this, nullptr);
auto* proxy = ProxyWindowBase::forObject(obj);
if (!proxy) continue;
QObject::disconnect(proxy, nullptr, this, nullptr);
if (this->grab && proxy->backingWindow()) {
this->grab->removeWindow(proxy->backingWindow());
}
}
for (auto it = windows.begin(); it != windows.end();) {
auto* proxy = ProxyWindowBase::forObject(*it);
if (!proxy) {
it = windows.erase(it);
continue;
}
if (this->windowObjects.contains(*it)) {
++it;
continue;
}
QObject::connect(*it, &QObject::destroyed, this, &HyprlandFocusGrab::onObjectDestroyed);
QObject::connect(
proxy,
&ProxyWindowBase::windowConnected,
this,
&HyprlandFocusGrab::onProxyConnected
);
if (this->grab && proxy->backingWindow()) {
this->grab->addWindow(proxy->backingWindow());
}
++it;
}
if (this->grab) this->grab->completeTransaction();
this->windowObjects = std::move(windows); this->windowObjects = std::move(windows);
this->syncWindows();
emit this->windowsChanged(); emit this->windowsChanged();
} }
@ -117,18 +75,59 @@ void HyprlandFocusGrab::tryActivate() {
QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared); QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared);
this->grab->startTransaction(); this->grab->startTransaction();
for (auto* obj: this->windowObjects) { for (auto* proxy: this->trackedProxies) {
auto* proxy = ProxyWindowBase::forObject(obj); if (proxy->backingWindow() != nullptr) {
if (proxy && proxy->backingWindow()) {
this->grab->addWindow(proxy->backingWindow()); this->grab->addWindow(proxy->backingWindow());
} }
} }
this->grab->completeTransaction(); this->grab->completeTransaction();
} }
void HyprlandFocusGrab::onObjectDestroyed(QObject* object) { void HyprlandFocusGrab::syncWindows() {
this->windowObjects.removeOne(object); auto newProxy = QList<ProxyWindowBase*>();
emit this->windowsChanged(); for (auto* windowObject: this->windowObjects) {
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(windowObject);
if (proxyWindow == nullptr) {
if (auto* iface = qobject_cast<WindowInterface*>(windowObject)) {
proxyWindow = iface->proxyWindow();
}
}
if (proxyWindow != nullptr) {
newProxy.push_back(proxyWindow);
}
}
if (this->grab) this->grab->startTransaction();
for (auto* oldWindow: this->trackedProxies) {
if (!newProxy.contains(oldWindow)) {
QObject::disconnect(oldWindow, nullptr, this, nullptr);
if (this->grab != nullptr && oldWindow->backingWindow() != nullptr) {
this->grab->removeWindow(oldWindow->backingWindow());
}
}
}
for (auto* newProxy: newProxy) {
if (!this->trackedProxies.contains(newProxy)) {
QObject::connect(
newProxy,
&ProxyWindowBase::windowConnected,
this,
&HyprlandFocusGrab::onProxyConnected
);
if (this->grab != nullptr && newProxy->backingWindow() != nullptr) {
this->grab->addWindow(newProxy->backingWindow());
}
}
}
this->trackedProxies = newProxy;
if (this->grab) this->grab->completeTransaction();
} }
} // namespace qs::hyprland } // namespace qs::hyprland

View file

@ -96,13 +96,15 @@ private slots:
void onGrabActivated(); void onGrabActivated();
void onGrabCleared(); void onGrabCleared();
void onProxyConnected(); void onProxyConnected();
void onObjectDestroyed(QObject* object);
private: private:
void tryActivate(); void tryActivate();
void syncWindows();
bool targetActive = false; bool targetActive = false;
QObjectList windowObjects; QObjectList windowObjects;
QList<ProxyWindowBase*> trackedProxies;
QList<QWindow*> trackedWindows;
focus_grab::FocusGrab* grab = nullptr; focus_grab::FocusGrab* grab = nullptr;
}; };

View file

@ -729,7 +729,7 @@ void HyprlandIpc::refreshToplevels() {
} }
auto* workspace = toplevel->bindableWorkspace().value(); auto* workspace = toplevel->bindableWorkspace().value();
if (workspace) workspace->insertToplevel(toplevel); workspace->insertToplevel(toplevel);
} }
}); });
} }

View file

@ -72,16 +72,20 @@ void HyprlandToplevel::updateFromObject(const QVariantMap& object) {
Qt::beginPropertyUpdateGroup(); Qt::beginPropertyUpdateGroup();
bool ok = false; bool ok = false;
auto address = addressStr.toULongLong(&ok, 16); auto address = addressStr.toULongLong(&ok, 16);
if (ok && address) this->setAddress(address); if (!ok || !address) {
return;
}
this->setAddress(address);
this->bTitle = title; this->bTitle = title;
auto workspaceMap = object.value("workspace").toMap(); auto workspaceMap = object.value("workspace").toMap();
auto workspaceName = workspaceMap.value("name").toString(); auto workspaceName = workspaceMap.value("name").toString();
auto* workspace = this->ipc->findWorkspaceByName(workspaceName, true); auto* workspace = this->ipc->findWorkspaceByName(workspaceName, false);
if (workspace) this->setWorkspace(workspace); if (!workspace) return;
this->setWorkspace(workspace);
this->bLastIpcObject = object; this->bLastIpcObject = object;
Qt::endPropertyUpdateGroup(); Qt::endPropertyUpdateGroup();
} }

View file

@ -14,6 +14,7 @@
#include "../../../core/region.hpp" #include "../../../core/region.hpp"
#include "../../../window/proxywindow.hpp" #include "../../../window/proxywindow.hpp"
#include "../../../window/windowinterface.hpp"
#include "manager.hpp" #include "manager.hpp"
#include "surface.hpp" #include "surface.hpp"
@ -22,7 +23,13 @@ using QtWaylandClient::QWaylandWindow;
namespace qs::hyprland::surface { namespace qs::hyprland::surface {
HyprlandWindow* HyprlandWindow::qmlAttachedProperties(QObject* object) { HyprlandWindow* HyprlandWindow::qmlAttachedProperties(QObject* object) {
auto* proxyWindow = ProxyWindowBase::forObject(object); auto* proxyWindow = qobject_cast<ProxyWindowBase*>(object);
if (!proxyWindow) {
if (auto* iface = qobject_cast<WindowInterface*>(object)) {
proxyWindow = iface->proxyWindow();
}
}
if (!proxyWindow) return nullptr; if (!proxyWindow) return nullptr;
return new HyprlandWindow(proxyWindow); return new HyprlandWindow(proxyWindow);

View file

@ -6,6 +6,7 @@
#include <qtmetamacros.h> #include <qtmetamacros.h>
#include "../../window/proxywindow.hpp" #include "../../window/proxywindow.hpp"
#include "../../window/windowinterface.hpp"
#include "proto.hpp" #include "proto.hpp"
namespace qs::wayland::idle_inhibit { namespace qs::wayland::idle_inhibit {
@ -24,13 +25,27 @@ QObject* IdleInhibitor::window() const { return this->bWindowObject; }
void IdleInhibitor::setWindow(QObject* window) { void IdleInhibitor::setWindow(QObject* window) {
if (window == this->bWindowObject) return; if (window == this->bWindowObject) return;
auto* proxyWindow = ProxyWindowBase::forObject(window); auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
if (proxyWindow == nullptr) {
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
proxyWindow = iface->proxyWindow();
}
}
this->bWindowObject = proxyWindow ? window : nullptr; this->bWindowObject = proxyWindow ? window : nullptr;
} }
void IdleInhibitor::boundWindowChanged() { void IdleInhibitor::boundWindowChanged() {
auto* window = this->bBoundWindow.value(); auto* window = this->bBoundWindow.value();
auto* proxyWindow = ProxyWindowBase::forObject(window); auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
if (proxyWindow == nullptr) {
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
proxyWindow = iface->proxyWindow();
}
}
if (proxyWindow == this->proxyWindow) return; if (proxyWindow == this->proxyWindow) return;
if (this->mWaylandWindow) { if (this->mWaylandWindow) {

View file

@ -10,7 +10,6 @@
#include "wlr_layershell/wlr_layershell.hpp" #include "wlr_layershell/wlr_layershell.hpp"
#endif #endif
void installWlProxySafeDeref(); // NOLINT(misc-use-internal-linkage)
void installPlatformMenuHook(); // NOLINT(misc-use-internal-linkage) void installPlatformMenuHook(); // NOLINT(misc-use-internal-linkage)
void installPopupPositioner(); // NOLINT(misc-use-internal-linkage) void installPopupPositioner(); // NOLINT(misc-use-internal-linkage)
@ -34,7 +33,6 @@ class WaylandPlugin: public QsEnginePlugin {
} }
void init() override { void init() override {
installWlProxySafeDeref();
installPlatformMenuHook(); installPlatformMenuHook();
installPopupPositioner(); installPopupPositioner();
} }

View file

@ -9,6 +9,7 @@
#include <qwindow.h> #include <qwindow.h>
#include "../../window/proxywindow.hpp" #include "../../window/proxywindow.hpp"
#include "../../window/windowinterface.hpp"
#include "proto.hpp" #include "proto.hpp"
namespace qs::wayland::shortcuts_inhibit { namespace qs::wayland::shortcuts_inhibit {
@ -47,7 +48,14 @@ ShortcutInhibitor::~ShortcutInhibitor() {
void ShortcutInhibitor::onBoundWindowChanged() { void ShortcutInhibitor::onBoundWindowChanged() {
auto* window = this->bBoundWindow.value(); auto* window = this->bBoundWindow.value();
auto* proxyWindow = ProxyWindowBase::forObject(window); auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
if (!proxyWindow) {
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
proxyWindow = iface->proxyWindow();
}
}
if (proxyWindow == this->proxyWindow) return; if (proxyWindow == this->proxyWindow) return;
if (this->proxyWindow) { if (this->proxyWindow) {

View file

@ -9,6 +9,7 @@
#include "../../core/qmlscreen.hpp" #include "../../core/qmlscreen.hpp"
#include "../../core/util.hpp" #include "../../core/util.hpp"
#include "../../window/proxywindow.hpp" #include "../../window/proxywindow.hpp"
#include "../../window/windowinterface.hpp"
#include "../output_tracking.hpp" #include "../output_tracking.hpp"
#include "handle.hpp" #include "handle.hpp"
#include "manager.hpp" #include "manager.hpp"
@ -72,7 +73,13 @@ void Toplevel::fullscreenOn(QuickshellScreenInfo* screen) {
} }
void Toplevel::setRectangle(QObject* window, QRect rect) { void Toplevel::setRectangle(QObject* window, QRect rect) {
auto* proxyWindow = ProxyWindowBase::forObject(window); auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
if (proxyWindow == nullptr) {
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
proxyWindow = iface->proxyWindow();
}
}
if (proxyWindow != this->rectWindow) { if (proxyWindow != this->rectWindow) {
if (this->rectWindow != nullptr) { if (this->rectWindow != nullptr) {

View file

@ -8,9 +8,9 @@
#include <qobjectdefs.h> #include <qobjectdefs.h>
#include <qproperty.h> #include <qproperty.h>
#include "../../windowmanager/screenprojection.hpp"
#include "../../windowmanager/windowmanager.hpp" #include "../../windowmanager/windowmanager.hpp"
#include "../../windowmanager/windowset.hpp" #include "../../windowmanager/windowset.hpp"
#include "../../windowmanager/screenprojection.hpp"
#include "ext_workspace.hpp" #include "ext_workspace.hpp"
namespace qs::wm::wayland { namespace qs::wm::wayland {

View file

@ -1,41 +0,0 @@
#include <dlfcn.h>
#include <qlogging.h>
#include <qloggingcategory.h>
#include <wayland-client-core.h>
#include <wayland-util.h>
#include "../core/logcat.hpp"
namespace {
QS_LOGGING_CATEGORY(logDeref, "quickshell.wayland.safederef", QtWarningMsg);
using wl_proxy_get_listener_t = const void* (*) (wl_proxy*);
wl_proxy_get_listener_t original_wl_proxy_get_listener = nullptr; // NOLINT
} // namespace
extern "C" {
WL_EXPORT const void* wl_proxy_get_listener(struct wl_proxy* proxy) {
// Avoid null derefs of protocol objects in qtbase.
// https://qt-project.atlassian.net/browse/QTBUG-145022
if (!proxy) [[unlikely]] {
qCCritical(logDeref) << "wl_proxy_get_listener called with a null proxy!";
return nullptr;
}
return original_wl_proxy_get_listener(proxy);
}
}
// NOLINTBEGIN (concurrency-mt-unsafe)
void installWlProxySafeDeref() {
dlerror(); // clear old errors
original_wl_proxy_get_listener =
reinterpret_cast<wl_proxy_get_listener_t>(dlsym(RTLD_NEXT, "wl_proxy_get_listener"));
if (auto* error = dlerror()) {
qCCritical(logDeref) << "Failed to find wl_proxy_get_listener for hooking:" << error;
} else {
qCInfo(logDeref) << "Installed wl_proxy_get_listener hook.";
}
}
// NOLINTEND

View file

@ -17,7 +17,6 @@
#include <qvariant.h> #include <qvariant.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h> #include <qwayland-wlr-layer-shell-unstable-v1.h>
#include <qwindow.h> #include <qwindow.h>
#include <wayland-xdg-shell-client-protocol.h>
#include "../../window/panelinterface.hpp" #include "../../window/panelinterface.hpp"
#include "shell_integration.hpp" #include "shell_integration.hpp"
@ -248,19 +247,9 @@ void LayerSurface::commit() {
} }
void LayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface* popup) { void LayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface* popup) {
#ifdef __FreeBSD__ std::any role = popup->surfaceRole();
// FreeBSD uses an alternate RTTI matching strategy by default which does
// not work across modules, preventing std::any from downcasting. On if (auto* popupRole = std::any_cast<::xdg_popup*>(&role)) { // NOLINT
// FreeBSD, Qt is built with a patch to expose the surface role through a
// pointer instead of an any, which does not have this problem.
// See https://bugs.kde.org/show_bug.cgi?id=479679
if (auto* xdgPopup = static_cast<::xdg_popup*>(popup->nativeResource("xdg_popup"))) {
this->get_popup(xdgPopup);
return;
}
#endif
auto role = popup->surfaceRole(); // NOLINT
if (auto* popupRole = std::any_cast<::xdg_popup*>(&role)) {
this->get_popup(*popupRole); this->get_popup(*popupRole);
} else { } else {
qWarning() << "Cannot attach popup" << popup << "to shell surface" << this qWarning() << "Cannot attach popup" << popup << "to shell surface" << this

View file

@ -57,12 +57,6 @@ ProxyWindowBase::ProxyWindowBase(QObject* parent)
ProxyWindowBase::~ProxyWindowBase() { this->deleteWindow(true); } ProxyWindowBase::~ProxyWindowBase() { this->deleteWindow(true); }
ProxyWindowBase* ProxyWindowBase::forObject(QObject* obj) {
if (auto* proxy = qobject_cast<ProxyWindowBase*>(obj)) return proxy;
if (auto* iface = qobject_cast<WindowInterface*>(obj)) return iface->proxyWindow();
return nullptr;
}
void ProxyWindowBase::onReload(QObject* oldInstance) { void ProxyWindowBase::onReload(QObject* oldInstance) {
if (this->mVisible) this->window = this->retrieveWindow(oldInstance); if (this->mVisible) this->window = this->retrieveWindow(oldInstance);
auto wasVisible = this->window != nullptr && this->window->isVisible(); auto wasVisible = this->window != nullptr && this->window->isVisible();

View file

@ -66,8 +66,6 @@ public:
explicit ProxyWindowBase(QObject* parent = nullptr); explicit ProxyWindowBase(QObject* parent = nullptr);
~ProxyWindowBase() override; ~ProxyWindowBase() override;
static ProxyWindowBase* forObject(QObject* obj);
ProxyWindowBase(ProxyWindowBase&) = delete; ProxyWindowBase(ProxyWindowBase&) = delete;
ProxyWindowBase(ProxyWindowBase&&) = delete; ProxyWindowBase(ProxyWindowBase&&) = delete;
void operator=(ProxyWindowBase&) = delete; void operator=(ProxyWindowBase&) = delete;