QSystemTrayIcon/X11: Move platform-specific calls to the xcb plugin

- Detect the tray icon window in the platform plugin by the object
  name. This way we don't need
  QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier().

- Get rid of unused calls
  QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannel()
  and QXcbWindowFunctions::setParentRelativeBackPixmap().

- Mark the tray icon window as embedded to be able to get the correct
  result from QWindow::mapToGlobal(). It allows to drop
  QXcbWindowFunctions::systemTrayWindowGlobalGeometry().

This change allows to remove the intermediate level between
the QSystemTrayIconSys widget and the xcb plugin. The code looks
clearer.

Change-Id: I7d067131287a6dec162b36f0bddc8cb518aaa38c
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
bb10
Alexander Volkov 2015-10-30 18:15:18 +03:00 committed by Gatis Paeglis
parent 5cf6f51b4c
commit 556221d97b
13 changed files with 12 additions and 311 deletions

View File

@ -1,60 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QXCBINTEGRATIONFUNCTIONS_H
#define QXCBINTEGRATIONFUNCTIONS_H
#include <QtPlatformHeaders/QPlatformHeaderHelper>
QT_BEGIN_NAMESPACE
class QXcbIntegrationFunctions
{
public:
typedef bool (*XEmbedSystemTrayVisualHasAlphaChannel)();
static const QByteArray xEmbedSystemTrayVisualHasAlphaChannelIdentifier() { return QByteArrayLiteral("XcbXEmbedSystemTrayVisualHasAlphaChannel"); }
static bool xEmbedSystemTrayVisualHasAlphaChannel()
{
return QPlatformHeaderHelper::callPlatformFunction<bool, XEmbedSystemTrayVisualHasAlphaChannel>(xEmbedSystemTrayVisualHasAlphaChannelIdentifier());
}
};
QT_END_NAMESPACE
#endif /*QXCBINTEGRATIONFUNCTIONS_H*/

View File

@ -90,27 +90,6 @@ public:
return QPlatformHeaderHelper::callPlatformFunction<void, SetWmWindowIconText, QWindow *, const QString &>(setWmWindowIconTextIdentifier(), window, text);
}
typedef void (*SetParentRelativeBackPixmap)(const QWindow *window);
static const QByteArray setParentRelativeBackPixmapIdentifier() { return QByteArrayLiteral("XcbSetParentRelativeBackPixmap"); }
static void setParentRelativeBackPixmap(const QWindow *window)
{
return QPlatformHeaderHelper::callPlatformFunction<void, SetParentRelativeBackPixmap, const QWindow *>(setParentRelativeBackPixmapIdentifier(), window);
}
typedef bool (*RequestSystemTrayWindowDock)(const QWindow *window);
static const QByteArray requestSystemTrayWindowDockIdentifier() { return QByteArrayLiteral("XcbRequestSystemTrayWindowDockIdentifier"); }
static bool requestSystemTrayWindowDock(const QWindow *window)
{
return QPlatformHeaderHelper::callPlatformFunction<bool, RequestSystemTrayWindowDock, const QWindow *>(requestSystemTrayWindowDockIdentifier(), window);
}
typedef QRect (*SystemTrayWindowGlobalGeometry)(const QWindow *window);
static const QByteArray systemTrayWindowGlobalGeometryIdentifier() { return QByteArrayLiteral("XcbSystemTrayWindowGlobalGeometryIdentifier"); }
static QRect systemTrayWindowGlobalGeometry(const QWindow *window)
{
return QPlatformHeaderHelper::callPlatformFunction<QRect, SystemTrayWindowGlobalGeometry, const QWindow *>(systemTrayWindowGlobalGeometryIdentifier(), window);
}
typedef uint (*VisualId)(QWindow *window);
static const QByteArray visualIdIdentifier() { return QByteArrayLiteral("XcbVisualId"); }

View File

