xcb: qxcbconnection_basic
A basic base class that creates a connection and initializes extensions. The goal was to reduce the size of qxcbconnection.h/cpp. Made QXcbAtom into a class that handles atom initialization and exposes the relevant APIs. Before this patch, all of that logic was inside of qxcbconnection.h/cpp. Change-Id: Ia893c3b31e2343dfbe62fe2aa6bfd0017abf46ea Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>bb10
parent
5fe2ed48d6
commit
d67214302f
|
|
@ -0,0 +1,287 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore 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 "qxcbatom.h"
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
static const char *xcb_atomnames = {
|
||||
// window-manager <-> client protocols
|
||||
"WM_PROTOCOLS\0"
|
||||
"WM_DELETE_WINDOW\0"
|
||||
"WM_TAKE_FOCUS\0"
|
||||
"_NET_WM_PING\0"
|
||||
"_NET_WM_CONTEXT_HELP\0"
|
||||
"_NET_WM_SYNC_REQUEST\0"
|
||||
"_NET_WM_SYNC_REQUEST_COUNTER\0"
|
||||
"MANAGER\0"
|
||||
"_NET_SYSTEM_TRAY_OPCODE\0"
|
||||
|
||||
// ICCCM window state
|
||||
"WM_STATE\0"
|
||||
"WM_CHANGE_STATE\0"
|
||||
"WM_CLASS\0"
|
||||
"WM_NAME\0"
|
||||
|
||||
// Session management
|
||||
"WM_CLIENT_LEADER\0"
|
||||
"WM_WINDOW_ROLE\0"
|
||||
"SM_CLIENT_ID\0"
|
||||
"WM_CLIENT_MACHINE\0"
|
||||
|
||||
// Clipboard
|
||||
"CLIPBOARD\0"
|
||||
"INCR\0"
|
||||
"TARGETS\0"
|
||||
"MULTIPLE\0"
|
||||
"TIMESTAMP\0"
|
||||
"SAVE_TARGETS\0"
|
||||
"CLIP_TEMPORARY\0"
|
||||
"_QT_SELECTION\0"
|
||||
"_QT_CLIPBOARD_SENTINEL\0"
|
||||
"_QT_SELECTION_SENTINEL\0"
|
||||
"CLIPBOARD_MANAGER\0"
|
||||
|
||||
"RESOURCE_MANAGER\0"
|
||||
|
||||
"_XSETROOT_ID\0"
|
||||
|
||||
"_QT_SCROLL_DONE\0"
|
||||
"_QT_INPUT_ENCODING\0"
|
||||
|
||||
"_QT_CLOSE_CONNECTION\0"
|
||||
|
||||
"_MOTIF_WM_HINTS\0"
|
||||
|
||||
"DTWM_IS_RUNNING\0"
|
||||
"ENLIGHTENMENT_DESKTOP\0"
|
||||
"_DT_SAVE_MODE\0"
|
||||
"_SGI_DESKS_MANAGER\0"
|
||||
|
||||
// EWMH (aka NETWM)
|
||||
"_NET_SUPPORTED\0"
|
||||
"_NET_VIRTUAL_ROOTS\0"
|
||||
"_NET_WORKAREA\0"
|
||||
|
||||
"_NET_MOVERESIZE_WINDOW\0"
|
||||
"_NET_WM_MOVERESIZE\0"
|
||||
|
||||
"_NET_WM_NAME\0"
|
||||
"_NET_WM_ICON_NAME\0"
|
||||
"_NET_WM_ICON\0"
|
||||
|
||||
"_NET_WM_PID\0"
|
||||
|
||||
"_NET_WM_WINDOW_OPACITY\0"
|
||||
|
||||
"_NET_WM_STATE\0"
|
||||
"_NET_WM_STATE_ABOVE\0"
|
||||
"_NET_WM_STATE_BELOW\0"
|
||||
"_NET_WM_STATE_FULLSCREEN\0"
|
||||
"_NET_WM_STATE_MAXIMIZED_HORZ\0"
|
||||
"_NET_WM_STATE_MAXIMIZED_VERT\0"
|
||||
"_NET_WM_STATE_MODAL\0"
|
||||
"_NET_WM_STATE_STAYS_ON_TOP\0"
|
||||
"_NET_WM_STATE_DEMANDS_ATTENTION\0"
|
||||
|
||||
"_NET_WM_USER_TIME\0"
|
||||
"_NET_WM_USER_TIME_WINDOW\0"
|
||||
"_NET_WM_FULL_PLACEMENT\0"
|
||||
|
||||
"_NET_WM_WINDOW_TYPE\0"
|
||||
"_NET_WM_WINDOW_TYPE_DESKTOP\0"
|
||||
"_NET_WM_WINDOW_TYPE_DOCK\0"
|
||||
"_NET_WM_WINDOW_TYPE_TOOLBAR\0"
|
||||
"_NET_WM_WINDOW_TYPE_MENU\0"
|
||||
"_NET_WM_WINDOW_TYPE_UTILITY\0"
|
||||
"_NET_WM_WINDOW_TYPE_SPLASH\0"
|
||||
"_NET_WM_WINDOW_TYPE_DIALOG\0"
|
||||
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
|
||||
"_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
|
||||
"_NET_WM_WINDOW_TYPE_TOOLTIP\0"
|
||||
"_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
|
||||
"_NET_WM_WINDOW_TYPE_COMBO\0"
|
||||
"_NET_WM_WINDOW_TYPE_DND\0"
|
||||
"_NET_WM_WINDOW_TYPE_NORMAL\0"
|
||||
"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
|
||||
|
||||
"_KDE_NET_WM_FRAME_STRUT\0"
|
||||
"_NET_FRAME_EXTENTS\0"
|
||||
|
||||
"_NET_STARTUP_INFO\0"
|
||||
"_NET_STARTUP_INFO_BEGIN\0"
|
||||
|
||||
"_NET_SUPPORTING_WM_CHECK\0"
|
||||
|
||||
"_NET_WM_CM_S0\0"
|
||||
|
||||
"_NET_SYSTEM_TRAY_VISUAL\0"
|
||||
|
||||
"_NET_ACTIVE_WINDOW\0"
|
||||
|
||||
// Property formats
|
||||
"TEXT\0"
|
||||
"UTF8_STRING\0"
|
||||
"CARDINAL\0"
|
||||
|
||||
// xdnd
|
||||
"XdndEnter\0"
|
||||
"XdndPosition\0"
|
||||
"XdndStatus\0"
|
||||
"XdndLeave\0"
|
||||
"XdndDrop\0"
|
||||
"XdndFinished\0"
|
||||
"XdndTypeList\0"
|
||||
"XdndActionList\0"
|
||||
|
||||
"XdndSelection\0"
|
||||
|
||||
"XdndAware\0"
|
||||
"XdndProxy\0"
|
||||
|
||||
"XdndActionCopy\0"
|
||||
"XdndActionLink\0"
|
||||
"XdndActionMove\0"
|
||||
"XdndActionPrivate\0"
|
||||
|
||||
// Motif DND
|
||||
"_MOTIF_DRAG_AND_DROP_MESSAGE\0"
|
||||
"_MOTIF_DRAG_INITIATOR_INFO\0"
|
||||
"_MOTIF_DRAG_RECEIVER_INFO\0"
|
||||
"_MOTIF_DRAG_WINDOW\0"
|
||||
"_MOTIF_DRAG_TARGETS\0"
|
||||
|
||||
"XmTRANSFER_SUCCESS\0"
|
||||
"XmTRANSFER_FAILURE\0"
|
||||
|
||||
// Xkb
|
||||
"_XKB_RULES_NAMES\0"
|
||||
|
||||
// XEMBED
|
||||
"_XEMBED\0"
|
||||
"_XEMBED_INFO\0"
|
||||
|
||||
// XInput2
|
||||
"Button Left\0"
|
||||
"Button Middle\0"
|
||||
"Button Right\0"
|
||||
"Button Wheel Up\0"
|
||||
"Button Wheel Down\0"
|
||||
"Button Horiz Wheel Left\0"
|
||||
"Button Horiz Wheel Right\0"
|
||||
"Abs MT Position X\0"
|
||||
"Abs MT Position Y\0"
|
||||
"Abs MT Touch Major\0"
|
||||
"Abs MT Touch Minor\0"
|
||||
"Abs MT Orientation\0"
|
||||
"Abs MT Pressure\0"
|
||||
"Abs MT Tracking ID\0"
|
||||
"Max Contacts\0"
|
||||
"Rel X\0"
|
||||
"Rel Y\0"
|
||||
// XInput2 tablet
|
||||
"Abs X\0"
|
||||
"Abs Y\0"
|
||||
"Abs Pressure\0"
|
||||
"Abs Tilt X\0"
|
||||
"Abs Tilt Y\0"
|
||||
"Abs Wheel\0"
|
||||
"Abs Distance\0"
|
||||
"Wacom Serial IDs\0"
|
||||
"INTEGER\0"
|
||||
"Rel Horiz Wheel\0"
|
||||
"Rel Vert Wheel\0"
|
||||
"Rel Horiz Scroll\0"
|
||||
"Rel Vert Scroll\0"
|
||||
"_XSETTINGS_SETTINGS\0"
|
||||
"_COMPIZ_DECOR_PENDING\0"
|
||||
"_COMPIZ_DECOR_REQUEST\0"
|
||||
"_COMPIZ_DECOR_DELETE_PIXMAP\0"
|
||||
"_COMPIZ_TOOLKIT_ACTION\0"
|
||||
"_GTK_LOAD_ICONTHEMES\0"
|
||||
"AT_SPI_BUS\0"
|
||||
"EDID\0"
|
||||
"EDID_DATA\0"
|
||||
"XFree86_DDC_EDID1_RAWDATA\0"
|
||||
// \0\0 terminates loop.
|
||||
};
|
||||
|
||||
QXcbAtom::QXcbAtom()
|
||||
{
|
||||
}
|
||||
|
||||
void QXcbAtom::initialize(xcb_connection_t *connection)
|
||||
{
|
||||
initializeAllAtoms(connection);
|
||||
}
|
||||
|
||||
void QXcbAtom::initializeAllAtoms(xcb_connection_t *connection) {
|
||||
const char *names[QXcbAtom::NAtoms];
|
||||
const char *ptr = xcb_atomnames;
|
||||
|
||||
int i = 0;
|
||||
while (*ptr) {
|
||||
names[i++] = ptr;
|
||||
while (*ptr)
|
||||
++ptr;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
Q_ASSERT(i == QXcbAtom::NAtoms);
|
||||
|
||||
xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
|
||||
|
||||
Q_ASSERT(i == QXcbAtom::NAtoms);
|
||||
for (i = 0; i < QXcbAtom::NAtoms; ++i)
|
||||
cookies[i] = xcb_intern_atom(connection, false, strlen(names[i]), names[i]);
|
||||
|
||||
for (i = 0; i < QXcbAtom::NAtoms; ++i) {
|
||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookies[i], 0);
|
||||
m_allAtoms[i] = reply->atom;
|
||||
free(reply);
|
||||
}
|
||||
}
|
||||
|
||||
QXcbAtom::Atom QXcbAtom::qatom(xcb_atom_t xatom) const
|
||||
{
|
||||
return static_cast<QXcbAtom::Atom>(std::find(m_allAtoms, m_allAtoms + QXcbAtom::NAtoms, xatom) - m_allAtoms);
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXCBATOM_H
|
||||
#define QXCBATOM_H
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
class QXcbAtom
|
||||
{
|
||||
public:
|
||||
enum Atom {
|
||||
// window-manager <-> client protocols
|
||||
WM_PROTOCOLS,
|
||||
WM_DELETE_WINDOW,
|
||||
WM_TAKE_FOCUS,
|
||||
_NET_WM_PING,
|
||||
_NET_WM_CONTEXT_HELP,
|
||||
_NET_WM_SYNC_REQUEST,
|
||||
_NET_WM_SYNC_REQUEST_COUNTER,
|
||||
MANAGER, // System tray notification
|
||||
_NET_SYSTEM_TRAY_OPCODE, // System tray operation
|
||||
|
||||
// ICCCM window state
|
||||
WM_STATE,
|
||||
WM_CHANGE_STATE,
|
||||
WM_CLASS,
|
||||
WM_NAME,
|
||||
|
||||
// Session management
|
||||
WM_CLIENT_LEADER,
|
||||
WM_WINDOW_ROLE,
|
||||
SM_CLIENT_ID,
|
||||
WM_CLIENT_MACHINE,
|
||||
|
||||
// Clipboard
|
||||
CLIPBOARD,
|
||||
INCR,
|
||||
TARGETS,
|
||||
MULTIPLE,
|
||||
TIMESTAMP,
|
||||
SAVE_TARGETS,
|
||||
CLIP_TEMPORARY,
|
||||
_QT_SELECTION,
|
||||
_QT_CLIPBOARD_SENTINEL,
|
||||
_QT_SELECTION_SENTINEL,
|
||||
CLIPBOARD_MANAGER,
|
||||
|
||||
RESOURCE_MANAGER,
|
||||
|
||||
_XSETROOT_ID,
|
||||
|
||||
_QT_SCROLL_DONE,
|
||||
_QT_INPUT_ENCODING,
|
||||
|
||||
// Qt/XCB specific
|
||||
_QT_CLOSE_CONNECTION,
|
||||
|
||||
_MOTIF_WM_HINTS,
|
||||
|
||||
DTWM_IS_RUNNING,
|
||||
ENLIGHTENMENT_DESKTOP,
|
||||
_DT_SAVE_MODE,
|
||||
_SGI_DESKS_MANAGER,
|
||||
|
||||
// EWMH (aka NETWM)
|
||||
_NET_SUPPORTED,
|
||||
_NET_VIRTUAL_ROOTS,
|
||||
_NET_WORKAREA,
|
||||
|
||||
_NET_MOVERESIZE_WINDOW,
|
||||
_NET_WM_MOVERESIZE,
|
||||
|
||||
_NET_WM_NAME,
|
||||
_NET_WM_ICON_NAME,
|
||||
_NET_WM_ICON,
|
||||
|
||||
_NET_WM_PID,
|
||||
|
||||
_NET_WM_WINDOW_OPACITY,
|
||||
|
||||
_NET_WM_STATE,
|
||||
_NET_WM_STATE_ABOVE,
|
||||
_NET_WM_STATE_BELOW,
|
||||
_NET_WM_STATE_FULLSCREEN,
|
||||
_NET_WM_STATE_MAXIMIZED_HORZ,
|
||||
_NET_WM_STATE_MAXIMIZED_VERT,
|
||||
_NET_WM_STATE_MODAL,
|
||||
_NET_WM_STATE_STAYS_ON_TOP,
|
||||
_NET_WM_STATE_DEMANDS_ATTENTION,
|
||||
|
||||
_NET_WM_USER_TIME,
|
||||
_NET_WM_USER_TIME_WINDOW,
|
||||
_NET_WM_FULL_PLACEMENT,
|
||||
|
||||
_NET_WM_WINDOW_TYPE,
|
||||
_NET_WM_WINDOW_TYPE_DESKTOP,
|
||||
_NET_WM_WINDOW_TYPE_DOCK,
|
||||
_NET_WM_WINDOW_TYPE_TOOLBAR,
|
||||
_NET_WM_WINDOW_TYPE_MENU,
|
||||
_NET_WM_WINDOW_TYPE_UTILITY,
|
||||
_NET_WM_WINDOW_TYPE_SPLASH,
|
||||
_NET_WM_WINDOW_TYPE_DIALOG,
|
||||
_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
|
||||
_NET_WM_WINDOW_TYPE_POPUP_MENU,
|
||||
_NET_WM_WINDOW_TYPE_TOOLTIP,
|
||||
_NET_WM_WINDOW_TYPE_NOTIFICATION,
|
||||
_NET_WM_WINDOW_TYPE_COMBO,
|
||||
_NET_WM_WINDOW_TYPE_DND,
|
||||
_NET_WM_WINDOW_TYPE_NORMAL,
|
||||
_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
|
||||
|
||||
_KDE_NET_WM_FRAME_STRUT,
|
||||
_NET_FRAME_EXTENTS,
|
||||
|
||||
_NET_STARTUP_INFO,
|
||||
_NET_STARTUP_INFO_BEGIN,
|
||||
|
||||
_NET_SUPPORTING_WM_CHECK,
|
||||
|
||||
_NET_WM_CM_S0,
|
||||
|
||||
_NET_SYSTEM_TRAY_VISUAL,
|
||||
|
||||
_NET_ACTIVE_WINDOW,
|
||||
|
||||
// Property formats
|
||||
TEXT,
|
||||
UTF8_STRING,
|
||||
CARDINAL,
|
||||
|
||||
// Xdnd
|
||||
XdndEnter,
|
||||
XdndPosition,
|
||||
XdndStatus,
|
||||
XdndLeave,
|
||||
XdndDrop,
|
||||
XdndFinished,
|
||||
XdndTypelist,
|
||||
XdndActionList,
|
||||
|
||||
XdndSelection,
|
||||
|
||||
XdndAware,
|
||||
XdndProxy,
|
||||
|
||||
XdndActionCopy,
|
||||
XdndActionLink,
|
||||
XdndActionMove,
|
||||
XdndActionPrivate,
|
||||
|
||||
// Motif DND
|
||||
_MOTIF_DRAG_AND_DROP_MESSAGE,
|
||||
_MOTIF_DRAG_INITIATOR_INFO,
|
||||
_MOTIF_DRAG_RECEIVER_INFO,
|
||||
_MOTIF_DRAG_WINDOW,
|
||||
_MOTIF_DRAG_TARGETS,
|
||||
|
||||
XmTRANSFER_SUCCESS,
|
||||
XmTRANSFER_FAILURE,
|
||||
|
||||
// Xkb
|
||||
_XKB_RULES_NAMES,
|
||||
|
||||
// XEMBED
|
||||
_XEMBED,
|
||||
_XEMBED_INFO,
|
||||
|
||||
// XInput2
|
||||
ButtonLeft,
|
||||
ButtonMiddle,
|
||||
ButtonRight,
|
||||
ButtonWheelUp,
|
||||
ButtonWheelDown,
|
||||
ButtonHorizWheelLeft,
|
||||
ButtonHorizWheelRight,
|
||||
AbsMTPositionX,
|
||||
AbsMTPositionY,
|
||||
AbsMTTouchMajor,
|
||||
AbsMTTouchMinor,
|
||||
AbsMTOrientation,
|
||||
AbsMTPressure,
|
||||
AbsMTTrackingID,
|
||||
MaxContacts,
|
||||
RelX,
|
||||
RelY,
|
||||
// XInput2 tablet
|
||||
AbsX,
|
||||
AbsY,
|
||||
AbsPressure,
|
||||
AbsTiltX,
|
||||
AbsTiltY,
|
||||
AbsWheel,
|
||||
AbsDistance,
|
||||
WacomSerialIDs,
|
||||
INTEGER,
|
||||
RelHorizWheel,
|
||||
RelVertWheel,
|
||||
RelHorizScroll,
|
||||
RelVertScroll,
|
||||
|
||||
_XSETTINGS_SETTINGS,
|
||||
|
||||
_COMPIZ_DECOR_PENDING,
|
||||
_COMPIZ_DECOR_REQUEST,
|
||||
_COMPIZ_DECOR_DELETE_PIXMAP,
|
||||
_COMPIZ_TOOLKIT_ACTION,
|
||||
_GTK_LOAD_ICONTHEMES,
|
||||
|
||||
AT_SPI_BUS,
|
||||
|
||||
EDID,
|
||||
EDID_DATA,
|
||||
XFree86_DDC_EDID1_RAWDATA,
|
||||
|
||||
NAtoms
|
||||
};
|
||||
|
||||
QXcbAtom();
|
||||
void initialize(xcb_connection_t *connection);
|
||||
|
||||
inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; }
|
||||
QXcbAtom::Atom qatom(xcb_atom_t atom) const;
|
||||
|
||||
protected:
|
||||
void initializeAllAtoms(xcb_connection_t *connection);
|
||||
|
||||
private:
|
||||
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
|
||||
};
|
||||
|
||||
#endif // QXCBATOM_H
|
||||
|
|
@ -106,7 +106,7 @@ public:
|
|||
void put(xcb_drawable_t dst, const QRegion ®ion, const QPoint &offset);
|
||||
void preparePaint(const QRegion ®ion);
|
||||
|
||||
static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1,
|
||||
static bool createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize = 1,
|
||||
xcb_shm_segment_info_t *shm_info = nullptr);
|
||||
|
||||
private:
|
||||
|
|
@ -406,12 +406,12 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
if (createSystemVShmSegment(connection(), segmentSize, &m_shm_info))
|
||||
if (createSystemVShmSegment(xcb_connection(), segmentSize, &m_shm_info))
|
||||
m_segmentSize = segmentSize;
|
||||
}
|
||||
}
|
||||
|
||||
bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize,
|
||||
bool QXcbBackingStoreImage::createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize,
|
||||
xcb_shm_segment_info_t *shmInfo)
|
||||
{
|
||||
const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
|
||||
|
|
@ -429,17 +429,17 @@ bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t se
|
|||
if (shmctl(id, IPC_RMID, 0) == -1)
|
||||
qCWarning(lcQpaXcb, "Error while marking the shared memory segment to be destroyed");
|
||||
|
||||
const auto seg = xcb_generate_id(c->xcb_connection());
|
||||
auto cookie = xcb_shm_attach_checked(c->xcb_connection(), seg, id, false);
|
||||
auto *error = xcb_request_check(c->xcb_connection(), cookie);
|
||||
const auto seg = xcb_generate_id(c);
|
||||
auto cookie = xcb_shm_attach_checked(c, seg, id, false);
|
||||
auto *error = xcb_request_check(c, cookie);
|
||||
if (error) {
|
||||
c->printXcbError("xcb_shm_attach() failed with error", error);
|
||||
qCWarning(lcQpaXcb(), "xcb_shm_attach() failed");
|
||||
free(error);
|
||||
if (shmdt(addr) == -1)
|
||||
qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), addr);
|
||||
return false;
|
||||
} else if (!shmInfo) { // this was a test run, free the allocated test segment
|
||||
xcb_shm_detach(c->xcb_connection(), seg);
|
||||
xcb_shm_detach(c, seg);
|
||||
auto shmaddr = static_cast<quint8 *>(addr);
|
||||
if (shmdt(shmaddr) == -1)
|
||||
qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), shmaddr);
|
||||
|
|
@ -766,7 +766,7 @@ void QXcbBackingStoreImage::preparePaint(const QRegion ®ion)
|
|||
m_pendingFlush |= region;
|
||||
}
|
||||
|
||||
bool QXcbBackingStore::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize, void *shmInfo)
|
||||
bool QXcbBackingStore::createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize, void *shmInfo)
|
||||
{
|
||||
auto info = reinterpret_cast<xcb_shm_segment_info_t *>(shmInfo);
|
||||
return QXcbBackingStoreImage::createSystemVShmSegment(c, segmentSize, info);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public:
|
|||
void beginPaint(const QRegion &) override;
|
||||
void endPaint() override;
|
||||
|
||||
static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1,
|
||||
static bool createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize = 1,
|
||||
void *shmInfo = nullptr);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -59,38 +59,24 @@
|
|||
#include "qxcbbackingstore.h"
|
||||
#include "qxcbeventqueue.h"
|
||||
|
||||
#include <QSocketNotifier>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QTimer>
|
||||
#include <QByteArray>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/sync.h>
|
||||
|
||||
#include <xcb/xfixes.h>
|
||||
#include <xcb/xinerama.h>
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
#define register /* C++17 deprecated register */
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/Xutil.h>
|
||||
#undef register
|
||||
#if QT_CONFIG(xkb)
|
||||
#define explicit dont_use_cxx_explicit
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#include <xcb/xinput.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xcb_render)
|
||||
#include <xcb/render.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input")
|
||||
|
|
@ -99,7 +85,6 @@ Q_LOGGING_CATEGORY(lcQpaXInputEvents, "qt.qpa.input.events")
|
|||
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
|
||||
Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
|
||||
Q_LOGGING_CATEGORY(lcQpaEventReader, "qt.qpa.events.reader")
|
||||
Q_LOGGING_CATEGORY(lcQpaXcb, "qt.qpa.xcb") // for general (uncategorized) XCB logging
|
||||
Q_LOGGING_CATEGORY(lcQpaPeeker, "qt.qpa.peeker")
|
||||
Q_LOGGING_CATEGORY(lcQpaKeyboard, "qt.qpa.xkeyboard")
|
||||
Q_LOGGING_CATEGORY(lcQpaXDnd, "qt.qpa.xdnd")
|
||||
|
|
@ -110,69 +95,19 @@ Q_LOGGING_CATEGORY(lcQpaXDnd, "qt.qpa.xdnd")
|
|||
#define XCB_GE_GENERIC 35
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
|
||||
// - "pad0" became "extension"
|
||||
// - "pad1" and "pad" became "pad0"
|
||||
// New and old version of this struct share the following fields:
|
||||
typedef struct qt_xcb_ge_event_t {
|
||||
uint8_t response_type;
|
||||
uint8_t extension;
|
||||
uint16_t sequence;
|
||||
uint32_t length;
|
||||
uint16_t event_type;
|
||||
} qt_xcb_ge_event_t;
|
||||
|
||||
static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
|
||||
void QXcbConnection::selectXRandrEvents()
|
||||
{
|
||||
qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
|
||||
return e->extension == opCode;
|
||||
}
|
||||
#endif // QT_CONFIG(xcb_xinput)
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
static const char * const xcbConnectionErrors[] = {
|
||||
"No error", /* Error 0 */
|
||||
"I/O error", /* XCB_CONN_ERROR */
|
||||
"Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
|
||||
"Out of memory", /* XCB_CONN_CLOSED_MEM_INSUFFICIENT */
|
||||
"Maximum allowed requested length exceeded", /* XCB_CONN_CLOSED_REQ_LEN_EXCEED */
|
||||
"Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
|
||||
"No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
|
||||
"Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
|
||||
};
|
||||
|
||||
static int nullErrorHandler(Display *dpy, XErrorEvent *err)
|
||||
{
|
||||
#ifndef Q_XCB_DEBUG
|
||||
Q_UNUSED(dpy);
|
||||
Q_UNUSED(err);
|
||||
#else
|
||||
const int buflen = 1024;
|
||||
char buf[buflen];
|
||||
|
||||
XGetErrorText(dpy, err->error_code, buf, buflen);
|
||||
fprintf(stderr, "X Error: serial %lu error %d %s\n", err->serial, (int) err->error_code, buf);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioErrorHandler(Display *dpy)
|
||||
{
|
||||
xcb_connection_t *conn = XGetXCBConnection(dpy);
|
||||
if (conn != NULL) {
|
||||
/* Print a message with a textual description of the error */
|
||||
int code = xcb_connection_has_error(conn);
|
||||
const char *str = "Unknown error";
|
||||
int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
|
||||
if (code >= 0 && code < arrayLength)
|
||||
str = xcbConnectionErrors[code];
|
||||
|
||||
qWarning("The X11 connection broke: %s (code %d)", str, code);
|
||||
xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(setup());
|
||||
for (; rootIter.rem; xcb_screen_next(&rootIter)) {
|
||||
xcb_randr_select_input(xcb_connection(),
|
||||
rootIter.data->root,
|
||||
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
|
||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
|
||||
XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
|
||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY
|
||||
);
|
||||
}
|
||||
return _XDefaultIOError(dpy);
|
||||
}
|
||||
#endif
|
||||
|
||||
QXcbScreen* QXcbConnection::findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const
|
||||
{
|
||||
|
|
@ -314,7 +249,7 @@ void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_cha
|
|||
if (screen->mode() != outputChange.mode)
|
||||
screen->updateRefreshRate(outputChange.mode);
|
||||
// Only screen which belongs to the primary virtual desktop can be a primary screen
|
||||
if (screen->screenNumber() == m_primaryScreenNumber) {
|
||||
if (screen->screenNumber() == primaryScreenNumber()) {
|
||||
if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
|
||||
screen->setPrimary(true);
|
||||
|
||||
|
|
@ -336,7 +271,7 @@ QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
|
|||
{
|
||||
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
|
||||
// Only screen which belongs to the primary virtual desktop can be a primary screen
|
||||
if (screen->screenNumber() == m_primaryScreenNumber)
|
||||
if (screen->screenNumber() == primaryScreenNumber())
|
||||
screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
|
||||
|
||||
if (screen->isPrimary()) {
|
||||
|
|
@ -384,7 +319,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
|
|||
|
||||
void QXcbConnection::initializeScreens()
|
||||
{
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup());
|
||||
int xcbScreenNumber = 0; // screen number in the xcb sense
|
||||
QXcbScreen *primaryScreen = nullptr;
|
||||
while (it.rem) {
|
||||
|
|
@ -396,7 +331,7 @@ void QXcbConnection::initializeScreens()
|
|||
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
|
||||
m_virtualDesktops.append(virtualDesktop);
|
||||
QList<QPlatformScreen *> siblings;
|
||||
if (has_randr_extension) {
|
||||
if (hasXRender()) {
|
||||
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
|
||||
// configuration is not initialized wrt to the hardware. We should call
|
||||
// RRGetScreenResources in this case.
|
||||
|
|
@ -457,7 +392,7 @@ void QXcbConnection::initializeScreens()
|
|||
// the first or an exact match. An exact match isn't
|
||||
// always available if primary->output is XCB_NONE
|
||||
// or currently disconnected output.
|
||||
if (m_primaryScreenNumber == xcbScreenNumber) {
|
||||
if (primaryScreenNumber() == xcbScreenNumber) {
|
||||
if (!primaryScreen || (primary && outputs[i] == primary->output)) {
|
||||
if (primaryScreen)
|
||||
primaryScreen->setPrimary(false);
|
||||
|
|
@ -470,9 +405,9 @@ void QXcbConnection::initializeScreens()
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (has_xinerama_extension) {
|
||||
} else if (hasXinerama()) {
|
||||
// Xinerama is available
|
||||
auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, m_connection);
|
||||
auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, xcb_connection());
|
||||
if (screens) {
|
||||
xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens.get());
|
||||
while (it.rem) {
|
||||
|
|
@ -492,7 +427,7 @@ void QXcbConnection::initializeScreens()
|
|||
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, nullptr);
|
||||
qCDebug(lcQpaScreen) << "created fake screen" << screen;
|
||||
m_screens << screen;
|
||||
if (m_primaryScreenNumber == xcbScreenNumber) {
|
||||
if (primaryScreenNumber() == xcbScreenNumber) {
|
||||
primaryScreen = screen;
|
||||
primaryScreen->setPrimary(true);
|
||||
}
|
||||
|
|
@ -528,72 +463,28 @@ void QXcbConnection::initializeScreens()
|
|||
}
|
||||
|
||||
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
|
||||
: m_canGrabServer(canGrabServer)
|
||||
: QXcbBasicConnection(displayName)
|
||||
, m_canGrabServer(canGrabServer)
|
||||
, m_defaultVisualId(defaultVisualId)
|
||||
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
|
||||
, m_nativeInterface(nativeInterface)
|
||||
{
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
Display *dpy = XOpenDisplay(m_displayName.constData());
|
||||
if (dpy) {
|
||||
m_primaryScreenNumber = DefaultScreen(dpy);
|
||||
m_connection = XGetXCBConnection(dpy);
|
||||
XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
|
||||
XSetErrorHandler(nullErrorHandler);
|
||||
XSetIOErrorHandler(ioErrorHandler);
|
||||
m_xlib_display = dpy;
|
||||
}
|
||||
#else
|
||||
m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber);
|
||||
#endif // QT_CONFIG(xcb_xlib)
|
||||
|
||||
if (Q_UNLIKELY(!m_connection || xcb_connection_has_error(m_connection))) {
|
||||
qCWarning(lcQpaScreen, "QXcbConnection: Could not connect to display %s", m_displayName.constData());
|
||||
if (!isConnected())
|
||||
return;
|
||||
}
|
||||
|
||||
m_eventQueue = new QXcbEventQueue(this);
|
||||
|
||||
xcb_extension_t *extensions[] = {
|
||||
&xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
|
||||
#if QT_CONFIG(xkb)
|
||||
&xcb_xkb_id,
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_render)
|
||||
&xcb_render_id,
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
&xcb_input_id,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
for (xcb_extension_t **ext_it = extensions; *ext_it; ++ext_it)
|
||||
xcb_prefetch_extension_data (m_connection, *ext_it);
|
||||
|
||||
m_setup = xcb_get_setup(xcb_connection());
|
||||
|
||||
m_xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
|
||||
|
||||
initializeAllAtoms();
|
||||
selectXRandrEvents();
|
||||
|
||||
initializeXSync();
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_MITSHM"))
|
||||
initializeShm();
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR"))
|
||||
initializeXRandr();
|
||||
if (!has_randr_extension)
|
||||
initializeXinerama();
|
||||
initializeXFixes();
|
||||
initializeScreens();
|
||||
|
||||
initializeXRender();
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_XI2"))
|
||||
initializeXInput2();
|
||||
if (hasXInput2()) {
|
||||
xi2SetupDevices();
|
||||
xi2SelectStateEvents();
|
||||
}
|
||||
#endif
|
||||
initializeXShape();
|
||||
initializeXKB();
|
||||
|
||||
m_wmSupport.reset(new QXcbWMSupport(this));
|
||||
m_keyboard = new QXcbKeyboard(this);
|
||||
|
|
@ -632,22 +523,9 @@ QXcbConnection::~QXcbConnection()
|
|||
|
||||
delete m_glIntegration;
|
||||
|
||||
if (isConnected()) {
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
XCloseDisplay(static_cast<Display *>(m_xlib_display));
|
||||
#else
|
||||
xcb_disconnect(xcb_connection());
|
||||
#endif
|
||||
}
|
||||
|
||||
delete m_keyboard;
|
||||
}
|
||||
|
||||
bool QXcbConnection::isConnected() const
|
||||
{
|
||||
return m_connection && !xcb_connection_has_error(m_connection);
|
||||
}
|
||||
|
||||
QXcbScreen *QXcbConnection::primaryScreen() const
|
||||
{
|
||||
if (!m_screens.isEmpty()) {
|
||||
|
|
@ -752,17 +630,17 @@ void QXcbConnection::printXcbEvent(const QLoggingCategory &log, const char *mess
|
|||
CASE_PRINT_AND_RETURN( XCB_GE_GENERIC );
|
||||
}
|
||||
// XFixes
|
||||
if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY)
|
||||
if (isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY))
|
||||
PRINT_AND_RETURN("XCB_XFIXES_SELECTION_NOTIFY");
|
||||
|
||||
// XRandR
|
||||
if (has_randr_extension) {
|
||||
if (response_type == xrandr_first_event + XCB_RANDR_NOTIFY)
|
||||
PRINT_AND_RETURN("XCB_RANDR_NOTIFY");
|
||||
if (response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)
|
||||
PRINT_AND_RETURN("XCB_RANDR_SCREEN_CHANGE_NOTIFY");
|
||||
}
|
||||
if (isXRandrType(response_type, XCB_RANDR_NOTIFY))
|
||||
PRINT_AND_RETURN("XCB_RANDR_NOTIFY");
|
||||
if (isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY))
|
||||
PRINT_AND_RETURN("XCB_RANDR_SCREEN_CHANGE_NOTIFY");
|
||||
|
||||
// XKB
|
||||
if (response_type == xkb_first_event)
|
||||
if (isXkbType(response_type))
|
||||
PRINT_AND_RETURN("XCB_XKB_* event");
|
||||
|
||||
// UNKNOWN
|
||||
|
|
@ -1155,7 +1033,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|||
#if QT_CONFIG(xcb_xinput)
|
||||
case XCB_GE_GENERIC:
|
||||
// Here the windowEventListener is invoked from xi2HandleEvent()
|
||||
if (hasXInput2() && isXIEvent(event, m_xiOpCode))
|
||||
if (hasXInput2() && isXIEvent(event))
|
||||
xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
|
||||
break;
|
||||
#endif
|
||||
|
|
@ -1168,7 +1046,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|||
return;
|
||||
|
||||
handled = true;
|
||||
if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
|
||||
if (isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY)) {
|
||||
auto notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event);
|
||||
setTime(notify_event->timestamp);
|
||||
#ifndef QT_NO_CLIPBOARD
|
||||
|
|
@ -1176,14 +1054,14 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|||
#endif
|
||||
for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
|
||||
virtualDesktop->handleXFixesSelectionNotify(notify_event);
|
||||
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) {
|
||||
} else if (isXRandrType(response_type, XCB_RANDR_NOTIFY)) {
|
||||
updateScreens(reinterpret_cast<xcb_randr_notify_event_t *>(event));
|
||||
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
|
||||
} else if (isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY)) {
|
||||
auto change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event);
|
||||
if (auto virtualDesktop = virtualDesktopForRootWindow(change_event->root))
|
||||
virtualDesktop->handleScreenChange(change_event);
|
||||
#if QT_CONFIG(xkb)
|
||||
} else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295
|
||||
} else if (isXkbType(response_type)) {
|
||||
auto xkb_event = reinterpret_cast<_xkb_event *>(event);
|
||||
if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) {
|
||||
switch (xkb_event->any.xkbType) {
|
||||
|
|
@ -1239,13 +1117,13 @@ void QXcbConnection::setMousePressWindow(QXcbWindow *w)
|
|||
void QXcbConnection::grabServer()
|
||||
{
|
||||
if (m_canGrabServer)
|
||||
xcb_grab_server(m_connection);
|
||||
xcb_grab_server(xcb_connection());
|
||||
}
|
||||
|
||||
void QXcbConnection::ungrabServer()
|
||||
{
|
||||
if (m_canGrabServer)
|
||||
xcb_ungrab_server(m_connection);
|
||||
xcb_ungrab_server(xcb_connection());
|
||||
}
|
||||
|
||||
xcb_timestamp_t QXcbConnection::getTimestamp()
|
||||
|
|
@ -1360,17 +1238,6 @@ xcb_window_t QXcbConnection::clientLeader()
|
|||
return m_clientLeader;
|
||||
}
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
static inline bool isXIType(xcb_generic_event_t *event, int opCode, uint16_t type)
|
||||
{
|
||||
if (!isXIEvent(event, opCode))
|
||||
return false;
|
||||
|
||||
auto *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
|
||||
return e->event_type == type;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! \internal
|
||||
|
||||
Compresses events of the same type to avoid swamping the event queue.
|
||||
|
|
@ -1405,7 +1272,7 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event) const
|
|||
return false;
|
||||
|
||||
// compress XI_Motion
|
||||
if (isXIType(event, m_xiOpCode, XCB_INPUT_MOTION)) {
|
||||
if (isXIType(event, XCB_INPUT_MOTION)) {
|
||||
#if QT_CONFIG(tabletevent)
|
||||
auto xdev = reinterpret_cast<xcb_input_motion_event_t *>(event);
|
||||
if (!QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents) &&
|
||||
|
|
@ -1414,17 +1281,18 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event) const
|
|||
#endif // QT_CONFIG(tabletevent)
|
||||
return m_eventQueue->peek(QXcbEventQueue::PeekRetainMatch,
|
||||
[this](xcb_generic_event_t *next, int) {
|
||||
return isXIType(next, m_xiOpCode, XCB_INPUT_MOTION);
|
||||
return isXIType(next, XCB_INPUT_MOTION);
|
||||
});
|
||||
}
|
||||
|
||||
// compress XI_TouchUpdate for the same touch point id
|
||||
if (isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE)) {
|
||||
if (isXIType(event, XCB_INPUT_TOUCH_UPDATE)) {
|
||||
auto touchUpdateEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(event);
|
||||
uint32_t id = touchUpdateEvent->detail % INT_MAX;
|
||||
|
||||
return m_eventQueue->peek(QXcbEventQueue::PeekRetainMatch,
|
||||
[this, &id](xcb_generic_event_t *next, int) {
|
||||
if (!isXIType(next, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE))
|
||||
if (!isXIType(next, XCB_INPUT_TOUCH_UPDATE))
|
||||
return false;
|
||||
auto touchUpdateNextEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(next);
|
||||
return id == touchUpdateNextEvent->detail % INT_MAX;
|
||||
|
|
@ -1465,16 +1333,16 @@ bool QXcbConnection::isUserInputEvent(xcb_generic_event_t *event) const
|
|||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (connection()->hasXInput2()) {
|
||||
isInputEvent = isXIType(event, m_xiOpCode, XCB_INPUT_BUTTON_PRESS) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_BUTTON_RELEASE) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_MOTION) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_BEGIN) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_END) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_ENTER) ||
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_LEAVE) ||
|
||||
isInputEvent = isXIType(event, XCB_INPUT_BUTTON_PRESS) ||
|
||||
isXIType(event, XCB_INPUT_BUTTON_RELEASE) ||
|
||||
isXIType(event, XCB_INPUT_MOTION) ||
|
||||
isXIType(event, XCB_INPUT_TOUCH_BEGIN) ||
|
||||
isXIType(event, XCB_INPUT_TOUCH_UPDATE) ||
|
||||
isXIType(event, XCB_INPUT_TOUCH_END) ||
|
||||
isXIType(event, XCB_INPUT_ENTER) ||
|
||||
isXIType(event, XCB_INPUT_LEAVE) ||
|
||||
// wacom driver's way of reporting tool proximity
|
||||
isXIType(event, m_xiOpCode, XCB_INPUT_PROPERTY);
|
||||
isXIType(event, XCB_INPUT_PROPERTY);
|
||||
}
|
||||
if (isInputEvent)
|
||||
return true;
|
||||
|
|
@ -1545,265 +1413,10 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
|
|||
xcb_flush(xcb_connection());
|
||||
}
|
||||
|
||||
static const char * xcb_atomnames = {
|
||||
// window-manager <-> client protocols
|
||||
"WM_PROTOCOLS\0"
|
||||
"WM_DELETE_WINDOW\0"
|
||||
"WM_TAKE_FOCUS\0"
|
||||
"_NET_WM_PING\0"
|
||||
"_NET_WM_CONTEXT_HELP\0"
|
||||
"_NET_WM_SYNC_REQUEST\0"
|
||||
"_NET_WM_SYNC_REQUEST_COUNTER\0"
|
||||
"MANAGER\0"
|
||||
"_NET_SYSTEM_TRAY_OPCODE\0"
|
||||
|
||||
// ICCCM window state
|
||||
"WM_STATE\0"
|
||||
"WM_CHANGE_STATE\0"
|
||||
"WM_CLASS\0"
|
||||
"WM_NAME\0"
|
||||
|
||||
// Session management
|
||||
"WM_CLIENT_LEADER\0"
|
||||
"WM_WINDOW_ROLE\0"
|
||||
"SM_CLIENT_ID\0"
|
||||
"WM_CLIENT_MACHINE\0"
|
||||
|
||||
// Clipboard
|
||||
"CLIPBOARD\0"
|
||||
"INCR\0"
|
||||
"TARGETS\0"
|
||||
"MULTIPLE\0"
|
||||
"TIMESTAMP\0"
|
||||
"SAVE_TARGETS\0"
|
||||
"CLIP_TEMPORARY\0"
|
||||
"_QT_SELECTION\0"
|
||||
"_QT_CLIPBOARD_SENTINEL\0"
|
||||
"_QT_SELECTION_SENTINEL\0"
|
||||
"CLIPBOARD_MANAGER\0"
|
||||
|
||||
"RESOURCE_MANAGER\0"
|
||||
|
||||
"_XSETROOT_ID\0"
|
||||
|
||||
"_QT_SCROLL_DONE\0"
|
||||
"_QT_INPUT_ENCODING\0"
|
||||
|
||||
"_QT_CLOSE_CONNECTION\0"
|
||||
|
||||
"_MOTIF_WM_HINTS\0"
|
||||
|
||||
"DTWM_IS_RUNNING\0"
|
||||
"ENLIGHTENMENT_DESKTOP\0"
|
||||
"_DT_SAVE_MODE\0"
|
||||
"_SGI_DESKS_MANAGER\0"
|
||||
|
||||
// EWMH (aka NETWM)
|
||||
"_NET_SUPPORTED\0"
|
||||
"_NET_VIRTUAL_ROOTS\0"
|
||||
"_NET_WORKAREA\0"
|
||||
|
||||
"_NET_MOVERESIZE_WINDOW\0"
|
||||
"_NET_WM_MOVERESIZE\0"
|
||||
|
||||
"_NET_WM_NAME\0"
|
||||
"_NET_WM_ICON_NAME\0"
|
||||
"_NET_WM_ICON\0"
|
||||
|
||||
"_NET_WM_PID\0"
|
||||
|
||||
"_NET_WM_WINDOW_OPACITY\0"
|
||||
|
||||
"_NET_WM_STATE\0"
|
||||
"_NET_WM_STATE_ABOVE\0"
|
||||
"_NET_WM_STATE_BELOW\0"
|
||||
"_NET_WM_STATE_FULLSCREEN\0"
|
||||
"_NET_WM_STATE_MAXIMIZED_HORZ\0"
|
||||
"_NET_WM_STATE_MAXIMIZED_VERT\0"
|
||||
"_NET_WM_STATE_MODAL\0"
|
||||
"_NET_WM_STATE_STAYS_ON_TOP\0"
|
||||
"_NET_WM_STATE_DEMANDS_ATTENTION\0"
|
||||
|
||||
"_NET_WM_USER_TIME\0"
|
||||
"_NET_WM_USER_TIME_WINDOW\0"
|
||||
"_NET_WM_FULL_PLACEMENT\0"
|
||||
|
||||
"_NET_WM_WINDOW_TYPE\0"
|
||||
"_NET_WM_WINDOW_TYPE_DESKTOP\0"
|
||||
"_NET_WM_WINDOW_TYPE_DOCK\0"
|
||||
"_NET_WM_WINDOW_TYPE_TOOLBAR\0"
|
||||
"_NET_WM_WINDOW_TYPE_MENU\0"
|
||||
"_NET_WM_WINDOW_TYPE_UTILITY\0"
|
||||
"_NET_WM_WINDOW_TYPE_SPLASH\0"
|
||||
"_NET_WM_WINDOW_TYPE_DIALOG\0"
|
||||
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
|
||||
"_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
|
||||
"_NET_WM_WINDOW_TYPE_TOOLTIP\0"
|
||||
"_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
|
||||
"_NET_WM_WINDOW_TYPE_COMBO\0"
|
||||
"_NET_WM_WINDOW_TYPE_DND\0"
|
||||
"_NET_WM_WINDOW_TYPE_NORMAL\0"
|
||||
"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
|
||||
|
||||
"_KDE_NET_WM_FRAME_STRUT\0"
|
||||
"_NET_FRAME_EXTENTS\0"
|
||||
|
||||
"_NET_STARTUP_INFO\0"
|
||||
"_NET_STARTUP_INFO_BEGIN\0"
|
||||
|
||||
"_NET_SUPPORTING_WM_CHECK\0"
|
||||
|
||||
"_NET_WM_CM_S0\0"
|
||||
|
||||
"_NET_SYSTEM_TRAY_VISUAL\0"
|
||||
|
||||
"_NET_ACTIVE_WINDOW\0"
|
||||
|
||||
// Property formats
|
||||
"TEXT\0"
|
||||
"UTF8_STRING\0"
|
||||
"CARDINAL\0"
|
||||
|
||||
// xdnd
|
||||
"XdndEnter\0"
|
||||
"XdndPosition\0"
|
||||
"XdndStatus\0"
|
||||
"XdndLeave\0"
|
||||
"XdndDrop\0"
|
||||
"XdndFinished\0"
|
||||
"XdndTypeList\0"
|
||||
"XdndActionList\0"
|
||||
|
||||
"XdndSelection\0"
|
||||
|
||||
"XdndAware\0"
|
||||
"XdndProxy\0"
|
||||
|
||||
"XdndActionCopy\0"
|
||||
"XdndActionLink\0"
|
||||
"XdndActionMove\0"
|
||||
"XdndActionPrivate\0"
|
||||
|
||||
// Motif DND
|
||||
"_MOTIF_DRAG_AND_DROP_MESSAGE\0"
|
||||
"_MOTIF_DRAG_INITIATOR_INFO\0"
|
||||
"_MOTIF_DRAG_RECEIVER_INFO\0"
|
||||
"_MOTIF_DRAG_WINDOW\0"
|
||||
"_MOTIF_DRAG_TARGETS\0"
|
||||
|
||||
"XmTRANSFER_SUCCESS\0"
|
||||
"XmTRANSFER_FAILURE\0"
|
||||
|
||||
// Xkb
|
||||
"_XKB_RULES_NAMES\0"
|
||||
|
||||
// XEMBED
|
||||
"_XEMBED\0"
|
||||
"_XEMBED_INFO\0"
|
||||
|
||||
// XInput2
|
||||
"Button Left\0"
|
||||
"Button Middle\0"
|
||||
"Button Right\0"
|
||||
"Button Wheel Up\0"
|
||||
"Button Wheel Down\0"
|
||||
"Button Horiz Wheel Left\0"
|
||||
"Button Horiz Wheel Right\0"
|
||||
"Abs MT Position X\0"
|
||||
"Abs MT Position Y\0"
|
||||
"Abs MT Touch Major\0"
|
||||
"Abs MT Touch Minor\0"
|
||||
"Abs MT Orientation\0"
|
||||
"Abs MT Pressure\0"
|
||||
"Abs MT Tracking ID\0"
|
||||
"Max Contacts\0"
|
||||
"Rel X\0"
|
||||
"Rel Y\0"
|
||||
// XInput2 tablet
|
||||
"Abs X\0"
|
||||
"Abs Y\0"
|
||||
"Abs Pressure\0"
|
||||
"Abs Tilt X\0"
|
||||
"Abs Tilt Y\0"
|
||||
"Abs Wheel\0"
|
||||
"Abs Distance\0"
|
||||
"Wacom Serial IDs\0"
|
||||
"INTEGER\0"
|
||||
"Rel Horiz Wheel\0"
|
||||
"Rel Vert Wheel\0"
|
||||
"Rel Horiz Scroll\0"
|
||||
"Rel Vert Scroll\0"
|
||||
"_XSETTINGS_SETTINGS\0"
|
||||
"_COMPIZ_DECOR_PENDING\0"
|
||||
"_COMPIZ_DECOR_REQUEST\0"
|
||||
"_COMPIZ_DECOR_DELETE_PIXMAP\0"
|
||||
"_COMPIZ_TOOLKIT_ACTION\0"
|
||||
"_GTK_LOAD_ICONTHEMES\0"
|
||||
"AT_SPI_BUS\0"
|
||||
"EDID\0"
|
||||
"EDID_DATA\0"
|
||||
"XFree86_DDC_EDID1_RAWDATA\0"
|
||||
// \0\0 terminates loop.
|
||||
};
|
||||
|
||||
QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const
|
||||
{
|
||||
return static_cast<QXcbAtom::Atom>(std::find(m_allAtoms, m_allAtoms + QXcbAtom::NAtoms, xatom) - m_allAtoms);
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeAllAtoms() {
|
||||
const char *names[QXcbAtom::NAtoms];
|
||||
const char *ptr = xcb_atomnames;
|
||||
|
||||
int i = 0;
|
||||
while (*ptr) {
|
||||
names[i++] = ptr;
|
||||
while (*ptr)
|
||||
++ptr;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
Q_ASSERT(i == QXcbAtom::NAtoms);
|
||||
|
||||
xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
|
||||
|
||||
Q_ASSERT(i == QXcbAtom::NAtoms);
|
||||
for (i = 0; i < QXcbAtom::NAtoms; ++i)
|
||||
cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
|
||||
|
||||
for (i = 0; i < QXcbAtom::NAtoms; ++i) {
|
||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
|
||||
m_allAtoms[i] = reply->atom;
|
||||
free(reply);
|
||||
}
|
||||
}
|
||||
|
||||
xcb_atom_t QXcbConnection::internAtom(const char *name)
|
||||
{
|
||||
if (!name || *name == 0)
|
||||
return XCB_NONE;
|
||||
|
||||
return Q_XCB_REPLY(xcb_intern_atom, xcb_connection(), false, strlen(name), name)->atom;
|
||||
}
|
||||
|
||||
QByteArray QXcbConnection::atomName(xcb_atom_t atom)
|
||||
{
|
||||
if (!atom)
|
||||
return QByteArray();
|
||||
|
||||
auto reply = Q_XCB_REPLY(xcb_get_atom_name, xcb_connection(), atom);
|
||||
if (!reply)
|
||||
qWarning() << "QXcbConnection::atomName: bad Atom" << atom;
|
||||
else
|
||||
return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get()));
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
|
||||
{
|
||||
xcb_format_iterator_t iterator =
|
||||
xcb_setup_pixmap_formats_iterator(m_setup);
|
||||
xcb_setup_pixmap_formats_iterator(setup());
|
||||
|
||||
while (iterator.rem) {
|
||||
xcb_format_t *format = iterator.data;
|
||||
|
|
@ -1823,208 +1436,6 @@ void QXcbConnection::sync()
|
|||
free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeShm()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_shm_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCDebug(lcQpaXcb, "MIT-SHM extension is not present on the X server");
|
||||
return;
|
||||
}
|
||||
has_shm = true;
|
||||
|
||||
auto shm_query = Q_XCB_REPLY(xcb_shm_query_version, m_connection);
|
||||
if (shm_query) {
|
||||
has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) ||
|
||||
shm_query->major_version > 1;
|
||||
} else {
|
||||
qCWarning(lcQpaXcb, "QXcbConnection: Failed to request MIT-SHM version");
|
||||
}
|
||||
|
||||
qCDebug(lcQpaXcb) << "Has MIT-SHM :" << has_shm;
|
||||
qCDebug(lcQpaXcb) << "Has MIT-SHM FD :" << has_shm_fd;
|
||||
|
||||
// Temporary disable warnings (unless running in debug mode).
|
||||
auto logging = const_cast<QLoggingCategory*>(&lcQpaXcb());
|
||||
bool wasEnabled = logging->isEnabled(QtMsgType::QtWarningMsg);
|
||||
if (!logging->isEnabled(QtMsgType::QtDebugMsg))
|
||||
logging->setEnabled(QtMsgType::QtWarningMsg, false);
|
||||
if (!QXcbBackingStore::createSystemVShmSegment(this)) {
|
||||
qCDebug(lcQpaXcb, "failed to create System V shared memory segment (remote "
|
||||
"X11 connection?), disabling SHM");
|
||||
has_shm = has_shm_fd = false;
|
||||
}
|
||||
if (wasEnabled)
|
||||
logging->setEnabled(QtMsgType::QtWarningMsg, true);
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXFixes()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
auto xfixes_query = Q_XCB_REPLY(xcb_xfixes_query_version, m_connection,
|
||||
XCB_XFIXES_MAJOR_VERSION,
|
||||
XCB_XFIXES_MINOR_VERSION);
|
||||
if (!xfixes_query || xfixes_query->major_version < 2) {
|
||||
qWarning("QXcbConnection: Failed to initialize XFixes");
|
||||
return;
|
||||
}
|
||||
xfixes_first_event = reply->first_event;
|
||||
has_xfixes = true;
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXRender()
|
||||
{
|
||||
#if QT_CONFIG(xcb_render)
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_render_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCDebug(lcQpaXcb, "XRender extension not present on the X server");
|
||||
return;
|
||||
}
|
||||
|
||||
auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection,
|
||||
XCB_RENDER_MAJOR_VERSION,
|
||||
XCB_RENDER_MINOR_VERSION);
|
||||
if (!xrender_query) {
|
||||
qCWarning(lcQpaXcb, "xcb_render_query_version failed");
|
||||
return;
|
||||
}
|
||||
|
||||
has_render_extension = true;
|
||||
m_xrenderVersion.first = xrender_query->major_version;
|
||||
m_xrenderVersion.second = xrender_query->minor_version;
|
||||
#endif
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXRandr()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_randr_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
xrandr_first_event = reply->first_event;
|
||||
|
||||
auto xrandr_query = Q_XCB_REPLY(xcb_randr_query_version, m_connection,
|
||||
XCB_RANDR_MAJOR_VERSION,
|
||||
XCB_RANDR_MINOR_VERSION);
|
||||
|
||||
has_randr_extension = true;
|
||||
|
||||
if (!xrandr_query || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) {
|
||||
qWarning("QXcbConnection: Failed to initialize XRandr");
|
||||
has_randr_extension = false;
|
||||
}
|
||||
|
||||
xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup);
|
||||
for (; rootIter.rem; xcb_screen_next(&rootIter)) {
|
||||
xcb_randr_select_input(xcb_connection(),
|
||||
rootIter.data->root,
|
||||
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
|
||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
|
||||
XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
|
||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXinerama()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xinerama_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
auto xinerama_is_active = Q_XCB_REPLY(xcb_xinerama_is_active, m_connection);
|
||||
has_xinerama_extension = xinerama_is_active && xinerama_is_active->state;
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXShape()
|
||||
{
|
||||
const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id);
|
||||
if (!xshape_reply || !xshape_reply->present)
|
||||
return;
|
||||
|
||||
has_shape_extension = true;
|
||||
auto shape_query = Q_XCB_REPLY(xcb_shape_query_version, m_connection);
|
||||
if (!shape_query) {
|
||||
qWarning("QXcbConnection: Failed to initialize SHAPE extension");
|
||||
} else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) {
|
||||
// The input shape is the only thing added in SHAPE 1.1
|
||||
has_input_shape = true;
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXKB()
|
||||
{
|
||||
#if QT_CONFIG(xkb)
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xkb_id);
|
||||
if (!reply || !reply->present) {
|
||||
qWarning("Qt: XKEYBOARD extension not present on the X server.");
|
||||
xkb_first_event = 0;
|
||||
return;
|
||||
}
|
||||
xkb_first_event = reply->first_event;
|
||||
|
||||
xcb_connection_t *c = connection()->xcb_connection();
|
||||
|
||||
auto xkb_query = Q_XCB_REPLY(xcb_xkb_use_extension, c,
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||
XKB_X11_MIN_MINOR_XKB_VERSION);
|
||||
|
||||
if (!xkb_query) {
|
||||
qWarning("Qt: Failed to initialize XKB extension");
|
||||
return;
|
||||
} else if (!xkb_query->supported) {
|
||||
qWarning("Qt: Unsupported XKB version (We want %d %d, but X server has %d %d)",
|
||||
XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION,
|
||||
xkb_query->serverMajor, xkb_query->serverMinor);
|
||||
return;
|
||||
}
|
||||
|
||||
has_xkb = true;
|
||||
|
||||
const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES |
|
||||
XCB_XKB_MAP_PART_KEY_SYMS |
|
||||
XCB_XKB_MAP_PART_MODIFIER_MAP |
|
||||
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
|
||||
XCB_XKB_MAP_PART_KEY_ACTIONS |
|
||||
XCB_XKB_MAP_PART_KEY_BEHAVIORS |
|
||||
XCB_XKB_MAP_PART_VIRTUAL_MODS |
|
||||
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
|
||||
|
||||
const uint16_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
|
||||
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
|
||||
XCB_XKB_EVENT_TYPE_STATE_NOTIFY);
|
||||
|
||||
// XKB events are reported to all interested clients without regard
|
||||
// to the current keyboard input focus or grab state
|
||||
xcb_void_cookie_t select = xcb_xkb_select_events_checked(c,
|
||||
XCB_XKB_ID_USE_CORE_KBD,
|
||||
required_events,
|
||||
0,
|
||||
required_events,
|
||||
required_map_parts,
|
||||
required_map_parts,
|
||||
0);
|
||||
|
||||
xcb_generic_error_t *error = xcb_request_check(c, select);
|
||||
if (error) {
|
||||
free(error);
|
||||
qWarning("Qt: failed to select notify events from xcb-xkb");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void QXcbConnection::initializeXSync()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
has_sync_extension = true;
|
||||
}
|
||||
|
||||
QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const
|
||||
{
|
||||
if (!m_systemTrayTracker) {
|
||||
|
|
|
|||
|
|
@ -47,31 +47,18 @@
|
|||
#include "qxcbexport.h"
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/private/qglobal_p.h>
|
||||
|
||||
#include "qxcbeventqueue.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
// This is needed to make Qt compile together with XKB. xkb.h is using a variable
|
||||
// which is called 'explicit', this is a reserved keyword in c++
|
||||
#if QT_CONFIG(xkb)
|
||||
#define explicit dont_use_cxx_explicit
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#endif
|
||||
#include "qxcbconnection_basic.h"
|
||||
|
||||
#if QT_CONFIG(tabletevent)
|
||||
#include <QTabletEvent>
|
||||
#endif
|
||||
|
||||
struct xcb_randr_get_output_info_reply_t;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput)
|
||||
|
|
@ -79,7 +66,6 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputDevices)
|
|||
Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputEvents)
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaXcb)
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaPeeker)
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaKeyboard)
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaXDnd)
|
||||
|
|
@ -96,215 +82,6 @@ class QXcbNativeInterface;
|
|||
class QXcbSystemTrayTracker;
|
||||
class QXcbGlIntegration;
|
||||
|
||||
namespace QXcbAtom {
|
||||
enum Atom {
|
||||
// window-manager <-> client protocols
|
||||
WM_PROTOCOLS,
|
||||
WM_DELETE_WINDOW,
|
||||
WM_TAKE_FOCUS,
|
||||
_NET_WM_PING,
|
||||
_NET_WM_CONTEXT_HELP,
|
||||
_NET_WM_SYNC_REQUEST,
|
||||
_NET_WM_SYNC_REQUEST_COUNTER,
|
||||
MANAGER, // System tray notification
|
||||
_NET_SYSTEM_TRAY_OPCODE, // System tray operation
|
||||
|
||||
// ICCCM window state
|
||||
WM_STATE,
|
||||
WM_CHANGE_STATE,
|
||||
WM_CLASS,
|
||||
WM_NAME,
|
||||
|
||||
// Session management
|
||||
WM_CLIENT_LEADER,
|
||||
WM_WINDOW_ROLE,
|
||||
SM_CLIENT_ID,
|
||||
WM_CLIENT_MACHINE,
|
||||
|
||||
// Clipboard
|
||||
CLIPBOARD,
|
||||
INCR,
|
||||
TARGETS,
|
||||
MULTIPLE,
|
||||
TIMESTAMP,
|
||||
SAVE_TARGETS,
|
||||
CLIP_TEMPORARY,
|
||||
_QT_SELECTION,
|
||||
_QT_CLIPBOARD_SENTINEL,
|
||||
_QT_SELECTION_SENTINEL,
|
||||
CLIPBOARD_MANAGER,
|
||||
|
||||
RESOURCE_MANAGER,
|
||||
|
||||
_XSETROOT_ID,
|
||||
|
||||
_QT_SCROLL_DONE,
|
||||
_QT_INPUT_ENCODING,
|
||||
|
||||
// Qt/XCB specific
|
||||
_QT_CLOSE_CONNECTION,
|
||||
|
||||
_MOTIF_WM_HINTS,
|
||||
|
||||
DTWM_IS_RUNNING,
|
||||
ENLIGHTENMENT_DESKTOP,
|
||||
_DT_SAVE_MODE,
|
||||
_SGI_DESKS_MANAGER,
|
||||
|
||||
// EWMH (aka NETWM)
|
||||
_NET_SUPPORTED,
|
||||
_NET_VIRTUAL_ROOTS,
|
||||
_NET_WORKAREA,
|
||||
|
||||
_NET_MOVERESIZE_WINDOW,
|
||||
_NET_WM_MOVERESIZE,
|
||||
|
||||
_NET_WM_NAME,
|
||||
_NET_WM_ICON_NAME,
|
||||
_NET_WM_ICON,
|
||||
|
||||
_NET_WM_PID,
|
||||
|
||||
_NET_WM_WINDOW_OPACITY,
|
||||
|
||||
_NET_WM_STATE,
|
||||
_NET_WM_STATE_ABOVE,
|
||||
_NET_WM_STATE_BELOW,
|
||||
_NET_WM_STATE_FULLSCREEN,
|
||||
_NET_WM_STATE_MAXIMIZED_HORZ,
|
||||
_NET_WM_STATE_MAXIMIZED_VERT,
|
||||
_NET_WM_STATE_MODAL,
|
||||
_NET_WM_STATE_STAYS_ON_TOP,
|
||||
_NET_WM_STATE_DEMANDS_ATTENTION,
|
||||
|
||||
_NET_WM_USER_TIME,
|
||||
_NET_WM_USER_TIME_WINDOW,
|
||||
_NET_WM_FULL_PLACEMENT,
|
||||
|
||||
_NET_WM_WINDOW_TYPE,
|
||||
_NET_WM_WINDOW_TYPE_DESKTOP,
|
||||
_NET_WM_WINDOW_TYPE_DOCK,
|
||||
_NET_WM_WINDOW_TYPE_TOOLBAR,
|
||||
_NET_WM_WINDOW_TYPE_MENU,
|
||||
_NET_WM_WINDOW_TYPE_UTILITY,
|
||||
_NET_WM_WINDOW_TYPE_SPLASH,
|
||||
_NET_WM_WINDOW_TYPE_DIALOG,
|
||||
_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
|
||||
_NET_WM_WINDOW_TYPE_POPUP_MENU,
|
||||
_NET_WM_WINDOW_TYPE_TOOLTIP,
|
||||
_NET_WM_WINDOW_TYPE_NOTIFICATION,
|
||||
_NET_WM_WINDOW_TYPE_COMBO,
|
||||
_NET_WM_WINDOW_TYPE_DND,
|
||||
_NET_WM_WINDOW_TYPE_NORMAL,
|
||||
_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
|
||||
|
||||
_KDE_NET_WM_FRAME_STRUT,
|
||||
_NET_FRAME_EXTENTS,
|
||||
|
||||
_NET_STARTUP_INFO,
|
||||
_NET_STARTUP_INFO_BEGIN,
|
||||
|
||||
_NET_SUPPORTING_WM_CHECK,
|
||||
|
||||
_NET_WM_CM_S0,
|
||||
|
||||
_NET_SYSTEM_TRAY_VISUAL,
|
||||
|
||||
_NET_ACTIVE_WINDOW,
|
||||
|
||||
// Property formats
|
||||
TEXT,
|
||||
UTF8_STRING,
|
||||
CARDINAL,
|
||||
|
||||
// Xdnd
|
||||
XdndEnter,
|
||||
XdndPosition,
|
||||
XdndStatus,
|
||||
XdndLeave,
|
||||
XdndDrop,
|
||||
XdndFinished,
|
||||
XdndTypelist,
|
||||
XdndActionList,
|
||||
|
||||
XdndSelection,
|
||||
|
||||
XdndAware,
|
||||
XdndProxy,
|
||||
|
||||
XdndActionCopy,
|
||||
XdndActionLink,
|
||||
XdndActionMove,
|
||||
XdndActionPrivate,
|
||||
|
||||
// Motif DND
|
||||
_MOTIF_DRAG_AND_DROP_MESSAGE,
|
||||
_MOTIF_DRAG_INITIATOR_INFO,
|
||||
_MOTIF_DRAG_RECEIVER_INFO,
|
||||
_MOTIF_DRAG_WINDOW,
|
||||
_MOTIF_DRAG_TARGETS,
|
||||
|
||||
XmTRANSFER_SUCCESS,
|
||||
XmTRANSFER_FAILURE,
|
||||
|
||||
// Xkb
|
||||
_XKB_RULES_NAMES,
|
||||
|
||||
// XEMBED
|
||||
_XEMBED,
|
||||
_XEMBED_INFO,
|
||||
|
||||
// XInput2
|
||||
ButtonLeft,
|
||||
ButtonMiddle,
|
||||
ButtonRight,
|
||||
ButtonWheelUp,
|
||||
ButtonWheelDown,
|
||||
ButtonHorizWheelLeft,
|
||||
ButtonHorizWheelRight,
|
||||
AbsMTPositionX,
|
||||
AbsMTPositionY,
|
||||
AbsMTTouchMajor,
|
||||
AbsMTTouchMinor,
|
||||
AbsMTOrientation,
|
||||
AbsMTPressure,
|
||||
AbsMTTrackingID,
|
||||
MaxContacts,
|
||||
RelX,
|
||||
RelY,
|
||||
// XInput2 tablet
|
||||
AbsX,
|
||||
AbsY,
|
||||
AbsPressure,
|
||||
AbsTiltX,
|
||||
AbsTiltY,
|
||||
AbsWheel,
|
||||
AbsDistance,
|
||||
WacomSerialIDs,
|
||||
INTEGER,
|
||||
RelHorizWheel,
|
||||
RelVertWheel,
|
||||
RelHorizScroll,
|
||||
RelVertScroll,
|
||||
|
||||
_XSETTINGS_SETTINGS,
|
||||
|
||||
_COMPIZ_DECOR_PENDING,
|
||||
_COMPIZ_DECOR_REQUEST,
|
||||
_COMPIZ_DECOR_DELETE_PIXMAP,
|
||||
_COMPIZ_TOOLKIT_ACTION,
|
||||
_GTK_LOAD_ICONTHEMES,
|
||||
|
||||
AT_SPI_BUS,
|
||||
|
||||
EDID,
|
||||
EDID_DATA,
|
||||
XFree86_DDC_EDID1_RAWDATA,
|
||||
|
||||
NAtoms
|
||||
};
|
||||
}
|
||||
|
||||
class QXcbWindowEventListener
|
||||
{
|
||||
public:
|
||||
|
|
@ -346,7 +123,7 @@ private:
|
|||
QXcbWindow *m_window;
|
||||
};
|
||||
|
||||
class Q_XCB_EXPORT QXcbConnection : public QObject
|
||||
class Q_XCB_EXPORT QXcbConnection : public QXcbBasicConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
@ -354,23 +131,15 @@ public:
|
|||
~QXcbConnection();
|
||||
|
||||
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
|
||||
bool isConnected() const;
|
||||
QXcbEventQueue *eventQueue() const { return m_eventQueue; }
|
||||
|
||||
const QList<QXcbVirtualDesktop *> &virtualDesktops() const { return m_virtualDesktops; }
|
||||
const QList<QXcbScreen *> &screens() const { return m_screens; }
|
||||
int primaryScreenNumber() const { return m_primaryScreenNumber; }
|
||||
QXcbVirtualDesktop *primaryVirtualDesktop() const { return m_virtualDesktops.value(m_primaryScreenNumber); }
|
||||
QXcbVirtualDesktop *primaryVirtualDesktop() const {
|
||||
return m_virtualDesktops.value(primaryScreenNumber());
|
||||
}
|
||||
QXcbScreen *primaryScreen() const;
|
||||
|
||||
inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; }
|
||||
QXcbAtom::Atom qatom(xcb_atom_t atom) const;
|
||||
xcb_atom_t internAtom(const char *name);
|
||||
QByteArray atomName(xcb_atom_t atom);
|
||||
|
||||
const char *displayName() const { return m_displayName.constData(); }
|
||||
xcb_connection_t *xcb_connection() const { return m_connection; }
|
||||
const xcb_setup_t *setup() const { return m_setup; }
|
||||
const xcb_format_t *formatForDepth(uint8_t depth) const;
|
||||
|
||||
bool imageNeedsEndianSwap() const
|
||||
|
|
@ -378,9 +147,9 @@ public:
|
|||
if (!hasShm())
|
||||
return false; // The non-Shm path does its own swapping
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||
return m_setup->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST;
|
||||
return setup()->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST;
|
||||
#else
|
||||
return m_setup->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST;
|
||||
return setup()->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -400,9 +169,6 @@ public:
|
|||
bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; }
|
||||
xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; }
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
void *xlib_display() const { return m_xlib_display; }
|
||||
#endif
|
||||
void sync();
|
||||
|
||||
void handleXcbError(xcb_generic_error_t *error);
|
||||
|
|
@ -425,23 +191,6 @@ public:
|
|||
inline xcb_timestamp_t netWmUserTime() const { return m_netWmUserTime; }
|
||||
inline void setNetWmUserTime(xcb_timestamp_t t) { if (t > m_netWmUserTime) m_netWmUserTime = t; }
|
||||
|
||||
bool hasXFixes() const { return has_xfixes; }
|
||||
bool hasXShape() const { return has_shape_extension; }
|
||||
bool hasXRandr() const { return has_randr_extension; }
|
||||
bool hasInputShape() const { return has_input_shape; }
|
||||
bool hasXKB() const { return has_xkb; }
|
||||
bool hasXRender(int major = -1, int minor = -1) const
|
||||
{
|
||||
if (has_render_extension && major != -1 && minor != -1)
|
||||
return m_xrenderVersion >= qMakePair(major, minor);
|
||||
|
||||
return has_render_extension;
|
||||
}
|
||||
bool hasXInput2() const { return m_xi2Enabled; }
|
||||
bool hasShm() const { return has_shm; }
|
||||
bool hasShmFd() const { return has_shm_fd; }
|
||||
bool hasXSync() const { return has_sync_extension; }
|
||||
|
||||
xcb_timestamp_t getTimestamp();
|
||||
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
|
||||
xcb_window_t getQtSelectionOwner();
|
||||
|
|
@ -483,8 +232,6 @@ public:
|
|||
void xi2SelectDeviceEventsCompatibility(xcb_window_t window);
|
||||
bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab);
|
||||
bool xi2MouseEventsDisabled() const;
|
||||
bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
|
||||
bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
|
||||
Qt::MouseButton xiToQtMouseButton(uint32_t b);
|
||||
void xi2UpdateScrollingDevices();
|
||||
bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
|
||||
|
|
@ -496,22 +243,14 @@ public:
|
|||
|
||||
QXcbGlIntegration *glIntegration() const;
|
||||
|
||||
void flush() { xcb_flush(m_connection); }
|
||||
void flush() { xcb_flush(xcb_connection()); }
|
||||
void processXcbEvents(QEventLoop::ProcessEventsFlags flags);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void initializeAllAtoms();
|
||||
void initializeShm();
|
||||
void initializeXFixes();
|
||||
void initializeXRender();
|
||||
void initializeXRandr();
|
||||
void initializeXinerama();
|
||||
void initializeXShape();
|
||||
void initializeXKB();
|
||||
void initializeXSync();
|
||||
void selectXRandrEvents();
|
||||
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const;
|
||||
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const;
|
||||
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow) const;
|
||||
|
|
@ -525,10 +264,7 @@ private:
|
|||
void initializeScreens();
|
||||
bool compressEvent(xcb_generic_event_t *event) const;
|
||||
|
||||
bool m_xi2Enabled = false;
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
int m_xi2Minor = -1;
|
||||
void initializeXInput2();
|
||||
void xi2SetupDevice(void *info, bool removeExisting = true);
|
||||
void xi2SetupDevices();
|
||||
struct TouchDeviceData {
|
||||
|
|
@ -554,7 +290,6 @@ private:
|
|||
void xi2HandleEvent(xcb_ge_event_t *event);
|
||||
void xi2HandleHierarchyEvent(void *event);
|
||||
void xi2HandleDeviceChangedEvent(void *event);
|
||||
int m_xiOpCode;
|
||||
void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
|
||||
#if QT_CONFIG(tabletevent)
|
||||
struct TabletData {
|
||||
|
|
@ -597,22 +332,15 @@ private:
|
|||
static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
|
||||
#endif
|
||||
|
||||
xcb_connection_t *m_connection = nullptr;
|
||||
const xcb_setup_t *m_setup = nullptr;
|
||||
const bool m_canGrabServer;
|
||||
const xcb_visualid_t m_defaultVisualId;
|
||||
|
||||
QList<QXcbVirtualDesktop *> m_virtualDesktops;
|
||||
QList<QXcbScreen *> m_screens;
|
||||
int m_primaryScreenNumber = 0;
|
||||
|
||||
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
|
||||
|
||||
xcb_timestamp_t m_time = XCB_CURRENT_TIME;
|
||||
xcb_timestamp_t m_netWmUserTime = XCB_CURRENT_TIME;
|
||||
|
||||
QByteArray m_displayName;
|
||||
|
||||
QXcbKeyboard *m_keyboard = nullptr;
|
||||
#ifndef QT_NO_CLIPBOARD
|
||||
QXcbClipboard *m_clipboard = nullptr;
|
||||
|
|
@ -623,9 +351,6 @@ private:
|
|||
QScopedPointer<QXcbWMSupport> m_wmSupport;
|
||||
QXcbNativeInterface *m_nativeInterface = nullptr;
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
void *m_xlib_display = nullptr;
|
||||
#endif
|
||||
QXcbEventQueue *m_eventQueue = nullptr;
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
|
|
@ -641,26 +366,6 @@ private:
|
|||
|
||||
QVector<PeekFunc> m_peekFuncs;
|
||||
|
||||
uint32_t xfixes_first_event = 0;
|
||||
uint32_t xrandr_first_event = 0;
|
||||
uint32_t xkb_first_event = 0;
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
uint32_t xinput_first_event = 0;
|
||||
#endif
|
||||
|
||||
bool has_xfixes = false;
|
||||
bool has_xinerama_extension = false;
|
||||
bool has_shape_extension = false;
|
||||
bool has_randr_extension = false;
|
||||
bool has_input_shape;
|
||||
bool has_xkb = false;
|
||||
bool has_render_extension = false;
|
||||
bool has_shm = false;
|
||||
bool has_shm_fd = false;
|
||||
bool has_sync_extension = false;
|
||||
|
||||
QPair<int, int> m_xrenderVersion;
|
||||
|
||||
Qt::MouseButtons m_buttonState = 0;
|
||||
Qt::MouseButton m_button = Qt::NoButton;
|
||||
|
||||
|
|
@ -699,22 +404,6 @@ private:
|
|||
QXcbConnection *m_connection;
|
||||
};
|
||||
|
||||
#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
|
||||
|
||||
struct QStdFreeDeleter {
|
||||
void operator()(void *p) const Q_DECL_NOTHROW { return std::free(p); }
|
||||
};
|
||||
|
||||
#define Q_XCB_REPLY(call, ...) \
|
||||
std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
|
||||
call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr) \
|
||||
)
|
||||
|
||||
#define Q_XCB_REPLY_UNCHECKED(call, ...) \
|
||||
std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
|
||||
call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr) \
|
||||
)
|
||||
|
||||
// The xcb_send_event() requires all events to have 32 bytes. It calls memcpy() on the
|
||||
// passed in event. If the passed in event is less than 32 bytes, memcpy() reaches into
|
||||
// unrelated memory.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,437 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore 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 "qxcbconnection_basic.h"
|
||||
#include "qxcbbackingstore.h" // for createSystemVShmSegment()
|
||||
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/sync.h>
|
||||
#include <xcb/xfixes.h>
|
||||
#include <xcb/xinerama.h>
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#include <xcb/xinput.h>
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_render)
|
||||
#include <xcb/render.h>
|
||||
#endif
|
||||
#if QT_CONFIG(xkb)
|
||||
#define explicit dont_use_cxx_explicit
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
#define register /* C++17 deprecated register */
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/Xutil.h>
|
||||
#undef register
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcQpaXcb, "qt.qpa.xcb")
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
static const char * const xcbConnectionErrors[] = {
|
||||
"No error", /* Error 0 */
|
||||
"I/O error", /* XCB_CONN_ERROR */
|
||||
"Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
|
||||
"Out of memory", /* XCB_CONN_CLOSED_MEM_INSUFFICIENT */
|
||||
"Maximum allowed requested length exceeded", /* XCB_CONN_CLOSED_REQ_LEN_EXCEED */
|
||||
"Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
|
||||
"No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
|
||||
"Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
|
||||
};
|
||||
|
||||
static int nullErrorHandler(Display *dpy, XErrorEvent *err)
|
||||
{
|
||||
#ifndef Q_XCB_DEBUG
|
||||
Q_UNUSED(dpy);
|
||||
Q_UNUSED(err);
|
||||
#else
|
||||
const int buflen = 1024;
|
||||
char buf[buflen];
|
||||
|
||||
XGetErrorText(dpy, err->error_code, buf, buflen);
|
||||
fprintf(stderr, "X Error: serial %lu error %d %s\n", err->serial, (int) err->error_code, buf);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioErrorHandler(Display *dpy)
|
||||
{
|
||||
xcb_connection_t *conn = XGetXCBConnection(dpy);
|
||||
if (conn != NULL) {
|
||||
/* Print a message with a textual description of the error */
|
||||
int code = xcb_connection_has_error(conn);
|
||||
const char *str = "Unknown error";
|
||||
int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
|
||||
if (code >= 0 && code < arrayLength)
|
||||
str = xcbConnectionErrors[code];
|
||||
|
||||
qWarning("The X11 connection broke: %s (code %d)", str, code);
|
||||
}
|
||||
return _XDefaultIOError(dpy);
|
||||
}
|
||||
#endif
|
||||
|
||||
QXcbBasicConnection::QXcbBasicConnection(const char *displayName)
|
||||
: m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
|
||||
{
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
Display *dpy = XOpenDisplay(m_displayName.constData());
|
||||
if (dpy) {
|
||||
m_primaryScreenNumber = DefaultScreen(dpy);
|
||||
m_xcbConnection = XGetXCBConnection(dpy);
|
||||
XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
|
||||
XSetErrorHandler(nullErrorHandler);
|
||||
XSetIOErrorHandler(ioErrorHandler);
|
||||
m_xlibDisplay = dpy;
|
||||
}
|
||||
#else
|
||||
m_xcbConnection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber);
|
||||
#endif
|
||||
if (Q_UNLIKELY(!isConnected())) {
|
||||
qCWarning(lcQpaXcb, "could not connect to display %s", m_displayName.constData());
|
||||
return;
|
||||
}
|
||||
|
||||
m_setup = xcb_get_setup(m_xcbConnection);
|
||||
m_xcbAtom.initialize(m_xcbConnection);
|
||||
|
||||
xcb_extension_t *extensions[] = {
|
||||
&xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
|
||||
#if QT_CONFIG(xkb)
|
||||
&xcb_xkb_id,
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_render)
|
||||
&xcb_render_id,
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
&xcb_input_id,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
for (xcb_extension_t **ext_it = extensions; *ext_it; ++ext_it)
|
||||
xcb_prefetch_extension_data (m_xcbConnection, *ext_it);
|
||||
|
||||
initializeXSync();
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_MITSHM"))
|
||||
initializeShm();
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR"))
|
||||
initializeXRandr();
|
||||
if (!m_hasXRandr)
|
||||
initializeXinerama();
|
||||
initializeXFixes();
|
||||
initializeXRender();
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_XI2"))
|
||||
initializeXInput2();
|
||||
#endif
|
||||
initializeXShape();
|
||||
initializeXKB();
|
||||
}
|
||||
|
||||
QXcbBasicConnection::~QXcbBasicConnection()
|
||||
{
|
||||
if (isConnected()) {
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
XCloseDisplay(static_cast<Display *>(m_xlibDisplay));
|
||||
#else
|
||||
xcb_disconnect(m_xcbConnection);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
xcb_atom_t QXcbBasicConnection::internAtom(const char *name)
|
||||
{
|
||||
if (!name || *name == 0)
|
||||
return XCB_NONE;
|
||||
|
||||
return Q_XCB_REPLY(xcb_intern_atom, m_xcbConnection, false, strlen(name), name)->atom;
|
||||
}
|
||||
|
||||
QByteArray QXcbBasicConnection::atomName(xcb_atom_t atom)
|
||||
{
|
||||
if (!atom)
|
||||
return QByteArray();
|
||||
|
||||
auto reply = Q_XCB_REPLY(xcb_get_atom_name, m_xcbConnection, atom);
|
||||
if (reply)
|
||||
return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get()));
|
||||
|
||||
qCWarning(lcQpaXcb) << "atomName: bad atom" << atom;
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
|
||||
// - "pad0" became "extension"
|
||||
// - "pad1" and "pad" became "pad0"
|
||||
// New and old version of this struct share the following fields:
|
||||
typedef struct qt_xcb_ge_event_t {
|
||||
uint8_t response_type;
|
||||
uint8_t extension;
|
||||
uint16_t sequence;
|
||||
uint32_t length;
|
||||
uint16_t event_type;
|
||||
} qt_xcb_ge_event_t;
|
||||
|
||||
bool QXcbBasicConnection::isXIEvent(xcb_generic_event_t *event) const
|
||||
{
|
||||
qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
|
||||
return e->extension == m_xiOpCode;
|
||||
}
|
||||
|
||||
bool QXcbBasicConnection::isXIType(xcb_generic_event_t *event, uint16_t type) const
|
||||
{
|
||||
if (!isXIEvent(event))
|
||||
return false;
|
||||
|
||||
auto *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
|
||||
return e->event_type == type;
|
||||
}
|
||||
#endif // QT_CONFIG(xcb_xinput)
|
||||
|
||||
bool QXcbBasicConnection::isXFixesType(uint responseType, int eventType) const
|
||||
{
|
||||
return m_hasXFixes && responseType == m_xfixesFirstEvent + eventType;
|
||||
}
|
||||
|
||||
bool QXcbBasicConnection::isXRandrType(uint responseType, int eventType) const
|
||||
{
|
||||
return m_hasXRandr && responseType == m_xrandrFirstEvent + eventType;
|
||||
}
|
||||
|
||||
bool QXcbBasicConnection::isXkbType(uint responseType) const
|
||||
{
|
||||
return m_hasXkb && responseType == m_xkbFirstEvent;
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeXSync()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_sync_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
m_hasXSync = true;
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeShm()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_shm_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCDebug(lcQpaXcb, "MIT-SHM extension is not present on the X server");
|
||||
return;
|
||||
}
|
||||
|
||||
auto shmQuery = Q_XCB_REPLY(xcb_shm_query_version, m_xcbConnection);
|
||||
if (!shmQuery) {
|
||||
qCWarning(lcQpaXcb, "failed to request MIT-SHM version");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasShm = true;
|
||||
m_hasShmFd = (shmQuery->major_version == 1 && shmQuery->minor_version >= 2) ||
|
||||
shmQuery->major_version > 1;
|
||||
|
||||
qCDebug(lcQpaXcb) << "Has MIT-SHM :" << m_hasShm;
|
||||
qCDebug(lcQpaXcb) << "Has MIT-SHM FD :" << m_hasShmFd;
|
||||
|
||||
// Temporary disable warnings (unless running in debug mode).
|
||||
auto logging = const_cast<QLoggingCategory*>(&lcQpaXcb());
|
||||
bool wasEnabled = logging->isEnabled(QtMsgType::QtWarningMsg);
|
||||
if (!logging->isEnabled(QtMsgType::QtDebugMsg))
|
||||
logging->setEnabled(QtMsgType::QtWarningMsg, false);
|
||||
if (!QXcbBackingStore::createSystemVShmSegment(m_xcbConnection)) {
|
||||
qCDebug(lcQpaXcb, "failed to create System V shared memory segment (remote "
|
||||
"X11 connection?), disabling SHM");
|
||||
m_hasShm = m_hasShmFd = false;
|
||||
}
|
||||
if (wasEnabled)
|
||||
logging->setEnabled(QtMsgType::QtWarningMsg, true);
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeXRandr()
|
||||
{
|
||||
#if QT_CONFIG(xcb_render)
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCDebug(lcQpaXcb, "XRender extension not present on the X server");
|
||||
return;
|
||||
}
|
||||
|
||||
auto xrenderQuery = Q_XCB_REPLY(xcb_render_query_version, m_xcbConnection,
|
||||
XCB_RENDER_MAJOR_VERSION,
|
||||
XCB_RENDER_MINOR_VERSION);
|
||||
if (!xrenderQuery) {
|
||||
qCWarning(lcQpaXcb, "xcb_render_query_version failed");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasXRender = true;
|
||||
m_xrenderVersion.first = xrenderQuery->major_version;
|
||||
m_xrenderVersion.second = xrenderQuery->minor_version;
|
||||
#endif
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeXinerama()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xinerama_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
auto xineramaActive = Q_XCB_REPLY(xcb_xinerama_is_active, m_xcbConnection);
|
||||
if (xineramaActive && xineramaActive->state)
|
||||
m_hasXinerama = true;
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeXFixes()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xfixes_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
auto xfixesQuery = Q_XCB_REPLY(xcb_xfixes_query_version, m_xcbConnection,
|
||||
XCB_XFIXES_MAJOR_VERSION,
|
||||
XCB_XFIXES_MINOR_VERSION);
|
||||
if (!xfixesQuery || xfixesQuery->major_version < 2) {
|
||||
qCWarning(lcQpaXcb, "failed to initialize XFixes");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasXFixes = true;
|
||||
m_xfixesFirstEvent = reply->first_event;
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeXRender()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
auto xrandrQuery = Q_XCB_REPLY(xcb_randr_query_version, m_xcbConnection,
|
||||
XCB_RANDR_MAJOR_VERSION,
|
||||
XCB_RANDR_MINOR_VERSION);
|
||||
if (!xrandrQuery || (xrandrQuery->major_version < 1 ||
|
||||
(xrandrQuery->major_version == 1 && xrandrQuery->minor_version < 2))) {
|
||||
qCWarning(lcQpaXcb, "failed to initialize XRandr");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasXRandr = true;
|
||||
m_xrandrFirstEvent = reply->first_event;
|
||||
}
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
void QXcbBasicConnection::initializeXInput2()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_input_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCDebug(lcQpaXcb, "XInput extension is not present on the X server");
|
||||
return;
|
||||
}
|
||||
|
||||
auto xinputQuery = Q_XCB_REPLY(xcb_input_xi_query_version, m_xcbConnection, 2, 2);
|
||||
if (!xinputQuery || xinputQuery->major_version != 2) {
|
||||
qCWarning(lcQpaXcb, "X server does not support XInput 2");
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(lcQpaXcb, "Using XInput version %d.%d",
|
||||
xinputQuery->major_version, xinputQuery->minor_version);
|
||||
|
||||
m_xi2Enabled = true;
|
||||
m_xiOpCode = reply->major_opcode;
|
||||
m_xinputFirstEvent = reply->first_event;
|
||||
m_xi2Minor = xinputQuery->minor_version;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QXcbBasicConnection::initializeXShape()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_shape_id);
|
||||
if (!reply || !reply->present)
|
||||
return;
|
||||
|
||||
m_hasXhape = true;
|
||||
|
||||
auto shapeQuery = Q_XCB_REPLY(xcb_shape_query_version, m_xcbConnection);
|
||||
if (!shapeQuery) {
|
||||
qCWarning(lcQpaXcb, "failed to initialize XShape extension");
|
||||
return;
|
||||
}
|
||||
|
||||
if (shapeQuery->major_version > 1 || (shapeQuery->major_version == 1 && shapeQuery->minor_version >= 1)) {
|
||||
// The input shape is the only thing added in SHAPE 1.1
|
||||
m_hasInputShape = true;
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbBasicConnection::initializeXKB()
|
||||
{
|
||||
#if QT_CONFIG(xkb)
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xkb_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCWarning(lcQpaXcb, "XKeyboard extension not present on the X server");
|
||||
return;
|
||||
}
|
||||
|
||||
int wantMajor = 1;
|
||||
int wantMinor = 0;
|
||||
auto xkbQuery = Q_XCB_REPLY(xcb_xkb_use_extension, m_xcbConnection, wantMajor, wantMinor);
|
||||
if (!xkbQuery) {
|
||||
qCWarning(lcQpaXcb, "failed to initialize XKeyboard extension");
|
||||
return;
|
||||
}
|
||||
if (!xkbQuery->supported) {
|
||||
qCWarning(lcQpaXcb, "unsupported XKB version (we want %d.%d, but X server has %d.%d)",
|
||||
wantMajor, wantMinor, xkbQuery->serverMajor, xkbQuery->serverMinor);
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasXkb = true;
|
||||
m_xkbFirstEvent = reply->first_event;
|
||||
#endif
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXCBBASICCONNECTION_H
|
||||
#define QXCBBASICCONNECTION_H
|
||||
|
||||
#include "qxcbatom.h"
|
||||
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtGui/private/qtguiglobal_p.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaXcb)
|
||||
|
||||
class QXcbBasicConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QXcbBasicConnection(const char *displayName);
|
||||
~QXcbBasicConnection();
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
void *xlib_display() const { return m_xlibDisplay; }
|
||||
#endif
|
||||
const char *displayName() const { return m_displayName.constData(); }
|
||||
int primaryScreenNumber() const { return m_primaryScreenNumber; }
|
||||
xcb_connection_t *xcb_connection() const { return m_xcbConnection; }
|
||||
bool isConnected() const {
|
||||
return m_xcbConnection && !xcb_connection_has_error(m_xcbConnection);
|
||||
}
|
||||
const xcb_setup_t *setup() const { return m_setup; }
|
||||
|
||||
inline xcb_atom_t atom(QXcbAtom::Atom qatom) const { return m_xcbAtom.atom(qatom); }
|
||||
QXcbAtom::Atom qatom(xcb_atom_t atom) const { return m_xcbAtom.qatom(atom); }
|
||||
xcb_atom_t internAtom(const char *name);
|
||||
QByteArray atomName(xcb_atom_t atom);
|
||||
|
||||
bool hasXFixes() const { return m_hasXFixes; }
|
||||
bool hasXShape() const { return m_hasXhape; }
|
||||
bool hasXRandr() const { return m_hasXRandr; }
|
||||
bool hasInputShape() const { return m_hasInputShape; }
|
||||
bool hasXKB() const { return m_hasXkb; }
|
||||
bool hasXRender(int major = -1, int minor = -1) const {
|
||||
if (m_hasXRender && major != -1 && minor != -1)
|
||||
return m_xrenderVersion >= qMakePair(major, minor);
|
||||
|
||||
return m_hasXRender;
|
||||
}
|
||||
bool hasXInput2() const { return m_xi2Enabled; }
|
||||
bool hasShm() const { return m_hasShm; }
|
||||
bool hasShmFd() const { return m_hasShmFd; }
|
||||
bool hasXSync() const { return m_hasXSync; }
|
||||
bool hasXinerama() const { return m_hasXinerama; }
|
||||
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
|
||||
bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
|
||||
bool isXIEvent(xcb_generic_event_t *event) const;
|
||||
bool isXIType(xcb_generic_event_t *event, uint16_t type) const;
|
||||
#endif
|
||||
|
||||
bool isXFixesType(uint responseType, int eventType) const;
|
||||
bool isXRandrType(uint responseType, int eventType) const;
|
||||
bool isXkbType(uint responseType) const; // https://bugs.freedesktop.org/show_bug.cgi?id=51295
|
||||
|
||||
protected:
|
||||
void initializeShm();
|
||||
void initializeXFixes();
|
||||
void initializeXRender();
|
||||
void initializeXRandr();
|
||||
void initializeXinerama();
|
||||
void initializeXShape();
|
||||
void initializeXKB();
|
||||
void initializeXSync();
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
void initializeXInput2();
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
void *m_xlibDisplay = nullptr;
|
||||
#endif
|
||||
QByteArray m_displayName;
|
||||
xcb_connection_t *m_xcbConnection = nullptr;
|
||||
int m_primaryScreenNumber = 0;
|
||||
const xcb_setup_t *m_setup = nullptr;
|
||||
QXcbAtom m_xcbAtom;
|
||||
|
||||
bool m_hasXFixes = false;
|
||||
bool m_hasXinerama = false;
|
||||
bool m_hasXhape = false;
|
||||
bool m_hasInputShape;
|
||||
bool m_hasXRandr = false;
|
||||
bool m_hasXkb = false;
|
||||
bool m_hasXRender = false;
|
||||
bool m_hasShm = false;
|
||||
bool m_hasShmFd = false;
|
||||
bool m_hasXSync = false;
|
||||
|
||||
QPair<int, int> m_xrenderVersion;
|
||||
|
||||
bool m_xi2Enabled = false;
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
int m_xi2Minor = -1;
|
||||
int m_xiOpCode = -1;
|
||||
uint32_t m_xinputFirstEvent = 0;
|
||||
#endif
|
||||
|
||||
uint32_t m_xfixesFirstEvent = 0;
|
||||
uint32_t m_xrandrFirstEvent = 0;
|
||||
uint32_t m_xkbFirstEvent = 0;
|
||||
};
|
||||
|
||||
#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
|
||||
|
||||
struct QStdFreeDeleter {
|
||||
void operator()(void *p) const Q_DECL_NOTHROW { return std::free(p); }
|
||||
};
|
||||
|
||||
#define Q_XCB_REPLY(call, ...) \
|
||||
std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
|
||||
call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr) \
|
||||
)
|
||||
|
||||
#define Q_XCB_REPLY_UNCHECKED(call, ...) \
|
||||
std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
|
||||
call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr) \
|
||||
)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QXCBBASICCONNECTION_H
|
||||
|
|
@ -51,31 +51,6 @@
|
|||
|
||||
using qt_xcb_input_device_event_t = xcb_input_button_press_event_t;
|
||||
|
||||
void QXcbConnection::initializeXInput2()
|
||||
{
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_input_id);
|
||||
if (!reply || !reply->present) {
|
||||
qCDebug(lcQpaXInput, "XInput extension is not present on the X server");
|
||||
return;
|
||||
}
|
||||
|
||||
m_xiOpCode = reply->major_opcode;
|
||||
xinput_first_event = reply->first_event;
|
||||
|
||||
auto xinput_query = Q_XCB_REPLY(xcb_input_xi_query_version, m_connection, 2, 2);
|
||||
|
||||
if (!xinput_query || xinput_query->major_version != 2) {
|
||||
qCWarning(lcQpaXInput, "X server does not support XInput 2");
|
||||
} else {
|
||||
qCDebug(lcQpaXInput, "Using XInput version %d.%d",
|
||||
xinput_query->major_version, xinput_query->minor_version);
|
||||
m_xi2Minor = xinput_query->minor_version;
|
||||
m_xi2Enabled = true;
|
||||
xi2SetupDevices();
|
||||
xi2SelectStateEvents();
|
||||
}
|
||||
}
|
||||
|
||||
struct qt_xcb_input_event_mask_t {
|
||||
xcb_input_event_mask_t header;
|
||||
uint32_t mask;
|
||||
|
|
@ -91,7 +66,7 @@ void QXcbConnection::xi2SelectStateEvents()
|
|||
xiEventMask.mask = XCB_INPUT_XI_EVENT_MASK_HIERARCHY;
|
||||
xiEventMask.mask |= XCB_INPUT_XI_EVENT_MASK_DEVICE_CHANGED;
|
||||
xiEventMask.mask |= XCB_INPUT_XI_EVENT_MASK_PROPERTY;
|
||||
xcb_input_xi_select_events(m_connection, rootWindow(), 1, &xiEventMask.header);
|
||||
xcb_input_xi_select_events(xcb_connection(), rootWindow(), 1, &xiEventMask.header);
|
||||
}
|
||||
|
||||
void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window)
|
||||
|
|
@ -117,8 +92,8 @@ void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window)
|
|||
mask.header.mask_len = 1;
|
||||
mask.mask = bitMask;
|
||||
xcb_void_cookie_t cookie =
|
||||
xcb_input_xi_select_events_checked(m_connection, window, 1, &mask.header);
|
||||
xcb_generic_error_t *error = xcb_request_check(m_connection, cookie);
|
||||
xcb_input_xi_select_events_checked(xcb_connection(), window, 1, &mask.header);
|
||||
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
|
||||
if (error) {
|
||||
qCDebug(lcQpaXInput, "failed to select events, window %x, error code %d", window, error->error_code);
|
||||
free(error);
|
||||
|
|
@ -310,7 +285,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||
m_touchDevices.clear();
|
||||
m_xiMasterPointerIds.clear();
|
||||
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, m_connection, XCB_INPUT_DEVICE_ALL);
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), XCB_INPUT_DEVICE_ALL);
|
||||
if (!reply) {
|
||||
qCDebug(lcQpaXInputDevices) << "failed to query devices";
|
||||
return;
|
||||
|
|
@ -387,8 +362,8 @@ void QXcbConnection::xi2SelectDeviceEventsCompatibility(xcb_window_t window)
|
|||
xiMask.mask = mask;
|
||||
|
||||
xcb_void_cookie_t cookie =
|
||||
xcb_input_xi_select_events_checked(m_connection, window, 1, &xiMask.header);
|
||||
xcb_generic_error_t *error = xcb_request_check(m_connection, cookie);
|
||||
xcb_input_xi_select_events_checked(xcb_connection(), window, 1, &xiMask.header);
|
||||
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
|
||||
if (error) {
|
||||
qCDebug(lcQpaXInput, "failed to select events, window %x, error code %d", window, error->error_code);
|
||||
free(error);
|
||||
|
|
@ -413,7 +388,7 @@ void QXcbConnection::xi2SelectDeviceEventsCompatibility(xcb_window_t window)
|
|||
xiEventMask[i].header.mask_len = 1;
|
||||
xiEventMask[i].mask = mask;
|
||||
}
|
||||
xcb_input_xi_select_events(m_connection, window, nrTablets, &(xiEventMask.data()->header));
|
||||
xcb_input_xi_select_events(xcb_connection(), window, nrTablets, &(xiEventMask.data()->header));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -430,7 +405,7 @@ void QXcbConnection::xi2SelectDeviceEventsCompatibility(xcb_window_t window)
|
|||
xiEventMask[i].mask = mask;
|
||||
i++;
|
||||
}
|
||||
xcb_input_xi_select_events(m_connection, window, i, &(xiEventMask.data()->header));
|
||||
xcb_input_xi_select_events(xcb_connection(), window, i, &(xiEventMask.data()->header));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -633,7 +608,7 @@ bool QXcbConnection::xi2MouseEventsDisabled() const
|
|||
static bool xi2MouseDisabled = qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
|
||||
// FIXME: Don't use XInput2 mouse events when Xinerama extension
|
||||
// is enabled, because it causes problems with multi-monitor setup.
|
||||
return xi2MouseDisabled || has_xinerama_extension;
|
||||
return xi2MouseDisabled || hasXinerama();
|
||||
}
|
||||
|
||||
bool QXcbConnection::isTouchScreen(int id)
|
||||
|
|
@ -745,7 +720,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||
// Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence
|
||||
// will get replayed when the grab ends.
|
||||
if (m_xiGrab) {
|
||||
xcb_input_xi_allow_events(m_connection, XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
|
||||
xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
|
||||
XCB_INPUT_EVENT_MODE_ACCEPT_TOUCH,
|
||||
xiDeviceEvent->detail, xiDeviceEvent->event);
|
||||
}
|
||||
|
|
@ -771,7 +746,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||
xiDeviceEvent->detail == m_startSystemMoveResizeInfo.pointid) {
|
||||
QXcbWindow *window = platformWindowFromId(m_startSystemMoveResizeInfo.window);
|
||||
if (window) {
|
||||
xcb_input_xi_allow_events(m_connection, XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
|
||||
xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
|
||||
XCB_INPUT_EVENT_MODE_REJECT_TOUCH,
|
||||
xiDeviceEvent->detail, xiDeviceEvent->event);
|
||||
window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.corner);
|
||||
|
|
@ -850,10 +825,10 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
|
|||
|
||||
for (int id : m_xiMasterPointerIds) {
|
||||
xcb_generic_error_t *error = nullptr;
|
||||
auto cookie = xcb_input_xi_grab_device(m_connection, w, XCB_CURRENT_TIME, XCB_CURSOR_NONE, id,
|
||||
auto cookie = xcb_input_xi_grab_device(xcb_connection(), w, XCB_CURRENT_TIME, XCB_CURSOR_NONE, id,
|
||||
XCB_INPUT_GRAB_MODE_22_ASYNC, XCB_INPUT_GRAB_MODE_22_ASYNC,
|
||||
false, 1, &mask);
|
||||
auto *reply = xcb_input_xi_grab_device_reply(m_connection, cookie, &error);
|
||||
auto *reply = xcb_input_xi_grab_device_reply(xcb_connection(), cookie, &error);
|
||||
if (error) {
|
||||
qCDebug(lcQpaXInput, "failed to grab events for device %d on window %x"
|
||||
"(error code %d)", id, w, error->error_code);
|
||||
|
|
@ -867,8 +842,8 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
|
|||
}
|
||||
} else { // ungrab
|
||||
for (int id : m_xiMasterPointerIds) {
|
||||
auto cookie = xcb_input_xi_ungrab_device_checked(m_connection, XCB_CURRENT_TIME, id);
|
||||
xcb_generic_error_t *error = xcb_request_check(m_connection, cookie);
|
||||
auto cookie = xcb_input_xi_ungrab_device_checked(xcb_connection(), XCB_CURRENT_TIME, id);
|
||||
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
|
||||
if (error) {
|
||||
qCDebug(lcQpaXInput, "XIUngrabDevice failed - id: %d (error code %d)", id, error->error_code);
|
||||
free(error);
|
||||
|
|
@ -911,7 +886,7 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
|
|||
auto *xiEvent = reinterpret_cast<xcb_input_device_changed_event_t *>(event);
|
||||
switch (xiEvent->reason) {
|
||||
case XCB_INPUT_CHANGE_REASON_DEVICE_CHANGE: {
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, m_connection, xiEvent->sourceid);
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), xiEvent->sourceid);
|
||||
if (!reply || reply->num_infos <= 0)
|
||||
return;
|
||||
auto it = xcb_input_xi_query_device_infos_iterator(reply.get());
|
||||
|
|
@ -931,7 +906,7 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
|
|||
|
||||
void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
|
||||
{
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, m_connection, scrollingDevice.deviceId);
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), scrollingDevice.deviceId);
|
||||
if (!reply || reply->num_infos <= 0) {
|
||||
qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId);
|
||||
return;
|
||||
|
|
@ -1184,7 +1159,7 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
|
|||
_WACSER_COUNT
|
||||
};
|
||||
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_get_property, m_connection, tabletData->deviceId, 0,
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_get_property, xcb_connection(), tabletData->deviceId, 0,
|
||||
ev->property, XCB_GET_PROPERTY_TYPE_ANY, 0, 100);
|
||||
if (reply) {
|
||||
if (reply->type == atom(QXcbAtom::INTEGER) && reply->format == 32 && reply->num_items == _WACSER_COUNT) {
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ void QXcbEventQueue::sendCloseConnectionEvent() const
|
|||
|
||||
xcb_connection_t *c = m_connection->xcb_connection();
|
||||
const xcb_window_t window = xcb_generate_id(c);
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_connection->m_setup);
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_connection->setup());
|
||||
xcb_screen_t *screen = it.data;
|
||||
xcb_create_window(c, XCB_COPY_FROM_PARENT,
|
||||
window, screen->root,
|
||||
|
|
|
|||
|
|
@ -1190,9 +1190,10 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
|
|||
#if QT_CONFIG(xkb)
|
||||
core_device_id = 0;
|
||||
if (connection->hasXKB()) {
|
||||
selectEvents();
|
||||
core_device_id = xkb_x11_get_core_keyboard_device_id(xcb_connection());
|
||||
if (core_device_id == -1) {
|
||||
qWarning("Qt: couldn't get core keyboard device info");
|
||||
qCWarning(lcQpaXcb, "failed to get core keyboard device info");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1210,6 +1211,42 @@ QXcbKeyboard::~QXcbKeyboard()
|
|||
xcb_key_symbols_free(m_key_symbols);
|
||||
}
|
||||
|
||||
void QXcbKeyboard::selectEvents()
|
||||
{
|
||||
#if QT_CONFIG(xkb)
|
||||
const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES |
|
||||
XCB_XKB_MAP_PART_KEY_SYMS |
|
||||
XCB_XKB_MAP_PART_MODIFIER_MAP |
|
||||
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
|
||||
XCB_XKB_MAP_PART_KEY_ACTIONS |
|
||||
XCB_XKB_MAP_PART_KEY_BEHAVIORS |
|
||||
XCB_XKB_MAP_PART_VIRTUAL_MODS |
|
||||
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
|
||||
|
||||
const uint16_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
|
||||
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
|
||||
XCB_XKB_EVENT_TYPE_STATE_NOTIFY);
|
||||
|
||||
// XKB events are reported to all interested clients without regard
|
||||
// to the current keyboard input focus or grab state
|
||||
xcb_void_cookie_t select = xcb_xkb_select_events_checked(
|
||||
xcb_connection(),
|
||||
XCB_XKB_ID_USE_CORE_KBD,
|
||||
required_events,
|
||||
0,
|
||||
required_events,
|
||||
required_map_parts,
|
||||
required_map_parts,
|
||||
0);
|
||||
|
||||
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), select);
|
||||
if (error) {
|
||||
free(error);
|
||||
qCWarning(lcQpaXcb, "failed to select notify events from XKB");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void QXcbKeyboard::updateVModMapping()
|
||||
{
|
||||
#if QT_CONFIG(xkb)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@
|
|||
#include "qxcbobject.h"
|
||||
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
#if QT_CONFIG(xkb)
|
||||
#define explicit dont_use_cxx_explicit
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#endif
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#if QT_CONFIG(xkb)
|
||||
|
|
@ -62,6 +67,8 @@ public:
|
|||
|
||||
~QXcbKeyboard();
|
||||
|
||||
void selectEvents();
|
||||
|
||||
void handleKeyPressEvent(const xcb_key_press_event_t *event);
|
||||
void handleKeyReleaseEvent(const xcb_key_release_event_t *event);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ macos: CONFIG += no_app_extension_api_only
|
|||
|
||||
SOURCES = \
|
||||
qxcbmain.cpp
|
||||
|
||||
OTHER_FILES += xcb.json README
|
||||
|
||||
PLUGIN_TYPE = platforms
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ SOURCES = \
|
|||
qxcbxsettings.cpp \
|
||||
qxcbsystemtraytracker.cpp \
|
||||
qxcbeventqueue.cpp \
|
||||
qxcbeventdispatcher.cpp
|
||||
qxcbeventdispatcher.cpp \
|
||||
qxcbconnection_basic.cpp \
|
||||
qxcbatom.cpp
|
||||
|
||||
HEADERS = \
|
||||
qxcbclipboard.h \
|
||||
|
|
@ -51,7 +53,9 @@ HEADERS = \
|
|||
qxcbsystemtraytracker.h \
|
||||
qxcbxkbcommon.h \
|
||||
qxcbeventqueue.h \
|
||||
qxcbeventdispatcher.h
|
||||
qxcbeventdispatcher.h \
|
||||
qxcbconnection_basic.h \
|
||||
qxcbatom.h
|
||||
|
||||
qtConfig(draganddrop) {
|
||||
SOURCES += qxcbdrag.cpp
|
||||
|
|
|
|||
Loading…
Reference in New Issue