summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authorJorgen Lind <jorgen.lind@digia.com>2013-11-14 13:22:13 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-27 15:32:17 +0100
commitd250b714f8eb5a60bb048830e723ac76f06215b7 (patch)
treef6a6334b5ed8d3f3425447bd995f2bbff75e312f /src/client
parent333648ff98558b78ca0464f8b1d606d40234d46f (diff)
Move wayland into a client directory not under the plugins src folder
And make wayland common files into a library, exporting all classes. Now there is no need to do bulild hacks to make your own version of the wayland plugin. Change-Id: Ib4872863dfb5ab3f2bc0f4a94ae16fc1e7b63b88 Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src/client')
-rw-r--r--src/client/client.pro103
-rw-r--r--src/client/qwaylandbuffer.h68
-rw-r--r--src/client/qwaylandclientexport.h60
-rw-r--r--src/client/qwaylandclipboard.cpp111
-rw-r--r--src/client/qwaylandclipboard.h72
-rw-r--r--src/client/qwaylandcursor.cpp302
-rw-r--r--src/client/qwaylandcursor.h116
-rw-r--r--src/client/qwaylanddatadevice.cpp242
-rw-r--r--src/client/qwaylanddatadevice.h97
-rw-r--r--src/client/qwaylanddatadevicemanager.cpp80
-rw-r--r--src/client/qwaylanddatadevicemanager.h69
-rw-r--r--src/client/qwaylanddataoffer.cpp139
-rw-r--r--src/client/qwaylanddataoffer.h92
-rw-r--r--src/client/qwaylanddatasource.cpp96
-rw-r--r--src/client/qwaylanddatasource.h77
-rw-r--r--src/client/qwaylanddecoration.cpp459
-rw-r--r--src/client/qwaylanddecoration.h155
-rw-r--r--src/client/qwaylanddisplay.cpp272
-rw-r--r--src/client/qwaylanddisplay.h193
-rw-r--r--src/client/qwaylanddnd.cpp136
-rw-r--r--src/client/qwaylanddnd.h80
-rw-r--r--src/client/qwaylandeventthread.cpp63
-rw-r--r--src/client/qwaylandeventthread.h46
-rw-r--r--src/client/qwaylandextendedoutput.cpp100
-rw-r--r--src/client/qwaylandextendedoutput.h69
-rw-r--r--src/client/qwaylandextendedsurface.cpp152
-rw-r--r--src/client/qwaylandextendedsurface.h85
-rw-r--r--src/client/qwaylandglintegration.cpp56
-rw-r--r--src/client/qwaylandglintegration.h76
-rw-r--r--src/client/qwaylandinputcontext.cpp260
-rw-r--r--src/client/qwaylandinputcontext.h103
-rw-r--r--src/client/qwaylandinputdevice.cpp798
-rw-r--r--src/client/qwaylandinputdevice.h204
-rw-r--r--src/client/qwaylandintegration.cpp252
-rw-r--r--src/client/qwaylandintegration.h101
-rw-r--r--src/client/qwaylandnativeinterface.cpp134
-rw-r--r--src/client/qwaylandnativeinterface.h79
-rw-r--r--src/client/qwaylandqtkey.cpp85
-rw-r--r--src/client/qwaylandqtkey.h76
-rw-r--r--src/client/qwaylandscreen.cpp184
-rw-r--r--src/client/qwaylandscreen.h110
-rw-r--r--src/client/qwaylandshellsurface.cpp176
-rw-r--r--src/client/qwaylandshellsurface.h96
-rw-r--r--src/client/qwaylandshmbackingstore.cpp322
-rw-r--r--src/client/qwaylandshmbackingstore.h134
-rw-r--r--src/client/qwaylandshmwindow.cpp73
-rw-r--r--src/client/qwaylandshmwindow.h75
-rw-r--r--src/client/qwaylandsubsurface.cpp91
-rw-r--r--src/client/qwaylandsubsurface.h73
-rw-r--r--src/client/qwaylandtouch.cpp209
-rw-r--r--src/client/qwaylandtouch.h97
-rw-r--r--src/client/qwaylandwindow.cpp608
-rw-r--r--src/client/qwaylandwindow.h233
-rw-r--r--src/client/qwaylandwindowmanagerintegration.cpp159
-rw-r--r--src/client/qwaylandwindowmanagerintegration.h88
55 files changed, 8486 insertions, 0 deletions
diff --git a/src/client/client.pro b/src/client/client.pro
new file mode 100644
index 000000000..66dc1a475
--- /dev/null
+++ b/src/client/client.pro
@@ -0,0 +1,103 @@
+TARGET = QtWaylandClient
+QT += core-private gui-private
+QT_FOR_PRIVATE += platformsupport-private
+
+MODULE=waylandclient
+load(qt_module)
+
+CONFIG += link_pkgconfig qpa/genericunixfontdatabase wayland-scanner
+
+!equals(QT_WAYLAND_GL_CONFIG, nogl) {
+ DEFINES += QT_WAYLAND_GL_SUPPORT
+}
+
+config_xkbcommon {
+ !contains(QT_CONFIG, no-pkg-config) {
+ PKGCONFIG += xkbcommon
+ } else {
+ LIBS += -lxkbcommon
+ }
+} else {
+ DEFINES += QT_NO_WAYLAND_XKB
+}
+
+!contains(QT_CONFIG, no-pkg-config) {
+ PKGCONFIG += wayland-client wayland-cursor
+ contains(QT_CONFIG, glib): PKGCONFIG_PRIVATE += glib-2.0
+} else {
+ LIBS += -lwayland-client -lwayland-cursor $$QT_LIBS_GLIB
+}
+
+INCLUDEPATH += $$PWD/../shared
+
+WAYLANDCLIENTSOURCES += \
+ ../3rdparty/protocol/wayland.xml \
+ ../extensions/surface-extension.xml \
+ ../extensions/sub-surface-extension.xml \
+ ../extensions/output-extension.xml \
+ ../extensions/touch-extension.xml \
+ ../extensions/qtkey-extension.xml \
+ ../extensions/windowmanager.xml \
+ ../3rdparty/protocol/text.xml \
+
+
+SOURCES += qwaylandintegration.cpp \
+ qwaylandnativeinterface.cpp \
+ qwaylandshmbackingstore.cpp \
+ qwaylandinputdevice.cpp \
+ qwaylandcursor.cpp \
+ qwaylanddisplay.cpp \
+ qwaylandwindow.cpp \
+ qwaylandscreen.cpp \
+ qwaylandshmwindow.cpp \
+ qwaylandclipboard.cpp \
+ qwaylanddnd.cpp \
+ qwaylanddataoffer.cpp \
+ qwaylanddatadevicemanager.cpp \
+ qwaylanddatasource.cpp \
+ qwaylandshellsurface.cpp \
+ qwaylandextendedoutput.cpp \
+ qwaylandextendedsurface.cpp \
+ qwaylandsubsurface.cpp \
+ qwaylandtouch.cpp \
+ qwaylandqtkey.cpp \
+ ../shared/qwaylandmimehelper.cpp \
+ qwaylanddecoration.cpp \
+ qwaylandeventthread.cpp\
+ qwaylandwindowmanagerintegration.cpp \
+ qwaylandinputcontext.cpp \
+ qwaylanddatadevice.cpp \
+
+HEADERS += qwaylandintegration.h \
+ qwaylandnativeinterface.h \
+ qwaylandcursor.h \
+ qwaylanddisplay.h \
+ qwaylandwindow.h \
+ qwaylandscreen.h \
+ qwaylandshmbackingstore.h \
+ qwaylandinputdevice.h \
+ qwaylandbuffer.h \
+ qwaylandshmwindow.h \
+ qwaylandclipboard.h \
+ qwaylanddnd.h \
+ qwaylanddataoffer.h \
+ qwaylanddatadevicemanager.h \
+ qwaylanddatasource.h \
+ qwaylandshellsurface.h \
+ qwaylandextendedoutput.h \
+ qwaylandextendedsurface.h \
+ qwaylandsubsurface.h \
+ qwaylandtouch.h \
+ qwaylandqtkey.h \
+ ../shared/qwaylandmimehelper.h \
+ qwaylanddecoration.h \
+ qwaylandeventthread.h \
+ qwaylandwindowmanagerintegration.h \
+ qwaylandinputcontext.h \
+ qwaylanddatadevice.h \
+
+contains(DEFINES, QT_WAYLAND_GL_SUPPORT) {
+ SOURCES += qwaylandglintegration.cpp
+ HEADERS += qwaylandglintegration.h
+}
+
diff --git a/src/client/qwaylandbuffer.h b/src/client/qwaylandbuffer.h
new file mode 100644
index 000000000..8d9ceaa8a
--- /dev/null
+++ b/src/client/qwaylandbuffer.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDBUFFER_H
+#define QWAYLANDBUFFER_H
+
+#include "qwaylandclientexport.h"
+
+#include <QtCore/QSize>
+#include <QtCore/QRect>
+
+#include <wayland-client.h>
+#include <wayland-client-protocol.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandBuffer {
+public:
+ QWaylandBuffer() { }
+ virtual ~QWaylandBuffer() { }
+ wl_buffer *buffer() {return mBuffer;}
+ virtual QSize size() const = 0;
+
+protected:
+ struct wl_buffer *mBuffer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDBUFFER_H
diff --git a/src/client/qwaylandclientexport.h b/src/client/qwaylandclientexport.h
new file mode 100644
index 000000000..d9d6d7f7c
--- /dev/null
+++ b/src/client/qwaylandclientexport.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDCLIENTEXPORT_H
+#define QWAYLANDCLIENTEXPORT_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_WAYLAND_CLIENT_EXPORT)
+# if defined(QT_SHARED)
+# define Q_WAYLAND_CLIENT_EXPORT Q_DECL_EXPORT
+# else
+# define Q_WAYLAND_CLIENT_EXPORT
+# endif
+#endif
+
+QT_END_NAMESPACE
+
+#endif //QWAYLANDCLIENTEXPORT_H
+
diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp
new file mode 100644
index 000000000..838f6d231
--- /dev/null
+++ b/src/client/qwaylandclipboard.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandclipboard.h"
+#include "qwaylanddisplay.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylanddataoffer.h"
+#include "qwaylanddatasource.h"
+#include "qwaylanddatadevice.h"
+
+QT_BEGIN_NAMESPACE
+
+QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display)
+ : mDisplay(display)
+{
+}
+
+QWaylandClipboard::~QWaylandClipboard()
+{
+}
+
+QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return 0;
+
+ QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
+ if (!inputDevice || !inputDevice->dataDevice())
+ return 0;
+
+ QWaylandDataSource *source = inputDevice->dataDevice()->selectionSource();
+ if (source) {
+ return source->mimeData();
+ }
+
+ if (inputDevice->dataDevice()->selectionOffer())
+ return inputDevice->dataDevice()->selectionOffer()->mimeData();
+
+ return 0;
+}
+
+void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return;
+
+ QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
+ if (!inputDevice || !inputDevice->dataDevice())
+ return;
+
+ inputDevice->dataDevice()->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : 0);
+
+ emitChanged(mode);
+}
+
+bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const
+{
+ return mode == QClipboard::Clipboard;
+}
+
+bool QWaylandClipboard::ownsMode(QClipboard::Mode mode) const
+{
+ if (mode != QClipboard::Clipboard)
+ return false;
+
+ QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
+ if (!inputDevice || !inputDevice->dataDevice())
+ return false;
+
+ return inputDevice->dataDevice()->selectionSource() != 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandclipboard.h b/src/client/qwaylandclipboard.h
new file mode 100644
index 000000000..692a31255
--- /dev/null
+++ b/src/client/qwaylandclipboard.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDCLIPBOARD_H
+#define QWAYLANDCLIPBOARD_H
+
+#include <qpa/qplatformclipboard.h>
+#include <QtCore/QVariant>
+
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandClipboard : public QPlatformClipboard
+{
+public:
+ QWaylandClipboard(QWaylandDisplay *display);
+
+ ~QWaylandClipboard();
+
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+
+private:
+ QWaylandDisplay *mDisplay;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDCLIPBOARD_H
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
new file mode 100644
index 000000000..05ab6d496
--- /dev/null
+++ b/src/client/qwaylandcursor.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandcursor.h"
+
+#include "qwaylanddisplay.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylandscreen.h"
+#include "qwaylandshmbackingstore.h"
+
+#include <QtGui/QImageReader>
+#include <QDebug>
+
+#include <wayland-cursor.h>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandCursor::QWaylandCursor(QWaylandScreen *screen)
+ : mDisplay(screen->display())
+{
+ //TODO: Make wl_cursor_theme_load arguments configurable here
+ QByteArray cursorTheme = qgetenv("XCURSOR_THEME");
+ if (cursorTheme.isEmpty())
+ cursorTheme = QByteArray("default");
+ QByteArray cursorSizeFromEnv = qgetenv("XCURSOR_SIZE");
+ bool hasCursorSize = false;
+ int cursorSize = cursorSizeFromEnv.toInt(&hasCursorSize);
+ if (!hasCursorSize || cursorSize <= 0)
+ cursorSize = 32;
+ mCursorTheme = wl_cursor_theme_load(cursorTheme, cursorSize, mDisplay->shm());
+ initCursorMap();
+}
+
+QWaylandCursor::~QWaylandCursor()
+{
+ wl_cursor_theme_destroy(mCursorTheme);
+}
+
+struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape)
+{
+ struct wl_cursor *waylandCursor = 0;
+
+ /* Hide cursor */
+ if (newShape == Qt::BlankCursor)
+ {
+ mDisplay->setCursor(NULL, NULL);
+ return NULL;
+ }
+
+ if (newShape < Qt::BitmapCursor) {
+ waylandCursor = requestCursor((WaylandCursor)newShape);
+ } else if (newShape == Qt::BitmapCursor) {
+ //TODO: Bitmap cursor logic
+ } else {
+ //TODO: Custom cursor logic (for resize arrows)
+ }
+
+ if (!waylandCursor) {
+ qDebug("Could not find cursor for shape %d", newShape);
+ return NULL;
+ }
+
+ struct wl_cursor_image *image = waylandCursor->images[0];
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer) {
+ qDebug("Could not find buffer for cursor");
+ return NULL;
+ }
+
+ return image;
+}
+
+void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window)
+{
+ Q_UNUSED(window)
+
+ const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
+
+ struct wl_cursor_image *image = cursorImage(newShape);
+ if (!image) {
+ return;
+ }
+
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ mDisplay->setCursor(buffer, image);
+}
+
+void QWaylandDisplay::setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image)
+{
+ /* Qt doesn't tell us which input device we should set the cursor
+ * for, so set it for all devices. */
+ for (int i = 0; i < mInputDevices.count(); i++) {
+ QWaylandInputDevice *inputDevice = mInputDevices.at(i);
+ inputDevice->setCursor(buffer, image);
+ }
+}
+
+QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
+{
+ return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
+}
+
+void QWaylandCursor::pointerEvent(const QMouseEvent &event)
+{
+ mLastPos = event.globalPos();
+}
+
+QPoint QWaylandCursor::pos() const
+{
+ return mLastPos;
+}
+
+void QWaylandCursor::setPos(const QPoint &pos)
+{
+ Q_UNUSED(pos);
+ qWarning() << "QWaylandCursor::setPos: not implemented";
+}
+
+wl_cursor *QWaylandCursor::requestCursor(WaylandCursor shape)
+{
+ struct wl_cursor *cursor = mCursors.value(shape, 0);
+
+ //If the cursor has not been loaded already, load it
+ if (!cursor) {
+ QList<QByteArray> cursorNames = mCursorNamesMap.values(shape);
+ foreach (QByteArray name, cursorNames) {
+ cursor = wl_cursor_theme_get_cursor(mCursorTheme, name.constData());
+ if (cursor) {
+ mCursors.insert(shape, cursor);
+ break;
+ }
+ }
+ }
+
+ //If there still no cursor for a shape, use the default cursor
+ if (!cursor && shape != ArrowCursor) {
+ cursor = requestCursor(ArrowCursor);
+ }
+
+ return cursor;
+}
+
+
+void QWaylandCursor::initCursorMap()
+{
+ //Fill the cursor name map will the table of xcursor names
+ mCursorNamesMap.insert(ArrowCursor, "left_ptr");
+ mCursorNamesMap.insert(ArrowCursor, "default");
+ mCursorNamesMap.insert(ArrowCursor, "top_left_arrow");
+ mCursorNamesMap.insert(ArrowCursor, "left_arrow");
+
+ mCursorNamesMap.insert(UpArrowCursor, "up_arrow");
+
+ mCursorNamesMap.insert(CrossCursor, "cross");
+
+ mCursorNamesMap.insert(WaitCursor, "wait");
+ mCursorNamesMap.insert(WaitCursor, "watch");
+ mCursorNamesMap.insert(WaitCursor, "0426c94ea35c87780ff01dc239897213");
+
+ mCursorNamesMap.insert(IBeamCursor, "ibeam");
+ mCursorNamesMap.insert(IBeamCursor, "text");
+ mCursorNamesMap.insert(IBeamCursor, "xterm");
+
+ mCursorNamesMap.insert(SizeVerCursor, "size_ver");
+ mCursorNamesMap.insert(SizeVerCursor, "ns-resize");
+ mCursorNamesMap.insert(SizeVerCursor, "v_double_arrow");
+ mCursorNamesMap.insert(SizeVerCursor, "00008160000006810000408080010102");
+
+ mCursorNamesMap.insert(SizeHorCursor, "size_hor");
+ mCursorNamesMap.insert(SizeHorCursor, "ew-resize");
+ mCursorNamesMap.insert(SizeHorCursor, "h_double_arrow");
+ mCursorNamesMap.insert(SizeHorCursor, "028006030e0e7ebffc7f7070c0600140");
+
+ mCursorNamesMap.insert(SizeBDiagCursor, "size_bdiag");
+ mCursorNamesMap.insert(SizeBDiagCursor, "nesw-resize");
+ mCursorNamesMap.insert(SizeBDiagCursor, "50585d75b494802d0151028115016902");
+ mCursorNamesMap.insert(SizeBDiagCursor, "fcf1c3c7cd4491d801f1e1c78f100000");
+
+ mCursorNamesMap.insert(SizeFDiagCursor, "size_fdiag");
+ mCursorNamesMap.insert(SizeFDiagCursor, "nwse-resize");
+ mCursorNamesMap.insert(SizeFDiagCursor, "38c5dff7c7b8962045400281044508d2");
+ mCursorNamesMap.insert(SizeFDiagCursor, "c7088f0f3e6c8088236ef8e1e3e70000");
+
+ mCursorNamesMap.insert(SizeAllCursor, "size_all");
+
+ mCursorNamesMap.insert(SplitVCursor, "split_v");
+ mCursorNamesMap.insert(SplitVCursor, "row-resize");
+ mCursorNamesMap.insert(SplitVCursor, "sb_v_double_arrow");
+ mCursorNamesMap.insert(SplitVCursor, "2870a09082c103050810ffdffffe0204");
+ mCursorNamesMap.insert(SplitVCursor, "c07385c7190e701020ff7ffffd08103c");
+
+ mCursorNamesMap.insert(SplitHCursor, "split_h");
+ mCursorNamesMap.insert(SplitHCursor, "col-resize");
+ mCursorNamesMap.insert(SplitHCursor, "sb_h_double_arrow");
+ mCursorNamesMap.insert(SplitHCursor, "043a9f68147c53184671403ffa811cc5");
+ mCursorNamesMap.insert(SplitHCursor, "14fef782d02440884392942c11205230");
+
+ mCursorNamesMap.insert(PointingHandCursor, "pointing_hand");
+ mCursorNamesMap.insert(PointingHandCursor, "pointer");
+ mCursorNamesMap.insert(PointingHandCursor, "hand1");
+ mCursorNamesMap.insert(PointingHandCursor, "e29285e634086352946a0e7090d73106");
+
+ mCursorNamesMap.insert(ForbiddenCursor, "forbidden");
+ mCursorNamesMap.insert(ForbiddenCursor, "not-allowed");
+ mCursorNamesMap.insert(ForbiddenCursor, "crossed_circle");
+ mCursorNamesMap.insert(ForbiddenCursor, "circle");
+ mCursorNamesMap.insert(ForbiddenCursor, "03b6e0fcb3499374a867c041f52298f0");
+
+ mCursorNamesMap.insert(WhatsThisCursor, "whats_this");
+ mCursorNamesMap.insert(WhatsThisCursor, "help");
+ mCursorNamesMap.insert(WhatsThisCursor, "question_arrow");
+ mCursorNamesMap.insert(WhatsThisCursor, "5c6cd98b3f3ebcb1f9c7f1c204630408");
+ mCursorNamesMap.insert(WhatsThisCursor, "d9ce0ab605698f320427677b458ad60b");
+
+ mCursorNamesMap.insert(BusyCursor, "left_ptr_watch");
+ mCursorNamesMap.insert(BusyCursor, "half-busy");
+ mCursorNamesMap.insert(BusyCursor, "progress");
+ mCursorNamesMap.insert(BusyCursor, "00000000000000020006000e7e9ffc3f");
+ mCursorNamesMap.insert(BusyCursor, "08e8e1c95fe2fc01f976f1e063a24ccd");
+
+ mCursorNamesMap.insert(OpenHandCursor, "openhand");
+ mCursorNamesMap.insert(OpenHandCursor, "fleur");
+ mCursorNamesMap.insert(OpenHandCursor, "5aca4d189052212118709018842178c0");
+ mCursorNamesMap.insert(OpenHandCursor, "9d800788f1b08800ae810202380a0822");
+
+ mCursorNamesMap.insert(ClosedHandCursor, "closedhand");
+ mCursorNamesMap.insert(ClosedHandCursor, "grabbing");
+ mCursorNamesMap.insert(ClosedHandCursor, "208530c400c041818281048008011002");
+
+ mCursorNamesMap.insert(DragCopyCursor, "dnd-copy");
+ mCursorNamesMap.insert(DragCopyCursor, "copy");
+
+ mCursorNamesMap.insert(DragMoveCursor, "dnd-move");
+ mCursorNamesMap.insert(DragMoveCursor, "move");
+
+ mCursorNamesMap.insert(DragLinkCursor, "dnd-link");
+ mCursorNamesMap.insert(DragLinkCursor, "link");
+
+ mCursorNamesMap.insert(ResizeNorthCursor, "n-resize");
+ mCursorNamesMap.insert(ResizeNorthCursor, "top_side");
+
+ mCursorNamesMap.insert(ResizeSouthCursor, "s-resize");
+ mCursorNamesMap.insert(ResizeSouthCursor, "bottom_side");
+
+ mCursorNamesMap.insert(ResizeEastCursor, "e-resize");
+ mCursorNamesMap.insert(ResizeEastCursor, "right_side");
+
+ mCursorNamesMap.insert(ResizeWestCursor, "w-resize");
+ mCursorNamesMap.insert(ResizeWestCursor, "left_side");
+
+ mCursorNamesMap.insert(ResizeNorthWestCursor, "nw-resize");
+ mCursorNamesMap.insert(ResizeNorthWestCursor, "top_left_corner");
+
+ mCursorNamesMap.insert(ResizeSouthEastCursor, "se-resize");
+ mCursorNamesMap.insert(ResizeSouthEastCursor, "bottom_right_corner");
+
+ mCursorNamesMap.insert(ResizeNorthEastCursor, "ne-resize");
+ mCursorNamesMap.insert(ResizeNorthEastCursor, "top_right_corner");
+
+ mCursorNamesMap.insert(ResizeSouthWestCursor, "sw-resize");
+ mCursorNamesMap.insert(ResizeSouthWestCursor, "bottom_left_corner");
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandcursor.h b/src/client/qwaylandcursor.h
new file mode 100644
index 000000000..894d322a6
--- /dev/null
+++ b/src/client/qwaylandcursor.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDCURSOR_H
+#define QWAYLANDCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+#include <QtCore/QMap>
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+struct wl_cursor;
+struct wl_cursor_image;
+struct wl_cursor_theme;
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandScreen;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandCursor : public QPlatformCursor
+{
+public:
+ QWaylandCursor(QWaylandScreen *screen);
+ ~QWaylandCursor();
+
+ void changeCursor(QCursor *cursor, QWindow *window);
+ void pointerEvent(const QMouseEvent &event);
+ QPoint pos() const;
+ void setPos(const QPoint &pos);
+
+ struct wl_cursor_image *cursorImage(Qt::CursorShape shape);
+
+private:
+ enum WaylandCursor {
+ ArrowCursor = Qt::ArrowCursor,
+ UpArrowCursor,
+ CrossCursor,
+ WaitCursor,
+ IBeamCursor,
+ SizeVerCursor,
+ SizeHorCursor,
+ SizeBDiagCursor,
+ SizeFDiagCursor,
+ SizeAllCursor,
+ BlankCursor,
+ SplitVCursor,
+ SplitHCursor,
+ PointingHandCursor,
+ ForbiddenCursor,
+ WhatsThisCursor,
+ BusyCursor,
+ OpenHandCursor,
+ ClosedHandCursor,
+ DragCopyCursor,
+ DragMoveCursor,
+ DragLinkCursor,
+ ResizeNorthCursor = Qt::CustomCursor + 1,
+ ResizeSouthCursor,
+ ResizeEastCursor,
+ ResizeWestCursor,
+ ResizeNorthWestCursor,
+ ResizeSouthEastCursor,
+ ResizeNorthEastCursor,
+ ResizeSouthWestCursor
+ };
+
+ struct wl_cursor* requestCursor(WaylandCursor shape);
+ void initCursorMap();
+ QWaylandDisplay *mDisplay;
+ struct wl_cursor_theme *mCursorTheme;
+ QPoint mLastPos;
+ QMap<WaylandCursor, wl_cursor *> mCursors;
+ QMultiMap<WaylandCursor, QByteArray> mCursorNamesMap;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDCURSOR_H
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
new file mode 100644
index 000000000..2a70a338c
--- /dev/null
+++ b/src/client/qwaylanddatadevice.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddatadevice.h"
+
+#include "qwaylanddatadevicemanager.h"
+#include "qwaylanddataoffer.h"
+#include "qwaylanddatasource.h"
+#include "qwaylanddnd.h"
+#include "qwaylandinputdevice.h"
+
+#include <QtCore/QMimeData>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatformclipboard.h>
+#include <qpa/qplatformdrag.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QDebug>
+
+QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
+ : QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
+ , m_display(manager->display())
+ , m_enterSerial(0)
+ , m_dragWindow(0)
+ , m_dragPoint()
+ , m_dragOffer()
+ , m_selectionOffer()
+{
+}
+
+QWaylandDataDevice::~QWaylandDataDevice()
+{
+}
+
+QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
+{
+ return m_selectionOffer.data();
+}
+
+QWaylandDataSource *QWaylandDataDevice::selectionSource() const
+{
+ return m_selectionSource.data();
+}
+
+void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source)
+{
+ m_selectionSource.reset(source);
+ set_selection(source ? source->object() : 0, 0 /* TODO m_display->serial() */);
+}
+
+QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
+{
+ return m_dragOffer.data();
+}
+
+void QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
+{
+ m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
+
+ QWaylandWindow *origin = m_display->currentInputDevice()->pointerFocus();
+
+ start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
+}
+
+void QWaylandDataDevice::cancelDrag()
+{
+ m_dragSource.reset();
+}
+
+void QWaylandDataDevice::data_device_data_offer(struct ::wl_data_offer *id)
+{
+ QWaylandDataOffer *offer = new QWaylandDataOffer(m_display, id);
+}
+
+void QWaylandDataDevice::data_device_drop()
+{
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+
+ qDebug() << Q_FUNC_INFO << drag << m_dragOffer.data();
+
+ QMimeData *dragData;
+ Qt::DropActions supportedActions;
+ if (drag) {
+ dragData = drag->mimeData();
+ supportedActions = drag->supportedActions();
+ } else if (m_dragOffer) {
+ dragData = m_dragOffer->mimeData();
+ supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ } else {
+ return;
+ }
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions);
+
+ if (drag) {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
+ }
+}
+
+void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, wl_fixed_t x, wl_fixed_t y, wl_data_offer *id)
+{
+ m_enterSerial = serial;
+ m_dragWindow = QWaylandWindow::fromWlSurface(surface)->window();
+ m_dragPoint = QPoint(wl_fixed_to_int(x), wl_fixed_to_int(y));
+
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+
+ QMimeData *dragData;
+ Qt::DropActions supportedActions;
+ if (drag) {
+ dragData = drag->mimeData();
+ supportedActions = drag->supportedActions();
+ } else {
+ m_dragOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
+ if (m_dragOffer) {
+ dragData = m_dragOffer->mimeData();
+ supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ }
+ }
+
+ const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+
+ if (drag) {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
+ } else {
+ if (response.isAccepted()) {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
+ } else {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, 0);
+ }
+ }
+}
+
+void QWaylandDataDevice::data_device_leave()
+{
+ QWindowSystemInterface::handleDrag(m_dragWindow, 0, QPoint(), Qt::IgnoreAction);
+
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+ if (!drag) {
+ m_dragOffer.reset();
+ }
+}
+
+void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixed_t y)
+{
+ Q_UNUSED(time);
+
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+
+ if (!drag && !m_dragOffer)
+ return;
+
+ m_dragPoint = QPoint(wl_fixed_to_int(x), wl_fixed_to_int(y));
+
+ QMimeData *dragData;
+ Qt::DropActions supportedActions;
+ if (drag) {
+ dragData = drag->mimeData();
+ supportedActions = drag->supportedActions();
+ } else {
+ dragData = m_dragOffer->mimeData();
+ supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ }
+
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+
+ if (drag) {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
+ } else {
+ if (response.isAccepted()) {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
+ } else {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, 0);
+ }
+ }
+}
+
+void QWaylandDataDevice::data_device_selection(wl_data_offer *id)
+{
+ if (id)
+ m_selectionOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
+ else
+ m_selectionOffer.reset();
+
+ QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
+}
+
+void QWaylandDataDevice::selectionSourceCancelled()
+{
+ m_selectionSource.reset();
+ QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
+}
+
+void QWaylandDataDevice::dragSourceCancelled()
+{
+ m_dragSource.reset();
+
+}
+
+void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType)
+{
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType);
+}
diff --git a/src/client/qwaylanddatadevice.h b/src/client/qwaylanddatadevice.h
new file mode 100644
index 000000000..e258d8776
--- /dev/null
+++ b/src/client/qwaylanddatadevice.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDATADEVICE_H
+#define QWAYLANDDATADEVICE_H
+
+#include "qwaylanddisplay.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMimeData;
+class QWaylandDataDeviceManager;
+class QWaylandDataOffer;
+class QWaylandDataSource;
+class QWindow;
+
+class QWaylandDataDevice : public QObject, public QtWayland::wl_data_device
+{
+ Q_OBJECT
+public:
+ QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice);
+ ~QWaylandDataDevice();
+
+ QWaylandDataOffer *selectionOffer() const;
+ QWaylandDataSource *selectionSource() const;
+ void setSelectionSource(QWaylandDataSource *source);
+
+ QWaylandDataOffer *dragOffer() const;
+ void startDrag(QMimeData *mimeData, QWaylandWindow *icon);
+ void cancelDrag();
+
+protected:
+ void data_device_data_offer(struct ::wl_data_offer *id) Q_DECL_OVERRIDE;
+ void data_device_drop() Q_DECL_OVERRIDE;
+ void data_device_enter(uint32_t serial, struct ::wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct ::wl_data_offer *id) Q_DECL_OVERRIDE;
+ void data_device_leave() Q_DECL_OVERRIDE;
+ void data_device_motion(uint32_t time, wl_fixed_t x, wl_fixed_t y) Q_DECL_OVERRIDE;
+ void data_device_selection(struct ::wl_data_offer *id) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void selectionSourceCancelled();
+ void dragSourceCancelled();
+ void dragSourceTargetChanged(const QString &mimeType);
+
+private:
+ QWaylandDisplay *m_display;
+
+ uint32_t m_enterSerial;
+ QWindow *m_dragWindow;
+ QPoint m_dragPoint;
+ QScopedPointer<QWaylandDataOffer> m_dragOffer;
+ QScopedPointer<QWaylandDataOffer> m_selectionOffer;
+ QScopedPointer<QWaylandDataSource> m_selectionSource;
+
+ QScopedPointer<QWaylandDataSource> m_dragSource;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDATADEVICE_H
diff --git a/src/client/qwaylanddatadevicemanager.cpp b/src/client/qwaylanddatadevicemanager.cpp
new file mode 100644
index 000000000..4a96dbce3
--- /dev/null
+++ b/src/client/qwaylanddatadevicemanager.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddatadevicemanager.h"
+
+#include "qwaylandinputdevice.h"
+#include "qwaylanddatadevice.h"
+#include "qwaylanddataoffer.h"
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
+ : wl_data_device_manager(display->wl_registry(), id)
+ , m_display(display)
+{
+ // Create transfer devices for all input devices.
+ // ### This only works if we get the global before all devices and is surely wrong when hotplugging.
+ QList<QWaylandInputDevice *> inputDevices = m_display->inputDevices();
+ for (int i = 0; i < inputDevices.size();i++) {
+ inputDevices.at(i)->setDataDevice(getDataDevice(inputDevices.at(i)));
+ }
+}
+
+QWaylandDataDeviceManager::~QWaylandDataDeviceManager()
+{
+ wl_data_device_manager_destroy(object());
+}
+
+QWaylandDataDevice *QWaylandDataDeviceManager::getDataDevice(QWaylandInputDevice *inputDevice)
+{
+ return new QWaylandDataDevice(this, inputDevice);
+}
+
+QWaylandDisplay *QWaylandDataDeviceManager::display() const
+{
+ return m_display;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylanddatadevicemanager.h b/src/client/qwaylanddatadevicemanager.h
new file mode 100644
index 000000000..6b3ad177c
--- /dev/null
+++ b/src/client/qwaylanddatadevicemanager.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDATADEVICEMANAGER_H
+#define QWAYLANDDATADEVICEMANAGER_H
+
+#include "qwaylanddisplay.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDataDevice;
+class QWaylandDataSource;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
+{
+public:
+ QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id);
+ ~QWaylandDataDeviceManager();
+
+ QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice);
+
+ QWaylandDisplay *display() const;
+
+private:
+ struct wl_data_device_manager *m_data_device_manager;
+ QWaylandDisplay *m_display;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDATADEVICEMANAGER_H
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
new file mode 100644
index 000000000..e237d0b9a
--- /dev/null
+++ b/src/client/qwaylanddataoffer.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddataoffer.h"
+#include "qwaylanddatadevicemanager.h"
+
+#include <QtCore/private/qcore_unix_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformclipboard.h>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
+ : QtWayland::wl_data_offer(offer)
+ , m_mimeData(new QWaylandMimeData(this, display))
+{
+}
+
+QWaylandDataOffer::~QWaylandDataOffer()
+{
+ destroy();
+}
+
+
+QString QWaylandDataOffer::firstFormat() const
+{
+ if (m_mimeData->formats().isEmpty())
+ return QString();
+
+ return m_mimeData->formats().first();
+}
+
+QMimeData *QWaylandDataOffer::mimeData()
+{
+ return m_mimeData.data();
+}
+
+void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
+{
+ m_mimeData->appendFormat(mime_type);
+}
+
+QWaylandMimeData::QWaylandMimeData(QWaylandDataOffer *dataOffer, QWaylandDisplay *display)
+ : QInternalMimeData()
+ , m_dataOffer(dataOffer)
+ , m_display(display)
+ , m_offered_mime_types()
+{
+}
+
+QWaylandMimeData::~QWaylandMimeData()
+{
+}
+
+void QWaylandMimeData::appendFormat(const QString &mimeType)
+{
+ m_offered_mime_types.append(mimeType);
+}
+
+bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
+{
+ return m_offered_mime_types.contains(mimeType);
+}
+
+QStringList QWaylandMimeData::formats_sys() const
+{
+ return m_offered_mime_types;
+}
+
+QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ Q_UNUSED(type);
+
+ if (m_offered_mime_types.isEmpty())
+ return QVariant();
+
+ int pipefd[2];
+ if (qt_safe_pipe(pipefd, O_CLOEXEC) == -1) {
+ qWarning("QWaylandMimeData: pipe() failed");
+ return QVariant();
+ }
+
+ m_dataOffer->receive(mimeType, pipefd[1]);
+ close(pipefd[1]);
+
+// m_display->forceRoundTrip();
+
+ QByteArray content;
+ char buf[4096];
+ int n;
+ while ((n = QT_READ(pipefd[0], &buf, sizeof buf)) > 0) {
+ content.append(buf, n);
+ }
+ close(pipefd[0]);
+
+ return content;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylanddataoffer.h b/src/client/qwaylanddataoffer.h
new file mode 100644
index 000000000..7dc3baa38
--- /dev/null
+++ b/src/client/qwaylanddataoffer.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDATAOFFER_H
+#define QWAYLANDDATAOFFER_H
+
+#include "qwaylanddisplay.h"
+
+#include <QtGui/private/qdnd_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandMimeData;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDataOffer : public QtWayland::wl_data_offer
+{
+public:
+ explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
+ ~QWaylandDataOffer();
+
+ QString firstFormat() const;
+
+ QMimeData *mimeData();
+
+protected:
+ void data_offer_offer(const QString &mime_type) Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWaylandMimeData> m_mimeData;
+};
+
+
+class QWaylandMimeData : public QInternalMimeData {
+public:
+ explicit QWaylandMimeData(QWaylandDataOffer *dataOffer, QWaylandDisplay *display);
+ ~QWaylandMimeData();
+
+ void appendFormat(const QString &mimeType);
+
+protected:
+ bool hasFormat_sys(const QString &mimeType) const Q_DECL_OVERRIDE;
+ QStringList formats_sys() const Q_DECL_OVERRIDE;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const Q_DECL_OVERRIDE;
+
+private:
+ mutable QWaylandDataOffer *m_dataOffer;
+ QWaylandDisplay *m_display;
+ QStringList m_offered_mime_types;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/client/qwaylanddatasource.cpp b/src/client/qwaylanddatasource.cpp
new file mode 100644
index 000000000..ba4b68110
--- /dev/null
+++ b/src/client/qwaylanddatasource.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddatasource.h"
+#include "qwaylanddataoffer.h"
+#include "qwaylanddatadevicemanager.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylandmimehelper.h"
+
+#include <QtCore/QFile>
+
+#include <QtCore/QDebug>
+
+#include <unistd.h>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandDataSource::QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData)
+ : QtWayland::wl_data_source(dataDeviceManager->create_data_source())
+ , m_mime_data(mimeData)
+{
+ if (!mimeData)
+ return;
+ Q_FOREACH (const QString &format, mimeData->formats()) {
+ offer(format);
+ }
+}
+
+QWaylandDataSource::~QWaylandDataSource()
+{
+ destroy();
+}
+
+QMimeData * QWaylandDataSource::mimeData() const
+{
+ return m_mime_data;
+}
+
+void QWaylandDataSource::data_source_cancelled()
+{
+ Q_EMIT cancelled();
+}
+
+void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
+{
+ QByteArray content = QWaylandMimeHelper::getByteArray(m_mime_data, mime_type);
+ if (!content.isEmpty()) {
+ write(fd, content.constData(), content.size());
+ }
+ close(fd);
+}
+
+void QWaylandDataSource::data_source_target(const QString &mime_type)
+{
+ Q_EMIT targetChanged(mime_type);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylanddatasource.h b/src/client/qwaylanddatasource.h
new file mode 100644
index 000000000..670a8872f
--- /dev/null
+++ b/src/client/qwaylanddatasource.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDATASOURCE_H
+#define QWAYLANDDATASOURCE_H
+
+#include "qwaylanddisplay.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMimeData;
+class QWaylandDataDeviceManager;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDataSource : public QObject, public QtWayland::wl_data_source
+{
+ Q_OBJECT
+public:
+ QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData);
+ ~QWaylandDataSource();
+
+ QMimeData *mimeData() const;
+
+Q_SIGNALS:
+ void targetChanged(const QString &mime_type);
+ void cancelled();
+
+protected:
+ void data_source_cancelled() Q_DECL_OVERRIDE;
+ void data_source_send(const QString &mime_type, int32_t fd) Q_DECL_OVERRIDE;
+ void data_source_target(const QString &mime_type) Q_DECL_OVERRIDE;
+
+private:
+ QWaylandDisplay *m_display;
+ QMimeData *m_mime_data;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDATASOURCE_H
diff --git a/src/client/qwaylanddecoration.cpp b/src/client/qwaylanddecoration.cpp
new file mode 100644
index 000000000..74c01f93a
--- /dev/null
+++ b/src/client/qwaylanddecoration.cpp
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddecoration.h"
+
+#include "qwaylandwindow.h"
+#include "qwaylandshellsurface.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylandscreen.h"
+
+#include <QtGui/QGuiApplication>
+#include <QtGui/QImage>
+#include <QtGui/QCursor>
+#include <QtGui/QPainter>
+#include <QtGui/QPalette>
+#include <QtGui/QLinearGradient>
+
+QT_BEGIN_NAMESPACE
+
+#define BUTTON_SPACING 5
+
+#ifndef QT_NO_IMAGEFORMAT_XPM
+# define BUTTON_WIDTH 10
+
+static const char * const qt_close_xpm[] = {
+"10 10 2 1",
+"# c #000000",
+". c None",
+"..........",
+".##....##.",
+"..##..##..",
+"...####...",
+"....##....",
+"...####...",
+"..##..##..",
+".##....##.",
+"..........",
+".........."};
+
+static const char * const qt_maximize_xpm[]={
+"10 10 2 1",
+"# c #000000",
+". c None",
+"#########.",
+"#########.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#########.",
+".........."};
+
+static const char * const qt_minimize_xpm[] = {
+"10 10 2 1",
+"# c #000000",
+". c None",
+"..........",
+"..........",
+"..........",
+"..........",
+"..........",
+"..........",
+"..........",
+".#######..",
+".#######..",
+".........."};
+
+static const char * const qt_normalizeup_xpm[] = {
+"10 10 2 1",
+"# c #000000",
+". c None",
+"...######.",
+"...######.",
+"...#....#.",
+".######.#.",
+".######.#.",
+".#....###.",
+".#....#...",
+".#....#...",
+".######...",
+".........."};
+#else
+# define BUTTON_WIDTH 22
+#endif
+
+QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window)
+ : m_window(window->window())
+ , m_wayland_window(window)
+ , m_isDirty(true)
+ , m_decorationContentImage(0)
+ , m_margins(3,30,3,3)
+ , m_mouseButtons(Qt::NoButton)
+{
+ m_wayland_window->setDecoration(this);
+
+ QPalette palette;
+ m_foregroundColor = palette.color(QPalette::Active, QPalette::HighlightedText);
+ m_backgroundColor = palette.color(QPalette::Active, QPalette::Highlight);
+
+ QTextOption option(Qt::AlignHCenter | Qt::AlignVCenter);
+ option.setWrapMode(QTextOption::NoWrap);
+ m_windowTitle.setTextOption(option);
+}
+
+QWaylandDecoration::~QWaylandDecoration()
+{
+ m_wayland_window->setDecoration(0);
+}
+
+const QImage &QWaylandDecoration::contentImage()
+{
+ if (m_isDirty) {
+ //Update the decoration backingstore
+
+ m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied);
+ m_decorationContentImage.fill(Qt::transparent);
+ this->paint(&m_decorationContentImage);
+
+ m_isDirty = false;
+ }
+
+ return m_decorationContentImage;
+}
+
+void QWaylandDecoration::update()
+{
+ m_isDirty = true;
+}
+
+void QWaylandDecoration::paint(QPaintDevice *device)
+{
+ QRect surfaceRect(QPoint(), window()->frameGeometry().size());
+ QRect clips[] =
+ {
+ QRect(0, 0, surfaceRect.width(), margins().top()),
+ QRect(0, surfaceRect.height() - margins().bottom(), surfaceRect.width(), margins().bottom()),
+ QRect(0, margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()),
+ QRect(surfaceRect.width() - margins().right(), margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom())
+ };
+
+ QRect top = clips[0];
+
+ QPainter p(device);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ // Title bar
+ QPoint gradCenter(top.center()+ QPoint(30, 60));
+ QLinearGradient grad(top.topLeft(), top.bottomLeft());
+ QColor base(backgroundColor());
+ grad.setColorAt(0, base.lighter(100));
+ grad.setColorAt(1, base.darker(180));
+ QPainterPath roundedRect;
+ roundedRect.addRoundedRect(surfaceRect, 6, 6);
+ for (int i = 0; i < 4; ++i) {
+ p.save();
+ p.setClipRect(clips[i]);
+ p.fillPath(roundedRect, grad);
+ p.restore();
+ }
+
+ // Window icon
+ QIcon icon = m_wayland_window->windowIcon();
+ if (!icon.isNull()) {
+ QPixmap pixmap = icon.pixmap(QSize(128, 128));
+ QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ QRectF iconRect(0, 0, 22, 22);
+ p.drawPixmap(iconRect.adjusted(margins().left() + BUTTON_SPACING, 4,
+ margins().left() + BUTTON_SPACING, 4),
+ scaled, iconRect);
+ }
+
+ // Window title
+ QString windowTitleText = window()->title();
+ if (!windowTitleText.isEmpty()) {
+ if (m_windowTitle.text() != windowTitleText) {
+ m_windowTitle.setText(windowTitleText);
+ m_windowTitle.prepare();
+ }
+
+ QRect titleBar = top;
+ titleBar.setLeft(m_margins.left() + BUTTON_SPACING +
+ (icon.isNull() ? 0 : 22 + BUTTON_SPACING));
+ titleBar.setRight(minimizeButtonRect().left() - BUTTON_SPACING);
+
+ p.save();
+ p.setClipRect(titleBar);
+ p.setPen(m_foregroundColor);
+ QSizeF size = m_windowTitle.size();
+ int dx = (top.width() - size.width()) /2;
+ int dy = (top.height()- size.height()) /2;
+ QFont font = p.font();
+ font.setBold(true);
+ p.setFont(font);
+ QPoint windowTitlePoint(top.topLeft().x() + dx,
+ top.topLeft().y() + dy);
+ p.drawStaticText(windowTitlePoint,m_windowTitle);
+ p.restore();
+ }
+
+#ifndef QT_NO_IMAGEFORMAT_XPM
+ p.save();
+
+ // Close button
+ QPixmap closePixmap(qt_close_xpm);
+ p.drawPixmap(closeButtonRect(), closePixmap, closePixmap.rect());
+
+ // Maximize button
+ QPixmap maximizePixmap(m_wayland_window->isMaximized()
+ ? qt_normalizeup_xpm : qt_maximize_xpm);
+ p.drawPixmap(maximizeButtonRect(), maximizePixmap, maximizePixmap.rect());
+
+ // Minimize button
+ QPixmap minimizePixmap(qt_minimize_xpm);
+ p.drawPixmap(minimizeButtonRect(), minimizePixmap, minimizePixmap.rect());
+
+ p.restore();
+#else
+ // We don't need antialiasing from now on
+ p.setRenderHint(QPainter::Antialiasing, false);
+
+ QRectF rect;
+
+ // Default pen
+ QPen pen(m_foregroundColor);
+ p.setPen(pen);
+
+ // Close button
+ p.save();
+ rect = closeButtonRect();
+ p.drawRect(rect);
+ qreal crossSize = rect.height() / 2;
+ QPointF crossCenter(rect.center());
+ QRectF crossRect(crossCenter.x() - crossSize / 2, crossCenter.y() - crossSize / 2, crossSize, crossSize);
+ pen.setWidth(2);
+ p.setPen(pen);
+ p.drawLine(crossRect.topLeft(), crossRect.bottomRight());
+ p.drawLine(crossRect.bottomLeft(), crossRect.topRight());
+ p.restore();
+
+ // Maximize button
+ p.save();
+ p.drawRect(maximizeButtonRect());
+ rect = maximizeButtonRect().adjusted(5, 5, -5, -5);
+ if (m_wayland_window->isMaximized()) {
+ QRectF rect1 = rect.adjusted(rect.width() / 3, 0, 0, -rect.height() / 3);
+ QRectF rect2 = rect.adjusted(0, rect.height() / 4, -rect.width() / 4, 0);
+ p.drawRect(rect1);
+ p.drawRect(rect2);
+ } else {
+ p.setPen(m_foregroundColor);
+ p.drawRect(rect);
+ p.drawLine(rect.left(), rect.top() + 1, rect.right(), rect.top() + 1);
+ }
+ p.restore();
+
+ // Minimize button
+ p.save();
+ p.drawRect(minimizeButtonRect());
+ rect = minimizeButtonRect().adjusted(5, 5, -5, -5);
+ pen.setWidth(2);
+ p.setPen(pen);
+ p.drawLine(rect.bottomLeft(), rect.bottomRight());
+ p.restore();
+#endif
+}
+
+bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+
+{
+ Q_UNUSED(global);
+
+ // Figure out what area mouse is in
+ if (closeButtonRect().contains(local) && isLeftClicked(b)) {
+ QWindowSystemInterface::handleCloseEvent(m_window);
+ } else if (maximizeButtonRect().contains(local) && isLeftClicked(b)) {
+ m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized);
+ } else if (minimizeButtonRect().contains(local) && isLeftClicked(b)) {
+ m_window->setWindowState(Qt::WindowMinimized);
+ } else if (local.y() <= m_margins.top()) {
+ processMouseTop(inputDevice,local,b,mods);
+ } else if (local.y() > m_window->height() - m_margins.bottom() + m_margins.top()) {
+ processMouseBottom(inputDevice,local,b,mods);
+ } else if (local.x() <= m_margins.left()) {
+ processMouseLeft(inputDevice,local,b,mods);
+ } else if (local.x() > m_window->width() - m_margins.right() + m_margins.left()) {
+ processMouseRight(inputDevice,local,b,mods);
+ } else {
+ m_wayland_window->restoreMouseCursor(inputDevice);
+ m_mouseButtons = b;
+ return false;
+ }
+
+ m_mouseButtons = b;
+ return true;
+}
+
+bool QWaylandDecoration::inMouseButtonPressedState() const
+{
+ return m_mouseButtons & Qt::NoButton;
+}
+
+void QWaylandDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons)
+{
+ if (isLeftClicked(buttons)) {
+ m_wayland_window->shellSurface()->resize(inputDevice, resize);
+ inputDevice->removeMouseButtonFromState(Qt::LeftButton);
+ }
+}
+
+void QWaylandDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons)
+{
+ if (isLeftClicked(buttons)) {
+ m_wayland_window->shellSurface()->move(inputDevice);
+ inputDevice->removeMouseButtonFromState(Qt::LeftButton);
+ }
+}
+
+void QWaylandDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(mods);
+ if (local.y() <= m_margins.bottom()) {
+ if (local.x() <= margins().left()) {
+ //top left bit
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_LEFT,b);
+ } else if (local.x() > m_window->width() - margins().right()) {
+ //top right bit
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_RIGHT,b);
+ } else {
+ //top reszie bit
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP,b);
+ }
+ } else {
+ m_wayland_window->restoreMouseCursor(inputDevice);
+ startMove(inputDevice,b);
+ }
+
+}
+
+void QWaylandDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(mods);
+ if (local.x() <= margins().left()) {
+ //bottom left bit
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor);
+ startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT,b);
+ } else if (local.x() > m_window->width() - margins().right()) {
+ //bottom right bit
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor);
+ startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT,b);
+ } else {
+ //bottom bit
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_BOTTOM,b);
+ }
+}
+
+void QWaylandDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(local);
+ Q_UNUSED(mods);
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SplitHCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b);
+}
+
+void QWaylandDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(local);
+ Q_UNUSED(mods);
+ m_wayland_window->setMouseCursor(inputDevice, Qt::SplitHCursor);
+ startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b);
+}
+
+bool QWaylandDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState)
+{
+ if ((!m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton))
+ return true;
+ return false;
+}
+
+bool QWaylandDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState)
+{
+ if ((m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton))
+ return true;
+ return false;
+}
+
+QRectF QWaylandDecoration::closeButtonRect() const
+{
+ return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2,
+ (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
+}
+
+QRectF QWaylandDecoration::maximizeButtonRect() const
+{
+ return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3,
+ (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
+}
+
+QRectF QWaylandDecoration::minimizeButtonRect() const
+{
+ return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4,
+ (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
+}
+
+void QWaylandDecoration::setForegroundColor(const QColor &c)
+{
+ m_foregroundColor = c;
+}
+
+void QWaylandDecoration::setBackgroundColor(const QColor &c)
+{
+ m_backgroundColor = c;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylanddecoration.h b/src/client/qwaylanddecoration.h
new file mode 100644
index 000000000..f99723588
--- /dev/null
+++ b/src/client/qwaylanddecoration.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDECORATION_H
+#define QWAYLANDDECORATION_H
+
+#include <QtCore/QMargins>
+#include <QtCore/QPointF>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QCursor>
+#include <QtGui/QColor>
+#include <QtGui/QStaticText>
+#include <QtGui/QImage>
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+#include <wayland-client.h>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+class QPaintDevice;
+class QPainter;
+class QEvent;
+class QWaylandScreen;
+class QWaylandWindow;
+class QWaylandInputDevice;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDecoration
+{
+public:
+ QWaylandDecoration(QWaylandWindow *window);
+ virtual ~QWaylandDecoration();
+
+ void update();
+ bool isDirty() const;
+
+ bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ bool inMouseButtonPressedState() const;
+
+ void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons);
+ void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons);
+ QMargins margins() const;
+ QWindow *window() const;
+ QWaylandWindow *waylandWindow() const;
+ const QImage &contentImage();
+
+ void setForegroundColor(const QColor &c);
+ inline QColor foregroundColor() const;
+
+ void setBackgroundColor(const QColor &c);
+ inline QColor backgroundColor() const;
+
+protected:
+ void paint(QPaintDevice *device);
+
+private:
+ void processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+
+ bool isLeftClicked(Qt::MouseButtons newMouseButtonState);
+ bool isLeftReleased(Qt::MouseButtons newMouseButtonState);
+
+ QRectF closeButtonRect() const;
+ QRectF maximizeButtonRect() const;
+ QRectF minimizeButtonRect() const;
+
+ QWindow *m_window;
+ QWaylandWindow *m_wayland_window;
+
+ bool m_isDirty;
+ QImage m_decorationContentImage;
+
+ QMargins m_margins;
+ Qt::MouseButtons m_mouseButtons;
+
+ QColor m_foregroundColor;
+ QColor m_backgroundColor;
+ QStaticText m_windowTitle;
+};
+
+inline bool QWaylandDecoration::isDirty() const
+{
+ return m_isDirty;
+}
+
+inline QMargins QWaylandDecoration::margins() const
+{
+ return m_margins;
+}
+
+inline QWindow *QWaylandDecoration::window() const
+{
+ return m_window;
+}
+
+inline QWaylandWindow *QWaylandDecoration::waylandWindow() const
+{
+ return m_wayland_window;
+}
+
+inline QColor QWaylandDecoration::foregroundColor() const
+{
+ return m_foregroundColor;
+}
+
+inline QColor QWaylandDecoration::backgroundColor() const
+{
+ return m_backgroundColor;
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDECORATION_H
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
new file mode 100644
index 000000000..d9a8b4528
--- /dev/null
+++ b/src/client/qwaylanddisplay.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddisplay.h"
+
+#include "qwaylandeventthread.h"
+#include "qwaylandwindow.h"
+#include "qwaylandscreen.h"
+#include "qwaylandcursor.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylandclipboard.h"
+#include "qwaylanddatadevicemanager.h"
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+#include "qwaylandglintegration.h"
+#endif
+
+#include "qwaylandwindowmanagerintegration.h"
+
+#include "qwaylandextendedoutput.h"
+#include "qwaylandextendedsurface.h"
+#include "qwaylandsubsurface.h"
+#include "qwaylandtouch.h"
+#include "qwaylandqtkey.h"
+
+#include <QtWaylandClient/private/qwayland-text.h>
+
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <QtCore/QDebug>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+struct wl_surface *QWaylandDisplay::createSurface(void *handle)
+{
+ struct wl_surface *surface = mCompositor.create_surface();
+ wl_surface_set_user_data(surface, handle);
+ return surface;
+}
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+QWaylandGLIntegration * QWaylandDisplay::eglIntegration()
+{
+ return mEglIntegration;
+}
+#endif
+
+QWaylandWindowManagerIntegration *QWaylandDisplay::windowManagerIntegration()
+{
+ return mWindowManagerIntegration;
+}
+
+QWaylandInputDevice *QWaylandDisplay::lastKeyboardFocusInputDevice() const
+{
+ return mLastKeyboardFocusInputDevice;
+}
+
+void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *device)
+{
+ mLastKeyboardFocusInputDevice = device;
+}
+
+static QWaylandDisplay *display = 0;
+
+QWaylandDisplay::QWaylandDisplay()
+ : mLastKeyboardFocusInputDevice(0)
+ , mDndSelectionHandler(0)
+ , mWindowExtension(0)
+ , mSubSurfaceExtension(0)
+ , mOutputExtension(0)
+ , mTouchExtension(0)
+ , mQtKeyExtension(0)
+ , mTextInputManager(0)
+{
+ display = this;
+ qRegisterMetaType<uint32_t>("uint32_t");
+
+ mEventThreadObject = new QWaylandEventThread(0);
+ mEventThread = new QThread(this);
+ mEventThreadObject->moveToThread(mEventThread);
+ mEventThread->start();
+
+ mEventThreadObject->displayConnect();
+ mDisplay = mEventThreadObject->display(); //blocks until display is available
+
+ //Create a new even queue for the QtGui thread
+ mEventQueue = wl_display_create_queue(mDisplay);
+
+ struct ::wl_registry *registry = wl_display_get_registry(mDisplay);
+ wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue);
+
+ init(registry);
+
+ connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests()));
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+ //mEglIntegration = QWaylandGLIntegration::createGLIntegration(this);
+#endif
+
+ mWindowManagerIntegration = new QWaylandWindowManagerIntegration(this);
+
+ blockingReadEvents();
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+ mEglIntegration->initialize();
+
+ flushRequests();
+ while (mEglIntegration->waitingForEvents())
+ blockingReadEvents();
+#endif
+
+ waitForScreens();
+}
+
+QWaylandDisplay::~QWaylandDisplay(void)
+{
+#ifdef QT_WAYLAND_GL_SUPPORT
+ delete mEglIntegration;
+#endif
+ mEventThread->quit();
+ mEventThread->wait();
+ delete mEventThreadObject;
+}
+
+void QWaylandDisplay::flushRequests()
+{
+ if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) == -1 && errno == EPIPE) {
+ qWarning("The Wayland connection broke. Did the Wayland compositor die?");
+ ::exit(1);
+ }
+ wl_display_flush(mDisplay);
+}
+
+void QWaylandDisplay::blockingReadEvents()
+{
+ if (wl_display_dispatch_queue(mDisplay, mEventQueue) == -1 && errno == EPIPE) {
+ qWarning("The Wayland connection broke. Did the Wayland compositor die?");
+ ::exit(1);
+ }
+}
+
+QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
+{
+ for (int i = 0; i < mScreens.size(); ++i) {
+ QWaylandScreen *screen = static_cast<QWaylandScreen *>(mScreens.at(i));
+ if (screen->output() == output)
+ return screen;
+ }
+ return 0;
+}
+
+void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
+{
+ Listener l = { listener, data };
+ mRegistryListeners.append(l);
+}
+
+void QWaylandDisplay::waitForScreens()
+{
+ flushRequests();
+
+ while (true) {
+ bool screensReady = !mScreens.isEmpty();
+
+ for (int ii = 0; screensReady && ii < mScreens.count(); ++ii) {
+ if (mScreens.at(ii)->geometry() == QRect(0, 0, 0, 0))
+ screensReady = false;
+ }
+
+ if (!screensReady)
+ blockingReadEvents();
+ else
+ return;
+ }
+}
+
+void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+
+ struct ::wl_registry *registry = object();
+
+ if (interface == "wl_output") {
+ mScreens.append(new QWaylandScreen(this, id));
+ } else if (interface == "wl_compositor") {
+ mCompositor.init(registry, id);
+ } else if (interface == "wl_shm") {
+ mShm = static_cast<struct wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface,1));
+ } else if (interface == "wl_shell"){
+ mShell = new QtWayland::wl_shell(registry, id);
+ } else if (interface == "wl_seat") {
+ QWaylandInputDevice *inputDevice = new QWaylandInputDevice(this, id);
+ mInputDevices.append(inputDevice);
+ } else if (interface == "wl_data_device_manager") {
+ mDndSelectionHandler = new QWaylandDataDeviceManager(this, id);
+ } else if (interface == "qt_output_extension") {
+ mOutputExtension = new QtWayland::qt_output_extension(registry, id);
+ foreach (QPlatformScreen *screen, screens())
+ static_cast<QWaylandScreen *>(screen)->createExtendedOutput();
+ } else if (interface == "qt_surface_extension") {
+ mWindowExtension = new QtWayland::qt_surface_extension(registry, id);
+ } else if (interface == "qt_sub_surface_extension") {
+ mSubSurfaceExtension = new QtWayland::qt_sub_surface_extension(registry, id);
+ } else if (interface == "qt_touch_extension") {
+ mTouchExtension = new QWaylandTouchExtension(this, id);
+ } else if (interface == "qt_key_extension") {
+ mQtKeyExtension = new QWaylandQtKeyExtension(this, id);
+ } else if (interface == "wl_text_input_manager") {
+ mTextInputManager = new QtWayland::wl_text_input_manager(registry, id);
+ }
+
+ foreach (Listener l, mRegistryListeners)
+ (*l.listener)(l.data, registry, id, interface, version);
+}
+
+uint32_t QWaylandDisplay::currentTimeMillisec()
+{
+ //### we throw away the time information
+ struct timeval tv;
+ int ret = gettimeofday(&tv, 0);
+ if (ret == 0)
+ return tv.tv_sec*1000 + tv.tv_usec/1000;
+ return 0;
+}
+
+void QWaylandDisplay::forceRoundTrip()
+{
+ wl_display_roundtrip(mDisplay);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylanddisplay.h b/src/client/qwaylanddisplay.h
new file mode 100644
index 000000000..451043507
--- /dev/null
+++ b/src/client/qwaylanddisplay.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDISPLAY_H
+#define QWAYLANDDISPLAY_H
+
+#include <QtCore/QObject>
+#include <QtCore/QRect>
+
+#include <QtCore/QWaitCondition>
+
+#include <wayland-client.h>
+#include <QtWaylandClient/private/qwayland-wayland.h>
+
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+struct wl_cursor_image;
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractEventDispatcher;
+class QWaylandInputDevice;
+class QSocketNotifier;
+class QWaylandBuffer;
+class QPlatformScreen;
+class QWaylandScreen;
+class QWaylandGLIntegration;
+class QWaylandWindowManagerIntegration;
+class QWaylandDataDeviceManager;
+class QWaylandTouchExtension;
+class QWaylandQtKeyExtension;
+class QWaylandWindow;
+class QWaylandEventThread;
+
+namespace QtWayland {
+ class qt_output_extension;
+ class qt_shell;
+ class qt_sub_surface_extension;
+ class qt_surface_extension;
+ class wl_text_input_manager;
+}
+
+typedef void (*RegistryListener)(void *data,
+ struct wl_registry *registry,
+ uint32_t id,
+ const QString &interface,
+ uint32_t version);
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
+ Q_OBJECT
+
+public:
+ QWaylandDisplay(void);
+ ~QWaylandDisplay(void);
+
+ QList<QPlatformScreen *> screens() const { return mScreens; }
+
+ QWaylandScreen *screenForOutput(struct wl_output *output) const;
+
+ struct wl_surface *createSurface(void *handle);
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+ QWaylandGLIntegration *eglIntegration();
+#endif
+
+ QWaylandWindowManagerIntegration *windowManagerIntegration();
+
+ void setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image);
+
+ struct wl_display *wl_display() const { return mDisplay; }
+ struct wl_event_queue *wl_event_queue() const { return mEventQueue; }
+ struct ::wl_registry *wl_registry() { return object(); }
+
+ const struct wl_compositor *wl_compositor() const { return mCompositor.object(); }
+ QtWayland::wl_compositor *compositor() { return &mCompositor; }
+
+ QtWayland::wl_shell *shell() { return mShell; }
+
+ QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
+ QWaylandInputDevice *defaultInputDevice() const;
+ QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
+
+ QWaylandInputDevice *lastKeyboardFocusInputDevice() const;
+ void setLastKeyboardFocusInputDevice(QWaylandInputDevice *device);
+
+ QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler; }
+
+ QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension; }
+ QtWayland::qt_sub_surface_extension *subSurfaceExtension() const { return mSubSurfaceExtension; }
+ QtWayland::qt_output_extension *outputExtension() const { return mOutputExtension; }
+ QWaylandTouchExtension *touchExtension() const { return mTouchExtension; }
+ QtWayland::wl_text_input_manager *textInputManager() const { return mTextInputManager; }
+
+ /* wl_registry_add_listener does not add but rather sets a listener, so this function is used
+ * to enable many listeners at once. */
+ void addRegistryListener(RegistryListener listener, void *data);
+
+ struct wl_shm *shm() const { return mShm; }
+
+ static uint32_t currentTimeMillisec();
+
+ void forceRoundTrip();
+
+public slots:
+ void blockingReadEvents();
+ void flushRequests();
+
+private:
+ void waitForScreens();
+
+ struct Listener {
+ RegistryListener listener;
+ void *data;
+ };
+
+ struct wl_display *mDisplay;
+ struct wl_event_queue *mEventQueue;
+ QtWayland::wl_compositor mCompositor;
+ struct wl_shm *mShm;
+ QThread *mEventThread;
+ QWaylandEventThread *mEventThreadObject;
+ QtWayland::wl_shell *mShell;
+ QList<QPlatformScreen *> mScreens;
+ QList<QWaylandInputDevice *> mInputDevices;
+ QList<Listener> mRegistryListeners;
+ QWaylandInputDevice *mLastKeyboardFocusInputDevice;
+ QWaylandDataDeviceManager *mDndSelectionHandler;
+ QtWayland::qt_surface_extension *mWindowExtension;
+ QtWayland::qt_sub_surface_extension *mSubSurfaceExtension;
+ QtWayland::qt_output_extension *mOutputExtension;
+ QWaylandTouchExtension *mTouchExtension;
+ QWaylandQtKeyExtension *mQtKeyExtension;
+ QWaylandWindowManagerIntegration *mWindowManagerIntegration;
+ QtWayland::wl_text_input_manager *mTextInputManager;
+
+ QSocketNotifier *mReadNotifier;
+ int mFd;
+ int mWritableNotificationFd;
+ bool mScreensInitialized;
+
+ void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE;
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+ QWaylandGLIntegration *mEglIntegration;
+#endif
+
+ static void shellHandleConfigure(void *data, struct wl_shell *shell,
+ uint32_t time, uint32_t edges,
+ struct wl_surface *surface,
+ int32_t width, int32_t height);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDISPLAY_H
diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp
new file mode 100644
index 000000000..635fd9678
--- /dev/null
+++ b/src/client/qwaylanddnd.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddnd.h"
+
+#include "qwaylanddatadevice.h"
+#include "qwaylanddatadevicemanager.h"
+#include "qwaylanddataoffer.h"
+#include "qwaylandinputdevice.h"
+
+#include <QtGui/private/qshapedpixmapdndwindow_p.h>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandDrag::QWaylandDrag(QWaylandDisplay *display)
+ : m_display(display)
+{
+}
+
+QWaylandDrag::~QWaylandDrag()
+{
+}
+
+QMimeData * QWaylandDrag::platformDropData()
+{
+ if (drag())
+ return drag()->mimeData();
+ return 0;
+}
+
+void QWaylandDrag::startDrag()
+{
+ if (!shapedPixmapWindow()) {
+ QBasicDrag::startDrag();
+ QBasicDrag::cancel();
+ }
+
+ QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
+ m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon);
+ QBasicDrag::startDrag();
+}
+
+void QWaylandDrag::cancel()
+{
+ QBasicDrag::cancel();
+
+ m_display->currentInputDevice()->dataDevice()->cancelDrag();
+}
+
+void QWaylandDrag::move(const QMouseEvent *me)
+{
+ Q_UNUSED(me);
+ // Do nothing
+}
+
+void QWaylandDrag::drop(const QMouseEvent *me)
+{
+ Q_UNUSED(me);
+ // Do nothing
+}
+
+void QWaylandDrag::endDrag()
+{
+ // Do nothing
+}
+
+void QWaylandDrag::updateTarget(const QString &mimeType)
+{
+ setCanDrop(!mimeType.isEmpty());
+
+ if (canDrop()) {
+ updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
+ } else {
+ updateCursor(Qt::IgnoreAction);
+ }
+}
+
+void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response)
+{
+ setCanDrop(response.isAccepted());
+
+ if (canDrop()) {
+ updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
+ } else {
+ updateCursor(Qt::IgnoreAction);
+ }
+}
+
+void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response)
+{
+ setExecutedDropAction(response.acceptedAction());
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
+ eventFilter(shapedPixmapWindow(), &event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylanddnd.h b/src/client/qwaylanddnd.h
new file mode 100644
index 000000000..f125dd2b2
--- /dev/null
+++ b/src/client/qwaylanddnd.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDND_H
+#define QWAYLANDDND_H
+
+#include <qpa/qplatformdrag.h>
+#include <QtGui/private/qsimpledrag_p.h>
+
+#include <QtGui/QDrag>
+#include <QtCore/QMimeData>
+#include "qwaylanddisplay.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDrag : public QBasicDrag
+{
+public:
+ QWaylandDrag(QWaylandDisplay *display);
+ ~QWaylandDrag();
+
+ QMimeData *platformDropData() Q_DECL_OVERRIDE;
+
+ void updateTarget(const QString &mimeType);
+ void setResponse(const QPlatformDragQtResponse &response);
+ void finishDrag(const QPlatformDropQtResponse &response);
+
+protected:
+ 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 endDrag() Q_DECL_OVERRIDE;
+
+
+private:
+ QWaylandDisplay *m_display;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDND_H
diff --git a/src/client/qwaylandeventthread.cpp b/src/client/qwaylandeventthread.cpp
new file mode 100644
index 000000000..3392d36c6
--- /dev/null
+++ b/src/client/qwaylandeventthread.cpp
@@ -0,0 +1,63 @@
+#include "qwaylandeventthread.h"
+#include <QtCore/QSocketNotifier>
+#include <QCoreApplication>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandEventThread::QWaylandEventThread(QObject *parent)
+ : QObject(parent)
+ , m_display(0)
+ , m_fileDescriptor(-1)
+ , m_readNotifier(0)
+ , m_displayLock(new QMutex)
+{
+}
+
+QWaylandEventThread::~QWaylandEventThread()
+{
+ delete m_displayLock;
+ wl_display_disconnect(m_display);
+}
+
+void QWaylandEventThread::displayConnect()
+{
+ m_displayLock->lock();
+ QMetaObject::invokeMethod(this, "waylandDisplayConnect", Qt::QueuedConnection);
+}
+
+void QWaylandEventThread::readWaylandEvents()
+{
+ if (wl_display_dispatch(m_display) == -1 && errno == EPIPE) {
+ qWarning("The Wayland connection broke. Did the Wayland compositor die?");
+ ::exit(1);
+ }
+ emit newEventsRead();
+}
+
+void QWaylandEventThread::waylandDisplayConnect()
+{
+ m_display = wl_display_connect(NULL);
+ if (m_display == NULL) {
+ qErrnoWarning(errno, "Failed to create display");
+ ::exit(1);
+ }
+ m_displayLock->unlock();
+
+ m_fileDescriptor = wl_display_get_fd(m_display);
+
+ m_readNotifier = new QSocketNotifier(m_fileDescriptor, QSocketNotifier::Read, this);
+ connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readWaylandEvents()));
+}
+
+wl_display *QWaylandEventThread::display() const
+{
+ QMutexLocker displayLock(m_displayLock);
+ return m_display;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandeventthread.h b/src/client/qwaylandeventthread.h
new file mode 100644
index 000000000..ba7e33e09
--- /dev/null
+++ b/src/client/qwaylandeventthread.h
@@ -0,0 +1,46 @@
+#ifndef QWAYLANDEVENTTHREAD_H
+#define QWAYLANDEVENTTHREAD_H
+
+#include <QObject>
+#include <QMutex>
+#include <wayland-client.h>
+
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandEventThread : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QWaylandEventThread(QObject *parent = 0);
+ ~QWaylandEventThread();
+
+ void displayConnect();
+
+ wl_display *display() const;
+
+private slots:
+ void readWaylandEvents();
+
+ void waylandDisplayConnect();
+
+signals:
+ void newEventsRead();
+
+private:
+
+ struct wl_display *m_display;
+ int m_fileDescriptor;
+
+ QSocketNotifier *m_readNotifier;
+
+ QMutex *m_displayLock;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDEVENTTHREAD_H
diff --git a/src/client/qwaylandextendedoutput.cpp b/src/client/qwaylandextendedoutput.cpp
new file mode 100644
index 000000000..d7c684be9
--- /dev/null
+++ b/src/client/qwaylandextendedoutput.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandextendedoutput.h"
+
+#include "qwaylandscreen.h"
+
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandExtendedOutput::QWaylandExtendedOutput(QWaylandScreen *screen, ::qt_extended_output *extended_output)
+ : QtWayland::qt_extended_output(extended_output)
+ , m_screen(screen)
+ , m_orientation(m_screen->orientation())
+{
+}
+
+Qt::ScreenOrientation QWaylandExtendedOutput::currentOrientation() const
+{
+ return m_orientation;
+}
+
+void QWaylandExtendedOutput::setOrientationUpdateMask(Qt::ScreenOrientations orientations)
+{
+ int mask = 0;
+ if (orientations & Qt::PortraitOrientation)
+ mask |= QT_EXTENDED_OUTPUT_ROTATION_PORTRAITORIENTATION;
+ if (orientations & Qt::LandscapeOrientation)
+ mask |= QT_EXTENDED_OUTPUT_ROTATION_LANDSCAPEORIENTATION;
+ if (orientations & Qt::InvertedPortraitOrientation)
+ mask |= QT_EXTENDED_OUTPUT_ROTATION_INVERTEDPORTRAITORIENTATION;
+ if (orientations & Qt::InvertedLandscapeOrientation)
+ mask |= QT_EXTENDED_OUTPUT_ROTATION_INVERTEDLANDSCAPEORIENTATION;
+ set_orientation_update_mask(mask);
+}
+
+void QWaylandExtendedOutput::extended_output_set_screen_rotation(int32_t rotation)
+{
+ switch (rotation) {
+ case QT_EXTENDED_OUTPUT_ROTATION_PORTRAITORIENTATION:
+ m_orientation = Qt::PortraitOrientation;
+ break;
+ case QT_EXTENDED_OUTPUT_ROTATION_LANDSCAPEORIENTATION:
+ m_orientation = Qt::LandscapeOrientation;
+ break;
+ case QT_EXTENDED_OUTPUT_ROTATION_INVERTEDPORTRAITORIENTATION:
+ m_orientation = Qt::InvertedPortraitOrientation;
+ break;
+ case QT_EXTENDED_OUTPUT_ROTATION_INVERTEDLANDSCAPEORIENTATION:
+ m_orientation = Qt::InvertedLandscapeOrientation;
+ break;
+ default:
+ m_orientation = Qt::PortraitOrientation;
+ break;
+ }
+ QWindowSystemInterface::handleScreenOrientationChange(m_screen->screen(), m_orientation);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandextendedoutput.h b/src/client/qwaylandextendedoutput.h
new file mode 100644
index 000000000..e311a9b4f
--- /dev/null
+++ b/src/client/qwaylandextendedoutput.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDEXTENDEDOUTPUT_H
+#define QWAYLANDEXTENDEDOUTPUT_H
+
+#include "qwaylanddisplay.h"
+#include <QtWaylandClient/private/qwayland-output-extension.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandExtendedOutput;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandExtendedOutput : public QtWayland::qt_extended_output
+{
+public:
+ QWaylandExtendedOutput(QWaylandScreen *screen, struct ::qt_extended_output *extended_output);
+
+ Qt::ScreenOrientation currentOrientation() const;
+ void setOrientationUpdateMask(Qt::ScreenOrientations mask);
+
+private:
+ void extended_output_set_screen_rotation(int32_t rotation) Q_DECL_OVERRIDE;
+
+ QWaylandScreen *m_screen;
+ Qt::ScreenOrientation m_orientation;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDEXTENDEDOUTPUT_H
diff --git a/src/client/qwaylandextendedsurface.cpp b/src/client/qwaylandextendedsurface.cpp
new file mode 100644
index 000000000..bfd2a1d0b
--- /dev/null
+++ b/src/client/qwaylandextendedsurface.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandextendedsurface.h"
+
+#include "qwaylandwindow.h"
+
+#include "wayland-client.h"
+
+#include "qwaylanddisplay.h"
+
+#include "qwaylandnativeinterface.h"
+
+#include <QtGui/QGuiApplication>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandExtendedSurface::QWaylandExtendedSurface(QWaylandWindow *window, struct ::qt_extended_surface *extended_surface)
+ : QtWayland::qt_extended_surface(extended_surface)
+ , m_window(window)
+{
+}
+
+QWaylandExtendedSurface::~QWaylandExtendedSurface()
+{
+ qt_extended_surface_destroy(object());
+}
+
+void QWaylandExtendedSurface::updateGenericProperty(const QString &name, const QVariant &value)
+{
+ QByteArray byteValue;
+ QDataStream ds(&byteValue, QIODevice::WriteOnly);
+ ds << value;
+
+ update_generic_property(name, byteValue);
+
+ m_properties.insert(name, value);
+ QWaylandNativeInterface *nativeInterface = static_cast<QWaylandNativeInterface *>(
+ QGuiApplication::platformNativeInterface());
+ nativeInterface->emitWindowPropertyChanged(m_window, name);
+}
+
+static int32_t waylandRotationFromScreenOrientation(Qt::ScreenOrientation orientation)
+{
+ switch (orientation) {
+ case Qt::PortraitOrientation: return QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION;
+ case Qt::InvertedPortraitOrientation: return QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION;
+ case Qt::LandscapeOrientation: return QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION;
+ case Qt::InvertedLandscapeOrientation: return QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION;
+ default: return QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION;
+ }
+}
+
+void QWaylandExtendedSurface::setContentOrientation(Qt::ScreenOrientation orientation)
+{
+ set_content_orientation(waylandRotationFromScreenOrientation(orientation));
+}
+
+QVariantMap QWaylandExtendedSurface::properties() const
+{
+ return m_properties;
+}
+
+QVariant QWaylandExtendedSurface::property(const QString &name)
+{
+ return m_properties.value(name);
+}
+
+QVariant QWaylandExtendedSurface::property(const QString &name, const QVariant &defaultValue)
+{
+ return m_properties.value(name,defaultValue);
+}
+
+void QWaylandExtendedSurface::extended_surface_onscreen_visibility(int32_t visibility)
+{
+ m_window->window()->setVisibility(static_cast<QWindow::Visibility>(visibility));
+}
+
+void QWaylandExtendedSurface::extended_surface_set_generic_property(const QString &name, wl_array *value)
+{
+ QByteArray data = QByteArray::fromRawData(static_cast<char *>(value->data), value->size);
+
+ QVariant variantValue;
+ QDataStream ds(data);
+ ds >> variantValue;
+
+ m_properties.insert(name, variantValue);
+
+ QWaylandNativeInterface *nativeInterface = static_cast<QWaylandNativeInterface *>(
+ QGuiApplication::platformNativeInterface());
+ nativeInterface->emitWindowPropertyChanged(m_window, name);
+}
+
+void QWaylandExtendedSurface::extended_surface_close()
+{
+ QWindowSystemInterface::handleCloseEvent(m_window->window());
+}
+
+Qt::WindowFlags QWaylandExtendedSurface::setWindowFlags(Qt::WindowFlags flags)
+{
+ uint wlFlags = 0;
+
+ if (flags & Qt::WindowStaysOnTopHint) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP;
+ if (flags & Qt::WindowOverridesSystemGestures) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES;
+ if (flags & Qt::BypassWindowManagerHint) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER;
+
+ set_window_flags(wlFlags);
+
+ return flags & (Qt::WindowStaysOnTopHint | Qt::WindowOverridesSystemGestures | Qt::BypassWindowManagerHint);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandextendedsurface.h b/src/client/qwaylandextendedsurface.h
new file mode 100644
index 000000000..8c0546473
--- /dev/null
+++ b/src/client/qwaylandextendedsurface.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDEXTENDEDSURFACE_H
+#define QWAYLANDEXTENDEDSURFACE_H
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+#include <wayland-client.h>
+#include <QtWaylandClient/private/qwayland-surface-extension.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandWindow;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandExtendedSurface : public QtWayland::qt_extended_surface
+{
+public:
+ QWaylandExtendedSurface(QWaylandWindow *window, struct ::qt_extended_surface *extended_surface);
+ ~QWaylandExtendedSurface();
+
+ void setContentOrientation(Qt::ScreenOrientation orientation);
+
+ void updateGenericProperty(const QString &name, const QVariant &value);
+
+ QVariantMap properties() const;
+ QVariant property(const QString &name);
+ QVariant property(const QString &name, const QVariant &defaultValue);
+
+ Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
+
+private:
+ void extended_surface_onscreen_visibility(int32_t visibility) Q_DECL_OVERRIDE;
+ void extended_surface_set_generic_property(const QString &name, wl_array *value) Q_DECL_OVERRIDE;
+ void extended_surface_close() Q_DECL_OVERRIDE;
+
+ QWaylandWindow *m_window;
+ QVariantMap m_properties;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDEXTENDEDSURFACE_H
diff --git a/src/client/qwaylandglintegration.cpp b/src/client/qwaylandglintegration.cpp
new file mode 100644
index 000000000..bafb99443
--- /dev/null
+++ b/src/client/qwaylandglintegration.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandglintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+QWaylandGLIntegration::QWaylandGLIntegration()
+{
+
+}
+
+QWaylandGLIntegration::~QWaylandGLIntegration()
+{
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandglintegration.h b/src/client/qwaylandglintegration.h
new file mode 100644
index 000000000..7697d3103
--- /dev/null
+++ b/src/client/qwaylandglintegration.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDGLINTEGRATION_H
+#define QWAYLANDGLINTEGRATION_H
+
+#include <QtCore/qglobal.h>
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandWindow;
+class QWaylandDisplay;
+class QWindow;
+
+class QPlatformOpenGLContext;
+class QSurfaceFormat;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandGLIntegration
+{
+public:
+ QWaylandGLIntegration();
+ virtual ~QWaylandGLIntegration();
+
+ virtual void initialize() = 0;
+ virtual bool waitingForEvents() { return false; }
+
+ virtual bool supportsThreadedOpenGL() const { return false; }
+
+ virtual QWaylandWindow *createEglWindow(QWindow *window) = 0;
+ virtual QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const = 0;
+
+ static QWaylandGLIntegration *createGLIntegration(QWaylandDisplay *waylandDisplay);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDGLINTEGRATION_H
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
new file mode 100644
index 000000000..f50581b3a
--- /dev/null
+++ b/src/client/qwaylandinputcontext.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandinputcontext.h"
+
+#include <QGuiApplication>
+#include <QWindow>
+#ifndef QT_NO_WAYLAND_XKB
+#include <xkbcommon/xkbcommon.h>
+#endif
+
+#include "qwaylanddisplay.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylandwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+static Qt::Key toQtKey(uint32_t sym)
+{
+#ifndef QT_NO_WAYLAND_XKB
+ switch (static_cast<xkb_keysym_t>(sym)) {
+ case XKB_KEY_BackSpace:
+ return Qt::Key_Backspace;
+ case XKB_KEY_Return:
+ return Qt::Key_Return;
+ case XKB_KEY_Left:
+ return Qt::Key_Left;
+ case XKB_KEY_Up:
+ return Qt::Key_Up;
+ case XKB_KEY_Right:
+ return Qt::Key_Right;
+ case XKB_KEY_Down:
+ return Qt::Key_Down;
+ default:
+ return Qt::Key_unknown;
+ }
+#else
+ return Qt::Key_unknown;
+#endif
+}
+
+static QEvent::Type toQEventType(uint32_t state)
+{
+ switch (static_cast<wl_keyboard_key_state>(state)) {
+ default:
+ case WL_KEYBOARD_KEY_STATE_PRESSED:
+ return QEvent::KeyPress;
+ case WL_KEYBOARD_KEY_STATE_RELEASED:
+ return QEvent::KeyRelease;
+ }
+}
+
+QWaylandTextInput::QWaylandTextInput(struct ::wl_text_input *text_input)
+ : QtWayland::wl_text_input(text_input)
+ , m_commit()
+ , m_serial(0)
+ , m_resetSerial(0)
+{
+}
+
+QString QWaylandTextInput::commitString() const
+{
+ return m_commit;
+}
+
+void QWaylandTextInput::reset()
+{
+ wl_text_input::reset();
+ updateState();
+ m_resetSerial = m_serial;
+}
+
+void QWaylandTextInput::updateState()
+{
+ if (!QGuiApplication::focusObject())
+ return;
+
+ QInputMethodQueryEvent event(Qt::ImQueryAll);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+
+ const QString &text = event.value(Qt::ImSurroundingText).toString();
+ const int cursor = event.value(Qt::ImCursorPosition).toInt();
+ const int anchor = event.value(Qt::ImAnchorPosition).toInt();
+
+ set_surrounding_text(text, text.leftRef(cursor).toUtf8().size(), text.leftRef(anchor).toUtf8().size());
+
+ commit_state(++m_serial);
+}
+
+void QWaylandTextInput::text_input_commit_string(uint32_t serial, const QString &text)
+{
+ if (!QGuiApplication::focusObject())
+ return;
+
+ QInputMethodEvent event;
+ event.setCommitString(text);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+}
+
+void QWaylandTextInput::text_input_enter(wl_surface *)
+{
+ updateState();
+ m_resetSerial = m_serial;
+}
+
+void QWaylandTextInput::text_input_leave()
+{
+}
+
+void QWaylandTextInput::text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
+{
+ if (!QGuiApplication::focusObject())
+ return;
+
+ // TODO: Convert modifiers to Qt::KeyboardModifiers.
+ QKeyEvent event(toQEventType(state), toQtKey(sym), Qt::NoModifier);
+ QCoreApplication::sendEvent(qGuiApp->focusWindow(), &event);
+}
+
+QWaylandInputContext::QWaylandInputContext(QWaylandDisplay *display)
+ : QPlatformInputContext()
+ , mDisplay(display)
+ , mTextInput()
+{
+}
+
+bool QWaylandInputContext::isValid() const
+{
+ return mDisplay->textInputManager() != 0;
+}
+
+void QWaylandInputContext::reset()
+{
+ if (!ensureTextInput())
+ return;
+
+ mTextInput->reset();
+}
+
+void QWaylandInputContext::commit()
+{
+ if (!ensureTextInput())
+ return;
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ QInputMethodEvent event;
+ event.setCommitString(mTextInput->commitString());
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+
+ mTextInput->reset();
+}
+
+void QWaylandInputContext::update(Qt::InputMethodQueries queries)
+{
+ if (!ensureTextInput())
+ return;
+
+ mTextInput->updateState();
+}
+
+void QWaylandInputContext::invokeAction(QInputMethod::Action, int cursorPosition)
+{
+ if (!ensureTextInput())
+ return;
+
+ mTextInput->invoke_action(0, cursorPosition); // FIXME button, to UTF8 cursor position
+}
+
+void QWaylandInputContext::showInputPanel()
+{
+ if (!ensureTextInput())
+ return;
+
+ mTextInput->show_input_panel();
+}
+
+void QWaylandInputContext::hideInputPanel()
+{
+ if (!ensureTextInput())
+ return;
+
+ mTextInput->hide_input_panel();
+}
+
+bool QWaylandInputContext::isInputPanelVisible() const
+{
+ return false;
+}
+
+void QWaylandInputContext::setFocusObject(QObject *object)
+{
+ if (!ensureTextInput())
+ return;
+
+ if (!object) {
+ mTextInput->deactivate(mDisplay->defaultInputDevice()->wl_seat());
+ return;
+ }
+
+ QWindow *window = QGuiApplication::focusWindow();
+ if (!window || !window->handle())
+ return;
+
+ struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object();
+ mTextInput->activate(mDisplay->defaultInputDevice()->wl_seat(), surface);
+}
+
+bool QWaylandInputContext::ensureTextInput()
+{
+ if (mTextInput)
+ return true;
+
+ if (!isValid())
+ return false;
+
+ mTextInput.reset(new QWaylandTextInput(mDisplay->textInputManager()->create_text_input()));
+ return true;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/client/qwaylandinputcontext.h b/src/client/qwaylandinputcontext.h
new file mode 100644
index 000000000..1f7e4e361
--- /dev/null
+++ b/src/client/qwaylandinputcontext.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDINPUTCONTEXT_H
+#define QWAYLANDINPUTCONTEXT_H
+
+#include <qpa/qplatforminputcontext.h>
+
+#include <QtWaylandClient/private/qwayland-text.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+
+class QWaylandTextInput : public QtWayland::wl_text_input
+{
+public:
+ QWaylandTextInput(struct ::wl_text_input *text_input);
+
+ QString commitString() const;
+
+ void reset();
+ void updateState();
+
+protected:
+ void text_input_commit_string(uint32_t serial, const QString &text) Q_DECL_OVERRIDE;
+ void text_input_enter(wl_surface *surface) Q_DECL_OVERRIDE;
+ void text_input_leave() Q_DECL_OVERRIDE;
+ void text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers);
+
+private:
+ QString m_commit;
+
+ uint32_t m_serial;
+ uint32_t m_resetSerial;
+};
+
+class QWaylandInputContext : public QPlatformInputContext
+{
+ Q_OBJECT
+public:
+ explicit QWaylandInputContext(QWaylandDisplay *display);
+
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ void reset() Q_DECL_OVERRIDE;
+ void commit() Q_DECL_OVERRIDE;
+ void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
+ void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
+
+ void showInputPanel() Q_DECL_OVERRIDE;
+ void hideInputPanel() Q_DECL_OVERRIDE;
+ bool isInputPanelVisible() const Q_DECL_OVERRIDE;
+
+ void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
+
+private:
+ bool ensureTextInput();
+
+ QWaylandDisplay *mDisplay;
+ QScopedPointer<QWaylandTextInput> mTextInput;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDINPUTCONTEXT_H
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
new file mode 100644
index 000000000..b9338b4c3
--- /dev/null
+++ b/src/client/qwaylandinputdevice.cpp
@@ -0,0 +1,798 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandinputdevice.h"
+
+#include "qwaylandintegration.h"
+#include "qwaylandwindow.h"
+#include "qwaylandbuffer.h"
+#include "qwaylanddatadevice.h"
+#include "qwaylanddatadevicemanager.h"
+#include "qwaylandtouch.h"
+#include "qwaylandscreen.h"
+#include "qwaylandcursor.h"
+
+#include <QtGui/private/qpixmap_raster_p.h>
+#include <qpa/qplatformwindow.h>
+#include <QDebug>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <wayland-cursor.h>
+
+#include <QtGui/QGuiApplication>
+
+#ifndef QT_NO_WAYLAND_XKB
+#include <xkbcommon/xkbcommon.h>
+#include <X11/keysym.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id)
+ : QObject()
+ , QtWayland::wl_seat(display->wl_registry(), id)
+ , mQDisplay(display)
+ , mDisplay(display->wl_display())
+ , mFocusCallback(0)
+ , mCaps(0)
+ , mDataDevice(0)
+ , mPointerFocus(0)
+ , mKeyboardFocus(0)
+ , mTouchFocus(0)
+ , mButtons(0)
+ , mTime(0)
+ , mSerial(0)
+ , mEnterSerial(0)
+ , mCursorSerial(0)
+ , mTouchDevice(0)
+ #ifndef QT_NO_WAYLAND_XKB
+ , mXkbContext(0)
+ , mXkbMap(0)
+ , mXkbState(0)
+ #endif
+{
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_rule_names names;
+ names.rules = strdup("evdev");
+ names.model = strdup("pc105");
+ names.layout = strdup("us");
+ names.variant = strdup("");
+ names.options = strdup("");
+
+ mXkbContext = xkb_context_new(xkb_context_flags(0));
+ if (mXkbContext) {
+ mXkbMap = xkb_map_new_from_names(mXkbContext, &names, xkb_map_compile_flags(0));
+ if (mXkbMap) {
+ mXkbState = xkb_state_new(mXkbMap);
+ }
+ }
+
+ if (!mXkbContext || !mXkbMap || !mXkbState)
+ qWarning() << "xkb_map_new_from_names failed, no key input";
+#endif
+
+ if (mQDisplay->dndSelectionHandler()) {
+ mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
+ }
+
+ connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey()));
+}
+
+QWaylandInputDevice::~QWaylandInputDevice()
+{
+#ifndef QT_NO_WAYLAND_XKB
+ if (mXkbState)
+ xkb_state_unref(mXkbState);
+ if (mXkbMap)
+ xkb_map_unref(mXkbMap);
+ if (mXkbContext)
+ xkb_context_unref(mXkbContext);
+#endif
+}
+
+void QWaylandInputDevice::seat_capabilities(uint32_t caps)
+{
+ mCaps = caps;
+
+ if (caps & WL_SEAT_CAPABILITY_KEYBOARD)
+ QtWayland::wl_keyboard::init(get_keyboard());
+
+ if (caps & WL_SEAT_CAPABILITY_POINTER) {
+ QtWayland::wl_pointer::init(get_pointer());
+ pointerSurface = mQDisplay->createSurface(this);
+ }
+
+ if (caps & WL_SEAT_CAPABILITY_TOUCH) {
+ QtWayland::wl_touch::init(get_touch());
+
+ if (!mTouchDevice) {
+ mTouchDevice = new QTouchDevice;
+ mTouchDevice->setType(QTouchDevice::TouchScreen);
+ mTouchDevice->setCapabilities(QTouchDevice::Position);
+ QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+ }
+ }
+}
+
+void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
+{
+ if (window == mPointerFocus)
+ mPointerFocus = 0;
+ if (window == mKeyboardFocus) {
+ mKeyboardFocus = 0;
+ mRepeatTimer.stop();
+ }
+}
+
+void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device)
+{
+ mDataDevice = device;
+}
+
+QWaylandDataDevice *QWaylandInputDevice::dataDevice() const
+{
+ Q_ASSERT(mDataDevice);
+ return mDataDevice;
+}
+
+void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
+{
+ mButtons = mButtons & !button;
+}
+
+QWaylandWindow *QWaylandInputDevice::pointerFocus() const
+{
+ return mPointerFocus;
+}
+
+Qt::KeyboardModifiers QWaylandInputDevice::modifiers() const
+{
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
+
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
+
+ if (xkb_state_mod_name_is_active(mXkbState, "Shift", cstate))
+ ret |= Qt::ShiftModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Control", cstate))
+ ret |= Qt::ControlModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Alt", cstate))
+ ret |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Mod1", cstate))
+ ret |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Mod4", cstate))
+ ret |= Qt::MetaModifier;
+#endif
+
+ return ret;
+}
+
+void QWaylandInputDevice::setCursor(Qt::CursorShape newShape, QWaylandScreen *screen)
+{
+ struct wl_cursor_image *image = screen->waylandCursor()->cursorImage(newShape);
+ if (!image) {
+ return;
+ }
+
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ setCursor(buffer, image);
+}
+
+void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image)
+{
+ if (mCaps & WL_SEAT_CAPABILITY_POINTER) {
+ mCursorSerial = mEnterSerial;
+ /* Hide cursor */
+ if (!buffer)
+ {
+ set_cursor(mEnterSerial, NULL, 0, 0);
+ return;
+ }
+
+ set_cursor(mEnterSerial, pointerSurface,
+ image->hotspot_x, image->hotspot_y);
+ wl_surface_attach(pointerSurface, buffer, 0, 0);
+ wl_surface_damage(pointerSurface, 0, 0, image->width, image->height);
+ wl_surface_commit(pointerSurface);
+ }
+}
+
+void QWaylandInputDevice::pointer_enter(uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t sx, wl_fixed_t sy)
+{
+ Q_UNUSED(sx);
+ Q_UNUSED(sy);
+
+ if (!surface)
+ return;
+
+ QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ window->window()->setCursor(window->window()->cursor());
+
+ mPointerFocus = window;
+
+ mTime = QWaylandDisplay::currentTimeMillisec();
+ mSerial = serial;
+ mEnterSerial = serial;
+
+ QWaylandWindow *grab = QWaylandWindow::mouseGrab();
+ if (!grab) {
+ window->handleMouseEnter(this);
+ window->handleMouse(this, mTime, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
+ }
+}
+
+void QWaylandInputDevice::pointer_leave(uint32_t time, struct wl_surface *surface)
+{
+ // The event may arrive after destroying the window, indicated by
+ // a null surface.
+ if (!surface)
+ return;
+
+ if (!QWaylandWindow::mouseGrab()) {
+ QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ window->handleMouseLeave(this);
+ }
+ mPointerFocus = 0;
+ mButtons = Qt::NoButton;
+
+ mTime = time;
+}
+
+void QWaylandInputDevice::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
+{
+ Q_UNUSED(surface_x);
+ Q_UNUSED(surface_y);
+
+ QWaylandWindow *window = mPointerFocus;
+
+ if (window == NULL) {
+ // We destroyed the pointer focus surface, but the server
+ // didn't get the message yet.
+ return;
+ }
+
+ QPointF pos(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
+ QPointF delta = pos - pos.toPoint();
+ QPointF global = window->window()->mapToGlobal(pos.toPoint());
+ global += delta;
+
+ mSurfacePos = pos;
+ mGlobalPos = global;
+ mTime = time;
+
+ QWaylandWindow *grab = QWaylandWindow::mouseGrab();
+ if (grab && grab != window) {
+ // We can't know the true position since we're getting events for another surface,
+ // so we just set it outside of the window boundaries.
+ pos = QPointF(-1, -1);
+ global = grab->window()->mapToGlobal(pos.toPoint());
+ grab->handleMouse(this, time, pos, global, mButtons, Qt::NoModifier);
+ } else
+ window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
+}
+
+void QWaylandInputDevice::pointer_button(uint32_t serial, uint32_t time,
+ uint32_t button, uint32_t state)
+{
+ Q_UNUSED(serial);
+ QWaylandWindow *window = mPointerFocus;
+ Qt::MouseButton qt_button;
+
+ // translate from kernel (input.h) 'button' to corresponding Qt:MouseButton.
+ // The range of mouse values is 0x110 <= mouse_button < 0x120, the first Joystick button.
+ switch (button) {
+ case 0x110: qt_button = Qt::LeftButton; break; // kernel BTN_LEFT
+ case 0x111: qt_button = Qt::RightButton; break;
+ case 0x112: qt_button = Qt::MiddleButton; break;
+ case 0x113: qt_button = Qt::ExtraButton1; break; // AKA Qt::BackButton
+ case 0x114: qt_button = Qt::ExtraButton2; break; // AKA Qt::ForwardButton
+ case 0x115: qt_button = Qt::ExtraButton3; break; // AKA Qt::TaskButton
+ case 0x116: qt_button = Qt::ExtraButton4; break;
+ case 0x117: qt_button = Qt::ExtraButton5; break;
+ case 0x118: qt_button = Qt::ExtraButton6; break;
+ case 0x119: qt_button = Qt::ExtraButton7; break;
+ case 0x11a: qt_button = Qt::ExtraButton8; break;
+ case 0x11b: qt_button = Qt::ExtraButton9; break;
+ case 0x11c: qt_button = Qt::ExtraButton10; break;
+ case 0x11d: qt_button = Qt::ExtraButton11; break;
+ case 0x11e: qt_button = Qt::ExtraButton12; break;
+ case 0x11f: qt_button = Qt::ExtraButton13; break;
+ default: return; // invalid button number (as far as Qt is concerned)
+ }
+
+ if (state)
+ mButtons |= qt_button;
+ else
+ mButtons &= ~qt_button;
+
+ mTime = time;
+ mSerial = serial;
+
+ QWaylandWindow *grab = QWaylandWindow::mouseGrab();
+ if (grab && grab != mPointerFocus) {
+ QPointF pos = QPointF(-1, -1);
+ QPointF global = grab->window()->mapToGlobal(pos.toPoint());
+ grab->handleMouse(this, time, pos, global, mButtons, Qt::NoModifier);
+ } else if (window)
+ window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
+}
+
+void QWaylandInputDevice::pointer_axis(uint32_t time, uint32_t axis, int32_t value)
+{
+ QWaylandWindow *window = mPointerFocus;
+ QPoint pixelDelta;
+ QPoint angleDelta;
+
+ //normalize value and inverse axis
+ int valueDelta = wl_fixed_to_int(value) * -12;
+
+ if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
+ pixelDelta = QPoint();
+ angleDelta.setX(valueDelta);
+ } else {
+ pixelDelta = QPoint();
+ angleDelta.setY(valueDelta);
+ }
+
+ QWindowSystemInterface::handleWheelEvent(window->window(),
+ time, mSurfacePos,
+ mGlobalPos, pixelDelta,
+ angleDelta);
+}
+
+#ifndef QT_NO_WAYLAND_XKB
+
+static const uint32_t KeyTbl[] = {
+ XK_Escape, Qt::Key_Escape,
+ XK_Tab, Qt::Key_Tab,
+ XK_ISO_Left_Tab, Qt::Key_Backtab,
+ XK_BackSpace, Qt::Key_Backspace,
+ XK_Return, Qt::Key_Return,
+ XK_Insert, Qt::Key_Insert,
+ XK_Delete, Qt::Key_Delete,
+ XK_Clear, Qt::Key_Delete,
+ XK_Pause, Qt::Key_Pause,
+ XK_Print, Qt::Key_Print,
+
+ XK_Home, Qt::Key_Home,
+ XK_End, Qt::Key_End,
+ XK_Left, Qt::Key_Left,
+ XK_Up, Qt::Key_Up,
+ XK_Right, Qt::Key_Right,
+ XK_Down, Qt::Key_Down,
+ XK_Prior, Qt::Key_PageUp,
+ XK_Next, Qt::Key_PageDown,
+
+ XK_Shift_L, Qt::Key_Shift,
+ XK_Shift_R, Qt::Key_Shift,
+ XK_Shift_Lock, Qt::Key_Shift,
+ XK_Control_L, Qt::Key_Control,
+ XK_Control_R, Qt::Key_Control,
+ XK_Meta_L, Qt::Key_Meta,
+ XK_Meta_R, Qt::Key_Meta,
+ XK_Alt_L, Qt::Key_Alt,
+ XK_Alt_R, Qt::Key_Alt,
+ XK_Caps_Lock, Qt::Key_CapsLock,
+ XK_Num_Lock, Qt::Key_NumLock,
+ XK_Scroll_Lock, Qt::Key_ScrollLock,
+ XK_Super_L, Qt::Key_Super_L,
+ XK_Super_R, Qt::Key_Super_R,
+ XK_Menu, Qt::Key_Menu,
+ XK_Hyper_L, Qt::Key_Hyper_L,
+ XK_Hyper_R, Qt::Key_Hyper_R,
+ XK_Help, Qt::Key_Help,
+
+ XK_KP_Space, Qt::Key_Space,
+ XK_KP_Tab, Qt::Key_Tab,
+ XK_KP_Enter, Qt::Key_Enter,
+ XK_KP_Home, Qt::Key_Home,
+ XK_KP_Left, Qt::Key_Left,
+ XK_KP_Up, Qt::Key_Up,
+ XK_KP_Right, Qt::Key_Right,
+ XK_KP_Down, Qt::Key_Down,
+ XK_KP_Prior, Qt::Key_PageUp,
+ XK_KP_Next, Qt::Key_PageDown,
+ XK_KP_End, Qt::Key_End,
+ XK_KP_Begin, Qt::Key_Clear,
+ XK_KP_Insert, Qt::Key_Insert,
+ XK_KP_Delete, Qt::Key_Delete,
+ XK_KP_Equal, Qt::Key_Equal,
+ XK_KP_Multiply, Qt::Key_Asterisk,
+ XK_KP_Add, Qt::Key_Plus,
+ XK_KP_Separator, Qt::Key_Comma,
+ XK_KP_Subtract, Qt::Key_Minus,
+ XK_KP_Decimal, Qt::Key_Period,
+ XK_KP_Divide, Qt::Key_Slash,
+
+ XK_ISO_Level3_Shift, Qt::Key_AltGr,
+ XK_Multi_key, Qt::Key_Multi_key,
+ XK_Codeinput, Qt::Key_Codeinput,
+ XK_SingleCandidate, Qt::Key_SingleCandidate,
+ XK_MultipleCandidate, Qt::Key_MultipleCandidate,
+ XK_PreviousCandidate, Qt::Key_PreviousCandidate,
+
+ XK_Mode_switch, Qt::Key_Mode_switch,
+ XK_script_switch, Qt::Key_Mode_switch,
+
+ 0, 0
+};
+
+static int keysymToQtKey(xkb_keysym_t key)
+{
+ int code = 0;
+ int i = 0;
+ while (KeyTbl[i]) {
+ if (key == KeyTbl[i]) {
+ code = (int)KeyTbl[i+1];
+ break;
+ }
+ i += 2;
+ }
+
+ return code;
+}
+
+static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text)
+{
+ int code = 0;
+
+ if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
+ code = Qt::Key_F1 + (int(keysym) - XKB_KEY_F1);
+ } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) {
+ if (keysym >= XKB_KEY_KP_0) {
+ // numeric keypad keys
+ code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0);
+ } else {
+ code = keysymToQtKey(keysym);
+ }
+ modifiers |= Qt::KeypadModifier;
+ } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
+ && text.unicode()->unicode() != 0x7f
+ && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_currency)) {
+ code = text.unicode()->toUpper().unicode();
+ } else {
+ // any other keys
+ code = keysymToQtKey(keysym);
+ }
+
+ return code;
+}
+
+#endif // QT_NO_WAYLAND_XKB
+
+void QWaylandInputDevice::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size)
+{
+#ifndef QT_NO_WAYLAND_XKB
+ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+ close(fd);
+ return;
+ }
+
+ char *map_str = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (map_str == MAP_FAILED) {
+ close(fd);
+ return;
+ }
+
+ mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, (xkb_keymap_compile_flags)0);
+ munmap(map_str, size);
+ close(fd);
+
+ mXkbState = xkb_state_new(mXkbMap);
+#else
+ Q_UNUSED(format);
+ Q_UNUSED(fd);
+ Q_UNUSED(size);
+#endif
+}
+
+void QWaylandInputDevice::keyboard_enter(uint32_t time, struct wl_surface *surface, struct wl_array *keys)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(keys);
+
+ if (!surface)
+ return;
+
+
+ QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ mKeyboardFocus = window;
+
+ if (!mFocusCallback) {
+ mFocusCallback = wl_display_sync(mDisplay);
+ wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::callback, this);
+ }
+}
+
+void QWaylandInputDevice::keyboard_leave(uint32_t time, struct wl_surface *surface)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(surface);
+
+ mKeyboardFocus = NULL;
+
+ // Use a callback to set the focus because we may get a leave/enter pair, and
+ // the latter one would be lost in the QWindowSystemInterface queue, if
+ // we issue the handleWindowActivated() calls immediately.
+ if (!mFocusCallback) {
+ mFocusCallback = wl_display_sync(mDisplay);
+ wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::callback, this);
+ }
+ mRepeatTimer.stop();
+}
+
+const wl_callback_listener QWaylandInputDevice::callback = {
+ QWaylandInputDevice::focusCallback
+};
+
+void QWaylandInputDevice::focusCallback(void *data, struct wl_callback *callback, uint32_t time)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(callback);
+ QWaylandInputDevice *self = static_cast<QWaylandInputDevice *>(data);
+ if (self->mFocusCallback) {
+ wl_callback_destroy(self->mFocusCallback);
+ self->mFocusCallback = 0;
+ }
+
+ self->mQDisplay->setLastKeyboardFocusInputDevice(self->mKeyboardFocus ? self : 0);
+ QWindowSystemInterface::handleWindowActivated(self->mKeyboardFocus ? self->mKeyboardFocus->window() : 0);
+}
+
+void QWaylandInputDevice::keyboard_key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
+{
+ Q_UNUSED(serial);
+ QWaylandWindow *window = mKeyboardFocus;
+#ifndef QT_NO_WAYLAND_XKB
+ if (!mXkbMap)
+ return;
+
+ uint32_t code = key + 8;
+ bool isDown = state != 0;
+ const xkb_keysym_t *syms;
+ uint32_t numSyms = xkb_key_get_syms(mXkbState, code, &syms);
+ xkb_state_update_key(mXkbState, code,
+ isDown ? XKB_KEY_DOWN : XKB_KEY_UP);
+ QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
+
+ if (!window) {
+ // We destroyed the keyboard focus surface, but the server
+ // didn't get the message yet.
+ return;
+ }
+
+ int qtkey = key + 8; // qt-compositor substracts 8 for some reason
+ QString text;
+
+ if (numSyms == 1) {
+ xkb_keysym_t sym = syms[0];
+ Qt::KeyboardModifiers modifiers = this->modifiers();
+
+ uint utf32 = xkb_keysym_to_utf32(sym);
+ text = QString::fromUcs4(&utf32, 1);
+
+ qtkey = keysymToQtKey(sym, modifiers, text);
+
+ QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
+ time, type, qtkey,
+ modifiers,
+ code, 0, 0, text);
+ }
+#else
+ // Generic fallback for single hard keys: Assume 'key' is a Qt key code.
+ if (window) {
+ QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
+ time, type,
+ qtkey,
+ Qt::NoModifier,
+ code, 0, 0);
+ }
+#endif
+
+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+ mRepeatKey = qtkey;
+ mRepeatCode = code;
+ mRepeatTime = time;
+ mRepeatText = text;
+ mRepeatTimer.setInterval(400);
+ mRepeatTimer.start();
+ } else {
+ mRepeatTimer.stop();
+ }
+}
+
+void QWaylandInputDevice::repeatKey()
+{
+ mRepeatTimer.setInterval(25);
+ QWindowSystemInterface::handleExtendedKeyEvent(mKeyboardFocus->window(),
+ mRepeatTime, QEvent::KeyPress, mRepeatKey,
+ Qt::NoModifier,
+ mRepeatCode, 0, 0, mRepeatText);
+}
+
+void QWaylandInputDevice::keyboard_modifiers(uint32_t serial,
+ uint32_t mods_depressed,
+ uint32_t mods_latched,
+ uint32_t mods_locked,
+ uint32_t group)
+{
+ Q_UNUSED(serial);
+#ifndef QT_NO_WAYLAND_XKB
+ if (mXkbState)
+ xkb_state_update_mask(mXkbState,
+ mods_depressed, mods_latched, mods_locked,
+ 0, 0, group);
+#else
+ Q_UNUSED(serial);
+ Q_UNUSED(mods_depressed);
+ Q_UNUSED(mods_latched);
+ Q_UNUSED(mods_locked);
+ Q_UNUSED(group);
+#endif
+}
+
+void QWaylandInputDevice::touch_down(uint32_t serial,
+ uint32_t time,
+ struct wl_surface *surface,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ Q_UNUSED(serial);
+ Q_UNUSED(time);
+ mTouchFocus = QWaylandWindow::fromWlSurface(surface);
+ handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed);
+}
+
+void QWaylandInputDevice::touch_up(uint32_t serial, uint32_t time, int32_t id)
+{
+ Q_UNUSED(serial);
+ Q_UNUSED(time);
+ mTouchFocus = 0;
+ handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
+}
+
+void QWaylandInputDevice::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
+{
+ Q_UNUSED(time);
+ handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointMoved);
+}
+
+void QWaylandInputDevice::touch_cancel()
+{
+ mPrevTouchPoints.clear();
+ mTouchPoints.clear();
+
+ QWaylandTouchExtension *touchExt = mQDisplay->touchExtension();
+ if (touchExt)
+ touchExt->touchCanceled();
+
+ QWindowSystemInterface::handleTouchCancelEvent(0, mTouchDevice);
+}
+
+void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::TouchPointState state)
+{
+ QWindowSystemInterface::TouchPoint tp;
+
+ // Find out the coordinates for Released events.
+ bool coordsOk = false;
+ if (state == Qt::TouchPointReleased)
+ for (int i = 0; i < mPrevTouchPoints.count(); ++i)
+ if (mPrevTouchPoints.at(i).id == id) {
+ tp.area = mPrevTouchPoints.at(i).area;
+ coordsOk = true;
+ break;
+ }
+
+ if (!coordsOk) {
+ // x and y are surface relative.
+ // We need a global (screen) position.
+ QWaylandWindow *win = mTouchFocus;
+
+ //is it possible that mTouchFocus is null;
+ if (!win)
+ win = mPointerFocus;
+ if (!win)
+ win = mKeyboardFocus;
+ if (!win || !win->window())
+ return;
+
+ tp.area = QRectF(0, 0, 8, 8);
+ QMargins margins = win->frameMargins();
+ tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x+margins.left(), y+margins.top())));
+ }
+
+ tp.state = state;
+ tp.id = id;
+ tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
+ mTouchPoints.append(tp);
+}
+
+void QWaylandInputDevice::touch_frame()
+{
+ // Copy all points, that are in the previous but not in the current list, as stationary.
+ 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 = mTouchFocus ? mTouchFocus->window() : 0;
+
+ QWindowSystemInterface::handleTouchEvent(window, mTouchDevice, mTouchPoints);
+
+ bool allReleased = true;
+ for (int i = 0; i < mTouchPoints.count(); ++i)
+ if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
+ allReleased = false;
+ break;
+ }
+
+ mPrevTouchPoints = mTouchPoints;
+ mTouchPoints.clear();
+
+ if (allReleased) {
+ QWindowSystemInterface::handleTouchEvent(window, mTouchDevice, mTouchPoints);
+ mPrevTouchPoints.clear();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandinputdevice.h b/src/client/qwaylandinputdevice.h
new file mode 100644
index 000000000..625d773d1
--- /dev/null
+++ b/src/client/qwaylandinputdevice.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDINPUTDEVICE_H
+#define QWAYLANDINPUTDEVICE_H
+
+#include "qwaylandwindow.h"
+
+#include <QSocketNotifier>
+#include <QObject>
+#include <QTimer>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <wayland-client.h>
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+
+#ifndef QT_NO_WAYLAND_XKB
+struct xkb_context;
+struct xkb_keymap;
+struct xkb_state;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandWindow;
+class QWaylandDisplay;
+class QWaylandDataDevice;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice
+ : public QObject
+ , public QtWayland::wl_pointer
+ , public QtWayland::wl_keyboard
+ , public QtWayland::wl_touch
+ , public QtWayland::wl_seat
+{
+ Q_OBJECT
+public:
+ QWaylandInputDevice(QWaylandDisplay *display, uint32_t id);
+ ~QWaylandInputDevice();
+
+ uint32_t capabilities() const { return mCaps; }
+
+ struct ::wl_seat *wl_seat() { return QtWayland::wl_seat::object(); }
+
+ void setCursor(Qt::CursorShape cursor, QWaylandScreen *screen);
+ void setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image);
+ void handleWindowDestroyed(QWaylandWindow *window);
+
+ void setDataDevice(QWaylandDataDevice *device);
+ QWaylandDataDevice *dataDevice() const;
+
+ void removeMouseButtonFromState(Qt::MouseButton button);
+
+ QWaylandWindow *pointerFocus() const;
+
+ Qt::KeyboardModifiers modifiers() const;
+
+ uint32_t serial() const;
+ uint32_t cursorSerial() const { return mCursorSerial; }
+
+private slots:
+ void repeatKey();
+
+private:
+ QWaylandDisplay *mQDisplay;
+ struct wl_display *mDisplay;
+ struct wl_callback *mFocusCallback;
+
+ uint32_t mCaps;
+
+ struct wl_surface *pointerSurface;
+
+ QWaylandDataDevice *mDataDevice;
+ QWaylandWindow *mPointerFocus;
+ QWaylandWindow *mKeyboardFocus;
+ QWaylandWindow *mTouchFocus;
+
+ Qt::MouseButtons mButtons;
+ QPointF mSurfacePos;
+ QPointF mGlobalPos;
+ uint32_t mTime;
+ uint32_t mSerial;
+ uint32_t mEnterSerial;
+ uint32_t mCursorSerial;
+
+ void seat_capabilities(uint32_t caps) Q_DECL_OVERRIDE;
+
+ void pointer_enter(uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t sx, wl_fixed_t sy) Q_DECL_OVERRIDE;
+ void pointer_leave(uint32_t time, struct wl_surface *surface);
+ void pointer_motion(uint32_t time,
+ wl_fixed_t sx, wl_fixed_t sy) Q_DECL_OVERRIDE;
+ void pointer_button(uint32_t serial, uint32_t time,
+ uint32_t button, uint32_t state) Q_DECL_OVERRIDE;
+ void pointer_axis(uint32_t time,
+ uint32_t axis,
+ wl_fixed_t value) Q_DECL_OVERRIDE;
+
+ void keyboard_keymap(uint32_t format,
+ int32_t fd,
+ uint32_t size) Q_DECL_OVERRIDE;
+ void keyboard_enter(uint32_t time,
+ struct wl_surface *surface,
+ struct wl_array *keys) Q_DECL_OVERRIDE;
+ void keyboard_leave(uint32_t time,
+ struct wl_surface *surface) Q_DECL_OVERRIDE;
+ void keyboard_key(uint32_t serial, uint32_t time,
+ uint32_t key, uint32_t state) Q_DECL_OVERRIDE;
+ void keyboard_modifiers(uint32_t serial,
+ uint32_t mods_depressed,
+ uint32_t mods_latched,
+ uint32_t mods_locked,
+ uint32_t group) Q_DECL_OVERRIDE;
+
+ void touch_down(uint32_t serial,
+ uint32_t time,
+ struct wl_surface *surface,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y) Q_DECL_OVERRIDE;
+ void touch_up(uint32_t serial,
+ uint32_t time,
+ int32_t id) Q_DECL_OVERRIDE;
+ void touch_motion(uint32_t time,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y) Q_DECL_OVERRIDE;
+ void touch_frame() Q_DECL_OVERRIDE;
+ void touch_cancel() Q_DECL_OVERRIDE;
+
+ void handleTouchPoint(int id, double x, double y, Qt::TouchPointState state);
+
+ static const wl_callback_listener callback;
+ static void focusCallback(void *data, struct wl_callback *callback, uint32_t time);
+
+ QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
+ QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
+ QTouchDevice *mTouchDevice;
+
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_context *mXkbContext;
+ xkb_keymap *mXkbMap;
+ xkb_state *mXkbState;
+#endif
+
+ int mRepeatKey;
+ uint32_t mRepeatCode;
+ uint32_t mRepeatTime;
+ QString mRepeatText;
+ QTimer mRepeatTimer;
+
+ friend class QWaylandTouchExtension;
+ friend class QWaylandQtKeyExtension;
+};
+
+inline uint32_t QWaylandInputDevice::serial() const
+{
+ return mSerial;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
new file mode 100644
index 000000000..9c02419b8
--- /dev/null
+++ b/src/client/qwaylandintegration.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandintegration.h"
+
+#include "qwaylanddisplay.h"
+#include "qwaylandinputcontext.h"
+#include "qwaylandshmbackingstore.h"
+#include "qwaylandshmwindow.h"
+#include "qwaylandnativeinterface.h"
+#include "qwaylandclipboard.h"
+#include "qwaylanddnd.h"
+#include "qwaylandwindowmanagerintegration.h"
+
+#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h"
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QtPlatformSupport/private/qgenericunixthemes_p.h>
+
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformcursor.h>
+#include <QtGui/QSurfaceFormat>
+#include <QtGui/QOpenGLContext>
+
+#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qplatformaccessibility.h>
+#include <qpa/qplatforminputcontext.h>
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+#include "qwaylandglintegration.h"
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+class GenericWaylandTheme: public QGenericUnixTheme
+{
+public:
+ static QStringList themeNames()
+ {
+ QStringList result;
+
+ if (QGuiApplication::desktopSettingsAware()) {
+ const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment();
+
+ // Ignore X11 desktop environments
+ if (!desktopEnvironment.isEmpty() &&
+ desktopEnvironment != QByteArrayLiteral("UNKNOWN") &&
+ desktopEnvironment != QByteArrayLiteral("KDE") &&
+ desktopEnvironment != QByteArrayLiteral("GNOME") &&
+ desktopEnvironment != QByteArrayLiteral("UNITY") &&
+ desktopEnvironment != QByteArrayLiteral("MATE") &&
+ desktopEnvironment != QByteArrayLiteral("XFCE") &&
+ desktopEnvironment != QByteArrayLiteral("LXDE"))
+ result.push_back(desktopEnvironment.toLower());
+ }
+
+ if (result.isEmpty())
+ result.push_back(QLatin1String(QGenericUnixTheme::name));
+
+ return result;
+ }
+};
+
+QWaylandIntegration::QWaylandIntegration()
+ : mFontDb(new QGenericUnixFontDatabase())
+ , mNativeInterface(new QWaylandNativeInterface(this))
+#ifndef QT_NO_ACCESSIBILITY
+ , mAccessibility(new QPlatformAccessibility())
+#else
+ , mAccessibility(0)
+#endif
+{
+ mDisplay = new QWaylandDisplay();
+ mClipboard = new QWaylandClipboard(mDisplay);
+ mDrag = new QWaylandDrag(mDisplay);
+
+ foreach (QPlatformScreen *screen, mDisplay->screens())
+ screenAdded(screen);
+
+ mInputContext.reset(new QWaylandInputContext(mDisplay));
+}
+
+QWaylandIntegration::~QWaylandIntegration()
+{
+ delete mDrag;
+ delete mClipboard;
+#ifndef QT_NO_ACCESSIBILITY
+ delete mAccessibility;
+#endif
+ delete mNativeInterface;
+ delete mDisplay;
+}
+
+QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
+{
+ return mNativeInterface;
+}
+
+bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case OpenGL:
+#ifdef QT_WAYLAND_GL_SUPPORT
+ return true;
+#else
+ return false;
+#endif
+ case ThreadedOpenGL:
+#ifdef QT_WAYLAND_GL_SUPPORT
+ return mDisplay->eglIntegration()->supportsThreadedOpenGL();
+#else
+ return false;
+#endif
+ case BufferQueueingOpenGL:
+ return true;
+ case MultipleWindows:
+ case NonFullScreenWindows:
+ return true;
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const
+{
+#ifdef QT_WAYLAND_GL_SUPPORT
+ if (window->surfaceType() == QWindow::OpenGLSurface)
+ return mDisplay->eglIntegration()->createEglWindow(window);
+#endif
+ return new QWaylandShmWindow(window);
+}
+
+QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+#ifdef QT_WAYLAND_GL_SUPPORT
+ return mDisplay->eglIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle());
+#else
+ Q_UNUSED(context);
+ return 0;
+#endif
+}
+
+QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ return new QWaylandShmBackingStore(window);
+}
+
+QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
+{
+ return createUnixEventDispatcher();
+}
+
+void QWaylandIntegration::initialize()
+{
+ QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
+ QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests()));
+}
+
+QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
+{
+ return mFontDb;
+}
+
+QPlatformClipboard *QWaylandIntegration::clipboard() const
+{
+ return mClipboard;
+}
+
+QPlatformDrag *QWaylandIntegration::drag() const
+{
+ return mDrag;
+}
+
+QPlatformInputContext *QWaylandIntegration::inputContext() const
+{
+ return mInputContext.data();
+}
+
+QVariant QWaylandIntegration::styleHint(StyleHint hint) const
+{
+ if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration())
+ return mDisplay->windowManagerIntegration()->showIsFullScreen();
+
+ return QPlatformIntegration::styleHint(hint);
+}
+
+QPlatformAccessibility *QWaylandIntegration::accessibility() const
+{
+ return mAccessibility;
+}
+
+QPlatformServices *QWaylandIntegration::services() const
+{
+ return mDisplay->windowManagerIntegration();
+}
+
+QWaylandDisplay *QWaylandIntegration::display() const
+{
+ return mDisplay;
+}
+
+QStringList QWaylandIntegration::themeNames() const
+{
+ return GenericWaylandTheme::themeNames();
+}
+
+QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) const
+{
+ return GenericWaylandTheme::createUnixTheme(name);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandintegration.h b/src/client/qwaylandintegration.h
new file mode 100644
index 000000000..8886c28da
--- /dev/null
+++ b/src/client/qwaylandintegration.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMINTEGRATION_WAYLAND_H
+#define QPLATFORMINTEGRATION_WAYLAND_H
+
+#include <qpa/qplatformintegration.h>
+
+#include <QtWaylandClient/qwaylandclientexport.h>
+QT_BEGIN_NAMESPACE
+
+class QWaylandBuffer;
+class QWaylandDisplay;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandIntegration : public QPlatformIntegration
+{
+public:
+ QWaylandIntegration();
+ ~QWaylandIntegration();
+
+ bool hasCapability(QPlatformIntegration::Capability cap) const;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+
+ QAbstractEventDispatcher *createEventDispatcher() const;
+ void initialize();
+
+ QPlatformFontDatabase *fontDatabase() const;
+
+ QPlatformNativeInterface *nativeInterface() const;
+
+ QPlatformClipboard *clipboard() const;
+
+ QPlatformDrag *drag() const;
+
+ QPlatformInputContext *inputContext() const;
+
+ QVariant styleHint(StyleHint hint) const;
+
+ QPlatformAccessibility *accessibility() const;
+
+ QPlatformServices *services() const;
+
+ QWaylandDisplay *display() const;
+
+ QStringList themeNames() const;
+
+ QPlatformTheme *createPlatformTheme(const QString &name) const;
+
+private:
+ QPlatformFontDatabase *mFontDb;
+ QPlatformClipboard *mClipboard;
+ QPlatformDrag *mDrag;
+ QWaylandDisplay *mDisplay;
+ QPlatformNativeInterface *mNativeInterface;
+ QScopedPointer<QPlatformInputContext> mInputContext;
+ QPlatformAccessibility *mAccessibility;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp
new file mode 100644
index 000000000..354e8dbaa
--- /dev/null
+++ b/src/client/qwaylandnativeinterface.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandnativeinterface.h"
+#include "qwaylanddisplay.h"
+#include "qwaylandwindow.h"
+#include "qwaylandextendedsurface.h"
+#include "qwaylandintegration.h"
+#include "qwaylanddisplay.h"
+#include "qwaylandwindowmanagerintegration.h"
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/QScreen>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandNativeInterface::QWaylandNativeInterface(QWaylandIntegration *integration)
+ : m_integration(integration)
+{
+}
+
+void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
+{
+ QByteArray lowerCaseResource = resourceString.toLower();
+
+ if (lowerCaseResource == "display")
+ return m_integration->display()->wl_display();
+ if (lowerCaseResource == "compositor")
+ return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
+
+ return 0;
+}
+
+void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
+{
+ QByteArray lowerCaseResource = resourceString.toLower();
+
+ if (lowerCaseResource == "display")
+ return m_integration->display()->wl_display();
+ if (lowerCaseResource == "compositor")
+ return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
+ if (lowerCaseResource == "surface") {
+ return ((QWaylandWindow *) window->handle())->object();
+ }
+
+ return NULL;
+}
+
+void *QWaylandNativeInterface::nativeResourceForScreen(const QByteArray &resourceString, QScreen *screen)
+{
+ QByteArray lowerCaseResource = resourceString.toLower();
+
+ if (lowerCaseResource == "output")
+ return ((QWaylandScreen *) screen->handle())->output();
+
+ return NULL;
+}
+
+QVariantMap QWaylandNativeInterface::windowProperties(QPlatformWindow *window) const
+{
+ QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(window);
+ if (QWaylandExtendedSurface *extendedWindow = waylandWindow->extendedWindow())
+ return extendedWindow->properties();
+ return QVariantMap();
+}
+
+
+QVariant QWaylandNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
+{
+ QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(window);
+ if (QWaylandExtendedSurface *extendedWindow = waylandWindow->extendedWindow())
+ return extendedWindow->property(name);
+ return QVariant();
+}
+
+QVariant QWaylandNativeInterface::windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const
+{
+ QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(window);
+ if (QWaylandExtendedSurface *extendedWindow = waylandWindow->extendedWindow()) {
+ return extendedWindow->property(name,defaultValue);
+ }
+ return defaultValue;
+}
+
+void QWaylandNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
+{
+ QWaylandWindow *wlWindow = static_cast<QWaylandWindow*>(window);
+ if (QWaylandExtendedSurface *extendedWindow = wlWindow->extendedWindow())
+ extendedWindow->updateGenericProperty(name,value);
+}
+
+void QWaylandNativeInterface::emitWindowPropertyChanged(QPlatformWindow *window, const QString &name)
+{
+ emit windowPropertyChanged(window,name);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandnativeinterface.h b/src/client/qwaylandnativeinterface.h
new file mode 100644
index 000000000..c5f0fda73
--- /dev/null
+++ b/src/client/qwaylandnativeinterface.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDNATIVEINTERFACE_H
+#define QWAYLANDNATIVEINTERFACE_H
+
+#include "qwaylandscreen.h"
+#include <QVariantMap>
+#include <qpa/qplatformnativeinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandIntegration;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandNativeInterface : public QPlatformNativeInterface
+{
+public:
+ QWaylandNativeInterface(QWaylandIntegration *integration);
+ void *nativeResourceForIntegration(const QByteArray &resource);
+ void *nativeResourceForWindow(const QByteArray &resourceString,
+ QWindow *window);
+ void *nativeResourceForScreen(const QByteArray &resourceString,
+ QScreen *screen);
+
+ QVariantMap windowProperties(QPlatformWindow *window) const;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name) const;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
+ void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
+
+ void emitWindowPropertyChanged(QPlatformWindow *window, const QString &name);
+private:
+ static QWaylandScreen *qPlatformScreenForWindow(QWindow *window);
+
+private:
+ QWaylandIntegration *m_integration;
+ QHash<QPlatformWindow*, QVariantMap> m_windowProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDNATIVEINTERFACE_H
diff --git a/src/client/qwaylandqtkey.cpp b/src/client/qwaylandqtkey.cpp
new file mode 100644
index 000000000..6cc4597d9
--- /dev/null
+++ b/src/client/qwaylandqtkey.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandqtkey.h"
+#include "qwaylandinputdevice.h"
+
+QT_BEGIN_NAMESPACE
+
+QWaylandQtKeyExtension::QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_t id)
+ : QtWayland::qt_key_extension(display->wl_registry(), id)
+ , m_display(display)
+{
+}
+
+void QWaylandQtKeyExtension::key_extension_qtkey(struct wl_surface *surface,
+ uint32_t time,
+ uint32_t type,
+ uint32_t key,
+ uint32_t modifiers,
+ uint32_t nativeScanCode,
+ uint32_t nativeVirtualKey,
+ uint32_t nativeModifiers,
+ const QString &text,
+ uint32_t autorep,
+ uint32_t count)
+{
+ QList<QWaylandInputDevice *> inputDevices = m_display->inputDevices();
+ if (!surface && inputDevices.isEmpty()) {
+ qWarning("qt_key_extension: handle_qtkey: No input device");
+ return;
+ }
+
+ QWaylandInputDevice *dev = inputDevices.first();
+ QWaylandWindow *win = surface ? QWaylandWindow::fromWlSurface(surface) : dev->mKeyboardFocus;
+
+ if (!win || !win->window()) {
+ qWarning("qt_key_extension: handle_qtkey: No keyboard focus");
+ return;
+ }
+
+ QWindow *window = win->window();
+ QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::Type(type), key, Qt::KeyboardModifiers(modifiers),
+ nativeScanCode, nativeVirtualKey, nativeModifiers, text,
+ autorep, count);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandqtkey.h b/src/client/qwaylandqtkey.h
new file mode 100644
index 000000000..0acc9e8ad
--- /dev/null
+++ b/src/client/qwaylandqtkey.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDQTKEY_H
+#define QWAYLANDQTKEY_H
+
+#include "qwaylanddisplay.h"
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtWaylandClient/private/qwayland-qtkey-extension.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandQtKeyExtension : public QtWayland::qt_key_extension
+{
+public:
+ QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_t id);
+
+private:
+ QWaylandDisplay *m_display;
+
+ void key_extension_qtkey(struct wl_surface *surface,
+ uint32_t time,
+ uint32_t type,
+ uint32_t key,
+ uint32_t modifiers,
+ uint32_t nativeScanCode,
+ uint32_t nativeVirtualKey,
+ uint32_t nativeModifiers,
+ const QString &text,
+ uint32_t autorep,
+ uint32_t count) Q_DECL_OVERRIDE;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDQTKEY_H
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
new file mode 100644
index 000000000..cda94a7e1
--- /dev/null
+++ b/src/client/qwaylandscreen.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandscreen.h"
+
+#include "qwaylanddisplay.h"
+#include "qwaylandcursor.h"
+#include "qwaylandextendedoutput.h"
+
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id)
+ : QtWayland::wl_output(waylandDisplay->wl_registry(), id)
+ , mWaylandDisplay(waylandDisplay)
+ , mExtendedOutput(0)
+ , mDepth(32)
+ , mRefreshRate(60000)
+ , mFormat(QImage::Format_ARGB32_Premultiplied)
+ , mOutputName(QStringLiteral("Screen%1").arg(id))
+ , mWaylandCursor(new QWaylandCursor(this))
+{
+ // handle case of output extension global being sent after outputs
+ createExtendedOutput();
+}
+
+QWaylandScreen::~QWaylandScreen()
+{
+ delete mWaylandCursor;
+}
+
+QWaylandDisplay * QWaylandScreen::display() const
+{
+ return mWaylandDisplay;
+}
+
+QRect QWaylandScreen::geometry() const
+{
+ return mGeometry;
+}
+
+int QWaylandScreen::depth() const
+{
+ return mDepth;
+}
+
+QImage::Format QWaylandScreen::format() const
+{
+ return mFormat;
+}
+
+QDpi QWaylandScreen::logicalDpi() const
+{
+ static int force_dpi = !qgetenv("QT_WAYLAND_FORCE_DPI").isEmpty() ? qgetenv("QT_WAYLAND_FORCE_DPI").toInt() : -1;
+ if (force_dpi > 0)
+ return QDpi(force_dpi, force_dpi);
+
+ return QPlatformScreen::logicalDpi();
+}
+
+void QWaylandScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
+{
+ if (mExtendedOutput)
+ mExtendedOutput->setOrientationUpdateMask(mask);
+}
+
+Qt::ScreenOrientation QWaylandScreen::orientation() const
+{
+ if (mExtendedOutput)
+ return mExtendedOutput->currentOrientation();
+ return QPlatformScreen::orientation();
+}
+
+qreal QWaylandScreen::refreshRate() const
+{
+ return mRefreshRate / 1000.f;
+}
+
+QPlatformCursor *QWaylandScreen::cursor() const
+{
+ return mWaylandCursor;
+}
+
+QWaylandExtendedOutput *QWaylandScreen::extendedOutput() const
+{
+ return mExtendedOutput;
+}
+
+void QWaylandScreen::createExtendedOutput()
+{
+ QtWayland::qt_output_extension *extension = mWaylandDisplay->outputExtension();
+ if (!mExtendedOutput && extension)
+ mExtendedOutput = new QWaylandExtendedOutput(this, extension->get_extended_output(output()));
+}
+
+QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
+{
+ QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(window);
+ return static_cast<QWaylandScreen *>(platformScreen);
+}
+
+void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
+{
+ if (!(flags & WL_OUTPUT_MODE_CURRENT))
+ return;
+
+ QSize size(width, height);
+
+ if (size != mGeometry.size()) {
+ mGeometry.setSize(size);
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry);
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry);
+ }
+
+ if (refresh != mRefreshRate) {
+ mRefreshRate = refresh;
+ QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate());
+ }
+}
+
+void QWaylandScreen::output_geometry(int32_t x, int32_t y,
+ int32_t width, int32_t height,
+ int subpixel,
+ const QString &make,
+ const QString &model,
+ int32_t transform)
+{
+ Q_UNUSED(subpixel);
+ Q_UNUSED(make);
+ Q_UNUSED(transform);
+
+ if (!model.isEmpty())
+ mOutputName = model;
+
+ QRect geom(x, y, width, height);
+
+ if (mGeometry == geom)
+ return;
+
+ mGeometry = geom;
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry);
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandscreen.h b/src/client/qwaylandscreen.h
new file mode 100644
index 000000000..15ae5189a
--- /dev/null
+++ b/src/client/qwaylandscreen.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSCREEN_H
+#define QWAYLANDSCREEN_H
+
+#include <qpa/qplatformscreen.h>
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandCursor;
+class QWaylandExtendedOutput;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandScreen : public QPlatformScreen, QtWayland::wl_output
+{
+public:
+ QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id);
+ ~QWaylandScreen();
+
+ QWaylandDisplay *display() const;
+
+ QRect geometry() const;
+ int depth() const;
+ QImage::Format format() const;
+
+ QDpi logicalDpi() const Q_DECL_OVERRIDE;
+
+ void setOrientationUpdateMask(Qt::ScreenOrientations mask);
+
+ Qt::ScreenOrientation orientation() const;
+ qreal refreshRate() const;
+
+ QString name() const { return mOutputName; }
+
+ QPlatformCursor *cursor() const;
+ QWaylandCursor *waylandCursor() const { return mWaylandCursor; };
+
+ ::wl_output *output() { return object(); }
+
+ QWaylandExtendedOutput *extendedOutput() const;
+ void createExtendedOutput();
+
+ static QWaylandScreen *waylandScreenFromWindow(QWindow *window);
+
+private:
+ void output_mode(uint32_t flags, int width, int height, int refresh) Q_DECL_OVERRIDE;
+ void output_geometry(int32_t x, int32_t y,
+ int32_t width, int32_t height,
+ int subpixel,
+ const QString &make,
+ const QString &model,
+ int32_t transform) Q_DECL_OVERRIDE;
+
+ QWaylandDisplay *mWaylandDisplay;
+ QWaylandExtendedOutput *mExtendedOutput;
+ QRect mGeometry;
+ int mDepth;
+ int mRefreshRate;
+ QImage::Format mFormat;
+ QSize mPhysicalSize;
+ QString mOutputName;
+
+ QWaylandCursor *mWaylandCursor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDSCREEN_H
diff --git a/src/client/qwaylandshellsurface.cpp b/src/client/qwaylandshellsurface.cpp
new file mode 100644
index 000000000..4c8ff1bc4
--- /dev/null
+++ b/src/client/qwaylandshellsurface.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandshellsurface.h"
+
+#include "qwaylanddisplay.h"
+#include "qwaylandwindow.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylanddecoration.h"
+#include "qwaylandscreen.h"
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandShellSurface::QWaylandShellSurface(struct ::wl_shell_surface *shell_surface, QWaylandWindow *window)
+ : QtWayland::wl_shell_surface(shell_surface)
+ , m_window(window)
+ , m_maximized(false)
+ , m_fullscreen(false)
+{
+}
+
+QWaylandShellSurface::~QWaylandShellSurface()
+{
+ wl_shell_surface_destroy(object());
+}
+
+void QWaylandShellSurface::resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges)
+{
+ resize(inputDevice->wl_seat(),
+ inputDevice->serial(),
+ edges);
+}
+
+void QWaylandShellSurface::move(QWaylandInputDevice *inputDevice)
+{
+ move(inputDevice->wl_seat(),
+ inputDevice->serial());
+}
+
+void QWaylandShellSurface::setMaximized()
+{
+ m_maximized = true;
+ m_size = m_window->window()->geometry().size();
+ set_maximized(0);
+}
+
+void QWaylandShellSurface::setFullscreen()
+{
+ m_fullscreen = true;
+ m_size = m_window->window()->geometry().size();
+ set_fullscreen(WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, 0);
+}
+
+void QWaylandShellSurface::setNormal()
+{
+ if (m_fullscreen || m_maximized) {
+ m_fullscreen = m_maximized = false;
+ setTopLevel();
+ QMargins m = m_window->frameMargins();
+ m_window->configure(0, m_size.width() + m.left() + m.right(), m_size.height() + m.top() + m.bottom());
+ }
+}
+
+void QWaylandShellSurface::setMinimized()
+{
+ // TODO: There's no wl_shell_surface API for this
+}
+
+void QWaylandShellSurface::setTopLevel()
+{
+ set_toplevel();
+}
+
+void QWaylandShellSurface::updateTransientParent(QWindow *parent)
+{
+ QWaylandWindow *parent_wayland_window = static_cast<QWaylandWindow *>(parent->handle());
+ if (!parent_wayland_window)
+ return;
+
+ // set_transient expects a position relative to the parent
+ QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
+ QWindow *parentWin = m_window->window()->transientParent();
+ transientPos -= parentWin->geometry().topLeft();
+ if (parent_wayland_window->decoration()) {
+ transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left());
+ transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
+ }
+
+ uint32_t flags = 0;
+ Qt::WindowFlags wf = m_window->window()->flags();
+ if (wf.testFlag(Qt::ToolTip)
+ || wf.testFlag(Qt::WindowTransparentForInput))
+ flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
+
+ set_transient(parent_wayland_window->object(),
+ transientPos.x(),
+ transientPos.y(),
+ flags);
+}
+
+void QWaylandShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial)
+{
+ QWaylandWindow *parent_wayland_window = parent;
+ if (!parent_wayland_window)
+ return;
+
+ // set_popup expects a position relative to the parent
+ QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
+ transientPos -= parent_wayland_window->geometry().topLeft();
+ if (parent_wayland_window->decoration()) {
+ transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left());
+ transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
+ }
+
+ set_popup(device->wl_seat(), serial, parent_wayland_window->object(),
+ transientPos.x(), transientPos.y(), 0);
+}
+
+void QWaylandShellSurface::shell_surface_ping(uint32_t serial)
+{
+ pong(serial);
+}
+
+void QWaylandShellSurface::shell_surface_configure(uint32_t edges,
+ int32_t width,
+ int32_t height)
+{
+ m_window->configure(edges, width, height);
+}
+
+void QWaylandShellSurface::shell_surface_popup_done()
+{
+ QCoreApplication::postEvent(m_window->window(), new QCloseEvent());
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandshellsurface.h b/src/client/qwaylandshellsurface.h
new file mode 100644
index 000000000..25f703334
--- /dev/null
+++ b/src/client/qwaylandshellsurface.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSHELLSURFACE_H
+#define QWAYLANDSHELLSURFACE_H
+
+#include <QtCore/QSize>
+
+#include <wayland-client.h>
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandWindow;
+class QWaylandInputDevice;
+class QWindow;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandShellSurface : public QtWayland::wl_shell_surface
+{
+public:
+ QWaylandShellSurface(struct ::wl_shell_surface *shell_surface, QWaylandWindow *window);
+ ~QWaylandShellSurface();
+
+ using QtWayland::wl_shell_surface::resize;
+ void resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges);
+
+ using QtWayland::wl_shell_surface::move;
+ void move(QWaylandInputDevice *inputDevice);
+
+private:
+ void setMaximized();
+ void setFullscreen();
+ void setNormal();
+ void setMinimized();
+
+ void setTopLevel();
+ void updateTransientParent(QWindow *parent);
+ void setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial);
+
+ QWaylandWindow *m_window;
+ bool m_maximized;
+ bool m_fullscreen;
+ QSize m_size;
+
+ void shell_surface_ping(uint32_t serial) Q_DECL_OVERRIDE;
+ void shell_surface_configure(uint32_t edges,
+ int32_t width,
+ int32_t height) Q_DECL_OVERRIDE;
+ void shell_surface_popup_done() Q_DECL_OVERRIDE;
+
+ friend class QWaylandWindow;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDSHELLSURFACE_H
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
new file mode 100644
index 000000000..00a4b13a2
--- /dev/null
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qwaylandshmbackingstore.h"
+
+#include <QtCore/qdebug.h>
+
+#include "qwaylanddisplay.h"
+#include "qwaylandshmwindow.h"
+#include "qwaylandscreen.h"
+#include "qwaylanddecoration.h"
+
+#include <QtGui/QPainter>
+
+#include <wayland-client.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
+ const QSize &size, QImage::Format format)
+ : mMarginsImage(0)
+{
+ int stride = size.width() * 4;
+ int alloc = stride * size.height();
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ int fd = mkstemp(filename);
+ if (fd < 0) {
+ qWarning("mkstemp %s failed: %s", filename, strerror(errno));
+ return;
+ }
+ int flags = fcntl(fd, F_GETFD);
+ if (flags != -1)
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+
+ if (ftruncate(fd, alloc) < 0) {
+ qWarning("ftruncate failed: %s", strerror(errno));
+ close(fd);
+ return;
+ }
+ uchar *data = (uchar *)
+ mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ unlink(filename);
+
+ if (data == (uchar *) MAP_FAILED) {
+ qWarning("mmap /dev/zero failed: %s", strerror(errno));
+ close(fd);
+ return;
+ }
+
+ mImage = QImage(data, size.width(), size.height(), stride, format);
+ mShmPool = wl_shm_create_pool(display->shm(), fd, alloc);
+ mBuffer = wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
+ stride, WL_SHM_FORMAT_ARGB8888);
+ close(fd);
+}
+
+QWaylandShmBuffer::~QWaylandShmBuffer(void)
+{
+ delete mMarginsImage;
+ munmap((void *) mImage.constBits(), mImage.byteCount());
+ wl_buffer_destroy(mBuffer);
+ wl_shm_pool_destroy(mShmPool);
+}
+
+QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &margins)
+{
+ if (!margins.isNull() && margins != mMargins) {
+ if (mMarginsImage) {
+ delete mMarginsImage;
+ }
+ uchar *bits = const_cast<uchar *>(mImage.constBits());
+ uchar *b_s_data = bits + margins.top() * mImage.bytesPerLine() + margins.left() * 4;
+ int b_s_width = mImage.size().width() - margins.left() - margins.right();
+ int b_s_height = mImage.size().height() - margins.top() - margins.bottom();
+ mMarginsImage = new QImage(b_s_data, b_s_width,b_s_height,mImage.bytesPerLine(),mImage.format());
+ }
+ if (margins.isNull()) {
+ delete mMarginsImage;
+ mMarginsImage = 0;
+ }
+
+ mMargins = margins;
+ if (!mMarginsImage)
+ return &mImage;
+
+ return mMarginsImage;
+
+}
+
+QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+ , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
+ , mFrontBuffer(0)
+ , mBackBuffer(0)
+ , mFrontBufferIsDirty(false)
+ , mPainting(false)
+ , mFrameCallback(0)
+{
+
+}
+
+QWaylandShmBackingStore::~QWaylandShmBackingStore()
+{
+ if (mFrameCallback)
+ wl_callback_destroy(mFrameCallback);
+
+// if (mFrontBuffer == waylandWindow()->attached())
+// waylandWindow()->attach(0);
+
+ if (mFrontBuffer != mBackBuffer)
+ delete mFrontBuffer;
+
+ delete mBackBuffer;
+}
+
+QPaintDevice *QWaylandShmBackingStore::paintDevice()
+{
+ if (!windowDecoration())
+ return mBackBuffer->image();
+ return mBackBuffer->imageInsideMargins(windowDecorationMargins());
+}
+
+void QWaylandShmBackingStore::beginPaint(const QRegion &)
+{
+ mPainting = true;
+ ensureSize();
+
+ if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached() && mFrameCallback) {
+ QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
+ Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
+ waylandWindow->waitForFrameSync();
+ }
+
+ waylandWindow()->setCanResize(false);
+}
+
+void QWaylandShmBackingStore::endPaint()
+{
+ mPainting = false;
+ waylandWindow()->setCanResize(true);
+}
+
+void QWaylandShmBackingStore::ensureSize()
+{
+ waylandWindow()->setBackingStore(this);
+ waylandWindow()->createDecoration();
+ resize(mRequestedSize);
+}
+
+void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(offset);
+ Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm);
+
+ if (windowDecoration() && windowDecoration()->isDirty())
+ updateDecorations();
+
+ mFrontBuffer = mBackBuffer;
+
+ if (mFrameCallback) {
+ mFrontBufferIsDirty = true;
+ return;
+ }
+
+ mFrameCallback = waylandWindow()->frame();
+ wl_callback_add_listener(mFrameCallback,&frameCallbackListener,this);
+ QMargins margins = windowDecorationMargins();
+
+ bool damageAll = false;
+ if (waylandWindow()->attached() != mFrontBuffer) {
+ delete waylandWindow()->attached();
+ damageAll = true;
+ }
+ waylandWindow()->attachOffset(mFrontBuffer);
+
+ if (damageAll) {
+ //need to damage it all, otherwise the attach offset may screw up
+ waylandWindow()->damage(QRect(QPoint(0,0),mFrontBuffer->size()));
+ } else {
+ QVector<QRect> rects = region.rects();
+ for (int i = 0; i < rects.size(); i++) {
+ QRect rect = rects.at(i);
+ rect.translate(margins.left(),margins.top());
+ waylandWindow()->damage(rect);
+ }
+ }
+ waylandWindow()->commit();
+ mFrontBufferIsDirty = false;
+}
+
+void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
+{
+ mRequestedSize = size;
+}
+
+void QWaylandShmBackingStore::resize(const QSize &size)
+{
+ QMargins margins = windowDecorationMargins();
+ QSize sizeWithMargins = size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom());
+
+ QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
+
+ if (mBackBuffer != NULL && mBackBuffer->size() == sizeWithMargins)
+ return;
+
+ if (mBackBuffer != mFrontBuffer) {
+ delete mBackBuffer; //we delete the attached buffer when we flush
+ }
+
+ mBackBuffer = new QWaylandShmBuffer(mDisplay, sizeWithMargins, format);
+
+ if (windowDecoration() && window()->isVisible())
+ windowDecoration()->update();
+}
+
+QImage *QWaylandShmBackingStore::entireSurface() const
+{
+ return mBackBuffer->image();
+}
+
+void QWaylandShmBackingStore::updateDecorations()
+{
+ QPainter decorationPainter(entireSurface());
+ decorationPainter.setCompositionMode(QPainter::CompositionMode_Source);
+ QImage sourceImage = windowDecoration()->contentImage();
+ QRect target;
+ //Top
+ target.setX(0);
+ target.setY(0);
+ target.setWidth(sourceImage.width());
+ target.setHeight(windowDecorationMargins().top());
+ decorationPainter.drawImage(target, sourceImage, target);
+
+ //Left
+ target.setWidth(windowDecorationMargins().left());
+ target.setHeight(sourceImage.height());
+ decorationPainter.drawImage(target, sourceImage, target);
+
+ //Right
+ target.setX(sourceImage.width() - windowDecorationMargins().right());
+ decorationPainter.drawImage(target, sourceImage, target);
+
+ //Bottom
+ target.setX(0);
+ target.setY(sourceImage.height() - windowDecorationMargins().bottom());
+ target.setWidth(sourceImage.width());
+ target.setHeight(windowDecorationMargins().bottom());
+ decorationPainter.drawImage(target, sourceImage, target);
+}
+
+void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time)
+{
+ Q_UNUSED(time);
+ QWaylandShmBackingStore *self =
+ static_cast<QWaylandShmBackingStore *>(data);
+ if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too
+ return;
+ QWaylandShmWindow *window = self->waylandWindow();
+ wl_callback_destroy(self->mFrameCallback);
+ self->mFrameCallback = 0;
+
+
+ if (self->mFrontBufferIsDirty && !self->mPainting) {
+ self->mFrontBufferIsDirty = false;
+ self->mFrameCallback = wl_surface_frame(window->object());
+ wl_callback_add_listener(self->mFrameCallback,&self->frameCallbackListener,self);
+ if (self->mFrontBuffer != window->attached()) {
+ delete window->attached();
+ }
+ window->attachOffset(self->mFrontBuffer);
+ window->damage(QRect(QPoint(0,0),self->mFrontBuffer->size()));
+ window->commit();
+ }
+}
+
+const struct wl_callback_listener QWaylandShmBackingStore::frameCallbackListener = {
+ QWaylandShmBackingStore::done
+};
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandshmbackingstore.h b/src/client/qwaylandshmbackingstore.h
new file mode 100644
index 000000000..c7875f52c
--- /dev/null
+++ b/src/client/qwaylandshmbackingstore.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSHMBACKINGSTORE_H
+#define QWAYLANDSHMBACKINGSTORE_H
+
+#include "qwaylandbuffer.h"
+
+#include "qwaylanddecoration.h"
+#include "qwaylandshmwindow.h"
+
+#include <qpa/qplatformbackingstore.h>
+#include <QtGui/QImage>
+#include <qpa/qplatformwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer {
+public:
+ QWaylandShmBuffer(QWaylandDisplay *display,
+ const QSize &size, QImage::Format format);
+ ~QWaylandShmBuffer();
+ QSize size() const { return mImage.size(); }
+ QImage *image() { return &mImage; }
+
+ QImage *imageInsideMargins(const QMargins &margins);
+private:
+ QImage mImage;
+ struct wl_shm_pool *mShmPool;
+ QMargins mMargins;
+ QImage *mMarginsImage;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingStore
+{
+public:
+ QWaylandShmBackingStore(QWindow *window);
+ ~QWaylandShmBackingStore();
+
+ QPaintDevice *paintDevice();
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset);
+ void resize(const QSize &size, const QRegion &staticContents);
+ void resize(const QSize &size);
+ void beginPaint(const QRegion &);
+ void endPaint();
+
+ QWaylandDecoration *windowDecoration() const;
+
+ QMargins windowDecorationMargins() const;
+ QImage *entireSurface() const;
+ void ensureSize();
+
+ QWaylandShmWindow *waylandWindow() const;
+ void iterateBuffer();
+
+private:
+ void updateDecorations();
+
+ QWaylandDisplay *mDisplay;
+ QWaylandShmBuffer *mFrontBuffer;
+ QWaylandShmBuffer *mBackBuffer;
+ bool mFrontBufferIsDirty;
+ bool mPainting;
+
+ QSize mRequestedSize;
+ Qt::WindowFlags mCurrentWindowFlags;
+
+ static const struct wl_callback_listener frameCallbackListener;
+ static void done(void *data,
+ struct wl_callback *callback,
+ uint32_t time);
+ struct wl_callback *mFrameCallback;
+};
+
+inline QWaylandDecoration *QWaylandShmBackingStore::windowDecoration() const
+{
+ return waylandWindow()->decoration();
+}
+
+inline QMargins QWaylandShmBackingStore::windowDecorationMargins() const
+{
+ if (windowDecoration())
+ return windowDecoration()->margins();
+ return QMargins();
+}
+
+inline QWaylandShmWindow *QWaylandShmBackingStore::waylandWindow() const
+{
+ return static_cast<QWaylandShmWindow *>(window()->handle());
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/client/qwaylandshmwindow.cpp b/src/client/qwaylandshmwindow.cpp
new file mode 100644
index 000000000..48a1bfd53
--- /dev/null
+++ b/src/client/qwaylandshmwindow.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandshmwindow.h"
+
+#include "qwaylandbuffer.h"
+
+#include <QtCore/QVector>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandShmWindow::QWaylandShmWindow(QWindow *window)
+ : QWaylandWindow(window)
+ , mBackingStore(0)
+{
+}
+
+QWaylandShmWindow::~QWaylandShmWindow()
+{
+
+}
+
+QWaylandWindow::WindowType QWaylandShmWindow::windowType() const
+{
+ return QWaylandWindow::Shm;
+}
+
+void QWaylandShmWindow::setBackingStore(QWaylandShmBackingStore *backingStore)
+{
+ mBackingStore = backingStore;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandshmwindow.h b/src/client/qwaylandshmwindow.h
new file mode 100644
index 000000000..e443bb187
--- /dev/null
+++ b/src/client/qwaylandshmwindow.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSHMWINDOW_H
+#define QWAYLANDSHMWINDOW_H
+
+#include "qwaylandwindow.h"
+#include <QtGui/QRegion>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandShmBackingStore;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow
+{
+public:
+ QWaylandShmWindow(QWindow *window);
+ ~QWaylandShmWindow();
+
+ WindowType windowType() const;
+ QSurfaceFormat format() const { return QSurfaceFormat(); }
+
+ void setBackingStore(QWaylandShmBackingStore *backingStore);
+ QWaylandShmBackingStore *backingStore() const;
+
+private:
+ QWaylandShmBackingStore *mBackingStore;
+};
+
+inline QWaylandShmBackingStore *QWaylandShmWindow::backingStore() const
+{
+ return mBackingStore;
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDSHMWINDOW_H
diff --git a/src/client/qwaylandsubsurface.cpp b/src/client/qwaylandsubsurface.cpp
new file mode 100644
index 000000000..0e9d575a9
--- /dev/null
+++ b/src/client/qwaylandsubsurface.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandsubsurface.h"
+
+#include "qwaylandwindow.h"
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandSubSurface::QWaylandSubSurface(QWaylandWindow *window, struct ::qt_sub_surface *sub_surface)
+ : QtWayland::qt_sub_surface(sub_surface)
+ , m_window(window)
+{
+}
+
+void QWaylandSubSurface::setParent(const QWaylandWindow *parent)
+{
+ QWaylandSubSurface *parentSurface = parent ? parent->subSurfaceWindow() : 0;
+ if (parentSurface) {
+ int x = m_window->geometry().x() + parent->frameMargins().left();
+ int y = m_window->geometry().y() + parent->frameMargins().top();
+ parentSurface->attach_sub_surface(object(), x, y);
+ }
+}
+
+static void setPositionToParent(QWaylandWindow *parentWaylandWindow)
+{
+ QObjectList children = parentWaylandWindow->window()->children();
+ for (int i = 0; i < children.size(); i++) {
+ QWindow *childWindow = qobject_cast<QWindow *>(children.at(i));
+ if (!childWindow)
+ continue;
+
+ if (childWindow->handle()) {
+ QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(childWindow->handle());
+ waylandWindow->subSurfaceWindow()->setParent(parentWaylandWindow);
+ setPositionToParent(waylandWindow);
+ }
+ }
+}
+
+void QWaylandSubSurface::adjustPositionOfChildren()
+{
+ QWindow *window = m_window->window();
+ if (window->parent()) {
+ qDebug() << "QWaylandSubSurface::adjustPositionOfChildren not called for toplevel window";
+ }
+ setPositionToParent(m_window);
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandsubsurface.h b/src/client/qwaylandsubsurface.h
new file mode 100644
index 000000000..97158b6aa
--- /dev/null
+++ b/src/client/qwaylandsubsurface.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSUBSURFACE_H
+#define QWAYLANDSUBSURFACE_H
+
+#include <wayland-client.h>
+
+#include <QtCore/qglobal.h>
+
+#include <QtWaylandClient/qwaylandclientexport.h>
+
+#include <QtWaylandClient/private/qwayland-sub-surface-extension.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandWindow;
+class QWaylandSubSurface;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandSubSurface : public QtWayland::qt_sub_surface
+{
+public:
+ QWaylandSubSurface(QWaylandWindow *window, struct ::qt_sub_surface *sub_surface);
+
+ void setParent(const QWaylandWindow *parent);
+ void adjustPositionOfChildren();
+
+private:
+ QWaylandWindow *m_window;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDSUBSURFACE_H
diff --git a/src/client/qwaylandtouch.cpp b/src/client/qwaylandtouch.cpp
new file mode 100644
index 000000000..5835d9d3c
--- /dev/null
+++ b/src/client/qwaylandtouch.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandtouch.h"
+#include "qwaylandinputdevice.h"
+
+QT_BEGIN_NAMESPACE
+
+QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id)
+ : QtWayland::qt_touch_extension(display->wl_registry(), id),
+ mDisplay(display),
+ mTouchDevice(0),
+ mPointsLeft(0),
+ mFlags(0),
+ mMouseSourceId(-1),
+ mInputDevice(0)
+{
+}
+
+void QWaylandTouchExtension::registerDevice(int caps)
+{
+ mTouchDevice = new QTouchDevice;
+ mTouchDevice->setType(QTouchDevice::TouchScreen);
+ mTouchDevice->setCapabilities(QTouchDevice::Capabilities(caps));
+ QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+}
+
+static inline qreal fromFixed(int f)
+{
+ return f / qreal(10000);
+}
+
+void QWaylandTouchExtension::touch_extension_touch(uint32_t time,
+ uint32_t id, uint32_t state, int32_t x, int32_t y,
+ int32_t normalized_x, int32_t normalized_y,
+ int32_t width, int32_t height, uint32_t pressure,
+ int32_t velocity_x, int32_t velocity_y,
+ uint32_t flags, wl_array *rawdata)
+{
+ if (!mInputDevice) {
+ QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
+ if (inputDevices.isEmpty()) {
+ qWarning("qt_touch_extension: handle_touch: No input devices");
+ return;
+ }
+ mInputDevice = inputDevices.first();
+ }
+ QWaylandWindow *win = mInputDevice->mTouchFocus;
+ if (!win)
+ win = mInputDevice->mPointerFocus;
+ if (!win)
+ win = mInputDevice->mKeyboardFocus;
+ if (!win || !win->window()) {
+ qWarning("qt_touch_extension: handle_touch: No pointer focus");
+ return;
+ }
+ mTargetWindow = win->window();
+
+ QWindowSystemInterface::TouchPoint tp;
+ tp.id = id;
+ tp.state = Qt::TouchPointState(int(state & 0xFFFF));
+ int sentPointCount = state >> 16;
+ if (!mPointsLeft) {
+ Q_ASSERT(sentPointCount > 0);
+ mPointsLeft = sentPointCount;
+ }
+ tp.flags = QTouchEvent::TouchPoint::InfoFlags(int(flags & 0xFFFF));
+
+ if (!mTouchDevice)
+ registerDevice(flags >> 16);
+
+ tp.area = QRectF(0, 0, fromFixed(width), fromFixed(height));
+ // Got surface-relative coords but need a (virtual) screen position.
+ QPointF relPos = QPointF(fromFixed(x), fromFixed(y));
+ QPointF delta = relPos - relPos.toPoint();
+ tp.area.moveCenter(mTargetWindow->mapToGlobal(relPos.toPoint()) + delta);
+
+ tp.normalPosition.setX(fromFixed(normalized_x));
+ tp.normalPosition.setY(fromFixed(normalized_y));
+ tp.pressure = pressure / 255.0;
+ tp.velocity.setX(fromFixed(velocity_x));
+ tp.velocity.setY(fromFixed(velocity_y));
+
+ if (rawdata) {
+ const int rawPosCount = rawdata->size / sizeof(float) / 2;
+ float *p = static_cast<float *>(rawdata->data);
+ for (int i = 0; i < rawPosCount; ++i) {
+ float x = *p++;
+ float y = *p++;
+ tp.rawPositions.append(QPointF(x, y));
+ }
+ }
+
+ mTouchPoints.append(tp);
+ mTimestamp = time;
+
+ if (!--mPointsLeft)
+ sendTouchEvent();
+}
+
+void QWaylandTouchExtension::sendTouchEvent()
+{
+ // Copy all points, that are in the previous but not in the current list, as stationary.
+ 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;
+ }
+
+ QWindowSystemInterface::handleTouchEvent(mTargetWindow, mTimestamp, mTouchDevice, mTouchPoints);
+
+ Qt::TouchPointStates states = 0;
+ for (int i = 0; i < mTouchPoints.count(); ++i)
+ states |= mTouchPoints.at(i).state;
+
+ if (mFlags & QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH) {
+ if (states == Qt::TouchPointPressed)
+ mMouseSourceId = mTouchPoints.first().id;
+ for (int i = 0; i < mTouchPoints.count(); ++i) {
+ const QWindowSystemInterface::TouchPoint &tp(mTouchPoints.at(i));
+ if (tp.id == mMouseSourceId) {
+ Qt::MouseButtons buttons = tp.state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton;
+ mLastMouseGlobal = tp.area.center();
+ QPoint globalPoint = mLastMouseGlobal.toPoint();
+ QPointF delta = mLastMouseGlobal - globalPoint;
+ mLastMouseLocal = mTargetWindow->mapFromGlobal(globalPoint) + delta;
+ QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, buttons);
+ if (buttons == Qt::NoButton)
+ mMouseSourceId = -1;
+ break;
+ }
+ }
+ }
+
+ mPrevTouchPoints = mTouchPoints;
+ mTouchPoints.clear();
+
+ if (states == Qt::TouchPointReleased)
+ mPrevTouchPoints.clear();
+}
+
+void QWaylandTouchExtension::touchCanceled()
+{
+ mTouchPoints.clear();
+ mPrevTouchPoints.clear();
+ if (mMouseSourceId != -1)
+ QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, Qt::NoButton);
+}
+
+void QWaylandTouchExtension::touch_extension_configure(uint32_t flags)
+{
+ mFlags = flags;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandtouch.h b/src/client/qwaylandtouch.h
new file mode 100644
index 000000000..0d14330e7
--- /dev/null
+++ b/src/client/qwaylandtouch.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDTOUCh_H
+#define QWAYLANDTOUCH_H
+
+#include "qwaylanddisplay.h"
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtWaylandClient/private/qwayland-touch-extension.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTouchExtension : public QtWayland::qt_touch_extension
+{
+public:
+ QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id);
+
+ void touchCanceled();
+
+private:
+ void registerDevice(int caps);
+
+ QWaylandDisplay *mDisplay;
+
+ void touch_extension_touch(uint32_t time,
+ uint32_t id,
+ uint32_t state,
+ int32_t x,
+ int32_t y,
+ int32_t normalized_x,
+ int32_t normalized_y,
+ int32_t width,
+ int32_t height,
+ uint32_t pressure,
+ int32_t velocity_x,
+ int32_t velocity_y,
+ uint32_t flags,
+ struct wl_array *rawdata) Q_DECL_OVERRIDE;
+ void touch_extension_configure(uint32_t flags) Q_DECL_OVERRIDE;
+
+ void sendTouchEvent();
+
+ QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
+ QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
+ QTouchDevice *mTouchDevice;
+ uint32_t mTimestamp;
+ int mPointsLeft;
+ uint32_t mFlags;
+ int mMouseSourceId;
+ QPointF mLastMouseLocal;
+ QPointF mLastMouseGlobal;
+ QWindow *mTargetWindow;
+ QWaylandInputDevice *mInputDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTOUCH_H
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
new file mode 100644
index 000000000..b64d3e6ab
--- /dev/null
+++ b/src/client/qwaylandwindow.cpp
@@ -0,0 +1,608 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandwindow.h"
+
+#include "qwaylandbuffer.h"
+#include "qwaylanddisplay.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylandscreen.h"
+#include "qwaylandshellsurface.h"
+#include "qwaylandextendedsurface.h"
+#include "qwaylandsubsurface.h"
+#include "qwaylanddecoration.h"
+#include "qwaylandwindowmanagerintegration.h"
+
+#include <QtCore/QFileInfo>
+#include <QtGui/QWindow>
+
+#include <QGuiApplication>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandWindow *QWaylandWindow::mMouseGrab = 0;
+
+QWaylandWindow::QWaylandWindow(QWindow *window)
+ : QObject()
+ , QPlatformWindow(window)
+ , mScreen(QWaylandScreen::waylandScreenFromWindow(window))
+ , mDisplay(mScreen->display())
+ , mShellSurface(0)
+ , mExtendedWindow(0)
+ , mSubSurfaceWindow(0)
+ , mWindowDecoration(0)
+ , mMouseEventsInContentArea(false)
+ , mMousePressedInContentArea(Qt::NoButton)
+ , m_cursorShape(Qt::ArrowCursor)
+ , mBuffer(0)
+ , mWaitingForFrameSync(false)
+ , mFrameCallback(0)
+ , mRequestResizeSent(false)
+ , mCanResize(true)
+ , mSentInitialResize(false)
+ , mMouseDevice(0)
+ , mMouseSerial(0)
+ , mState(Qt::WindowNoState)
+{
+ init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
+
+ static WId id = 1;
+ mWindowId = id++;
+
+ if (mDisplay->shell() && window->type() & Qt::Window && !(window->flags() & Qt::BypassWindowManagerHint))
+ mShellSurface = new QWaylandShellSurface(mDisplay->shell()->get_shell_surface(object()), this);
+ if (mDisplay->windowExtension())
+ mExtendedWindow = new QWaylandExtendedSurface(this, mDisplay->windowExtension()->get_extended_surface(object()));
+ if (mDisplay->subSurfaceExtension())
+ mSubSurfaceWindow = new QWaylandSubSurface(this, mDisplay->subSurfaceExtension()->get_sub_surface_aware_surface(object()));
+
+ if (mShellSurface) {
+ // Set initial surface title
+ mShellSurface->set_title(window->title());
+
+ // Set surface class to the .desktop file name (obtained from executable name)
+ QFileInfo exeFileInfo(qApp->applicationFilePath());
+ QString className = exeFileInfo.baseName() + QLatin1String(".desktop");
+ mShellSurface->set_class(className);
+ }
+
+ if (QPlatformWindow::parent() && mSubSurfaceWindow) {
+ mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(QPlatformWindow::parent()));
+ } else if (window->transientParent() && mShellSurface) {
+ if (window->type() != Qt::Popup) {
+ mShellSurface->updateTransientParent(window->transientParent());
+ }
+ } else if (mShellSurface) {
+ mShellSurface->setTopLevel();
+ }
+
+ setWindowFlags(window->flags());
+ setGeometry(window->geometry());
+ setWindowState(window->windowState());
+}
+
+QWaylandWindow::~QWaylandWindow()
+{
+ if (isInitialized()) {
+ delete mShellSurface;
+ delete mExtendedWindow;
+ destroy();
+ }
+ if (mFrameCallback)
+ wl_callback_destroy(mFrameCallback);
+
+ QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
+ for (int i = 0; i < inputDevices.size(); ++i)
+ inputDevices.at(i)->handleWindowDestroyed(this);
+
+ const QWindow *parent = window();
+ foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
+ if (w->transientParent() == parent)
+ QWindowSystemInterface::handleCloseEvent(w);
+ }
+
+ if (mMouseGrab == this) {
+ mMouseGrab = 0;
+ }
+}
+
+QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
+{
+ return static_cast<QWaylandWindow *>(static_cast<QtWayland::wl_surface *>(wl_surface_get_user_data(surface)));
+}
+
+WId QWaylandWindow::winId() const
+{
+ return mWindowId;
+}
+
+void QWaylandWindow::setParent(const QPlatformWindow *parent)
+{
+ const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
+ if (subSurfaceWindow()) {
+ subSurfaceWindow()->setParent(parentWaylandWindow);
+ }
+}
+
+void QWaylandWindow::setWindowTitle(const QString &title)
+{
+ if (mShellSurface) {
+ mShellSurface->set_title(title);
+ }
+
+ if (mWindowDecoration && window()->isVisible())
+ mWindowDecoration->update();
+}
+
+void QWaylandWindow::setWindowIcon(const QIcon &icon)
+{
+ mWindowIcon = icon;
+
+ if (mWindowDecoration && window()->isVisible())
+ mWindowDecoration->update();
+}
+
+void QWaylandWindow::setGeometry(const QRect &rect)
+{
+ QPlatformWindow::setGeometry(QRect(rect.x(), rect.y(),
+ qBound(window()->minimumWidth(), rect.width(), window()->maximumWidth()),
+ qBound(window()->minimumHeight(), rect.height(), window()->maximumHeight())));
+
+ if (shellSurface() && window()->transientParent() && window()->type() != Qt::Popup)
+ shellSurface()->updateTransientParent(window()->transientParent());
+
+ if (mWindowDecoration && window()->isVisible())
+ mWindowDecoration->update();
+
+ if (mConfigure.isEmpty()) {
+ QWindowSystemInterface::handleGeometryChange(window(), geometry());
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
+ }
+}
+
+void QWaylandWindow::setVisible(bool visible)
+{
+ if (visible) {
+ if (mBuffer)
+ attach(mBuffer->buffer(), 0, 0);
+
+ if (window()->type() == Qt::Popup && transientParent()) {
+ QWaylandWindow *parent = transientParent();
+ mMouseDevice = parent->mMouseDevice;
+ mMouseSerial = parent->mMouseSerial;
+
+ if (mMouseDevice)
+ mShellSurface->setPopup(transientParent(), mMouseDevice, mMouseSerial);
+ }
+
+ if (!mSentInitialResize) {
+ QWindowSystemInterface::handleGeometryChange(window(), geometry());
+ mSentInitialResize = true;
+ }
+
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+ // Don't flush the events here, or else the newly visible window may start drawing, but since
+ // there was no frame before it will be stuck at the waitForFrameSync() in
+ // QWaylandShmBackingStore::beginPaint().
+ } else {
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion());
+ attach(static_cast<QWaylandBuffer *>(0), 0, 0);
+ }
+ damage(QRect(QPoint(0,0),geometry().size()));
+ commit();
+}
+
+
+void QWaylandWindow::raise()
+{
+ if (mExtendedWindow)
+ mExtendedWindow->raise();
+}
+
+
+void QWaylandWindow::lower()
+{
+ if (mExtendedWindow)
+ mExtendedWindow->lower();
+}
+
+void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
+{
+ QMutexLocker resizeLocker(&mResizeLock);
+ mConfigure.edges |= edges;
+ mConfigure.width = width;
+ mConfigure.height = height;
+
+ if (!mRequestResizeSent && !mConfigure.isEmpty()) {
+ mRequestResizeSent= true;
+ QMetaObject::invokeMethod(this, "requestResize", Qt::QueuedConnection);
+ }
+}
+
+void QWaylandWindow::doResize()
+{
+ if (mConfigure.isEmpty()) {
+ return;
+ }
+
+ int widthWithoutMargins = qMax(mConfigure.width-(frameMargins().left() +frameMargins().right()),1);
+ int heightWithoutMargins = qMax(mConfigure.height-(frameMargins().top()+frameMargins().bottom()),1);
+
+ widthWithoutMargins = qMax(widthWithoutMargins, window()->minimumSize().width());
+ heightWithoutMargins = qMax(heightWithoutMargins, window()->minimumSize().height());
+ QRect geometry = QRect(0,0, widthWithoutMargins, heightWithoutMargins);
+
+ int x = 0;
+ int y = 0;
+ QSize size = this->geometry().size();
+ if (mConfigure.edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
+ x = size.width() - geometry.width();
+ }
+ if (mConfigure.edges & WL_SHELL_SURFACE_RESIZE_TOP) {
+ y = size.height() - geometry.height();
+ }
+ mOffset += QPoint(x, y);
+
+ setGeometry(geometry);
+
+ mConfigure.clear();
+ QWindowSystemInterface::handleGeometryChange(window(), geometry);
+}
+
+void QWaylandWindow::setCanResize(bool canResize)
+{
+ QMutexLocker lock(&mResizeLock);
+ mCanResize = canResize;
+
+ if (canResize && !mConfigure.isEmpty()) {
+ doResize();
+ QWindowSystemInterface::handleExposeEvent(window(), geometry());
+ }
+}
+
+void QWaylandWindow::requestResize()
+{
+ QMutexLocker lock(&mResizeLock);
+
+ if (mCanResize) {
+ doResize();
+ }
+
+ mRequestResizeSent = false;
+ lock.unlock();
+ QWindowSystemInterface::handleExposeEvent(window(), geometry());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
+{
+ mBuffer = buffer;
+
+ if (mBuffer)
+ attach(mBuffer->buffer(), x, y);
+ else
+ QtWayland::wl_surface::attach(0, 0, 0);
+}
+
+void QWaylandWindow::attachOffset(QWaylandBuffer *buffer)
+{
+ attach(buffer, mOffset.x(), mOffset.y());
+ mOffset = QPoint();
+}
+
+QWaylandBuffer *QWaylandWindow::attached() const
+{
+ return mBuffer;
+}
+
+void QWaylandWindow::damage(const QRect &rect)
+{
+ //We have to do sync stuff before calling damage, or we might
+ //get a frame callback before we get the timestamp
+ if (!mWaitingForFrameSync) {
+ mFrameCallback = frame();
+ wl_callback_add_listener(mFrameCallback,&QWaylandWindow::callbackListener,this);
+ mWaitingForFrameSync = true;
+ }
+ if (mBuffer) {
+ damage(rect.x(), rect.y(), rect.width(), rect.height());
+ }
+}
+
+const wl_callback_listener QWaylandWindow::callbackListener = {
+ QWaylandWindow::frameCallback
+};
+
+void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uint32_t time)
+{
+ Q_UNUSED(time);
+ QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
+ if (callback != self->mFrameCallback) // might be a callback caused by the shm backingstore
+ return;
+ self->mWaitingForFrameSync = false;
+ if (self->mFrameCallback) {
+ wl_callback_destroy(self->mFrameCallback);
+ self->mFrameCallback = 0;
+ }
+}
+
+QMutex QWaylandWindow::mFrameSyncMutex;
+
+void QWaylandWindow::waitForFrameSync()
+{
+ QMutexLocker locker(&mFrameSyncMutex);
+ if (!mWaitingForFrameSync)
+ return;
+ mDisplay->flushRequests();
+ while (mWaitingForFrameSync)
+ mDisplay->blockingReadEvents();
+}
+
+QMargins QWaylandWindow::frameMargins() const
+{
+ if (mWindowDecoration)
+ return mWindowDecoration->margins();
+ return QPlatformWindow::frameMargins();
+}
+
+QWaylandShellSurface *QWaylandWindow::shellSurface() const
+{
+ return mShellSurface;
+}
+
+QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
+{
+ return mExtendedWindow;
+}
+
+QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
+{
+ return mSubSurfaceWindow;
+}
+
+void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
+{
+ if (mExtendedWindow)
+ mExtendedWindow->setContentOrientation(orientation);
+}
+
+void QWaylandWindow::setWindowState(Qt::WindowState state)
+{
+ if (mState == state) {
+ return;
+ }
+
+ // As of february 2013 QWindow::setWindowState sets the new state value after
+ // QPlatformWindow::setWindowState returns, so we cannot rely on QWindow::windowState
+ // here. We use then this mState variable.
+ mState = state;
+ createDecoration();
+ switch (state) {
+ case Qt::WindowFullScreen:
+ mShellSurface->setFullscreen();
+ break;
+ case Qt::WindowMaximized:
+ mShellSurface->setMaximized();
+ break;
+ case Qt::WindowMinimized:
+ mShellSurface->setMinimized();
+ break;
+ default:
+ mShellSurface->setNormal();
+ }
+
+ QWindowSystemInterface::handleWindowStateChanged(window(), mState);
+ QWindowSystemInterface::flushWindowSystemEvents(); // Required for oldState to work on WindowStateChanged
+}
+
+void QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
+{
+ if (mExtendedWindow)
+ mExtendedWindow->setWindowFlags(flags);
+}
+
+bool QWaylandWindow::createDecoration()
+{
+ static bool disableWaylandDecorations = !qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").isEmpty();
+ if (disableWaylandDecorations)
+ return false;
+
+ bool decoration = false;
+ switch (window()->type()) {
+ case Qt::Window:
+ case Qt::Widget:
+ case Qt::Dialog:
+ case Qt::Tool:
+ case Qt::Drawer:
+ decoration = true;
+ break;
+ default:
+ break;
+ }
+ if (window()->flags() & Qt::FramelessWindowHint || isFullscreen())
+ decoration = false;
+ if (window()->flags() & Qt::BypassWindowManagerHint)
+ decoration = false;
+
+ if (decoration) {
+ if (!mWindowDecoration)
+ mWindowDecoration = new QWaylandDecoration(this);
+ } else {
+ delete mWindowDecoration;
+ mWindowDecoration = 0;
+ }
+
+ return mWindowDecoration;
+}
+
+QWaylandDecoration *QWaylandWindow::decoration() const
+{
+ return mWindowDecoration;
+}
+
+void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
+{
+ mWindowDecoration = decoration;
+ if (subSurfaceWindow()) {
+ subSurfaceWindow()->adjustPositionOfChildren();
+ }
+}
+
+static QWindow *topLevelWindow(QWindow *window)
+{
+ while (QWindow *parent = window->parent())
+ window = parent;
+ return window;
+}
+
+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.
+ return static_cast<QWaylandWindow *>(topLevelWindow(window()->transientParent())->handle());
+ }
+ return 0;
+}
+
+void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ if (b != Qt::NoButton) {
+ mMouseSerial = inputDevice->serial();
+ mMouseDevice = inputDevice;
+ }
+
+ if (mWindowDecoration) {
+ handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
+ return;
+ }
+
+ QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
+}
+
+void QWaylandWindow::handleMouseEnter(QWaylandInputDevice *inputDevice)
+{
+ if (!mWindowDecoration) {
+ QWindowSystemInterface::handleEnterEvent(window());
+ }
+ restoreMouseCursor(inputDevice);
+}
+
+void QWaylandWindow::handleMouseLeave(QWaylandInputDevice *inputDevice)
+{
+ if (mWindowDecoration) {
+ if (mMouseEventsInContentArea) {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ }
+ } else {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ }
+ restoreMouseCursor(inputDevice);
+}
+
+void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ if (mWindowDecoration->handleMouse(inputDevice,local,global,b,mods))
+ return;
+
+ QMargins marg = frameMargins();
+ QRect windowRect(0 + marg.left(),
+ 0 + marg.top(),
+ geometry().size().width() - marg.right(),
+ geometry().size().height() - marg.bottom());
+ if (windowRect.contains(local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
+ QPointF localTranslated = local;
+ QPointF globalTranslated = global;
+ localTranslated.setX(localTranslated.x() - marg.left());
+ localTranslated.setY(localTranslated.y() - marg.top());
+ globalTranslated.setX(globalTranslated.x() - marg.left());
+ globalTranslated.setY(globalTranslated.y() - marg.top());
+ if (!mMouseEventsInContentArea) {
+ restoreMouseCursor(inputDevice);
+ QWindowSystemInterface::handleEnterEvent(window());
+ }
+ QWindowSystemInterface::handleMouseEvent(window(), timestamp, localTranslated, globalTranslated, b, mods);
+ mMouseEventsInContentArea = true;
+ mMousePressedInContentArea = b;
+ } else {
+ if (mMouseEventsInContentArea) {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ mMouseEventsInContentArea = false;
+ }
+ mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
+ }
+}
+
+void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, Qt::CursorShape shape)
+{
+ if (m_cursorShape != shape || device->serial() > device->cursorSerial()) {
+ device->setCursor(shape, mScreen);
+ m_cursorShape = shape;
+ }
+}
+
+void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
+{
+ setMouseCursor(device, window()->cursor().shape());
+}
+
+void QWaylandWindow::requestActivateWindow()
+{
+ // no-op. Wayland does not have activation protocol,
+ // we rely on compositor setting keyboard focus based on window stacking.
+}
+
+bool QWaylandWindow::setMouseGrabEnabled(bool grab)
+{
+ if (window()->type() != Qt::Popup) {
+ qWarning("This plugin supports grabbing the mouse only for popup windows");
+ return false;
+ }
+
+ mMouseGrab = grab ? this : 0;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandwindow.h b/src/client/qwaylandwindow.h
new file mode 100644
index 000000000..c4d391807
--- /dev/null
+++ b/src/client/qwaylandwindow.h
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDWINDOW_H
+#define QWAYLANDWINDOW_H
+
+#include <QtCore/QWaitCondition>
+#include <QtCore/QMutex>
+#include <QtGui/QIcon>
+
+#include <qpa/qplatformwindow.h>
+
+#include "qwaylanddisplay.h"
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+
+struct wl_egl_window;
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandBuffer;
+class QWaylandShellSurface;
+class QWaylandExtendedSurface;
+class QWaylandSubSurface;
+class QWaylandDecoration;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure
+{
+public:
+ QWaylandWindowConfigure()
+ : width(0)
+ , height(0)
+ , edges(0)
+ { }
+
+ void clear()
+ { width = height = edges = 0; }
+
+ bool isEmpty() const
+ { return !height || !width; }
+
+ int width;
+ int height;
+ uint32_t edges;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow, public QtWayland::wl_surface
+{
+ Q_OBJECT
+public:
+ enum WindowType {
+ Shm,
+ Egl
+ };
+
+ QWaylandWindow(QWindow *window);
+ ~QWaylandWindow();
+
+ virtual WindowType windowType() const = 0;
+ WId winId() const;
+ void setVisible(bool visible);
+ void setParent(const QPlatformWindow *parent);
+
+ void setWindowTitle(const QString &title);
+
+ inline QIcon windowIcon() const;
+ void setWindowIcon(const QIcon &icon);
+
+ void setGeometry(const QRect &rect);
+
+ void configure(uint32_t edges, int32_t width, int32_t height);
+
+ using QtWayland::wl_surface::attach;
+ void attach(QWaylandBuffer *buffer, int x, int y);
+ void attachOffset(QWaylandBuffer *buffer);
+ QWaylandBuffer *attached() const;
+ QPoint attachOffset() const;
+
+ using QtWayland::wl_surface::damage;
+ void damage(const QRect &rect);
+
+ void waitForFrameSync();
+
+ QMargins frameMargins() const;
+
+ static QWaylandWindow *fromWlSurface(::wl_surface *surface);
+
+ QWaylandShellSurface *shellSurface() const;
+ QWaylandExtendedSurface *extendedWindow() const;
+ QWaylandSubSurface *subSurfaceWindow() const;
+
+ void handleContentOrientationChange(Qt::ScreenOrientation orientation);
+
+ void setWindowState(Qt::WindowState state);
+ void setWindowFlags(Qt::WindowFlags flags);
+
+ void raise() Q_DECL_OVERRIDE;
+ void lower() Q_DECL_OVERRIDE;
+
+ void requestActivateWindow() Q_DECL_OVERRIDE;
+
+ QWaylandDecoration *decoration() const;
+ void setDecoration(QWaylandDecoration *decoration);
+
+
+ void handleMouse(QWaylandInputDevice *inputDevice,
+ ulong timestamp,
+ const QPointF & local,
+ const QPointF & global,
+ Qt::MouseButtons b,
+ Qt::KeyboardModifiers mods);
+ void handleMouseEnter(QWaylandInputDevice *inputDevice);
+ void handleMouseLeave(QWaylandInputDevice *inputDevice);
+
+ bool createDecoration();
+
+ inline bool isMaximized() const { return mState == Qt::WindowMaximized; }
+ inline bool isFullscreen() const { return mState == Qt::WindowFullScreen; }
+
+ void setMouseCursor(QWaylandInputDevice *device, Qt::CursorShape shape);
+ void restoreMouseCursor(QWaylandInputDevice *device);
+
+ QWaylandWindow *transientParent() const;
+
+ QMutex *resizeMutex() { return &mResizeLock; }
+ void doResize();
+ void setCanResize(bool canResize);
+
+ bool setMouseGrabEnabled(bool grab);
+ static QWaylandWindow *mouseGrab() { return mMouseGrab; }
+
+public slots:
+ void requestResize();
+
+protected:
+ QWaylandScreen *mScreen;
+ QWaylandDisplay *mDisplay;
+ QWaylandShellSurface *mShellSurface;
+ QWaylandExtendedSurface *mExtendedWindow;
+ QWaylandSubSurface *mSubSurfaceWindow;
+
+ QWaylandDecoration *mWindowDecoration;
+ bool mMouseEventsInContentArea;
+ Qt::MouseButtons mMousePressedInContentArea;
+ Qt::CursorShape m_cursorShape;
+
+ QWaylandBuffer *mBuffer;
+ WId mWindowId;
+ bool mWaitingForFrameSync;
+ struct wl_callback *mFrameCallback;
+ QWaitCondition mFrameSyncWait;
+
+ QMutex mResizeLock;
+ QWaylandWindowConfigure mConfigure;
+ bool mRequestResizeSent;
+ bool mCanResize;
+
+ bool mSentInitialResize;
+ QPoint mOffset;
+
+ QIcon mWindowIcon;
+ QWaylandInputDevice *mMouseDevice;
+ int mMouseSerial;
+
+ Qt::WindowState mState;
+
+private:
+ void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice,
+ ulong timestamp,
+ const QPointF & local,
+ const QPointF & global,
+ Qt::MouseButtons b,
+ Qt::KeyboardModifiers mods);
+
+ static const wl_callback_listener callbackListener;
+ static void frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
+
+ static QMutex mFrameSyncMutex;
+ static QWaylandWindow *mMouseGrab;
+};
+
+inline QIcon QWaylandWindow::windowIcon() const
+{
+ return mWindowIcon;
+}
+
+inline QPoint QWaylandWindow::attachOffset() const
+{
+ return mOffset;
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDWINDOW_H
diff --git a/src/client/qwaylandwindowmanagerintegration.cpp b/src/client/qwaylandwindowmanagerintegration.cpp
new file mode 100644
index 000000000..7543ba13c
--- /dev/null
+++ b/src/client/qwaylandwindowmanagerintegration.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandwindowmanagerintegration.h"
+#include "qwaylandscreen.h"
+#include "qwaylandwindow.h"
+
+#include <stdint.h>
+#include <QtCore/QEvent>
+#include <QtCore/QHash>
+#include <QtCore/QUrl>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformwindow.h>
+#include <QtGui/QtEvents>
+#include <QtGui/QGuiApplication>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandWindowManagerIntegrationPrivate {
+public:
+ QWaylandWindowManagerIntegrationPrivate(QWaylandDisplay *waylandDisplay);
+ bool m_blockPropertyUpdates;
+ QWaylandDisplay *m_waylandDisplay;
+ QHash<QWindow*, QVariantMap> m_queuedProperties;
+ bool m_showIsFullScreen;
+};
+
+QWaylandWindowManagerIntegrationPrivate::QWaylandWindowManagerIntegrationPrivate(QWaylandDisplay *waylandDisplay)
+ : m_blockPropertyUpdates(false)
+ , m_waylandDisplay(waylandDisplay)
+ , m_showIsFullScreen(false)
+{
+
+}
+
+QWaylandWindowManagerIntegration::QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay)
+ : d_ptr(new QWaylandWindowManagerIntegrationPrivate(waylandDisplay))
+{
+ waylandDisplay->addRegistryListener(&wlHandleListenerGlobal, this);
+}
+
+QWaylandWindowManagerIntegration::~QWaylandWindowManagerIntegration()
+{
+
+}
+
+bool QWaylandWindowManagerIntegration::showIsFullScreen() const
+{
+ Q_D(const QWaylandWindowManagerIntegration);
+ return d->m_showIsFullScreen;
+}
+
+void QWaylandWindowManagerIntegration::wlHandleListenerGlobal(void *data, wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == "qt_windowmanager")
+ static_cast<QWaylandWindowManagerIntegration *>(data)->init(registry, id);
+}
+
+void QWaylandWindowManagerIntegration::windowmanager_hints(int32_t showIsFullScreen)
+{
+ Q_D(QWaylandWindowManagerIntegration);
+ d->m_showIsFullScreen = showIsFullScreen;
+}
+
+void QWaylandWindowManagerIntegration::windowmanager_quit()
+{
+ QGuiApplication::quit();
+}
+
+QByteArray QWaylandWindowManagerIntegration::desktopEnvironment() const
+{
+ const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP");
+ if (!xdgCurrentDesktop.isEmpty())
+ return xdgCurrentDesktop.toUpper(); // KDE, GNOME, UNITY, LXDE, MATE, XFCE...
+
+ // Classic fallbacks
+ if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION"))
+ return QByteArrayLiteral("KDE");
+ if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID"))
+ return QByteArrayLiteral("GNOME");
+
+ // Fallback to checking $DESKTOP_SESSION (unreliable)
+ const QByteArray desktopSession = qgetenv("DESKTOP_SESSION");
+ if (desktopSession == "gnome")
+ return QByteArrayLiteral("GNOME");
+ if (desktopSession == "xfce")
+ return QByteArrayLiteral("XFCE");
+
+ return QByteArrayLiteral("UNKNOWN");
+}
+
+void QWaylandWindowManagerIntegration::openUrl_helper(const QUrl &url)
+{
+ if (isInitialized()) {
+ QByteArray data = url.toString().toUtf8();
+
+ static const int chunkSize = 128;
+ while (!data.isEmpty()) {
+ QByteArray chunk = data.left(chunkSize);
+ data = data.mid(chunkSize);
+ open_url(!data.isEmpty(), QString::fromUtf8(chunk));
+ }
+ }
+}
+
+bool QWaylandWindowManagerIntegration::openUrl(const QUrl &url)
+{
+ openUrl_helper(url);
+ return true;
+}
+
+bool QWaylandWindowManagerIntegration::openDocument(const QUrl &url)
+{
+ openUrl_helper(url);
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandwindowmanagerintegration.h b/src/client/qwaylandwindowmanagerintegration.h
new file mode 100644
index 000000000..4506f06a1
--- /dev/null
+++ b/src/client/qwaylandwindowmanagerintegration.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDWINDOWMANAGERINTEGRATION_H
+#define QWAYLANDWINDOWMANAGERINTEGRATION_H
+
+#include <QtCore/QObject>
+#include <QtCore/QScopedPointer>
+
+#include "wayland-client.h"
+#include "qwaylanddisplay.h"
+#include <qpa/qplatformservices.h>
+
+#include "QtWaylandClient/private/qwayland-windowmanager.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandWindow;
+class QWaylandWindowManagerIntegrationPrivate;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowManagerIntegration : public QObject, public QPlatformServices, public QtWayland::qt_windowmanager
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandWindowManagerIntegration)
+public:
+ explicit QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay);
+ virtual ~QWaylandWindowManagerIntegration();
+
+ QByteArray desktopEnvironment() const;
+
+ bool openUrl(const QUrl &url);
+ bool openDocument(const QUrl &url);
+
+ bool showIsFullScreen() const;
+
+private:
+ static void wlHandleListenerGlobal(void *data, wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+
+ QScopedPointer<QWaylandWindowManagerIntegrationPrivate> d_ptr;
+
+ void windowmanager_hints(int32_t showIsFullScreen) Q_DECL_OVERRIDE;
+ void windowmanager_quit() Q_DECL_OVERRIDE;
+
+ void openUrl_helper(const QUrl &url);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDWINDOWMANAGERINTEGRATION_H