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
This commit is contained in:
Frederik Gladhorn 2015-02-16 11:05:38 +01:00
commit d1de454093
11 changed files with 91 additions and 31 deletions

View File

@ -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);

View File

@ -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]);

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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()) {

View File

@ -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);

View File

@ -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);

View File

@ -222,8 +222,6 @@ protected:
QPoint mOffset;
QIcon mWindowIcon;
QWaylandInputDevice *mMouseDevice;
int mMouseSerial;
Qt::WindowState mState;
QRegion mMask;

View File

@ -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