summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-02-16 11:05:38 +0100
committerFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-02-16 11:05:38 +0100
commit2d0c80018e6da8193a6c5bd5d764da509e16ab46 (patch)
treee6ffaf8ec73f6cade2d5fbd17b3ba6d27c790a77
parente6805407b62c9c57bac488813f77ee5cca71868e (diff)
parent8458e06b25c07ebc8cf6b210fc1ea4cc9aeb42eb (diff)
Merge remote-tracking branch 'origin/5.4' into dev
Conflicts: src/client/qwaylanddataoffer.cpp src/client/qwaylanddisplay.cpp src/client/qwaylandinputdevice.cpp src/client/qwaylandwindow.cpp src/compositor/compositor_api/qwaylandsurfaceitem.cpp Change-Id: I2eae0fd43a71fbfd7c907ca715707a26f3c134c5
-rw-r--r--src/client/qwaylandclipboard.cpp4
-rw-r--r--src/client/qwaylanddataoffer.cpp25
-rw-r--r--src/client/qwaylanddisplay.cpp8
-rw-r--r--src/client/qwaylanddisplay_p.h8
-rw-r--r--src/client/qwaylanddnd.cpp9
-rw-r--r--src/client/qwaylandinputdevice.cpp20
-rw-r--r--src/client/qwaylandscreen.cpp8
-rw-r--r--src/client/qwaylandscreen_p.h1
-rw-r--r--src/client/qwaylandwindow.cpp29
-rw-r--r--src/client/qwaylandwindow_p.h2
-rw-r--r--src/client/qwaylandwlshellsurface.cpp8
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.cpp14
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.h1
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceview.cpp6
14 files changed, 112 insertions, 31 deletions
diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp
index 226a374ab..3e25875f0 100644
--- a/src/client/qwaylandclipboard.cpp
+++ b/src/client/qwaylandclipboard.cpp
@@ -88,6 +88,10 @@ void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
if (!inputDevice || !inputDevice->dataDevice())
return;
+ static const QString plain = QStringLiteral("text/plain");
+ static const QString utf8 = QStringLiteral("text/plain;charset=utf-8");
+ if (data && data->hasFormat(plain) && !data->hasFormat(utf8))
+ data->setData(utf8, data->data(plain));
inputDevice->dataDevice()->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : 0);
emitChanged(mode);
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
index 10bf2f1e1..7b69ce6ce 100644
--- a/src/client/qwaylanddataoffer.cpp
+++ b/src/client/qwaylanddataoffer.cpp
@@ -53,6 +53,11 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+static QString utf8Text()
+{
+ return QStringLiteral("text/plain;charset=utf-8");
+}
+
QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
: QtWayland::wl_data_offer(offer)
, m_mimeData(new QWaylandMimeData(this, display))
@@ -102,7 +107,13 @@ void QWaylandMimeData::appendFormat(const QString &mimeType)
bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
{
- return m_types.contains(mimeType);
+ if (m_types.contains(mimeType))
+ return true;
+
+ if (mimeType == QStringLiteral("text/plain") && m_types.contains(utf8Text()))
+ return true;
+
+ return false;
}
QStringList QWaylandMimeData::formats_sys() const
@@ -117,8 +128,14 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
if (m_data.contains(mimeType))
return m_data.value(mimeType);
- if (!m_types.contains(mimeType))
- return QVariant();
+ QString mime = mimeType;
+
+ if (!m_types.contains(mimeType)) {
+ if (mimeType == QStringLiteral("text/plain") && m_types.contains(utf8Text()))
+ mime = utf8Text();
+ else
+ return QVariant();
+ }
int pipefd[2];
if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) {
@@ -126,7 +143,7 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
return QVariant();
}
- m_dataOffer->receive(mimeType, pipefd[1]);
+ m_dataOffer->receive(mime, pipefd[1]);
m_display->flushRequests();
close(pipefd[1]);
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index ea7fe1a6a..1284d39a1 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -140,6 +140,9 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
, mQtKeyExtension(0)
, mTextInputManager(0)
, mHardwareIntegration(0)
+ , mLastInputSerial(0)
+ , mLastInputDevice(0)
+ , mLastInputWindow(0)
{
qRegisterMetaType<uint32_t>("uint32_t");
@@ -373,6 +376,11 @@ bool QWaylandDisplay::supportsWindowDecoration() const
return integrationSupport;
}
+void QWaylandDisplay::setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *win)
+{
+ mLastInputDevice = device;
+ mLastInputSerial = serial;
+ mLastInputWindow = win;
}
QT_END_NAMESPACE
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 9d4413f6f..394fd4270 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -163,6 +163,11 @@ public:
bool supportsWindowDecoration() const;
+ uint32_t lastInputSerial() const { return mLastInputSerial; }
+ QWaylandInputDevice *lastInputDevice() const { return mLastInputDevice; }
+ QWaylandWindow *lastInputWindow() const { return mLastInputWindow; }
+ void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window);
+
public slots:
void blockingReadEvents();
void flushRequests();
@@ -204,6 +209,9 @@ private:
bool mScreensInitialized;
QList<RegistryGlobal> mGlobals;
int mCompositorVersion;
+ uint32_t mLastInputSerial;
+ QWaylandInputDevice *mLastInputDevice;
+ QWaylandWindow *mLastInputWindow;
void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE;
void registry_global_remove(uint32_t id) Q_DECL_OVERRIDE;
diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp
index 514383d30..85deaf27f 100644
--- a/src/client/qwaylanddnd.cpp
+++ b/src/client/qwaylanddnd.cpp
@@ -73,13 +73,20 @@ QMimeData * QWaylandDrag::platformDropData()
void QWaylandDrag::startDrag()
{
+ bool cancel = false;
if (!shapedPixmapWindow()) {
QBasicDrag::startDrag();
- QBasicDrag::cancel();
+ // Don't call cancel() here, since that will hide 'shapedPixmapWindow()', and
+ // QWaylandWindow::setVisible(false) will flush the window system queue,
+ // ending up trying to render the window, which doesn't have a role yet,
+ // and so blocking waiting for a frame callback.
+ cancel = true;
}
QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon);
+ if (cancel)
+ QBasicDrag::cancel();
QBasicDrag::startDrag();
}
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index db43e525b..63bbeb14a 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -439,10 +439,10 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
// so we just set it outside of the window boundaries.
pos = QPointF(-1, -1);
global = grab->window()->mapToGlobal(pos.toPoint());
- MotionEvent e(time, pos, global, mButtons, Qt::NoModifier);
+ MotionEvent e(time, pos, global, mButtons, mParent->modifiers());
grab->handleMouse(mParent, e);
} else {
- MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
+ MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
window->handleMouse(mParent, e);
}
}
@@ -450,7 +450,6 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time,
uint32_t button, uint32_t state)
{
- Q_UNUSED(serial);
QWaylandWindow *window = mFocus;
Qt::MouseButton qt_button;
@@ -483,15 +482,17 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
mParent->mTime = time;
mParent->mSerial = serial;
+ if (state)
+ mParent->mQDisplay->setLastInputDevice(mParent, serial, window);
QWaylandWindow *grab = QWaylandWindow::mouseGrab();
if (grab && grab != mFocus) {
QPointF pos = QPointF(-1, -1);
QPointF global = grab->window()->mapToGlobal(pos.toPoint());
- MotionEvent e(time, pos, global, mButtons, Qt::NoModifier);
+ MotionEvent e(time, pos, global, mButtons, mParent->modifiers());
grab->handleMouse(mParent, e);
} else if (window) {
- MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
+ MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
window->handleMouse(mParent, e);
}
}
@@ -736,13 +737,13 @@ void QWaylandInputDevice::Keyboard::focusCallback(void *data, struct wl_callback
void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
- Q_UNUSED(serial);
QWaylandWindow *window = mFocus;
uint32_t code = key + 8;
bool isDown = state != 0;
QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
QString text;
int qtkey = key + 8; // qt-compositor substracts 8 for some reason
+ mParent->mSerial = serial;
if (!window) {
// We destroyed the keyboard focus surface, but the server
@@ -750,6 +751,9 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
return;
}
+ if (isDown)
+ mParent->mQDisplay->setLastInputDevice(mParent, serial, window);
+
#ifndef QT_NO_WAYLAND_XKB
if (!createDefaultKeyMap()) {
return;
@@ -761,7 +765,8 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
Qt::KeyboardModifiers modifiers = mParent->modifiers();
uint utf32 = xkb_keysym_to_utf32(sym);
- text = QString::fromUcs4(&utf32, 1);
+ if (utf32)
+ text = QString::fromUcs4(&utf32, 1);
qtkey = keysymToQtKey(sym, modifiers, text);
@@ -855,6 +860,7 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
mParent->mTime = time;
mParent->mSerial = serial;
mFocus = QWaylandWindow::fromWlSurface(surface);
+ mParent->mQDisplay->setLastInputDevice(mParent, serial, mFocus);
mParent->handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed);
}
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index a1aff8d1c..56885531c 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -118,6 +118,14 @@ QDpi QWaylandScreen::logicalDpi() const
return QPlatformScreen::logicalDpi();
}
+QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const
+{
+ QList<QPlatformScreen *> list;
+ foreach (QWaylandScreen *screen, mWaylandDisplay->screens())
+ list << screen;
+ return list;
+}
+
void QWaylandScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
{
foreach (QWindow *window, QGuiApplication::allWindows()) {
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index c337d9be3..b1b4a73f7 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -70,6 +70,7 @@ public:
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
+ QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE;
void setOrientationUpdateMask(Qt::ScreenOrientations mask);
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index cf4e0e672..b01e1f108 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -90,8 +90,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
, mResizeDirty(false)
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
, mSentInitialResize(false)
- , mMouseDevice(0)
- , mMouseSerial(0)
, mState(Qt::WindowNoState)
, mMask()
, mBackingStore(Q_NULLPTR)
@@ -218,7 +216,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
{
setGeometry_helper(rect);
- if (window()->isVisible()) {
+ if (window()->isVisible() && rect.isValid()) {
if (mWindowDecoration)
mWindowDecoration->update();
@@ -236,14 +234,17 @@ void QWaylandWindow::setGeometry(const QRect &rect)
void QWaylandWindow::setVisible(bool visible)
{
if (visible) {
- if (window()->type() == Qt::Popup && transientParent()) {
+ if (window()->type() == Qt::Popup) {
QWaylandWindow *parent = transientParent();
- mMouseDevice = parent->mMouseDevice;
- mMouseSerial = parent->mMouseSerial;
-
- QWaylandWlShellSurface *wlshellSurface = dynamic_cast<QWaylandWlShellSurface*>(mShellSurface);
- if (mMouseDevice && wlshellSurface) {
- wlshellSurface->setPopup(transientParent(), mMouseDevice, mMouseSerial);
+ if (!parent) {
+ // Try with the current focus window. It should be the right one and anyway
+ // better than having no parent at all.
+ parent = mDisplay->lastInputWindow();
+ }
+ if (parent) {
+ QWaylandWlShellSurface *wlshellSurface = dynamic_cast<QWaylandWlShellSurface*>(mShellSurface);
+ if (wlshellSurface)
+ wlshellSurface->setPopup(parent, mDisplay->lastInputDevice(), mDisplay->lastInputSerial());
}
}
@@ -364,7 +365,7 @@ void QWaylandWindow::requestResize()
{
QMutexLocker lock(&mResizeLock);
- if (mCanResize) {
+ if (mCanResize || !mSentInitialResize) {
doResize();
}
@@ -599,7 +600,7 @@ QWaylandWindow *QWaylandWindow::transientParent() const
if (window()->transientParent()) {
// Take the top level window here, since the transient parent may be a QWidgetWindow
// or some other window without a shell surface, which is then not able to get mouse
- // events, nor set mMouseSerial and mMouseDevice.
+ // events.
return static_cast<QWaylandWindow *>(topLevelWindow(window()->transientParent())->handle());
}
return 0;
@@ -607,10 +608,6 @@ QWaylandWindow *QWaylandWindow::transientParent() const
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{
- if (e.buttons != Qt::NoButton) {
- mMouseSerial = inputDevice->serial();
- mMouseDevice = inputDevice;
- }
if (mWindowDecoration) {
handleMouseEventWithDecoration(inputDevice, e);
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index de59e4e20..21d4886cc 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -222,8 +222,6 @@ protected:
QPoint mOffset;
QIcon mWindowIcon;
- QWaylandInputDevice *mMouseDevice;
- int mMouseSerial;
Qt::WindowState mState;
QRegion mMask;
diff --git a/src/client/qwaylandwlshellsurface.cpp b/src/client/qwaylandwlshellsurface.cpp
index 550e6caeb..0f249e36e 100644
--- a/src/client/qwaylandwlshellsurface.cpp
+++ b/src/client/qwaylandwlshellsurface.cpp
@@ -189,8 +189,14 @@ void QWaylandWlShellSurface::updateTransientParent(QWindow *parent)
void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial)
{
QWaylandWindow *parent_wayland_window = parent;
- if (!parent_wayland_window)
+ if (!parent_wayland_window) {
+ qWarning("setPopup called without parent window");
+ return;
+ }
+ if (!device) {
+ qWarning("setPopup called without input device");
return;
+ }
// set_popup expects a position relative to the parent
QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
index 8a0d6bd28..972a9d34a 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
+++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
@@ -229,6 +229,12 @@ void QWaylandSurfaceItem::touchEvent(QTouchEvent *event)
if (m_touchEventsEnabled) {
QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
+ if (event->type() == QEvent::TouchBegin) {
+ QQuickItem *grabber = window()->mouseGrabberItem();
+ if (grabber != this)
+ grabMouse();
+ }
+
QPoint pointPos;
const QList<QTouchEvent::TouchPoint> &points = event->touchPoints();
if (!points.isEmpty())
@@ -249,6 +255,14 @@ void QWaylandSurfaceItem::touchEvent(QTouchEvent *event)
}
}
+void QWaylandSurfaceItem::mouseUngrabEvent()
+{
+ if (surface()) {
+ QTouchEvent e(QEvent::TouchCancel);
+ touchEvent(&e);
+ }
+}
+
void QWaylandSurfaceItem::takeFocus(QWaylandInputDevice *device)
{
setFocus(true);
diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h
index 2573fba3e..2bf822f54 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceitem.h
+++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h
@@ -101,6 +101,7 @@ protected:
void keyReleaseEvent(QKeyEvent *event);
void touchEvent(QTouchEvent *event);
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
public slots:
virtual void takeFocus(QWaylandInputDevice *device = 0);
diff --git a/src/compositor/compositor_api/qwaylandsurfaceview.cpp b/src/compositor/compositor_api/qwaylandsurfaceview.cpp
index e6fd90587..664ab9805 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceview.cpp
+++ b/src/compositor/compositor_api/qwaylandsurfaceview.cpp
@@ -42,6 +42,8 @@
#include "qwaylandsurfaceview.h"
#include "qwaylandsurface.h"
#include "qwaylandsurface_p.h"
+#include "qwaylandcompositor.h"
+#include "qwaylandinput.h"
QT_BEGIN_NAMESPACE
@@ -65,6 +67,10 @@ QWaylandSurfaceView::QWaylandSurfaceView(QWaylandSurface *surf)
QWaylandSurfaceView::~QWaylandSurfaceView()
{
if (d->surface) {
+ QWaylandInputDevice *i = d->surface->compositor()->defaultInputDevice();
+ if (i->mouseFocus() == this)
+ i->setMouseFocus(nullptr, QPointF());
+
d->surface->destroy();
d->surface->d_func()->views.removeOne(this);
}