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");
             }