remove the last piece of Qt internal classes
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
a97b1782ae
commit
9d71baffd1
|
@ -54,11 +54,7 @@ if(WIN32)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
list(APPEND SOURCES utils_mac.mm)
|
list(APPEND SOURCES utils_mac.mm)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES utils_linux.cpp)
|
||||||
qtx11extras_p.h
|
|
||||||
qtx11extras.cpp
|
|
||||||
utils_linux.cpp
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
||||||
|
|
|
@ -1,575 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
** Copyright (C) 2022 Richard Moore <rich@kde.org>
|
|
||||||
** Copyright (C) 2022 David Faure <david.faure@kdab.com>
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the QtGui module 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$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "qtx11extras_p.h"
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
|
|
||||||
#include <QtCore/qdebug.h>
|
|
||||||
#include <QtGui/qscreen.h>
|
|
||||||
#include <QtGui/qwindow.h>
|
|
||||||
#include <QtGui/qguiapplication.h>
|
|
||||||
#include <QtGui/qpa/qplatformnativeinterface.h>
|
|
||||||
#include <QtGui/qpa/qplatformwindow.h>
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
# include <QtGui/qpa/qplatformscreen_p.h>
|
|
||||||
# include <QtGui/qpa/qplatformscreen.h>
|
|
||||||
#else
|
|
||||||
# include <QtPlatformHeaders/qxcbscreenfunctions.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
[[nodiscard]] static inline QScreen *findScreenForVirtualDesktop(const int virtualDesktopNumber)
|
|
||||||
{
|
|
||||||
if (virtualDesktopNumber == -1) {
|
|
||||||
return QGuiApplication::primaryScreen();
|
|
||||||
}
|
|
||||||
const QList<QScreen *> screens = QGuiApplication::screens();
|
|
||||||
if (screens.isEmpty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
for (auto &&screen : qAsConst(screens)) {
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
const auto qxcbScreen = dynamic_cast<QNativeInterface::Private::QXcbScreen *>(screen->handle());
|
|
||||||
if (qxcbScreen && (qxcbScreen->virtualDesktopNumber() == virtualDesktopNumber)) {
|
|
||||||
return screen;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (QXcbScreenFunctions::virtualDesktopNumber(screen) == virtualDesktopNumber) {
|
|
||||||
return screen;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QX11Info
|
|
||||||
\inmodule QtGui
|
|
||||||
\since 6.2
|
|
||||||
\internal
|
|
||||||
|
|
||||||
\brief Provides information about the X display configuration.
|
|
||||||
|
|
||||||
The class provides two APIs: a set of non-static functions that
|
|
||||||
provide information about a specific widget or pixmap, and a set
|
|
||||||
of static functions that provide the default information for the
|
|
||||||
application.
|
|
||||||
|
|
||||||
\warning This class is only available on X11. For querying
|
|
||||||
per-screen information in a portable way, use QDesktopWidget.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Constructs an empty QX11Info object.
|
|
||||||
*/
|
|
||||||
QX11Info::QX11Info()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Destructor of QX11Info object.
|
|
||||||
*/
|
|
||||||
QX11Info::~QX11Info() = default;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns true if the application is currently running on X11.
|
|
||||||
|
|
||||||
\since 6.2
|
|
||||||
*/
|
|
||||||
bool QX11Info::isPlatformX11()
|
|
||||||
{
|
|
||||||
return QGuiApplication::platformName() == QLatin1String("xcb");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the horizontal resolution of the given \a screen in terms of the
|
|
||||||
number of dots per inch.
|
|
||||||
|
|
||||||
The \a screen argument is an X screen number. Be aware that if
|
|
||||||
the user's system uses Xinerama (as opposed to traditional X11
|
|
||||||
multiscreen), there is only one X screen. Use QDesktopWidget to
|
|
||||||
query for information about Xinerama screens.
|
|
||||||
|
|
||||||
\sa appDpiY()
|
|
||||||
*/
|
|
||||||
int QX11Info::appDpiX(const int screen)
|
|
||||||
{
|
|
||||||
if (screen == -1) {
|
|
||||||
const QScreen *scr = QGuiApplication::primaryScreen();
|
|
||||||
if (!scr)
|
|
||||||
return 75;
|
|
||||||
return qRound(scr->logicalDotsPerInchX());
|
|
||||||
}
|
|
||||||
|
|
||||||
QScreen *scr = findScreenForVirtualDesktop(screen);
|
|
||||||
if (!scr)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return scr->logicalDotsPerInchX();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the vertical resolution of the given \a screen in terms of the
|
|
||||||
number of dots per inch.
|
|
||||||
|
|
||||||
The \a screen argument is an X screen number. Be aware that if
|
|
||||||
the user's system uses Xinerama (as opposed to traditional X11
|
|
||||||
multiscreen), there is only one X screen. Use QDesktopWidget to
|
|
||||||
query for information about Xinerama screens.
|
|
||||||
|
|
||||||
\sa appDpiX()
|
|
||||||
*/
|
|
||||||
int QX11Info::appDpiY(const int screen)
|
|
||||||
{
|
|
||||||
if (screen == -1) {
|
|
||||||
const QScreen *scr = QGuiApplication::primaryScreen();
|
|
||||||
if (!scr)
|
|
||||||
return 75;
|
|
||||||
return qRound(scr->logicalDotsPerInchY());
|
|
||||||
}
|
|
||||||
|
|
||||||
QScreen *scr = findScreenForVirtualDesktop(screen);
|
|
||||||
if (!scr)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return scr->logicalDotsPerInchY();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns a handle for the applications root window on the given \a screen.
|
|
||||||
|
|
||||||
The \a screen argument is an X screen number. Be aware that if
|
|
||||||
the user's system uses Xinerama (as opposed to traditional X11
|
|
||||||
multiscreen), there is only one X screen. Use QDesktopWidget to
|
|
||||||
query for information about Xinerama screens.
|
|
||||||
*/
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
unsigned long QX11Info::appRootWindow(const int screen)
|
|
||||||
#else
|
|
||||||
quint32 QX11Info::appRootWindow(const int screen)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return 0;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return 0;
|
|
||||||
QScreen *scr = screen == -1 ? QGuiApplication::primaryScreen() : findScreenForVirtualDesktop(screen);
|
|
||||||
if (!scr)
|
|
||||||
return 0;
|
|
||||||
return static_cast<xcb_window_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), scr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the number of the screen where the application is being
|
|
||||||
displayed.
|
|
||||||
|
|
||||||
This method refers to screens in the original X11 meaning with a
|
|
||||||
different DISPLAY environment variable per screen.
|
|
||||||
This information is only useful if your application needs to know
|
|
||||||
on which X screen it is running.
|
|
||||||
|
|
||||||
In a typical multi-head configuration, multiple physical monitors
|
|
||||||
are combined in one X11 screen. This means this method returns the
|
|
||||||
same number for each of the physical monitors. In such a setup you
|
|
||||||
are interested in the monitor information as provided by the X11
|
|
||||||
RandR extension. This is available through QDesktopWidget and QScreen.
|
|
||||||
|
|
||||||
\sa display()
|
|
||||||
*/
|
|
||||||
int QX11Info::appScreen()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return 0;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return 0;
|
|
||||||
return reinterpret_cast<qintptr>(native->nativeResourceForIntegration(QByteArrayLiteral("x11screen")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the X11 time.
|
|
||||||
|
|
||||||
\sa setAppTime(), appUserTime()
|
|
||||||
*/
|
|
||||||
quint32 QX11Info::appTime()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return 0;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return 0;
|
|
||||||
QScreen* screen = QGuiApplication::primaryScreen();
|
|
||||||
return static_cast<xcb_timestamp_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen("apptime", screen)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the X11 user time.
|
|
||||||
|
|
||||||
\sa setAppUserTime(), appTime()
|
|
||||||
*/
|
|
||||||
quint32 QX11Info::appUserTime()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return 0;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return 0;
|
|
||||||
QScreen* screen = QGuiApplication::primaryScreen();
|
|
||||||
return static_cast<xcb_timestamp_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen("appusertime", screen)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sets the X11 time to the value specified by \a time.
|
|
||||||
|
|
||||||
\sa appTime(), setAppUserTime()
|
|
||||||
*/
|
|
||||||
void QX11Info::setAppTime(const quint32 time)
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return;
|
|
||||||
using SetAppTimeFunc = void(*)(QScreen *, xcb_timestamp_t);
|
|
||||||
QScreen* screen = QGuiApplication::primaryScreen();
|
|
||||||
auto func = reinterpret_cast<SetAppTimeFunc>(reinterpret_cast<void *>(native->nativeResourceFunctionForScreen("setapptime")));
|
|
||||||
if (func)
|
|
||||||
func(screen, time);
|
|
||||||
else
|
|
||||||
qWarning("Internal error: QPA plugin doesn't implement setAppTime");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sets the X11 user time as specified by \a time.
|
|
||||||
|
|
||||||
\sa appUserTime(), setAppTime()
|
|
||||||
*/
|
|
||||||
void QX11Info::setAppUserTime(const quint32 time)
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return;
|
|
||||||
using SetAppUserTimeFunc = void(*)(QScreen *, xcb_timestamp_t);
|
|
||||||
QScreen* screen = QGuiApplication::primaryScreen();
|
|
||||||
auto func = reinterpret_cast<SetAppUserTimeFunc>(reinterpret_cast<void *>(native->nativeResourceFunctionForScreen("setappusertime")));
|
|
||||||
if (func)
|
|
||||||
func(screen, time);
|
|
||||||
else
|
|
||||||
qWarning("Internal error: QPA plugin doesn't implement setAppUserTime");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Fetches the current X11 time stamp from the X Server.
|
|
||||||
|
|
||||||
This method creates a property notify event and blocks till it is
|
|
||||||
received back from the X Server.
|
|
||||||
*/
|
|
||||||
quint32 QX11Info::getTimestamp()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return 0;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return 0;
|
|
||||||
QScreen* screen = QGuiApplication::primaryScreen();
|
|
||||||
return static_cast<xcb_timestamp_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen("gettimestamp", screen)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the startup ID that will be used for the next window to be shown by this process.
|
|
||||||
|
|
||||||
After the next window is shown, the next startup ID will be empty.
|
|
||||||
|
|
||||||
http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt
|
|
||||||
|
|
||||||
\sa setNextStartupId()
|
|
||||||
*/
|
|
||||||
QByteArray QX11Info::nextStartupId()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return QByteArray();
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return QByteArray();
|
|
||||||
return static_cast<char *>(native->nativeResourceForIntegration("startupid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sets the next startup ID to \a id.
|
|
||||||
|
|
||||||
This is the startup ID that will be used for the next window to be shown by this process.
|
|
||||||
|
|
||||||
The startup ID of the first window comes from the environment variable DESKTOP_STARTUP_ID.
|
|
||||||
This method is useful for subsequent windows, when the request comes from another process
|
|
||||||
(e.g. via DBus).
|
|
||||||
|
|
||||||
\sa nextStartupId()
|
|
||||||
*/
|
|
||||||
void QX11Info::setNextStartupId(const QByteArray &id)
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return;
|
|
||||||
using SetStartupIdFunc = void(*)(const char*);
|
|
||||||
auto func = reinterpret_cast<SetStartupIdFunc>(reinterpret_cast<void *>(native->nativeResourceFunctionForIntegration("setstartupid")));
|
|
||||||
if (func)
|
|
||||||
func(id.constData());
|
|
||||||
else
|
|
||||||
qWarning("Internal error: QPA plugin doesn't implement setStartupId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the default display for the application.
|
|
||||||
|
|
||||||
\sa appScreen()
|
|
||||||
*/
|
|
||||||
Display *QX11Info::display()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return nullptr;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
void *display = native->nativeResourceForIntegration(QByteArray("display"));
|
|
||||||
return reinterpret_cast<Display *>(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the default XCB connection for the application.
|
|
||||||
|
|
||||||
\sa display()
|
|
||||||
*/
|
|
||||||
xcb_connection_t *QX11Info::connection()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return nullptr;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
void *connection = native->nativeResourceForIntegration(QByteArray("connection"));
|
|
||||||
return reinterpret_cast<xcb_connection_t *>(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns true if there is a compositing manager running for the connection
|
|
||||||
attached to \a screen.
|
|
||||||
|
|
||||||
If \a screen equals -1, the application's primary screen is used.
|
|
||||||
*/
|
|
||||||
bool QX11Info::isCompositingManagerRunning(const int screen)
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return false;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
QScreen *scr = screen == -1 ? QGuiApplication::primaryScreen() : findScreenForVirtualDesktop(screen);
|
|
||||||
if (!scr) {
|
|
||||||
qWarning() << "isCompositingManagerRunning: Could not find screen number" << screen;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return native->nativeResourceForScreen(QByteArray("compositingEnabled"), scr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns a new peeker id or -1 if some interal error has occurred.
|
|
||||||
Each peeker id is associated with an index in the buffered native
|
|
||||||
event queue.
|
|
||||||
|
|
||||||
For more details see QX11Info::PeekOption and peekEventQueue().
|
|
||||||
|
|
||||||
\sa peekEventQueue(), removePeekerId()
|
|
||||||
*/
|
|
||||||
qint32 QX11Info::generatePeekerId()
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return -1;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
using GeneratePeekerIdFunc = qint32(*)(void);
|
|
||||||
auto generatepeekerid = reinterpret_cast<GeneratePeekerIdFunc>(
|
|
||||||
reinterpret_cast<void *>(native->nativeResourceFunctionForIntegration("generatepeekerid")));
|
|
||||||
if (!generatepeekerid) {
|
|
||||||
qWarning("Internal error: QPA plugin doesn't implement generatePeekerId");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return generatepeekerid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Removes \a peekerId, which was earlier obtained via generatePeekerId().
|
|
||||||
|
|
||||||
Returns \c true on success or \c false if unknown peeker id was
|
|
||||||
provided or some interal error has occurred.
|
|
||||||
|
|
||||||
\sa generatePeekerId()
|
|
||||||
*/
|
|
||||||
bool QX11Info::removePeekerId(const qint32 peekerId)
|
|
||||||
{
|
|
||||||
if (!qApp)
|
|
||||||
return false;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
using RemovePeekerIdFunc = bool(*)(qint32);
|
|
||||||
auto removePeekerId = reinterpret_cast<RemovePeekerIdFunc>(
|
|
||||||
reinterpret_cast<void *>(native->nativeResourceFunctionForIntegration("removepeekerid")));
|
|
||||||
if (!removePeekerId) {
|
|
||||||
qWarning("Internal error: QPA plugin doesn't implement removePeekerId");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return removePeekerId(peekerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\enum QX11Info::PeekOption
|
|
||||||
\brief An enum to tune the behavior of QX11Info::peekEventQueue().
|
|
||||||
|
|
||||||
\value PeekDefault
|
|
||||||
Peek from the beginning of the buffered native event queue. A peeker
|
|
||||||
id is optional with PeekDefault. If a peeker id is provided to
|
|
||||||
peekEventQueue() when using PeekDefault, then peeking starts from
|
|
||||||
the beginning of the queue, not from the cached index; thus, this
|
|
||||||
can be used to manually reset a cached index to peek from the start
|
|
||||||
of the queue. When this operation completes, the associated index
|
|
||||||
will be updated to the new position in the queue.
|
|
||||||
|
|
||||||
\value PeekFromCachedIndex
|
|
||||||
QX11Info::peekEventQueue() can optimize the peeking algorithm by
|
|
||||||
skipping events that it already has seen in earlier calls to
|
|
||||||
peekEventQueue(). When control returns to the main event loop,
|
|
||||||
which causes the buffered native event queue to be flushed to Qt's
|
|
||||||
event queue, the cached indices are marked invalid and will be
|
|
||||||
reset on the next access. The same is true if the program
|
|
||||||
explicitly flushes the buffered native event queue by
|
|
||||||
QCoreApplication::processEvents().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef QX11Info::PeekerCallback
|
|
||||||
Typedef for a pointer to a function with the following signature:
|
|
||||||
|
|
||||||
\code
|
|
||||||
bool (*PeekerCallback)(xcb_generic_event_t *event, void *peekerData);
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
The \a event is a native XCB event.
|
|
||||||
The \a peekerData is a pointer to data, passed in via peekEventQueue().
|
|
||||||
|
|
||||||
Return \c true from this function to stop examining the buffered
|
|
||||||
native event queue or \c false to continue.
|
|
||||||
|
|
||||||
\note A non-capturing lambda can serve as a PeekerCallback.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Peek into the buffered XCB event queue.
|
|
||||||
|
|
||||||
You can call peekEventQueue() periodically, when your program is busy
|
|
||||||
performing a long-running operation, to peek into the buffered native
|
|
||||||
event queue. The more time the long-running operation blocks the
|
|
||||||
program from returning control to the main event loop, the more
|
|
||||||
events will accumulate in the buffered XCB event queue. Once control
|
|
||||||
returns to the main event loop these events will be flushed to Qt's
|
|
||||||
event queue, which is a separate event queue from the queue this
|
|
||||||
function is peeking into.
|
|
||||||
|
|
||||||
\note It is usually better to run CPU-intensive operations in a
|
|
||||||
non-GUI thread, instead of blocking the main event loop.
|
|
||||||
|
|
||||||
The buffered XCB event queue is populated from a non-GUI thread and
|
|
||||||
therefore might be ahead of the current GUI state. To handle native
|
|
||||||
events as they are processed by the GUI thread, see
|
|
||||||
QAbstractNativeEventFilter::nativeEventFilter().
|
|
||||||
|
|
||||||
The \a peeker is a callback function as documented in PeekerCallback.
|
|
||||||
The \a peekerData can be used to pass in arbitrary data to the \a
|
|
||||||
peeker callback.
|
|
||||||
The \a option is an enum that tunes the behavior of peekEventQueue().
|
|
||||||
The \a peekerId is used to track an index in the queue, for more
|
|
||||||
details see QX11Info::PeekOption. There can be several indices,
|
|
||||||
each tracked individually by a peeker id obtained via generatePeekerId().
|
|
||||||
|
|
||||||
This function returns \c true when the peeker has stopped the event
|
|
||||||
proccesing by returning \c true from the callback. If there were no
|
|
||||||
events in the buffered native event queue to peek at or all the
|
|
||||||
events have been processed by the peeker, this function returns \c
|
|
||||||
false.
|
|
||||||
|
|
||||||
\sa generatePeekerId(), QAbstractNativeEventFilter::nativeEventFilter()
|
|
||||||
*/
|
|
||||||
bool QX11Info::peekEventQueue(PeekerCallback peeker, void *peekerData,
|
|
||||||
const PeekOptions option, const qint32 peekerId)
|
|
||||||
{
|
|
||||||
if (!peeker || !qApp)
|
|
||||||
return false;
|
|
||||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
|
||||||
if (!native)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
using PeekEventQueueFunc = bool(*)(PeekerCallback, void *, const PeekOptions, const qint32);
|
|
||||||
auto peekeventqueue = reinterpret_cast<PeekEventQueueFunc>(
|
|
||||||
reinterpret_cast<void *>(native->nativeResourceFunctionForIntegration("peekeventqueue")));
|
|
||||||
if (!peekeventqueue) {
|
|
||||||
qWarning("Internal error: QPA plugin doesn't implement peekEventQueue");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return peekeventqueue(peeker, peekerData, option, peekerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
|
|
|
@ -1,122 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the QtGui module 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$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//
|
|
||||||
// W A R N I N G
|
|
||||||
// -------------
|
|
||||||
//
|
|
||||||
// This file is not part of the Qt API. It exists purely as an
|
|
||||||
// implementation detail. This header file may change from version to
|
|
||||||
// version without notice, or even be removed.
|
|
||||||
//
|
|
||||||
// We mean it.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "framelesshelpercore_global.h"
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 0))
|
|
||||||
#include <QtGui/private/qtx11extras_p.h>
|
|
||||||
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 2, 0))
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
|
|
||||||
using Display = struct _XDisplay;
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class FRAMELESSHELPER_CORE_API QX11Info
|
|
||||||
{
|
|
||||||
Q_GADGET
|
|
||||||
Q_DISABLE_COPY_MOVE(QX11Info)
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum class PeekOption
|
|
||||||
{
|
|
||||||
Default = 0x0000,
|
|
||||||
FromCachedIndex = 0x0001
|
|
||||||
};
|
|
||||||
Q_ENUM(PeekOption)
|
|
||||||
Q_DECLARE_FLAGS(PeekOptions, PeekOption)
|
|
||||||
Q_FLAG(PeekOptions)
|
|
||||||
|
|
||||||
[[nodiscard]] static bool isPlatformX11();
|
|
||||||
|
|
||||||
[[nodiscard]] static int appDpiX(const int screen = -1);
|
|
||||||
[[nodiscard]] static int appDpiY(const int screen = -1);
|
|
||||||
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
[[nodiscard]] static unsigned long appRootWindow(const int screen = -1);
|
|
||||||
#else
|
|
||||||
[[nodiscard]] static quint32 appRootWindow(const int screen = -1);
|
|
||||||
#endif
|
|
||||||
[[nodiscard]] static int appScreen();
|
|
||||||
|
|
||||||
[[nodiscard]] static quint32 appTime();
|
|
||||||
[[nodiscard]] static quint32 appUserTime();
|
|
||||||
|
|
||||||
static void setAppTime(const quint32 time);
|
|
||||||
static void setAppUserTime(const quint32 time);
|
|
||||||
|
|
||||||
[[nodiscard]] static quint32 getTimestamp();
|
|
||||||
|
|
||||||
[[nodiscard]] static QByteArray nextStartupId();
|
|
||||||
static void setNextStartupId(const QByteArray &id);
|
|
||||||
|
|
||||||
[[nodiscard]] static Display *display();
|
|
||||||
[[nodiscard]] static xcb_connection_t *connection();
|
|
||||||
|
|
||||||
[[nodiscard]] static bool isCompositingManagerRunning(const int screen = -1);
|
|
||||||
|
|
||||||
[[nodiscard]] static qint32 generatePeekerId();
|
|
||||||
[[nodiscard]] static bool removePeekerId(const qint32 peekerId);
|
|
||||||
|
|
||||||
using PeekerCallback = bool(*)(xcb_generic_event_t *, void *);
|
|
||||||
[[nodiscard]] static bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
|
|
||||||
const PeekOptions option = PeekOption::Default, const qint32 peekerId = -1);
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit QX11Info();
|
|
||||||
~QX11Info();
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QX11Info::PeekOptions)
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 2, 0))
|
|
|
@ -23,10 +23,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "qtx11extras_p.h"
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
#include <QtCore/qregularexpression.h>
|
#include <QtCore/qregularexpression.h>
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
|
#include <QtGui/qscreen.h>
|
||||||
|
#include <QtGui/qguiapplication.h>
|
||||||
|
#include <QtGui/qpa/qplatformnativeinterface.h>
|
||||||
|
#include <QtGui/qpa/qplatformwindow.h>
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
# include <QtGui/qpa/qplatformscreen_p.h>
|
||||||
|
# include <QtGui/qpa/qplatformscreen.h>
|
||||||
|
#else
|
||||||
|
# include <QtPlatformHeaders/qxcbscreenfunctions.h>
|
||||||
|
#endif
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
@ -34,6 +43,8 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
|
using Display = struct _XDisplay;
|
||||||
|
|
||||||
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
|
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
|
||||||
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOP = 1;
|
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOP = 1;
|
||||||
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
|
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
|
||||||
|
@ -113,6 +124,127 @@ template<typename T>
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline
|
||||||
|
QScreen *x11_findScreenForVirtualDesktop(const int virtualDesktopNumber)
|
||||||
|
{
|
||||||
|
if (virtualDesktopNumber == -1) {
|
||||||
|
return QGuiApplication::primaryScreen();
|
||||||
|
}
|
||||||
|
const QList<QScreen *> screens = QGuiApplication::screens();
|
||||||
|
if (screens.isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
for (auto &&screen : qAsConst(screens)) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
const auto qxcbScreen = dynamic_cast<QNativeInterface::Private::QXcbScreen *>(screen->handle());
|
||||||
|
if (qxcbScreen && (qxcbScreen->virtualDesktopNumber() == virtualDesktopNumber)) {
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (QXcbScreenFunctions::virtualDesktopNumber(screen) == virtualDesktopNumber) {
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline
|
||||||
|
unsigned long x11_appRootWindow(const int screen)
|
||||||
|
#else
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline
|
||||||
|
quint32 x11_appRootWindow(const int screen)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return 0;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return 0;
|
||||||
|
QScreen *scr = screen == -1 ? QGuiApplication::primaryScreen() : x11_findScreenForVirtualDesktop(screen);
|
||||||
|
if (!scr)
|
||||||
|
return 0;
|
||||||
|
return static_cast<xcb_window_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), scr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline int x11_appScreen()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return 0;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return 0;
|
||||||
|
return reinterpret_cast<qintptr>(native->nativeResourceForIntegration(QByteArrayLiteral("x11screen")));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline quint32 x11_appTime()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return 0;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return 0;
|
||||||
|
QScreen* screen = QGuiApplication::primaryScreen();
|
||||||
|
return static_cast<xcb_timestamp_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen("apptime", screen)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline quint32 x11_appUserTime()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return 0;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return 0;
|
||||||
|
QScreen* screen = QGuiApplication::primaryScreen();
|
||||||
|
return static_cast<xcb_timestamp_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen("appusertime", screen)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline quint32 x11_getTimestamp()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return 0;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return 0;
|
||||||
|
QScreen* screen = QGuiApplication::primaryScreen();
|
||||||
|
return static_cast<xcb_timestamp_t>(reinterpret_cast<quintptr>(native->nativeResourceForScreen("gettimestamp", screen)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline QByteArray x11_nextStartupId()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return QByteArray();
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return QByteArray();
|
||||||
|
return static_cast<char *>(native->nativeResourceForIntegration("startupid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline Display *x11_display()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return nullptr;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
void *display = native->nativeResourceForIntegration(QByteArray("display"));
|
||||||
|
return reinterpret_cast<Display *>(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline xcb_connection_t *x11_connection()
|
||||||
|
{
|
||||||
|
if (!qApp)
|
||||||
|
return nullptr;
|
||||||
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
|
if (!native)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
void *connection = native->nativeResourceForIntegration(QByteArray("connection"));
|
||||||
|
return reinterpret_cast<xcb_connection_t *>(connection);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emulateMouseButtonRelease(const WId windowId, const QPoint &globalPos, const QPoint &localPos)
|
emulateMouseButtonRelease(const WId windowId, const QPoint &globalPos, const QPoint &localPos)
|
||||||
{
|
{
|
||||||
|
@ -120,14 +252,14 @@ static inline void
|
||||||
if (!windowId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xcb_connection_t * const connection = QX11Info::connection();
|
xcb_connection_t * const connection = x11_connection();
|
||||||
Q_ASSERT(connection);
|
Q_ASSERT(connection);
|
||||||
const quint32 rootWindow = QX11Info::appRootWindow(QX11Info::appScreen());
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
Q_ASSERT(rootWindow);
|
Q_ASSERT(rootWindow);
|
||||||
xcb_button_release_event_t xev;
|
xcb_button_release_event_t xev;
|
||||||
memset(&xev, 0, sizeof(xev));
|
memset(&xev, 0, sizeof(xev));
|
||||||
xev.response_type = XCB_BUTTON_RELEASE;
|
xev.response_type = XCB_BUTTON_RELEASE;
|
||||||
xev.time = QX11Info::appTime();
|
xev.time = x11_appTime();
|
||||||
xev.root = rootWindow;
|
xev.root = rootWindow;
|
||||||
xev.root_x = globalPos.x();
|
xev.root_x = globalPos.x();
|
||||||
xev.root_y = globalPos.y();
|
xev.root_y = globalPos.y();
|
||||||
|
@ -148,7 +280,7 @@ static inline void
|
||||||
if (!windowId || (edges < 0)) {
|
if (!windowId || (edges < 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xcb_connection_t * const connection = QX11Info::connection();
|
xcb_connection_t * const connection = x11_connection();
|
||||||
Q_ASSERT(connection);
|
Q_ASSERT(connection);
|
||||||
static const xcb_atom_t netMoveResize = [connection]() -> xcb_atom_t {
|
static const xcb_atom_t netMoveResize = [connection]() -> xcb_atom_t {
|
||||||
const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false,
|
const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false,
|
||||||
|
@ -160,7 +292,7 @@ static inline void
|
||||||
std::free(reply);
|
std::free(reply);
|
||||||
return atom;
|
return atom;
|
||||||
}();
|
}();
|
||||||
const quint32 rootWindow = QX11Info::appRootWindow(QX11Info::appScreen());
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
Q_ASSERT(rootWindow);
|
Q_ASSERT(rootWindow);
|
||||||
xcb_client_message_event_t xev;
|
xcb_client_message_event_t xev;
|
||||||
memset(&xev, 0, sizeof(xev));
|
memset(&xev, 0, sizeof(xev));
|
||||||
|
@ -174,7 +306,7 @@ static inline void
|
||||||
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
|
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
|
||||||
// First we need to ungrab the pointer that may have been
|
// First we need to ungrab the pointer that may have been
|
||||||
// automatically grabbed by Qt on ButtonPressEvent.
|
// automatically grabbed by Qt on ButtonPressEvent.
|
||||||
xcb_ungrab_pointer(connection, QX11Info::appTime());
|
xcb_ungrab_pointer(connection, x11_appTime());
|
||||||
xcb_send_event(connection, false, rootWindow,
|
xcb_send_event(connection, false, rootWindow,
|
||||||
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY),
|
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY),
|
||||||
reinterpret_cast<const char *>(&xev));
|
reinterpret_cast<const char *>(&xev));
|
||||||
|
|
Loading…
Reference in New Issue