Implement XDnD in the xcb plugin
Ported most of the code to support dragging from qdnd_x11.cpp to xcb. Some features are still not working 100% correct, but it's becoming usable. Reviewed-by: Samuel
This commit is contained in:
parent
30b7c6512c
commit
c3f9de6296
@ -143,6 +143,7 @@ QDragManager::QDragManager()
|
|||||||
#ifdef Q_WS_X11
|
#ifdef Q_WS_X11
|
||||||
xdndMimeTransferedPixmapIndex = 0;
|
xdndMimeTransferedPixmapIndex = 0;
|
||||||
#endif
|
#endif
|
||||||
|
shapedPixmapWindow = 0;
|
||||||
|
|
||||||
possible_actions = Qt::IgnoreAction;
|
possible_actions = Qt::IgnoreAction;
|
||||||
|
|
||||||
@ -298,50 +299,9 @@ static const char *const default_pm[] = {
|
|||||||
|
|
||||||
static Qt::KeyboardModifiers oldstate;
|
static Qt::KeyboardModifiers oldstate;
|
||||||
|
|
||||||
class QShapedPixmapWindow : public QWindow {
|
|
||||||
QPixmap pixmap;
|
|
||||||
public:
|
|
||||||
QShapedPixmapWindow() :
|
|
||||||
QWindow(0)
|
|
||||||
{
|
|
||||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
|
|
||||||
// ### Should we set the surface type to raster?
|
|
||||||
// ### FIXME
|
|
||||||
// setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
void move(const QPoint &p) {
|
|
||||||
QRect g = geometry();
|
|
||||||
g.setTopLeft(p);
|
|
||||||
setGeometry(g);
|
|
||||||
}
|
|
||||||
void setPixmap(QPixmap pm)
|
|
||||||
{
|
|
||||||
pixmap = pm;
|
|
||||||
// ###
|
|
||||||
// if (!pixmap.mask().isNull()) {
|
|
||||||
// setMask(pixmap.mask());
|
|
||||||
// } else {
|
|
||||||
// clearMask();
|
|
||||||
// }
|
|
||||||
setGeometry(QRect(geometry().topLeft(), pm.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ### Get it painted again!
|
|
||||||
// void paintEvent(QPaintEvent*)
|
|
||||||
// {
|
|
||||||
// QPainter p(this);
|
|
||||||
// p.drawPixmap(0,0,pixmap);
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static QShapedPixmapWindow *qt_qws_dnd_deco = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void QDragManager::updatePixmap()
|
void QDragManager::updatePixmap()
|
||||||
{
|
{
|
||||||
if (qt_qws_dnd_deco) {
|
if (shapedPixmapWindow) {
|
||||||
QPixmap pm;
|
QPixmap pm;
|
||||||
QPoint pm_hot(default_pm_hotx,default_pm_hoty);
|
QPoint pm_hot(default_pm_hotx,default_pm_hoty);
|
||||||
if (object) {
|
if (object) {
|
||||||
@ -354,12 +314,12 @@ void QDragManager::updatePixmap()
|
|||||||
defaultPm = new QPixmap(default_pm);
|
defaultPm = new QPixmap(default_pm);
|
||||||
pm = *defaultPm;
|
pm = *defaultPm;
|
||||||
}
|
}
|
||||||
qt_qws_dnd_deco->setPixmap(pm);
|
shapedPixmapWindow->setPixmap(pm);
|
||||||
qt_qws_dnd_deco->move(QCursor::pos()-pm_hot);
|
shapedPixmapWindow->move(QCursor::pos()-pm_hot);
|
||||||
if (willDrop) {
|
if (willDrop) {
|
||||||
qt_qws_dnd_deco->show();
|
shapedPixmapWindow->show();
|
||||||
} else {
|
} else {
|
||||||
qt_qws_dnd_deco->hide();
|
shapedPixmapWindow->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,8 +328,8 @@ void QDragManager::updateCursor()
|
|||||||
{
|
{
|
||||||
#ifndef QT_NO_CURSOR
|
#ifndef QT_NO_CURSOR
|
||||||
if (willDrop) {
|
if (willDrop) {
|
||||||
if (qt_qws_dnd_deco)
|
if (shapedPixmapWindow)
|
||||||
qt_qws_dnd_deco->show();
|
shapedPixmapWindow->show();
|
||||||
if (currentActionForOverrideCursor != global_accepted_action) {
|
if (currentActionForOverrideCursor != global_accepted_action) {
|
||||||
QGuiApplication::changeOverrideCursor(QCursor(dragCursor(global_accepted_action), 0, 0));
|
QGuiApplication::changeOverrideCursor(QCursor(dragCursor(global_accepted_action), 0, 0));
|
||||||
currentActionForOverrideCursor = global_accepted_action;
|
currentActionForOverrideCursor = global_accepted_action;
|
||||||
@ -380,8 +340,8 @@ void QDragManager::updateCursor()
|
|||||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::ForbiddenCursor));
|
QGuiApplication::changeOverrideCursor(QCursor(Qt::ForbiddenCursor));
|
||||||
currentActionForOverrideCursor = Qt::IgnoreAction;
|
currentActionForOverrideCursor = Qt::IgnoreAction;
|
||||||
}
|
}
|
||||||
if (qt_qws_dnd_deco)
|
if (shapedPixmapWindow)
|
||||||
qt_qws_dnd_deco->hide();
|
shapedPixmapWindow->hide();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -468,8 +428,8 @@ Qt::DropAction QDragManager::drag(QDrag *o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object = o;
|
object = o;
|
||||||
if (!qt_qws_dnd_deco)
|
if (!shapedPixmapWindow)
|
||||||
qt_qws_dnd_deco = new QShapedPixmapWindow();
|
shapedPixmapWindow = new QShapedPixmapWindow();
|
||||||
oldstate = Qt::NoModifier; // #### Should use state that caused the drag
|
oldstate = Qt::NoModifier; // #### Should use state that caused the drag
|
||||||
// drag_mode = mode;
|
// drag_mode = mode;
|
||||||
|
|
||||||
@ -494,8 +454,8 @@ Qt::DropAction QDragManager::drag(QDrag *o)
|
|||||||
delete eventLoop;
|
delete eventLoop;
|
||||||
eventLoop = 0;
|
eventLoop = 0;
|
||||||
|
|
||||||
delete qt_qws_dnd_deco;
|
delete shapedPixmapWindow;
|
||||||
qt_qws_dnd_deco = 0;
|
shapedPixmapWindow = 0;
|
||||||
|
|
||||||
return global_accepted_action;
|
return global_accepted_action;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include "QtGui/qdrag.h"
|
#include "QtGui/qdrag.h"
|
||||||
#include "QtGui/qpixmap.h"
|
#include "QtGui/qpixmap.h"
|
||||||
#include "QtGui/qcursor.h"
|
#include "QtGui/qcursor.h"
|
||||||
|
#include "QtGui/qwindow.h"
|
||||||
#include "QtCore/qpoint.h"
|
#include "QtCore/qpoint.h"
|
||||||
#include "private/qobject_p.h"
|
#include "private/qobject_p.h"
|
||||||
|
|
||||||
@ -108,6 +109,44 @@ public:
|
|||||||
Qt::DropAction defaultDropAction;
|
Qt::DropAction defaultDropAction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QShapedPixmapWindow : public QWindow {
|
||||||
|
QPixmap pixmap;
|
||||||
|
public:
|
||||||
|
QShapedPixmapWindow() :
|
||||||
|
QWindow(0)
|
||||||
|
{
|
||||||
|
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
|
||||||
|
// ### Should we set the surface type to raster?
|
||||||
|
// ### FIXME
|
||||||
|
// setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(const QPoint &p) {
|
||||||
|
QRect g = geometry();
|
||||||
|
g.setTopLeft(p);
|
||||||
|
setGeometry(g);
|
||||||
|
}
|
||||||
|
void setPixmap(QPixmap pm)
|
||||||
|
{
|
||||||
|
pixmap = pm;
|
||||||
|
// ###
|
||||||
|
// if (!pixmap.mask().isNull()) {
|
||||||
|
// setMask(pixmap.mask());
|
||||||
|
// } else {
|
||||||
|
// clearMask();
|
||||||
|
// }
|
||||||
|
setGeometry(QRect(geometry().topLeft(), pm.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ### Get it painted again!
|
||||||
|
// void paintEvent(QPaintEvent*)
|
||||||
|
// {
|
||||||
|
// QPainter p(this);
|
||||||
|
// p.drawPixmap(0,0,pixmap);
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Q_GUI_EXPORT QDragManager : public QObject {
|
class Q_GUI_EXPORT QDragManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -159,6 +198,8 @@ public:
|
|||||||
// Shift/Ctrl handling, and final drop status
|
// Shift/Ctrl handling, and final drop status
|
||||||
Qt::DropAction global_accepted_action;
|
Qt::DropAction global_accepted_action;
|
||||||
|
|
||||||
|
QShapedPixmapWindow *shapedPixmapWindow;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMimeData *platformDropData;
|
QMimeData *platformDropData;
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
|
|||||||
*d = data;
|
*d = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_set_selection_owner(m_connection->xcb_connection(), newOwner, modeAtom, XCB_CURRENT_TIME);
|
xcb_set_selection_owner(m_connection->xcb_connection(), newOwner, modeAtom, m_connection->time());
|
||||||
|
|
||||||
if (getSelectionOwner(modeAtom) != newOwner) {
|
if (getSelectionOwner(modeAtom) != newOwner) {
|
||||||
qWarning("QClipboard::setData: Cannot set X11 selection owner");
|
qWarning("QClipboard::setData: Cannot set X11 selection owner");
|
||||||
@ -390,7 +390,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
|
|||||||
} else if (req->selection == m_connection->atom(QXcbAtom::CLIPBOARD)) {
|
} else if (req->selection == m_connection->atom(QXcbAtom::CLIPBOARD)) {
|
||||||
d = m_clientClipboard;
|
d = m_clientClipboard;
|
||||||
} else {
|
} else {
|
||||||
qWarning("QClipboard: Unknown selection '%lx'", (long)req->selection);
|
qWarning() << "QClipboard: Unknown selection" << m_connection->atomName(req->selection);
|
||||||
xcb_send_event(m_connection->xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
|
xcb_send_event(m_connection->xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -505,7 +505,7 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
|
|||||||
format = &dummy_format;
|
format = &dummy_format;
|
||||||
|
|
||||||
// Don't read anything, just get the size of the property data
|
// Don't read anything, just get the size of the property data
|
||||||
xcb_get_property_cookie_t cookie = xcb_get_property(m_connection->xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
|
xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(m_connection->xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
|
||||||
xcb_get_property_reply_t *reply = xcb_get_property_reply(m_connection->xcb_connection(), cookie, 0);
|
xcb_get_property_reply_t *reply = xcb_get_property_reply(m_connection->xcb_connection(), cookie, 0);
|
||||||
if (!reply || reply->type == XCB_NONE) {
|
if (!reply || reply->type == XCB_NONE) {
|
||||||
buffer->resize(0);
|
buffer->resize(0);
|
||||||
@ -546,7 +546,7 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
|
|||||||
while (bytes_left) {
|
while (bytes_left) {
|
||||||
// more to read...
|
// more to read...
|
||||||
|
|
||||||
xcb_get_property_cookie_t cookie = xcb_get_property(m_connection->xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4);
|
xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(m_connection->xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4));
|
||||||
reply = xcb_get_property_reply(m_connection->xcb_connection(), cookie, 0);
|
reply = xcb_get_property_reply(m_connection->xcb_connection(), cookie, 0);
|
||||||
if (!reply || reply->type == XCB_NONE) {
|
if (!reply || reply->type == XCB_NONE) {
|
||||||
free(reply);
|
free(reply);
|
||||||
|
@ -109,6 +109,8 @@ QXcbConnection::QXcbConnection(const char *displayName)
|
|||||||
|
|
||||||
initializeAllAtoms();
|
initializeAllAtoms();
|
||||||
|
|
||||||
|
m_time = XCB_CURRENT_TIME;
|
||||||
|
|
||||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
|
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
|
||||||
|
|
||||||
int screenNumber = 0;
|
int screenNumber = 0;
|
||||||
@ -450,7 +452,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|||||||
case XCB_UNMAP_NOTIFY:
|
case XCB_UNMAP_NOTIFY:
|
||||||
HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
|
HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
|
handleClientMessageEvent((xcb_client_message_event_t *)event);
|
||||||
case XCB_ENTER_NOTIFY:
|
case XCB_ENTER_NOTIFY:
|
||||||
HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
|
HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
|
||||||
case XCB_LEAVE_NOTIFY:
|
case XCB_LEAVE_NOTIFY:
|
||||||
@ -467,9 +469,16 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|||||||
m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
|
m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_SELECTION_REQUEST:
|
case XCB_SELECTION_REQUEST:
|
||||||
m_clipboard->handleSelectionRequest((xcb_selection_request_event_t *)event);
|
{
|
||||||
|
xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
|
||||||
|
if (sr->selection == atom(QXcbAtom::XdndSelection))
|
||||||
|
m_drag->handleSelectionRequest(sr);
|
||||||
|
else
|
||||||
|
m_clipboard->handleSelectionRequest(sr);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case XCB_SELECTION_CLEAR:
|
case XCB_SELECTION_CLEAR:
|
||||||
|
setTime(((xcb_selection_clear_event_t *)event)->time);
|
||||||
qDebug() << "XCB_SELECTION_CLEAR";
|
qDebug() << "XCB_SELECTION_CLEAR";
|
||||||
handled = false;
|
handled = false;
|
||||||
break;
|
break;
|
||||||
@ -477,6 +486,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|||||||
qDebug() << "XCB_SELECTION_NOTIFY";
|
qDebug() << "XCB_SELECTION_NOTIFY";
|
||||||
handled = false;
|
handled = false;
|
||||||
break;
|
break;
|
||||||
|
case XCB_PROPERTY_NOTIFY:
|
||||||
|
setTime(((xcb_property_notify_event_t *)event)->time);
|
||||||
|
// qDebug() << "XCB_PROPERTY_NOTIFY";
|
||||||
|
handled = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
handled = false;
|
handled = false;
|
||||||
break;
|
break;
|
||||||
@ -533,6 +547,25 @@ void QXcbConnection::processXcbEvents()
|
|||||||
xcb_flush(xcb_connection());
|
xcb_flush(xcb_connection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event)
|
||||||
|
{
|
||||||
|
if (event->format != 32)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event->type == atom(QXcbAtom::XdndStatus)) {
|
||||||
|
drag()->handleStatus(event, false);
|
||||||
|
} else if (event->type == atom(QXcbAtom::XdndFinished)) {
|
||||||
|
drag()->handleFinished(event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QXcbWindow *window = platformWindowFromId(event->window);
|
||||||
|
if (!window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window->handleClientMessageEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
xcb_generic_event_t *QXcbConnection::checkEvent(int type)
|
xcb_generic_event_t *QXcbConnection::checkEvent(int type)
|
||||||
{
|
{
|
||||||
while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection()))
|
while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection()))
|
||||||
|
@ -238,7 +238,7 @@ public:
|
|||||||
|
|
||||||
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
|
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
|
||||||
|
|
||||||
QList<QXcbScreen *> screens() const { return m_screens; }
|
const QList<QXcbScreen *> &screens() const { return m_screens; }
|
||||||
int primaryScreen() const { return m_primaryScreen; }
|
int primaryScreen() const { return m_primaryScreen; }
|
||||||
|
|
||||||
xcb_atom_t atom(QXcbAtom::Atom atom);
|
xcb_atom_t atom(QXcbAtom::Atom atom);
|
||||||
@ -290,6 +290,9 @@ public:
|
|||||||
typedef bool (*PeekFunc)(xcb_generic_event_t *);
|
typedef bool (*PeekFunc)(xcb_generic_event_t *);
|
||||||
void addPeekFunc(PeekFunc f);
|
void addPeekFunc(PeekFunc f);
|
||||||
|
|
||||||
|
inline xcb_timestamp_t time() const { return m_time; }
|
||||||
|
inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void processXcbEvents();
|
void processXcbEvents();
|
||||||
|
|
||||||
@ -299,6 +302,7 @@ private:
|
|||||||
#ifdef XCB_USE_DRI2
|
#ifdef XCB_USE_DRI2
|
||||||
void initializeDri2();
|
void initializeDri2();
|
||||||
#endif
|
#endif
|
||||||
|
void handleClientMessageEvent(const xcb_client_message_event_t *event);
|
||||||
|
|
||||||
xcb_connection_t *m_connection;
|
xcb_connection_t *m_connection;
|
||||||
const xcb_setup_t *m_setup;
|
const xcb_setup_t *m_setup;
|
||||||
@ -308,6 +312,8 @@ private:
|
|||||||
|
|
||||||
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
|
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
|
||||||
|
|
||||||
|
xcb_timestamp_t m_time;
|
||||||
|
|
||||||
QByteArray m_displayName;
|
QByteArray m_displayName;
|
||||||
|
|
||||||
QXcbKeyboard *m_keyboard;
|
QXcbKeyboard *m_keyboard;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@
|
|||||||
#include <qpoint.h>
|
#include <qpoint.h>
|
||||||
#include <qrect.h>
|
#include <qrect.h>
|
||||||
#include <qsharedpointer.h>
|
#include <qsharedpointer.h>
|
||||||
|
#include <qvector.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -57,8 +58,10 @@ class QWindow;
|
|||||||
class QXcbConnection;
|
class QXcbConnection;
|
||||||
class QXcbWindow;
|
class QXcbWindow;
|
||||||
class QDropData;
|
class QDropData;
|
||||||
|
class QXcbScreen;
|
||||||
|
class QDrag;
|
||||||
|
|
||||||
class QXcbDrag : public QPlatformDrag
|
class QXcbDrag : public QObject, public QPlatformDrag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QXcbDrag(QXcbConnection *c);
|
QXcbDrag(QXcbConnection *c);
|
||||||
@ -72,22 +75,32 @@ public:
|
|||||||
virtual void cancel();
|
virtual void cancel();
|
||||||
virtual void move(const QMouseEvent *me);
|
virtual void move(const QMouseEvent *me);
|
||||||
virtual void drop(const QMouseEvent *me);
|
virtual void drop(const QMouseEvent *me);
|
||||||
|
void endDrag();
|
||||||
|
|
||||||
void handleEnter(QWindow *window, const xcb_client_message_event_t *event);
|
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 handlePosition(QWindow *w, const xcb_client_message_event_t *event, bool passive);
|
||||||
void handleStatus(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 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 handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive);
|
||||||
|
|
||||||
|
void handleStatus(const xcb_client_message_event_t *event, bool passive);
|
||||||
|
void handleSelectionRequest(const xcb_selection_request_event_t *event);
|
||||||
|
void handleFinished(const xcb_client_message_event_t *event, bool passive);
|
||||||
|
|
||||||
bool dndEnable(QXcbWindow *win, bool on);
|
bool dndEnable(QXcbWindow *win, bool on);
|
||||||
|
|
||||||
QXcbConnection *connection() const { return m_connection; }
|
QXcbConnection *connection() const { return m_connection; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent* e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class QDropData;
|
friend class QDropData;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event, bool passive);
|
void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event, bool passive);
|
||||||
void handle_xdnd_status(QWindow *, const xcb_client_message_event_t *event, bool);
|
void handle_xdnd_status(const xcb_client_message_event_t *event, bool);
|
||||||
|
void send_leave();
|
||||||
|
|
||||||
Qt::DropAction toDropAction(xcb_atom_t atom) const;
|
Qt::DropAction toDropAction(xcb_atom_t atom) const;
|
||||||
xcb_atom_t toXdndAction(Qt::DropAction a) const;
|
xcb_atom_t toXdndAction(Qt::DropAction a) const;
|
||||||
@ -107,14 +120,40 @@ private:
|
|||||||
QList<xcb_atom_t> xdnd_types;
|
QList<xcb_atom_t> xdnd_types;
|
||||||
|
|
||||||
xcb_timestamp_t target_time;
|
xcb_timestamp_t target_time;
|
||||||
|
xcb_timestamp_t source_time;
|
||||||
Qt::DropAction last_target_accepted_action;
|
Qt::DropAction last_target_accepted_action;
|
||||||
|
|
||||||
// rectangle in which the answer will be the same
|
// rectangle in which the answer will be the same
|
||||||
QRect source_sameanswer;
|
QRect source_sameanswer;
|
||||||
bool waiting_for_status;
|
bool waiting_for_status;
|
||||||
|
|
||||||
|
// top-level window we sent position to last.
|
||||||
|
xcb_window_t current_target;
|
||||||
// window to send events to (always valid if current_target)
|
// window to send events to (always valid if current_target)
|
||||||
xcb_window_t current_proxy_target;
|
xcb_window_t current_proxy_target;
|
||||||
|
|
||||||
|
QXcbScreen *current_screen;
|
||||||
|
|
||||||
|
int heartbeat;
|
||||||
|
bool xdnd_dragging;
|
||||||
|
|
||||||
|
QVector<xcb_atom_t> drag_types;
|
||||||
|
|
||||||
|
struct Transaction
|
||||||
|
{
|
||||||
|
xcb_timestamp_t timestamp;
|
||||||
|
xcb_window_t target;
|
||||||
|
xcb_window_t proxy_target;
|
||||||
|
QWindow *targetWindow;
|
||||||
|
// QWidget *embedding_widget;
|
||||||
|
QDrag *object;
|
||||||
|
};
|
||||||
|
QList<Transaction> transactions;
|
||||||
|
|
||||||
|
int transaction_expiry_timer;
|
||||||
|
void restartDropExpiryTimer();
|
||||||
|
int findTransactionByWindow(xcb_window_t window);
|
||||||
|
int findTransactionByTime(xcb_timestamp_t timestamp);
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -944,6 +944,9 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
|
|||||||
if (event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
|
if (event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
|
||||||
if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
|
if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
|
||||||
QWindowSystemInterface::handleCloseEvent(window());
|
QWindowSystemInterface::handleCloseEvent(window());
|
||||||
|
} else if (event->data.data32[0] == atom(QXcbAtom::WM_TAKE_FOCUS)) {
|
||||||
|
connection()->setTime(event->data.data32[1]);
|
||||||
|
// ### handle take focus!
|
||||||
} else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
|
} else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
|
||||||
xcb_client_message_event_t reply = *event;
|
xcb_client_message_event_t reply = *event;
|
||||||
|
|
||||||
@ -953,6 +956,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
|
|||||||
xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
|
xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
|
||||||
xcb_flush(xcb_connection());
|
xcb_flush(xcb_connection());
|
||||||
} else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
|
} else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
|
||||||
|
connection()->setTime(event->data.data32[1]);
|
||||||
if (!m_hasReceivedSyncRequest) {
|
if (!m_hasReceivedSyncRequest) {
|
||||||
m_hasReceivedSyncRequest = true;
|
m_hasReceivedSyncRequest = true;
|
||||||
printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n");
|
printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n");
|
||||||
@ -1077,6 +1081,8 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
|
|||||||
|
|
||||||
void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global)
|
void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global)
|
||||||
{
|
{
|
||||||
|
connection()->setTime(time);
|
||||||
|
|
||||||
Qt::MouseButtons buttons = translateMouseButtons(state);
|
Qt::MouseButtons buttons = translateMouseButtons(state);
|
||||||
Qt::MouseButton button = translateMouseButton(detail);
|
Qt::MouseButton button = translateMouseButton(detail);
|
||||||
|
|
||||||
@ -1087,6 +1093,8 @@ void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_times
|
|||||||
|
|
||||||
void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
|
void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
|
||||||
{
|
{
|
||||||
|
connection()->setTime(event->time);
|
||||||
|
|
||||||
if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
|
if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
|
||||||
|| event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
|| event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
||||||
|| event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL)
|
|| event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL)
|
||||||
@ -1099,6 +1107,8 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
|
|||||||
|
|
||||||
void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
|
void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
|
||||||
{
|
{
|
||||||
|
connection()->setTime(event->time);
|
||||||
|
|
||||||
if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
|
if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
|
||||||
|| event->detail == XCB_NOTIFY_DETAIL_INFERIOR)
|
|| event->detail == XCB_NOTIFY_DETAIL_INFERIOR)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user