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/README4
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp18
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp55
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h6
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp438
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h45
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp7
-rw-r--r--src/plugins/platforms/xcb/xcb.pro2
17 files changed, 320 insertions, 332 deletions
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index ab802ced27..17e8bb53eb 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -1,6 +1,6 @@
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
+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
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
+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
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
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index f8d35ed4da..63ce73993f 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -74,7 +74,7 @@ public:
break;
default:
- qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode");
+ qWarning("QXcbClipboardMime: Internal error: Unsupported clipboard mode");
break;
}
}
@@ -209,7 +209,7 @@ QXcbClipboard::~QXcbClipboard()
// waiting until the clipboard manager fetches the content.
if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) {
- qWarning("QClipboard: Unable to receive an event from the "
+ qWarning("QXcbClipboard: Unable to receive an event from the "
"clipboard manager in a reasonable time");
}
}
@@ -292,7 +292,7 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
xcb_set_selection_owner(xcb_connection(), newOwner, modeAtom, connection()->time());
if (getSelectionOwner(modeAtom) != newOwner) {
- qWarning("QClipboard::setData: Cannot set X11 selection owner");
+ qWarning("QXcbClipboard::setData: Cannot set X11 selection owner");
}
emitChanged(mode);
@@ -403,7 +403,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment);
- qWarning() << "not implemented INCR just YET!";
+ qWarning("QXcbClipboard: INCR is unimplemented");
return property;
}
@@ -445,7 +445,7 @@ void QXcbClipboard::handleSelectionClearRequest(xcb_selection_clear_event_t *eve
void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
{
if (requestor() && req->requestor == requestor()) {
- qDebug() << "This should be caught before";
+ qWarning("QXcbClipboard: Selection request should be caught before");
return;
}
@@ -460,7 +460,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
QMimeData *d;
QClipboard::Mode mode = modeForAtom(req->selection);
if (mode > QClipboard::Selection) {
- qWarning() << "QClipboard: Unknown selection" << connection()->atomName(req->selection);
+ qWarning() << "QXcbClipboard: Unknown selection" << connection()->atomName(req->selection);
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
return;
}
@@ -468,14 +468,14 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
d = m_clientClipboard[mode];
if (!d) {
- qWarning("QClipboard: Cannot transfer data, no data available");
+ qWarning("QXcbClipboard: Cannot transfer data, no data available");
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
return;
}
if (m_timestamp[mode] == XCB_CURRENT_TIME // we don't own the selection anymore
|| (req->time != XCB_CURRENT_TIME && req->time < m_timestamp[mode])) {
- qDebug("QClipboard: SelectionRequest too old");
+ qWarning("QXcbClipboard: SelectionRequest too old");
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
return;
}
@@ -530,7 +530,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
property, XCB_ATOM_INTEGER, 32, 1, &m_timestamp[mode]);
ret = property;
} else {
- qWarning("QClipboard: Invalid data timestamp");
+ qWarning("QXcbClipboard: Invalid data timestamp");
}
} else if (target == xa_targets) {
ret = sendTargetsSelection(d, req->requestor, property);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index fdc2c76fea..367b24da9d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -109,6 +109,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
, m_has_support_for_dri2(false)
#endif
, xfixes_first_event(0)
+ , has_shape_extension(false)
+ , has_input_shape(false)
{
m_primaryScreen = 0;
@@ -133,7 +135,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
#endif //XCB_USE_XLIB
if (!m_connection || xcb_connection_has_error(m_connection))
- qFatal("Could not connect to display %s", m_displayName.constData());
+ qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData());
m_reader = new QXcbEventReader(this);
#ifdef XCB_POLL_FOR_QUEUED_EVENT
@@ -175,6 +177,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
#ifdef XCB_USE_XINPUT2_MAEMO
initializeXInput2();
#endif
+ initializeXShape();
m_wmSupport.reset(new QXcbWMSupport(this));
m_keyboard = new QXcbKeyboard(this);
@@ -191,7 +194,9 @@ QXcbConnection::~QXcbConnection()
{
delete m_clipboard;
- qDeleteAll(m_screens);
+ // Delete screens in reverse order to avoid crash in case of multiple screens
+ while (!m_screens.isEmpty())
+ delete m_screens.takeLast();
#ifdef XCB_USE_XINPUT2_MAEMO
finalizeXInput2();
@@ -250,7 +255,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
#ifdef XCB_EVENT_DEBUG
#define PRINT_XCB_EVENT(ev) \
case ev: \
- qDebug("%s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \
+ qDebug("QXcbConnection: %s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \
break;
switch (event->response_type & ~0x80) {
@@ -287,7 +292,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
default:
- qDebug("%s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
+ qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
}
#else
Q_UNUSED(message);
@@ -460,7 +465,7 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
- qDebug("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+ qWarning("QXcbConnection: XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
int(error->error_code), xcb_errors[clamped_error_code],
int(error->sequence), int(error->resource_id),
int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
@@ -552,7 +557,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
break;
case XCB_SELECTION_NOTIFY:
setTime(((xcb_selection_notify_event_t *)event)->time);
- qDebug() << "XCB_SELECTION_NOTIFY";
handled = false;
break;
case XCB_PROPERTY_NOTIFY:
@@ -714,9 +718,9 @@ void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *
return;
if (event->type == atom(QXcbAtom::XdndStatus)) {
- drag()->handleStatus(event, false);
+ drag()->handleStatus(event);
} else if (event->type == atom(QXcbAtom::XdndFinished)) {
- drag()->handleFinished(event, false);
+ drag()->handleFinished(event);
}
QXcbWindow *window = platformWindowFromId(event->window);
@@ -1024,7 +1028,7 @@ void QXcbConnection::initializeXFixes()
xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
xfixes_query_cookie, &error);
if (!xfixes_query || error || xfixes_query->major_version < 2) {
- qWarning("Failed to initialize XFixes");
+ qWarning("QXcbConnection: Failed to initialize XFixes");
free(error);
xfixes_first_event = 0;
}
@@ -1041,13 +1045,32 @@ void QXcbConnection::initializeXRender()
xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
xrender_query_cookie, &error);
if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
- qWarning("Failed to initialize XRender");
+ qWarning("QXcbConnection: Failed to initialize XRender");
free(error);
}
free(xrender_query);
#endif
}
+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;
+ xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection);
+ xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection,
+ cookie, NULL);
+ 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;
+ }
+ free(shape_query);
+}
+
#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
@@ -1066,7 +1089,7 @@ void QXcbConnection::initializeDri2()
connect_cookie, NULL);
if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
- qDebug() << "Failed to connect to dri2";
+ qWarning("QXcbConnection: Failed to connect to DRI2");
return;
}
@@ -1076,14 +1099,14 @@ void QXcbConnection::initializeDri2()
int fd = open(m_dri2_device_name.constData(), O_RDWR);
if (fd < 0) {
- qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
+ qWarning() << "QXcbConnection: Couldn't open DRI2 device" << m_dri2_device_name;
m_dri2_device_name = QByteArray();
return;
}
drm_magic_t magic;
if (drmGetMagic(fd, &magic)) {
- qDebug() << "Failed to get drmMagic";
+ qWarning("QXcbConnection: Failed to get drmMagic");
return;
}
@@ -1092,7 +1115,7 @@ void QXcbConnection::initializeDri2()
xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
authenticate_cookie, NULL);
if (authenticate == NULL || !authenticate->authenticated) {
- qWarning("DRI2: failed to authenticate");
+ qWarning("QXcbConnection: DRI2: failed to authenticate");
free(authenticate);
return;
}
@@ -1101,14 +1124,14 @@ void QXcbConnection::initializeDri2()
EGLDisplay display = eglGetDRMDisplayMESA(fd);
if (!display) {
- qWarning("failed to create display");
+ qWarning("QXcbConnection: Failed to create EGL display using DRI2");
return;
}
m_egl_display = display;
EGLint major,minor;
if (!eglInitialize(display, &major, &minor)) {
- qWarning("failed to initialize display");
+ qWarning("QXcbConnection: Failed to initialize EGL display using DRI2");
return;
}
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 7beb41bdd7..34943bfdef 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -354,6 +354,8 @@ public:
inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; }
bool hasXFixes() const { return xfixes_first_event > 0; }
+ bool hasXShape() const { return has_shape_extension; }
+ bool hasInputShape() const { return has_input_shape; }
private slots:
void processXcbEvents();
@@ -363,6 +365,7 @@ private:
void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
void initializeXFixes();
void initializeXRender();
+ void initializeXShape();
#ifdef XCB_USE_DRI2
void initializeDri2();
#endif
@@ -429,6 +432,9 @@ private:
QVector<PeekFunc> m_peekFuncs;
uint32_t xfixes_first_event;
+
+ bool has_shape_extension;
+ bool has_input_shape;
};
#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index ed7c22b1e6..7e1b66829a 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -261,7 +261,7 @@ static const char * const cursorNames[] = {
};
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
- : QXcbObject(conn), QPlatformCursor(screen), m_screen(screen)
+ : QXcbObject(conn), m_screen(screen)
{
if (cursorCount++)
return;
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index e928fe2d0a..3aeaaba2d8 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -52,6 +52,12 @@
#include <qevent.h>
#include <qguiapplication.h>
#include <qrect.h>
+#include <qpainter.h>
+
+#include <QtGui/QWindowSystemInterface>
+
+#include <QtPlatformSupport/private/qshapedpixmapdndwindow_p.h>
+#include <QtPlatformSupport/private/qsimpledrag_p.h>
QT_BEGIN_NAMESPACE
@@ -109,12 +115,11 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
return proxy;
}
-
-class QDropData : public QXcbMime
+class QXcbDropData : public QXcbMime
{
public:
- QDropData(QXcbDrag *d);
- ~QDropData();
+ QXcbDropData(QXcbDrag *d);
+ ~QXcbDropData();
protected:
bool hasFormat_sys(const QString &mimeType) const;
@@ -127,10 +132,9 @@ protected:
};
-QXcbDrag::QXcbDrag(QXcbConnection *c)
- : QXcbObject(c)
+QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)
{
- dropData = new QDropData(this);
+ dropData = new QXcbDropData(this);
init();
heartbeat = -1;
@@ -147,13 +151,13 @@ void QXcbDrag::init()
{
currentWindow.clear();
+ accepted_drop_action = Qt::IgnoreAction;
+
xdnd_dragsource = XCB_NONE;
- last_target_accepted_action = Qt::IgnoreAction;
waiting_for_status = false;
current_target = XCB_NONE;
current_proxy_target = XCB_NONE;
- xdnd_dragging = false;
source_time = XCB_CURRENT_TIME;
target_time = XCB_CURRENT_TIME;
@@ -169,16 +173,17 @@ QMimeData *QXcbDrag::platformDropData()
void QXcbDrag::startDrag()
{
+ // #fixme enableEventFilter();
+
init();
heartbeat = startTimer(200);
- xdnd_dragging = true;
+
xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(),
atom(QXcbAtom::XdndSelection), connection()->time());
- QDragManager *manager = QDragManager::self();
- QStringList fmts = QXcbMime::formatsHelper(manager->dropData());
+ QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
for (int j = 0; j < atoms.size(); ++j) {
@@ -190,23 +195,16 @@ void QXcbDrag::startDrag()
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(),
atom(QXcbAtom::XdndTypelist),
XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());
-
- QPointF pos = QCursor::pos();
- QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- move(&me);
-
-// if (!QWidget::mouseGrabber())
-// manager->shapedPixmapWindow->grabMouse();
+ QBasicDrag::startDrag();
}
void QXcbDrag::endDrag()
{
- Q_ASSERT(heartbeat != -1);
- killTimer(heartbeat);
- heartbeat = -1;
-
- xdnd_dragging = false;
+ if (heartbeat != -1) {
+ killTimer(heartbeat);
+ heartbeat = -1;
+ }
+ QBasicDrag::endDrag();
}
static xcb_translate_coordinates_reply_t *
@@ -217,9 +215,29 @@ translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int
return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0);
}
+static
+bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType)
+{
+ bool interacts = true;
+ xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL);
+ if (reply) {
+ xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply);
+ if (rectangles) {
+ interacts = false;
+ const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply);
+ for (int i = 0; !interacts && i < nRectangles; ++i) {
+ interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
+ }
+ }
+ free(reply);
+ }
+
+ return interacts;
+}
+
xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md)
{
- if (w == QDragManager::self()->shapedPixmapWindow->handle()->winId())
+ if (w == shapedPixmapWindow()->handle()->winId())
return 0;
if (md) {
@@ -244,22 +262,12 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
bool isAware = reply && reply->type != XCB_NONE;
free(reply);
if (isAware) {
- xcb_xfixes_region_t region = xcb_generate_id(xcb_connection());
- xcb_xfixes_create_region_from_window(xcb_connection(), region, w, XCB_SHAPE_SK_BOUNDING);
- xcb_xfixes_fetch_region_reply_t *reply = xcb_xfixes_fetch_region_reply(xcb_connection(), xcb_xfixes_fetch_region(xcb_connection(), region), NULL);
- if (reply) {
- xcb_rectangle_t *rectangles = xcb_xfixes_fetch_region_rectangles(reply);
- if (rectangles) {
- windowContainsMouse = false;
- const int nRectangles = xcb_xfixes_fetch_region_rectangles_length(reply);
- for (int i = 0; !windowContainsMouse && i < nRectangles; ++i) {
- windowContainsMouse = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
- }
- }
- free(reply);
- }
- xcb_xfixes_destroy_region(xcb_connection(), region);
-
+ // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we
+ // need to check both here so that in the case one is set and the other is not we still get the correct result.
+ if (connection()->hasInputShape())
+ windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_INPUT);
+ if (windowContainsMouse && connection()->hasXShape())
+ windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_BOUNDING);
if (windowContainsMouse)
return w;
}
@@ -296,9 +304,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
void QXcbDrag::move(const QMouseEvent *me)
{
- DEBUG() << "QDragManager::move enter" << me->globalPos();
-
- // ###
+ QBasicDrag::move(me);
QPoint globalPos = me->globalPos();
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
@@ -337,15 +343,13 @@ void QXcbDrag::move(const QMouseEvent *me)
::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y());
if (!translate)
return;
+
xcb_window_t target = translate->child;
int lx = translate->dst_x;
int ly = translate->dst_y;
free (translate);
- if (target == rootwin) {
- // Ok.
- } else if (target) {
- //me
+ if (target && target != rootwin) {
xcb_window_t src = rootwin;
while (target != 0) {
DNDDEBUG << "checking target for XdndAware" << target << lx << ly;
@@ -376,7 +380,7 @@ void QXcbDrag::move(const QMouseEvent *me)
target = child;
}
- if (!target || target == QDragManager::self()->shapedPixmapWindow->handle()->winId()) {
+ if (!target || target == shapedPixmapWindow()->handle()->winId()) {
DNDDEBUG << "need to find real window";
target = findRealWindow(globalPos, rootwin, 6);
DNDDEBUG << "real window found" << target;
@@ -393,9 +397,6 @@ void QXcbDrag::move(const QMouseEvent *me)
target = rootwin;
}
- DNDDEBUG << "and the final target is " << target;
- DNDDEBUG << "the widget w is" << (w ? w->window() : 0);
-
xcb_window_t proxy_target = xdndProxy(connection(), target);
if (!proxy_target)
proxy_target = target;
@@ -414,7 +415,6 @@ void QXcbDrag::move(const QMouseEvent *me)
free(reply);
}
- DEBUG() << "target=" << target << "current_target=" << current_target;
if (target != current_target) {
if (current_target)
send_leave();
@@ -447,11 +447,10 @@ void QXcbDrag::move(const QMouseEvent *me)
waiting_for_status = false;
}
}
+
if (waiting_for_status)
return;
- QDragManager *m = QDragManager::self();
-
if (target) {
waiting_for_status = true;
@@ -465,28 +464,21 @@ void QXcbDrag::move(const QMouseEvent *me)
move.data.data32[1] = 0; // flags
move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();
move.data.data32[3] = connection()->time();
- move.data.data32[4] = toXdndAction(m->defaultAction(m->dragPrivate()->possible_actions, QGuiApplication::keyboardModifiers()));
+ move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers()));
DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;
source_time = connection()->time();
if (w)
- handle_xdnd_position(w->window(), &move, false);
+ handle_xdnd_position(w->window(), &move);
else
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
- } else {
- if (m->willDrop) {
- m->willDrop = false;
- }
}
- m->updateCursor();
- DEBUG() << "QDragManager::move leave";
}
-void QXcbDrag::drop(const QMouseEvent *)
+void QXcbDrag::drop(const QMouseEvent *event)
{
- endDrag();
-
+ QBasicDrag::drop(event);
if (!current_target)
return;
@@ -500,14 +492,13 @@ void QXcbDrag::drop(const QMouseEvent *)
drop.data.data32[2] = connection()->time();
drop.data.data32[3] = 0;
- drop.data.data32[4] = 0;
+ drop.data.data32[4] = currentDrag()->supportedActions();
QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);
if (w && (w->window()->windowType() == Qt::Desktop) /*&& !w->acceptDrops()*/)
w = 0;
- QDragManager *manager = QDragManager::self();
Transaction t = {
connection()->time(),
@@ -515,21 +506,22 @@ void QXcbDrag::drop(const QMouseEvent *)
current_proxy_target,
(w ? w->window() : 0),
// current_embedding_widget,
- manager->object
+ currentDrag()
};
transactions.append(t);
restartDropExpiryTimer();
- if (w)
- handleDrop(w->window(), &drop, false);
- else
+ if (w) {
+ handleDrop(w->window(), &drop);
+ } else {
xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
+ }
current_target = 0;
current_proxy_target = 0;
source_time = 0;
// current_embedding_widget = 0;
- manager->object = 0;
+ // #fixme resetDndState(false);
}
Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const
@@ -719,7 +711,7 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev
DEBUG() << " " << connection()->atomName(xdnd_types.at(i));
}
-void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e, bool passive)
+void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e)
{
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
Q_ASSERT(w);
@@ -727,11 +719,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
p -= geometry.topLeft();
- // ####
-// if (!passive && checkEmbedded(w, e))
-// return;
-
- if (!w || (/*!w->acceptDrops() &&*/ (w->windowType() == Qt::Desktop)))
+ if (!w || (w->windowType() == Qt::Desktop))
return;
if (e->data.data32[0] != xdnd_dragsource) {
@@ -739,12 +727,27 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
return;
}
+ currentPosition = p;
+ currentWindow = w;
+
// timestamp from the source
- if (e->data.data32[3] != XCB_NONE)
- target_time /*= X11->userTime*/ = e->data.data32[3];
+ if (e->data.data32[3] != XCB_NONE) {
+ target_time = e->data.data32[3];
+ }
- QDragManager *manager = QDragManager::self();
- QMimeData *dropData = manager->dropData();
+ QMimeData *dropData = 0;
+ Qt::DropActions supported_actions = Qt::IgnoreAction;
+ if (currentDrag()) {
+ dropData = currentDrag()->mimeData();
+ supported_actions = currentDrag()->supportedActions();
+ } else {
+ dropData = platformDropData();
+ supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
+ }
+
+ QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w,dropData,p,supported_actions);
+ QRect answerRect(p + geometry.topLeft(), QSize(1,1));
+ answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);
xcb_client_message_event_t response;
response.response_type = XCB_CLIENT_MESSAGE;
@@ -752,83 +755,33 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
response.format = 32;
response.type = atom(QXcbAtom::XdndStatus);
response.data.data32[0] = xcb_window(w);
- response.data.data32[1] = 0; // flags
+ response.data.data32[1] = qt_response.isAccepted(); // flags
response.data.data32[2] = 0; // x, y
response.data.data32[3] = 0; // w, h
- response.data.data32[4] = 0; // action
+ response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // action
- if (!passive) { // otherwise just reject
- QRect answerRect(p + geometry.topLeft(), QSize(1,1));
- if (manager->object) {
- manager->possible_actions = manager->dragPrivate()->possible_actions;
- } else {
- manager->possible_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
- }
- QDragMoveEvent me(p, manager->possible_actions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
-
- Qt::DropAction accepted_action = Qt::IgnoreAction;
-
- currentPosition = p;
-
- if (w != currentWindow.data()) {
- if (currentWindow) {
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(currentWindow.data(), &e);
- }
- currentWindow = w;
-
- last_target_accepted_action = Qt::IgnoreAction;
- QDragEnterEvent de(p, manager->possible_actions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- QGuiApplication::sendEvent(w, &de);
- if (de.isAccepted() && de.dropAction() != Qt::IgnoreAction)
- last_target_accepted_action = de.dropAction();
- }
- DEBUG() << "qt_handle_xdnd_position action=" << connection()->atomName(e->data.data32[4]);
+ if (answerRect.left() < 0)
+ answerRect.setLeft(0);
+ if (answerRect.right() > 4096)
+ answerRect.setRight(4096);
+ if (answerRect.top() < 0)
+ answerRect.setTop(0);
+ if (answerRect.bottom() > 4096)
+ answerRect.setBottom(4096);
+ if (answerRect.width() < 0)
+ answerRect.setWidth(0);
+ if (answerRect.height() < 0)
+ answerRect.setHeight(0);
- if (last_target_accepted_action != Qt::IgnoreAction) {
- me.setDropAction(last_target_accepted_action);
- me.accept();
- }
- QGuiApplication::sendEvent(w, &me);
- if (me.isAccepted()) {
- response.data.data32[1] = 1; // yes
- accepted_action = me.dropAction();
- last_target_accepted_action = accepted_action;
- } else {
- response.data.data32[0] = 0;
- last_target_accepted_action = Qt::IgnoreAction;
- }
- answerRect = me.answerRect().translated(geometry.topLeft()).intersected(geometry);
-
- if (answerRect.left() < 0)
- answerRect.setLeft(0);
- if (answerRect.right() > 4096)
- answerRect.setRight(4096);
- if (answerRect.top() < 0)
- answerRect.setTop(0);
- if (answerRect.bottom() > 4096)
- answerRect.setBottom(4096);
- if (answerRect.width() < 0)
- answerRect.setWidth(0);
- if (answerRect.height() < 0)
- answerRect.setHeight(0);
-
-// response.data.data32[2] = (answerRect.x() << 16) + answerRect.y();
-// response.data.data32[3] = (answerRect.width() << 16) + answerRect.height();
- response.data.data32[4] = toXdndAction(accepted_action);
- }
+ response.data.data32[4] = toXdndAction(qt_response.acceptedAction());
// reset
target_time = XCB_CURRENT_TIME;
- DEBUG() << "sending XdndStatus" << (xdnd_dragsource == connection()->clipboard()->owner()) << xdnd_dragsource
- << response.data.data32[1] << connection()->atomName(response.data.data32[4]);
if (xdnd_dragsource == connection()->clipboard()->owner())
- handle_xdnd_status(&response, passive);
+ handle_xdnd_status(&response);
else
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
XCB_EVENT_MASK_NO_EVENT, (const char *)&response));
@@ -850,7 +803,7 @@ namespace
};
}
-void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event, bool passive)
+void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event)
{
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
xcb_generic_event_t *nextEvent;
@@ -861,19 +814,28 @@ void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *eve
lastEvent = (xcb_client_message_event_t *)nextEvent;
}
- handle_xdnd_position(w, lastEvent, passive);
+ handle_xdnd_position(w, lastEvent);
if (lastEvent != event)
free(lastEvent);
}
-void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event, bool)
+void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleStatus");
+ waiting_for_status = false;
// ignore late status messages
if (event->data.data32[0] && event->data.data32[0] != current_proxy_target)
return;
- Qt::DropAction newAction = (event->data.data32[1] & 0x1) ? toDropAction(event->data.data32[4]) : Qt::IgnoreAction;
+ const bool dropPossible = event->data.data32[1];
+ setCanDrop(dropPossible);
+
+ if (dropPossible) {
+ accepted_drop_action = toDropAction(event->data.data32[4]);
+ updateCursor(accepted_drop_action);
+ } else {
+ updateCursor(Qt::IgnoreAction);
+ }
if ((event->data.data32[1] & 2) == 0) {
QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff);
@@ -882,18 +844,9 @@ void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event, bool)
} else {
source_sameanswer = QRect();
}
- QDragManager *manager = QDragManager::self();
- manager->willDrop = (event->data.data32[1] & 0x1);
- if (manager->global_accepted_action != newAction) {
- manager->global_accepted_action = newAction;
- manager->emitActionChanged(newAction);
- }
- DEBUG() << "willDrop=" << manager->willDrop << "action=" << newAction;
- manager->updateCursor();
- waiting_for_status = false;
}
-void QXcbDrag::handleStatus(const xcb_client_message_event_t *event, bool passive)
+void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
{
if (event->window != connection()->clipboard()->owner())
return;
@@ -907,13 +860,13 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event, bool passiv
lastEvent = (xcb_client_message_event_t *)nextEvent;
}
- handle_xdnd_status(lastEvent, passive);
+ handle_xdnd_status(lastEvent);
if (lastEvent != event)
free(lastEvent);
DEBUG("xdndHandleStatus end");
}
-void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event, bool /*passive*/)
+void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event)
{
DEBUG("xdnd leave");
if (!currentWindow || w != currentWindow.data())
@@ -931,8 +884,8 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event,
DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource);
}
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(currentWindow.data(), &e);
+ QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction);
+ updateAction(Qt::IgnoreAction);
xdnd_dragsource = 0;
xdnd_types.clear();
@@ -944,7 +897,6 @@ void QXcbDrag::send_leave()
if (!current_target)
return;
- QDragManager *manager = QDragManager::self();
xcb_client_message_event_t leave;
leave.response_type = XCB_CLIENT_MESSAGE;
@@ -963,24 +915,18 @@ void QXcbDrag::send_leave()
w = 0;
if (w)
- handleLeave(w->window(), (const xcb_client_message_event_t *)&leave, false);
+ handleLeave(w->window(), (const xcb_client_message_event_t *)&leave);
else
xcb_send_event(xcb_connection(), false,current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (const char *)&leave);
- // reset the drag manager state
- manager->willDrop = false;
- if (manager->global_accepted_action != Qt::IgnoreAction)
- manager->emitActionChanged(Qt::IgnoreAction);
- manager->global_accepted_action = Qt::IgnoreAction;
- manager->updateCursor();
current_target = 0;
current_proxy_target = 0;
source_time = XCB_CURRENT_TIME;
waiting_for_status = false;
}
-void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive)
+void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleDrop");
if (!currentWindow) {
@@ -988,16 +934,8 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo
return; // sanity
}
- // ###
-// if (!passive && checkEmbedded(currentWindow, xe)){
-// current_embedding_widget = 0;
-// xdnd_dragsource = 0;
-// currentWindow = 0;
-// return;
-// }
const uint32_t *l = event->data.data32;
- QDragManager *manager = QDragManager::self();
DEBUG("xdnd drop");
if (l[0] != xdnd_dragsource) {
@@ -1009,50 +947,39 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo
if (l[2] != 0)
target_time = /*X11->userTime =*/ l[2];
- if (!passive) {
- // this could be a same-application drop, just proxied due to
- // some XEMBEDding, so try to find the real QMimeData used
- // based on the timestamp for this drop.
- QMimeData *dropData = 0;
- // ###
-// int at = findXdndDropTransactionByTime(target_time);
-// if (at != -1)
-// dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
- // if we can't find it, then use the data in the drag manager
- if (!dropData)
- dropData = manager->dropData();
-
- // Drop coming from another app? Update keyboard modifiers.
-// if (!qt_xdnd_dragging) {
-// QApplicationPrivate::modifier_buttons = currentKeyboardModifiers();
-// }
-
- QDropEvent de(currentPosition, manager->possible_actions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- QGuiApplication::sendEvent(currentWindow.data(), &de);
- if (!de.isAccepted()) {
- // Ignore a failed drag
- manager->global_accepted_action = Qt::IgnoreAction;
- } else {
- manager->global_accepted_action = de.dropAction();
- }
- xcb_client_message_event_t finished;
- finished.response_type = XCB_CLIENT_MESSAGE;
- finished.window = xdnd_dragsource;
- finished.format = 32;
- finished.type = atom(QXcbAtom::XdndFinished);
- DNDDEBUG << "xdndHandleDrop"
- << "currentWindow" << currentWindow.data()
- << (currentWindow ? xcb_window(currentWindow.data()) : 0);
- finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
- finished.data.data32[1] = de.isAccepted() ? 1 : 0; // flags
- finished.data.data32[2] = toXdndAction(manager->global_accepted_action);
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
- XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
+ // this could be a same-application drop, just proxied due to
+ // some XEMBEDding, so try to find the real QMimeData used
+ // based on the timestamp for this drop.
+ Qt::DropActions supported_drop_actions(l[4]);
+ QMimeData *dropData = 0;
+ if (currentDrag()) {
+ dropData = currentDrag()->mimeData();
} else {
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(currentWindow.data(), &e);
+ dropData = platformDropData();
}
+
+ if (!dropData)
+ return;
+ // ###
+ // int at = findXdndDropTransactionByTime(target_time);
+ // if (at != -1)
+ // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
+ // if we can't find it, then use the data in the drag manager
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(currentWindow.data(),dropData,currentPosition,supported_drop_actions);
+ setExecutedDropAction(response.acceptedAction());
+
+ xcb_client_message_event_t finished;
+ finished.response_type = XCB_CLIENT_MESSAGE;
+ finished.window = xdnd_dragsource;
+ finished.format = 32;
+ finished.type = atom(QXcbAtom::XdndFinished);
+ finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
+ finished.data.data32[1] = response.isAccepted(); // flags
+ finished.data.data32[2] = toXdndAction(response.acceptedAction());
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+ XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
+
xdnd_dragsource = 0;
currentWindow.clear();
waiting_for_status = false;
@@ -1062,7 +989,7 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo
}
-void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool)
+void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleFinished");
if (event->window != connection()->clipboard()->owner())
@@ -1099,8 +1026,8 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool)
// current_target = 0;
// current_proxy_target = 0;
- if (t.object)
- t.object->deleteLater();
+ if (t.drag)
+ t.drag->deleteLater();
// current_target = target;
// current_proxy_target = proxy_target;
@@ -1126,7 +1053,7 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
// dnd within the same process, don't delete these
continue;
}
- t.object->deleteLater();
+ t.drag->deleteLater();
transactions.removeAt(i--);
}
@@ -1138,12 +1065,9 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
void QXcbDrag::cancel()
{
DEBUG("QXcbDrag::cancel");
- endDrag();
-
+ QBasicDrag::cancel();
if (current_target)
send_leave();
-
- current_target = 0;
}
@@ -1157,14 +1081,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
notify.property = XCB_NONE;
notify.time = event->time;
- QDragManager *manager = QDragManager::self();
- QDrag *currentObject = manager->object;
-
// which transaction do we use? (note: -2 means use current manager->object)
int at = -1;
// figure out which data the requestor is really interested in
- if (manager->object && event->time == source_time) {
+ if (currentDrag() && event->time == source_time) {
// requestor wants the current drag data
at = -2;
} else {
@@ -1188,20 +1109,18 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
// }
// }
}
+
+ QDrag *transactionDrag = 0;
if (at >= 0) {
restartDropExpiryTimer();
- // use the drag object from an XdndDrop tansaction
- manager->object = transactions.at(at).object;
- } else if (at != -2) {
- // no transaction found, we'll have to reject the request
- manager->object = 0;
+ transactionDrag = transactions.at(at).drag;
}
- if (manager->object) {
+ if (transactionDrag) {
xcb_atom_t atomFormat = event->target;
int dataFormat = 0;
QByteArray data;
- if (QXcbMime::mimeDataForAtom(connection(), event->target, manager->dragPrivate()->data,
+ if (QXcbMime::mimeDataForAtom(connection(), event->target, transactionDrag->mimeData(),
&data, &atomFormat, &dataFormat)) {
int dataSize = data.size() / (dataFormat / 8);
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, event->requestor, event->property,
@@ -1211,9 +1130,6 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
}
}
- // reset manager->object in case we modified it above
- manager->object = currentObject;
-
xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
}
@@ -1268,20 +1184,17 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
}
}
-
-
-
-QDropData::QDropData(QXcbDrag *d)
+QXcbDropData::QXcbDropData(QXcbDrag *d)
: QXcbMime(),
drag(d)
{
}
-QDropData::~QDropData()
+QXcbDropData::~QXcbDropData()
{
}
-QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const
+QVariant QXcbDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const
{
QByteArray mime = mimetype.toLatin1();
QVariant data = /*X11->motifdnd_active
@@ -1290,17 +1203,16 @@ QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type req
return data;
}
-QVariant QDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const
+QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const
{
QByteArray result;
- QDragManager *manager = QDragManager::self();
QXcbConnection *c = drag->connection();
QXcbWindow *xcb_window = c->platformWindowFromId(drag->xdnd_dragsource);
- if (xcb_window && manager->object && xcb_window->window()->windowType() != Qt::Desktop) {
- QDragPrivate *o = manager->dragPrivate();
- if (o->data->hasFormat(QLatin1String(format)))
- result = o->data->data(QLatin1String(format));
+ if (xcb_window && drag->currentDrag() && xcb_window->window()->windowType() != Qt::Desktop) {
+ QMimeData *data = drag->currentDrag()->mimeData();
+ if (data->hasFormat(QLatin1String(format)))
+ result = data->data(QLatin1String(format));
return result;
}
@@ -1320,12 +1232,12 @@ QVariant QDropData::xdndObtainData(const QByteArray &format, QVariant::Type requ
}
-bool QDropData::hasFormat_sys(const QString &format) const
+bool QXcbDropData::hasFormat_sys(const QString &format) const
{
return formats().contains(format);
}
-QStringList QDropData::formats_sys() const
+QStringList QXcbDropData::formats_sys() const
{
QStringList formats;
// if (X11->motifdnd_active) {
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index e32e630548..710a07a5a4 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -43,6 +43,7 @@
#define QXCBDRAG_H
#include <qplatformdrag_qpa.h>
+#include <QtPlatformSupport/private/qsimpledrag_p.h>
#include <qxcbobject.h>
#include <xcb/xcb.h>
#include <qlist.h>
@@ -51,17 +52,23 @@
#include <qsharedpointer.h>
#include <qvector.h>
+#include <qpixmap.h>
+#include <qbackingstore.h>
+
+#include <QtCore/QDebug>
+
QT_BEGIN_NAMESPACE
class QMouseEvent;
class QWindow;
class QXcbConnection;
class QXcbWindow;
-class QDropData;
+class QXcbDropData;
class QXcbScreen;
class QDrag;
+class QShapedPixmapWindow;
-class QXcbDrag : public QObject, public QXcbObject, public QPlatformDrag
+class QXcbDrag : public QXcbObject, public QBasicDrag
{
public:
QXcbDrag(QXcbConnection *c);
@@ -69,35 +76,36 @@ public:
virtual QMimeData *platformDropData();
-// virtual Qt::DropAction drag(QDrag *);
- virtual void startDrag();
- virtual void cancel();
- virtual void move(const QMouseEvent *me);
- virtual void drop(const QMouseEvent *me);
+ void startDrag();
+ void cancel();
+ void move(const QMouseEvent *me);
+ void drop(const QMouseEvent *me);
void endDrag();
void handleEnter(QWindow *window, const xcb_client_message_event_t *event);
- void handlePosition(QWindow *w, const xcb_client_message_event_t *event, bool passive);
- void handleLeave(QWindow *w, const xcb_client_message_event_t *event, bool /*passive*/);
- void handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive);
+ void handlePosition(QWindow *w, const xcb_client_message_event_t *event);
+ void handleLeave(QWindow *w, const xcb_client_message_event_t *event);
+ void handleDrop(QWindow *, const xcb_client_message_event_t *event);
- void handleStatus(const xcb_client_message_event_t *event, bool passive);
+ void handleStatus(const xcb_client_message_event_t *event);
void handleSelectionRequest(const xcb_selection_request_event_t *event);
- void handleFinished(const xcb_client_message_event_t *event, bool passive);
+ void handleFinished(const xcb_client_message_event_t *event);
bool dndEnable(QXcbWindow *win, bool on);
+ void updatePixmap();
+
protected:
void timerEvent(QTimerEvent* e);
private:
- friend class QDropData;
+ friend class QXcbDropData;
void init();
- void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event, bool passive);
- void handle_xdnd_status(const xcb_client_message_event_t *event, bool);
+ void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event);
+ void handle_xdnd_status(const xcb_client_message_event_t *event);
void send_leave();
Qt::DropAction toDropAction(xcb_atom_t atom) const;
@@ -106,7 +114,8 @@ private:
QWeakPointer<QWindow> currentWindow;
QPoint currentPosition;
- QDropData *dropData;
+ QXcbDropData *dropData;
+ Qt::DropAction accepted_drop_action;
QWindow *desktop_proxy;
@@ -118,7 +127,6 @@ private:
xcb_timestamp_t target_time;
xcb_timestamp_t source_time;
- Qt::DropAction last_target_accepted_action;
// rectangle in which the answer will be the same
QRect source_sameanswer;
@@ -132,7 +140,6 @@ private:
QXcbScreen *current_screen;
int heartbeat;
- bool xdnd_dragging;
QVector<xcb_atom_t> drag_types;
@@ -143,7 +150,7 @@ private:
xcb_window_t proxy_target;
QWindow *targetWindow;
// QWidget *embedding_widget;
- QDrag *object;
+ QDrag *drag;
};
QList<Transaction> transactions;
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 13ff8ab2a5..12979bfb68 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -201,7 +201,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
formatsCookie,
&error);
if (!formatsReply || error) {
- qWarning("createCursorXRender: query_pict_formats failed");
+ qWarning("qt_xcb_createCursorXRender: query_pict_formats failed");
free(formatsReply);
free(error);
return XCB_NONE;
@@ -209,7 +209,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply,
XCB_PICT_STANDARD_ARGB_32);
if (!fmt) {
- qWarning("createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
+ qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
free(formatsReply);
return XCB_NONE;
}
@@ -221,13 +221,13 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
XCB_IMAGE_ORDER_MSB_FIRST,
0, 0, 0);
if (!xi) {
- qWarning("createCursorXRender: xcb_image_create failed");
+ qWarning("qt_xcb_createCursorXRender: xcb_image_create failed");
free(formatsReply);
return XCB_NONE;
}
xi->data = (uint8_t *) malloc(xi->stride * h);
if (!xi->data) {
- qWarning("createCursorXRender: Failed to malloc() image data");
+ qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data");
xcb_image_destroy(xi);
free(formatsReply);
return XCB_NONE;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 98f69e9e16..fe33bd7153 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -101,7 +101,9 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
m_connections << new QXcbConnection(m_nativeInterface.data());
for (int i = 0; i < parameters.size() - 1; i += 2) {
- qDebug() << parameters.at(i) << parameters.at(i+1);
+#ifdef Q_XCB_DEBUG
+ qDebug() << "QXcbIntegration: Connecting to additional display: " << parameters.at(i) << parameters.at(i+1);
+#endif
QString display = parameters.at(i) + ':' + parameters.at(i+1);
m_connections << new QXcbConnection(m_nativeInterface.data(), display.toAscii().constData());
}
@@ -185,7 +187,7 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
#elif defined(XCB_USE_DRI2)
return new QDri2Context(context->format(), context->shareHandle());
#endif
- qWarning("Cannot create platform GL context, none of GLX, EGL, DRI2 is enabled");
+ qWarning("QXcbIntegration: Cannot create platform OpenGL context, none of GLX, EGL, or DRI2 are enabled");
return 0;
}
#endif
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index b682b87bc3..03156dc544 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -935,7 +935,7 @@ void QXcbKeyboard::setupModifiers()
xcb_get_modifier_mapping_reply_t *modMapReply =
xcb_get_modifier_mapping_reply(conn, modMapCookie, &error);
if (error) {
- qWarning("xcb keyboard: failed to get modifier mapping");
+ qWarning("QXcbKeyboard: failed to get modifier mapping");
free(error);
return;
}
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 406f9c24bd..f56072f9d7 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -137,7 +137,7 @@ QPlatformNativeInterface::EventFilter QXcbNativeInterface::setEventFilter(const
if (eventType == QByteArrayLiteral("xcb_generic_event_t"))
type = GenericEventFilter;
if (type == -1) {
- qWarning("%s: Attempt to set invalid event filter type '%s'.",
+ qWarning("QXcbNativeInterface: %s: Attempt to set invalid event filter type '%s'.",
Q_FUNC_INFO, eventType.constData());
return 0;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index c93b4863e1..8b66ef4603 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -55,6 +55,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
, m_screen(screen)
, m_number(number)
{
+#ifdef Q_XCB_DEBUG
qDebug();
qDebug("Information of screen %d:", screen->root);
qDebug(" width.........: %d", screen->width_in_pixels);
@@ -63,6 +64,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
qDebug(" white pixel...: %x", screen->white_pixel);
qDebug(" black pixel...: %x", screen->black_pixel);
qDebug();
+#endif
const quint32 mask = XCB_CW_EVENT_MASK;
const quint32 values[] = {
@@ -93,7 +95,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
atom(QXcbAtom::UTF8_STRING), 0, 1024), &error);
if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply));
+#ifdef Q_XCB_DEBUG
qDebug("Running window manager: %s", qPrintable(m_windowManagerName));
+#endif
} else if (error) {
connection->handleXcbError(error);
free(error);
@@ -233,6 +237,11 @@ QSizeF QXcbScreen::physicalSize() const
return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters);
}
+QPlatformCursor *QXcbScreen::cursor() const
+{
+ return m_cursor;
+}
+
int QXcbScreen::screenNumber() const
{
return m_number;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 870d4d5662..ac4ecb1c8d 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -68,6 +68,7 @@ public:
int depth() const;
QImage::Format format() const;
QSizeF physicalSize() const;
+ QPlatformCursor *cursor() const;
int screenNumber() const;
diff --git a/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp b/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp
index f9e388b662..8bd3aea259 100644
--- a/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp
+++ b/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp
@@ -581,7 +581,7 @@ QXcbSharedBufferManager::Buffer *QXcbSharedBufferManager::allocateBuffer(int wid
bool ok = buffer->buffer->create(buffer->width * buffer->height * buffer->bytesPerPixel,
QSharedMemory::ReadWrite);
if (!ok) {
- qWarning("SharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)",
+ qWarning("QXcbSharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)",
qPrintable(buffer->buffer->errorString()));
delete buffer;
return 0;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 067cb775c8..542d7ab69f 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -369,6 +369,14 @@ void QXcbWindow::destroy()
if (m_syncCounter && m_screen->syncRequestSupported())
Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
if (m_window) {
+ if (m_netWmUserTimeWindow) {
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
+ // Some window managers, like metacity, do XSelectInput on the _NET_WM_USER_TIME_WINDOW window,
+ // without trapping BadWindow (which crashes when the user time window is destroyed).
+ connection()->sync();
+ xcb_destroy_window(xcb_connection(), m_netWmUserTimeWindow);
+ m_netWmUserTimeWindow = XCB_NONE;
+ }
connection()->removeWindow(m_window);
Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
}
@@ -540,6 +548,8 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
+ updateNetWmUserTime(connection()->time());
+
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
xcb_flush(xcb_connection());
@@ -1168,10 +1178,31 @@ void QXcbWindow::propagateSizeHints()
void QXcbWindow::requestActivateWindow()
{
- if (m_mapped){
- updateNetWmUserTime(connection()->time());
+ if (!m_mapped)
+ return;
+
+ updateNetWmUserTime(connection()->time());
+
+ if (window()->isTopLevel()
+ && connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
+ xcb_client_message_event_t event;
+
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = m_window;
+ event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
+ event.data.data32[0] = 1;
+ event.data.data32[1] = connection()->time();
+ QWindow *focusWindow = QGuiApplication::focusWindow();
+ event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
+ } else {
Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()));
}
+
connection()->sync();
}
@@ -1252,18 +1283,18 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
m_syncValue.lo = event->data.data32[2];
m_syncValue.hi = event->data.data32[3];
} else {
- qWarning() << "unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]);
+ qWarning() << "QXcbWindow: Unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]);
}
} else if (event->type == atom(QXcbAtom::XdndEnter)) {
connection()->drag()->handleEnter(window(), event);
} else if (event->type == atom(QXcbAtom::XdndPosition)) {
- connection()->drag()->handlePosition(window(), event, false);
+ connection()->drag()->handlePosition(window(), event);
} else if (event->type == atom(QXcbAtom::XdndLeave)) {
- connection()->drag()->handleLeave(window(), event, false);
+ connection()->drag()->handleLeave(window(), event);
} else if (event->type == atom(QXcbAtom::XdndDrop)) {
- connection()->drag()->handleDrop(window(), event, false);
+ connection()->drag()->handleDrop(window(), event);
} else {
- qWarning() << "unhandled client message:" << connection()->atomName(event->type);
+ qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type);
}
}
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 114049f911..c9f4ca69dd 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -89,11 +89,6 @@ void QXcbWMSupport::updateNetWMAtoms()
free(reply);
} while (remaining > 0);
-
-// qDebug() << "======== updateNetWMAtoms";
-// for (int i = 0; i < net_wm_atoms.size(); ++i)
-// qDebug() << atomName(net_wm_atoms.at(i));
-// qDebug() << "======== updateNetWMAtoms";
}
// update the virtual roots array
@@ -130,10 +125,12 @@ void QXcbWMSupport::updateVirtualRoots()
free(reply);
} while (remaining > 0);
+#ifdef Q_XCB_DEBUG
qDebug() << "======== updateVirtualRoots";
for (int i = 0; i < net_virtual_roots.size(); ++i)
qDebug() << connection()->atomName(net_virtual_roots.at(i));
qDebug() << "======== updateVirtualRoots";
+#endif
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index 7bad2b4dad..d220766be0 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -94,7 +94,7 @@ contains(DEFINES, XCB_USE_DRI2) {
}
}
-LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes
+LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shape
DEFINES += $$QMAKE_DEFINES_XCB
LIBS += $$QMAKE_LIBS_XCB