@ -137,81 +137,6 @@
relayed to the function retrieved by QGuiApplication.
*/
/*!
\typedef QXcbWindowFunctions::SetParentRelativeBackPixmap
This is the typedef for the function returned by
QGuiApplication::platformFunction when passed the
value returned by setParentRelativeBackPixmapIdentifier().
*/
/*!
\fn const QByteArray QXcbWindowFunctions::setParentRelativeBackPixmapIdentifier()
This function returns the byte array that can be used to query
QGuiApplication::platformFunction to retrieve the SetParentRelativeBackPixmap function.
*/
/*!
\fn void QXcbWindowFunctions::setParentRelativeBackPixmap(const QWindow *window)
This is a convenience function that can be used directly instead
of resolving the function pointer. \a window will be
relayed to the function retrieved by QGuiApplication.
*/
/*!
\typedef QXcbWindowFunctions::RequestSystemTrayWindowDock
This is the typedef for the function returned by
QGuiApplication::platformFunction when passed the
value returned by requestSystemTrayWindowDockIdentifier().
*/
/*!
\fn const QByteArray QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier()
This function returns the byte array that can be used to query
QGuiApplication::platformFunction to retrieve the RequestSystemTrayWindowDock function.
*/
/*!
\fn bool QXcbWindowFunctions::requestSystemTrayWindowDock(const QWindow *window)
This is a convenience function that can be used directly instead
of resolving the function pointer. \a window will be
relayed to the function retrieved by QGuiApplication.
Returns the boolean result of calling the function or false if the
function was not found.
*/
/*!
\typedef QXcbWindowFunctions::SystemTrayWindowGlobalGeometry
This is the typedef for the function returned by
QGuiApplication::platformFunction when passed the
value returned by systemTrayWindowGlobalGeometryIdentifier().
*/
/*!
\fn const QByteArray QXcbWindowFunctions::systemTrayWindowGlobalGeometryIdentifier()
This function returns the byte array that can be used to query
QGuiApplication::platformFunction to retrieve the SystemTrayWindowGlobalGeometry function.
*/
/*!
\fn QRect QXcbWindowFunctions::systemTrayWindowGlobalGeometry(const QWindow *window)
This is a convenience function that can be used directly instead
of resolving the function pointer. \a window will be
relayed to the function retrieved by QGuiApplication.
Returns the QRect result of calling the function or an empty
QRect if the function was not found.
*/
/*!
\typedef QXcbWindowFunctions::VisualId

View File

@ -1,4 +1,3 @@
HEADERS += \
$$PWD/qxcbwindowfunctions.h \
$$PWD/qxcbintegrationfunctions.h \
$$PWD/qxcbscreenfunctions.h

View File

@ -2287,22 +2287,6 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const
return m_systemTrayTracker;
}
bool QXcbConnection::xEmbedSystemTrayAvailable()
{
if (!QGuiApplicationPrivate::platformIntegration())
return false;
QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection();
return connection->systemTrayTracker();
}
bool QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel()
{
if (!QGuiApplicationPrivate::platformIntegration())
return false;
QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection();
return connection->systemTrayTracker() && connection->systemTrayTracker()->visualHasAlphaChannel();
}
Qt::MouseButtons QXcbConnection::queryMouseButtons() const
{
int stateMask = 0;

View File

@ -506,8 +506,6 @@ public:
QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; }
QXcbSystemTrayTracker *systemTrayTracker() const;
static bool xEmbedSystemTrayAvailable();
static bool xEmbedSystemTrayVisualHasAlphaChannel();
Qt::MouseButtons queryMouseButtons() const;
Qt::KeyboardModifiers queryKeyboardModifiers() const;

View File

@ -54,7 +54,6 @@
#include <QtGui/qscreen.h>
#include <QtPlatformHeaders/qxcbwindowfunctions.h>
#include <QtPlatformHeaders/qxcbintegrationfunctions.h>
#include <QtPlatformHeaders/qxcbscreenfunctions.h>
#include <stdio.h>
@ -106,21 +105,6 @@ static inline QXcbSystemTrayTracker *systemTrayTracker(const QScreen *s)
return static_cast<const QXcbScreen *>(s->handle())->connection()->systemTrayTracker();
}
bool QXcbNativeInterface::systemTrayAvailable(const QScreen *screen) const
{
return systemTrayTracker(screen);
}
bool QXcbNativeInterface::requestSystemTrayWindowDock(const QWindow *window)
{
return QXcbWindow::requestSystemTrayWindowDockStatic(window);
}
QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window)
{
return QXcbWindow::systemTrayWindowGlobalGeometryStatic(window);
}
xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen)
{
if (m_sysTraySelectionAtom == XCB_ATOM_NONE) {
@ -140,16 +124,6 @@ xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const
return sel_owner_r->owner;
}
bool QXcbNativeInterface::systrayVisualHasAlphaChannel()
{
return QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel();
}
void QXcbNativeInterface::setParentRelativeBackPixmap(QWindow *window)
{
QXcbWindow::setParentRelativeBackPixmapStatic(window);
}
void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
{
QByteArray lowerCaseResource = resourceString.toLower();
@ -371,18 +345,6 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio
if (function == QXcbWindowFunctions::setWmWindowIconTextIdentifier())
return QFunctionPointer(QXcbWindowFunctions::SetWmWindowIconText(QXcbWindow::setWindowIconTextStatic));
if (function == QXcbWindowFunctions::setParentRelativeBackPixmapIdentifier())
return QFunctionPointer(QXcbWindowFunctions::SetParentRelativeBackPixmap(QXcbWindow::setParentRelativeBackPixmapStatic));
if (function == QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier())
return QFunctionPointer(QXcbWindowFunctions::RequestSystemTrayWindowDock(QXcbWindow::requestSystemTrayWindowDockStatic));
if (function == QXcbWindowFunctions::systemTrayWindowGlobalGeometryIdentifier())
return QFunctionPointer(QXcbWindowFunctions::SystemTrayWindowGlobalGeometry(QXcbWindow::systemTrayWindowGlobalGeometryStatic));
if (function == QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannelIdentifier())
return QFunctionPointer(QXcbIntegrationFunctions::XEmbedSystemTrayVisualHasAlphaChannel(QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel));
if (function == QXcbWindowFunctions::visualIdIdentifier()) {
return QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic));
}

View File

@ -122,11 +122,6 @@ public:
QXcbConnection::PeekOptions option = QXcbConnection::PeekDefault,
qint32 peekerId = -1);
Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const;
Q_INVOKABLE void setParentRelativeBackPixmap(QWindow *window);
Q_INVOKABLE bool systrayVisualHasAlphaChannel();
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
Q_INVOKABLE QString dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const;
Q_INVOKABLE QString dumpNativeWindows(WId root = 0) const;

View File

@ -91,8 +91,7 @@ xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *conne
return reply->owner;
}
// API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Request a window
// to be docked on the tray.
// Request a window to be docked on the tray.
void QXcbSystemTrayTracker::requestSystemTrayWindowDock(xcb_window_t window) const
{
xcb_client_message_event_t trayRequest;
@ -122,23 +121,6 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow()
return m_trayWindow;
}
// API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Return the geometry of a
// a window parented on the tray. Determines the global geometry via XCB since mapToGlobal
// does not work for the QWindow parented on the tray.
QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const
{
xcb_connection_t *conn = m_connection->xcb_connection();
auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window);
if (!geomReply)
return QRect();
auto translateReply = Q_XCB_REPLY(xcb_translate_coordinates, conn, window, m_connection->rootWindow(), 0, 0);
if (!translateReply)
return QRect();
return QRect(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height));
}
inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged()
{
if (const QPlatformScreen *ps = m_connection->primaryScreen())
@ -170,16 +152,6 @@ xcb_visualid_t QXcbSystemTrayTracker::visualId()
return visual;
}
bool QXcbSystemTrayTracker::visualHasAlphaChannel()
{
const xcb_visualid_t systrayVisualId = netSystemTrayVisual();
if (systrayVisualId != XCB_NONE) {
quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId);
return depth == 32;
}
return false;
}
xcb_visualid_t QXcbSystemTrayTracker::netSystemTrayVisual()
{
if (m_trayWindow == XCB_WINDOW_NONE)

View File

@ -57,14 +57,12 @@ public:
xcb_window_t trayWindow();
void requestSystemTrayWindowDock(xcb_window_t window) const;
QRect systemTrayWindowGlobalGeometry(xcb_window_t window) const;
void notifyManagerClientMessageEvent(const xcb_client_message_event_t *);
void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *) override;
xcb_visualid_t visualId();
bool visualHasAlphaChannel();
signals:
void systemTrayWindowChanged(QScreen *screen);

View File

@ -558,6 +558,9 @@ void QXcbWindow::create()
QByteArray wmWindowRole = window()->property(wm_window_role_property_id).toByteArray();
setWmWindowRole(wmWindowRole);
}
if (m_trayIconWindow)
m_embedded = requestSystemTrayWindowDock();
}
QXcbWindow::~QXcbWindow()
@ -792,7 +795,7 @@ void QXcbWindow::show()
else if (connection()->time() != XCB_TIME_CURRENT_TIME)
updateNetWmUserTime(connection()->time());
if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow"))
if (m_trayIconWindow)
return; // defer showing until XEMBED_EMBEDDED_NOTIFY
xcb_map_window(xcb_connection(), m_window);
@ -1793,12 +1796,6 @@ void QXcbWindow::setWmWindowRole(const QByteArray &role)
role.size(), role.constData());
}
void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window)
{
if (window->handle())
static_cast<QXcbWindow *>(window->handle())->setParentRelativeBackPixmap();
}
void QXcbWindow::setParentRelativeBackPixmap()
{
const quint32 mask = XCB_CW_BACK_PIXMAP;
@ -1806,14 +1803,7 @@ void QXcbWindow::setParentRelativeBackPixmap()
xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
}
bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window)
{
if (window->handle())
return static_cast<QXcbWindow *>(window->handle())->requestSystemTrayWindowDock();
return false;
}
bool QXcbWindow::requestSystemTrayWindowDock() const
bool QXcbWindow::requestSystemTrayWindowDock()
{
if (!connection()->systemTrayTracker())
return false;
@ -1821,20 +1811,6 @@ bool QXcbWindow::requestSystemTrayWindowDock() const
return true;
}
QRect QXcbWindow::systemTrayWindowGlobalGeometryStatic(const QWindow *window)
{
if (window->handle())
return static_cast<QXcbWindow *>(window->handle())->systemTrayWindowGlobalGeometry();
return QRect();
}
QRect QXcbWindow::systemTrayWindowGlobalGeometry() const
{
if (!connection()->systemTrayTracker())
return QRect();
return connection()->systemTrayTracker()->systemTrayWindowGlobalGeometry(m_window);
}
class ExposeCompressor
{
public:
@ -2094,7 +2070,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
updateNetWmUserTime(timestamp);
if (m_embedded) {
if (m_embedded && !m_trayIconWindow) {
if (window() != QGuiApplication::focusWindow()) {
const QXcbWindow *container = static_cast<const QXcbWindow *>(parent());
Q_ASSERT(container != 0);
@ -2554,7 +2530,7 @@ bool QXcbWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
case QEvent::FocusIn:
if (m_embedded && !event->spontaneous()) {
if (m_embedded && !m_trayIconWindow && !event->spontaneous()) {
QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
switch (focusEvent->reason()) {
case Qt::TabFocusReason:

View File

@ -159,14 +159,8 @@ public:
static void setWindowIconTextStatic(QWindow *window, const QString &text);
static void setParentRelativeBackPixmapStatic(QWindow *window);
void setParentRelativeBackPixmap();
static bool requestSystemTrayWindowDockStatic(const QWindow *window);
bool requestSystemTrayWindowDock() const;
static QRect systemTrayWindowGlobalGeometryStatic(const QWindow *window);
QRect systemTrayWindowGlobalGeometry() const;
bool requestSystemTrayWindowDock();
uint visualId() const;
bool needsSync() const;

View File

@ -63,8 +63,6 @@
#include <private/qguiapplication_p.h>
#include <qdebug.h>
#include <QtPlatformHeaders/qxcbwindowfunctions.h>
#include <QtPlatformHeaders/qxcbintegrationfunctions.h>
#ifndef QT_NO_SYSTEMTRAYICON
QT_BEGIN_NAMESPACE
@ -98,8 +96,6 @@ private slots:
void systemTrayWindowChanged(QScreen *screen);
private:
bool addToTray();
QSystemTrayIcon *q;
};
@ -117,30 +113,12 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
setGeometry(QRect(QPoint(0, 0), size));
setMinimumSize(size);
setAttribute(Qt::WA_TranslucentBackground);
addToTray();
}
bool QSystemTrayIconSys::addToTray()
{
if (!locateSystemTray())
return false;
createWinId();
setMouseTracking(true);
if (!QXcbWindowFunctions::requestSystemTrayWindowDock(windowHandle()))
return false;
show();
return true;
}
void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
{
if (locateSystemTray()) {
addToTray();
} else {
if (!locateSystemTray()) {
QBalloonTip::hideBalloon();
hide(); // still no luck
destroy();
@ -149,7 +127,7 @@ void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
QRect QSystemTrayIconSys::globalGeometry() const
{
return QXcbWindowFunctions::systemTrayWindowGlobalGeometry(windowHandle());
return QRect(mapToGlobal(QPoint(0, 0)), size());
}
void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)
@ -244,6 +222,7 @@ void QSystemTrayIconPrivate::install_sys()
sys = new QSystemTrayIconSys(q);
QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
sys, SLOT(systemTrayWindowChanged(QScreen*)));
sys->show();
}
}