diff options
Diffstat (limited to 'src/compositor')
36 files changed, 1386 insertions, 995 deletions
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 8c0d4d0b7..c1300994d 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -116,7 +116,7 @@ QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(WaylandClient* c) QList<QWaylandSurface *> result; for (int i = 0; i < surfaces.count(); ++i) { - if (surfaces.at(i)->base()->resource.client == client) { + if (surfaces.at(i)->resource()->client() == client) { result.append(surfaces.at(i)->waylandSurface()); } } @@ -124,9 +124,9 @@ QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(WaylandClient* c) return result; } -void QWaylandCompositor::setDirectRenderSurface(QWaylandSurface *surface, QOpenGLContext *context) +bool QWaylandCompositor::setDirectRenderSurface(QWaylandSurface *surface, QOpenGLContext *context) { - m_compositor->setDirectRenderSurface(surface ? surface->handle() : 0, context); + return m_compositor->setDirectRenderSurface(surface ? surface->handle() : 0, context); } QWaylandSurface *QWaylandCompositor::directRenderSurface() const diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index 0f258617e..cd1f9bd38 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -75,7 +75,7 @@ public: QList<QWaylandSurface *> surfacesForClient(WaylandClient* client) const; - void setDirectRenderSurface(QWaylandSurface *surface, QOpenGLContext *context); + bool setDirectRenderSurface(QWaylandSurface *surface, QOpenGLContext *context); QWaylandSurface *directRenderSurface() const; QWindow *window()const; diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp index c73784ebf..76e83030b 100644 --- a/src/compositor/compositor_api/qwaylandinput.cpp +++ b/src/compositor/compositor_api/qwaylandinput.cpp @@ -41,6 +41,7 @@ #include "qwaylandinput.h" #include "qwlinputdevice_p.h" +#include "qwlkeyboard_p.h" #include "qwaylandcompositor.h" #include "qwlsurface_p.h" #include "qwlcompositor_p.h" @@ -88,12 +89,12 @@ void QWaylandInputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int d void QWaylandInputDevice::sendKeyPressEvent(uint code) { - d->sendKeyPressEvent(code); + d->keyboardDevice()->sendKeyPressEvent(code); } void QWaylandInputDevice::sendKeyReleaseEvent(uint code) { - d->sendKeyReleaseEvent(code); + d->keyboardDevice()->sendKeyReleaseEvent(code); } void QWaylandInputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state) diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 7f0813a42..88b68ebd1 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -92,7 +92,7 @@ QWaylandSurface::QWaylandSurface(QtWayland::Surface *surface) WaylandClient *QWaylandSurface::client() const { Q_D(const QWaylandSurface); - return d->surface->base()->resource.client; + return d->surface->resource()->client(); } QWaylandSurface *QWaylandSurface::parentSurface() const @@ -149,13 +149,7 @@ QSize QWaylandSurface::size() const return d->surface->size(); } -void QWaylandSurface::setSize(const QSize &size) -{ - Q_D(QWaylandSurface); - d->surface->setSize(size); -} - -void QWaylandSurface::sendConfigure(const QSize &size) +void QWaylandSurface::requestSize(const QSize &size) { Q_D(QWaylandSurface); if (d->surface->shellSurface()) @@ -226,7 +220,6 @@ void QWaylandSurface::setSurfaceItem(QWaylandSurfaceItem *surfaceItem) qint64 QWaylandSurface::processId() const { - Q_D(const QWaylandSurface); struct wl_client *client = static_cast<struct wl_client *>(this->client()); pid_t pid; wl_client_get_credentials(client,&pid, 0,0); @@ -291,11 +284,25 @@ QWaylandSurface *QWaylandSurface::transientParent() const return 0; } -void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) +QWindow::Visibility QWaylandSurface::visibility() const +{ + Q_D(const QWaylandSurface); + if (d->surface->extendedSurface()) + return d->surface->extendedSurface()->visibility(); + + return QWindow::AutomaticVisibility; +} + +void QWaylandSurface::setVisibility(QWindow::Visibility visibility) { Q_D(QWaylandSurface); if (d->surface->extendedSurface()) - d->surface->extendedSurface()->sendOnScreenVisibility(visible); + d->surface->extendedSurface()->setVisibility(visibility); +} + +void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) +{ + setVisibility(visible ? QWindow::AutomaticVisibility : QWindow::Hidden); } QString QWaylandSurface::className() const @@ -328,4 +335,21 @@ bool QWaylandSurface::transientInactive() const return d->surface->transientInactive(); } +void QWaylandSurface::destroySurface() +{ + Q_D(QWaylandSurface); + if (d->surface->extendedSurface()) { + d->surface->extendedSurface()->send_close(); + } else { + destroySurfaceByForce(); + } +} + +void QWaylandSurface::destroySurfaceByForce() +{ + Q_D(QWaylandSurface); + wl_resource *surface_resource = d->surface->resource()->handle; + wl_resource_destroy(surface_resource); +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index 544fbc047..308e8d546 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -45,6 +45,7 @@ #include <QtCore/QScopedPointer> #include <QtGui/QImage> +#include <QtGui/QWindow> #include <QtCore/QVariantMap> #include <QtGui/QOpenGLContext> @@ -72,13 +73,14 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandSurface) - Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged) + Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) Q_PROPERTY(QPointF pos READ pos WRITE setPos NOTIFY posChanged) Q_PROPERTY(QWaylandSurface::WindowFlags windowFlags READ windowFlags NOTIFY windowFlagsChanged) Q_PROPERTY(Qt::ScreenOrientation contentOrientation READ contentOrientation NOTIFY contentOrientationChanged) Q_PROPERTY(QString className READ className NOTIFY classNameChanged) Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask NOTIFY orientationUpdateMaskChanged) + Q_PROPERTY(QWindow::Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) Q_ENUMS(WindowFlag) Q_FLAGS(WindowFlag WindowFlags) @@ -111,8 +113,7 @@ public: QPointF pos() const; void setPos(const QPointF &pos); QSize size() const; - void setSize(const QSize &size); - void sendConfigure(const QSize &size); + Q_INVOKABLE void requestSize(const QSize &size); Qt::ScreenOrientations orientationUpdateMask() const; Qt::ScreenOrientation contentOrientation() const; @@ -126,7 +127,9 @@ public: uint texture(QOpenGLContext *context) const; #endif - Q_INVOKABLE void sendOnScreenVisibilityChange(bool visible); + QWindow::Visibility visibility() const; + void setVisibility(QWindow::Visibility visibility); + Q_INVOKABLE void sendOnScreenVisibilityChange(bool visible); // Compat void frameFinished(); @@ -157,6 +160,8 @@ public: bool transientInactive() const; + Q_INVOKABLE void destroySurface(); + Q_INVOKABLE void destroySurfaceByForce(); signals: void mapped(); void unmapped(); @@ -171,7 +176,9 @@ signals: void extendedSurfaceReady(); void classNameChanged(); void titleChanged(); - + void raiseRequested(); + void lowerRequested(); + void visibilityChanged(); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index a6f425a8b..dde6848b1 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -93,7 +93,7 @@ QWaylandSurfaceItem::QWaylandSurfaceItem(QQuickItem *parent) , m_node(0) , m_paintEnabled(true) , m_useTextureAlpha(false) - , m_clientRenderingEnabled(false) + , m_clientRenderingEnabled(true) , m_touchEventsEnabled(false) , m_resizeSurfaceToItem(false) { @@ -108,8 +108,9 @@ QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *p , m_node(0) , m_paintEnabled(true) , m_useTextureAlpha(false) - , m_clientRenderingEnabled(false) + , m_clientRenderingEnabled(true) , m_touchEventsEnabled(false) + , m_resizeSurfaceToItem(false) { init(surface); } @@ -125,9 +126,7 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface) m_surface = surface; m_surface->setSurfaceItem(this); - if (m_clientRenderingEnabled) { - m_surface->sendOnScreenVisibilityChange(m_clientRenderingEnabled); - } + m_surface->sendOnScreenVisibilityChange(m_clientRenderingEnabled); if (m_resizeSurfaceToItem) { updateSurfaceSize(); @@ -203,8 +202,8 @@ void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event) if (m_surface) { QWaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice(); if (inputDevice->mouseFocus() != m_surface) - inputDevice->setMouseFocus(m_surface, event->pos(), event->globalPos()); - inputDevice->sendMousePressEvent(event->button(), toSurface(event->pos()), event->globalPos()); + inputDevice->setMouseFocus(m_surface, event->localPos(), event->windowPos()); + inputDevice->sendMousePressEvent(event->button(), event->localPos(), event->windowPos()); } } @@ -212,7 +211,7 @@ void QWaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event) { if (m_surface){ QWaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice(); - inputDevice->sendMouseMoveEvent(m_surface, toSurface(event->pos()), event->globalPos()); + inputDevice->sendMouseMoveEvent(m_surface, event->localPos(), event->windowPos()); } } @@ -220,7 +219,7 @@ void QWaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event) { if (m_surface){ QWaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice(); - inputDevice->sendMouseReleaseEvent(event->button(), toSurface(event->pos()), event->globalPos()); + inputDevice->sendMouseReleaseEvent(event->button(), event->localPos(), event->windowPos()); } } @@ -276,11 +275,6 @@ void QWaylandSurfaceItem::takeFocus() } } -QPoint QWaylandSurfaceItem::toSurface(const QPointF &pos) const -{ - return pos.toPoint(); -} - void QWaylandSurfaceItem::surfaceMapped() { setPaintEnabled(true); @@ -339,7 +333,7 @@ void QWaylandSurfaceItem::updateSize() void QWaylandSurfaceItem::updateSurfaceSize() { if (m_resizeSurfaceToItem) { - m_surface->sendConfigure(QSize(width(), height())); + m_surface->requestSize(QSize(width(), height())); } } @@ -455,6 +449,6 @@ void QWaylandSurfaceItem::setResizeSurfaceToItem(bool enabled) } } -#include "qwaylandsurfaceitem.moc" - QT_END_NAMESPACE + +#include "qwaylandsurfaceitem.moc" diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h index c6a5cff83..93a0c62c0 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h @@ -134,7 +134,6 @@ protected: private: friend class QWaylandSurfaceNode; void updateTexture(); - QPoint toSurface(const QPointF &pos) const; void init(QWaylandSurface *); void ensureProvider(); diff --git a/src/compositor/global/global.pri b/src/compositor/global/global.pri index f187619e5..9cbd62d89 100644 --- a/src/compositor/global/global.pri +++ b/src/compositor/global/global.pri @@ -2,7 +2,6 @@ INCLUDEPATH += global/ HEADERS += \ global/qwaylandexport.h \ - global/qwaylandobject.h \ global/qwaylandresourcecollection.h SOURCES += \ diff --git a/src/compositor/hardware_integration/qwaylandgraphicshardwareintegration.h b/src/compositor/hardware_integration/qwaylandgraphicshardwareintegration.h index 373880440..b8cc90fb4 100644 --- a/src/compositor/hardware_integration/qwaylandgraphicshardwareintegration.h +++ b/src/compositor/hardware_integration/qwaylandgraphicshardwareintegration.h @@ -66,14 +66,16 @@ public: /** Bind the Wayland buffer to the textureId. The correct context is the current context, so there is no need to do makeCurrent in this function. **/ - virtual GLuint createTextureFromBuffer(struct wl_buffer *buffer, QOpenGLContext *context) = 0; - virtual bool isYInverted(struct wl_buffer *) const { return true; } + virtual GLuint createTextureFromBuffer(struct ::wl_resource *buffer, QOpenGLContext *context) = 0; + virtual bool isYInverted(struct ::wl_resource *) const { return true; } virtual bool setDirectRenderSurface(QWaylandSurface *) {return false;} - virtual void *lockNativeBuffer(struct wl_buffer *, QOpenGLContext *) const { return 0; } + virtual void *lockNativeBuffer(struct ::wl_resource *, QOpenGLContext *) const { return 0; } virtual void unlockNativeBuffer(void *, QOpenGLContext *) const { return; } + virtual QSize bufferSize(struct ::wl_resource *) const { return QSize(); } + protected: QWaylandCompositor *m_compositor; }; diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index 0f2fedc4a..4f0e6ced9 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -51,10 +51,11 @@ #include "qwlextendedsurface_p.h" #include "qwlsubsurface_p.h" #include "qwlshellsurface_p.h" -#include "qwltouch_p.h" +#include "qwlqttouch_p.h" #include "qwlqtkey_p.h" #include "qwlinputdevice_p.h" #include "qwlregion_p.h" +#include "qwlpointer_p.h" #include <QWindow> #include <QSocketNotifier> @@ -246,36 +247,6 @@ void Compositor::createSurface(struct wl_client *client, uint32_t id) m_qt_compositor->surfaceCreated(surface->waylandSurface()); } -struct wl_client *Compositor::getClientFromWinId(uint winId) const -{ - Surface *surface = getSurfaceFromWinId(winId); - if (surface) - return surface->resource()->client(); - - return 0; -} - -Surface *Compositor::getSurfaceFromWinId(uint winId) const -{ - foreach (Surface *surface, m_surfaces) { - if (surface->id() == winId) - return surface; - } - - return 0; -} - -QImage Compositor::image(uint winId) const -{ - foreach (Surface *surface, m_surfaces) { - if (surface->id() == winId) { - return surface->image(); - } - } - - return QImage(); -} - uint Compositor::currentTimeMsecs() { //### we throw away the time information @@ -286,9 +257,9 @@ uint Compositor::currentTimeMsecs() return 0; } -void Compositor::releaseBuffer(SurfaceBuffer *screenBuffer) +void Compositor::releaseBuffer(QPlatformScreenBuffer *screenBuffer) { - screenBuffer->scheduledRelease(); + static_cast<SurfaceBuffer *>(screenBuffer)->scheduledRelease(); } void Compositor::processWaylandEvents() @@ -307,7 +278,10 @@ void Compositor::surfaceDestroyed(Surface *surface) // Make sure the surface is reset regardless of what the grabber // interface's focus() does. (e.g. the default implementation does // nothing when a button is down which would be disastrous here) - wl_pointer_set_focus(dev->pointerDevice(), 0, 0, 0); + dev->pointerDevice()->setFocus(0, QPointF()); + } + if (dev->pointerDevice()->current() == surface) { + dev->pointerDevice()->setCurrent(0, QPointF()); } if (dev->keyboardFocus() == surface) dev->setKeyboardFocus(0); @@ -494,22 +468,6 @@ QList<QtWayland::Surface *> Compositor::surfacesForClient(wl_client *client) return ret; } -wl_resource *Compositor::resourceForSurface(wl_list *resourceList, Surface *surface) -{ - if (!surface) - return 0; - - wl_resource *r; - wl_client *surfaceClient = surface->resource()->client(); - - wl_list_for_each(r, resourceList, link) { - if (r->client == surfaceClient) - return r; - } - - return 0; -} - void Compositor::configureTouchExtension(int flags) { if (m_touchExtension) @@ -536,7 +494,7 @@ void Compositor::feedRetainedSelectionData(QMimeData *data) void Compositor::scheduleReleaseBuffer(SurfaceBuffer *screenBuffer) { - QMetaObject::invokeMethod(this,"releaseBuffer",Q_ARG(SurfaceBuffer*,screenBuffer)); + QMetaObject::invokeMethod(this,"releaseBuffer",Q_ARG(QPlatformScreenBuffer*,screenBuffer)); } void Compositor::overrideSelection(QMimeData *data) diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h index 628470681..5e3c7be4e 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor_p.h +++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h @@ -84,11 +84,6 @@ public: void frameFinished(Surface *surface = 0); - //these 3 functions will be removed if noone steps up soon. - Surface *getSurfaceFromWinId(uint winId) const; - struct wl_client *getClientFromWinId(uint winId) const; - QImage image(uint winId) const; - InputDevice *defaultInputDevice(); //we just have 1 default device for now (since QPA doesn't give us anything else) void createSurface(struct wl_client *client, uint32_t id); @@ -153,11 +148,9 @@ public: void scheduleReleaseBuffer(SurfaceBuffer *screenBuffer); - static wl_resource *resourceForSurface(wl_list *resourceList, Surface *surface); - private slots: - void releaseBuffer(SurfaceBuffer *screenBuffer); + void releaseBuffer(QPlatformScreenBuffer *screenBuffer); void processWaylandEvents(); private: diff --git a/src/compositor/wayland_wrapper/qwldatasource.cpp b/src/compositor/wayland_wrapper/qwldatasource.cpp index 271467f2e..d60ec5108 100644 --- a/src/compositor/wayland_wrapper/qwldatasource.cpp +++ b/src/compositor/wayland_wrapper/qwldatasource.cpp @@ -43,7 +43,7 @@ #include "qwldatadevicemanager_p.h" #include "qwlcompositor_p.h" -#include <wayland-server-protocol.h> +#include <wayland-wayland-server-protocol.h> #include <QtCore/QDebug> diff --git a/src/compositor/wayland_wrapper/qwldisplay.cpp b/src/compositor/wayland_wrapper/qwldisplay.cpp index be5b54182..5dd6e3823 100644 --- a/src/compositor/wayland_wrapper/qwldisplay.cpp +++ b/src/compositor/wayland_wrapper/qwldisplay.cpp @@ -42,7 +42,7 @@ #include <QtCore/QDebug> -#include <wayland-server-protocol.h> +#include <wayland-wayland-server-protocol.h> QT_BEGIN_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlextendedsurface.cpp b/src/compositor/wayland_wrapper/qwlextendedsurface.cpp index 19df7eb25..4f1791da2 100644 --- a/src/compositor/wayland_wrapper/qwlextendedsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlextendedsurface.cpp @@ -48,52 +48,30 @@ QT_BEGIN_NAMESPACE namespace QtWayland { SurfaceExtensionGlobal::SurfaceExtensionGlobal(Compositor *compositor) - : m_compositor(compositor) + : QtWaylandServer::qt_surface_extension(compositor->wl_display()) { - wl_display_add_global(m_compositor->wl_display(), - &qt_surface_extension_interface, - this, - SurfaceExtensionGlobal::bind_func); } -void SurfaceExtensionGlobal::bind_func(struct wl_client *client, void *data, - uint32_t version, uint32_t id) +void SurfaceExtensionGlobal::surface_extension_get_extended_surface(Resource *resource, + uint32_t id, + struct wl_resource *surface_resource) { - Q_UNUSED(version); - wl_client_add_object(client, &qt_surface_extension_interface,&surface_extension_interface,id,data); -} - -const struct qt_surface_extension_interface SurfaceExtensionGlobal::surface_extension_interface = { - SurfaceExtensionGlobal::get_extended_surface -}; - -void SurfaceExtensionGlobal::get_extended_surface(struct wl_client *client, - struct wl_resource *surface_extension_resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - Q_UNUSED(surface_extension_resource); Surface *surface = Surface::fromResource(surface_resource); - new ExtendedSurface(client,id,surface); + new ExtendedSurface(resource->client(),id,surface); } ExtendedSurface::ExtendedSurface(struct wl_client *client, uint32_t id, Surface *surface) - : m_surface(surface) + : QtWaylandServer::qt_extended_surface(client,id) + , m_surface(surface) , m_contentOrientation(Qt::PrimaryOrientation) , m_windowFlags(0) { Q_ASSERT(surface->extendedSurface() == 0); - m_extended_surface_resource = wl_client_add_object(client, - &qt_extended_surface_interface, - &extended_surface_interface, - id, - this); surface->setExtendedSurface(this); } ExtendedSurface::~ExtendedSurface() { - } void ExtendedSurface::sendGenericProperty(const QString &name, const QVariant &variant) @@ -101,31 +79,33 @@ void ExtendedSurface::sendGenericProperty(const QString &name, const QVariant &v QByteArray byteValue; QDataStream ds(&byteValue, QIODevice::WriteOnly); ds << variant; - wl_array data; - data.size = byteValue.size(); - data.data = (void*) byteValue.constData(); - data.alloc = 0; - qt_extended_surface_send_set_generic_property(m_extended_surface_resource, qPrintable(name), &data); + send_set_generic_property(name, byteValue); } -void ExtendedSurface::sendOnScreenVisibility(bool visible) +void ExtendedSurface::setVisibility(QWindow::Visibility visibility, bool updateClient) { - int32_t visibleInt = visible; - qt_extended_surface_send_onscreen_visibility(m_extended_surface_resource, visibleInt); -} + if (visibility == m_visibility) + return; + + m_visibility = visibility; + emit m_surface->waylandSurface()->visibilityChanged(); + // If this change came from the client, we shouldn't update it + if (updateClient) + send_onscreen_visibility(m_visibility); +} -void ExtendedSurface::update_generic_property(wl_client *client, wl_resource *extended_surface_resource, const char *name, wl_array *value) +void ExtendedSurface::extended_surface_update_generic_property(Resource *resource, + const QString &name, + struct wl_array *value) { - Q_UNUSED(client); - ExtendedSurface *extended_surface = static_cast<ExtendedSurface *>(extended_surface_resource->data); + Q_UNUSED(resource); QVariant variantValue; QByteArray byteValue((const char*)value->data, value->size); QDataStream ds(&byteValue, QIODevice::ReadOnly); ds >> variantValue; - extended_surface->setWindowProperty(QString::fromLatin1(name),variantValue,false); - + setWindowProperty(name,variantValue,false); } static Qt::ScreenOrientation screenOrientationFromWaylandOrientation(int32_t orientation) @@ -144,25 +124,13 @@ Qt::ScreenOrientation ExtendedSurface::contentOrientation() const return m_contentOrientation; } -void ExtendedSurface::set_content_orientation(struct wl_client *client, - struct wl_resource *extended_surface_resource, - int32_t orientation) -{ - Q_UNUSED(client); - ExtendedSurface *extended_surface = static_cast<ExtendedSurface *>(extended_surface_resource->data); - - Qt::ScreenOrientation oldOrientation = extended_surface->m_contentOrientation; - extended_surface->m_contentOrientation = screenOrientationFromWaylandOrientation(orientation); - if (extended_surface->m_contentOrientation != oldOrientation) - emit extended_surface->m_surface->waylandSurface()->contentOrientationChanged(); -} - -void ExtendedSurface::setWindowFlags(QWaylandSurface::WindowFlags flags) +void ExtendedSurface::extended_surface_set_content_orientation(Resource *resource, int32_t orientation) { - if (flags == m_windowFlags) - return; - m_windowFlags = flags; - emit m_surface->waylandSurface()->windowFlagsChanged(flags); + Q_UNUSED(resource); + Qt::ScreenOrientation oldOrientation = m_contentOrientation; + m_contentOrientation = screenOrientationFromWaylandOrientation(orientation); + if (m_contentOrientation != oldOrientation) + emit m_surface->waylandSurface()->contentOrientationChanged(); } QVariantMap ExtendedSurface::windowProperties() const @@ -184,18 +152,30 @@ void ExtendedSurface::setWindowProperty(const QString &name, const QVariant &val sendGenericProperty(name, value); } -void ExtendedSurface::set_window_flags(wl_client *client, wl_resource *resource, int32_t flags) +void ExtendedSurface::extended_surface_set_window_flags(Resource *resource, int32_t flags) +{ + Q_UNUSED(resource); + QWaylandSurface::WindowFlags windowFlags(flags); + if (windowFlags== m_windowFlags) + return; + m_windowFlags = windowFlags; + emit m_surface->waylandSurface()->windowFlagsChanged(windowFlags); +} + +void ExtendedSurface::extended_surface_destroy_resource(Resource *) +{ + delete this; +} + +void ExtendedSurface::extended_surface_raise(Resource *) { - Q_UNUSED(client); - ExtendedSurface *extended_surface = static_cast<ExtendedSurface *>(resource->data); - extended_surface->setWindowFlags(QWaylandSurface::WindowFlags(flags)); + emit m_surface->waylandSurface()->raiseRequested(); } -const struct qt_extended_surface_interface ExtendedSurface::extended_surface_interface = { - ExtendedSurface::update_generic_property, - ExtendedSurface::set_content_orientation, - ExtendedSurface::set_window_flags -}; +void ExtendedSurface::extended_surface_lower(Resource *) +{ + emit m_surface->waylandSurface()->lowerRequested(); +} } diff --git a/src/compositor/wayland_wrapper/qwlextendedsurface_p.h b/src/compositor/wayland_wrapper/qwlextendedsurface_p.h index db9a2e8a4..ecf2f49dd 100644 --- a/src/compositor/wayland_wrapper/qwlextendedsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlextendedsurface_p.h @@ -42,13 +42,14 @@ #define WLEXTENDEDSURFACE_H #include <wayland-server.h> -#include "wayland-surface-extension-server-protocol.h" +#include "qwayland-server-surface-extension.h" #include <private/qwlsurface_p.h> #include <QtCompositor/qwaylandsurface.h> #include <QtCore/QVariant> #include <QtCore/QLinkedList> +#include <QtGui/QWindow> QT_BEGIN_NAMESPACE @@ -58,32 +59,28 @@ namespace QtWayland { class Compositor; -class SurfaceExtensionGlobal +class SurfaceExtensionGlobal : public QtWaylandServer::qt_surface_extension { public: SurfaceExtensionGlobal(Compositor *compositor); private: - Compositor *m_compositor; - - static void bind_func(struct wl_client *client, void *data, - uint32_t version, uint32_t id); - static void get_extended_surface(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface); - static const struct qt_surface_extension_interface surface_extension_interface; + void surface_extension_get_extended_surface(Resource *resource, + uint32_t id, + struct wl_resource *surface); }; -class ExtendedSurface +class ExtendedSurface : public QtWaylandServer::qt_extended_surface { public: ExtendedSurface(struct wl_client *client, uint32_t id, Surface *surface); ~ExtendedSurface(); void sendGenericProperty(const QString &name, const QVariant &variant); - void sendOnScreenVisibility(bool visible); + + QWindow::Visibility visibility() const { return m_visibility; } + void setVisibility(QWindow::Visibility visibility, bool updateClient = true); void setSubSurface(ExtendedSurface *subSurface,int x, int y); void removeSubSurface(ExtendedSurface *subSurfaces); @@ -95,40 +92,34 @@ public: QWaylandSurface::WindowFlags windowFlags() const { return m_windowFlags; } - qint64 processId() const; - void setProcessId(qint64 processId); - QVariantMap windowProperties() const; QVariant windowProperty(const QString &propertyName) const; void setWindowProperty(const QString &name, const QVariant &value, bool writeUpdateToClient = true); private: - struct wl_resource *m_extended_surface_resource; Surface *m_surface; Qt::ScreenOrientation m_contentOrientation; QWaylandSurface::WindowFlags m_windowFlags; + QWindow::Visibility m_visibility; QByteArray m_authenticationToken; QVariantMap m_windowProperties; + void extended_surface_update_generic_property(Resource *resource, + const QString &name, + struct wl_array *value) Q_DECL_OVERRIDE; - static void update_generic_property(struct wl_client *client, - struct wl_resource *resource, - const char *name, - struct wl_array *value); - - static void set_content_orientation(struct wl_client *client, - struct wl_resource *resource, - int32_t orientation); + void extended_surface_set_content_orientation(Resource *resource, + int32_t orientation) Q_DECL_OVERRIDE; - static void set_window_flags(struct wl_client *client, - struct wl_resource *resource, - int32_t flags); - void setWindowFlags(QWaylandSurface::WindowFlags flags); + void extended_surface_set_window_flags(Resource *resource, + int32_t flags) Q_DECL_OVERRIDE; - static const struct qt_extended_surface_interface extended_surface_interface; + void extended_surface_destroy_resource(Resource *) Q_DECL_OVERRIDE; + void extended_surface_raise(Resource *) Q_DECL_OVERRIDE; + void extended_surface_lower(Resource *) Q_DECL_OVERRIDE; }; } diff --git a/src/compositor/wayland_wrapper/qwlinputdevice.cpp b/src/compositor/wayland_wrapper/qwlinputdevice.cpp index e75d98334..d9a91bfaf 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice.cpp +++ b/src/compositor/wayland_wrapper/qwlinputdevice.cpp @@ -43,23 +43,15 @@ #include "qwlcompositor_p.h" #include "qwldatadevice_p.h" #include "qwlsurface_p.h" -#include "qwltouch_p.h" +#include "qwlqttouch_p.h" #include "qwlqtkey_p.h" #include "qwaylandcompositor.h" +#include "qwlpointer_p.h" +#include "qwlkeyboard_p.h" +#include "qwltouch_p.h" #include <QtGui/QTouchEvent> -#ifndef QT_NO_WAYLAND_XKB -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/epoll.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#endif - QT_BEGIN_NAMESPACE namespace QtWayland { @@ -68,146 +60,54 @@ InputDevice::InputDevice(QWaylandInputDevice *handle, Compositor *compositor) : QtWaylandServer::wl_seat(compositor->wl_display()) , m_handle(handle) , m_compositor(compositor) + , m_pointer(new Pointer(m_compositor, this)) + , m_keyboard(new Keyboard(m_compositor, this)) + , m_touch(new Touch(m_compositor)) { - wl_seat_init(&m_seat); - initDevices(); - -#ifndef QT_NO_WAYLAND_XKB - xkb_rule_names xkb_names; - xkb_context *context = xkb_context_new(xkb_context_flags(0)); - - memset(&xkb_names, 0, sizeof(xkb_names)); - xkb_names.rules = strdup("evdev"); - xkb_names.model = strdup("pc105"); - xkb_names.layout = strdup("us"); - - xkb_keymap *keymap = xkb_map_new_from_names(context, &xkb_names, xkb_map_compile_flags(0)); - if (!keymap) - qFatal("Failed to compile global XKB keymap"); - - char *keymap_str_data = xkb_map_get_as_string(keymap); - QByteArray keymap_str = keymap_str_data; - m_keymap_size = keymap_str.size() + 1; - free(keymap_str_data); - - const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) - qFatal("XDG_RUNTIME_DIR not set"); - - QByteArray name = QByteArray(path) + "/qtwayland-xkb-map-XXXXXX"; - - int fd = mkstemp(name.data()); - if (fd >= 0) { - long flags = fcntl(fd, F_GETFD); - if (flags == -1 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { - close(fd); - qFatal("Failed to set FD_CLOEXEC on anonymous file"); - } - unlink(name.data()); - } else { - qFatal("Failed to create anonymous file with name %s", name.constData()); - } - - if (ftruncate(fd, m_keymap_size) < 0) - qFatal("Failed to create anonymous file of size %lu", (unsigned long)m_keymap_size); - - m_keymap_fd = fd; - - m_keymap_area = (char *)mmap(0, m_keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_keymap_fd, 0); - if (m_keymap_area == MAP_FAILED) { - close(m_keymap_fd); - qFatal("Failed to map shared memory segment"); - } - - strcpy(m_keymap_area, keymap_str.constData()); - - m_state = xkb_state_new(keymap); - - free((char *)xkb_names.rules); - free((char *)xkb_names.model); - free((char *)xkb_names.layout); - xkb_map_unref(keymap); - xkb_context_unref(context); -#endif } InputDevice::~InputDevice() { qDeleteAll(m_data_devices); - releaseDevices(); - -#ifndef QT_NO_WAYLAND_XKB - if (m_keymap_area) - munmap(m_keymap_area, m_keymap_size); - close(m_keymap_fd); - xkb_state_unref(m_state); -#endif -} - -void InputDevice::initDevices() -{ - wl_pointer_init(&m_device_interfaces.pointer); - wl_seat_set_pointer(&m_seat, &m_device_interfaces.pointer); - - wl_keyboard_init(&m_device_interfaces.keyboard); - wl_seat_set_keyboard(&m_seat, &m_device_interfaces.keyboard); - - wl_touch_init(&m_device_interfaces.touch); - wl_seat_set_touch(&m_seat, &m_device_interfaces.touch); } -void InputDevice::releaseDevices() +Pointer *InputDevice::pointerDevice() { - wl_pointer_release(&m_device_interfaces.pointer); - wl_keyboard_release(&m_device_interfaces.keyboard); - wl_touch_release(&m_device_interfaces.touch); + return m_pointer.data(); } -wl_pointer *InputDevice::pointerDevice() +Keyboard *InputDevice::keyboardDevice() { - return &m_device_interfaces.pointer; + return m_keyboard.data(); } -wl_keyboard *InputDevice::keyboardDevice() +Touch *InputDevice::touchDevice() { - return &m_device_interfaces.keyboard; + return m_touch.data(); } -wl_touch *InputDevice::touchDevice() +const Pointer *InputDevice::pointerDevice() const { - return &m_device_interfaces.touch; + return m_pointer.data(); } -const wl_pointer *InputDevice::pointerDevice() const +const Keyboard *InputDevice::keyboardDevice() const { - return &m_device_interfaces.pointer; + return m_keyboard.data(); } -const wl_keyboard *InputDevice::keyboardDevice() const +const Touch *InputDevice::touchDevice() const { - return &m_device_interfaces.keyboard; -} - -const wl_touch *InputDevice::touchDevice() const -{ - return &m_device_interfaces.touch; + return m_touch.data(); } void InputDevice::seat_destroy_resource(wl_seat::Resource *resource) { - if (keyboardDevice()->focus_resource == resource->handle) - keyboardDevice()->focus_resource = 0; - - if (pointerDevice()->focus_resource == resource->handle) - pointerDevice()->focus_resource = 0; - cleanupDataDeviceForClient(resource->client(), true); } void InputDevice::seat_bind_resource(wl_seat::Resource *resource) { - wl_list_insert(&m_seat.base_resource_list, &resource->handle->link); - uint32_t caps = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD; if (!QTouchDevice::devices().isEmpty()) caps |= WL_SEAT_CAPABILITY_TOUCH; @@ -215,76 +115,34 @@ void InputDevice::seat_bind_resource(wl_seat::Resource *resource) wl_seat::send_capabilities(resource->handle, caps); } -void InputDevice::pointer_set_cursor(wl_pointer::Resource *resource, - uint32_t serial, wl_resource *surface_resource, - int32_t hotspot_x, int32_t hotspot_y) -{ - Q_UNUSED(resource); - Q_UNUSED(serial); - - QtWayland::Surface *surface = QtWayland::Surface::fromResource(surface_resource); - - surface->setCursorSurface(true); - m_compositor->waylandCompositor()->setCursorSurface(surface->waylandSurface(), hotspot_x, hotspot_y); -} - void InputDevice::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) { - ::wl_pointer *pointer = pointerDevice(); - wl_pointer::add(&pointer->resource_list, resource->client(), id); + m_pointer->add(resource->client(), id); } void InputDevice::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) { - ::wl_keyboard *keyboard = keyboardDevice(); - wl_keyboard::add(&keyboard->resource_list, resource->client(), id); -} - -void InputDevice::keyboard_bind_resource(wl_keyboard::Resource *resource) -{ -#ifndef QT_NO_WAYLAND_XKB - wl_keyboard::send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - m_keymap_fd, m_keymap_size); -#endif + m_keyboard->add(resource->client(), id); } void InputDevice::seat_get_touch(wl_seat::Resource *resource, uint32_t id) { - ::wl_touch *touch = touchDevice(); - wl_touch::add(&touch->resource_list, resource->client(), id); + m_touch->add(resource->client(), id); } void InputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) { - sendMouseMoveEvent(localPos,globalPos); - ::wl_pointer *pointer = pointerDevice(); - pointer->button_count++; - uint32_t time = m_compositor->currentTimeMsecs(); - const struct wl_pointer_grab_interface *interface = pointer->grab->interface; - interface->button(pointer->grab, time, toWaylandButton(button), 1); + pointerDevice()->sendMousePressEvent(button, localPos, globalPos); } void InputDevice::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) { - sendMouseMoveEvent(localPos,globalPos); - ::wl_pointer *pointer = pointerDevice(); - pointer->button_count--; - uint32_t time = m_compositor->currentTimeMsecs(); - const struct wl_pointer_grab_interface *interface = pointer->grab->interface; - interface->button(pointer->grab, time, toWaylandButton(button), 0); + pointerDevice()->sendMouseReleaseEvent(button, localPos, globalPos); } void InputDevice::sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos) { - Q_UNUSED(globalPos); - uint32_t time = m_compositor->currentTimeMsecs(); - ::wl_pointer *pointer = pointerDevice(); - const struct wl_pointer_grab_interface *interface = pointer->grab->interface; - pointer->x = wl_fixed_from_double(globalPos.x()); - pointer->y = wl_fixed_from_double(globalPos.y()); - interface->motion(pointer->grab, - time, - wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y())); + pointerDevice()->sendMouseMoveEvent(localPos, globalPos); } void InputDevice::sendMouseMoveEvent(Surface *surface, const QPointF &localPos, const QPointF &globalPos) @@ -295,100 +153,20 @@ void InputDevice::sendMouseMoveEvent(Surface *surface, const QPointF &localPos, void InputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta) { - ::wl_pointer *pointer = pointerDevice(); - struct wl_resource *resource = pointer->focus_resource; - if (!resource) - return; - uint32_t time = m_compositor->currentTimeMsecs(); - uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL - : WL_POINTER_AXIS_VERTICAL_SCROLL; - wl_pointer_send_axis(resource, time, axis, wl_fixed_from_int(-delta / 12)); -} - -void InputDevice::updateModifierState(uint code, int state) -{ -#ifndef QT_NO_WAYLAND_XKB - xkb_state_update_key(m_state, code, state ? XKB_KEY_DOWN : XKB_KEY_UP); - - uint32_t mods_depressed = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_DEPRESSED); - uint32_t mods_latched = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_LATCHED); - uint32_t mods_locked = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_LATCHED); - uint32_t group = xkb_state_serialize_group(m_state, (xkb_state_component)XKB_STATE_EFFECTIVE); - - ::wl_keyboard *keyboard = keyboardDevice(); - - if (mods_depressed == keyboard->modifiers.mods_depressed - && mods_latched == keyboard->modifiers.mods_latched - && mods_locked == keyboard->modifiers.mods_locked - && group == keyboard->modifiers.group) - { - return; // no change - } - - keyboard->modifiers.mods_depressed = mods_depressed; - keyboard->modifiers.mods_latched = mods_latched; - keyboard->modifiers.mods_locked = mods_locked; - keyboard->modifiers.group = group; - - if (keyboard->focus_resource) - sendKeyModifiers(keyboard->focus_resource); -#else - Q_UNUSED(code); - Q_UNUSED(state); -#endif -} - -void InputDevice::sendKeyModifiers(wl_resource *resource) -{ - ::wl_keyboard *keyboard = keyboardDevice(); - uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); - wl_keyboard_send_modifiers(resource, serial, keyboard->modifiers.mods_depressed, - keyboard->modifiers.mods_latched, keyboard->modifiers.mods_locked, keyboard->modifiers.group); -} - -void InputDevice::sendKeyPressEvent(uint code) -{ - ::wl_keyboard *keyboard = keyboardDevice(); - if (keyboard->focus_resource) { - uint32_t time = m_compositor->currentTimeMsecs(); - uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); - wl_keyboard_send_key(keyboard->focus_resource, - serial, time, code - 8, 1); - } - updateModifierState(code, 1); -} - -void InputDevice::sendKeyReleaseEvent(uint code) -{ - ::wl_keyboard *keyboard = keyboardDevice(); - if (keyboard->focus_resource) { - uint32_t time = m_compositor->currentTimeMsecs(); - uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); - wl_keyboard_send_key(keyboard->focus_resource, - serial, time, code - 8, 0); - } - updateModifierState(code, 0); + pointerDevice()->sendMouseWheelEvent(orientation, delta); } void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state) { - uint32_t time = m_compositor->currentTimeMsecs(); - uint32_t serial = 0; - ::wl_touch *touch = touchDevice(); - wl_resource *resource = touch->focus_resource; - if (!resource) - return; switch (state) { case Qt::TouchPointPressed: - wl_touch_send_down(resource, serial, time, &touch->focus->resource, id, - wl_fixed_from_double(x), wl_fixed_from_double(y)); + m_touch->sendDown(id, QPointF(x, y)); break; case Qt::TouchPointMoved: - wl_touch_send_motion(resource, time, id, - wl_fixed_from_double(x), wl_fixed_from_double(y)); + m_touch->sendMotion(id, QPointF(x, y)); break; case Qt::TouchPointReleased: - wl_touch_send_up(resource, serial, time, id); + m_touch->sendUp(id); break; case Qt::TouchPointStationary: // stationary points are not sent through wayland, the client must cache them @@ -400,18 +178,12 @@ void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPoint void InputDevice::sendTouchFrameEvent() { - ::wl_touch *touch = touchDevice(); - wl_resource *resource = touch->focus_resource; - if (resource) - wl_touch_send_frame(resource); + m_touch->sendFrame(); } void InputDevice::sendTouchCancelEvent() { - ::wl_touch *touch = touchDevice(); - wl_resource *resource = touch->focus_resource; - if (resource) - wl_touch_send_cancel(resource); + m_touch->sendCancel(); } void InputDevice::sendFullKeyEvent(QKeyEvent *event) @@ -426,9 +198,9 @@ void InputDevice::sendFullKeyEvent(QKeyEvent *event) return; if (event->type() == QEvent::KeyPress) - sendKeyPressEvent(event->nativeScanCode()); + m_keyboard->sendKeyPressEvent(event->nativeScanCode()); else if (event->type() == QEvent::KeyRelease) - sendKeyReleaseEvent(event->nativeScanCode()); + m_keyboard->sendKeyReleaseEvent(event->nativeScanCode()); } void InputDevice::sendFullTouchEvent(QTouchEvent *event) @@ -464,7 +236,7 @@ void InputDevice::sendFullTouchEvent(QTouchEvent *event) Surface *InputDevice::keyboardFocus() const { - return static_cast<Surface *>(keyboardDevice()->focus); + return m_keyboard->focus(); } /*! @@ -476,31 +248,22 @@ bool InputDevice::setKeyboardFocus(Surface *surface) return false; sendSelectionFocus(surface); - wl_keyboard_set_focus(keyboardDevice(), surface); + m_keyboard->setFocus(surface); return true; } Surface *InputDevice::mouseFocus() const { - return static_cast<Surface *>(pointerDevice()->focus); + return m_pointer->focusSurface(); } void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos) { - ::wl_pointer *pointer = pointerDevice(); - pointer->x = wl_fixed_from_double(globalPos.x()); - pointer->y = wl_fixed_from_double(globalPos.y()); - pointer->current = surface; - pointer->current_x = wl_fixed_from_double(localPos.x()); - pointer->current_y = wl_fixed_from_double(localPos.y()); - pointer->grab->interface->focus(pointer->grab, surface, - wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y())); + m_pointer->setMouseFocus(surface, localPos, globalPos); // We have no separate touch focus management so make it match the pointer focus always. // No wl_touch_set_focus() is available so set it manually. - ::wl_touch *touch = touchDevice(); - touch->focus = surface; - touch->focus_resource = Compositor::resourceForSurface(&touch->resource_list, surface); + m_touch->setFocus(surface); } void InputDevice::cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev) @@ -544,35 +307,6 @@ QWaylandInputDevice *InputDevice::handle() const return m_handle; } -uint32_t InputDevice::toWaylandButton(Qt::MouseButton button) -{ -#ifndef BTN_LEFT - uint32_t BTN_LEFT = 0x110; -#endif - // the range of valid buttons (evdev module) is from 0x110 - // through 0x11f. 0x120 is the first 'Joystick' button. - switch (button) { - case Qt::LeftButton: return BTN_LEFT; - case Qt::RightButton: return uint32_t(0x111); - case Qt::MiddleButton: return uint32_t(0x112); - case Qt::ExtraButton1: return uint32_t(0x113); // AKA Qt::BackButton, Qt::XButton1 - case Qt::ExtraButton2: return uint32_t(0x114); // AKA Qt::ForwardButton, Qt::XButton2 - case Qt::ExtraButton3: return uint32_t(0x115); - case Qt::ExtraButton4: return uint32_t(0x116); - case Qt::ExtraButton5: return uint32_t(0x117); - case Qt::ExtraButton6: return uint32_t(0x118); - case Qt::ExtraButton7: return uint32_t(0x119); - case Qt::ExtraButton8: return uint32_t(0x11a); - case Qt::ExtraButton9: return uint32_t(0x11b); - case Qt::ExtraButton10: return uint32_t(0x11c); - case Qt::ExtraButton11: return uint32_t(0x11d); - case Qt::ExtraButton12: return uint32_t(0x11e); - case Qt::ExtraButton13: return uint32_t(0x11f); - // default should not occur; but if it does, then return Wayland's highest possible button number. - default: return uint32_t(0x11f); - } -} - DataDevice *InputDevice::dataDevice(struct wl_client *client) const { for (int i = 0; i < m_data_devices.size();i++) { diff --git a/src/compositor/wayland_wrapper/qwlinputdevice_p.h b/src/compositor/wayland_wrapper/qwlinputdevice_p.h index fd1b0fb4e..8ad8a0a75 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice_p.h +++ b/src/compositor/wayland_wrapper/qwlinputdevice_p.h @@ -45,6 +45,7 @@ #include <QtCore/QList> #include <QtCore/QPoint> +#include <QtCore/QScopedPointer> #ifndef QT_NO_WAYLAND_XKB #include <xkbcommon/xkbcommon.h> @@ -64,8 +65,11 @@ class Compositor; class DataDevice; class Surface; class DataDeviceManager; +class Pointer; +class Keyboard; +class Touch; -class InputDevice : public QtWaylandServer::wl_seat, public QtWaylandServer::wl_pointer, public QtWaylandServer::wl_keyboard, public QtWaylandServer::wl_touch +class InputDevice : public QtWaylandServer::wl_seat, public QtWaylandServer::wl_touch { public: InputDevice(QWaylandInputDevice *handle, Compositor *compositor); @@ -77,9 +81,6 @@ public: void sendMouseMoveEvent(Surface *surface, const QPointF &localPos, const QPointF &globalPos = QPointF()); void sendMouseWheelEvent(Qt::Orientation orientation, int delta); - void sendKeyPressEvent(uint code); - void sendKeyReleaseEvent(uint code); - void sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state); void sendTouchFrameEvent(); void sendTouchCancelEvent(); @@ -100,13 +101,13 @@ public: Compositor *compositor() const; QWaylandInputDevice *handle() const; - ::wl_pointer *pointerDevice(); - ::wl_keyboard *keyboardDevice(); - ::wl_touch *touchDevice(); + Pointer *pointerDevice(); + Keyboard *keyboardDevice(); + Touch *touchDevice(); - const ::wl_pointer *pointerDevice() const; - const ::wl_keyboard *keyboardDevice() const; - const ::wl_touch *touchDevice() const; + const Pointer *pointerDevice() const; + const Keyboard *keyboardDevice() const; + const Touch *touchDevice() const; static InputDevice *fromSeatResource(struct ::wl_resource *resource) { @@ -114,44 +115,18 @@ public: } private: - void initDevices(); - void releaseDevices(); void cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev); - void updateModifierState(uint key, int state); - void sendKeyModifiers(wl_resource *resource); QWaylandInputDevice *m_handle; Compositor *m_compositor; QList<DataDevice *> m_data_devices; - struct { - ::wl_pointer pointer; - ::wl_keyboard keyboard; - ::wl_touch touch; - } m_device_interfaces; - - ::wl_seat m_seat; - -#ifndef QT_NO_WAYLAND_XKB - struct xkb_keymap *m_keymap; - struct xkb_state *m_state; - int m_keymap_fd; - size_t m_keymap_size; - char *m_keymap_area; -#endif - - uint32_t toWaylandButton(Qt::MouseButton button); + QScopedPointer<Pointer> m_pointer; + QScopedPointer<Keyboard> m_keyboard; + QScopedPointer<Touch> m_touch; void seat_bind_resource(wl_seat::Resource *resource) Q_DECL_OVERRIDE; - void pointer_set_cursor(wl_pointer::Resource *resource, - uint32_t serial, - struct wl_resource *surface, - int32_t hotspot_x, - int32_t hotspot_y) Q_DECL_OVERRIDE; - - void keyboard_bind_resource(wl_keyboard::Resource *resource) Q_DECL_OVERRIDE; - void seat_get_pointer(wl_seat::Resource *resource, uint32_t id) Q_DECL_OVERRIDE; void seat_get_keyboard(wl_seat::Resource *resource, diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp new file mode 100644 index 000000000..54349e300 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** 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 "qwlkeyboard_p.h" + +#include <QFile> +#include <QStandardPaths> + +#include "qwlcompositor_p.h" +#include "qwlsurface_p.h" + +#include <fcntl.h> +#include <unistd.h> +#ifndef QT_NO_WAYLAND_XKB +#include <sys/mman.h> +#include <sys/types.h> +#endif + +namespace QtWayland { + +Keyboard::Keyboard(Compositor *compositor, InputDevice *seat) + : QtWaylandServer::wl_keyboard() + , m_compositor(compositor) + , m_seat(seat) + , m_focus() + , m_focusResource() + , m_keys() + , m_modsDepressed() + , m_modsLatched() + , m_modsLocked() + , m_group() +{ +#ifndef QT_NO_WAYLAND_XKB + initXKB(); +#endif +} + +Keyboard::~Keyboard() +{ +#ifndef QT_NO_WAYLAND_XKB + if (m_keymap_area) + munmap(m_keymap_area, m_keymap_size); + close(m_keymap_fd); + xkb_state_unref(m_state); +#endif +} + +void Keyboard::setFocus(Surface *surface) +{ + if (m_focusResource && m_focus != surface) { + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_leave(m_focusResource->handle, serial, m_focus->resource()->handle); + } + + Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; + + if (resource && (m_focus != surface || m_focusResource != resource)) { + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group); + send_enter(resource->handle, serial, surface->resource()->handle, m_keys); + } + + m_focusResource = resource; + m_focus = surface; +} + +void Keyboard::sendKeyModifiers(wl_keyboard::Resource *resource, uint32_t serial) +{ + send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group); +} + +void Keyboard::sendKeyPressEvent(uint code) +{ + sendKeyEvent(code, WL_KEYBOARD_KEY_STATE_PRESSED); +} + +void Keyboard::sendKeyReleaseEvent(uint code) +{ + sendKeyEvent(code, WL_KEYBOARD_KEY_STATE_RELEASED); +} + +Surface *Keyboard::focus() const +{ + return m_focus; +} + +void Keyboard::keyboard_bind_resource(wl_keyboard::Resource *resource) +{ +#ifndef QT_NO_WAYLAND_XKB + send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + m_keymap_fd, m_keymap_size); +#else + int null_fd = open("/dev/null", O_RDONLY); + send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */, + null_fd, 0); + close(null_fd); +#endif +} + +void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) +{ + if (m_focusResource == resource) + m_focusResource = 0; +} + +void Keyboard::sendKeyEvent(uint code, uint32_t state) +{ + if (m_focusResource) { + uint32_t time = m_compositor->currentTimeMsecs(); + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_key(m_focusResource->handle, serial, time, code - 8, state); + } + updateModifierState(code, state); +} + +void Keyboard::updateModifierState(uint code, uint32_t state) +{ +#ifndef QT_NO_WAYLAND_XKB + xkb_state_update_key(m_state, code, state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); + + uint32_t modsDepressed = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_DEPRESSED); + uint32_t modsLatched = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_LATCHED); + uint32_t modsLocked = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_LATCHED); + uint32_t group = xkb_state_serialize_group(m_state, (xkb_state_component)XKB_STATE_EFFECTIVE); + + if (modsDepressed == m_modsDepressed + && modsLatched == m_modsLatched + && modsLocked == m_modsLocked + && group == m_group) + return; + + m_modsDepressed = modsDepressed; + m_modsLatched = modsLatched; + m_modsLocked = modsLocked; + m_group = group; + + if (m_focusResource) + sendKeyModifiers(m_focusResource, wl_display_next_serial(m_compositor->wl_display())); +#else + Q_UNUSED(code); + Q_UNUSED(state); +#endif +} + +#ifndef QT_NO_WAYLAND_XKB +static int createAnonymousFile(size_t size) +{ + QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); + if (path.isEmpty()) + return -1; + + QByteArray name = QFile::encodeName(path + QStringLiteral("/qtwayland-XXXXXX")); + + int fd = mkstemp(name.data()); + if (fd < 0) + return -1; + + long flags = fcntl(fd, F_GETFD); + if (flags == -1 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { + close(fd); + fd = -1; + } + unlink(name.constData()); + + if (fd < 0) + return -1; + + if (ftruncate(fd, size) < 0) + return -1; + + return fd; +} + +void Keyboard::initXKB() +{ + struct xkb_context *context = xkb_context_new(static_cast<xkb_context_flags>(0)); + + struct xkb_rule_names rule_names = {0, 0, 0, 0, 0}; + struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rule_names, static_cast<xkb_keymap_compile_flags>(0)); + + char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1); + if (!keymap_str) + qFatal("Failed to compile global XKB keymap"); + + m_keymap_size = strlen(keymap_str) + 1; + m_keymap_fd = createAnonymousFile(m_keymap_size); + if (m_keymap_fd < 0) + qFatal("Failed to create anonymous file of size %lu", static_cast<unsigned long>(m_keymap_size)); + + m_keymap_area = static_cast<char *>(mmap(0, m_keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_keymap_fd, 0)); + if (m_keymap_area == MAP_FAILED) { + close(m_keymap_fd); + qFatal("Failed to map shared memory segment"); + } + + strcpy(m_keymap_area, keymap_str); + + m_state = xkb_state_new(keymap); + + xkb_keymap_unref(keymap); + xkb_context_unref(context); +} +#endif + +} // namespace QtWayland diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h new file mode 100644 index 000000000..80b211060 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidi ary(-ies). +** 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 QTWAYLAND_QWLKEYBOARD_P_H +#define QTWAYLAND_QWLKEYBOARD_P_H + +#include <qwayland-server-wayland.h> + +#include <QtCore/QByteArray> + +#ifndef QT_NO_WAYLAND_XKB +#include <xkbcommon/xkbcommon.h> +#endif + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +class Compositor; +class InputDevice; +class Surface; + +class Keyboard : public QtWaylandServer::wl_keyboard +{ +public: + Keyboard(Compositor *compositor, InputDevice *seat); + ~Keyboard(); + + void setFocus(Surface *surface); + + void sendKeyModifiers(Resource *resource, uint32_t serial); + void sendKeyPressEvent(uint code); + void sendKeyReleaseEvent(uint code); + + Surface *focus() const; + +protected: + void keyboard_bind_resource(Resource *resource); + void keyboard_destroy_resource(Resource *resource); + +private: + void sendKeyEvent(uint code, uint32_t state); + void updateModifierState(uint code, uint32_t state); + +#ifndef QT_NO_WAYLAND_XKB + void initXKB(); +#endif + + Compositor *m_compositor; + InputDevice *m_seat; + + Surface *m_focus; + Resource *m_focusResource; + + QByteArray m_keys; + uint32_t m_modsDepressed; + uint32_t m_modsLatched; + uint32_t m_modsLocked; + uint32_t m_group; + +#ifndef QT_NO_WAYLAND_XKB + size_t m_keymap_size; + int m_keymap_fd; + char *m_keymap_area; + struct xkb_state *m_state; +#endif +}; + +} // namespace QtWayland + +QT_END_NAMESPACE + +#endif // QTWAYLAND_QWLKEYBOARD_P_H diff --git a/src/compositor/wayland_wrapper/qwloutput.cpp b/src/compositor/wayland_wrapper/qwloutput.cpp index bb516f8c4..e5123e03b 100644 --- a/src/compositor/wayland_wrapper/qwloutput.cpp +++ b/src/compositor/wayland_wrapper/qwloutput.cpp @@ -44,8 +44,6 @@ #include <QtGui/QScreen> #include <QRect> -#include "qwaylandresourcecollection.h" - QT_BEGIN_NAMESPACE namespace QtWayland { @@ -57,7 +55,7 @@ OutputGlobal::OutputGlobal(struct ::wl_display *display) { QScreen *screen = QGuiApplication::primaryScreen(); m_geometry = QRect(QPoint(0, 0), screen->availableGeometry().size()); - m_refreshRate = qRound(screen->refreshRate()); + m_refreshRate = qRound(screen->refreshRate() * 1000.0); } OutputGlobal::~OutputGlobal() @@ -85,7 +83,7 @@ void OutputGlobal::setRefreshRate(int rate) Output *OutputGlobal::outputForClient(wl_client *client) const { - return static_cast<Output *>(resourceForClient(resourceList(), client)->data); + return static_cast<Output *>(resourceMap().value(client)); } } // namespace Wayland diff --git a/src/compositor/wayland_wrapper/qwlpointer.cpp b/src/compositor/wayland_wrapper/qwlpointer.cpp new file mode 100644 index 000000000..e1e1305e1 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlpointer.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** 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 "qwlpointer_p.h" + +#include "qwlcompositor_p.h" +#include "qwlinputdevice_p.h" +#include "qwlkeyboard_p.h" +#include "qwlsurface_p.h" +#include "qwaylandcompositor.h" + +namespace QtWayland { + +using QtWaylandServer::wl_keyboard; + +static uint32_t toWaylandButton(Qt::MouseButton button) +{ +#ifndef BTN_LEFT + uint32_t BTN_LEFT = 0x110; +#endif + // the range of valid buttons (evdev module) is from 0x110 + // through 0x11f. 0x120 is the first 'Joystick' button. + switch (button) { + case Qt::LeftButton: return BTN_LEFT; + case Qt::RightButton: return uint32_t(0x111); + case Qt::MiddleButton: return uint32_t(0x112); + case Qt::ExtraButton1: return uint32_t(0x113); // AKA Qt::BackButton, Qt::XButton1 + case Qt::ExtraButton2: return uint32_t(0x114); // AKA Qt::ForwardButton, Qt::XButton2 + case Qt::ExtraButton3: return uint32_t(0x115); + case Qt::ExtraButton4: return uint32_t(0x116); + case Qt::ExtraButton5: return uint32_t(0x117); + case Qt::ExtraButton6: return uint32_t(0x118); + case Qt::ExtraButton7: return uint32_t(0x119); + case Qt::ExtraButton8: return uint32_t(0x11a); + case Qt::ExtraButton9: return uint32_t(0x11b); + case Qt::ExtraButton10: return uint32_t(0x11c); + case Qt::ExtraButton11: return uint32_t(0x11d); + case Qt::ExtraButton12: return uint32_t(0x11e); + case Qt::ExtraButton13: return uint32_t(0x11f); + // default should not occur; but if it does, then return Wayland's highest possible button number. + default: return uint32_t(0x11f); + } +} + +Pointer::Pointer(Compositor *compositor, InputDevice *seat) + : wl_pointer() + , PointerGrabber() + , m_compositor(compositor) + , m_seat(seat) + , m_grab(this) + , m_position(100, 100) + , m_focus() + , m_focusResource() + , m_current() + , m_currentPoint() + , m_buttonCount() +{ +} + +void Pointer::setFocus(Surface *surface, const QPointF &position) +{ + if (m_focusResource && m_focus != surface) { + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_leave(m_focusResource->handle, serial, m_focus->resource()->handle); + } + + Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; + + if (resource && (m_focus != surface || resource != m_focusResource)) { + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + Keyboard *keyboard = m_seat->keyboardDevice(); + if (keyboard) { + wl_keyboard::Resource *kr = keyboard->resourceMap().value(surface->resource()->client()); + if (kr) + keyboard->sendKeyModifiers(kr, serial); + } + send_enter(resource->handle, serial, surface->resource()->handle, + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); + } + + m_focusResource = resource; + m_focus = surface; +} + +void Pointer::startGrab(PointerGrabber *grab) +{ + m_grab = grab; + grab->m_pointer = this; + + if (m_current) + grab->focus(); +} + +void Pointer::endGrab() +{ + m_grab = this; + m_grab->focus(); +} + +void Pointer::setCurrent(Surface *surface, const QPointF &point) +{ + m_current = surface; + m_currentPoint = point; +} + +bool Pointer::buttonPressed() const +{ + return m_buttonCount > 0; +} + +Surface *Pointer::focusSurface() const +{ + return m_focus; +} + +Surface *Pointer::current() const +{ + return m_current; +} + +QPointF Pointer::position() const +{ + return m_position; +} + +void Pointer::pointer_destroy_resource(wl_pointer::Resource *resource) +{ + if (m_focusResource == resource) + m_focusResource = 0; +} + +void Pointer::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos) +{ + m_position = globalPos; + + m_current = surface; + m_currentPoint = localPos; + + m_grab->focus(); +} + +void Pointer::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) +{ + sendMouseMoveEvent(localPos, globalPos); + m_buttonCount++; + uint32_t time = m_compositor->currentTimeMsecs(); + m_grab->button(time, button, WL_POINTER_BUTTON_STATE_PRESSED); +} + +void Pointer::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) +{ + sendMouseMoveEvent(localPos, globalPos); + m_buttonCount--; + uint32_t time = m_compositor->currentTimeMsecs(); + m_grab->button(time, button, WL_POINTER_BUTTON_STATE_RELEASED); +} + +void Pointer::sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos) +{ + uint32_t time = m_compositor->currentTimeMsecs(); + + m_position = globalPos; + m_currentPoint = localPos; + + m_grab->motion(time); +} + +void Pointer::sendMouseWheelEvent(Qt::Orientation orientation, int delta) +{ + if (!m_focusResource) + return; + + uint32_t time = m_compositor->currentTimeMsecs(); + uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL + : WL_POINTER_AXIS_VERTICAL_SCROLL; + send_axis(m_focusResource->handle, time, axis, wl_fixed_from_int(-delta / 12)); +} + +void Pointer::focus() +{ + if (buttonPressed()) + return; + + setFocus(m_current, m_currentPoint); +} + +void Pointer::motion(uint32_t time) +{ + if (m_focusResource) + send_motion(m_focusResource->handle, time, + wl_fixed_from_double(m_currentPoint.x()), + wl_fixed_from_double(m_currentPoint.y())); + +} + +void Pointer::button(uint32_t time, Qt::MouseButton button, uint32_t state) +{ + if (m_focusResource) { + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_button(m_focusResource->handle, serial, time, toWaylandButton(button), state); + } + + if (!buttonPressed() && state == WL_POINTER_BUTTON_STATE_RELEASED) + setFocus(m_current, m_currentPoint); +} + +void Pointer::pointer_set_cursor(wl_pointer::Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) +{ + Q_UNUSED(resource); + Q_UNUSED(serial); + + if (!surface) { + m_compositor->waylandCompositor()->setCursorSurface(NULL, 0, 0); + return; + } + + Surface *s = Surface::fromResource(surface); + s->setCursorSurface(true); + m_compositor->waylandCompositor()->setCursorSurface(s->waylandSurface(), hotspot_x, hotspot_y); +} + +PointerGrabber::~PointerGrabber() +{ +} + +} // namespace QtWayland diff --git a/src/compositor/wayland_wrapper/qwlpointer_p.h b/src/compositor/wayland_wrapper/qwlpointer_p.h new file mode 100644 index 000000000..f6db2dcb3 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlpointer_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** 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 QTWAYLAND_QWLPOINTER_P_H +#define QTWAYLAND_QWLPOINTER_P_H + +#include <QtCore/QList> +#include <QtCore/QPoint> + +#include <qwayland-server-wayland.h> + +#include <stdint.h> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +class Compositor; +class InputDevice; +class Pointer; +class Surface; + +class PointerGrabber { +public: + virtual ~PointerGrabber(); + + virtual void focus() = 0; + virtual void motion(uint32_t time) = 0; + virtual void button(uint32_t time, Qt::MouseButton button, uint32_t state) = 0; + + Pointer *m_pointer; +}; + +class Pointer : public QtWaylandServer::wl_pointer, public PointerGrabber +{ +public: + Pointer(Compositor *compositor, InputDevice *seat); + + void setFocus(Surface *surface, const QPointF &position); + + void startGrab(PointerGrabber *grab); + void endGrab(); + + void setCurrent(Surface *surface, const QPointF &point); + void setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos); + + void sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos); + void sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos); + void sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos); + void sendMouseWheelEvent(Qt::Orientation orientation, int delta); + + Surface *focusSurface() const; + Surface *current() const; + QPointF position() const; + + void focus() Q_DECL_OVERRIDE; + void motion(uint32_t time) Q_DECL_OVERRIDE; + void button(uint32_t time, Qt::MouseButton button, uint32_t state) Q_DECL_OVERRIDE; + +protected: + void pointer_set_cursor(Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) Q_DECL_OVERRIDE; + void pointer_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + +private: + bool buttonPressed() const; + + Compositor *m_compositor; + InputDevice *m_seat; + + PointerGrabber *m_grab; + + QPointF m_position; + + Surface *m_focus; + Resource *m_focusResource; + + Surface *m_current; + QPointF m_currentPoint; + + int m_buttonCount; +}; + +} // namespace QtWayland + +QT_END_NAMESPACE + +#endif // QTWAYLAND_QWLPOINTER_P_H diff --git a/src/compositor/wayland_wrapper/qwlqtkey.cpp b/src/compositor/wayland_wrapper/qwlqtkey.cpp index 6ced27881..a2b99ebc1 100644 --- a/src/compositor/wayland_wrapper/qwlqtkey.cpp +++ b/src/compositor/wayland_wrapper/qwlqtkey.cpp @@ -57,14 +57,12 @@ QtKeyExtensionGlobal::QtKeyExtensionGlobal(Compositor *compositor) bool QtKeyExtensionGlobal::postQtKeyEvent(QKeyEvent *event, Surface *surface) { - wl_client *surfaceClient = surface->resource()->client(); - uint32_t time = m_compositor->currentTimeMsecs(); - struct wl_resource *target = resourceForClient(resourceList(), surfaceClient); + Resource *target = surface ? resourceMap().value(surface->resource()->client()) : 0; if (target) { - send_qtkey(target, + send_qtkey(target->handle, time, event->type(), event->key(), event->modifiers(), event->nativeScanCode(), event->nativeVirtualKey(), diff --git a/src/compositor/wayland_wrapper/qwlqttouch.cpp b/src/compositor/wayland_wrapper/qwlqttouch.cpp new file mode 100644 index 000000000..2b97bef72 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlqttouch.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** 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 "qwlqttouch_p.h" +#include "qwlsurface_p.h" +#include <QTouchEvent> +#include <QWindow> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +static const int maxRawPos = 24; + +TouchExtensionGlobal::TouchExtensionGlobal(Compositor *compositor) + : QtWaylandServer::qt_touch_extension(compositor->wl_display()) + , m_compositor(compositor) + , m_flags(0) + , m_resources() + , m_posData(maxRawPos * 2) +{ +} + +TouchExtensionGlobal::~TouchExtensionGlobal() +{ +} + +static inline int toFixed(qreal f) +{ + return int(f * 10000); +} + +bool TouchExtensionGlobal::postTouchEvent(QTouchEvent *event, Surface *surface) +{ + const QList<QTouchEvent::TouchPoint> points = event->touchPoints(); + const int pointCount = points.count(); + if (!pointCount) + return false; + + QPointF surfacePos = surface->pos(); + wl_client *surfaceClient = surface->resource()->client(); + uint32_t time = m_compositor->currentTimeMsecs(); + const int rescount = m_resources.count(); + + for (int res = 0; res < rescount; ++res) { + Resource *target = m_resources.at(res); + if (target->client() != surfaceClient) + continue; + + // We will use no touch_frame type of event, to reduce the number of + // events flowing through the wire. Instead, the number of points sent is + // included in the touch point events. + int sentPointCount = 0; + for (int i = 0; i < pointCount; ++i) { + if (points.at(i).state() != Qt::TouchPointStationary) + ++sentPointCount; + } + + for (int i = 0; i < pointCount; ++i) { + const QTouchEvent::TouchPoint &tp(points.at(i)); + // Stationary points are never sent. They are cached on client side. + if (tp.state() == Qt::TouchPointStationary) + continue; + + uint32_t id = tp.id(); + uint32_t state = (tp.state() & 0xFFFF) | (sentPointCount << 16); + uint32_t flags = (tp.flags() & 0xFFFF) | (int(event->device()->capabilities()) << 16); + + QPointF p = tp.pos() - surfacePos; // surface-relative + int x = toFixed(p.x()); + int y = toFixed(p.y()); + int nx = toFixed(tp.normalizedPos().x()); + int ny = toFixed(tp.normalizedPos().y()); + int w = toFixed(tp.rect().width()); + int h = toFixed(tp.rect().height()); + int vx = toFixed(tp.velocity().x()); + int vy = toFixed(tp.velocity().y()); + uint32_t pressure = uint32_t(tp.pressure() * 255); + + QByteArray rawData; + QVector<QPointF> rawPosList = tp.rawScreenPositions(); + int rawPosCount = rawPosList.count(); + if (rawPosCount) { + rawPosCount = qMin(maxRawPos, rawPosCount); + QVector<float>::iterator iter = m_posData.begin(); + for (int rpi = 0; rpi < rawPosCount; ++rpi) { + const QPointF &rawPos(rawPosList.at(rpi)); + // This will stay in screen coordinates for performance + // reasons, clients using this data will presumably know + // what they are doing. + *iter++ = static_cast<float>(rawPos.x()); + *iter++ = static_cast<float>(rawPos.y()); + } + rawData = QByteArray::fromRawData(reinterpret_cast<const char*>(m_posData.constData()), sizeof(float) * rawPosCount * 2); + } + + send_touch(target->handle, + time, id, state, + x, y, nx, ny, w, h, + pressure, vx, vy, + flags, rawData); + } + + return true; + } + + return false; +} + +void TouchExtensionGlobal::touch_extension_bind_resource(Resource *resource) +{ + m_resources.append(resource); + send_configure(resource->handle, m_flags); +} + +void TouchExtensionGlobal::touch_extension_destroy_resource(Resource *resource) +{ + m_resources.removeOne(resource); +} + +} + +QT_END_NAMESPACE diff --git a/src/compositor/global/qwaylandobject.h b/src/compositor/wayland_wrapper/qwlqttouch_p.h index 9b3450397..2610936a3 100644 --- a/src/compositor/global/qwaylandobject.h +++ b/src/compositor/wayland_wrapper/qwlqttouch_p.h @@ -38,32 +38,44 @@ ** ****************************************************************************/ -#ifndef WAYLAND_OBJECT_H -#define WAYLAND_OBJECT_H +#ifndef WLTOUCH_H +#define WLTOUCH_H -#include <wayland-server.h> -#include <string.h> - -#include <QtCompositor/qwaylandexport.h> +#include <private/qwlcompositor_p.h> +#include "qwayland-server-touch-extension.h" +#include "wayland-util.h" QT_BEGIN_NAMESPACE +class Compositor; +class Surface; +class QTouchEvent; + namespace QtWayland { -template <typename T> -class Object : public T +class TouchExtensionGlobal : public QtWaylandServer::qt_touch_extension { public: - typedef T Base; + TouchExtensionGlobal(Compositor *compositor); + ~TouchExtensionGlobal(); + + bool postTouchEvent(QTouchEvent *event, Surface *surface); + + void setFlags(int flags) { m_flags = flags; } - Object() { memset(this, 0, sizeof(T)); } +protected: + void touch_extension_bind_resource(Resource *resource) Q_DECL_OVERRIDE; + void touch_extension_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; - const T *base() const { return this; } - T *base() { return this; } +private: + Compositor *m_compositor; + int m_flags; + QList<Resource *> m_resources; + QVector<float> m_posData; }; } QT_END_NAMESPACE -#endif //WAYLAND_OBJECT_H +#endif // WLTOUCH_H diff --git a/src/compositor/wayland_wrapper/qwlshellsurface.cpp b/src/compositor/wayland_wrapper/qwlshellsurface.cpp index 903b42592..a1e6bb377 100644 --- a/src/compositor/wayland_wrapper/qwlshellsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlshellsurface.cpp @@ -44,6 +44,8 @@ #include "qwlsurface_p.h" #include "qwlinputdevice_p.h" #include "qwlsubsurface_p.h" +#include "qwlpointer_p.h" +#include "qwlextendedsurface_p.h" #include <QtCore/qglobal.h> #include <QtCore/QDebug> @@ -106,8 +108,8 @@ void ShellSurface::adjustPosInResize() if (!m_resizeGrabber || !(m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT)) return; - int bottomLeftX = wl_fixed_to_int(m_resizeGrabber->base()->x) + m_resizeGrabber->width; - int bottomLeftY = wl_fixed_to_int(m_resizeGrabber->base()->y) + m_resizeGrabber->height; + int bottomLeftX = m_resizeGrabber->point.x() + m_resizeGrabber->width; + int bottomLeftY = m_resizeGrabber->point.y() + m_resizeGrabber->height; qreal x = surface()->pos().x(); qreal y = surface()->pos().y(); if (m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) @@ -166,15 +168,11 @@ void ShellSurface::shell_surface_move(Resource *resource, } InputDevice *input_device = InputDevice::fromSeatResource(input_device_super); - ::wl_pointer *pointer = input_device->pointerDevice(); + Pointer *pointer = input_device->pointerDevice(); - m_moveGrabber = new ShellSurfaceMoveGrabber(this); - m_moveGrabber->base()->x = pointer->x; - m_moveGrabber->base()->y = pointer->y; - m_moveGrabber->offset_x = wl_fixed_to_int(pointer->x) - surface()->pos().x(); - m_moveGrabber->offset_y = wl_fixed_to_int(pointer->y) - surface()->pos().y(); + m_moveGrabber = new ShellSurfaceMoveGrabber(this, pointer->position() - surface()->pos()); - wl_pointer_start_grab(pointer, m_moveGrabber->base()); + pointer->startGrab(m_moveGrabber); } void ShellSurface::shell_surface_resize(Resource *resource, @@ -194,15 +192,14 @@ void ShellSurface::shell_surface_resize(Resource *resource, m_resizeGrabber = new ShellSurfaceResizeGrabber(this); InputDevice *input_device = InputDevice::fromSeatResource(input_device_super); - ::wl_pointer *pointer = input_device->pointerDevice(); + Pointer *pointer = input_device->pointerDevice(); - m_resizeGrabber->base()->x = pointer->x; - m_resizeGrabber->base()->y = pointer->y; - m_resizeGrabber->resize_edges = wl_shell_surface_resize(edges); + m_resizeGrabber->point = pointer->position(); + m_resizeGrabber->resize_edges = static_cast<wl_shell_surface_resize>(edges); m_resizeGrabber->width = surface()->size().width(); m_resizeGrabber->height = surface()->size().height(); - wl_pointer_start_grab(pointer, m_resizeGrabber->base()); + pointer->startGrab(m_resizeGrabber); } void ShellSurface::shell_surface_set_toplevel(Resource *resource) @@ -212,6 +209,8 @@ void ShellSurface::shell_surface_set_toplevel(Resource *resource) m_xOffset = 0; m_yOffset = 0; + if (m_surface->extendedSurface()) + m_surface->extendedSurface()->setVisibility(QWindow::Windowed, false); } void ShellSurface::shell_surface_set_transient(Resource *resource, @@ -229,6 +228,9 @@ void ShellSurface::shell_surface_set_transient(Resource *resource, m_yOffset = y; if (flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE) surface()->setTransientInactive(true); + + if (m_surface->extendedSurface()) + m_surface->extendedSurface()->setVisibility(QWindow::AutomaticVisibility, false); } void ShellSurface::shell_surface_set_fullscreen(Resource *resource, @@ -240,6 +242,11 @@ void ShellSurface::shell_surface_set_fullscreen(Resource *resource, Q_UNUSED(method); Q_UNUSED(framerate); Q_UNUSED(output); + QSize defaultScreenSize = m_surface->compositor()->outputGeometry().size(); + send_configure(resize_bottom_right, defaultScreenSize.width(), defaultScreenSize.height()); + + if (m_surface->extendedSurface()) + m_surface->extendedSurface()->setVisibility(QWindow::FullScreen, false); } void ShellSurface::shell_surface_set_popup(Resource *resource, wl_resource *input_device, uint32_t time, wl_resource *parent, int32_t x, int32_t y, uint32_t flags) @@ -251,6 +258,9 @@ void ShellSurface::shell_surface_set_popup(Resource *resource, wl_resource *inpu Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(flags); + + if (m_surface->extendedSurface()) + m_surface->extendedSurface()->setVisibility(QWindow::AutomaticVisibility, false); } void ShellSurface::shell_surface_set_maximized(Resource *resource, @@ -258,6 +268,11 @@ void ShellSurface::shell_surface_set_maximized(Resource *resource, { Q_UNUSED(resource); Q_UNUSED(output); + QSize defaultScreenSize = m_surface->compositor()->outputGeometry().size(); + send_configure(resize_bottom_right, defaultScreenSize.width(), defaultScreenSize.height()); + + if (m_surface->extendedSurface()) + m_surface->extendedSurface()->setVisibility(QWindow::Maximized, false); } void ShellSurface::shell_surface_pong(Resource *resource, @@ -281,175 +296,91 @@ void ShellSurface::shell_surface_set_class(Resource *resource, surface()->setClassName(className); } -Qt::MouseButton toQtButton(uint32_t button) -{ -#ifndef BTN_LEFT - static const uint32_t BTN_LEFT = 0x110; - static const uint32_t BTN_RIGHT = 0x111; - static const uint32_t BTN_MIDDLE = 0x112; -#endif - switch (button) { - case BTN_LEFT: - return Qt::LeftButton; - case BTN_RIGHT: - return Qt::RightButton; - case BTN_MIDDLE: - return Qt::MiddleButton; - default: - return Qt::NoButton; - } -} - -ShellSurfaceGrabber::ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface) - : shell_surface(shellSurface) +ShellSurfaceGrabber::ShellSurfaceGrabber(ShellSurface *shellSurface) + : PointerGrabber() + , shell_surface(shellSurface) { - base()->interface = interface; - base()->focus = shell_surface->surface(); } ShellSurfaceGrabber::~ShellSurfaceGrabber() { } - -void ShellSurfaceGrabber::destroy(wl_listener *listener, wl_resource *resource, uint32_t time) -{ - Q_UNUSED(resource); - Q_UNUSED(time); - Q_UNUSED(listener); - //ShellSurfaceGrabber *shell_surface_grabber = container_of(listener, ShellSurfaceGrabber,surface_destroy_listener); - Q_ASSERT(false); //hasn't been enabled yet - //wl_input_device_end_grab(shell_surface_grabber->base()->input_device,Compositor::currentTimeMsecs()); -} - - ShellSurfaceResizeGrabber::ShellSurfaceResizeGrabber(ShellSurface *shellSurface) - : ShellSurfaceGrabber(shellSurface,&resize_grabber_interface) + : ShellSurfaceGrabber(shellSurface) { } -void ShellSurfaceResizeGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y) +void ShellSurfaceResizeGrabber::focus() { - Q_UNUSED(grab); - Q_UNUSED(surface); - Q_UNUSED(x); - Q_UNUSED(y); } -void ShellSurfaceResizeGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y) +void ShellSurfaceResizeGrabber::motion(uint32_t time) { Q_UNUSED(time); - Q_UNUSED(x); - Q_UNUSED(y); - //Should be more structured - ShellSurfaceResizeGrabber *resize_grabber = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab); - ShellSurface *shell_surface = resize_grabber->shell_surface; - wl_pointer *pointer = grab->pointer; - int width_delta = wl_fixed_to_int(grab->x) - wl_fixed_to_int(pointer->x); - int height_delta = wl_fixed_to_int(grab->y) - wl_fixed_to_int(pointer->y); - int new_width = resize_grabber->width; - int new_height = resize_grabber->height; - if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT) { - if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) { - if (new_height + height_delta > 0) { - new_height += height_delta; - } else { - new_height = 1; - } - } - if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) { - if (new_width + width_delta > 0) { - new_width += width_delta; - } else { - new_width = 1; - } - } - } - if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) { - if (new_height - height_delta > 0) { - new_height -= height_delta; - } else { - new_height = 1; - } - } - if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_RIGHT) { - if (new_width - width_delta > 0) { - new_width -= width_delta; - } else { - new_width =1; - } - } + int width_delta = point.x() - m_pointer->position().x(); + int height_delta = point.y() - m_pointer->position().y(); + + int new_height = height; + if (resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) + new_height = qMax(new_height + height_delta, 1); + else if (resize_edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) + new_height = qMax(new_height - height_delta, 1); - shell_surface->sendConfigure(resize_grabber->resize_edges,new_width,new_height); + int new_width = width; + if (resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) + new_width = qMax(new_width + width_delta, 1); + else if (resize_edges & WL_SHELL_SURFACE_RESIZE_RIGHT) + new_width = qMax(new_width - width_delta, 1); + + shell_surface->sendConfigure(resize_edges, new_width, new_height); } -void ShellSurfaceResizeGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state) +void ShellSurfaceResizeGrabber::button(uint32_t time, Qt::MouseButton button, uint32_t state) { Q_UNUSED(time) - ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab); - ShellSurface *shell_surface = self->shell_surface; - if (toQtButton(button) == Qt::LeftButton && !state) { - wl_pointer_end_grab(grab->pointer); + + if (button == Qt::LeftButton && !state) { + m_pointer->endGrab(); shell_surface->resetResizeGrabber(); - delete self; + delete this; } } -const struct wl_pointer_grab_interface ShellSurfaceResizeGrabber::resize_grabber_interface = { - ShellSurfaceResizeGrabber::focus, - ShellSurfaceResizeGrabber::motion, - ShellSurfaceResizeGrabber::button -}; - -ShellSurfaceMoveGrabber::ShellSurfaceMoveGrabber(ShellSurface *shellSurface) - : ShellSurfaceGrabber(shellSurface,&move_grabber_interface) +ShellSurfaceMoveGrabber::ShellSurfaceMoveGrabber(ShellSurface *shellSurface, const QPointF &offset) + : ShellSurfaceGrabber(shellSurface) + , m_offset(offset) { } -void ShellSurfaceMoveGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y) +void ShellSurfaceMoveGrabber::focus() { - Q_UNUSED(grab); - Q_UNUSED(surface); - Q_UNUSED(x); - Q_UNUSED(y); } -void ShellSurfaceMoveGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y) +void ShellSurfaceMoveGrabber::motion(uint32_t time) { Q_UNUSED(time); - Q_UNUSED(x); - Q_UNUSED(y); - ShellSurfaceMoveGrabber *shell_surface_grabber = reinterpret_cast<ShellSurfaceMoveGrabber *>(grab); - ShellSurface *shell_surface = shell_surface_grabber->shell_surface; - wl_pointer *pointer = grab->pointer; - QPointF pos(wl_fixed_to_int(pointer->x) - shell_surface_grabber->offset_x, - wl_fixed_to_int(pointer->y) - shell_surface_grabber->offset_y); + + QPointF pos(m_pointer->position() - m_offset); shell_surface->surface()->setPos(pos); if (shell_surface->transientParent()) shell_surface->setOffset(pos - shell_surface->transientParent()->surface()->pos()); } -void ShellSurfaceMoveGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state) +void ShellSurfaceMoveGrabber::button(uint32_t time, Qt::MouseButton button, uint32_t state) { Q_UNUSED(time) - ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab); - ShellSurface *shell_surface = self->shell_surface; - if (toQtButton(button) == Qt::LeftButton && !state) { - wl_pointer_set_focus(grab->pointer, 0, 0, 0); - wl_pointer_end_grab(grab->pointer); + + if (button == Qt::LeftButton && !state) { + m_pointer->setFocus(0, QPointF()); + m_pointer->endGrab(); shell_surface->resetMoveGrabber(); - delete self; + delete this; } } -const struct wl_pointer_grab_interface ShellSurfaceMoveGrabber::move_grabber_interface = { - ShellSurfaceMoveGrabber::focus, - ShellSurfaceMoveGrabber::motion, - ShellSurfaceMoveGrabber::button -}; - } QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlshellsurface_p.h b/src/compositor/wayland_wrapper/qwlshellsurface_p.h index 4c296a97c..91fb17c2a 100644 --- a/src/compositor/wayland_wrapper/qwlshellsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlshellsurface_p.h @@ -42,8 +42,8 @@ #define WLSHELLSURFACE_H #include <wayland-server.h> -#include <qwaylandobject.h> #include <QPoint> +#include <private/qwlpointer_p.h> #include <qwayland-server-wayland.h> @@ -136,16 +136,12 @@ private: const QString &class_) Q_DECL_OVERRIDE; }; -class ShellSurfaceGrabber : public Object<struct ::wl_pointer_grab> +class ShellSurfaceGrabber : public PointerGrabber { public: - ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface); + ShellSurfaceGrabber(ShellSurface *shellSurface); ~ShellSurfaceGrabber(); - struct wl_listener surface_destroy_listener; - static void destroy(struct wl_listener *listener, - struct wl_resource *resource, uint32_t time); - ShellSurface *shell_surface; }; @@ -154,35 +150,27 @@ class ShellSurfaceResizeGrabber : public ShellSurfaceGrabber public: ShellSurfaceResizeGrabber(ShellSurface *shellSurface); - + QPointF point; enum wl_shell_surface_resize resize_edges; int32_t width; int32_t height; - static void focus(struct wl_pointer_grab *grab, - struct wl_surface *surface, int32_t x, int32_t y); - static void motion(struct wl_pointer_grab *grab, - uint32_t time, int32_t x, int32_t y); - static void button(struct wl_pointer_grab *grab, - uint32_t time, uint32_t mouse_grabber_button, uint32_t state); - static const struct wl_pointer_grab_interface resize_grabber_interface; + void focus() Q_DECL_OVERRIDE; + void motion(uint32_t time) Q_DECL_OVERRIDE; + void button(uint32_t time, Qt::MouseButton button, uint32_t state) Q_DECL_OVERRIDE; }; class ShellSurfaceMoveGrabber : public ShellSurfaceGrabber { public: - ShellSurfaceMoveGrabber(ShellSurface *shellSurface); - - int32_t offset_x; - int32_t offset_y; - - static void focus(struct wl_pointer_grab *grab, - struct wl_surface *surface, int32_t x, int32_t y); - static void motion(struct wl_pointer_grab *grab, - uint32_t time, int32_t x, int32_t y); - static void button(struct wl_pointer_grab *grab, - uint32_t time, uint32_t mouse_grabber_button, uint32_t state); - static const struct wl_pointer_grab_interface move_grabber_interface; + ShellSurfaceMoveGrabber(ShellSurface *shellSurface, const QPointF &offset); + + void focus() Q_DECL_OVERRIDE; + void motion(uint32_t time) Q_DECL_OVERRIDE; + void button(uint32_t time, Qt::MouseButton button, uint32_t state) Q_DECL_OVERRIDE; + +private: + QPointF m_offset; }; } diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index 85dfddb42..f3a9aa4d3 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -74,7 +74,7 @@ namespace QtWayland { static bool QT_WAYLAND_PRINT_BUFFERING_WARNINGS = qEnvironmentVariableIsSet("QT_WAYLAND_PRINT_BUFFERING_WARNINGS"); Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor) - : QtWaylandServer::wl_surface(client, &base()->resource, id) + : QtWaylandServer::wl_surface(client, id) , m_compositor(compositor) , m_waylandSurface(new QWaylandSurface(this)) , m_backBuffer(0) @@ -95,7 +95,6 @@ Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor) Surface::~Surface() { delete m_waylandSurface; - delete m_extendedSurface; delete m_subSurface; for (int i = 0; i < buffer_pool_size; i++) { @@ -302,11 +301,9 @@ bool Surface::advanceBufferQueue() if (m_backBuffer && !m_backBuffer->isDisplayed()) return true; if (m_bufferQueue.size()) { - int width = 0; - int height = 0; + QSize size; if (m_backBuffer && m_backBuffer->waylandBufferHandle()) { - width = m_backBuffer->width(); - height = m_backBuffer->height(); + size = m_backBuffer->size(); } if (!m_bufferQueue.first()->isComitted()) @@ -322,10 +319,9 @@ bool Surface::advanceBufferQueue() return false; //we have no new backbuffer; if (m_backBuffer->waylandBufferHandle()) { - width = m_backBuffer->width(); - height = m_backBuffer->height(); + size = m_backBuffer->size(); } - setSize(QSize(width,height)); + setSize(size); if (m_backBuffer && (!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) { @@ -364,7 +360,7 @@ void Surface::doUpdate() { } } -SurfaceBuffer *Surface::createSurfaceBuffer(struct wl_buffer *buffer) +SurfaceBuffer *Surface::createSurfaceBuffer(struct ::wl_resource *buffer) { SurfaceBuffer *newBuffer = 0; for (int i = 0; i < Surface::buffer_pool_size; i++) { @@ -400,7 +396,7 @@ bool Surface::postBuffer() { return false; } -void Surface::attach(struct wl_buffer *buffer) +void Surface::attach(struct ::wl_resource *buffer) { SurfaceBuffer *last = m_bufferQueue.size()?m_bufferQueue.last():0; if (last) { @@ -459,7 +455,7 @@ void Surface::surface_attach(Resource *, struct wl_resource *buffer, int x, int Q_UNUSED(x); Q_UNUSED(y); - attach(buffer ? reinterpret_cast<wl_buffer *>(buffer->data) : 0); + attach(buffer); } void Surface::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height) diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index 0a4413ae3..a4817d7b8 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -42,7 +42,6 @@ #define WL_SURFACE_H #include <QtCompositor/qwaylandexport.h> -#include <QtCompositor/qwaylandobject.h> #include <private/qwlsurfacebuffer_p.h> #include <QtCompositor/qwaylandsurface.h> @@ -74,7 +73,7 @@ class ExtendedSurface; class SubSurface; class ShellSurface; -class Q_COMPOSITOR_EXPORT Surface : public Object<struct ::wl_surface>, public QtWaylandServer::wl_surface +class Q_COMPOSITOR_EXPORT Surface : public QtWaylandServer::wl_surface { public: Surface(struct wl_client *client, uint32_t id, Compositor *compositor); @@ -87,8 +86,6 @@ public: bool visible() const; - uint id() const { return ::wl_surface::resource.object.id; } - using QtWaylandServer::wl_surface::resource; QPointF pos() const; @@ -175,11 +172,11 @@ private: void damage(const QRect &rect); bool advanceBufferQueue(); void doUpdate(); - SurfaceBuffer *createSurfaceBuffer(struct wl_buffer *buffer); + SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); void frameFinishedInternal(); bool postBuffer(); - void attach(struct wl_buffer *buffer); + void attach(struct ::wl_resource *buffer); void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp index 064d7be7f..9fafc39c6 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp @@ -67,7 +67,9 @@ SurfaceBuffer::SurfaceBuffer(Surface *surface) , m_texture(0) , m_guard(0) , m_is_shm_resolved(false) - , m_is_shm(false) + , m_shmBuffer(0) + , m_isSizeResolved(false) + , m_size() , m_image(0) { } @@ -78,7 +80,7 @@ SurfaceBuffer::~SurfaceBuffer() destructBufferState(); } -void SurfaceBuffer::initialize(wl_buffer *buffer) +void SurfaceBuffer::initialize(struct ::wl_resource *buffer) { m_buffer = buffer; m_texture = 0; @@ -91,11 +93,13 @@ void SurfaceBuffer::initialize(wl_buffer *buffer) m_destroyed = false; m_handle = 0; m_is_shm_resolved = false; - m_is_shm = false; + m_shmBuffer = 0; + m_isSizeResolved = false; + m_size = QSize(); m_destroy_listener.surfaceBuffer = this; m_destroy_listener.listener.notify = destroy_listener_callback; if (buffer) - wl_signal_add(&buffer->resource.destroy_signal, &m_destroy_listener.listener); + wl_signal_add(&buffer->destroy_signal, &m_destroy_listener.listener); m_damageRect = QRect(); } @@ -107,7 +111,7 @@ void SurfaceBuffer::destructBufferState() if (m_buffer) { if (m_handle) { - if (m_is_shm) { + if (m_shmBuffer) { delete static_cast<QImage *>(m_handle); #ifdef QT_COMPOSITOR_WAYLAND_GL } else { @@ -127,20 +131,40 @@ void SurfaceBuffer::destructBufferState() m_image = QImage(); } +QSize SurfaceBuffer::size() const +{ + if (!m_isSizeResolved) { + if (isShmBuffer()) { + m_size = QSize(wl_shm_buffer_get_width(m_shmBuffer), wl_shm_buffer_get_height(m_shmBuffer)); +#ifdef QT_COMPOSITOR_WAYLAND_GL + } else { + QWaylandGraphicsHardwareIntegration *hwIntegration = m_compositor->graphicsHWIntegration(); + m_size = hwIntegration->bufferSize(m_buffer); +#endif + } + } + + return m_size; +} + bool SurfaceBuffer::isShmBuffer() const { if (!m_is_shm_resolved) { - SurfaceBuffer *that = const_cast<SurfaceBuffer *>(this); - that->m_is_shm = wl_buffer_is_shm(m_buffer); - that->m_is_shm_resolved = true; +#if (WAYLAND_VERSION_MAJOR >= 1) && (WAYLAND_VERSION_MINOR >= 2) + m_shmBuffer = wl_shm_buffer_get(m_buffer); +#else + if (wl_buffer_is_shm(static_cast<struct ::wl_buffer*>(m_buffer->data))) + m_shmBuffer = static_cast<struct ::wl_buffer*>(m_buffer->data); +#endif + m_is_shm_resolved = true; } - return m_is_shm; + return m_shmBuffer != 0; } void SurfaceBuffer::sendRelease() { Q_ASSERT(m_buffer); - wl_buffer_send_release(&m_buffer->resource); + wl_buffer_send_release(m_buffer); } void SurfaceBuffer::setPageFlipperHasBuffer(bool owns) @@ -221,10 +245,10 @@ void *SurfaceBuffer::handle() const if (!m_handle) { SurfaceBuffer *that = const_cast<SurfaceBuffer *>(this); if (isShmBuffer()) { - const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_buffer)); - int stride = wl_shm_buffer_get_stride(m_buffer); - int width = m_buffer->width; - int height = m_buffer->height; + const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_shmBuffer)); + int stride = wl_shm_buffer_get_stride(m_shmBuffer); + int width = wl_shm_buffer_get_width(m_shmBuffer); + int height = wl_shm_buffer_get_height(m_shmBuffer); QImage *image = new QImage(data,width,height,stride, QImage::Format_ARGB32_Premultiplied); that->m_handle = image; #ifdef QT_COMPOSITOR_WAYLAND_GL @@ -245,10 +269,10 @@ QImage SurfaceBuffer::image() if (m_image.isNull()) { - const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_buffer)); - int stride = wl_shm_buffer_get_stride(m_buffer); - int width = m_buffer->width; - int height = m_buffer->height; + const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_shmBuffer)); + int stride = wl_shm_buffer_get_stride(m_shmBuffer); + int width = wl_shm_buffer_get_width(m_shmBuffer); + int height = wl_shm_buffer_get_height(m_shmBuffer); m_image = QImage(data, width, height, stride, QImage::Format_ARGB32_Premultiplied); } diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h index 2595f1fdd..93627f67b 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h @@ -72,11 +72,10 @@ public: ~SurfaceBuffer(); - void initialize(struct wl_buffer *buffer); + void initialize(struct ::wl_resource *bufferResource); void destructBufferState(); - inline int32_t width() const { return m_buffer->width; } - inline int32_t height() const { return m_buffer->height; } + QSize size() const; bool isShmBuffer() const; @@ -104,7 +103,7 @@ public: inline GLuint texture() const; void destroyTexture(); - inline struct wl_buffer *waylandBufferHandle() const { return m_buffer; } + inline struct ::wl_resource *waylandBufferHandle() const { return m_buffer; } void handleAboutToBeDisplayed(); void handleDisplayed(); @@ -114,7 +113,7 @@ public: private: Surface *m_surface; Compositor *m_compositor; - struct wl_buffer *m_buffer; + struct ::wl_resource *m_buffer; struct surface_buffer_destroy_listener m_destroy_listener; QRect m_damageRect; bool m_committed; @@ -131,8 +130,16 @@ private: uint m_guard; #endif void *m_handle; - bool m_is_shm_resolved; - bool m_is_shm; + mutable bool m_is_shm_resolved; + +#if (WAYLAND_VERSION_MAJOR >= 1) && (WAYLAND_VERSION_MINOR >= 2) + mutable struct ::wl_shm_buffer *m_shmBuffer; +#else + mutable struct ::wl_buffer *m_shmBuffer; +#endif + + mutable bool m_isSizeResolved; + mutable QSize m_size; QImage m_image; diff --git a/src/compositor/wayland_wrapper/qwltouch.cpp b/src/compositor/wayland_wrapper/qwltouch.cpp index 7142c985e..e595440d7 100644 --- a/src/compositor/wayland_wrapper/qwltouch.cpp +++ b/src/compositor/wayland_wrapper/qwltouch.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Compositor. @@ -39,142 +40,66 @@ ****************************************************************************/ #include "qwltouch_p.h" -#include "qwlsurface_p.h" -#include <QTouchEvent> -#include <QWindow> -QT_BEGIN_NAMESPACE +#include "qwlcompositor_p.h" +#include "qwlsurface_p.h" namespace QtWayland { -static void dummy(wl_client *, wl_resource *) +Touch::Touch(Compositor *compositor) + : wl_touch() + , m_compositor(compositor) + , m_focus() + , m_focusResource() { } -const struct qt_touch_extension_interface TouchExtensionGlobal::touch_interface = { - dummy -}; - -static const int maxRawPos = 24; - -TouchExtensionGlobal::TouchExtensionGlobal(Compositor *compositor) - : m_compositor(compositor), - m_flags(0) +void Touch::setFocus(Surface *surface) { - wl_array_init(&m_rawdata_array); - m_rawdata_ptr = static_cast<float *>(wl_array_add(&m_rawdata_array, maxRawPos * sizeof(float) * 2)); - - wl_display_add_global(compositor->wl_display(), - &qt_touch_extension_interface, - this, - TouchExtensionGlobal::bind_func); + m_focus = surface; + m_focusResource = surface ? resourceMap().value(surface->resource()->client()) : 0; } -TouchExtensionGlobal::~TouchExtensionGlobal() +void Touch::sendCancel() { - wl_array_release(&m_rawdata_array); + if (m_focusResource) + send_cancel(m_focusResource->handle); } -void TouchExtensionGlobal::destroy_resource(wl_resource *resource) +void Touch::sendFrame() { - TouchExtensionGlobal *self = static_cast<TouchExtensionGlobal *>(resource->data); - self->m_resources.removeOne(resource); - free(resource); + if (m_focusResource) + send_frame(m_focusResource->handle); } -void TouchExtensionGlobal::bind_func(wl_client *client, void *data, uint32_t version, uint32_t id) +void Touch::sendDown(int touch_id, const QPointF &position) { - Q_UNUSED(version); - wl_resource *resource = wl_client_add_object(client, &qt_touch_extension_interface, &touch_interface, id, data); - resource->destroy = destroy_resource; - TouchExtensionGlobal *self = static_cast<TouchExtensionGlobal *>(resource->data); - self->m_resources.append(resource); - qt_touch_extension_send_configure(resource, self->m_flags); + if (!m_focusResource || !m_focus) + return; + + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + + send_down(m_focusResource->handle, serial, Compositor::currentTimeMsecs(), m_focus->resource()->handle, touch_id, + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); } -static inline int toFixed(qreal f) +void Touch::sendMotion(int touch_id, const QPointF &position) { - return int(f * 10000); + if (!m_focusResource) + return; + + send_motion(m_focusResource->handle, Compositor::currentTimeMsecs(), touch_id, + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); } -bool TouchExtensionGlobal::postTouchEvent(QTouchEvent *event, Surface *surface) +void Touch::sendUp(int touch_id) { - const QList<QTouchEvent::TouchPoint> points = event->touchPoints(); - const int pointCount = points.count(); - if (!pointCount) - return false; - - QPointF surfacePos = surface->pos(); - wl_client *surfaceClient = surface->resource()->client(); - uint32_t time = m_compositor->currentTimeMsecs(); - const int rescount = m_resources.count(); - - for (int res = 0; res < rescount; ++res) { - wl_resource *target = m_resources.at(res); - if (target->client != surfaceClient) - continue; - - // We will use no touch_frame type of event, to reduce the number of - // events flowing through the wire. Instead, the number of points sent is - // included in the touch point events. - int sentPointCount = 0; - for (int i = 0; i < pointCount; ++i) { - if (points.at(i).state() != Qt::TouchPointStationary) - ++sentPointCount; - } - - for (int i = 0; i < pointCount; ++i) { - const QTouchEvent::TouchPoint &tp(points.at(i)); - // Stationary points are never sent. They are cached on client side. - if (tp.state() == Qt::TouchPointStationary) - continue; - - uint32_t id = tp.id(); - uint32_t state = (tp.state() & 0xFFFF) | (sentPointCount << 16); - uint32_t flags = (tp.flags() & 0xFFFF) | (int(event->device()->capabilities()) << 16); - - QPointF p = tp.pos() - surfacePos; // surface-relative - int x = toFixed(p.x()); - int y = toFixed(p.y()); - int nx = toFixed(tp.normalizedPos().x()); - int ny = toFixed(tp.normalizedPos().y()); - int w = toFixed(tp.rect().width()); - int h = toFixed(tp.rect().height()); - int vx = toFixed(tp.velocity().x()); - int vy = toFixed(tp.velocity().y()); - uint32_t pressure = uint32_t(tp.pressure() * 255); - - wl_array *rawData = 0; - QVector<QPointF> rawPosList = tp.rawScreenPositions(); - int rawPosCount = rawPosList.count(); - if (rawPosCount) { - rawPosCount = qMin(maxRawPos, rawPosCount); - rawData = &m_rawdata_array; - rawData->size = rawPosCount * sizeof(float) * 2; - float *p = m_rawdata_ptr; - for (int rpi = 0; rpi < rawPosCount; ++rpi) { - const QPointF &rawPos(rawPosList.at(rpi)); - // This will stay in screen coordinates for performance - // reasons, clients using this data will presumably know - // what they are doing. - *p++ = float(rawPos.x()); - *p++ = float(rawPos.y()); - } - } - - qt_touch_extension_send_touch(target, - time, id, state, - x, y, nx, ny, w, h, - pressure, vx, vy, - flags, rawData); - } - - return true; - } - - return false; -} + if (!m_focusResource) + return; + + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_up(m_focusResource->handle, serial, Compositor::currentTimeMsecs(), touch_id); } -QT_END_NAMESPACE +} // namespace QtWayland diff --git a/src/compositor/wayland_wrapper/qwltouch_p.h b/src/compositor/wayland_wrapper/qwltouch_p.h index 955aa5f8a..6b597e29e 100644 --- a/src/compositor/wayland_wrapper/qwltouch_p.h +++ b/src/compositor/wayland_wrapper/qwltouch_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Compositor. @@ -38,48 +39,43 @@ ** ****************************************************************************/ -#ifndef WLTOUCH_H -#define WLTOUCH_H +#ifndef QTWAYLAND_QWLTOUCH_P_H +#define QTWAYLAND_QWLTOUCH_P_H -#include <private/qwlcompositor_p.h> -#include "wayland-touch-extension-server-protocol.h" -#include "wayland-util.h" +#include <QtCore/QPoint> + +#include <qwayland-server-wayland.h> QT_BEGIN_NAMESPACE +namespace QtWayland { + class Compositor; class Surface; -class QTouchEvent; - -namespace QtWayland { -class TouchExtensionGlobal +class Touch : public QtWaylandServer::wl_touch { public: - TouchExtensionGlobal(Compositor *compositor); - ~TouchExtensionGlobal(); + explicit Touch(Compositor *compositor); - bool postTouchEvent(QTouchEvent *event, Surface *surface); + void setFocus(Surface *surface); - void setFlags(int flags) { m_flags = flags; } + void sendCancel(); + void sendFrame(); -private: - static void bind_func(struct wl_client *client, void *data, - uint32_t version, uint32_t id); - - static void destroy_resource(wl_resource *resource); - - static const struct qt_touch_extension_interface touch_interface; + void sendDown(int touch_id, const QPointF &position); + void sendMotion(int touch_id, const QPointF &position); + void sendUp(int touch_id); +private: Compositor *m_compositor; - int m_flags; - QList<wl_resource *> m_resources; - wl_array m_rawdata_array; - float *m_rawdata_ptr; + + Surface *m_focus; + Resource *m_focusResource; }; -} +} // namespace QtWayland QT_END_NAMESPACE -#endif // WLTOUCH_H +#endif // QTWAYLAND_QWLTOUCH_P_H diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri index c425e2e5b..663638ec0 100644 --- a/src/compositor/wayland_wrapper/wayland_wrapper.pri +++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri @@ -17,8 +17,11 @@ HEADERS += \ wayland_wrapper/qwlextendedoutput_p.h \ wayland_wrapper/qwlextendedsurface_p.h \ wayland_wrapper/qwlinputdevice_p.h \ + wayland_wrapper/qwlkeyboard_p.h \ wayland_wrapper/qwloutput_p.h \ + wayland_wrapper/qwlpointer_p.h \ wayland_wrapper/qwlqtkey_p.h \ + wayland_wrapper/qwlqttouch_p.h \ wayland_wrapper/qwlregion_p.h \ wayland_wrapper/qwlshellsurface_p.h \ wayland_wrapper/qwlsubsurface_p.h \ @@ -36,8 +39,11 @@ SOURCES += \ wayland_wrapper/qwlextendedoutput.cpp \ wayland_wrapper/qwlextendedsurface.cpp \ wayland_wrapper/qwlinputdevice.cpp \ + wayland_wrapper/qwlkeyboard.cpp \ wayland_wrapper/qwloutput.cpp \ + wayland_wrapper/qwlpointer.cpp \ wayland_wrapper/qwlqtkey.cpp \ + wayland_wrapper/qwlqttouch.cpp \ wayland_wrapper/qwlregion.cpp \ wayland_wrapper/qwlshellsurface.cpp \ wayland_wrapper/qwlsubsurface.cpp \ diff --git a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp index e607d636a..f2fa21407 100644 --- a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp +++ b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp @@ -40,13 +40,12 @@ #include "waylandwindowmanagerintegration.h" -#include "wayland_wrapper/qwldisplay_p.h" -#include "wayland_wrapper/qwlcompositor_p.h" +#include <wayland_wrapper/qwldisplay_p.h> +#include <wayland_wrapper/qwlcompositor_p.h> -#include "compositor_api/qwaylandcompositor.h" +#include <compositor_api/qwaylandcompositor.h> -#include "wayland-server.h" -#include "wayland-windowmanager-server-protocol.h" +#include <wayland-server.h> #include <QUrl> @@ -54,6 +53,7 @@ QT_BEGIN_NAMESPACE WindowManagerServerIntegration::WindowManagerServerIntegration(QWaylandCompositor *compositor, QObject *parent) : QObject(parent) + , QtWaylandServer::qt_windowmanager() , m_showIsFullScreen(false) , m_compositor(compositor) { @@ -65,75 +65,47 @@ WindowManagerServerIntegration::~WindowManagerServerIntegration() void WindowManagerServerIntegration::initialize(QtWayland::Display *waylandDisplay) { - wl_display_add_global(waylandDisplay->handle(),&qt_windowmanager_interface,this,WindowManagerServerIntegration::bind_func); + init(waylandDisplay->handle()); } void WindowManagerServerIntegration::setShowIsFullScreen(bool value) { m_showIsFullScreen = value; - struct wl_resource *resource; - wl_list_for_each(resource,&client_resources, link) { - qt_windowmanager_send_hints(resource, int32_t(m_showIsFullScreen)); + Q_FOREACH (Resource *resource, resourceMap().values()) { + send_hints(resource->handle, static_cast<int32_t>(m_showIsFullScreen)); } } void WindowManagerServerIntegration::sendQuitMessage(wl_client *client) { - struct wl_resource *resource; - wl_list_for_each(resource, &client_resources, link) { - if (resource->client == client) { - qt_windowmanager_send_quit(resource); - return; - } - } -} + Resource *resource = resourceMap().value(client); -struct WindowManagerServerIntegrationClientData -{ - QByteArray url; - WindowManagerServerIntegration *integration; -}; + if (resource) + send_quit(resource->handle); +} -void WindowManagerServerIntegration::bind_func(struct wl_client *client, void *data, - uint32_t version, uint32_t id) +void WindowManagerServerIntegration::windowmanager_bind_resource(Resource *resource) { - Q_UNUSED(version); - - WindowManagerServerIntegrationClientData *clientData = new WindowManagerServerIntegrationClientData; - clientData->integration = static_cast<WindowManagerServerIntegration *>(data); - - wl_resource *resource = wl_client_add_object(client,&qt_windowmanager_interface,&windowmanager_interface,id,clientData); - resource->destroy = WindowManagerServerIntegration::destroy_resource; - clientData->integration->registerResource(resource); - qt_windowmanager_send_hints(resource, int32_t(clientData->integration->m_showIsFullScreen)); + send_hints(resource->handle, static_cast<int32_t>(m_showIsFullScreen)); } -void WindowManagerServerIntegration::destroy_resource(wl_resource *resource) +void WindowManagerServerIntegration::windowmanager_destroy_resource(Resource *resource) { - WindowManagerServerIntegrationClientData *data = static_cast<WindowManagerServerIntegrationClientData *>(resource->data); - - delete data; - free(resource); + m_urls.remove(resource); } -void WindowManagerServerIntegration::open_url(struct wl_client *client, - struct wl_resource *window_mgr_resource, - uint32_t remaining, - const char *url) +void WindowManagerServerIntegration::windowmanager_open_url(Resource *resource, uint32_t remaining, const QString &newUrl) { - WindowManagerServerIntegrationClientData *data = static_cast<WindowManagerServerIntegrationClientData *>(window_mgr_resource->data); - WindowManagerServerIntegration *window_mgr = data->integration; + QString url = m_urls.value(resource, QString()); - data->url.append(url); + url.append(newUrl); - if (!remaining) { - window_mgr->m_compositor->openUrl(client, QUrl(QString::fromUtf8(data->url))); - data->url = QByteArray(); + if (remaining) + m_urls.insert(resource, url); + else { + m_urls.remove(resource); + m_compositor->openUrl(resource->client(), QUrl(url)); } } -const struct qt_windowmanager_interface WindowManagerServerIntegration::windowmanager_interface = { - WindowManagerServerIntegration::open_url -}; - QT_END_NAMESPACE diff --git a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h index 10a29a47e..ccf5d4e8d 100644 --- a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h +++ b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h @@ -42,17 +42,10 @@ #define WAYLANDWINDOWMANAGERINTEGRATION_H #include <QtCompositor/qwaylandexport.h> -#include <QtCompositor/qwaylandresourcecollection.h> - -#include <qwindowdefs.h> -#include <stdint.h> +#include "qwayland-server-windowmanager.h" #include <QObject> #include <QMap> -#include <QVariant> - -struct wl_client; -struct wl_object; QT_BEGIN_NAMESPACE @@ -60,15 +53,13 @@ namespace QtWayland { class Display; } -class WindowManagerObject; -class WaylandManagedClient; class QWaylandCompositor; -class Q_COMPOSITOR_EXPORT WindowManagerServerIntegration : public QObject, private QtWayland::ResourceCollection +class Q_COMPOSITOR_EXPORT WindowManagerServerIntegration : public QObject, public QtWaylandServer::qt_windowmanager { Q_OBJECT public: - WindowManagerServerIntegration(QWaylandCompositor *compositor, QObject *parent = 0); + explicit WindowManagerServerIntegration(QWaylandCompositor *compositor, QObject *parent = 0); ~WindowManagerServerIntegration(); void initialize(QtWayland::Display *waylandDisplay); @@ -76,25 +67,15 @@ public: void setShowIsFullScreen(bool value); void sendQuitMessage(wl_client *client); +protected: + void windowmanager_bind_resource(Resource *resource) Q_DECL_OVERRIDE; + void windowmanager_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + void windowmanager_open_url(Resource *resource, uint32_t remaining, const QString &url) Q_DECL_OVERRIDE; + private: bool m_showIsFullScreen; QWaylandCompositor *m_compositor; - - static void bind_func(struct wl_client *client, void *data, - uint32_t version, uint32_t id); - - static void destroy_resource(wl_resource *resource); - static void map_client_to_process(struct wl_client *client, - struct wl_resource *windowMgrResource, - uint32_t processId); - static void authenticate_with_token(struct wl_client *client, - struct wl_resource *windowMgrResource, - const char *wl_authentication_token); - static void open_url(struct wl_client *client, - struct wl_resource *window_mgr_resource, - uint32_t remaining, - const char *url); - static const struct qt_windowmanager_interface windowmanager_interface; + QMap<Resource*, QString> m_urls; }; QT_END_NAMESPACE |