summaryrefslogtreecommitdiffstats
path: root/src/compositor/compositor_api/qwaylandcompositor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor/compositor_api/qwaylandcompositor.cpp')
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp840
1 files changed, 637 insertions, 203 deletions
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 04d1c4aed..a431cdde8 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -4,367 +4,801 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the Qt Compositor.
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
-** "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 The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-**
-** 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."
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwaylandcompositor.h"
+#include "qwaylandcompositor_p.h"
+
+#include <QtWaylandCompositor/qwaylandclient.h>
+#include <QtWaylandCompositor/qwaylandinput.h>
+#include <QtWaylandCompositor/qwaylandoutput.h>
+#include <QtWaylandCompositor/qwaylandview.h>
+#include <QtWaylandCompositor/qwaylandclient.h>
+#include <QtWaylandCompositor/qwaylandkeyboard.h>
+#include <QtWaylandCompositor/qwaylandpointer.h>
+#include <QtWaylandCompositor/qwaylandtouch.h>
-#include "qwaylandclient.h"
-#include "qwaylandinput.h"
-#include "qwaylandoutput.h"
-#include "qwaylandglobalinterface.h"
-#include "qwaylandsurfaceview.h"
+#include <QtWaylandCompositor/private/qwaylandkeyboard_p.h>
+#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
-#include "wayland_wrapper/qwlcompositor_p.h"
#include "wayland_wrapper/qwldatadevice_p.h"
-#include "wayland_wrapper/qwlsurface_p.h"
-#include "wayland_wrapper/qwlinputdevice_p.h"
-#include "wayland_wrapper/qwlinputpanel_p.h"
-#include "wayland_wrapper/qwlshellsurface_p.h"
+#include "wayland_wrapper/qwldatadevicemanager_p.h"
+
+#include "hardware_integration/qwlclientbufferintegration_p.h"
+#include "hardware_integration/qwlclientbufferintegrationfactory_p.h"
+#include "hardware_integration/qwlserverbufferintegration_p.h"
+#include "hardware_integration/qwlserverbufferintegrationfactory_p.h"
+#include "hardware_integration/qwlhwintegration_p.h"
+
+#include "extensions/qwaylandwindowmanagerextension.h"
+
+#include "qwaylandxkb.h"
+#include "qwaylandshmformathelper.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
+#include <QtCore/QSocketNotifier>
#include <QtGui/QDesktopServices>
#include <QtGui/QScreen>
-#include <QDebug>
+#include <QtGui/qpa/qwindowsysteminterface_p.h>
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QtGui/private/qguiapplication_p.h>
QT_BEGIN_NAMESPACE
-QWaylandCompositor::QWaylandCompositor(const char *socketName, ExtensionFlags extensions)
- : m_compositor(new QtWayland::Compositor(this, extensions))
+namespace QtWayland {
+
+class WindowSystemEventHandler : public QWindowSystemEventHandler
{
- m_compositor->m_socket_name = socketName;
- m_compositor->init();
-}
+public:
+ WindowSystemEventHandler(QWaylandCompositor *c) : compositor(c) {}
+ bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) Q_DECL_OVERRIDE
+ {
+ if (e->type == QWindowSystemInterfacePrivate::Key) {
+ QWindowSystemInterfacePrivate::KeyEvent *ke = static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e);
+ QWaylandKeyboardPrivate *keyb = QWaylandKeyboardPrivate::get(compositor->defaultInputDevice()->keyboard());
+
+ uint32_t code = ke->nativeScanCode;
+ bool isDown = ke->keyType == QEvent::KeyPress;
+
+#ifndef QT_NO_WAYLAND_XKB
+ QString text;
+ Qt::KeyboardModifiers modifiers = QWaylandXkb::modifiers(keyb->xkbState());
+
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(keyb->xkbState(), code);
+ uint utf32 = xkb_keysym_to_utf32(sym);
+ if (utf32)
+ text = QString::fromUcs4(&utf32, 1);
+ int qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text);
+
+ ke->key = qtkey;
+ ke->modifiers = modifiers;
+ ke->nativeVirtualKey = sym;
+ ke->nativeModifiers = keyb->xkbModsMask();
+ ke->unicode = text;
+#endif
+ if (!ke->repeat)
+ keyb->keyEvent(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
-QWaylandCompositor::QWaylandCompositor(const char *socketName, QtWayland::Compositor *dptr)
- : m_compositor(dptr)
+ QWindowSystemEventHandler::sendEvent(e);
+
+ if (!ke->repeat) {
+ keyb->updateKeymap();
+ keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
+ }
+ } else {
+ QWindowSystemEventHandler::sendEvent(e);
+ }
+ return true;
+ }
+
+ QWaylandCompositor *compositor;
+};
+
+} // namespace
+
+QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor)
+ : display(0)
+#if defined (QT_COMPOSITOR_WAYLAND_GL)
+ , use_hw_integration_extension(true)
+ , client_buffer_integration(0)
+ , server_buffer_integration(0)
+#endif
+ , retainSelection(false)
+ , initialized(false)
{
- m_compositor->m_socket_name = socketName;
- m_compositor->init();
+ display = static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("server_wl_display"));
+ if (!display)
+ display = wl_display_create();
+ eventHandler.reset(new QtWayland::WindowSystemEventHandler(compositor));
+ timer.start();
+
+ QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data());
}
-QWaylandCompositor::~QWaylandCompositor()
+void QWaylandCompositorPrivate::init()
{
- qDeleteAll(m_compositor->m_globals);
- delete m_compositor;
+ Q_Q(QWaylandCompositor);
+ QStringList arguments = QCoreApplication::instance()->arguments();
+
+ int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name"));
+ if (socketArg != -1 && socketArg + 1 < arguments.size())
+ socket_name = arguments.at(socketArg + 1).toLocal8Bit();
+
+ wl_compositor::init(display, 3);
+
+ data_device_manager = new QtWayland::DataDeviceManager(q);
+
+ wl_display_init_shm(display);
+ QVector<wl_shm_format> formats = QWaylandShmFormatHelper::supportedWaylandFormats();
+ foreach (wl_shm_format format, formats)
+ wl_display_add_shm_format(display, format);
+
+ const char *socketName = 0;
+ if (socket_name.size())
+ socketName = socket_name.constData();
+ if (wl_display_add_socket(display, socketName)) {
+ qFatal("Fatal: Failed to open server socket\n");
+ }
+
+ loop = wl_display_get_event_loop(display);
+
+ int fd = wl_event_loop_get_fd(loop);
+
+ QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, q);
+ QObject::connect(sockNot, SIGNAL(activated(int)), q, SLOT(processWaylandEvents()));
+
+ QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
+ QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents()));
+
+ initializeHardwareIntegration();
+ initializeDefaultInputDevice();
+
+ initialized = true;
+
+ Q_FOREACH (QPointer<QObject> object, polish_objects) {
+ if (object) {
+ QEvent polishEvent(QEvent::Polish);
+ QCoreApplication::sendEvent(object.data(), &polishEvent);
+ }
+ }
}
-void QWaylandCompositor::addGlobalInterface(QWaylandGlobalInterface *interface)
+QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
{
- wl_global_create(m_compositor->wl_display(), interface->interface(), interface->version(), interface, QtWayland::Compositor::bindGlobal);
- m_compositor->m_globals << interface;
+ qDeleteAll(clients);
+
+ qDeleteAll(outputs);
+
+ delete data_device_manager;
+
+ wl_display_destroy(display);
}
-void QWaylandCompositor::addDefaultShell()
+void QWaylandCompositorPrivate::destroySurface(QWaylandSurface *surface)
{
- addGlobalInterface(new QtWayland::Shell);
+ Q_Q(QWaylandCompositor);
+ q->surfaceAboutToBeDestroyed(surface);
+
+ delete surface;
}
-struct wl_display *QWaylandCompositor::waylandDisplay() const
+void QWaylandCompositorPrivate::unregisterSurface(QWaylandSurface *surface)
{
- return m_compositor->wl_display();
+ if (!all_surfaces.removeOne(surface))
+ qWarning("%s Unexpected state. Cant find registered surface\n", Q_FUNC_INFO);
}
-void QWaylandCompositor::sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces)
+void QWaylandCompositorPrivate::feedRetainedSelectionData(QMimeData *data)
{
- m_compositor->sendFrameCallbacks(visibleSurfaces);
+ Q_Q(QWaylandCompositor);
+ if (retainSelection)
+ q->retainedSelectionReceived(data);
}
-void QWaylandCompositor::frameStarted()
+void QWaylandCompositorPrivate::addPolishObject(QObject *object)
{
- foreach (QtWayland::Surface *surf, m_compositor->surfaces())
- surf->frameStarted();
+ if (initialized) {
+ QCoreApplication::postEvent(object, new QEvent(QEvent::Polish));
+ } else {
+ polish_objects.append(object);
+ }
}
-void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface)
+/*!
+ \qmlsignal void QtWaylandCompositor::WaylandCompositor::createSurface(object client, int id, int version)
+
+ This signal is emitted when a client has created a surface.
+ The slot connecting to this signal may create and initialize
+ a WaylandSurface instance in the scope of the slot.
+ Otherwise a default surface is created.
+*/
+
+/*!
+ \fn void QWaylandCompositor::createSurface(QWaylandClient *client, uint id, int version)
+
+ This signal is emitted when a client has created a surface.
+ The slot connecting to this signal may create and initialize
+ a QWaylandSurface instance in the scope of the slot.
+ Otherwise a default surface is created.
+
+ Connections to this signal must be of Qt::DirectConnection connection type.
+*/
+
+/*
+ \qmlsignal void surfaceCreated(QWaylandSurface *surface)
+
+ This signal is emitted when a new WaylandSurface instance has been created.
+*/
+
+/*
+ \fn void surfaceCreated(QWaylandSurface *surface)
+
+ This signal is emitted when a new QWaylandSurface instance has been created.
+*/
+
+
+void QWaylandCompositorPrivate::compositor_create_surface(Resource *resource, uint32_t id)
{
- destroyClient(surface->client());
+ Q_Q(QWaylandCompositor);
+ QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client());
+ emit q->createSurface(client, id, resource->version());
+#ifndef QT_NO_DEBUG
+ Q_ASSERT_X(!QWaylandSurfacePrivate::hasUninitializedSurface(), "QWaylandCompositor", QStringLiteral("Found uninitialized QWaylandSurface after emitting QWaylandCompositor::createSurface for id %1. All surfaces has to be initialized immediately after creation. See QWaylandSurface::initialize.").arg(id).toLocal8Bit().constData());
+#endif
+ struct wl_resource *surfResource = wl_client_get_object(client->client(), id);
+
+ QWaylandSurface *surface;
+ if (surfResource) {
+ surface = QWaylandSurface::fromResource(surfResource);
+ } else {
+ surface = createDefaultSurface();
+ surface->initialize(q, client, id, resource->version());
+ }
+ Q_ASSERT(surface);
+ all_surfaces.append(surface);
+ emit q->surfaceCreated(surface);
}
-void QWaylandCompositor::destroyClient(QWaylandClient *client)
+void QWaylandCompositorPrivate::compositor_create_region(Resource *resource, uint32_t id)
{
- m_compositor->destroyClient(client);
+ new QtWayland::Region(resource->client(), id);
}
-QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const
+/*!
+ \internal
+ Used to create a fallback QWaylandSurface when no surface was
+ created by emitting the QWaylandCompositor::createSurface signal.
+*/
+QWaylandSurface *QWaylandCompositorPrivate::createDefaultSurface()
{
- QList<QtWayland::Surface *> surfaces = m_compositor->surfaces();
+ return new QWaylandSurface();
+}
- QList<QWaylandSurface *> result;
- for (int i = 0; i < surfaces.count(); ++i) {
- if (surfaces.at(i)->waylandSurface()->client() == client) {
- result.append(surfaces.at(i)->waylandSurface());
- }
- }
+void QWaylandCompositorPrivate::initializeHardwareIntegration()
+{
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ Q_Q(QWaylandCompositor);
+ if (use_hw_integration_extension)
+ hw_integration.reset(new QtWayland::HardwareIntegration(q));
+
+ loadClientBufferIntegration();
+ loadServerBufferIntegration();
- return result;
+ if (client_buffer_integration)
+ client_buffer_integration->initializeHardware(display);
+ if (server_buffer_integration)
+ server_buffer_integration->initializeHardware(q);
+#endif
}
-QList<QWaylandSurface *> QWaylandCompositor::surfaces() const
+void QWaylandCompositorPrivate::initializeDefaultInputDevice()
{
- QList<QtWayland::Surface *> surfaces = m_compositor->surfaces();
- QList<QWaylandSurface *> surfs;
- surfs.reserve(surfaces.count());
- foreach (QtWayland::Surface *s, surfaces)
- surfs << s->waylandSurface();
- return surfs;
+ Q_Q(QWaylandCompositor);
+ inputDevices.append(q->createInputDevice());
+ q->defaultInputDeviceChanged();
}
-QList<QWaylandOutput *> QWaylandCompositor::outputs() const
+void QWaylandCompositorPrivate::loadClientBufferIntegration()
{
- return m_compositor->outputs();
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ Q_Q(QWaylandCompositor);
+ QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys();
+ QString targetKey;
+ QByteArray clientBufferIntegration = qgetenv("QT_WAYLAND_HARDWARE_INTEGRATION");
+ if (clientBufferIntegration.isEmpty())
+ clientBufferIntegration = qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION");
+ if (keys.contains(QString::fromLocal8Bit(clientBufferIntegration.constData()))) {
+ targetKey = QString::fromLocal8Bit(clientBufferIntegration.constData());
+ } else if (keys.contains(QString::fromLatin1("wayland-egl"))) {
+ targetKey = QString::fromLatin1("wayland-egl");
+ } else if (!keys.isEmpty()) {
+ targetKey = keys.first();
+ }
+
+ if (!targetKey.isEmpty()) {
+ client_buffer_integration.reset(QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList()));
+ if (client_buffer_integration) {
+ client_buffer_integration->setCompositor(q);
+ if (hw_integration)
+ hw_integration->setClientBufferIntegration(targetKey);
+ }
+ }
+ //BUG: if there is no client buffer integration, bad things will happen when opengl is used
+#endif
}
-QWaylandOutput *QWaylandCompositor::output(QWindow *window)
+void QWaylandCompositorPrivate::loadServerBufferIntegration()
{
- return m_compositor->output(window);
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys();
+ QString targetKey;
+ QByteArray serverBufferIntegration = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
+ if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) {
+ targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData());
+ }
+ if (!targetKey.isEmpty()) {
+ server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList()));
+ if (hw_integration)
+ hw_integration->setServerBufferIntegration(targetKey);
+ }
+#endif
}
-QWaylandOutput *QWaylandCompositor::primaryOutput() const
+/*!
+ \qmltype WaylandCompositor
+ \inqmlmodule QtWayland.Compositor
+ \brief Type managing the Wayland display server.
+
+ The WaylandCompositor manages the connections to the clients, as well as the different
+ \l{WaylandOutput}{outputs} and \l{WaylandInput}{input devices}.
+
+ Normally, a compositor application will have a single WaylandCompositor
+ instance, which can have several outputs as children. When a client
+ requests the compositor to create a surface, the request is handled by
+ the onCreateSurface handler.
+
+ Extensions that are supported by the compositor should be instantiated and added to the
+ extensions property.
+*/
+
+
+/*!
+ \class QWaylandCompositor
+ \inmodule QtWaylandCompositor
+ \brief Class managing the Wayland display server.
+
+ The QWaylandCompositor manages the connections to the clients, as well as the different \l{QWaylandOutput}{outputs}
+ and \l{QWaylandInput}{input devices}.
+
+ Normally, a compositor application will have a single WaylandCompositor
+ instance, which can have several outputs as children.
+*/
+
+/*!
+ * Constructs a QWaylandCompositor with the given \a parent.
+ */
+QWaylandCompositor::QWaylandCompositor(QObject *parent)
+ : QWaylandObject(*new QWaylandCompositorPrivate(this), parent)
{
- return m_compositor->primaryOutput();
}
-void QWaylandCompositor::setPrimaryOutput(QWaylandOutput *output)
+/*!
+ * \internal
+ * Constructs a QWaylandCompositor with the private object \a dptr and \a parent.
+ */
+QWaylandCompositor::QWaylandCompositor(QWaylandCompositorPrivate &dptr, QObject *parent)
+ : QWaylandObject(dptr, parent)
{
- m_compositor->setPrimaryOutput(output);
}
-void QWaylandCompositor::cleanupGraphicsResources()
+/*!
+ * Destroys the QWaylandCompositor
+ */
+QWaylandCompositor::~QWaylandCompositor()
{
- m_compositor->cleanupGraphicsResources();
}
-void QWaylandCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface)
+/*!
+ * Initializes the QWaylandCompositor.
+ * If you override this function in your subclass, be sure to call the base class implementation.
+ */
+void QWaylandCompositor::create()
{
- Q_UNUSED(surface);
+ Q_D(QWaylandCompositor);
+ d->init();
}
-QWaylandSurfaceView *QWaylandCompositor::pickView(const QPointF &globalPosition) const
+/*!
+ * Returns true if the QWaylandCompositor has been initialized. Otherwise returns false.
+ */
+bool QWaylandCompositor::isCreated() const
{
- Q_FOREACH (QWaylandOutput *output, outputs()) {
- // Skip coordinates not in output
- if (!QRectF(output->geometry()).contains(globalPosition))
- continue;
+ Q_D(const QWaylandCompositor);
+ return d->initialized;
+}
- Q_FOREACH (QWaylandSurface *surface, output->surfaces()) {
- Q_FOREACH (QWaylandSurfaceView *view, surface->views()) {
- if (QRectF(view->pos(), surface->size()).contains(globalPosition))
- return view;
- }
- }
- }
+/*!
+ * \qmlproperty string QtWaylandCompositor::WaylandCompositor::socketName
+ *
+ * This property holds the socket name used by WaylandCompositor to communicate with
+ * clients. It must be set before the component is completed.
+ *
+ * If the socketName is empty (the default), the contents of the environment
+ * variable WAYLAND_DISPLAY is used instead. If this is not set, the
+ * default "wayland-0" is used.
+ */
- return Q_NULLPTR;
+/*!
+ * \property QWaylandCompositor::socketName
+ *
+ * This property holds the socket name used by QWaylandCompositor to communicate with
+ * clients. This must be set before the QWaylandCompositor is \l{create()}{created}.
+ *
+ * If the socketName is empty (the default), the contents of the environment
+ * variable WAYLAND_DISPLAY is used instead. If this is not set, the
+ * default "wayland-0" is used.
+ */
+void QWaylandCompositor::setSocketName(const QByteArray &name)
+{
+ Q_D(QWaylandCompositor);
+ if (d->initialized) {
+ qWarning("%s: Changing socket name after initializing the compositor is not supported.\n", Q_FUNC_INFO);
+ return;
+ }
+ d->socket_name = name;
}
-QPointF QWaylandCompositor::mapToView(QWaylandSurfaceView *surface, const QPointF &globalPosition) const
+QByteArray QWaylandCompositor::socketName() const
{
- return globalPosition - surface->pos();
+ Q_D(const QWaylandCompositor);
+ return d->socket_name;
}
/*!
- Override this to handle QDesktopServices::openUrl() requests from the clients.
-
- The default implementation simply forwards the request to QDesktopServices::openUrl().
-*/
-bool QWaylandCompositor::openUrl(QWaylandClient *client, const QUrl &url)
+ * \internal
+ */
+struct wl_display *QWaylandCompositor::display() const
{
- Q_UNUSED(client);
- return QDesktopServices::openUrl(url);
+ Q_D(const QWaylandCompositor);
+ return d->display;
}
-QtWayland::Compositor * QWaylandCompositor::handle() const
+/*!
+ * \internal
+ */
+uint32_t QWaylandCompositor::nextSerial()
{
- return m_compositor;
+ Q_D(QWaylandCompositor);
+ return wl_display_next_serial(d->display);
}
-void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled)
+/*!
+ * \internal
+ */
+QList<QWaylandClient *>QWaylandCompositor::clients() const
{
- m_compositor->setRetainedSelectionEnabled(enabled);
+ Q_D(const QWaylandCompositor);
+ return d->clients;
}
-bool QWaylandCompositor::retainedSelectionEnabled() const
+/*!
+ * \qmlmethod QtWaylandCompositor::WaylandCompositor::destroyClientForSurface(surface)
+ *
+ * Destroys the client for the WaylandSurface \a surface.
+ */
+
+/*!
+ * Destroys the client for the \a surface.
+ */
+void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface)
{
- return m_compositor->retainedSelectionEnabled();
+ destroyClient(surface->client());
}
-void QWaylandCompositor::retainedSelectionReceived(QMimeData *)
+/*!
+ * \qmlmethod QtWaylandCompositor::WaylandCompositor::destroyClient(client)
+ *
+ * Destroys the given WaylandClient \a client.
+ */
+
+/*!
+ * Destroys the \a client.
+ */
+void QWaylandCompositor::destroyClient(QWaylandClient *client)
{
+ if (!client)
+ return;
+
+ QWaylandWindowManagerExtension *wmExtension = QWaylandWindowManagerExtension::findIn(this);
+ if (wmExtension)
+ wmExtension->sendQuitMessage(client->client());
+
+ wl_client_destroy(client->client());
}
-void QWaylandCompositor::overrideSelection(const QMimeData *data)
+/*!
+ * \internal
+ */
+QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const
{
- m_compositor->overrideSelection(data);
+ Q_D(const QWaylandCompositor);
+ QList<QWaylandSurface *> surfs;
+ foreach (QWaylandSurface *surface, d->all_surfaces) {
+ if (surface->client() == client)
+ surfs.append(surface);
+ }
+ return surfs;
}
-void QWaylandCompositor::setClientFullScreenHint(bool value)
+/*!
+ * \internal
+ */
+QList<QWaylandSurface *> QWaylandCompositor::surfaces() const
{
- m_compositor->setClientFullScreenHint(value);
+ Q_D(const QWaylandCompositor);
+ return d->all_surfaces;
}
-const char *QWaylandCompositor::socketName() const
-{
- if (m_compositor->m_socket_name.isEmpty())
- return 0;
- return m_compositor->m_socket_name.constData();
+/*!
+ * Returns the QWaylandOutput that is connected to the given \a window.
+ */
+QWaylandOutput *QWaylandCompositor::outputFor(QWindow *window) const
+{
+ Q_D(const QWaylandCompositor);
+ foreach (QWaylandOutput *output, d->outputs) {
+ if (output->window() == window)
+ return output;
+ }
+
+ return Q_NULLPTR;
}
-#if QT_DEPRECATED_SINCE(5, 5)
/*!
- Set the screen orientation based on accelerometer data or similar.
-*/
-void QWaylandCompositor::setScreenOrientation(Qt::ScreenOrientation orientation)
+ * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultOutput
+ *
+ * This property contains the first in the list of outputs added to the
+ * WaylandCompositor, or null if no outputs have been added.
+ *
+ * Setting a new default output prepends it to the output list, making
+ * it the new default, but the previous default is not removed from
+ * the list.
+ */
+/*!
+ * \property QWaylandCompositor::defaultOutput
+ *
+ * This property contains the first in the list of outputs added to the
+ * QWaylandCompositor, or null if no outputs have been added.
+ *
+ * Setting a new default output prepends it to the output list, making
+ * it the new default, but the previous default is not removed from
+ * the list. If the new default output was already in the list of outputs,
+ * it is moved to the beginning of the list.
+ */
+QWaylandOutput *QWaylandCompositor::defaultOutput() const
{
- QWaylandOutput *output = primaryOutput();
- if (output) {
- bool isPortrait = output->window()->screen()->primaryOrientation() == Qt::PortraitOrientation;
-
- switch (orientation) {
- case Qt::PrimaryOrientation:
- output->setTransform(QWaylandOutput::TransformNormal);
- break;
- case Qt::LandscapeOrientation:
- output->setTransform(isPortrait ? QWaylandOutput::Transform270 : QWaylandOutput::TransformNormal);
- break;
- case Qt::PortraitOrientation:
- output->setTransform(isPortrait ? QWaylandOutput::TransformNormal : QWaylandOutput::Transform90);
- break;
- case Qt::InvertedLandscapeOrientation:
- output->setTransform(isPortrait ? QWaylandOutput::Transform90 : QWaylandOutput::Transform180);
- break;
- case Qt::InvertedPortraitOrientation:
- output->setTransform(isPortrait ? QWaylandOutput::Transform180 : QWaylandOutput::Transform270);
- break;
- }
- }
+ Q_D(const QWaylandCompositor);
+ return d->defaultOutput();
}
-void QWaylandCompositor::setOutputGeometry(const QRect &geometry)
+void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output)
{
- QWaylandOutput *output = primaryOutput();
- if (output)
- output->setGeometry(geometry);
+ Q_D(QWaylandCompositor);
+ if (d->outputs.size() && d->outputs.first() == output)
+ return;
+ d->outputs.removeOne(output);
+ d->outputs.prepend(output);
+ defaultOutputChanged();
}
-QRect QWaylandCompositor::outputGeometry() const
+/*!
+ * \internal
+ */
+QList<QWaylandOutput *> QWaylandCompositor::outputs() const
{
- QWaylandOutput *output = primaryOutput();
- if (output)
- return output->geometry();
- return QRect();
+ Q_D(const QWaylandCompositor);
+ return d->outputs;
}
-void QWaylandCompositor::setOutputRefreshRate(int rate)
+/*!
+ * \internal
+ */
+uint QWaylandCompositor::currentTimeMsecs() const
{
- QWaylandOutput *output = primaryOutput();
- if (output)
- output->setMode({output->mode().size, rate});
+ Q_D(const QWaylandCompositor);
+ return d->timer.elapsed();
}
-int QWaylandCompositor::outputRefreshRate() const
+/*!
+ * \internal
+ */
+void QWaylandCompositor::processWaylandEvents()
{
- QWaylandOutput *output = primaryOutput();
- if (output)
- return output->mode().refreshRate;
- return 0;
+ Q_D(QWaylandCompositor);
+ int ret = wl_event_loop_dispatch(d->loop, 0);
+ if (ret)
+ fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret);
+ wl_display_flush_clients(d->display);
}
-#endif
-QWaylandInputDevice *QWaylandCompositor::defaultInputDevice() const
+/*!
+ * \internal
+ */
+QWaylandInputDevice *QWaylandCompositor::createInputDevice()
{
- return m_compositor->defaultInputDevice()->handle();
+ return new QWaylandInputDevice(this);
}
-QWaylandInputPanel *QWaylandCompositor::inputPanel() const
+/*!
+ * \internal
+ */
+QWaylandPointer *QWaylandCompositor::createPointerDevice(QWaylandInputDevice *inputDevice)
{
- return m_compositor->inputPanel()->handle();
+ return new QWaylandPointer(inputDevice);
}
-QWaylandDrag *QWaylandCompositor::drag() const
+/*!
+ * \internal
+ */
+QWaylandKeyboard *QWaylandCompositor::createKeyboardDevice(QWaylandInputDevice *inputDevice)
{
- return m_compositor->defaultInputDevice()->dragHandle();
+ return new QWaylandKeyboard(inputDevice);
}
-bool QWaylandCompositor::isDragging() const
+/*!
+ * \internal
+ */
+QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandInputDevice *inputDevice)
{
- return m_compositor->isDragging();
+ return new QWaylandTouch(inputDevice);
}
-void QWaylandCompositor::sendDragMoveEvent(const QPoint &global, const QPoint &local,
- QWaylandSurface *surface)
+/*!
+ * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::retainedSelection
+ *
+ * This property holds whether retained selection is enabled.
+ */
+
+/*!
+ * \property QWaylandCompositor::retainedSelection
+ *
+ * This property holds whether retained selection is enabled.
+ */
+void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled)
{
- m_compositor->sendDragMoveEvent(global, local, surface ? surface->handle() : 0);
+ Q_D(QWaylandCompositor);
+ d->retainSelection = enabled;
}
-void QWaylandCompositor::sendDragEndEvent()
+bool QWaylandCompositor::retainedSelectionEnabled() const
{
- m_compositor->sendDragEndEvent();
+ Q_D(const QWaylandCompositor);
+ return d->retainSelection;
}
-void QWaylandCompositor::setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY)
+/*!
+ * \internal
+ */
+void QWaylandCompositor::retainedSelectionReceived(QMimeData *)
{
- Q_UNUSED(surface);
- Q_UNUSED(hotspotX);
- Q_UNUSED(hotspotY);
}
-void QWaylandCompositor::configureTouchExtension(TouchExtensionFlags flags)
+/*!
+ * \internal
+ */
+void QWaylandCompositor::overrideSelection(const QMimeData *data)
{
- m_compositor->configureTouchExtension(flags);
+ Q_D(QWaylandCompositor);
+ d->data_device_manager->overrideSelection(*data);
}
-QWaylandSurfaceView *QWaylandCompositor::createView(QWaylandSurface *surface)
+/*!
+ * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultInputDevice
+ *
+ * This property contains the default input device for this
+ * WaylandCompositor.
+ */
+
+/*!
+ * \property QWaylandCompositor::defaultInputDevice
+ *
+ * This property contains the default input device for this
+ * QWaylandCompositor.
+ */
+QWaylandInputDevice *QWaylandCompositor::defaultInputDevice() const
{
- return new QWaylandSurfaceView(surface);
+ Q_D(const QWaylandCompositor);
+ if (d->inputDevices.size())
+ return d->inputDevices.first();
+ return Q_NULLPTR;
}
+/*!
+ * \internal
+ *
+ * Currently, Qt only supports a single input device, so this exists for
+ * future proofing the APIs.
+ */
QWaylandInputDevice *QWaylandCompositor::inputDeviceFor(QInputEvent *inputEvent)
{
- return m_compositor->inputDeviceFor(inputEvent);
+ Q_D(QWaylandCompositor);
+ QWaylandInputDevice *dev = NULL;
+ for (int i = 0; i < d->inputDevices.size(); i++) {
+ QWaylandInputDevice *candidate = d->inputDevices.at(i);
+ if (candidate->isOwner(inputEvent)) {
+ dev = candidate;
+ break;
+ }
+ }
+ return dev;
}
-QWaylandOutput *QWaylandCompositor::createOutput(QWindow *window,
- const QString &manufacturer,
- const QString &model)
+/*!
+ * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::useHardwareIntegrationExtension
+ *
+ * This property holds whether the hardware integration extension should be enabled for
+ * this WaylandCompositor.
+ *
+ * This property must be set before the compositor component is completed.
+ */
+
+/*!
+ * \property QWaylandCompositor::useHardwareIntegrationExtension
+ *
+ * This property holds whether the hardware integration extension should be enabled for
+ * this QWaylandCompositor.
+ *
+ * This property must be set before the compositor is \l{create()}{created}.
+ */
+bool QWaylandCompositor::useHardwareIntegrationExtension() const
{
- return new QWaylandOutput(this, window, manufacturer, model);
+ Q_D(const QWaylandCompositor);
+ return d->use_hw_integration_extension;
+}
+
+void QWaylandCompositor::setUseHardwareIntegrationExtension(bool use)
+{
+ Q_D(QWaylandCompositor);
+ if (use == d->use_hw_integration_extension)
+ return;
+
+ if (d->initialized)
+ qWarning("Setting QWaylandCompositor::useHardwareIntegrationExtension after initialization has no effect");
+
+ d->use_hw_integration_extension = use;
+ useHardwareIntegrationExtensionChanged();
}
QT_END_NAMESPACE