diff --git a/src/client/client.pro b/src/client/client.pro index 08c184a5e594eb1c020af2ee3ed46a36abf90628..29016c9c8ec96c94c9a17a7c998be6c690a8a104 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -8,6 +8,8 @@ MODULE_PLUGIN_TYPES = \ wayland-inputdevice-integration \ wayland-decoration-client +CONFIG += generated_privates + load(qt_module) # We have a bunch of C code with casts, so we can't have this option diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 6bad56ae3f00bd69593b700763f8c5ef9258b990..bda85c49c25bd5c695f8461c89a4b11cf2cfbb74 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -237,6 +237,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin mScreens.append(screen); // We need to get the output events before creating surfaces forceRoundTrip(); + screen->init(); mWaylandIntegration->screenAdded(screen); } else if (interface == QStringLiteral("wl_compositor")) { mCompositorVersion = qMin((int)version, 3); @@ -369,6 +370,11 @@ bool QWaylandDisplay::supportsWindowDecoration() const return integrationSupport; } +QWaylandWindow *QWaylandDisplay::lastInputWindow() const +{ + return mLastInputWindow.data(); +} + void QWaylandDisplay::setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *win) { mLastInputDevice = device; diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index bbd0e871ddaa0da01b84ea1432aa374b389cacd0..9a7ad39ce82db9963d2a0b477c78b2b056a00a13 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -36,6 +36,7 @@ #include <QtCore/QObject> #include <QtCore/QRect> +#include <QtCore/QPointer> #include <QtCore/QWaitCondition> @@ -156,7 +157,7 @@ public: uint32_t lastInputSerial() const { return mLastInputSerial; } QWaylandInputDevice *lastInputDevice() const { return mLastInputDevice; } - QWaylandWindow *lastInputWindow() const { return mLastInputWindow; } + QWaylandWindow *lastInputWindow() const; void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window); public slots: @@ -200,7 +201,7 @@ private: int mCompositorVersion; uint32_t mLastInputSerial; QWaylandInputDevice *mLastInputDevice; - QWaylandWindow *mLastInputWindow; + QPointer<QWaylandWindow> mLastInputWindow; void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE; void registry_global_remove(uint32_t id) Q_DECL_OVERRIDE; diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 3b5e83481fbe0f2ab4e93277c431cd07e2a7812a..76ae258696bd57f96c4c40e163cfb1ba2fa908bb 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -118,6 +118,10 @@ QWaylandInputDevice::Keyboard::~Keyboard() #ifndef QT_NO_WAYLAND_XKB releaseKeyMap(); #endif + if (mFocus) + QWindowSystemInterface::handleWindowActivated(0); + if (mFocusCallback) + wl_callback_destroy(mFocusCallback); if (mParent->mVersion >= 3) wl_keyboard_release(object()); else @@ -295,17 +299,18 @@ Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const Qt::KeyboardModifiers ret = Qt::NoModifier; #ifndef QT_NO_WAYLAND_XKB + if (!mXkbState) + return ret; + xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED); - if (xkb_state_mod_name_is_active(mXkbState, "Shift", cstate)) + if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_SHIFT, cstate)) ret |= Qt::ShiftModifier; - if (xkb_state_mod_name_is_active(mXkbState, "Control", cstate)) + if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_CTRL, cstate)) ret |= Qt::ControlModifier; - if (xkb_state_mod_name_is_active(mXkbState, "Alt", cstate)) - ret |= Qt::AltModifier; - if (xkb_state_mod_name_is_active(mXkbState, "Mod1", cstate)) + if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_ALT, cstate)) ret |= Qt::AltModifier; - if (xkb_state_mod_name_is_active(mXkbState, "Mod4", cstate)) + if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_LOGO, cstate)) ret |= Qt::MetaModifier; #endif @@ -592,13 +597,30 @@ static const uint32_t KeyTbl[] = { XKB_KEY_Mode_switch, Qt::Key_Mode_switch, XKB_KEY_script_switch, Qt::Key_Mode_switch, + XKB_KEY_XF86Back, Qt::Key_Back, + XKB_KEY_XF86Forward, Qt::Key_Forward, + XKB_KEY_XF86AudioPlay, Qt::Key_MediaTogglePlayPause, //there isn't a PlayPause keysym, however just play keys are not common XKB_KEY_XF86AudioPause, Qt::Key_MediaPause, XKB_KEY_XF86AudioStop, Qt::Key_MediaStop, XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious, XKB_KEY_XF86AudioNext, Qt::Key_MediaNext, + XKB_KEY_XF86AudioRewind, Qt::Key_MediaPrevious, + XKB_KEY_XF86AudioForward, Qt::Key_MediaNext, XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord, + XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute, + XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown, + XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp, + + XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay, + XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat, + + XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn, + XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut, + + XKB_KEY_XF86Eject, Qt::Key_Eject, + 0, 0 }; @@ -759,7 +781,6 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, } const xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code); - xkb_state_update_key(mXkbState, code, isDown ? XKB_KEY_DOWN : XKB_KEY_UP); Qt::KeyboardModifiers modifiers = mParent->modifiers(); diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index 050feba736b03e40396a590dfcc91515b6da6727..9526aec4c4e3b90ff9fc4bc34be783256931c276 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -226,6 +226,13 @@ QVariant QWaylandIntegration::styleHint(StyleHint hint) const if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration()) return mDisplay->windowManagerIntegration()->showIsFullScreen(); + switch (hint) { + case QPlatformIntegration::FontSmoothingGamma: + return qreal(1.0); + default: + break; + } + return QPlatformIntegration::styleHint(hint); } diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp index 057515af02b2c2487df1ae177b1a7e33a3816f25..dc634f88bc97666aedac1089ac44f95b77faf688 100644 --- a/src/client/qwaylandscreen.cpp +++ b/src/client/qwaylandscreen.cpp @@ -58,7 +58,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin , mFormat(QImage::Format_ARGB32_Premultiplied) , mOutputName(QStringLiteral("Screen%1").arg(id)) , m_orientation(Qt::PrimaryOrientation) - , mWaylandCursor(new QWaylandCursor(this)) + , mWaylandCursor(0) { } @@ -67,6 +67,11 @@ QWaylandScreen::~QWaylandScreen() delete mWaylandCursor; } +void QWaylandScreen::init() +{ + mWaylandCursor = new QWaylandCursor(this); +} + QWaylandDisplay * QWaylandScreen::display() const { return mWaylandDisplay; diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h index e2acac4b3a3d8a13f6a9b68f3fbfd01c0f551757..3d38e30a8da29b75352976704b70a6d2689f2fae 100644 --- a/src/client/qwaylandscreen_p.h +++ b/src/client/qwaylandscreen_p.h @@ -52,6 +52,7 @@ public: QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id); ~QWaylandScreen(); + void init(); QWaylandDisplay *display() const; QRect geometry() const; diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 0d5d84eb96f31ace0ef98b01034ac645362bd7d1..28e8f9d4a9ebcee2ae0b3df1066b6bc622f62352 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -40,6 +41,7 @@ #include "qwaylandcompositor.h" +#include "qwaylandclient.h" #include "qwaylandinput.h" #include "qwaylandoutput.h" #include "qwaylandglobalinterface.h" @@ -175,13 +177,20 @@ void QWaylandCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface) QWaylandSurfaceView *QWaylandCompositor::pickView(const QPointF &globalPosition) const { - Q_FOREACH (QtWayland::Surface *surface, m_compositor->surfaces()) { - foreach (QWaylandSurfaceView *view, surface->waylandSurface()->views()) - if (QRectF(view->pos(), surface->size()).contains(globalPosition)) - return view; + Q_FOREACH (QWaylandOutput *output, outputs()) { + // Skip coordinates not in output + if (!QRectF(output->geometry()).contains(globalPosition)) + continue; + + Q_FOREACH (QWaylandSurface *surface, output->surfaces()) { + Q_FOREACH (QWaylandSurfaceView *view, surface->views()) { + if (QRectF(view->pos(), surface->size()).contains(globalPosition)) + return view; + } + } } - return 0; + return Q_NULLPTR; } QPointF QWaylandCompositor::mapToView(QWaylandSurfaceView *surface, const QPointF &globalPosition) const diff --git a/src/compositor/compositor_api/qwaylandinput.h b/src/compositor/compositor_api/qwaylandinput.h index ba28bbd67b9fbd72bb853d3b363a8ff472a89467..7842fa38b19b404bd4f8609d5e68241f1d95cde2 100644 --- a/src/compositor/compositor_api/qwaylandinput.h +++ b/src/compositor/compositor_api/qwaylandinput.h @@ -63,8 +63,8 @@ class InputDevice; class Q_COMPOSITOR_EXPORT QWaylandKeymap { public: - QWaylandKeymap(const QString &layout = QLatin1String("us"), const QString &variant = QString(), const QString &options = QString(), - const QString &model = QLatin1String("pc105"), const QString &rules = QLatin1String("evdev")); + QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), + const QString &model = QString(), const QString &rules = QString()); inline QString layout() const { return m_layout; } inline QString variant() const { return m_variant; } diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp index 8f6c5e2cc29f98e1cd4faee8eb82c9be2bb7f6a3..ba9f39887dda0bb5f98dcd60fbf801e51e515a35 100644 --- a/src/compositor/compositor_api/qwaylandoutput.cpp +++ b/src/compositor/compositor_api/qwaylandoutput.cpp @@ -49,6 +49,7 @@ #include "wayland_wrapper/qwloutput_p.h" #include "qwaylandcompositor.h" #include "qwaylandoutput.h" +#include "qwaylandsurface.h" QWaylandOutput::QWaylandOutput(QWaylandCompositor *compositor, QWindow *window, const QString &manufacturer, const QString &model) @@ -244,3 +245,13 @@ QtWayland::Output *QWaylandOutput::handle() { return d_ptr; } + +QList<QWaylandSurface *> QWaylandOutput::surfaces() const +{ + QList<QWaylandSurface *> list; + Q_FOREACH (QWaylandSurface *surface, d_ptr->compositor()->waylandCompositor()->surfaces()) { + if (surface->outputs().contains(const_cast<QWaylandOutput *>(this))) + list.append(surface); + } + return list; +} diff --git a/src/compositor/compositor_api/qwaylandoutput.h b/src/compositor/compositor_api/qwaylandoutput.h index 9efbd95981d49eb7ef6fbd757a60c32e8ae3813e..9c9dc3767d1ec00fb2169f14beb90c6696912f70 100644 --- a/src/compositor/compositor_api/qwaylandoutput.h +++ b/src/compositor/compositor_api/qwaylandoutput.h @@ -54,6 +54,8 @@ struct wl_resource; class QWaylandCompositor; class QWindow; +class QWaylandSurface; +class QWaylandClient; namespace QtWayland { class Output; @@ -143,6 +145,8 @@ public: QtWayland::Output *handle(); + QList<QWaylandSurface *> surfaces() const; + Q_SIGNALS: void positionChanged(); void geometryChanged(); diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp index 36ee8e760aae203568096d4dd197eaf275f7f88e..3a3c0ecea4cda5c1ef49149165f18099cf417a2e 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** @@ -32,6 +33,7 @@ ****************************************************************************/ #include <QtCompositor/private/qwlcompositor_p.h> +#include <QtCompositor/private/qwlsurface_p.h> #include "qwaylandclient.h" #include "qwaylandquickcompositor.h" @@ -46,26 +48,17 @@ class QWaylandQuickCompositorPrivate : public QtWayland::Compositor public: QWaylandQuickCompositorPrivate(QWaylandQuickCompositor *compositor, QWaylandCompositor::ExtensionFlags extensions) : QtWayland::Compositor(compositor, extensions) - , updateScheduled(false) { } void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE { QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, wl_resource_get_version(resource->handle), static_cast<QWaylandQuickCompositor *>(m_qt_compositor)); + surface->handle()->addToOutput(primaryOutput()->handle()); m_surfaces << surface->handle(); //BUG: This may not be an on-screen window surface though m_qt_compositor->surfaceCreated(surface); } - - void updateStarted() - { - updateScheduled = false; - m_qt_compositor->frameStarted(); - m_qt_compositor->cleanupGraphicsResources(); - } - - bool updateScheduled; }; diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index 91237b879d88de58cfa8fe806cbf99637e23f8a5..44e0edf5deade04fcc673300ebac203bdcf1b8c3 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -77,7 +77,8 @@ public: bufferRef.destroyTexture(); bufferRef = nextBuffer; - QQuickWindow *window = static_cast<QQuickWindow *>(surface->output()->window()); + QQuickWindow *window = static_cast<QQuickWindow *>(surface->mainOutput()->window()); + // If the next buffer is NULL do not delete the current texture. If the client called // attach(0) the surface is going to be unmapped anyway, if instead the client attached // a valid buffer but died before we got here we want to keep the old buffer around @@ -142,7 +143,8 @@ public: } QWaylandSurfacePrivate::surface_commit(resource); - output()->waylandOutput()->update(); + Q_FOREACH (QtWayland::Output *output, outputs()) + output->waylandOutput()->update(); } BufferAttacher *buffer; @@ -159,12 +161,8 @@ QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, int ve d->buffer->surface = this; setBufferAttacher(d->buffer); - QQuickWindow *window = static_cast<QQuickWindow *>(output()->window()); - connect(window, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickSurface::updateTexture, Qt::DirectConnection); - connect(window, &QQuickWindow::sceneGraphInvalidated, this, &QWaylandQuickSurface::invalidateTexture, Qt::DirectConnection); connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert); connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty); - } QWaylandQuickSurface::~QWaylandQuickSurface() @@ -200,6 +198,40 @@ QObject *QWaylandQuickSurface::windowPropertyMap() const return d->windowPropertyMap; } +bool QWaylandQuickSurface::event(QEvent *e) +{ + if (e->type() == static_cast<QEvent::Type>(QWaylandSurfaceLeaveEvent::WaylandSurfaceLeave)) { + QWaylandSurfaceLeaveEvent *event = static_cast<QWaylandSurfaceLeaveEvent *>(e); + + if (event->output()) { + QQuickWindow *oldWindow = static_cast<QQuickWindow *>(event->output()->window()); + disconnect(oldWindow, &QQuickWindow::beforeSynchronizing, + this, &QWaylandQuickSurface::updateTexture); + disconnect(oldWindow, &QQuickWindow::sceneGraphInvalidated, + this, &QWaylandQuickSurface::invalidateTexture); + } + + return true; + } + + if (e->type() == static_cast<QEvent::Type>(QWaylandSurfaceEnterEvent::WaylandSurfaceEnter)) { + QWaylandSurfaceEnterEvent *event = static_cast<QWaylandSurfaceEnterEvent *>(e); + + if (event->output()) { + QQuickWindow *window = static_cast<QQuickWindow *>(event->output()->window()); + connect(window, &QQuickWindow::beforeSynchronizing, + this, &QWaylandQuickSurface::updateTexture, + Qt::DirectConnection); + connect(window, &QQuickWindow::sceneGraphInvalidated, + this, &QWaylandQuickSurface::invalidateTexture, + Qt::DirectConnection); + } + + return true; + } + + return QObject::event(e); +} void QWaylandQuickSurface::updateTexture() { diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h index 1c7eea6c96eee4fbd79d97e05defa558608f24a2..4c37e6670d44036a53aa602635a4d969943e7791 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.h +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -67,6 +67,9 @@ public: QObject *windowPropertyMap() const; +private: + bool event(QEvent *event) Q_DECL_OVERRIDE; + Q_SIGNALS: void useTextureAlphaChanged(); void clientRenderingEnabledChanged(); diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index cbfe92055ac3d2afbe9b61a8c52c22fda2cd34f3..e5ecb15b4df74333675a3ea11a480334ef0e039d 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -63,6 +63,9 @@ QT_BEGIN_NAMESPACE +const QEvent::Type QWaylandSurfaceEnterEvent::WaylandSurfaceEnter = (QEvent::Type)QEvent::registerEventType(); +const QEvent::Type QWaylandSurfaceLeaveEvent::WaylandSurfaceLeave = (QEvent::Type)QEvent::registerEventType(); + QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface) : QtWayland::Surface(wlClient, id, version, compositor, surface) , closing(false) @@ -72,6 +75,63 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, {} +class QWaylandSurfaceEnterEventPrivate +{ +public: + QWaylandSurfaceEnterEventPrivate(QWaylandOutput *_output) + : output(_output) + { + } + + QWaylandOutput *output; +}; + + +QWaylandSurfaceEnterEvent::QWaylandSurfaceEnterEvent(QWaylandOutput *output) + : QEvent(WaylandSurfaceEnter) + , d(new QWaylandSurfaceEnterEventPrivate(output)) +{ +} + +QWaylandSurfaceEnterEvent::~QWaylandSurfaceEnterEvent() +{ + delete d; +} + +QWaylandOutput *QWaylandSurfaceEnterEvent::output() const +{ + return d->output; +} + + +class QWaylandSurfaceLeaveEventPrivate +{ +public: + QWaylandSurfaceLeaveEventPrivate(QWaylandOutput *_output) + : output(_output) + { + } + + QWaylandOutput *output; +}; + + +QWaylandSurfaceLeaveEvent::QWaylandSurfaceLeaveEvent(QWaylandOutput *output) + : QEvent(WaylandSurfaceLeave) + , d(new QWaylandSurfaceLeaveEventPrivate(output)) +{ +} + +QWaylandSurfaceLeaveEvent::~QWaylandSurfaceLeaveEvent() +{ + delete d; +} + +QWaylandOutput *QWaylandSurfaceLeaveEvent::output() const +{ + return d->output; +} + QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor) : QObject(*new QWaylandSurfacePrivate(client, id, version, compositor, this)) @@ -239,12 +299,32 @@ QWaylandCompositor *QWaylandSurface::compositor() const return d->compositor()->waylandCompositor(); } -QWaylandOutput *QWaylandSurface::output() const +QWaylandOutput *QWaylandSurface::mainOutput() const { Q_D(const QWaylandSurface); - if (!d->output()) - return Q_NULLPTR; - return d->output()->waylandOutput(); + + // Returns the output that contains the most if not all + // the surface (window managers will take care of setting + // this, defaults to the first output) + return d->mainOutput()->waylandOutput(); +} + +void QWaylandSurface::setMainOutput(QWaylandOutput *mainOutput) +{ + Q_D(QWaylandSurface); + + if (mainOutput) + d->setMainOutput(mainOutput->handle()); +} + +QList<QWaylandOutput *> QWaylandSurface::outputs() const +{ + Q_D(const QWaylandSurface); + + QList<QWaylandOutput *> list; + Q_FOREACH (QtWayland::Output *output, d->outputs()) + list.append(output->waylandOutput()); + return list; } QWindow::Visibility QWaylandSurface::visibility() const diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index e16bdb40a9e37098c69ddabf9a6bbab9bd5dbc70..653d74c1b2ff346a9df33269cd7e84f1ab48fd51 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -81,6 +81,38 @@ protected: friend class QtWayland::Surface; }; +class QWaylandSurfaceEnterEventPrivate; + +class Q_COMPOSITOR_EXPORT QWaylandSurfaceEnterEvent : public QEvent +{ +public: + QWaylandSurfaceEnterEvent(QWaylandOutput *output); + ~QWaylandSurfaceEnterEvent(); + + QWaylandOutput *output() const; + + static const QEvent::Type WaylandSurfaceEnter; + +private: + QWaylandSurfaceEnterEventPrivate *d; +}; + +class QWaylandSurfaceLeaveEventPrivate; + +class Q_COMPOSITOR_EXPORT QWaylandSurfaceLeaveEvent : public QEvent +{ +public: + QWaylandSurfaceLeaveEvent(QWaylandOutput *output); + ~QWaylandSurfaceLeaveEvent(); + + QWaylandOutput *output() const; + + static const QEvent::Type WaylandSurfaceLeave; + +private: + QWaylandSurfaceLeaveEventPrivate *d; +}; + class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject { Q_OBJECT @@ -163,7 +195,10 @@ public: QWaylandCompositor *compositor() const; - QWaylandOutput *output() const; + QWaylandOutput *mainOutput() const; + void setMainOutput(QWaylandOutput *mainOutput); + + QList<QWaylandOutput *> outputs() const; QString className() const; @@ -192,7 +227,7 @@ public: static QWaylandSurface *fromResource(::wl_resource *resource); -public slots: +public Q_SLOTS: void updateSelection(); protected: @@ -223,6 +258,7 @@ Q_SIGNALS: friend class QWaylandSurfaceView; friend class QWaylandSurfaceInterface; + friend class QtWayland::Surface; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index c3951909f1168b9c2b45669f700f3bcba3f5a639..90a68c4f99c4028d14213ea7e0251e4b553b670d 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -372,7 +372,7 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD { bool mapped = surface() && surface()->isMapped(); - if (!mapped || !m_provider->t || !m_paintEnabled) { + if (!mapped || !m_provider || !m_provider->t || !m_paintEnabled) { delete oldNode; return 0; } diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h index 7af8c88217ff00e3346b6ec1656186c9b43f6ea2..91dc6879b620902aa59746664c4e0881c2aaa5f9 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h @@ -102,11 +102,11 @@ protected: void touchEvent(QTouchEvent *event); void mouseUngrabEvent() Q_DECL_OVERRIDE; -public slots: +public Q_SLOTS: virtual void takeFocus(QWaylandInputDevice *device = 0); void setPaintEnabled(bool paintEnabled); -private slots: +private Q_SLOTS: void surfaceMapped(); void surfaceUnmapped(); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index fa7e90f00134d97251161f4a620e92f87129b4f7..7941db824688b55981023c1c667203584fb5b58e 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -297,6 +297,7 @@ void Compositor::compositor_create_surface(Resource *resource, uint32_t id) { QWaylandSurface *surface = new QWaylandSurface(resource->client(), id, resource->version(), m_qt_compositor); m_surfaces << surface->handle(); + surface->handle()->addToOutput(primaryOutput()->handle()); //BUG: This may not be an on-screen window surface though m_qt_compositor->surfaceCreated(surface); } @@ -400,18 +401,6 @@ InputDevice* Compositor::defaultInputDevice() return m_inputDevices.last()->handle(); } -QList<QtWayland::Surface *> Compositor::surfacesForClient(wl_client *client) -{ - QList<QtWayland::Surface *> ret; - - for (int i=0; i < m_surfaces.count(); ++i) { - if (m_surfaces.at(i)->resource()->client() == client) { - ret.append(m_surfaces.at(i)); - } - } - return ret; -} - void Compositor::configureTouchExtension(int flags) { if (m_touchExtension) diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h index 4deccde23dc5216b4d22f00fd8e6ebdbf08480f7..04a9e317c6056da817165b7536364cc52e1d6458 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor_p.h +++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -94,7 +94,6 @@ public: void init(); void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces); - void frameFinished(Surface *surface = 0); InputDevice *defaultInputDevice(); @@ -125,8 +124,8 @@ public: void initializeDefaultInputDevice(); void initializeWindowManagerProtocol(); - QList<Surface*> surfaces() const { return m_surfaces; } - QList<Surface*> surfacesForClient(wl_client* client); + QList<Surface *> surfaces() const { return m_surfaces; } + QWaylandCompositor *waylandCompositor() const { return m_qt_compositor; } struct wl_display *wl_display() const { return m_display->handle(); } diff --git a/src/compositor/wayland_wrapper/qwloutput.cpp b/src/compositor/wayland_wrapper/qwloutput.cpp index 22eaaa8248260815273027c9e81cd6801f35a826..0cbe166e2a3211d70a1670c44dbde0dcf11270d5 100644 --- a/src/compositor/wayland_wrapper/qwloutput.cpp +++ b/src/compositor/wayland_wrapper/qwloutput.cpp @@ -46,6 +46,8 @@ #include <QtGui/QWindow> #include <QRect> +#include <QtCompositor/QWaylandSurface> +#include <QtCompositor/QWaylandOutput> QT_BEGIN_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwloutput_p.h b/src/compositor/wayland_wrapper/qwloutput_p.h index 3f6658f5e07c662d4c6eed8f673c59291124eb90..b85081e80431bdb0594628f5ef0718c3b17c2739 100644 --- a/src/compositor/wayland_wrapper/qwloutput_p.h +++ b/src/compositor/wayland_wrapper/qwloutput_p.h @@ -126,6 +126,7 @@ private: QWaylandOutput::Subpixel m_subpixel; QWaylandOutput::Transform m_transform; int m_scaleFactor; + QList<QWaylandSurface *> m_surfaces; void sendGeometryInfo(); }; diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index 2c30872a4855e7f461c8f8d9acac80b3ffa402db..a20e911421ce852bbbd07e47ddc6d00899824ec0 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -114,7 +114,7 @@ Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCom : QtWaylandServer::wl_surface(client, id, version) , m_compositor(compositor->handle()) , m_waylandSurface(surface) - , m_output(m_compositor->primaryOutput()->handle()) + , m_mainOutput(0) , m_buffer(0) , m_surfaceMapped(false) , m_attacher(0) @@ -291,9 +291,66 @@ Compositor *Surface::compositor() const return m_compositor; } -Output *Surface::output() const +Output *Surface::mainOutput() const { - return m_output; + if (!m_mainOutput) + return m_compositor->primaryOutput()->handle(); + return m_mainOutput; +} + +void Surface::setMainOutput(Output *output) +{ + m_mainOutput = output; +} + +QList<Output *> Surface::outputs() const +{ + return m_outputs; +} + +void Surface::addToOutput(Output *output) +{ + if (!output) + return; + + if (!m_mainOutput) + m_mainOutput = output; + + if (m_outputs.contains(output)) + return; + + m_outputs.append(output); + + QWaylandSurfaceEnterEvent event(output->waylandOutput()); + QCoreApplication::sendEvent(waylandSurface(), &event); + + // Send surface enter event + Q_FOREACH (Resource *resource, resourceMap().values()) { + QList<Output::Resource *> outputs = output->resourceMap().values(); + for (int i = 0; i < outputs.size(); i++) + send_enter(resource->handle, outputs.at(i)->handle); + } +} + +void Surface::removeFromOutput(Output *output) +{ + if (!output) + return; + + m_outputs.removeOne(output); + + if (m_outputs.size() == 0) + m_mainOutput = m_compositor->primaryOutput()->handle(); + + QWaylandSurfaceLeaveEvent event(output->waylandOutput()); + QCoreApplication::sendEvent(waylandSurface(), &event); + + // Send surface leave event + Q_FOREACH (Resource *resource, resourceMap().values()) { + QList<Output::Resource *> outputs = output->resourceMap().values(); + for (int i = 0; i < outputs.size(); i++) + send_leave(resource->handle, outputs.at(i)->handle); + } } /*! diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index 422c147e71ac33fdfb8b4740e890c663336fe7ee..a41d788804fdd75a251157b586bd4ceb032982c3 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -121,7 +121,13 @@ public: Compositor *compositor() const; - Output *output() const; + Output *mainOutput() const; + void setMainOutput(Output *output); + + QList<Output *> outputs() const; + + void addToOutput(Output *output); + void removeFromOutput(Output *output); QString className() const { return m_className; } void setClassName(const QString &className); @@ -171,7 +177,8 @@ protected: Compositor *m_compositor; QWaylandSurface *m_waylandSurface; - Output *m_output; + Output *m_mainOutput; + QList<Output *> m_outputs; QRegion m_damage; SurfaceBuffer *m_buffer; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp index ccacf5739182460ed1b66ed988684b1b09491abd..8f3ce09364faab6c0e615297c42a9ad500ae89ff 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp @@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { static const char *qwaylandegl_threadedgl_blacklist_vendor[] = { - "Mesa Project", 0 }; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index a062a2f98970b7e8875922f2f99e23a28d157c77..18ed1d61e6d30dde15b55b2dc4c4985444c91fe7 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -260,21 +260,22 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis switch (m_format.renderableType()) { case QSurfaceFormat::OpenVG: - eglBindAPI(EGL_OPENVG_API); + m_api = EGL_OPENVG_API; break; #ifdef EGL_VERSION_1_4 # if !defined(QT_OPENGL_ES_2) case QSurfaceFormat::DefaultRenderableType: # endif case QSurfaceFormat::OpenGL: - eglBindAPI(EGL_OPENGL_API); + m_api = EGL_OPENGL_API; break; #endif case QSurfaceFormat::OpenGLES: default: - eglBindAPI(EGL_OPENGL_ES_API); + m_api = EGL_OPENGL_ES_API; break; } + eglBindAPI(m_api); m_context = eglCreateContext(m_eglDisplay, m_config, m_shareEGLContext, eglContextAttrs.constData()); @@ -358,6 +359,15 @@ QWaylandGLContext::~QWaylandGLContext() bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) { + // in QWaylandGLContext() we called eglBindAPI with the correct value. However, + // eglBindAPI's documentation says: + // "eglBindAPI defines the current rendering API for EGL in the thread it is called from" + // Since makeCurrent() can be called from a different thread than the one we created the + // context in make sure to call eglBindAPI in the correct thread. + if (eglQueryAPI() != m_api) { + eglBindAPI(m_api); + } + QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface); EGLSurface eglSurface = window->eglSurface(); diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h index 1c2db8aaf3a11e5f895886adbaf62690ba605105..bc92c9501f2f0d0ff94c81e983ee62b8b4644ce4 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h @@ -85,6 +85,7 @@ private: QSurfaceFormat m_format; DecorationsBlitter *m_blitter; bool mUseNativeDefaultFbo; + uint m_api; friend class DecorationsBlitter; }; diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp index a0b4afcfaf2c7fb118e3f1bc90a833530372615a..784687d26493928070db9ec7d531af0dead71513 100644 --- a/src/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/qtwaylandscanner/qtwaylandscanner.cpp @@ -88,6 +88,7 @@ struct WaylandArgument { struct WaylandEvent { bool request; QByteArray name; + QByteArray type; QList<WaylandArgument> arguments; }; @@ -124,6 +125,7 @@ WaylandEvent readEvent(QXmlStreamReader &xml, bool request) WaylandEvent event; event.request = request; event.name = byteArrayValue(xml, "name"); + event.type = byteArrayValue(xml, "type"); while (xml.readNextStartElement()) { if (xml.name() == "arg") { WaylandArgument argument; @@ -998,6 +1000,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr } } printf(");\n"); + if (e.type == "destructor") + printf(" m_%s = 0;\n", interfaceName); printf(" }\n"); }