Fix highdpi drag-n-drop for X11
Task-number: QTBUG-46615 Change-Id: Iad548e62a580d6fbd15b7a826116a53ce23b4b8b Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>bb10
parent
ec462b245f
commit
3c12482df0
|
|
@ -55,6 +55,7 @@
|
|||
#include <private/qdnd_p.h>
|
||||
|
||||
#include <private/qshapedpixmapdndwindow_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -106,6 +107,12 @@ void QBasicDrag::disableEventFilter()
|
|||
qApp->removeEventFilter(this);
|
||||
}
|
||||
|
||||
|
||||
static inline QPoint getNativeMousePos(QEvent *e, QObject *o)
|
||||
{
|
||||
return QHighDpi::toNativePixels(static_cast<QMouseEvent *>(e)->globalPos(), qobject_cast<QWindow*>(o));
|
||||
}
|
||||
|
||||
bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
Q_UNUSED(o);
|
||||
|
|
@ -139,19 +146,21 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
|
|||
}
|
||||
|
||||
case QEvent::MouseMove:
|
||||
move(static_cast<QMouseEvent *>(e));
|
||||
{
|
||||
QPoint nativePosition = getNativeMousePos(e, o);
|
||||
move(nativePosition);
|
||||
return true; // Eat all mouse events
|
||||
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
disableEventFilter();
|
||||
if (canDrop()) {
|
||||
drop(static_cast<QMouseEvent *>(e));
|
||||
QPoint nativePosition = getNativeMousePos(e, o);
|
||||
drop(nativePosition);
|
||||
} else {
|
||||
cancel();
|
||||
}
|
||||
exitDndEventLoop();
|
||||
return true; // Eat all mouse events
|
||||
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::Wheel:
|
||||
|
|
@ -227,13 +236,18 @@ void QBasicDrag::cancel()
|
|||
m_drag_icon_window->setVisible(false);
|
||||
}
|
||||
|
||||
void QBasicDrag::move(const QMouseEvent *e)
|
||||
/*!
|
||||
Move the drag label to \a globalPos, which is
|
||||
interpreted in device independent coordinates. Typically called from reimplementations of move().
|
||||
*/
|
||||
|
||||
void QBasicDrag::moveShapedPixmapWindow(const QPoint &globalPos)
|
||||
{
|
||||
if (m_drag)
|
||||
m_drag_icon_window->updateGeometry(e->globalPos());
|
||||
m_drag_icon_window->updateGeometry(globalPos);
|
||||
}
|
||||
|
||||
void QBasicDrag::drop(const QMouseEvent *)
|
||||
void QBasicDrag::drop(const QPoint &)
|
||||
{
|
||||
disableEventFilter();
|
||||
restoreCursor();
|
||||
|
|
@ -330,14 +344,15 @@ void QSimpleDrag::cancel()
|
|||
}
|
||||
}
|
||||
|
||||
void QSimpleDrag::move(const QMouseEvent *me)
|
||||
void QSimpleDrag::move(const QPoint &globalPos)
|
||||
{
|
||||
QBasicDrag::move(me);
|
||||
QWindow *window = topLevelAt(me->globalPos());
|
||||
//### not high-DPI aware
|
||||
moveShapedPixmapWindow(globalPos);
|
||||
QWindow *window = topLevelAt(globalPos);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
const QPoint pos = me->globalPos() - window->geometry().topLeft();
|
||||
const QPoint pos = globalPos - window->geometry().topLeft();
|
||||
const QPlatformDragQtResponse qt_response =
|
||||
QWindowSystemInterface::handleDrag(window, drag()->mimeData(), pos, drag()->supportedActions());
|
||||
|
||||
|
|
@ -345,14 +360,16 @@ void QSimpleDrag::move(const QMouseEvent *me)
|
|||
setCanDrop(qt_response.isAccepted());
|
||||
}
|
||||
|
||||
void QSimpleDrag::drop(const QMouseEvent *me)
|
||||
void QSimpleDrag::drop(const QPoint &globalPos)
|
||||
{
|
||||
QBasicDrag::drop(me);
|
||||
QWindow *window = topLevelAt(me->globalPos());
|
||||
//### not high-DPI aware
|
||||
|
||||
QBasicDrag::drop(globalPos);
|
||||
QWindow *window = topLevelAt(globalPos);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
const QPoint pos = me->globalPos() - window->geometry().topLeft();
|
||||
const QPoint pos = globalPos - window->geometry().topLeft();
|
||||
const QPlatformDropQtResponse response =
|
||||
QWindowSystemInterface::handleDrop(window, drag()->mimeData(),pos, drag()->supportedActions());
|
||||
if (response.isAccepted()) {
|
||||
|
|
|
|||
|
|
@ -73,10 +73,12 @@ protected:
|
|||
|
||||
virtual void startDrag();
|
||||
virtual void cancel();
|
||||
virtual void move(const QMouseEvent *me);
|
||||
virtual void drop(const QMouseEvent *me);
|
||||
virtual void move(const QPoint &globalPos) = 0;
|
||||
virtual void drop(const QPoint &globalPos) = 0;
|
||||
virtual void endDrag();
|
||||
|
||||
|
||||
void moveShapedPixmapWindow(const QPoint &deviceIndependentPosition);
|
||||
QShapedPixmapWindow *shapedPixmapWindow() const { return m_drag_icon_window; }
|
||||
void updateCursor(Qt::DropAction action);
|
||||
|
||||
|
|
@ -111,8 +113,8 @@ public:
|
|||
protected:
|
||||
virtual void startDrag() Q_DECL_OVERRIDE;
|
||||
virtual void cancel() Q_DECL_OVERRIDE;
|
||||
virtual void move(const QMouseEvent *me) Q_DECL_OVERRIDE;
|
||||
virtual void drop(const QMouseEvent *me) Q_DECL_OVERRIDE;
|
||||
virtual void move(const QPoint &globalPos) Q_DECL_OVERRIDE;
|
||||
virtual void drop(const QPoint &globalPos) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
QWindow *m_current_window;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
#include <private/qshapedpixmapdndwindow_p.h>
|
||||
#include <private/qsimpledrag_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -71,6 +72,11 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
const int xdnd_version = 5;
|
||||
|
||||
static inline xcb_window_t xcb_window(QPlatformWindow *w)
|
||||
{
|
||||
return static_cast<QXcbWindow *>(w)->xcb_window();
|
||||
}
|
||||
|
||||
static inline xcb_window_t xcb_window(QWindow *w)
|
||||
{
|
||||
return static_cast<QXcbWindow *>(w->handle())->xcb_window();
|
||||
|
|
@ -296,14 +302,8 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
|
|||
return 0;
|
||||
}
|
||||
|
||||
void QXcbDrag::move(const QMouseEvent *me)
|
||||
void QXcbDrag::move(const QPoint &globalPos)
|
||||
{
|
||||
// The mouse event is in the coordinate system of the window that started the drag.
|
||||
// We do not know which window that was at this point, so we just use the device pixel ratio
|
||||
// of the QGuiApplication. This will break once we support screens with different DPR. Fixing
|
||||
// this properly requires some redesign of the drag and drop architecture.
|
||||
QBasicDrag::move(me);
|
||||
QPoint globalPos = me->globalPos();
|
||||
|
||||
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
|
||||
return;
|
||||
|
|
@ -317,6 +317,8 @@ void QXcbDrag::move(const QMouseEvent *me)
|
|||
}
|
||||
}
|
||||
|
||||
QBasicDrag::moveShapedPixmapWindow(QHighDpiScaling::mapPositionFromNative(globalPos, screen));
|
||||
|
||||
if (screen != current_screen) {
|
||||
// ### need to recreate the shaped pixmap window?
|
||||
// int screen = QCursor::x11Screen();
|
||||
|
|
@ -442,7 +444,7 @@ void QXcbDrag::move(const QMouseEvent *me)
|
|||
|
||||
DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
|
||||
if (w)
|
||||
handleEnter(w->window(), &enter);
|
||||
handleEnter(w, &enter);
|
||||
else if (target)
|
||||
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);
|
||||
waiting_for_status = false;
|
||||
|
|
@ -470,15 +472,15 @@ void QXcbDrag::move(const QMouseEvent *me)
|
|||
source_time = connection()->time();
|
||||
|
||||
if (w)
|
||||
handle_xdnd_position(w->window(), &move);
|
||||
handle_xdnd_position(w, &move);
|
||||
else
|
||||
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbDrag::drop(const QMouseEvent *event)
|
||||
void QXcbDrag::drop(const QPoint &globalPos)
|
||||
{
|
||||
QBasicDrag::drop(event);
|
||||
QBasicDrag::drop(globalPos);
|
||||
|
||||
if (!current_target)
|
||||
return;
|
||||
|
|
@ -504,7 +506,7 @@ void QXcbDrag::drop(const QMouseEvent *event)
|
|||
connection()->time(),
|
||||
current_target,
|
||||
current_proxy_target,
|
||||
(w ? w->window() : 0),
|
||||
w,
|
||||
// current_embeddig_widget,
|
||||
currentDrag(),
|
||||
QTime::currentTime()
|
||||
|
|
@ -517,7 +519,7 @@ void QXcbDrag::drop(const QMouseEvent *event)
|
|||
}
|
||||
|
||||
if (w) {
|
||||
handleDrop(w->window(), &drop);
|
||||
handleDrop(w, &drop);
|
||||
} else {
|
||||
xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
|
||||
}
|
||||
|
|
@ -663,7 +665,7 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe)
|
|||
#endif
|
||||
|
||||
|
||||
void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *event)
|
||||
void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event)
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
DEBUG() << "handleEnter" << window;
|
||||
|
|
@ -704,14 +706,14 @@ 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)
|
||||
void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e)
|
||||
{
|
||||
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
|
||||
Q_ASSERT(w);
|
||||
QRect geometry = w->geometry();
|
||||
p -= geometry.topLeft();
|
||||
|
||||
if (!w || (w->type() == Qt::Desktop))
|
||||
if (!w || !w->window() || (w->window()->type() == Qt::Desktop))
|
||||
return;
|
||||
|
||||
if (e->data.data32[0] != xdnd_dragsource) {
|
||||
|
|
@ -720,7 +722,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
|
|||
}
|
||||
|
||||
currentPosition = p;
|
||||
currentWindow = w;
|
||||
currentWindow = w->window();
|
||||
|
||||
// timestamp from the source
|
||||
if (e->data.data32[3] != XCB_NONE) {
|
||||
|
|
@ -737,7 +739,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
|
|||
supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
|
||||
}
|
||||
|
||||
QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w,dropData,p,supported_actions);
|
||||
QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w->window(),dropData,p,supported_actions);
|
||||
QRect answerRect(p + geometry.topLeft(), QSize(1,1));
|
||||
answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);
|
||||
|
||||
|
|
@ -793,7 +795,7 @@ namespace
|
|||
};
|
||||
}
|
||||
|
||||
void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event)
|
||||
void QXcbDrag::handlePosition(QPlatformWindow * 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;
|
||||
|
|
@ -856,10 +858,10 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
|
|||
DEBUG("xdndHandleStatus end");
|
||||
}
|
||||
|
||||
void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event)
|
||||
void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event)
|
||||
{
|
||||
DEBUG("xdnd leave");
|
||||
if (!currentWindow || w != currentWindow.data())
|
||||
if (!currentWindow || w != currentWindow.data()->handle())
|
||||
return; // sanity
|
||||
|
||||
// ###
|
||||
|
|
@ -874,7 +876,7 @@ 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);
|
||||
}
|
||||
|
||||
QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction);
|
||||
QWindowSystemInterface::handleDrag(w->window(),0,QPoint(),Qt::IgnoreAction);
|
||||
|
||||
xdnd_dragsource = 0;
|
||||
xdnd_types.clear();
|
||||
|
|
@ -904,7 +906,7 @@ void QXcbDrag::send_leave()
|
|||
w = 0;
|
||||
|
||||
if (w)
|
||||
handleLeave(w->window(), (const xcb_client_message_event_t *)&leave);
|
||||
handleLeave(w, (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);
|
||||
|
|
@ -915,7 +917,7 @@ void QXcbDrag::send_leave()
|
|||
waiting_for_status = false;
|
||||
}
|
||||
|
||||
void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event)
|
||||
void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event)
|
||||
{
|
||||
DEBUG("xdndHandleDrop");
|
||||
if (!currentWindow) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
#ifndef QT_NO_DRAGANDDROP
|
||||
|
||||
class QMouseEvent;
|
||||
class QWindow;
|
||||
class QPlatformWindow;
|
||||
class QXcbConnection;
|
||||
|
|
@ -73,14 +72,14 @@ public:
|
|||
|
||||
void startDrag() Q_DECL_OVERRIDE;
|
||||
void cancel() Q_DECL_OVERRIDE;
|
||||
void move(const QMouseEvent *me) Q_DECL_OVERRIDE;
|
||||
void drop(const QMouseEvent *me) Q_DECL_OVERRIDE;
|
||||
void move(const QPoint &globalPos) Q_DECL_OVERRIDE;
|
||||
void drop(const QPoint &globalPos) Q_DECL_OVERRIDE;
|
||||
void endDrag() Q_DECL_OVERRIDE;
|
||||
|
||||
void handleEnter(QWindow *window, const xcb_client_message_event_t *event);
|
||||
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 handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event);
|
||||
void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
|
||||
void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event);
|
||||
void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event);
|
||||
|
||||
void handleStatus(const xcb_client_message_event_t *event);
|
||||
void handleSelectionRequest(const xcb_selection_request_event_t *event);
|
||||
|
|
@ -100,7 +99,7 @@ private:
|
|||
|
||||
void init();
|
||||
|
||||
void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event);
|
||||
void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event);
|
||||
void handle_xdnd_status(const xcb_client_message_event_t *event);
|
||||
void send_leave();
|
||||
|
||||
|
|
@ -147,7 +146,7 @@ private:
|
|||
xcb_timestamp_t timestamp;
|
||||
xcb_window_t target;
|
||||
xcb_window_t proxy_target;
|
||||
QWindow *targetWindow;
|
||||
QPlatformWindow *targetWindow;
|
||||
// QWidget *embedding_widget;
|
||||
QPointer<QDrag> drag;
|
||||
QTime time;
|
||||
|
|
|
|||
Loading…
Reference in New Issue