Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions plugins/application-tray/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include <QDebug>
#include <QLoggingCategory>

Check warning on line 5 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QLoggingCategory> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "util.h"
#include "xcbthread.h"

#include <QSize>

Check warning on line 9 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QSize> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QPixmap>

Check warning on line 10 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QPixmap> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QBitmap>

Check warning on line 11 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QBitmap> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QFileInfo>

Check warning on line 12 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QFileInfo> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtGlobal>

Check warning on line 13 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtGlobal> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QSocketNotifier>

Check warning on line 14 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QSocketNotifier> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QCoreApplication>

Check warning on line 15 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QCoreApplication> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QAbstractEventDispatcher>

Check warning on line 16 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QAbstractEventDispatcher> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <X11/Xlib.h>

Check warning on line 18 in plugins/application-tray/util.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <X11/Xlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <mutex>
#include <xcb/res.h>
#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <xcb/xtest.h>
#include <xcb/xproto.h>
#include <xcb/composite.h>

Q_LOGGING_CATEGORY(TRAYUTIL, "org.deepin.dde.trayloader.util")

namespace tray {
void clean_xcb_image(void *data)
{
Expand All @@ -36,7 +41,29 @@
return _instance;
}

void Util::dispatchEvents(DispatchEventsMode mode)
{
xcb_connection_t *connection = m_x11connection;
if (!connection) {
qCWarning(TRAYUTIL, "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();
Comment on lines +52 to +57
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Guard against a null QAbstractEventDispatcher before calling filterNativeEvent.

QCoreApplication::eventDispatcher() may return nullptr during early startup or shutdown, which would cause a crash when calling dispatcher->filterNativeEvent(...). Please add a null check and skip processing if no dispatcher is available.

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("");
Expand All @@ -50,8 +77,20 @@
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()
Expand Down Expand Up @@ -143,6 +182,11 @@
return name;
}

xcb_atom_t Util::getAtomFromDisplay(const char * name)
{
return getAtomByName(xcb_atom_name_by_screen(name, DefaultScreen(getDisplay())));
Comment on lines +185 to +187
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Clarify the intent and correctness of getAtomFromDisplay’s Xlib/XCB interop and helper usage.

This currently mixes Xlib (DefaultScreen(getDisplay())) with an XCB helper, then forwards to getAtomByName. Please explain why this indirection is needed instead of calling getAtomByName(QString::fromLatin1(name)) directly, and confirm that xcb_atom_name_by_screen(...) behaves as expected here (no extra round-trips, correct encoding/screen handling). If it’s equivalent, simplifying to the direct call would reduce Xlib/XCB interop complexity.

}

void Util::moveX11Window(const xcb_window_t& window, const uint32_t& x, const uint32_t& y)
{
const uint32_t windowMoveConfigVals[2] = {x, y};
Expand Down
13 changes: 9 additions & 4 deletions plugins/application-tray/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <QImage>
#include <QSharedPointer>
#include <QSet>
#include <QObject>

#include <cstdint>
#include <sys/types.h>
Expand All @@ -20,8 +21,7 @@ struct _XDisplay;

namespace tray {
#define UTIL Util::instance()
class XcbThread;
class Util
class Util : public QObject
{

public:
Expand All @@ -34,6 +34,7 @@ class Util

xcb_atom_t getAtomByName(const QString& name);
QString getNameByAtom(const xcb_atom_t& atom);
xcb_atom_t getAtomFromDisplay(const char * name);

void moveX11Window(const xcb_window_t& window, const uint32_t& x, const uint32_t& y);
void setX11WindowSize(const xcb_window_t& window, const QSize& size);
Expand All @@ -58,6 +59,12 @@ class Util
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);
Expand All @@ -71,8 +78,6 @@ class Util
_XDisplay *m_display;

QSet<QString> m_currentIds;

XcbThread *m_xcbThread;
};

}
42 changes: 0 additions & 42 deletions plugins/application-tray/xcbthread.cpp

This file was deleted.

22 changes: 0 additions & 22 deletions plugins/application-tray/xcbthread.h

This file was deleted.

23 changes: 23 additions & 0 deletions plugins/application-tray/xembedprotocolhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <xcb/xcb.h>
#include <xcb/xtest.h>
#include <xcb/xcb_event.h>

#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
Expand All @@ -31,6 +32,8 @@ XembedProtocol::XembedProtocol(QObject *parent)
: AbstractTrayProtocol(parent)
, m_trayManager(new TrayManager("org.deepin.dde.TrayManager1", "/org/deepin/dde/TrayManager1", QDBusConnection::sessionBus(), this))
{
qApp->installNativeEventFilter(this);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Remove the native event filter in the destructor to avoid a dangling pointer in QCoreApplication.

QCoreApplication stores a raw pointer to the installed QAbstractNativeEventFilter. If XembedProtocol is destroyed without unregistering, the app may still invoke nativeEventFilter(...) on a freed object. Add qApp->removeNativeEventFilter(this); in the destructor to prevent a use-after-free during shutdown or protocol replacement.


m_trayManager->Manage();
connect(m_trayManager, &TrayManager::Added, this, &XembedProtocol::onTrayIconsChanged);
connect(m_trayManager, &TrayManager::Removed, this, &XembedProtocol::onTrayIconsChanged);
Expand All @@ -43,6 +46,26 @@ XembedProtocol::~XembedProtocol()
m_registedItem.clear();
}

bool XembedProtocol::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
{
Q_UNUSED(result)

if (eventType != "xcb_generic_event_t") {
return false;
}

auto *ev = static_cast<xcb_generic_event_t *>(message);

const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev);
if (responseType == XCB_LEAVE_NOTIFY) {
xcb_leave_notify_event_t *lE = (xcb_leave_notify_event_t *)ev;
UTIL->setX11WindowInputShape(lE->event, QSize(0, 0));
return true;
}

return false;
}

void XembedProtocol::onTrayIconsChanged()
{
QTimer::singleShot(200, this,[this](){
Expand Down
5 changes: 4 additions & 1 deletion plugins/application-tray/xembedprotocolhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
#include <xcb/xcb_image.h>

namespace tray {
class XembedProtocol : public AbstractTrayProtocol
class XembedProtocol : public AbstractTrayProtocol, public QAbstractNativeEventFilter
{
Q_OBJECT

public:
XembedProtocol(QObject *parent = nullptr);
~XembedProtocol();

protected:
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;

private Q_SLOTS:
void onTrayIconsChanged();

Expand Down