chore: no longer rely on qpa x11 platform

This commit is contained in:
2025-12-25 13:39:17 +08:00
parent b0df2b9e27
commit faf5b43e2b
4 changed files with 57 additions and 6 deletions

View File

@@ -32,7 +32,7 @@ using Util = tray::Util;
FdoSelectionManager::FdoSelectionManager()
: QObject()
, m_selectionOwner(new KSelectionOwner(Util::instance()->getAtomFromDisplay("_NET_SYSTEM_TRAY"), -1, this))
, m_selectionOwner(new KSelectionOwner(UTIL->getAtomFromDisplay("_NET_SYSTEM_TRAY"), UTIL->getX11Connection(), UTIL->getRootWindow(), this))
{
qDebug(SNIPROXY) << "starting";

View File

@@ -10,6 +10,7 @@
#include "fdoselectionmanager.h"
#include "debug.h"
#include "util.h"
#ifdef None
#ifndef FIXX11H_None
@@ -25,18 +26,22 @@ inline constexpr XID None = XNone;
#include <KWindowSystem>
using Util = tray::Util;
int main(int argc, char **argv)
{
// the whole point of this is to interact with X, if we are in any other session, force trying to connect to X
// if the QPA can't load xcb, this app is useless anyway.
qputenv("QT_QPA_PLATFORM", "xcb");
qputenv("QT_QPA_PLATFORM", "wayland");
qputenv("WAYLAND_DISPLAY", "dockplugin");
qputenv("QT_WAYLAND_SHELL_INTEGRATION", "plugin-shell");
QGuiApplication::setDesktopSettingsAware(false);
QCoreApplication::setAttribute(Qt::AA_DisableSessionManager);
QGuiApplication app(argc, argv);
if (!KWindowSystem::isPlatformX11()) {
if (!UTIL->isXAvaliable()) {
qFatal("xembed-traymanager-proxy requires X11. Aborting");
}

View File

@@ -4,6 +4,8 @@
#include <QDebug>
#include "debug.h"
#include "util.h"
#include "xcbthread.h"
@@ -12,6 +14,9 @@
#include <QBitmap>
#include <QFileInfo>
#include <QtGlobal>
#include <QSocketNotifier>
#include <QCoreApplication>
#include <QAbstractEventDispatcher>
#include <X11/Xlib.h>
@@ -37,7 +42,29 @@ Util* Util::instance()
return _instance;
}
void Util::dispatchEvents(DispatchEventsMode mode)
{
xcb_connection_t *connection = m_x11connection;
if (!connection) {
qCWarning(SNIPROXY, "Attempting to dispatch X11 events with no connection");
return;
}
auto pollEventFunc = mode == DispatchEventsMode::Poll ? xcb_poll_for_event : xcb_poll_for_queued_event;
while (xcb_generic_event_t *event = pollEventFunc(connection)) {
qintptr result = 0;
QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
dispatcher->filterNativeEvent(QByteArrayLiteral("xcb_generic_event_t"), event, &result);
free(event);
}
xcb_flush(connection);
}
Util::Util()
: QObject()
{
m_x11connection = xcb_connect(nullptr, nullptr);
m_display = XOpenDisplay("");
@@ -51,8 +78,20 @@ Util::Util()
m_rootWindow = screen->root;
xcb_ewmh_init_atoms_replies(&m_ewmh, xcb_ewmh_init_atoms(m_x11connection, &m_ewmh), nullptr);
m_xcbThread = new XcbThread(m_x11connection);
m_xcbThread->start();
const int fd = xcb_get_file_descriptor(m_x11connection);
QSocketNotifier * qfd = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(qfd, &QSocketNotifier::activated, this, [this](){
dispatchEvents(DispatchEventsMode::Poll);
});
QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
connect(dispatcher, &QAbstractEventDispatcher::aboutToBlock, this, [this]() {
dispatchEvents(DispatchEventsMode::EventQueue);
});
connect(dispatcher, &QAbstractEventDispatcher::awake, this, [this]() {
dispatchEvents(DispatchEventsMode::EventQueue);
});
}
Util::~Util()

9
util.h
View File

@@ -8,6 +8,7 @@
#include <QImage>
#include <QSharedPointer>
#include <QSet>
#include <QObject>
#include <cstdint>
#include <sys/types.h>
@@ -21,7 +22,7 @@ struct _XDisplay;
namespace tray {
#define UTIL Util::instance()
class XcbThread;
class Util
class Util : public QObject
{
public:
@@ -59,6 +60,12 @@ private:
Util(const Util&) = delete;
Util& operator=(const Util&) = delete;
enum class DispatchEventsMode {
Poll,
EventQueue
};
void dispatchEvents(DispatchEventsMode mode);
bool isTransparentImage(const QImage &image);
QImage convertFromNative(xcb_image_t* image);