Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
libqt5-qtbase.10740
xcb-use-XShape-for-DnD-when-compositing-manager...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xcb-use-XShape-for-DnD-when-compositing-manager-is-not-running.patch of Package libqt5-qtbase.10740
From e9121328866efa6ba3eb78a991fef785338fd55e Mon Sep 17 00:00:00 2001 From: Alexander Volkov <a.volkov@rusbitech.ru> Date: Mon, 13 Apr 2015 14:13:34 +0300 Subject: [PATCH] xcb: Use XShape for DnD when a compositing manager is not running Otherwise transparent areas of the drag'n'drop pixmap are painted with the black color. Task-number: QTBUG-45193 Change-Id: I55b7c7caababe13584fa1c7a52835f112e20f920 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> --- src/gui/kernel/qshapedpixmapdndwindow.cpp | 13 ++++++-- src/gui/kernel/qshapedpixmapdndwindow_p.h | 2 ++ src/gui/kernel/qsimpledrag.cpp | 3 +- src/gui/kernel/qsimpledrag_p.h | 4 +++ src/plugins/platforms/xcb/qxcbclipboard.cpp | 24 ++------------- src/plugins/platforms/xcb/qxcbconnection.cpp | 45 ++++++++++++++++++++++++++-- src/plugins/platforms/xcb/qxcbconnection.h | 4 +++ src/plugins/platforms/xcb/qxcbdrag.cpp | 3 ++ src/plugins/platforms/xcb/qxcbscreen.cpp | 28 +++++++++++++++++ src/plugins/platforms/xcb/qxcbscreen.h | 8 +++++ 10 files changed, 106 insertions(+), 28 deletions(-) diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp index 5736c41..d77b6dc 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow.cpp +++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp @@ -35,12 +35,16 @@ #include <QtGui/QPainter> #include <QtGui/QCursor> +#include <QtGui/QGuiApplication> +#include <QtGui/QPalette> +#include <QtGui/QBitmap> QT_BEGIN_NAMESPACE QShapedPixmapWindow::QShapedPixmapWindow(QScreen *screen) : QWindow(screen), - m_backingStore(0) + m_backingStore(0), + m_useCompositing(true) { QSurfaceFormat format; format.setAlphaBufferSize(8); @@ -68,7 +72,10 @@ void QShapedPixmapWindow::render() { QPainter p(device); - p.setCompositionMode(QPainter::CompositionMode_Source); + if (m_useCompositing) + p.setCompositionMode(QPainter::CompositionMode_Source); + else + p.fillRect(rect, QGuiApplication::palette().base()); p.drawPixmap(0, 0, m_pixmap); } @@ -79,6 +86,8 @@ void QShapedPixmapWindow::render() void QShapedPixmapWindow::setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; + if (!m_useCompositing) + setMask(m_pixmap.mask()); } void QShapedPixmapWindow::setHotspot(const QPoint &hotspot) diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h index 7536c09..3d7974f 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow_p.h +++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h @@ -60,6 +60,7 @@ public: void render(); + void setUseCompositing(bool on) { m_useCompositing = on; } void setPixmap(const QPixmap &pixmap); void setHotspot(const QPoint &hotspot); @@ -72,6 +73,7 @@ private: QBackingStore *m_backingStore; QPixmap m_pixmap; QPoint m_hotSpot; + bool m_useCompositing; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 6acac4c..9f38c9b 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -88,7 +88,7 @@ static QWindow* topLevelAt(const QPoint &pos) QBasicDrag::QBasicDrag() : m_restoreCursor(false), m_eventLoop(0), m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false), - m_drag(0), m_drag_icon_window(0) + m_drag(0), m_drag_icon_window(0), m_useCompositing(true) { } @@ -226,6 +226,7 @@ void QBasicDrag::recreateShapedPixmapWindow(QScreen *screen, const QPoint &pos) // when QDrag is used without a pixmap - QDrag::setPixmap() m_drag_icon_window = new QShapedPixmapWindow(screen); + m_drag_icon_window->setUseCompositing(m_useCompositing); m_drag_icon_window->setPixmap(m_drag->pixmap()); m_drag_icon_window->setHotspot(m_drag->hotSpot()); m_drag_icon_window->updateGeometry(pos); diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index 4c9edba..055136c 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -87,6 +87,9 @@ protected: bool canDrop() const { return m_can_drop; } void setCanDrop(bool c) { m_can_drop = c; } + bool useCompositing() const { return m_useCompositing; } + void setUseCompositing(bool on) { m_useCompositing = on; } + Qt::DropAction executedDropAction() const { return m_executed_drop_action; } void setExecutedDropAction(Qt::DropAction da) { m_executed_drop_action = da; } @@ -104,6 +107,7 @@ private: bool m_can_drop; QDrag *m_drag; QShapedPixmapWindow *m_drag_icon_window; + bool m_useCompositing; }; class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 248d1b4..8b75c13 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -275,22 +275,8 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) m_clientClipboard[QClipboard::Selection] = 0; m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME; m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME; + m_owner = connection()->getQtSelectionOwner(); - QXcbScreen *platformScreen = screen(); - - int x = 0, y = 0, w = 3, h = 3; - - m_owner = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - m_owner, // window id - platformScreen->screen()->root, // parent window id - x, y, w, h, - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - platformScreen->screen()->root_visual, // visual - 0, // value mask - 0)); // value list #ifndef QT_NO_DEBUG QByteArray ba("Qt clipboard window"); Q_XCB_CALL(xcb_change_property(xcb_connection(), @@ -353,13 +339,7 @@ void QXcbClipboard::incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepte xcb_window_t QXcbClipboard::getSelectionOwner(xcb_atom_t atom) const { - xcb_connection_t *c = xcb_connection(); - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom); - xcb_get_selection_owner_reply_t *reply; - reply = xcb_get_selection_owner_reply(c, cookie, 0); - xcb_window_t win = reply->owner; - free(reply); - return win; + return connection()->getSelectionOwner(atom); } xcb_atom_t QXcbClipboard::atomForMode(QClipboard::Mode mode) const diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 13d73c7..a20d957 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -449,6 +449,9 @@ void QXcbConnection::initializeScreens() ++xcbScreenNumber; } // for each xcb screen + foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) + virtualDesktop->subscribeToXFixesSelectionNotify(); + // If there's no randr extension, or there was some error above, or we found a // screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X), // but the dimensions are known anyway, and we don't already have any lingering @@ -507,6 +510,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_systemTrayTracker(0) , m_glIntegration(Q_NULLPTR) , m_xiGrab(false) + , m_qtSelectionOwner(0) { #ifdef XCB_USE_XLIB Display *dpy = XOpenDisplay(m_displayName.constData()); @@ -551,12 +555,12 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra m_netWmUserTime = XCB_CURRENT_TIME; initializeXRandr(); + initializeXFixes(); initializeScreens(); if (m_screens.isEmpty()) qFatal("QXcbConnection: no screens available"); - initializeXFixes(); initializeXRender(); m_xi2Enabled = false; #if defined(XCB_USE_XINPUT2) @@ -1139,10 +1143,14 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) if (!handled) { if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) { - setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp); + xcb_xfixes_selection_notify_event_t *notify_event = (xcb_xfixes_selection_notify_event_t *)event; + setTime(notify_event->timestamp); #ifndef QT_NO_CLIPBOARD - m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event); + m_clipboard->handleXFixesSelectionRequest(notify_event); #endif + foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) + virtualDesktop->handleXFixesSelectionNotify(notify_event); + handled = true; } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { updateScreens((xcb_randr_notify_event_t *)event); @@ -1371,6 +1379,37 @@ xcb_timestamp_t QXcbConnection::getTimestamp() return timestamp; } +xcb_window_t QXcbConnection::getSelectionOwner(xcb_atom_t atom) const +{ + xcb_connection_t *c = xcb_connection(); + xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom); + xcb_get_selection_owner_reply_t *reply; + reply = xcb_get_selection_owner_reply(c, cookie, 0); + xcb_window_t win = reply->owner; + free(reply); + return win; +} + +xcb_window_t QXcbConnection::getQtSelectionOwner() +{ + if (!m_qtSelectionOwner) { + xcb_screen_t *xcbScreen = primaryVirtualDesktop()->screen(); + int x = 0, y = 0, w = 3, h = 3; + m_qtSelectionOwner = xcb_generate_id(xcb_connection()); + Q_XCB_CALL(xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_qtSelectionOwner, // window id + xcbScreen->root, // parent window id + x, y, w, h, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + xcbScreen->root_visual, // visual + 0, // value mask + 0)); // value list + } + return m_qtSelectionOwner; +} + xcb_window_t QXcbConnection::rootWindow() { QXcbScreen *s = primaryScreen(); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index fb5b941..3c82170 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -460,6 +460,8 @@ public: bool threadedEventHandling() const { return m_reader->isRunning(); } xcb_timestamp_t getTimestamp(); + xcb_window_t getSelectionOwner(xcb_atom_t atom) const; + xcb_window_t getQtSelectionOwner(); void setButton(Qt::MouseButton button, bool down) { if (down) m_buttons |= button; else m_buttons &= ~button; } Qt::MouseButtons buttons() const { return m_buttons; } @@ -650,6 +652,8 @@ private: QXcbGlIntegration *m_glIntegration; bool m_xiGrab; + xcb_window_t m_qtSelectionOwner; + friend class QXcbEventReader; }; diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index f9c3aa7..d19ea24 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -191,6 +191,8 @@ 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()); + + setUseCompositing(current_virtual_desktop->compositingActive()); QBasicDrag::startDrag(); } @@ -316,6 +318,7 @@ void QXcbDrag::move(const QPoint &globalPos) QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen); if (virtualDesktop != current_virtual_desktop) { + setUseCompositing(virtualDesktop->compositingActive()); recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos); current_virtual_desktop = virtualDesktop; } else { diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 64645b9..0aa5810 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -54,6 +54,10 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t , m_number(number) , m_xSettings(Q_NULLPTR) { + QByteArray cmAtomName("_NET_WM_CM_S"); + cmAtomName += QByteArray::number(m_number); + m_net_wm_cm_atom = connection->internAtom(cmAtomName.constData()); + m_compositingActive = connection->getSelectionOwner(m_net_wm_cm_atom); } QXcbVirtualDesktop::~QXcbVirtualDesktop() @@ -79,6 +83,30 @@ QXcbXSettings *QXcbVirtualDesktop::xSettings() const return m_xSettings; } +bool QXcbVirtualDesktop::compositingActive() const +{ + if (connection()->hasXFixes()) + return m_compositingActive; + else + return connection()->getSelectionOwner(m_net_wm_cm_atom); +} + +void QXcbVirtualDesktop::handleXFixesSelectionNotify(xcb_xfixes_selection_notify_event_t *notify_event) +{ + if (notify_event->selection == m_net_wm_cm_atom) + m_compositingActive = notify_event->owner; +} + +void QXcbVirtualDesktop::subscribeToXFixesSelectionNotify() +{ + if (connection()->hasXFixes()) { + const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; + Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->getQtSelectionOwner(), m_net_wm_cm_atom, mask)); + } +} + QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, QString outputName) diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index d8d6360..51c92a4 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -39,6 +39,7 @@ #include <xcb/xcb.h> #include <xcb/randr.h> +#include <xcb/xfixes.h> #include "qxcbobject.h" #include "qxcbscreen.h" @@ -69,11 +70,18 @@ public: QXcbXSettings *xSettings() const; + bool compositingActive() const; + + void handleXFixesSelectionNotify(xcb_xfixes_selection_notify_event_t *notify_event); + void subscribeToXFixesSelectionNotify(); + private: xcb_screen_t *m_screen; int m_number; QXcbXSettings *m_xSettings; + xcb_atom_t m_net_wm_cm_atom; + bool m_compositingActive; }; class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen -- 2.6.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor