Adaptitions for kWin support on Flatpak

This commit is contained in:
WarmUpTill
2026-08-17 19:31:03 +02:00
parent e11499c308
commit bc17f0c708
4 changed files with 124 additions and 20 deletions

View File

@@ -1,5 +1,16 @@
#include "platform-funcs.hpp"
#include "log-helper.hpp"
#include "obs-module-helper.hpp"
#include "plugin-state-helpers.hpp"
#include "ui-helpers.hpp"
#include <obs-frontend-api.h>
#include <QCheckBox>
#include <QFontDatabase>
#include <QGridLayout>
#include <QLineEdit>
#include <QMessageBox>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
@@ -628,27 +639,108 @@ int ignoreXerror(Display *d, XErrorEvent *e)
return 0;
}
static bool warnAboutWindowDetectionUnavailable = true;
static bool setupWindowDetectionWarningPersistence = []() {
AddSaveStep([](obs_data_t *obj) {
obs_data_set_bool(obj, "warnAboutFlatpakWindowDetection",
warnAboutWindowDetectionUnavailable);
});
AddLoadStep([](obs_data_t *obj) {
obs_data_set_default_bool(
obj, "warnAboutFlatpakWindowDetection", true);
warnAboutWindowDetectionUnavailable = obs_data_get_bool(
obj, "warnAboutFlatpakWindowDetection");
});
return true;
}();
static void showWindowDetectionWarning(const char *messageId,
const char *command)
{
auto mainWindow =
static_cast<QWidget *>(obs_frontend_get_main_window());
QMessageBox msgBox(QMessageBox::Warning,
obs_module_text("AdvSceneSwitcher.pluginName"),
obs_module_text(messageId), QMessageBox::Ok,
mainWindow);
if (command) {
auto commandLineEdit = new QLineEdit(command, &msgBox);
commandLineEdit->setReadOnly(true);
commandLineEdit->setFont(
QFontDatabase::systemFont(QFontDatabase::FixedFont));
commandLineEdit->setCursorPosition(0);
auto layout = qobject_cast<QGridLayout *>(msgBox.layout());
if (layout) {
layout->addWidget(commandLineEdit, layout->rowCount(),
0, 1, layout->columnCount());
}
}
auto checkbox = new QCheckBox(obs_module_text(
"AdvSceneSwitcher.flatpakWindowDetectionWarning.doNotShowAgain"));
msgBox.setCheckBox(checkbox);
msgBox.exec();
warnAboutWindowDetectionUnavailable = !checkbox->isChecked();
}
static void handleWindowDetectionUnavailable(bool hasX11)
{
if (hasX11 || KWin) {
return;
}
if (!qEnvironmentVariableIsSet("FLATPAK_ID")) {
return;
}
const bool onKDE = qEnvironmentVariable("XDG_CURRENT_DESKTOP")
.contains("KDE", Qt::CaseInsensitive);
const char *messageId =
onKDE ? "AdvSceneSwitcher.kwin.flatpakPermissionWarning"
: "AdvSceneSwitcher.wayland.flatpakPermissionWarning";
const char *command =
onKDE ? "flatpak override --user --talk-name=org.kde.KWin com.obsproject.Studio"
: nullptr;
blog(LOG_WARNING,
"window detection unavailable: OBS Flatpak sandbox has no X11 "
"access on this Wayland session and %s",
onKDE ? "the KWin D-Bus compat call was blocked (missing "
"'org.kde.KWin' talk-name permission)"
: "no compatible native Wayland integration exists for "
"this desktop");
AddFinishedLoadingStep([messageId, command]() {
if (!warnAboutWindowDetectionUnavailable) {
return;
}
showWindowDetectionWarning(messageId, command);
});
}
void PlatformInit()
{
const bool kwinAvailable = isKWinAvailable();
KWin = kwinAvailable && registerKWinDBusListener(&notifier) &&
startKWinScript(KWinScriptObjectPath);
if (KWin) {
blog(LOG_INFO, "using KWin compat");
} else {
blog(LOG_INFO, "not using KWin compat");
}
initProcps();
initProc2();
auto display = disp();
handleWindowDetectionUnavailable(display != nullptr);
if (!display) {
return;
}
KWin = isKWinAvailable();
if (!(KWin && startKWinScript(KWinScriptObjectPath) &&
registerKWinDBusListener(&notifier))) {
// something bad happened while trying to initialize
// the KWin script/dbus so disable it
KWin = false;
blog(LOG_INFO, "not using KWin compat");
} else {
blog(LOG_INFO, "using KWin compat");
}
initXss();
initProcps();
initProc2();
XSetErrorHandler(ignoreXerror);
}

View File

@@ -5,6 +5,7 @@
#include <QDir>
#include <QFile>
#include <QFileDevice>
#include <QStandardPaths>
#include <QTextStream>
#include <QtDBus/QDBusConnectionInterface>
#include <QtDBus/QDBusInterface>
@@ -96,12 +97,16 @@ bool isKWinAvailable()
bool startKWinScript(QString &scriptObjectPath)
{
// Not RuntimeLocation: under Flatpak, $XDG_RUNTIME_DIR is private to
// the sandbox, so the unsandboxed KWin process can't read it back.
const QString scriptPath =
"/tmp/AdvancedSceneSwitcher/KWinFocusNotifier.js";
QStandardPaths::writableLocation(
QStandardPaths::CacheLocation) +
"/AdvancedSceneSwitcher/KWinFocusNotifier.js";
const QString script =
R"(var adss = "com.github.AdvancedSceneSwitcher";
var adssPath = "/com/github/AdvancedSceneSwitcher";
R"(var adss = "com.obsproject.Studio.Plugin.SceneSwitcher";
var adssPath = "/com/obsproject/Studio/Plugin/SceneSwitcher";
function trackWindow(window) {
var id = window.internalId.toString();
@@ -129,7 +134,8 @@ workspace.windowActivated.connect(function(client) {
}))";
if (const QDir dir; !dir.mkpath(QFileInfo(scriptPath).absolutePath())) {
blog(LOG_ERROR, "error creating /tmp/AdvancedSceneSwitcher");
blog(LOG_ERROR,
"error creating KWinFocusNotifier script directory");
return false;
}
@@ -198,8 +204,10 @@ bool stopKWinScript(const QString &scriptObjectPath)
bool registerKWinDBusListener(FocusNotifier *notifier)
{
static const QString serviceName = "com.github.AdvancedSceneSwitcher";
static const QString objectPath = "/com/github/AdvancedSceneSwitcher";
static const QString serviceName =
"com.obsproject.Studio.Plugin.SceneSwitcher";
static const QString objectPath =
"/com/obsproject/Studio/Plugin/SceneSwitcher";
auto bus = QDBusConnection::sessionBus();
if (bus.objectRegisteredAt(objectPath)) {

View File

@@ -12,7 +12,8 @@ namespace advss {
class FocusNotifier final : public QObject {
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.github.AdvancedSceneSwitcher")
Q_CLASSINFO("D-Bus Interface",
"com.obsproject.Studio.Plugin.SceneSwitcher")
static std::mutex _mutex;
static int activePID;