mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-04-10 06:11:54 +10:00
Compare commits
8 commits
6705e2da77
...
0cb62920a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cb62920a7 | ||
|
|
3520c85d77 | ||
|
|
3cf65af49f | ||
|
|
a51dcd0a01 | ||
|
|
97b2688ad6 | ||
|
|
0a859d51f2 | ||
|
|
1bd5b083cb | ||
|
|
365bf16b1e |
22 changed files with 160 additions and 197 deletions
91
.github/ISSUE_TEMPLATE/crash.yml
vendored
91
.github/ISSUE_TEMPLATE/crash.yml
vendored
|
|
@ -1,82 +1,17 @@
|
|||
name: Crash Report (v1)
|
||||
description: Quickshell has crashed
|
||||
labels: ["bug", "crash"]
|
||||
description: Quickshell has crashed (old)
|
||||
labels: ["unactionable"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: crashinfo
|
||||
- type: markdown
|
||||
attributes:
|
||||
label: General crash information
|
||||
description: |
|
||||
Paste the contents of the `info.txt` file in your crash folder here.
|
||||
value: "<details> <summary>General information</summary>
|
||||
|
||||
|
||||
```
|
||||
|
||||
<Paste the contents of the file here inside of the triple backticks>
|
||||
|
||||
```
|
||||
|
||||
|
||||
</details>"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: userinfo
|
||||
value: |
|
||||
Thank you for taking the time to click the report button.
|
||||
At this point most of the worst issues in 0.2.1 and before have been fixed and we are
|
||||
preparing for a new release. Please do not submit this report.
|
||||
- type: checkboxes
|
||||
id: donotcheck
|
||||
attributes:
|
||||
label: What caused the crash
|
||||
description: |
|
||||
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?
|
||||
- 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.
|
||||
label: Read the text above. Do not submit the report.
|
||||
options:
|
||||
- label: Yes I want this report to be deleted.
|
||||
required: true
|
||||
|
|
|
|||
8
.github/ISSUE_TEMPLATE/crash2.yml
vendored
8
.github/ISSUE_TEMPLATE/crash2.yml
vendored
|
|
@ -9,21 +9,21 @@ body:
|
|||
description: |
|
||||
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?
|
||||
- type: textarea
|
||||
- type: upload
|
||||
id: report
|
||||
attributes:
|
||||
label: Report file
|
||||
description: Attach `report.txt` here.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
- type: upload
|
||||
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>`.
|
||||
You can preview the log if you'd like using `qs log <path-to-log> -r '*=true'`.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
|
@ -31,7 +31,7 @@ body:
|
|||
attributes:
|
||||
label: Configuration
|
||||
description: |
|
||||
Attach your configuration here, preferrably in full (not just one file).
|
||||
Attach or link 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.
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ set shell id.
|
|||
- 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 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 asynchronous loaders not working after reload.
|
||||
- Fixed asynchronous loaders not working before window creation.
|
||||
|
|
@ -58,6 +59,8 @@ set shell id.
|
|||
- Fixed ToplevelManager not clearing activeToplevel on deactivation.
|
||||
- Desktop action order is now preserved.
|
||||
- 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
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
#include <sys/sendfile.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "instanceinfo.hpp"
|
||||
#include "logcat.hpp"
|
||||
|
|
@ -67,7 +70,7 @@ bool copyFileData(int sourceFd, int destFd, qint64 size) {
|
|||
return true;
|
||||
#else
|
||||
std::array<char, 64 * 1024> buffer = {};
|
||||
auto remaining = totalTarget;
|
||||
auto remaining = usize;
|
||||
|
||||
while (remaining > 0) {
|
||||
auto chunk = std::min(remaining, buffer.size());
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include <qwindow.h>
|
||||
|
||||
#include "../window/proxywindow.hpp"
|
||||
#include "../window/windowinterface.hpp"
|
||||
#include "iconprovider.hpp"
|
||||
#include "model.hpp"
|
||||
#include "platformmenu_p.hpp"
|
||||
|
|
@ -91,10 +90,8 @@ bool PlatformMenuEntry::display(QObject* parentWindow, int relativeX, int relati
|
|||
} else if (parentWindow == nullptr) {
|
||||
qCritical() << "Cannot display PlatformMenuEntry with null parent window.";
|
||||
return false;
|
||||
} else if (auto* proxy = qobject_cast<ProxyWindowBase*>(parentWindow)) {
|
||||
} else if (auto* proxy = ProxyWindowBase::forObject(parentWindow)) {
|
||||
window = proxy->backingWindow();
|
||||
} else if (auto* interface = qobject_cast<WindowInterface*>(parentWindow)) {
|
||||
window = interface->proxyWindow()->backingWindow();
|
||||
} else {
|
||||
qCritical() << "PlatformMenuEntry.display() must be called with a window.";
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include <qwindow.h>
|
||||
|
||||
#include "../window/proxywindow.hpp"
|
||||
#include "../window/windowinterface.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
bool PopupAnchorState::operator==(const PopupAnchorState& other) const {
|
||||
|
|
@ -40,10 +39,8 @@ void PopupAnchor::setWindowInternal(QObject* window) {
|
|||
}
|
||||
|
||||
if (window) {
|
||||
if (auto* proxy = qobject_cast<ProxyWindowBase*>(window)) {
|
||||
if (auto* proxy = ProxyWindowBase::forObject(window)) {
|
||||
this->bProxyWindow = proxy;
|
||||
} else if (auto* interface = qobject_cast<WindowInterface*>(window)) {
|
||||
this->bProxyWindow = interface->proxyWindow();
|
||||
} else {
|
||||
qWarning() << "Tried to set popup anchor window to" << window
|
||||
<< "which is not a quickshell window.";
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#include <qtmetamacros.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "../../core/logcat.hpp"
|
||||
#include "ipc.hpp"
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ endfunction()
|
|||
# -----
|
||||
|
||||
qt_add_library(quickshell-wayland STATIC
|
||||
wl_proxy_safe_deref.cpp
|
||||
platformmenu.cpp
|
||||
popupanchor.cpp
|
||||
xdgshell.cpp
|
||||
|
|
@ -80,6 +81,10 @@ qt_add_library(quickshell-wayland STATIC
|
|||
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
|
||||
add_library(quickshell-wayland-init OBJECT init.cpp)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include <qwindow.h>
|
||||
|
||||
#include "../../../window/proxywindow.hpp"
|
||||
#include "../../../window/windowinterface.hpp"
|
||||
#include "grab.hpp"
|
||||
#include "manager.hpp"
|
||||
|
||||
|
|
@ -38,8 +37,51 @@ QObjectList HyprlandFocusGrab::windows() const { return this->windowObjects; }
|
|||
|
||||
void HyprlandFocusGrab::setWindows(QObjectList windows) {
|
||||
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->syncWindows();
|
||||
emit this->windowsChanged();
|
||||
}
|
||||
|
||||
|
|
@ -75,59 +117,18 @@ void HyprlandFocusGrab::tryActivate() {
|
|||
QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared);
|
||||
|
||||
this->grab->startTransaction();
|
||||
for (auto* proxy: this->trackedProxies) {
|
||||
if (proxy->backingWindow() != nullptr) {
|
||||
for (auto* obj: this->windowObjects) {
|
||||
auto* proxy = ProxyWindowBase::forObject(obj);
|
||||
if (proxy && proxy->backingWindow()) {
|
||||
this->grab->addWindow(proxy->backingWindow());
|
||||
}
|
||||
}
|
||||
this->grab->completeTransaction();
|
||||
}
|
||||
|
||||
void HyprlandFocusGrab::syncWindows() {
|
||||
auto newProxy = QList<ProxyWindowBase*>();
|
||||
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();
|
||||
void HyprlandFocusGrab::onObjectDestroyed(QObject* object) {
|
||||
this->windowObjects.removeOne(object);
|
||||
emit this->windowsChanged();
|
||||
}
|
||||
|
||||
} // namespace qs::hyprland
|
||||
|
|
|
|||
|
|
@ -96,15 +96,13 @@ private slots:
|
|||
void onGrabActivated();
|
||||
void onGrabCleared();
|
||||
void onProxyConnected();
|
||||
void onObjectDestroyed(QObject* object);
|
||||
|
||||
private:
|
||||
void tryActivate();
|
||||
void syncWindows();
|
||||
|
||||
bool targetActive = false;
|
||||
QObjectList windowObjects;
|
||||
QList<ProxyWindowBase*> trackedProxies;
|
||||
QList<QWindow*> trackedWindows;
|
||||
|
||||
focus_grab::FocusGrab* grab = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -729,7 +729,7 @@ void HyprlandIpc::refreshToplevels() {
|
|||
}
|
||||
|
||||
auto* workspace = toplevel->bindableWorkspace().value();
|
||||
workspace->insertToplevel(toplevel);
|
||||
if (workspace) workspace->insertToplevel(toplevel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,20 +72,16 @@ void HyprlandToplevel::updateFromObject(const QVariantMap& object) {
|
|||
Qt::beginPropertyUpdateGroup();
|
||||
bool ok = false;
|
||||
auto address = addressStr.toULongLong(&ok, 16);
|
||||
if (!ok || !address) {
|
||||
return;
|
||||
}
|
||||
if (ok && address) this->setAddress(address);
|
||||
|
||||
this->setAddress(address);
|
||||
this->bTitle = title;
|
||||
|
||||
auto workspaceMap = object.value("workspace").toMap();
|
||||
auto workspaceName = workspaceMap.value("name").toString();
|
||||
|
||||
auto* workspace = this->ipc->findWorkspaceByName(workspaceName, false);
|
||||
if (!workspace) return;
|
||||
auto* workspace = this->ipc->findWorkspaceByName(workspaceName, true);
|
||||
if (workspace) this->setWorkspace(workspace);
|
||||
|
||||
this->setWorkspace(workspace);
|
||||
this->bLastIpcObject = object;
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "../../../core/region.hpp"
|
||||
#include "../../../window/proxywindow.hpp"
|
||||
#include "../../../window/windowinterface.hpp"
|
||||
#include "manager.hpp"
|
||||
#include "surface.hpp"
|
||||
|
||||
|
|
@ -23,13 +22,7 @@ using QtWaylandClient::QWaylandWindow;
|
|||
namespace qs::hyprland::surface {
|
||||
|
||||
HyprlandWindow* HyprlandWindow::qmlAttachedProperties(QObject* object) {
|
||||
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(object);
|
||||
|
||||
if (!proxyWindow) {
|
||||
if (auto* iface = qobject_cast<WindowInterface*>(object)) {
|
||||
proxyWindow = iface->proxyWindow();
|
||||
}
|
||||
}
|
||||
auto* proxyWindow = ProxyWindowBase::forObject(object);
|
||||
|
||||
if (!proxyWindow) return nullptr;
|
||||
return new HyprlandWindow(proxyWindow);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include <qtmetamacros.h>
|
||||
|
||||
#include "../../window/proxywindow.hpp"
|
||||
#include "../../window/windowinterface.hpp"
|
||||
#include "proto.hpp"
|
||||
|
||||
namespace qs::wayland::idle_inhibit {
|
||||
|
|
@ -25,27 +24,13 @@ QObject* IdleInhibitor::window() const { return this->bWindowObject; }
|
|||
void IdleInhibitor::setWindow(QObject* window) {
|
||||
if (window == this->bWindowObject) return;
|
||||
|
||||
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
|
||||
|
||||
if (proxyWindow == nullptr) {
|
||||
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
|
||||
proxyWindow = iface->proxyWindow();
|
||||
}
|
||||
}
|
||||
|
||||
auto* proxyWindow = ProxyWindowBase::forObject(window);
|
||||
this->bWindowObject = proxyWindow ? window : nullptr;
|
||||
}
|
||||
|
||||
void IdleInhibitor::boundWindowChanged() {
|
||||
auto* window = this->bBoundWindow.value();
|
||||
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
|
||||
|
||||
if (proxyWindow == nullptr) {
|
||||
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
|
||||
proxyWindow = iface->proxyWindow();
|
||||
}
|
||||
}
|
||||
|
||||
auto* proxyWindow = ProxyWindowBase::forObject(window);
|
||||
if (proxyWindow == this->proxyWindow) return;
|
||||
|
||||
if (this->mWaylandWindow) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "wlr_layershell/wlr_layershell.hpp"
|
||||
#endif
|
||||
|
||||
void installWlProxySafeDeref(); // NOLINT(misc-use-internal-linkage)
|
||||
void installPlatformMenuHook(); // NOLINT(misc-use-internal-linkage)
|
||||
void installPopupPositioner(); // NOLINT(misc-use-internal-linkage)
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ class WaylandPlugin: public QsEnginePlugin {
|
|||
}
|
||||
|
||||
void init() override {
|
||||
installWlProxySafeDeref();
|
||||
installPlatformMenuHook();
|
||||
installPopupPositioner();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include <qwindow.h>
|
||||
|
||||
#include "../../window/proxywindow.hpp"
|
||||
#include "../../window/windowinterface.hpp"
|
||||
#include "proto.hpp"
|
||||
|
||||
namespace qs::wayland::shortcuts_inhibit {
|
||||
|
|
@ -48,14 +47,7 @@ ShortcutInhibitor::~ShortcutInhibitor() {
|
|||
|
||||
void ShortcutInhibitor::onBoundWindowChanged() {
|
||||
auto* window = this->bBoundWindow.value();
|
||||
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
|
||||
|
||||
if (!proxyWindow) {
|
||||
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
|
||||
proxyWindow = iface->proxyWindow();
|
||||
}
|
||||
}
|
||||
|
||||
auto* proxyWindow = ProxyWindowBase::forObject(window);
|
||||
if (proxyWindow == this->proxyWindow) return;
|
||||
|
||||
if (this->proxyWindow) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include "../../core/qmlscreen.hpp"
|
||||
#include "../../core/util.hpp"
|
||||
#include "../../window/proxywindow.hpp"
|
||||
#include "../../window/windowinterface.hpp"
|
||||
#include "../output_tracking.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "manager.hpp"
|
||||
|
|
@ -73,13 +72,7 @@ void Toplevel::fullscreenOn(QuickshellScreenInfo* screen) {
|
|||
}
|
||||
|
||||
void Toplevel::setRectangle(QObject* window, QRect rect) {
|
||||
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
|
||||
|
||||
if (proxyWindow == nullptr) {
|
||||
if (auto* iface = qobject_cast<WindowInterface*>(window)) {
|
||||
proxyWindow = iface->proxyWindow();
|
||||
}
|
||||
}
|
||||
auto* proxyWindow = ProxyWindowBase::forObject(window);
|
||||
|
||||
if (proxyWindow != this->rectWindow) {
|
||||
if (this->rectWindow != nullptr) {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
#include <qobjectdefs.h>
|
||||
#include <qproperty.h>
|
||||
|
||||
#include "../../windowmanager/screenprojection.hpp"
|
||||
#include "../../windowmanager/windowmanager.hpp"
|
||||
#include "../../windowmanager/windowset.hpp"
|
||||
#include "../../windowmanager/screenprojection.hpp"
|
||||
#include "ext_workspace.hpp"
|
||||
|
||||
namespace qs::wm::wayland {
|
||||
|
|
|
|||
41
src/wayland/wl_proxy_safe_deref.cpp
Normal file
41
src/wayland/wl_proxy_safe_deref.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#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
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include <qvariant.h>
|
||||
#include <qwayland-wlr-layer-shell-unstable-v1.h>
|
||||
#include <qwindow.h>
|
||||
#include <wayland-xdg-shell-client-protocol.h>
|
||||
|
||||
#include "../../window/panelinterface.hpp"
|
||||
#include "shell_integration.hpp"
|
||||
|
|
@ -247,9 +248,19 @@ void LayerSurface::commit() {
|
|||
}
|
||||
|
||||
void LayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface* popup) {
|
||||
std::any role = popup->surfaceRole();
|
||||
|
||||
if (auto* popupRole = std::any_cast<::xdg_popup*>(&role)) { // NOLINT
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD uses an alternate RTTI matching strategy by default which does
|
||||
// not work across modules, preventing std::any from downcasting. On
|
||||
// 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);
|
||||
} else {
|
||||
qWarning() << "Cannot attach popup" << popup << "to shell surface" << this
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ ProxyWindowBase::ProxyWindowBase(QObject* parent)
|
|||
|
||||
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) {
|
||||
if (this->mVisible) this->window = this->retrieveWindow(oldInstance);
|
||||
auto wasVisible = this->window != nullptr && this->window->isVisible();
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ public:
|
|||
explicit ProxyWindowBase(QObject* parent = nullptr);
|
||||
~ProxyWindowBase() override;
|
||||
|
||||
static ProxyWindowBase* forObject(QObject* obj);
|
||||
|
||||
ProxyWindowBase(ProxyWindowBase&) = delete;
|
||||
ProxyWindowBase(ProxyWindowBase&&) = delete;
|
||||
void operator=(ProxyWindowBase&) = delete;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue