summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/README6
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp59
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp21
-rw-r--r--src/plugins/platforms/xcb/xcb-static/xcb-static.pro6
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro2
11 files changed, 113 insertions, 22 deletions
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index 2f666bebfd..15cf4cf241 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -3,14 +3,14 @@ Requires libxcb >= 1.5.
PACKAGE DEPENDENCIES
Required packages:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev
On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev
The packages for xcb-render-util can be installed manually from http://packages.ubuntu.com/natty/libxcb-render-util0 and http://packages.ubuntu.com/natty/libxcb-render-util0-dev
On Ubuntu 12.04 icccm1 is replaced by icccm4 and xcb-render-util can be installed automatically:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-glx0-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-glx0-dev libxcb-xinerama0-dev
On Fedora, the following packages are required:
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index e1fb63fbc4..208170de37 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -175,7 +175,11 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
{
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
+#if defined(QT_OPENGL_ES_2)
+ m_format.setRenderableType(QSurfaceFormat::OpenGLES);
+#else
m_format.setRenderableType(QSurfaceFormat::OpenGL);
+#endif
if (m_format.renderableType() != QSurfaceFormat::OpenGL && m_format.renderableType() != QSurfaceFormat::OpenGLES)
return;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index e28d84cf92..f16bebb758 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -60,6 +60,7 @@
#include <xcb/shm.h>
#include <xcb/sync.h>
#include <xcb/xfixes.h>
+#include <xcb/xinerama.h>
#ifdef XCB_USE_XLIB
#include <X11/Xlib.h>
@@ -386,6 +387,7 @@ void QXcbConnection::initializeScreens()
xcb_screen_t *xcbScreen = it.data;
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop);
+ QList<QPlatformScreen *> siblings;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
@@ -429,7 +431,6 @@ void QXcbConnection::initializeScreens()
qWarning("failed to get the primary output of the screen");
free(error);
} else {
- QList<QPlatformScreen *> siblings;
for (int i = 0; i < outputCount; i++) {
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
xcb_randr_get_output_info_reply(xcb_connection(),
@@ -471,12 +472,30 @@ void QXcbConnection::initializeScreens()
}
}
}
- virtualDesktop->setScreens(siblings);
}
}
}
+ } else if (has_xinerama_extension) {
+ // Xinerama is available
+ xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(m_connection);
+ xcb_xinerama_query_screens_reply_t *screens = xcb_xinerama_query_screens_reply(m_connection,
+ cookie,
+ Q_NULLPTR);
+ if (screens) {
+ xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens);
+ while (it.rem) {
+ xcb_xinerama_screen_info_t *screen_info = it.data;
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop,
+ XCB_NONE, Q_NULLPTR,
+ screen_info, it.index);
+ siblings << screen;
+ m_screens << screen;
+ xcb_xinerama_screen_info_next(&it);
+ }
+ free(screens);
+ }
}
- if (virtualDesktop->screens().isEmpty()) {
+ if (siblings.isEmpty()) {
// If there are no XRandR outputs or XRandR extension is missing,
// then create a fake/legacy screen.
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
@@ -486,8 +505,9 @@ void QXcbConnection::initializeScreens()
primaryScreen = screen;
primaryScreen->setPrimary(true);
}
- virtualDesktop->addScreen(screen);
+ siblings << screen;
}
+ virtualDesktop->setScreens(siblings);
xcb_screen_next(&it);
++xcbScreenNumber;
} // for each xcb screen
@@ -529,12 +549,14 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
, xfixes_first_event(0)
, xrandr_first_event(0)
, xkb_first_event(0)
+ , has_xinerama_extension(false)
, has_shape_extension(false)
, has_randr_extension(false)
, has_input_shape(false)
, has_xkb(false)
, m_buttons(0)
, m_focusWindow(0)
+ , m_mouseGrabber(0)
, m_clientLeader(0)
, m_systemTrayTracker(0)
, m_glIntegration(Q_NULLPTR)
@@ -583,7 +605,10 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
m_time = XCB_CURRENT_TIME;
m_netWmUserTime = XCB_CURRENT_TIME;
- initializeXRandr();
+ if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR"))
+ initializeXRandr();
+ if (!has_randr_extension)
+ initializeXinerama();
initializeXFixes();
initializeScreens();
@@ -1331,6 +1356,10 @@ void QXcbConnection::setFocusWindow(QXcbWindow *w)
{
m_focusWindow = w;
}
+void QXcbConnection::setMouseGrabber(QXcbWindow *w)
+{
+ m_mouseGrabber = w;
+}
void QXcbConnection::grabServer()
{
@@ -2090,6 +2119,22 @@ void QXcbConnection::initializeXRandr()
}
}
+void QXcbConnection::initializeXinerama()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xinerama_id);
+ if (!reply || !reply->present)
+ return;
+
+ xcb_generic_error_t *error = Q_NULLPTR;
+ xcb_xinerama_is_active_cookie_t xinerama_query_cookie = xcb_xinerama_is_active(m_connection);
+ xcb_xinerama_is_active_reply_t *xinerama_is_active = xcb_xinerama_is_active_reply(m_connection,
+ xinerama_query_cookie,
+ &error);
+ has_xinerama_extension = xinerama_is_active && !error && xinerama_is_active->state;
+ free(error);
+ free(xinerama_is_active);
+}
+
void QXcbConnection::initializeXShape()
{
const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id);
@@ -2177,7 +2222,9 @@ void QXcbConnection::initializeXKB()
bool QXcbConnection::xi2MouseEvents() const
{
static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
- return mouseViaXI2;
+ // Don't use XInput2 when Xinerama extension is enabled,
+ // because it causes problems with multi-monitor setup.
+ return mouseViaXI2 && !has_xinerama_extension;
}
#if defined(XCB_USE_XINPUT2)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 4acca7d374..6fa7532555 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -469,6 +469,8 @@ public:
QXcbWindow *focusWindow() const { return m_focusWindow; }
void setFocusWindow(QXcbWindow *);
+ QXcbWindow *mouseGrabber() const { return m_mouseGrabber; }
+ void setMouseGrabber(QXcbWindow *);
QByteArray startupId() const { return m_startupId; }
void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
@@ -515,6 +517,7 @@ private:
void initializeXFixes();
void initializeXRender();
void initializeXRandr();
+ void initializeXinerama();
void initializeXShape();
void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event);
@@ -643,6 +646,7 @@ private:
uint32_t xrandr_first_event;
uint32_t xkb_first_event;
+ bool has_xinerama_extension;
bool has_shape_extension;
bool has_randr_extension;
bool has_input_shape;
@@ -651,6 +655,7 @@ private:
Qt::MouseButtons m_buttons;
QXcbWindow *m_focusWindow;
+ QXcbWindow *m_mouseGrabber;
xcb_window_t m_clientLeader;
QByteArray m_startupId;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 1a123703a5..1b84de4834 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -274,7 +274,7 @@ void QXcbConnection::finalizeXInput2()
void QXcbConnection::xi2Select(xcb_window_t window)
{
- if (!m_xi2Enabled)
+ if (!m_xi2Enabled || window == rootWindow())
return;
Display *xDisplay = static_cast<Display *>(m_xlib_display);
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index d19ea241f1..9296a6d141 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -194,6 +194,8 @@ void QXcbDrag::startDrag()
setUseCompositing(current_virtual_desktop->compositingActive());
QBasicDrag::startDrag();
+ if (connection()->mouseGrabber() == Q_NULLPTR)
+ shapedPixmapWindow()->setMouseGrabEnabled(true);
}
void QXcbDrag::endDrag()
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 9b1b9fcbb0..caddd2b2a5 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -155,8 +155,15 @@ void QXcbVirtualDesktop::updateWorkArea()
}
}
+static inline QSizeF sizeInMillimeters(const QSize &size, const QDpi &dpi)
+{
+ return QSizeF(Q_MM_PER_INCH * size.width() / dpi.first,
+ Q_MM_PER_INCH * size.height() / dpi.second);
+}
+
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
+ const xcb_xinerama_screen_info_t *xineramaScreenInfo, int xineramaScreenIdx)
: QXcbObject(connection)
, m_virtualDesktop(virtualDesktop)
, m_output(outputId)
@@ -188,6 +195,14 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
updateRefreshRate(crtc->mode);
free(crtc);
}
+ } else if (xineramaScreenInfo) {
+ m_geometry = QRect(xineramaScreenInfo->x_org, xineramaScreenInfo->y_org,
+ xineramaScreenInfo->width, xineramaScreenInfo->height);
+ m_nativeGeometry = m_geometry;
+ m_availableGeometry = m_geometry & m_virtualDesktop->workArea();
+ m_sizeMillimeters = sizeInMillimeters(m_geometry.size(), virtualDpi());
+ if (xineramaScreenIdx > -1)
+ m_outputName += QLatin1Char('-') + QString::number(xineramaScreenIdx);
}
if (m_geometry.isEmpty()) {
@@ -536,11 +551,8 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
// It can be that physical size is unknown while virtual size
// is known (probably back-calculated from DPI and resolution),
// e.g. on VNC or with some hardware.
- if (m_sizeMillimeters.isEmpty()) {
- QDpi dpi = virtualDpi();
- m_sizeMillimeters = QSizeF(Q_MM_PER_INCH * xGeometry.width() / dpi.first,
- Q_MM_PER_INCH * xGeometry.width() / dpi.second);
- }
+ if (m_sizeMillimeters.isEmpty())
+ m_sizeMillimeters = sizeInMillimeters(xGeometry.size(), virtualDpi());
qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4);
m_pixelDensity = qRound(dpi/96);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 79620f40ec..dd7396aca2 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -40,6 +40,7 @@
#include <xcb/xcb.h>
#include <xcb/randr.h>
#include <xcb/xfixes.h>
+#include <xcb/xinerama.h>
#include "qxcbobject.h"
#include "qxcbscreen.h"
@@ -102,7 +103,8 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo,
+ const xcb_xinerama_screen_info_t *xineramaScreenInfo = Q_NULLPTR, int xineramaScreenIdx = -1);
~QXcbScreen();
QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index ae81674eca..f030252865 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -594,12 +594,16 @@ QXcbWindow::~QXcbWindow()
{
if (window()->type() != Qt::ForeignWindow)
destroy();
+ else if (connection()->mouseGrabber() == this)
+ connection()->setMouseGrabber(Q_NULLPTR);
}
void QXcbWindow::destroy()
{
if (connection()->focusWindow() == this)
doFocusOut();
+ if (connection()->mouseGrabber() == this)
+ connection()->setMouseGrabber(Q_NULLPTR);
if (m_syncCounter && m_usingSyncProtocol)
Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
@@ -847,6 +851,9 @@ void QXcbWindow::hide()
xcb_flush(xcb_connection());
+ if (connection()->mouseGrabber() == this)
+ connection()->setMouseGrabber(Q_NULLPTR);
+
m_mapped = false;
}
@@ -2367,6 +2374,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
QWindowSystemInterface::handleWindowStateChanged(window(), newState);
m_lastWindowStateEvent = newState;
m_windowState = newState;
+ if (m_windowState == Qt::WindowMinimized && connection()->mouseGrabber() == this)
+ connection()->setMouseGrabber(Q_NULLPTR);
}
return;
} else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
@@ -2421,9 +2430,15 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
bool QXcbWindow::setMouseGrabEnabled(bool grab)
{
+ if (!grab && connection()->mouseGrabber() == this)
+ connection()->setMouseGrabber(Q_NULLPTR);
#ifdef XCB_USE_XINPUT22
- if (connection()->xi2MouseEvents())
- return connection()->xi2SetMouseGrabEnabled(m_window, grab);
+ if (connection()->xi2MouseEvents()) {
+ bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab);
+ if (grab && result)
+ connection()->setMouseGrabber(this);
+ return result;
+ }
#endif
if (grab && !connection()->canGrab())
return false;
@@ -2442,6 +2457,8 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, NULL);
bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS);
free(reply);
+ if (result)
+ connection()->setMouseGrabber(this);
return result;
}
diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
index d0fe282b14..20481e4834 100644
--- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
+++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
@@ -1,7 +1,8 @@
#
# Statically compile in code for
# libxcb-fixes, libxcb-randr, libxcb-shm, libxcb-sync, libxcb-image,
-# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb
+# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb,
+# libxcb-xinerama
#
CONFIG += static
load(qt_helper_lib)
@@ -28,7 +29,8 @@ SOURCES += \
$$LIBXCB_DIR/sync.c \
$$LIBXCB_DIR/render.c \
$$LIBXCB_DIR/shape.c \
- $$LIBXCB_DIR/xkb.c
+ $$LIBXCB_DIR/xkb.c \
+ $$LIBXCB_DIR/xinerama.c
#
# xcb-util
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index 60eb8a02e3..302d87e007 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -92,7 +92,7 @@ contains(QT_CONFIG, xcb-qt) {
INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude
LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static
} else {
- LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms
+ LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama
!contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb
}