Merge "Merge remote-tracking branch 'origin/5.12' into 5.13"
This commit is contained in:
commit
0816fda053
@ -102,19 +102,22 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
|
|||||||
return m_dragOffer.data();
|
return m_dragOffer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
||||||
{
|
{
|
||||||
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
|
||||||
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
|
||||||
|
|
||||||
QWaylandWindow *origin = m_display->currentInputDevice()->pointerFocus();
|
QWaylandWindow *origin = m_display->currentInputDevice()->pointerFocus();
|
||||||
if (!origin)
|
if (!origin)
|
||||||
origin = m_display->currentInputDevice()->touchFocus();
|
origin = m_display->currentInputDevice()->touchFocus();
|
||||||
|
|
||||||
if (origin)
|
if (!origin) {
|
||||||
start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
|
|
||||||
else
|
|
||||||
qCDebug(lcQpaWayland) << "Couldn't start a drag because the origin window could not be found.";
|
qCDebug(lcQpaWayland) << "Couldn't start a drag because the origin window could not be found.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
||||||
|
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
||||||
|
|
||||||
|
start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandDataDevice::cancelDrag()
|
void QWaylandDataDevice::cancelDrag()
|
||||||
|
@ -89,7 +89,7 @@ public:
|
|||||||
|
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
QWaylandDataOffer *dragOffer() const;
|
QWaylandDataOffer *dragOffer() const;
|
||||||
void startDrag(QMimeData *mimeData, QWaylandWindow *icon);
|
bool startDrag(QMimeData *mimeData, QWaylandWindow *icon);
|
||||||
void cancelDrag();
|
void cancelDrag();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -66,8 +66,13 @@ void QWaylandDrag::startDrag()
|
|||||||
{
|
{
|
||||||
QBasicDrag::startDrag();
|
QBasicDrag::startDrag();
|
||||||
QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
|
QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
|
||||||
m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon);
|
if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) {
|
||||||
icon->addAttachOffset(-drag()->hotSpot());
|
icon->addAttachOffset(-drag()->hotSpot());
|
||||||
|
} else {
|
||||||
|
// Cancelling immediately does not work, since the event loop for QDrag::exec is started
|
||||||
|
// after this function returns.
|
||||||
|
QMetaObject::invokeMethod(this, [this](){ cancelDrag(); }, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandDrag::cancel()
|
void QWaylandDrag::cancel()
|
||||||
|
@ -994,15 +994,20 @@ void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_
|
|||||||
{
|
{
|
||||||
Q_UNUSED(serial);
|
Q_UNUSED(serial);
|
||||||
Q_UNUSED(time);
|
Q_UNUSED(time);
|
||||||
mFocus = nullptr;
|
|
||||||
mParent->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
|
mParent->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
|
||||||
|
|
||||||
// As of Weston 1.5.90 there is no touch_frame after the last touch_up
|
if (allTouchPointsReleased()) {
|
||||||
|
mFocus = nullptr;
|
||||||
|
|
||||||
|
// As of Weston 7.0.0 there is no touch_frame after the last touch_up
|
||||||
// (i.e. when the last finger is released). To accommodate for this, issue a
|
// (i.e. when the last finger is released). To accommodate for this, issue a
|
||||||
// touch_frame. This cannot hurt since it is safe to call the touch_frame
|
// touch_frame. This cannot hurt since it is safe to call the touch_frame
|
||||||
// handler multiple times when there are no points left.
|
// handler multiple times when there are no points left.
|
||||||
if (allTouchPointsReleased())
|
// See: https://gitlab.freedesktop.org/wayland/weston/issues/44
|
||||||
|
// TODO: change logging category to lcQpaWaylandInput in newer versions.
|
||||||
|
qCDebug(lcQpaWayland, "Generating fake frame event to work around Weston bug");
|
||||||
touch_frame();
|
touch_frame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
|
void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
|
||||||
@ -1013,8 +1018,7 @@ void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixe
|
|||||||
|
|
||||||
void QWaylandInputDevice::Touch::touch_cancel()
|
void QWaylandInputDevice::Touch::touch_cancel()
|
||||||
{
|
{
|
||||||
mPrevTouchPoints.clear();
|
mPendingTouchPoints.clear();
|
||||||
mTouchPoints.clear();
|
|
||||||
|
|
||||||
QWaylandTouchExtension *touchExt = mParent->mQDisplay->touchExtension();
|
QWaylandTouchExtension *touchExt = mParent->mQDisplay->touchExtension();
|
||||||
if (touchExt)
|
if (touchExt)
|
||||||
@ -1025,19 +1029,16 @@ void QWaylandInputDevice::Touch::touch_cancel()
|
|||||||
|
|
||||||
void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::TouchPointState state)
|
void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::TouchPointState state)
|
||||||
{
|
{
|
||||||
QWindowSystemInterface::TouchPoint tp;
|
auto end = mTouch->mPendingTouchPoints.end();
|
||||||
|
auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](auto tp){ return tp.id == id; });
|
||||||
// Find out the coordinates for Released events.
|
if (it == end) {
|
||||||
bool coordsOk = false;
|
it = mTouch->mPendingTouchPoints.insert(end, QWindowSystemInterface::TouchPoint());
|
||||||
if (state == Qt::TouchPointReleased)
|
it->id = id;
|
||||||
for (int i = 0; i < mTouch->mPrevTouchPoints.count(); ++i)
|
|
||||||
if (mTouch->mPrevTouchPoints.at(i).id == id) {
|
|
||||||
tp.area = mTouch->mPrevTouchPoints.at(i).area;
|
|
||||||
coordsOk = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
QWindowSystemInterface::TouchPoint &tp = *it;
|
||||||
|
|
||||||
if (!coordsOk) {
|
// Only moved and pressed needs to update/set position
|
||||||
|
if (state == Qt::TouchPointMoved || state == Qt::TouchPointPressed) {
|
||||||
// x and y are surface relative.
|
// x and y are surface relative.
|
||||||
// We need a global (screen) position.
|
// We need a global (screen) position.
|
||||||
QWaylandWindow *win = mTouch->mFocus;
|
QWaylandWindow *win = mTouch->mFocus;
|
||||||
@ -1056,59 +1057,37 @@ void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::Touch
|
|||||||
}
|
}
|
||||||
|
|
||||||
tp.state = state;
|
tp.state = state;
|
||||||
tp.id = id;
|
|
||||||
tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
|
tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
|
||||||
mTouch->mTouchPoints.append(tp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWaylandInputDevice::Touch::allTouchPointsReleased()
|
bool QWaylandInputDevice::Touch::allTouchPointsReleased()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mTouchPoints.count(); ++i)
|
for (const auto &tp : qAsConst(mPendingTouchPoints)) {
|
||||||
if (mTouchPoints.at(i).state != Qt::TouchPointReleased)
|
if (tp.state != Qt::TouchPointReleased)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandInputDevice::Touch::releasePoints()
|
void QWaylandInputDevice::Touch::releasePoints()
|
||||||
{
|
{
|
||||||
Q_FOREACH (const QWindowSystemInterface::TouchPoint &previousPoint, mPrevTouchPoints) {
|
if (mPendingTouchPoints.empty())
|
||||||
QWindowSystemInterface::TouchPoint tp = previousPoint;
|
return;
|
||||||
|
|
||||||
|
for (QWindowSystemInterface::TouchPoint &tp : mPendingTouchPoints)
|
||||||
tp.state = Qt::TouchPointReleased;
|
tp.state = Qt::TouchPointReleased;
|
||||||
mTouchPoints.append(tp);
|
|
||||||
}
|
|
||||||
touch_frame();
|
touch_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandInputDevice::Touch::touch_frame()
|
void QWaylandInputDevice::Touch::touch_frame()
|
||||||
{
|
{
|
||||||
// Copy all points, that are in the previous but not in the current list, as stationary.
|
// TODO: early return if no events?
|
||||||
for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
|
|
||||||
const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
|
|
||||||
if (prevPoint.state == Qt::TouchPointReleased)
|
|
||||||
continue;
|
|
||||||
bool found = false;
|
|
||||||
for (int j = 0; j < mTouchPoints.count(); ++j)
|
|
||||||
if (mTouchPoints.at(j).id == prevPoint.id) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
QWindowSystemInterface::TouchPoint p = prevPoint;
|
|
||||||
p.state = Qt::TouchPointStationary;
|
|
||||||
mTouchPoints.append(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTouchPoints.isEmpty()) {
|
|
||||||
mPrevTouchPoints.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWindow *window = mFocus ? mFocus->window() : nullptr;
|
QWindow *window = mFocus ? mFocus->window() : nullptr;
|
||||||
|
|
||||||
if (mFocus) {
|
if (mFocus) {
|
||||||
const QWindowSystemInterface::TouchPoint &tp = mTouchPoints.last();
|
const QWindowSystemInterface::TouchPoint &tp = mPendingTouchPoints.last();
|
||||||
// When the touch event is received, the global pos is calculated with the margins
|
// When the touch event is received, the global pos is calculated with the margins
|
||||||
// in mind. Now we need to adjust again to get the correct local pos back.
|
// in mind. Now we need to adjust again to get the correct local pos back.
|
||||||
QMargins margins = window->frameMargins();
|
QMargins margins = window->frameMargins();
|
||||||
@ -1117,14 +1096,21 @@ void QWaylandInputDevice::Touch::touch_frame()
|
|||||||
if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers()))
|
if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers()))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints);
|
|
||||||
|
|
||||||
if (allTouchPointsReleased())
|
QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mPendingTouchPoints);
|
||||||
mPrevTouchPoints.clear();
|
|
||||||
else
|
// Prepare state for next frame
|
||||||
mPrevTouchPoints = mTouchPoints;
|
const auto prevTouchPoints = mPendingTouchPoints;
|
||||||
|
mPendingTouchPoints.clear();
|
||||||
|
for (const auto &prevPoint: prevTouchPoints) {
|
||||||
|
// All non-released touch points should be part of the next touch event
|
||||||
|
if (prevPoint.state != Qt::TouchPointReleased) {
|
||||||
|
QWindowSystemInterface::TouchPoint tp = prevPoint;
|
||||||
|
tp.state = Qt::TouchPointStationary; // ... as stationary (unless proven otherwise)
|
||||||
|
mPendingTouchPoints.append(tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mTouchPoints.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -333,8 +333,7 @@ public:
|
|||||||
|
|
||||||
QWaylandInputDevice *mParent = nullptr;
|
QWaylandInputDevice *mParent = nullptr;
|
||||||
QPointer<QWaylandWindow> mFocus;
|
QPointer<QWaylandWindow> mFocus;
|
||||||
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
|
QList<QWindowSystemInterface::TouchPoint> mPendingTouchPoints;
|
||||||
QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QWaylandPointerEvent
|
class QWaylandPointerEvent
|
||||||
|
@ -200,7 +200,10 @@ void QWaylandWindow::initWindow()
|
|||||||
void QWaylandWindow::initializeWlSurface()
|
void QWaylandWindow::initializeWlSurface()
|
||||||
{
|
{
|
||||||
Q_ASSERT(!isInitialized());
|
Q_ASSERT(!isInitialized());
|
||||||
|
{
|
||||||
|
QWriteLocker lock(&mSurfaceLock);
|
||||||
init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
|
init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
|
||||||
|
}
|
||||||
emit wlSurfaceCreated();
|
emit wlSurfaceCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +241,7 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
|
|||||||
mSubSurfaceWindow = nullptr;
|
mSubSurfaceWindow = nullptr;
|
||||||
if (isInitialized()) {
|
if (isInitialized()) {
|
||||||
emit wlSurfaceDestroyed();
|
emit wlSurfaceDestroyed();
|
||||||
|
QWriteLocker lock(&mSurfaceLock);
|
||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
mScreens.clear();
|
mScreens.clear();
|
||||||
@ -659,10 +663,11 @@ QMutex QWaylandWindow::mFrameSyncMutex;
|
|||||||
|
|
||||||
bool QWaylandWindow::waitForFrameSync(int timeout)
|
bool QWaylandWindow::waitForFrameSync(int timeout)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mFrameSyncMutex);
|
|
||||||
if (!mWaitingForFrameCallback)
|
if (!mWaitingForFrameCallback)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
QMutexLocker locker(&mFrameSyncMutex);
|
||||||
|
|
||||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(mFrameCallback), mFrameQueue);
|
wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(mFrameCallback), mFrameQueue);
|
||||||
mDisplay->dispatchQueueWhile(mFrameQueue, [&]() { return mWaitingForFrameCallback; }, timeout);
|
mDisplay->dispatchQueueWhile(mFrameQueue, [&]() { return mWaitingForFrameCallback; }, timeout);
|
||||||
|
|
||||||
@ -1159,6 +1164,9 @@ void QWaylandWindow::requestUpdate()
|
|||||||
void QWaylandWindow::handleUpdate()
|
void QWaylandWindow::handleUpdate()
|
||||||
{
|
{
|
||||||
// TODO: Should sync subsurfaces avoid requesting frame callbacks?
|
// TODO: Should sync subsurfaces avoid requesting frame callbacks?
|
||||||
|
QReadLocker lock(&mSurfaceLock);
|
||||||
|
if (!isInitialized())
|
||||||
|
return;
|
||||||
|
|
||||||
if (mFrameCallback) {
|
if (mFrameCallback) {
|
||||||
wl_callback_destroy(mFrameCallback);
|
wl_callback_destroy(mFrameCallback);
|
||||||
|
@ -53,6 +53,8 @@
|
|||||||
|
|
||||||
#include <QtCore/QWaitCondition>
|
#include <QtCore/QWaitCondition>
|
||||||
#include <QtCore/QMutex>
|
#include <QtCore/QMutex>
|
||||||
|
#include <QtCore/QReadWriteLock>
|
||||||
|
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
#include <QtCore/QLoggingCategory>
|
#include <QtCore/QLoggingCategory>
|
||||||
@ -279,6 +281,8 @@ private:
|
|||||||
static QMutex mFrameSyncMutex;
|
static QMutex mFrameSyncMutex;
|
||||||
static QWaylandWindow *mMouseGrab;
|
static QWaylandWindow *mMouseGrab;
|
||||||
|
|
||||||
|
QReadWriteLock mSurfaceLock;
|
||||||
|
|
||||||
friend class QWaylandSubSurface;
|
friend class QWaylandSubSurface;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user