diff --git a/changelog/next.md b/changelog/next.md index 7b7ee40..53b50c8 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -4,6 +4,10 @@ - Added support for wayland idle timeouts. - Added the ability to override Quickshell.cacheDir with a custom path. +## Other Changes + +- IPC operations filter available instances to the current display connection by default. + ## Bug Fixes - Fixed volume control breaking with pipewire pro audio mode. diff --git a/src/core/instanceinfo.cpp b/src/core/instanceinfo.cpp index 7f0132b..1f71b8a 100644 --- a/src/core/instanceinfo.cpp +++ b/src/core/instanceinfo.cpp @@ -3,12 +3,14 @@ #include QDataStream& operator<<(QDataStream& stream, const InstanceInfo& info) { - stream << info.instanceId << info.configPath << info.shellId << info.launchTime << info.pid; + stream << info.instanceId << info.configPath << info.shellId << info.launchTime << info.pid + << info.display; return stream; } QDataStream& operator>>(QDataStream& stream, InstanceInfo& info) { - stream >> info.instanceId >> info.configPath >> info.shellId >> info.launchTime >> info.pid; + stream >> info.instanceId >> info.configPath >> info.shellId >> info.launchTime >> info.pid + >> info.display; return stream; } diff --git a/src/core/instanceinfo.hpp b/src/core/instanceinfo.hpp index 98ce614..d462f6e 100644 --- a/src/core/instanceinfo.hpp +++ b/src/core/instanceinfo.hpp @@ -11,6 +11,7 @@ struct InstanceInfo { QString shellId; QDateTime launchTime; pid_t pid = -1; + QString display; static InstanceInfo CURRENT; // NOLINT }; diff --git a/src/core/paths.cpp b/src/core/paths.cpp index 1424d2b..70e1bd1 100644 --- a/src/core/paths.cpp +++ b/src/core/paths.cpp @@ -411,7 +411,7 @@ bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info, bool allowD } QPair, QVector> -QsPaths::collectInstances(const QString& path) { +QsPaths::collectInstances(const QString& path, const QString& display) { qCDebug(logPaths) << "Collecting instances from" << path; auto liveInstances = QVector(); auto deadInstances = QVector(); @@ -425,6 +425,11 @@ QsPaths::collectInstances(const QString& path) { qCDebug(logPaths).nospace() << "Found instance " << info.instance.instanceId << " (pid " << info.pid << ") at " << path; + if (!display.isEmpty() && info.instance.display != display) { + qCDebug(logPaths) << "Skipped instance with mismatched display at" << path; + continue; + } + if (info.pid == -1) { deadInstances.push_back(info); } else { diff --git a/src/core/paths.hpp b/src/core/paths.hpp index 1c10758..c2500ed 100644 --- a/src/core/paths.hpp +++ b/src/core/paths.hpp @@ -30,7 +30,7 @@ public: static bool checkLock(const QString& path, InstanceLockInfo* info = nullptr, bool allowDead = false); static QPair, QVector> - collectInstances(const QString& path); + collectInstances(const QString& path, const QString& display); QDir* baseRunDir(); QDir* shellRunDir(); diff --git a/src/launch/command.cpp b/src/launch/command.cpp index e63498a..18dcc43 100644 --- a/src/launch/command.cpp +++ b/src/launch/command.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -178,7 +179,8 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance, bool deadFallb } } else if (!cmd.instance.id->isEmpty()) { path = basePath->filePath("by-pid"); - auto [liveInstances, deadInstances] = QsPaths::collectInstances(path); + auto [liveInstances, deadInstances] = + QsPaths::collectInstances(path, cmd.config.anyDisplay ? "" : getDisplayConnection()); liveInstances.removeIf([&](const InstanceLockInfo& info) { return !info.instance.instanceId.startsWith(*cmd.instance.id); @@ -228,7 +230,8 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance, bool deadFallb path = QDir(basePath->filePath("by-path")).filePath(pathId); - auto [liveInstances, deadInstances] = QsPaths::collectInstances(path); + auto [liveInstances, deadInstances] = + QsPaths::collectInstances(path, cmd.config.anyDisplay ? "" : getDisplayConnection()); auto instances = liveInstances; if (instances.isEmpty() && deadFallback) { @@ -311,7 +314,10 @@ int listInstances(CommandState& cmd) { path = QDir(basePath->filePath("by-path")).filePath(pathId); } - auto [liveInstances, deadInstances] = QsPaths::collectInstances(path); + auto [liveInstances, deadInstances] = QsPaths::collectInstances( + path, + cmd.config.anyDisplay || cmd.instance.all ? "" : getDisplayConnection() + ); sortInstances(liveInstances, cmd.config.newest); @@ -373,6 +379,7 @@ int listInstances(CommandState& cmd) { << " Process ID: " << instance.instance.pid << '\n' << " Shell ID: " << instance.instance.shellId << '\n' << " Config path: " << instance.instance.configPath << '\n' + << " Display connection: " << instance.instance.display << '\n' << " Launch time: " << launchTimeStr << (isDead ? "" : " (running for " + runtimeStr + ")") << '\n' << (gray ? "\033[0m" : ""); @@ -545,4 +552,18 @@ int runCommand(int argc, char** argv, QCoreApplication* coreApplication) { return 0; } +QString getDisplayConnection() { + auto platform = qEnvironmentVariable("QT_QPA_PLATFORM"); + auto wlDisplay = qEnvironmentVariable("WAYLAND_DISPLAY"); + auto xDisplay = qEnvironmentVariable("DISPLAY"); + + if (platform == "wayland" || (platform.isEmpty() && !wlDisplay.isEmpty())) { + return "wayland," + wlDisplay; + } else if (platform == "xcb" || (platform.isEmpty() && !xDisplay.isEmpty())) { + return "x11," + xDisplay; + } else { + return "unk," + QGuiApplication::platformName(); + } +} + } // namespace qs::launch diff --git a/src/launch/launch.cpp b/src/launch/launch.cpp index 101820e..f269f61 100644 --- a/src/launch/launch.cpp +++ b/src/launch/launch.cpp @@ -134,6 +134,7 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio .shellId = shellId, .launchTime = qs::Common::LAUNCH_TIME, .pid = getpid(), + .display = getDisplayConnection(), }; #if CRASH_REPORTER diff --git a/src/launch/launch_p.hpp b/src/launch/launch_p.hpp index 7b8fca6..a186ddb 100644 --- a/src/launch/launch_p.hpp +++ b/src/launch/launch_p.hpp @@ -50,6 +50,7 @@ struct CommandState { QStringOption manifest; QStringOption name; bool newest = false; + bool anyDisplay = false; } config; struct { @@ -106,6 +107,8 @@ void exitDaemon(int code); int parseCommand(int argc, char** argv, CommandState& state); int runCommand(int argc, char** argv, QCoreApplication* coreApplication); +QString getDisplayConnection(); + int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplication); } // namespace qs::launch diff --git a/src/launch/parsecommand.cpp b/src/launch/parsecommand.cpp index fc16086..c12d9b9 100644 --- a/src/launch/parsecommand.cpp +++ b/src/launch/parsecommand.cpp @@ -16,7 +16,7 @@ int parseCommand(int argc, char** argv, CommandState& state) { .argv = argv, }; - auto addConfigSelection = [&](CLI::App* cmd, bool withNewestOption = false) { + auto addConfigSelection = [&](CLI::App* cmd, bool filtering = false) { auto* group = cmd->add_option_group("Config Selection") ->description( @@ -49,9 +49,13 @@ int parseCommand(int argc, char** argv, CommandState& state) { ->envname("QS_MANIFEST") ->excludes(path); - if (withNewestOption) { + if (filtering) { group->add_flag("-n,--newest", state.config.newest) ->description("Operate on the most recently launched instance instead of the oldest"); + + group->add_flag("--any-display", state.config.anyDisplay) + ->description("If passed, instances will not be filtered by the display connection they " + "were launched on."); } return group;