mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-04-10 06:11:54 +10:00
Compare commits
3 commits
a849a88893
...
6bcd3d9bbf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bcd3d9bbf | ||
|
|
c030300191 | ||
|
|
5721955686 |
5 changed files with 37 additions and 17 deletions
|
|
@ -50,6 +50,7 @@ set shell id.
|
||||||
- Fixed ClippingRectangle related crashes.
|
- Fixed ClippingRectangle related crashes.
|
||||||
- Fixed crashes when monitors are unplugged.
|
- Fixed crashes when monitors are unplugged.
|
||||||
- Fixed crashes when default pipewire devices are lost.
|
- Fixed crashes when default pipewire devices are lost.
|
||||||
|
- Desktop action order is now preserved.
|
||||||
|
|
||||||
## Packaging Changes
|
## Packaging Changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
wayland-protocols,
|
wayland-protocols,
|
||||||
wayland-scanner,
|
wayland-scanner,
|
||||||
xorg,
|
xorg,
|
||||||
|
libxcb ? xorg.libxcb,
|
||||||
libdrm,
|
libdrm,
|
||||||
libgbm ? null,
|
libgbm ? null,
|
||||||
vulkan-headers,
|
vulkan-headers,
|
||||||
|
|
@ -88,7 +89,7 @@
|
||||||
++ lib.optional (withWayland && lib.strings.compareVersions qt6.qtbase.version "6.10.0" == -1) qt6.qtwayland
|
++ lib.optional (withWayland && lib.strings.compareVersions qt6.qtbase.version "6.10.0" == -1) qt6.qtwayland
|
||||||
++ lib.optionals withWayland [ wayland wayland-protocols ]
|
++ lib.optionals withWayland [ wayland wayland-protocols ]
|
||||||
++ lib.optionals (withWayland && libgbm != null) [ libdrm libgbm vulkan-headers ]
|
++ lib.optionals (withWayland && libgbm != null) [ libdrm libgbm vulkan-headers ]
|
||||||
++ lib.optional withX11 xorg.libxcb
|
++ lib.optional withX11 libxcb
|
||||||
++ lib.optional withPam pam
|
++ lib.optional withPam pam
|
||||||
++ lib.optional withPipewire pipewire
|
++ lib.optional withPipewire pipewire
|
||||||
++ lib.optionals withPolkit [ polkit glib ];
|
++ lib.optionals withPolkit [ polkit glib ];
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,10 @@ ParsedDesktopEntryData DesktopEntry::parseText(const QString& id, const QString&
|
||||||
auto groupName = QString();
|
auto groupName = QString();
|
||||||
auto entries = QHash<QString, QPair<Locale, QString>>();
|
auto entries = QHash<QString, QPair<Locale, QString>>();
|
||||||
|
|
||||||
auto finishCategory = [&data, &groupName, &entries]() {
|
auto actionOrder = QStringList();
|
||||||
|
auto pendingActions = QHash<QString, DesktopActionData>();
|
||||||
|
|
||||||
|
auto finishCategory = [&data, &groupName, &entries, &actionOrder, &pendingActions]() {
|
||||||
if (groupName == "Desktop Entry") {
|
if (groupName == "Desktop Entry") {
|
||||||
if (entries.value("Type").second != "Application") return;
|
if (entries.value("Type").second != "Application") return;
|
||||||
|
|
||||||
|
|
@ -129,9 +132,10 @@ ParsedDesktopEntryData DesktopEntry::parseText(const QString& id, const QString&
|
||||||
else if (key == "Terminal") data.terminal = value == "true";
|
else if (key == "Terminal") data.terminal = value == "true";
|
||||||
else if (key == "Categories") data.categories = value.split(u';', Qt::SkipEmptyParts);
|
else if (key == "Categories") data.categories = value.split(u';', Qt::SkipEmptyParts);
|
||||||
else if (key == "Keywords") data.keywords = value.split(u';', Qt::SkipEmptyParts);
|
else if (key == "Keywords") data.keywords = value.split(u';', Qt::SkipEmptyParts);
|
||||||
|
else if (key == "Actions") actionOrder = value.split(u';', Qt::SkipEmptyParts);
|
||||||
}
|
}
|
||||||
} else if (groupName.startsWith("Desktop Action ")) {
|
} else if (groupName.startsWith("Desktop Action ")) {
|
||||||
auto actionName = groupName.sliced(16);
|
auto actionName = groupName.sliced(15);
|
||||||
DesktopActionData action;
|
DesktopActionData action;
|
||||||
action.id = actionName;
|
action.id = actionName;
|
||||||
|
|
||||||
|
|
@ -147,7 +151,7 @@ ParsedDesktopEntryData DesktopEntry::parseText(const QString& id, const QString&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.actions.insert(actionName, action);
|
pendingActions.insert(actionName, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.clear();
|
entries.clear();
|
||||||
|
|
@ -193,6 +197,13 @@ ParsedDesktopEntryData DesktopEntry::parseText(const QString& id, const QString&
|
||||||
}
|
}
|
||||||
|
|
||||||
finishCategory();
|
finishCategory();
|
||||||
|
|
||||||
|
for (const auto& actionId: actionOrder) {
|
||||||
|
if (pendingActions.contains(actionId)) {
|
||||||
|
data.actions.append(pendingActions.value(actionId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,17 +227,18 @@ void DesktopEntry::updateState(const ParsedDesktopEntryData& newState) {
|
||||||
this->updateActions(newState.actions);
|
this->updateActions(newState.actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesktopEntry::updateActions(const QHash<QString, DesktopActionData>& newActions) {
|
void DesktopEntry::updateActions(const QVector<DesktopActionData>& newActions) {
|
||||||
auto old = this->mActions;
|
auto old = this->mActions;
|
||||||
|
this->mActions.clear();
|
||||||
|
|
||||||
for (const auto& [key, d]: newActions.asKeyValueRange()) {
|
for (const auto& d: newActions) {
|
||||||
DesktopAction* act = nullptr;
|
DesktopAction* act = nullptr;
|
||||||
if (auto found = old.find(key); found != old.end()) {
|
auto found = std::ranges::find(old, d.id, &DesktopAction::mId);
|
||||||
act = found.value();
|
if (found != old.end()) {
|
||||||
|
act = *found;
|
||||||
old.erase(found);
|
old.erase(found);
|
||||||
} else {
|
} else {
|
||||||
act = new DesktopAction(d.id, this);
|
act = new DesktopAction(d.id, this);
|
||||||
this->mActions.insert(key, act);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::beginPropertyUpdateGroup();
|
Qt::beginPropertyUpdateGroup();
|
||||||
|
|
@ -237,6 +249,7 @@ void DesktopEntry::updateActions(const QHash<QString, DesktopActionData>& newAct
|
||||||
Qt::endPropertyUpdateGroup();
|
Qt::endPropertyUpdateGroup();
|
||||||
|
|
||||||
act->mEntries = d.entries;
|
act->mEntries = d.entries;
|
||||||
|
this->mActions.append(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* leftover: old) {
|
for (auto* leftover: old) {
|
||||||
|
|
@ -250,7 +263,7 @@ void DesktopEntry::execute() const {
|
||||||
|
|
||||||
bool DesktopEntry::isValid() const { return !this->bName.value().isEmpty(); }
|
bool DesktopEntry::isValid() const { return !this->bName.value().isEmpty(); }
|
||||||
|
|
||||||
QVector<DesktopAction*> DesktopEntry::actions() const { return this->mActions.values(); }
|
QVector<DesktopAction*> DesktopEntry::actions() const { return this->mActions; }
|
||||||
|
|
||||||
QVector<QString> DesktopEntry::parseExecString(const QString& execString) {
|
QVector<QString> DesktopEntry::parseExecString(const QString& execString) {
|
||||||
QVector<QString> arguments;
|
QVector<QString> arguments;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ struct ParsedDesktopEntryData {
|
||||||
QVector<QString> categories;
|
QVector<QString> categories;
|
||||||
QVector<QString> keywords;
|
QVector<QString> keywords;
|
||||||
QHash<QString, QString> entries;
|
QHash<QString, QString> entries;
|
||||||
QHash<QString, DesktopActionData> actions;
|
QVector<DesktopActionData> actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A desktop entry. See @@DesktopEntries for details.
|
/// A desktop entry. See @@DesktopEntries for details.
|
||||||
|
|
@ -164,10 +164,10 @@ public:
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateActions(const QHash<QString, DesktopActionData>& newActions);
|
void updateActions(const QVector<DesktopActionData>& newActions);
|
||||||
|
|
||||||
ParsedDesktopEntryData state;
|
ParsedDesktopEntryData state;
|
||||||
QHash<QString, DesktopAction*> mActions;
|
QVector<DesktopAction*> mActions;
|
||||||
|
|
||||||
friend class DesktopAction;
|
friend class DesktopAction;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -143,12 +143,17 @@ void PwCore::onSync(void* data, quint32 id, qint32 seq) {
|
||||||
void PwCore::onError(void* data, quint32 id, qint32 /*seq*/, qint32 res, const char* message) {
|
void PwCore::onError(void* data, quint32 id, qint32 /*seq*/, qint32 res, const char* message) {
|
||||||
auto* self = static_cast<PwCore*>(data);
|
auto* self = static_cast<PwCore*>(data);
|
||||||
|
|
||||||
if (message != nullptr) {
|
// Pipewire's documentation describes the error event as being fatal, however it isn't.
|
||||||
qCWarning(logLoop) << "Fatal pipewire error on object" << id << "with code" << res << message;
|
// We're not sure what causes these ENOENTs on device removal, presumably something in
|
||||||
} else {
|
// the teardown sequence, but they're harmless. Attempting to handle them as a fatal
|
||||||
qCWarning(logLoop) << "Fatal pipewire error on object" << id << "with code" << res;
|
// error causes unnecessary triggers for shells.
|
||||||
|
if (res == -ENOENT) {
|
||||||
|
qCDebug(logLoop) << "Pipewire ENOENT on object" << id << "with code" << res << message;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qCWarning(logLoop) << "Pipewire error on object" << id << "with code" << res << message;
|
||||||
|
|
||||||
emit self->fatalError();
|
emit self->fatalError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue