diff options
Diffstat (limited to 'src/compositor')
22 files changed, 272 insertions, 234 deletions
diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h index 213474fab..103a1b388 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.h +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -65,7 +65,8 @@ public: #ifdef QT_COMPOSITOR_WAYLAND_GL /** * There must be a GL context bound when calling this function. - * It is responsibility of the caller to call destroyTexture() later. + * The texture will be automatically destroyed when the last QWaylandBufferRef + * referring to the same underlying buffer will be destroyed or reset. */ GLuint createTexture(); void destroyTexture(); diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 28e8f9d4a..04d1c4aed 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -140,6 +140,7 @@ QList<QWaylandSurface *> QWaylandCompositor::surfaces() const { QList<QtWayland::Surface *> surfaces = m_compositor->surfaces(); QList<QWaylandSurface *> surfs; + surfs.reserve(surfaces.count()); foreach (QtWayland::Surface *s, surfaces) surfs << s->waylandSurface(); return surfs; diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index fe48db06d..1817fa07d 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -75,15 +75,14 @@ class Q_COMPOSITOR_EXPORT QWaylandCompositor public: enum ExtensionFlag { WindowManagerExtension = 0x01, - OutputExtension = 0x02, - SurfaceExtension = 0x04, - QtKeyExtension = 0x08, - TouchExtension = 0x10, - SubSurfaceExtension = 0x20, - TextInputExtension = 0x40, - HardwareIntegrationExtension = 0x80, - - DefaultExtensions = WindowManagerExtension | OutputExtension | SurfaceExtension | QtKeyExtension | TouchExtension | HardwareIntegrationExtension + SurfaceExtension = 0x02, + QtKeyExtension = 0x04, + TouchExtension = 0x08, + SubSurfaceExtension = 0x10, + TextInputExtension = 0x20, + HardwareIntegrationExtension = 0x40, + + DefaultExtensions = WindowManagerExtension | SurfaceExtension | QtKeyExtension | TouchExtension | HardwareIntegrationExtension }; Q_DECLARE_FLAGS(ExtensionFlags, ExtensionFlag) diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index ef78c8849..c8edcb6bc 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -73,19 +73,12 @@ public: void createTexture() { - if (bufferRef) - bufferRef.destroyTexture(); bufferRef = nextBuffer; + delete texture; + texture = 0; 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 - // in case some destroy animation is run. - if (bufferRef) { - delete texture; - + if (nextBuffer) { if (bufferRef.isShm()) { texture = window->createTextureFromImage(bufferRef.image()); } else { @@ -101,6 +94,12 @@ public: update = false; } + void unmap() Q_DECL_OVERRIDE + { + nextBuffer = QWaylandBufferRef(); + update = true; + } + void invalidateTexture() { if (bufferRef) @@ -141,9 +140,6 @@ public: void surface_commit(Resource *resource) Q_DECL_OVERRIDE { - if (m_pending.newlyAttached) { - buffer->update = true; - } QWaylandSurfacePrivate::surface_commit(resource); Q_FOREACH (QtWayland::Output *output, outputs()) diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index e5ecb15b4..a8dc41fd5 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -71,7 +71,7 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, , closing(false) , refCount(1) , client(QWaylandClient::fromWlClient(wlClient)) - , windowType(QWaylandSurface::WindowType::None) + , windowType(QWaylandSurface::None) {} @@ -322,7 +322,9 @@ QList<QWaylandOutput *> QWaylandSurface::outputs() const Q_D(const QWaylandSurface); QList<QWaylandOutput *> list; - Q_FOREACH (QtWayland::Output *output, d->outputs()) + const QList<QtWayland::Output *> outputs = d->outputs(); + list.reserve(outputs.count()); + Q_FOREACH (QtWayland::Output *output, outputs) list.append(output->waylandOutput()); return list; } @@ -509,4 +511,30 @@ void QWaylandSurfacePrivate::setType(QWaylandSurface::WindowType type) } } +class QWaylandUnmapLockPrivate +{ +public: + QWaylandSurface *surface; +}; + +/*! + Constructs a QWaylandUnmapLock object. + + The lock will act on the \a surface parameter, and will prevent the surface to + be unmapped, retaining the last valid buffer when the client attachs a NULL buffer. + The lock will be automatically released when deleted. +*/ +QWaylandUnmapLock::QWaylandUnmapLock(QWaylandSurface *surface) + : d(new QWaylandUnmapLockPrivate) +{ + d->surface = surface; + surface->handle()->addUnmapLock(this); +} + +QWaylandUnmapLock::~QWaylandUnmapLock() +{ + d->surface->handle()->removeUnmapLock(this); + delete d; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index 653d74c1b..db1e1fb44 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -77,6 +77,7 @@ public: protected: virtual void attach(const QWaylandBufferRef &ref) = 0; + virtual void unmap() = 0; friend class QtWayland::Surface; }; @@ -261,6 +262,17 @@ Q_SIGNALS: friend class QtWayland::Surface; }; +class QWaylandUnmapLockPrivate; +class Q_COMPOSITOR_EXPORT QWaylandUnmapLock +{ +public: + QWaylandUnmapLock(QWaylandSurface *surface); + ~QWaylandUnmapLock(); + +private: + QWaylandUnmapLockPrivate *const d; +}; + QT_END_NAMESPACE #endif // QWAYLANDSURFACE_H diff --git a/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp b/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp index 355777377..cddd231dd 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp @@ -110,7 +110,7 @@ int QWaylandSurfaceOp::type() const QWaylandSurfaceSetVisibilityOp::QWaylandSurfaceSetVisibilityOp(QWindow::Visibility visibility) - : QWaylandSurfaceOp(Type::SetVisibility) + : QWaylandSurfaceOp(QWaylandSurfaceOp::SetVisibility) , m_visibility(visibility) { } @@ -121,7 +121,7 @@ QWindow::Visibility QWaylandSurfaceSetVisibilityOp::visibility() const } QWaylandSurfaceResizeOp::QWaylandSurfaceResizeOp(const QSize &size) - : QWaylandSurfaceOp(Type::Resize) + : QWaylandSurfaceOp(QWaylandSurfaceOp::Resize) , m_size(size) { } @@ -132,7 +132,7 @@ QSize QWaylandSurfaceResizeOp::size() const } QWaylandSurfacePingOp::QWaylandSurfacePingOp(uint32_t serial) - : QWaylandSurfaceOp(Type::Ping) + : QWaylandSurfaceOp(QWaylandSurfaceOp::Ping) , m_serial(serial) { } diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index 93cfaf008..0c48df382 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -364,9 +364,7 @@ void QWaylandSurfaceItem::updateTexture(bool changed) if (!m_provider) m_provider = new QWaylandSurfaceTextureProvider(); - bool mapped = surface() && surface()->isMapped(); - if (mapped) - m_provider->t = static_cast<QWaylandQuickSurface *>(surface())->texture(); + m_provider->t = static_cast<QWaylandQuickSurface *>(surface())->texture(); m_provider->smooth = smooth(); if (m_newTexture || changed) emit m_provider->textureChanged(); diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index f057542ca..f8c8bdc1f 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -49,7 +49,6 @@ #include "qwaylandcompositor.h" #include "qwldatadevicemanager_p.h" #include "qwldatadevice_p.h" -#include "qwlextendedoutput_p.h" #include "qwlextendedsurface_p.h" #include "qwlsubsurface_p.h" #include "qwlshellsurface_p.h" @@ -64,6 +63,7 @@ #include "qwaylandsurfaceview.h" #include "qwaylandshmformathelper.h" #include "qwaylandoutput.h" +#include "qwlkeyboard_p.h" #include <QWindow> #include <QSocketNotifier> @@ -99,12 +99,61 @@ #include "hardware_integration/qwlclientbufferintegrationfactory_p.h" #include "hardware_integration/qwlserverbufferintegrationfactory_p.h" +#include "../shared/qwaylandxkb.h" + QT_BEGIN_NAMESPACE namespace QtWayland { static Compositor *compositor; +class WindowSystemEventHandler : public QWindowSystemEventHandler +{ +public: + WindowSystemEventHandler(Compositor *c) : compositor(c) {} + bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) Q_DECL_OVERRIDE + { + if (e->type == QWindowSystemInterfacePrivate::Key) { + QWindowSystemInterfacePrivate::KeyEvent *ke = static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e); + Keyboard *keyb = compositor->defaultInputDevice()->keyboardDevice(); + + uint32_t code = ke->nativeScanCode; + bool isDown = ke->keyType == QEvent::KeyPress; + +#ifndef QT_NO_WAYLAND_XKB + QString text; + Qt::KeyboardModifiers modifiers = QWaylandXkb::modifiers(keyb->xkbState()); + + const xkb_keysym_t sym = xkb_state_key_get_one_sym(keyb->xkbState(), code); + uint utf32 = xkb_keysym_to_utf32(sym); + if (utf32) + text = QString::fromUcs4(&utf32, 1); + int qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text); + + ke->key = qtkey; + ke->modifiers = modifiers; + ke->nativeVirtualKey = sym; + ke->nativeModifiers = keyb->xkbModsMask(); + ke->unicode = text; +#endif + if (!ke->repeat) + keyb->keyEvent(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); + + QWindowSystemEventHandler::sendEvent(e); + + if (!ke->repeat) { + keyb->updateKeymap(); + keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); + } + } else { + QWindowSystemEventHandler::sendEvent(e); + } + return true; + } + + Compositor *compositor; +}; + Compositor *Compositor::instance() { return compositor; @@ -123,17 +172,19 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex , m_server_buffer_integration(0) #endif , m_windowManagerIntegration(0) - , m_outputExtension(0) , m_surfaceExtension(0) , m_subSurfaceExtension(0) , m_touchExtension(0) , m_qtkeyExtension(0) , m_textInputManager() , m_inputPanel() + , m_eventHandler(new WindowSystemEventHandler(this)) , m_retainSelection(false) { m_timer.start(); compositor = this; + + QWindowSystemInterfacePrivate::installWindowSystemEventHandler(m_eventHandler.data()); } void Compositor::init() @@ -187,7 +238,6 @@ Compositor::~Compositor() qDeleteAll(m_outputs); - delete m_outputExtension; delete m_surfaceExtension; delete m_subSurfaceExtension; delete m_touchExtension; @@ -360,8 +410,6 @@ void Compositor::initializeHardwareIntegration() void Compositor::initializeExtensions() { - if (m_extensions & QWaylandCompositor::OutputExtension) - m_outputExtension = new OutputExtensionGlobal(this); if (m_extensions & QWaylandCompositor::SurfaceExtension) m_surfaceExtension = new SurfaceExtensionGlobal(this); if (m_extensions & QWaylandCompositor::SubSurfaceExtension) diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h index 1efbd2ee3..7360e7dca 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor_p.h +++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h @@ -66,6 +66,7 @@ class WindowManagerServerIntegration; class QMimeData; class QPlatformScreenBuffer; class QWaylandSurface; +class QWindowSystemEventHandler; namespace QtWayland { @@ -74,7 +75,6 @@ class SurfaceBuffer; class InputDevice; class DataDeviceManager; class OutputGlobal; -class OutputExtensionGlobal; class SurfaceExtensionGlobal; class SubSurfaceExtensionGlobal; class TouchExtensionGlobal; @@ -214,7 +214,6 @@ protected: //extensions WindowManagerServerIntegration *m_windowManagerIntegration; - OutputExtensionGlobal *m_outputExtension; SurfaceExtensionGlobal *m_surfaceExtension; SubSurfaceExtensionGlobal *m_subSurfaceExtension; TouchExtensionGlobal *m_touchExtension; @@ -222,6 +221,7 @@ protected: QScopedPointer<TextInputManager> m_textInputManager; QScopedPointer<InputPanel> m_inputPanel; QList<QWaylandGlobalInterface *> m_globals; + QScopedPointer<QWindowSystemEventHandler> m_eventHandler; static void bind_func(struct wl_client *client, void *data, uint32_t version, uint32_t id); diff --git a/src/compositor/wayland_wrapper/qwlextendedoutput.cpp b/src/compositor/wayland_wrapper/qwlextendedoutput.cpp deleted file mode 100644 index dbcbb57b8..000000000 --- a/src/compositor/wayland_wrapper/qwlextendedoutput.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** 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 The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** 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 "qwlextendedoutput_p.h" - -#include "qwlcompositor_p.h" -#include "qwlsurface_p.h" -#include "qwloutput_p.h" - -QT_BEGIN_NAMESPACE - -namespace QtWayland { - -OutputExtensionGlobal::OutputExtensionGlobal(Compositor *compositor) - : QtWaylandServer::qt_output_extension(compositor->wl_display(), 1) - , m_compositor(compositor) -{ -} - -void OutputExtensionGlobal::output_extension_get_extended_output(qt_output_extension::Resource *resource, uint32_t id, wl_resource *output_resource) -{ - OutputResource *output = static_cast<OutputResource *>(Output::Resource::fromResource(output_resource)); - Q_ASSERT(output->extendedOutput == 0); - - ExtendedOutput *extendedOutput = static_cast<ExtendedOutput *>(qt_extended_output::add(resource->client(), id)); - - Q_ASSERT(!output->extendedOutput); - output->extendedOutput = extendedOutput; - extendedOutput->output = output; -} - -} - -QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlextendedoutput_p.h b/src/compositor/wayland_wrapper/qwlextendedoutput_p.h deleted file mode 100644 index 8d030dd95..000000000 --- a/src/compositor/wayland_wrapper/qwlextendedoutput_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** 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 The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** 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 WLEXTENDEDOUTPUT_H -#define WLEXTENDEDOUTPUT_H - -#include "wayland-server.h" - -#include <QtCompositor/qwaylandexport.h> - -#include <QtCore/qnamespace.h> - -#include <QtCompositor/private/qwayland-server-output-extension.h> - -QT_BEGIN_NAMESPACE - -namespace QtWayland { - -class Compositor; -class OutputResource; - -class ExtendedOutput : public QtWaylandServer::qt_extended_output::Resource -{ -public: - ExtendedOutput() : output(0) {} - - OutputResource *output; -}; - -class OutputExtensionGlobal : public QtWaylandServer::qt_output_extension, public QtWaylandServer::qt_extended_output -{ -public: - OutputExtensionGlobal(Compositor *compositor); - -private: - Compositor *m_compositor; - - qt_extended_output::Resource *extended_output_allocate() Q_DECL_OVERRIDE { return new ExtendedOutput; } - - void output_extension_get_extended_output(qt_output_extension::Resource *resource, - uint32_t id, - struct wl_resource *output_resource) Q_DECL_OVERRIDE; -}; - - -} - -QT_END_NAMESPACE - -#endif // WLEXTENDEDOUTPUT_H diff --git a/src/compositor/wayland_wrapper/qwlextendedsurface.cpp b/src/compositor/wayland_wrapper/qwlextendedsurface.cpp index 1c6a14172..50cc5bb7e 100644 --- a/src/compositor/wayland_wrapper/qwlextendedsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlextendedsurface.cpp @@ -85,11 +85,10 @@ void ExtendedSurface::sendGenericProperty(const QString &name, const QVariant &v } -void ExtendedSurface::setVisibility(QWindow::Visibility visibility, bool updateClient) +void ExtendedSurface::setVisibility(QWindow::Visibility visibility) { // If this change came from the client, we shouldn't update it - if (updateClient) - send_onscreen_visibility(visibility); + send_onscreen_visibility(visibility); } void ExtendedSurface::setParentSurface(Surface *surface) diff --git a/src/compositor/wayland_wrapper/qwlextendedsurface_p.h b/src/compositor/wayland_wrapper/qwlextendedsurface_p.h index e3c370091..8af6232a6 100644 --- a/src/compositor/wayland_wrapper/qwlextendedsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlextendedsurface_p.h @@ -80,7 +80,7 @@ public: void sendGenericProperty(const QString &name, const QVariant &variant); - void setVisibility(QWindow::Visibility visibility, bool updateClient = true); + void setVisibility(QWindow::Visibility visibility); void setSubSurface(ExtendedSurface *subSurface,int x, int y); void removeSubSurface(ExtendedSurface *subSurfaces); diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp index 59b69a3cf..060965663 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp +++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp @@ -146,7 +146,15 @@ void Keyboard::setFocus(Surface* surface) void Keyboard::setKeymap(const QWaylandKeymap &keymap) { m_keymap = keymap; - m_pendingKeymap = true; + + // If there is no key currently pressed, update right away the keymap + // Otherwise, delay the update when keys are released + // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html + if (m_keys.isEmpty()) { + updateKeymap(); + } else { + m_pendingKeymap = true; + } } void Keyboard::focusDestroyed(void *data) @@ -216,17 +224,9 @@ void Keyboard::key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state) } } -void Keyboard::sendKeyEvent(uint code, uint32_t state) +void Keyboard::keyEvent(uint code, uint32_t state) { - // There must be no keys pressed when changing the keymap, - // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html - if (m_pendingKeymap && m_keys.isEmpty()) - updateKeymap(); - - uint32_t time = m_compositor->currentTimeMsecs(); - uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); uint key = code - 8; - m_grab->key(serial, time, key, state); if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { m_keys << key; } else { @@ -236,7 +236,14 @@ void Keyboard::sendKeyEvent(uint code, uint32_t state) } } } - updateModifierState(code, state); +} + +void Keyboard::sendKeyEvent(uint code, uint32_t state) +{ + uint32_t time = m_compositor->currentTimeMsecs(); + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + uint key = code - 8; + m_grab->key(serial, time, key, state); } void Keyboard::modifiers(uint32_t serial, uint32_t mods_depressed, @@ -280,6 +287,11 @@ void Keyboard::updateModifierState(uint code, uint32_t state) void Keyboard::updateKeymap() { + // There must be no keys pressed when changing the keymap, + // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html + if (!m_pendingKeymap || !m_keys.isEmpty()) + return; + m_pendingKeymap = false; #ifndef QT_NO_WAYLAND_XKB if (!m_context) diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h index 2ace8c000..c4df31266 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard_p.h +++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h @@ -99,10 +99,18 @@ public: void modifiers(uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group); + void keyEvent(uint code, uint32_t state); + void updateModifierState(uint code, uint32_t state); + void updateKeymap(); + void startGrab(KeyboardGrabber *grab); void endGrab(); KeyboardGrabber *currentGrab() const; +#ifndef QT_NO_WAYLAND_XKB + struct xkb_state *xkbState() const { return m_state; } + uint32_t xkbModsMask() const { return m_modsDepressed | m_modsLatched | m_modsLocked; } +#endif Q_SIGNALS: void focusChanged(Surface *surface); @@ -114,8 +122,6 @@ protected: private: void sendKeyEvent(uint code, uint32_t state); - void updateModifierState(uint code, uint32_t state); - void updateKeymap(); void focusDestroyed(void *data); #ifndef QT_NO_WAYLAND_XKB diff --git a/src/compositor/wayland_wrapper/qwloutput.cpp b/src/compositor/wayland_wrapper/qwloutput.cpp index ba9338d34..0cbe166e2 100644 --- a/src/compositor/wayland_wrapper/qwloutput.cpp +++ b/src/compositor/wayland_wrapper/qwloutput.cpp @@ -42,7 +42,6 @@ #include "qwloutput_p.h" #include "qwlcompositor_p.h" -#include "qwlextendedoutput_p.h" #include "qwlsurface_p.h" #include <QtGui/QWindow> diff --git a/src/compositor/wayland_wrapper/qwloutput_p.h b/src/compositor/wayland_wrapper/qwloutput_p.h index 1bf6e01f6..b85081e80 100644 --- a/src/compositor/wayland_wrapper/qwloutput_p.h +++ b/src/compositor/wayland_wrapper/qwloutput_p.h @@ -57,12 +57,10 @@ class QWindow; namespace QtWayland { class Compositor; -class ExtendedOutput; struct OutputResource : public QtWaylandServer::wl_output::Resource { - OutputResource() : extendedOutput(0) {} - ExtendedOutput *extendedOutput; + OutputResource() {} }; class Output : public QtWaylandServer::wl_output diff --git a/src/compositor/wayland_wrapper/qwlshellsurface.cpp b/src/compositor/wayland_wrapper/qwlshellsurface.cpp index beb11d095..b2725462b 100644 --- a/src/compositor/wayland_wrapper/qwlshellsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlshellsurface.cpp @@ -254,8 +254,7 @@ void ShellSurface::shell_surface_set_toplevel(Resource *resource) setSurfaceType(QWaylandSurface::Toplevel); - if (m_surface->extendedSurface()) - m_surface->extendedSurface()->setVisibility(QWindow::Windowed, false); + m_surface->setVisibility(QWindow::Windowed); } void ShellSurface::shell_surface_set_transient(Resource *resource, @@ -275,8 +274,7 @@ void ShellSurface::shell_surface_set_transient(Resource *resource, setSurfaceType(QWaylandSurface::Transient); - if (m_surface->extendedSurface()) - m_surface->extendedSurface()->setVisibility(QWindow::AutomaticVisibility, false); + m_surface->setVisibility(QWindow::AutomaticVisibility); } void ShellSurface::shell_surface_set_fullscreen(Resource *resource, @@ -310,8 +308,7 @@ void ShellSurface::shell_surface_set_fullscreen(Resource *resource, m_view->setPos(output->geometry().topLeft()); send_configure(resize_bottom_right, outputSize.width(), outputSize.height()); - if (m_surface->extendedSurface()) - m_surface->extendedSurface()->setVisibility(QWindow::FullScreen, false); + m_surface->setVisibility(QWindow::FullScreen); } void ShellSurface::shell_surface_set_popup(Resource *resource, wl_resource *input_device, uint32_t serial, wl_resource *parent, int32_t x, int32_t y, uint32_t flags) @@ -329,8 +326,7 @@ void ShellSurface::shell_surface_set_popup(Resource *resource, wl_resource *inpu setSurfaceType(QWaylandSurface::Popup); - if (m_surface->extendedSurface()) - m_surface->extendedSurface()->setVisibility(QWindow::AutomaticVisibility, false); + m_surface->setVisibility(QWindow::AutomaticVisibility); } void ShellSurface::shell_surface_set_maximized(Resource *resource, @@ -360,8 +356,7 @@ void ShellSurface::shell_surface_set_maximized(Resource *resource, m_view->setPos(output->availableGeometry().topLeft()); send_configure(resize_bottom_right, outputSize.width(), outputSize.height()); - if (m_surface->extendedSurface()) - m_surface->extendedSurface()->setVisibility(QWindow::Maximized, false); + m_surface->setVisibility(QWindow::Maximized); } void ShellSurface::shell_surface_pong(Resource *resource, diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index 2b7f21aee..d23c6aeb0 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -129,6 +129,8 @@ Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCom , m_destroyed(false) , m_contentOrientation(Qt::PrimaryOrientation) , m_visibility(QWindow::Hidden) + , m_role(0) + , m_roleHandler(0) { m_pending.buffer = 0; m_pending.newlyAttached = false; @@ -150,6 +152,17 @@ Surface::~Surface() c->destroy(); } +bool Surface::setRole(const SurfaceRole *role, wl_resource *errorResource, uint32_t errorCode) +{ + if (m_role && m_role != role) { + wl_resource_post_error(errorResource, errorCode, "Cannot assign role %s to wl_surface@%d, already has role %s\n", role->name, + wl_resource_get_id(resource()->handle), m_role->name); + return false; + } + m_role = role; + return true; +} + void Surface::setTransientOffset(qreal x, qreal y) { m_transientOffset.setX(x); @@ -187,7 +200,7 @@ bool Surface::isYInverted() const bool Surface::mapped() const { - return m_buffer ? bool(m_buffer->waylandBufferHandle()) : false; + return !m_unmapLocks.isEmpty() || (m_buffer && bool(m_buffer->waylandBufferHandle())); } QSize Surface::size() const @@ -353,7 +366,8 @@ void Surface::setBackBuffer(SurfaceBuffer *buffer) if (m_buffer) { bool valid = m_buffer->waylandBufferHandle() != 0; - setSize(valid ? m_buffer->size() : QSize()); + if (valid) + setSize(m_buffer->size()); m_damage = m_damage.intersected(QRect(QPoint(), m_size)); emit m_waylandSurface->damaged(m_damage); @@ -374,6 +388,20 @@ void Surface::setMapped(bool mapped) } } +void Surface::addUnmapLock(QWaylandUnmapLock *l) +{ + m_unmapLocks << l; +} + +void Surface::removeUnmapLock(QWaylandUnmapLock *l) +{ + m_unmapLocks.removeOne(l); + if (!mapped() && m_attacher) { + setSize(QSize()); + m_attacher->unmap(); + } +} + SurfaceBuffer *Surface::createSurfaceBuffer(struct ::wl_resource *buffer) { SurfaceBuffer *newBuffer = 0; @@ -468,9 +496,17 @@ void Surface::surface_commit(Resource *) setBackBuffer(m_pending.buffer); m_bufferRef = QWaylandBufferRef(m_buffer); - if (m_attacher) - m_attacher->attach(m_bufferRef); + if (m_attacher) { + if (m_bufferRef) { + m_attacher->attach(m_bufferRef); + } else if (!mapped()) { + setSize(QSize()); + m_attacher->unmap(); + } + } emit m_waylandSurface->configure(m_bufferRef); + if (m_roleHandler) + m_roleHandler->configure(m_pending.offset.x(), m_pending.offset.y()); } m_pending.buffer = 0; diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index 103b5994a..d08fb4cd6 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE class QTouchEvent; +class QWaylandUnmapLock; + namespace QtWayland { class Compositor; @@ -74,12 +76,20 @@ class InputPanelSurface; class SubSurface; class FrameCallback; +class SurfaceRole; +class RoleBase; + class Q_COMPOSITOR_EXPORT Surface : public QtWaylandServer::wl_surface { public: Surface(struct wl_client *client, uint32_t id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface); ~Surface(); + bool setRole(const SurfaceRole *role, wl_resource *errorResource, uint32_t errorCode); + const SurfaceRole *role() const { return m_role; } + template<class T> + bool setRoleHandler(T *handler); + static Surface *fromResource(struct ::wl_resource *resource); QWaylandSurface::Type type() const; @@ -141,7 +151,11 @@ public: void releaseSurfaces(); void frameStarted(); + void addUnmapLock(QWaylandUnmapLock *l); + void removeUnmapLock(QWaylandUnmapLock *l); + void setMapped(bool mapped); + void setVisibility(QWindow::Visibility visibility) { m_visibility = visibility; } inline bool isDestroyed() const { return m_destroyed; } @@ -176,6 +190,7 @@ protected: QWaylandBufferRef m_bufferRef; bool m_surfaceMapped; QWaylandBufferAttacher *m_attacher; + QVector<QWaylandUnmapLock *> m_unmapLocks; struct { SurfaceBuffer *buffer; @@ -211,12 +226,66 @@ protected: Qt::ScreenOrientation m_contentOrientation; QWindow::Visibility m_visibility; + const SurfaceRole *m_role; + RoleBase *m_roleHandler; + void setBackBuffer(SurfaceBuffer *buffer); SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); friend class QWaylandSurface; + friend class RoleBase; +}; + +class SurfaceRole +{ +public: + const char *name; +}; + +class RoleBase +{ +public: + virtual ~RoleBase() { + if (m_surface) { + m_surface->m_roleHandler = 0; m_surface = 0; + } + } + +protected: + RoleBase() : m_surface(0) {} + static inline RoleBase *roleOf(Surface *s) { return s->m_roleHandler; } + + virtual void configure(int dx, int dy) = 0; + +private: + Surface *m_surface; + friend class Surface; +}; + +template<class T> +class SurfaceRoleHandler : public RoleBase +{ +public: + static T *get(Surface *surface) { + if (surface->role() == T::role()) { + return static_cast<T *>(roleOf(surface)); + } + return 0; + } }; +template<class T> +bool Surface::setRoleHandler(T *handler) +{ + RoleBase *base = handler; + if (m_role == T::role()) { + m_roleHandler = base; + base->m_surface = this; + return true; + } + return false; +} + } QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri index ac34ae283..eb66f6949 100644 --- a/src/compositor/wayland_wrapper/wayland_wrapper.pri +++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri @@ -2,7 +2,6 @@ CONFIG += wayland-scanner WAYLANDSERVERSOURCES += \ ../extensions/surface-extension.xml \ ../extensions/sub-surface-extension.xml \ - ../extensions/output-extension.xml \ ../extensions/touch-extension.xml \ ../extensions/qtkey-extension.xml \ ../extensions/windowmanager.xml \ @@ -17,7 +16,6 @@ HEADERS += \ wayland_wrapper/qwldataoffer_p.h \ wayland_wrapper/qwldatasource_p.h \ wayland_wrapper/qwldisplay_p.h \ - wayland_wrapper/qwlextendedoutput_p.h \ wayland_wrapper/qwlextendedsurface_p.h \ wayland_wrapper/qwlinputdevice_p.h \ wayland_wrapper/qwlinputmethod_p.h \ @@ -38,6 +36,7 @@ HEADERS += \ wayland_wrapper/qwltextinputmanager_p.h \ wayland_wrapper/qwltouch_p.h \ wayland_wrapper/qwllistener_p.h \ + ../shared/qwaylandxkb.h \ SOURCES += \ wayland_wrapper/qwlcompositor.cpp \ @@ -46,7 +45,6 @@ SOURCES += \ wayland_wrapper/qwldataoffer.cpp \ wayland_wrapper/qwldatasource.cpp \ wayland_wrapper/qwldisplay.cpp \ - wayland_wrapper/qwlextendedoutput.cpp \ wayland_wrapper/qwlextendedsurface.cpp \ wayland_wrapper/qwlinputdevice.cpp \ wayland_wrapper/qwlinputmethod.cpp \ @@ -67,6 +65,7 @@ SOURCES += \ wayland_wrapper/qwltextinputmanager.cpp \ wayland_wrapper/qwltouch.cpp \ wayland_wrapper/qwllistener.cpp \ + ../shared/qwaylandxkb.cpp \ INCLUDEPATH += wayland_wrapper |