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.cpp438
1 files changed, 387 insertions, 51 deletions
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index d86b48d8a..2fac37d0d 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -36,97 +36,378 @@
****************************************************************************/
#include "qwaylandcompositor.h"
-
-#include "qwaylandclient.h"
-#include "qwaylandinput.h"
-#include "qwaylandoutput.h"
-#include "qwaylandview.h"
-#include "qwaylandclient.h"
-#include "qwaylandkeyboard.h"
-#include "qwaylandpointer.h"
-#include "qwaylandtouch.h"
+#include "qwaylandcompositor_p.h"
+
+#include <QtCompositor/qwaylandclient.h>
+#include <QtCompositor/qwaylandinput.h>
+#include <QtCompositor/qwaylandoutput.h>
+#include <QtCompositor/qwaylandview.h>
+#include <QtCompositor/qwaylandclient.h>
+#include <QtCompositor/qwaylandkeyboard.h>
+#include <QtCompositor/private/qwlkeyboard_p.h>
+#include <QtCompositor/qwaylandpointer.h>
+#include <QtCompositor/qwaylandtouch.h>
#include "qwaylandsurface_p.h"
-#include "wayland_wrapper/qwlcompositor_p.h"
#include "wayland_wrapper/qwldatadevice_p.h"
#include "wayland_wrapper/qwlinputdevice_p.h"
+#include "wayland_wrapper/qwldatadevicemanager_p.h"
#include "extensions/qwlinputpanel_p.h"
#include "extensions/qwlshellsurface_p.h"
+#include "extensions/qwlextendedsurface_p.h"
+#include "extensions/qwlsubsurface_p.h"
+#include "extensions/qwlqttouch_p.h"
+#include "extensions/qwlqtkey_p.h"
+#include "extensions/qwltextinputmanager_p.h"
+#include "extensions/qwaylandwindowmanagerextension.h"
+
+#include "hardware_integration/qwlhwintegration_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 "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/private/qguiapplication_p.h>
QT_BEGIN_NAMESPACE
+namespace QtWayland {
+
+class WindowSystemEventHandler : public QWindowSystemEventHandler
+{
+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);
+
+ 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)
+ : extensions(QWaylandCompositor::DefaultExtensions)
+ , display(wl_display_create())
+#if defined (QT_COMPOSITOR_WAYLAND_GL)
+ , hw_integration(0)
+ , client_buffer_integration(0)
+ , server_buffer_integration(0)
+#endif
+ , eventHandler(new QtWayland::WindowSystemEventHandler(compositor))
+ , retainSelection(false)
+ , initialized(false)
+{
+ timer.start();
+
+ QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data());
+}
+
+void QWaylandCompositorPrivate::init()
+{
+ Q_Q(QWaylandCompositor);
+ outputSpaces.append(new QWaylandOutputSpace(q));
+ 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()));
+
+ qRegisterMetaType<QtWayland::SurfaceBuffer*>("SurfaceBuffer*");
+ qRegisterMetaType<QWaylandClient*>("WaylandClient*");
+ qRegisterMetaType<QWaylandSurface*>("WaylandSurface*");
+ qRegisterMetaType<QWaylandView*>("WaylandSurfaceView*");
+ //initialize distancefieldglyphcache here
+
+ initializeHardwareIntegration();
+ initializeExtensions();
+ initializeDefaultInputDevice();
+
+ initialized = true;
+}
+
+QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
+{
+ if (!destroyed_surfaces.isEmpty())
+ qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually");
+ qDeleteAll(clients);
+
+ qDeleteAll(outputSpaces);
+
+ delete data_device_manager;
+
+ wl_display_destroy(display);
+}
+
+void QWaylandCompositorPrivate::destroySurface(QWaylandSurface *surface)
+{
+ Q_Q(QWaylandCompositor);
+ q->surfaceAboutToBeDestroyed(surface);
+
+ destroyed_surfaces << surface;
+}
+
+void QWaylandCompositorPrivate::unregisterSurface(QWaylandSurface *surface)
+{
+ if (!all_surfaces.removeOne(surface))
+ qWarning("%s Unexpected state. Cant find registered surface\n", Q_FUNC_INFO);
+}
+
+void QWaylandCompositorPrivate::feedRetainedSelectionData(QMimeData *data)
+{
+ Q_Q(QWaylandCompositor);
+ if (retainSelection)
+ q->retainedSelectionReceived(data);
+}
+
+void QWaylandCompositorPrivate::compositor_create_surface(Resource *resource, uint32_t id)
+{
+ Q_Q(QWaylandCompositor);
+ QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client());
+ QWaylandSurface *surface = q->createSurface(client, id, resource->version());
+ all_surfaces.append(surface);
+ emit q->surfaceCreated(surface);
+}
+
+void QWaylandCompositorPrivate::compositor_create_region(Resource *resource, uint32_t id)
+{
+ new QtWayland::Region(resource->client(), id);
+}
+
+
+void QWaylandCompositorPrivate::initializeHardwareIntegration()
+{
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ Q_Q(QWaylandCompositor);
+ if (extensions & QWaylandCompositor::HardwareIntegrationExtension)
+ hw_integration.reset(new QtWayland::HardwareIntegration(q));
+
+ loadClientBufferIntegration();
+ loadServerBufferIntegration();
+
+ if (client_buffer_integration)
+ client_buffer_integration->initializeHardware(display);
+ if (server_buffer_integration)
+ server_buffer_integration->initializeHardware(q);
+#endif
+}
+
+void QWaylandCompositorPrivate::initializeExtensions()
+{
+ Q_Q(QWaylandCompositor);
+ if (extensions & QWaylandCompositor::SurfaceExtension)
+ new QtWayland::SurfaceExtensionGlobal(q);
+ if (extensions & QWaylandCompositor::SubSurfaceExtension)
+ new QtWayland::SubSurfaceExtensionGlobal(q);
+ if (extensions & QWaylandCompositor::TouchExtension)
+ new QtWayland::TouchExtensionGlobal(q);
+ if (extensions & QWaylandCompositor::QtKeyExtension)
+ new QtWayland::QtKeyExtensionGlobal(q);
+ if (extensions & QWaylandCompositor::TextInputExtension) {
+ new QtWayland::TextInputManager(q);
+ new QWaylandInputPanel(q);
+ }
+ if (extensions & QWaylandCompositor::WindowManagerExtension)
+ new QWaylandWindowManagerExtension(q);
+}
+
+void QWaylandCompositorPrivate::initializeDefaultInputDevice()
+{
+ Q_Q(QWaylandCompositor);
+ inputDevices.append(q->createInputDevice());
+}
+
+void QWaylandCompositorPrivate::loadClientBufferIntegration()
+{
+#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
+}
+
+void QWaylandCompositorPrivate::loadServerBufferIntegration()
+{
+#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
+}
+
QWaylandCompositor::QWaylandCompositor(QObject *parent)
- : QObject(parent)
- , m_compositor(new QtWayland::Compositor(this))
+ : QObject(*new QWaylandCompositorPrivate(this), parent)
{
}
QWaylandCompositor::~QWaylandCompositor()
{
- delete m_compositor;
}
void QWaylandCompositor::create()
{
- m_compositor->init();
+ Q_D(QWaylandCompositor);
+ d->init();
}
bool QWaylandCompositor::isCreated() const
{
- return m_compositor->m_initialized;
+ Q_D(const QWaylandCompositor);
+ return d->initialized;
}
void QWaylandCompositor::setSocketName(const QByteArray &name)
{
- if (m_compositor->m_initialized) {
+ Q_D(QWaylandCompositor);
+ if (d->initialized) {
qWarning("%s: It is not supported to alter the compostors socket name after the compositor is initialized\n", Q_FUNC_INFO);
return;
}
- m_compositor->m_socket_name = name;
+ d->socket_name = name;
}
QByteArray QWaylandCompositor::socketName() const
{
- return m_compositor->m_socket_name;
+ Q_D(const QWaylandCompositor);
+ return d->socket_name;
}
void QWaylandCompositor::setExtensionFlags(QWaylandCompositor::ExtensionFlags flags)
{
- if (m_compositor->m_initialized) {
+ Q_D(QWaylandCompositor);
+ if (d->initialized) {
qWarning("%s: It is not supported to alter the extension flags after the compositor is initialized\n", Q_FUNC_INFO);
return;
}
- m_compositor->m_extensions = flags;
+ d->extensions = flags;
}
QWaylandCompositor::ExtensionFlags QWaylandCompositor::extensionFlags() const
{
- return m_compositor->extensions();
+ Q_D(const QWaylandCompositor);
+ return d->extensions;
}
-struct wl_display *QWaylandCompositor::waylandDisplay() const
+struct wl_display *QWaylandCompositor::display() const
{
- return m_compositor->wl_display();
+ Q_D(const QWaylandCompositor);
+ return d->display;
}
uint32_t QWaylandCompositor::nextSerial()
{
- return wl_display_next_serial(waylandDisplay());
+ Q_D(QWaylandCompositor);
+ return wl_display_next_serial(d->display);
}
QList<QWaylandClient *>QWaylandCompositor::clients() const
{
- return m_compositor->clients();
+ Q_D(const QWaylandCompositor);
+ return d->clients;
}
void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface)
@@ -136,13 +417,21 @@ void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface)
void QWaylandCompositor::destroyClient(QWaylandClient *client)
{
- m_compositor->destroyClient(client);
+ if (!client)
+ return;
+
+ QWaylandWindowManagerExtension *wmExtension = QWaylandWindowManagerExtension::findIn(this);
+ if (wmExtension)
+ wmExtension->sendQuitMessage(client->client());
+
+ wl_client_destroy(client->client());
}
QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const
{
+ Q_D(const QWaylandCompositor);
QList<QWaylandSurface *> surfs;
- foreach (QWaylandSurface *surface, m_compositor->m_all_surfaces) {
+ foreach (QWaylandSurface *surface, d->all_surfaces) {
if (surface->client() == client)
surfs.append(surface);
}
@@ -151,42 +440,66 @@ QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* c
QList<QWaylandSurface *> QWaylandCompositor::surfaces() const
{
- return m_compositor->m_all_surfaces;
+ Q_D(const QWaylandCompositor);
+ return d->all_surfaces;
}
QWaylandOutput *QWaylandCompositor::output(QWindow *window) const
{
- return m_compositor->output(window);
+ Q_D(const QWaylandCompositor);
+ foreach (QWaylandOutputSpace *outputSpace, d->outputSpaces) {
+ QWaylandOutput *output = outputSpace->output(window);
+ if (output)
+ return output;
+ }
+
+ return Q_NULLPTR;
}
QWaylandOutput *QWaylandCompositor::primaryOutput() const
{
- return m_compositor->primaryOutput();
+ Q_D(const QWaylandCompositor);
+ return d->primaryOutput();
}
QWaylandOutputSpace *QWaylandCompositor::primaryOutputSpace() const
{
- return m_compositor->primaryOutputSpace();
+ Q_D(const QWaylandCompositor);
+ return d->primaryOutputSpace();
}
void QWaylandCompositor::setPrimaryOutputSpace(QWaylandOutputSpace *outputSpace)
{
- m_compositor->setPrimaryOutputSpace(outputSpace);
+ Q_D(QWaylandCompositor);
+
+ Q_ASSERT(!d->outputSpaces.isEmpty());
+ if (d->outputSpaces.first() == outputSpace)
+ return;
+ if (d->outputSpaces.removeOne(outputSpace)) {
+ d->outputSpaces.prepend(outputSpace);
+ primaryOutputSpaceChanged();
+ }
}
void QWaylandCompositor::addOutputSpace(QWaylandOutputSpace *outputSpace)
{
- m_compositor->addOutputSpace(outputSpace);
+ Q_D(QWaylandCompositor);
+ Q_ASSERT(!d->outputSpaces.contains(outputSpace));
+ d->outputSpaces.append(outputSpace);
+ outputSpacesChanged();
}
void QWaylandCompositor::removeOutputSpace(QWaylandOutputSpace *outputSpace)
{
- m_compositor->removeOutputSpace(outputSpace);
+ Q_D(QWaylandCompositor);
+ if (d->outputSpaces.removeOne(outputSpace))
+ outputSpacesChanged();
}
uint QWaylandCompositor::currentTimeMsecs() const
{
- return m_compositor->currentTimeMsecs();
+ Q_D(const QWaylandCompositor);
+ return d->timer.elapsed();
}
QWaylandOutput *QWaylandCompositor::createOutput(QWaylandOutputSpace *outputSpace,
@@ -204,9 +517,21 @@ QWaylandSurface *QWaylandCompositor::createSurface(QWaylandClient *client, quint
void QWaylandCompositor::cleanupGraphicsResources()
{
- m_compositor->cleanupGraphicsResources();
+ Q_D(QWaylandCompositor);
+ qDeleteAll(d->destroyed_surfaces);
+ d->destroyed_surfaces.clear();
+}
+
+void QWaylandCompositor::processWaylandEvents()
+{
+ 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);
}
+
QWaylandInputDevice *QWaylandCompositor::createInputDevice()
{
return new QWaylandInputDevice(this);
@@ -227,19 +552,16 @@ QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandInputDevice *inputD
return new QWaylandTouch(inputDevice);
}
-QtWayland::Compositor * QWaylandCompositor::handle() const
-{
- return m_compositor;
-}
-
void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled)
{
- m_compositor->setRetainedSelectionEnabled(enabled);
+ Q_D(QWaylandCompositor);
+ d->retainSelection = enabled;
}
bool QWaylandCompositor::retainedSelectionEnabled() const
{
- return m_compositor->retainedSelectionEnabled();
+ Q_D(const QWaylandCompositor);
+ return d->retainSelection;
}
void QWaylandCompositor::retainedSelectionReceived(QMimeData *)
@@ -248,38 +570,52 @@ void QWaylandCompositor::retainedSelectionReceived(QMimeData *)
void QWaylandCompositor::overrideSelection(const QMimeData *data)
{
- m_compositor->overrideSelection(data);
+ Q_D(QWaylandCompositor);
+ d->data_device_manager->overrideSelection(*data);
}
QWaylandInputDevice *QWaylandCompositor::defaultInputDevice() const
{
- return m_compositor->defaultInputDevice();
+ Q_D(const QWaylandCompositor);
+ return d->inputDevices.first();
}
QWaylandDrag *QWaylandCompositor::drag() const
{
- return m_compositor->defaultInputDevice()->drag();
+ return defaultInputDevice()->drag();
}
bool QWaylandCompositor::isDragging() const
{
- return m_compositor->isDragging();
+ return false;
}
void QWaylandCompositor::sendDragMoveEvent(const QPoint &global, const QPoint &local,
QWaylandSurface *surface)
{
- m_compositor->sendDragMoveEvent(global, local, surface);
+ Q_UNUSED(global);
+ Q_UNUSED(local);
+ Q_UNUSED(surface);
+// Drag::instance()->dragMove(global, local, surface);
}
void QWaylandCompositor::sendDragEndEvent()
{
- m_compositor->sendDragEndEvent();
+// Drag::instance()->dragEnd();
}
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;
}
QT_END_NAMESPACE