diff options
43 files changed, 633 insertions, 645 deletions
diff --git a/.qmake.conf b/.qmake.conf index e5439818..66a0241e 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.5.1 +MODULE_VERSION = 5.6.0 diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp index 0b39f110..5d338692 100644 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp +++ b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp @@ -98,6 +98,13 @@ public: } } + void unmap() + { + delete shmTex; + shmTex = 0; + bufferRef = QWaylandBufferRef(); + } + QImage image() const { if (!bufferRef || !bufferRef.isShm()) diff --git a/src/client/client.pro b/src/client/client.pro index 0c13a4a9..ba17b21c 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -46,7 +46,6 @@ WAYLANDCLIENTSOURCES += \ ../3rdparty/protocol/wayland.xml \ ../extensions/surface-extension.xml \ ../extensions/sub-surface-extension.xml \ - ../extensions/output-extension.xml \ ../extensions/touch-extension.xml \ ../extensions/qtkey-extension.xml \ ../extensions/windowmanager.xml \ @@ -71,12 +70,12 @@ SOURCES += qwaylandintegration.cpp \ qwaylandwlshellsurface.cpp \ qwaylandxdgshell.cpp \ qwaylandxdgsurface.cpp \ - qwaylandextendedoutput.cpp \ qwaylandextendedsurface.cpp \ qwaylandsubsurface.cpp \ qwaylandtouch.cpp \ qwaylandqtkey.cpp \ ../shared/qwaylandmimehelper.cpp \ + ../shared/qwaylandxkb.cpp \ qwaylandabstractdecoration.cpp \ qwaylanddecorationfactory.cpp \ qwaylanddecorationplugin.cpp \ @@ -104,12 +103,12 @@ HEADERS += qwaylandintegration_p.h \ qwaylandwlshellsurface_p.h \ qwaylandxdgshell_p.h \ qwaylandxdgsurface_p.h \ - qwaylandextendedoutput_p.h \ qwaylandextendedsurface_p.h \ qwaylandsubsurface_p.h \ qwaylandtouch_p.h \ qwaylandqtkey_p.h \ ../shared/qwaylandmimehelper.h \ + ../shared/qwaylandxkb.h \ qwaylandabstractdecoration_p.h \ qwaylanddecorationfactory_p.h \ qwaylanddecorationplugin_p.h \ diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp index 8e8293a0..8dfc95c3 100644 --- a/src/client/qwaylandcursor.cpp +++ b/src/client/qwaylandcursor.cpp @@ -161,7 +161,7 @@ wl_cursor *QWaylandCursor::requestCursor(WaylandCursor shape) return NULL; QList<QByteArray> cursorNames = mCursorNamesMap.values(shape); - foreach (QByteArray name, cursorNames) { + foreach (const QByteArray &name, cursorNames) { cursor = wl_cursor_theme_get_cursor(mCursorTheme, name.constData()); if (cursor) { mCursors.insert(shape, cursor); diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index f197b378..2d1c81a7 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -50,7 +50,6 @@ #include "qwaylandshellintegration_p.h" #include "qwaylandclientbufferintegration_p.h" -#include "qwaylandextendedoutput_p.h" #include "qwaylandextendedsurface_p.h" #include "qwaylandsubsurface_p.h" #include "qwaylandtouch_p.h" @@ -101,6 +100,15 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion) return region; } +::wl_subsurface *QWaylandDisplay::createSubSurface(QWaylandWindow *window, QWaylandWindow *parent) +{ + if (!mSubCompositor) { + return NULL; + } + + return mSubCompositor->get_subsurface(window->object(), parent->object()); +} + QWaylandClientBufferIntegration * QWaylandDisplay::clientBufferIntegration() const { return mWaylandIntegration->clientBufferIntegration(); @@ -126,8 +134,7 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) , mLastKeyboardFocusInputDevice(0) , mDndSelectionHandler(0) , mWindowExtension(0) - , mSubSurfaceExtension(0) - , mOutputExtension(0) + , mSubCompositor(0) , mTouchExtension(0) , mQtKeyExtension(0) , mTextInputManager(0) @@ -254,14 +261,10 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin mInputDevices.append(inputDevice); } else if (interface == QStringLiteral("wl_data_device_manager")) { mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); - } else if (interface == QStringLiteral("qt_output_extension")) { - mOutputExtension.reset(new QtWayland::qt_output_extension(registry, id, 1)); - foreach (QPlatformScreen *screen, screens()) - static_cast<QWaylandScreen *>(screen)->createExtendedOutput(); } else if (interface == QStringLiteral("qt_surface_extension")) { mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1)); - } else if (interface == QStringLiteral("qt_sub_surface_extension")) { - mSubSurfaceExtension.reset(new QtWayland::qt_sub_surface_extension(registry, id, 1)); + } else if (interface == QStringLiteral("wl_subcompositor")) { + mSubCompositor.reset(new QtWayland::wl_subcompositor(registry, id, 1)); } else if (interface == QStringLiteral("qt_touch_extension")) { mTouchExtension.reset(new QWaylandTouchExtension(this, id)); } else if (interface == QStringLiteral("qt_key_extension")) { diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index ee129a50..84c79d70 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -100,6 +100,7 @@ public: struct wl_surface *createSurface(void *handle); QWaylandShellSurface *createShellSurface(QWaylandWindow *window); struct ::wl_region *createRegion(const QRegion &qregion); + struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent); QWaylandClientBufferIntegration *clientBufferIntegration() const; @@ -127,8 +128,6 @@ public: QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); } QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); } - QtWayland::qt_sub_surface_extension *subSurfaceExtension() const { return mSubSurfaceExtension.data(); } - QtWayland::qt_output_extension *outputExtension() const { return mOutputExtension.data(); } QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); } QtWayland::wl_text_input_manager *textInputManager() const { return mTextInputManager.data(); } QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); } @@ -187,8 +186,7 @@ private: QWaylandInputDevice *mLastKeyboardFocusInputDevice; QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler; QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension; - QScopedPointer<QtWayland::qt_sub_surface_extension> mSubSurfaceExtension; - QScopedPointer<QtWayland::qt_output_extension> mOutputExtension; + QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor; QScopedPointer<QWaylandTouchExtension> mTouchExtension; QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension; QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration; diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp index 302864d4..59f91411 100644 --- a/src/client/qwaylanddnd.cpp +++ b/src/client/qwaylanddnd.cpp @@ -89,15 +89,15 @@ void QWaylandDrag::cancel() m_display->currentInputDevice()->dataDevice()->cancelDrag(); } -void QWaylandDrag::move(const QMouseEvent *me) +void QWaylandDrag::move(const QPoint &globalPos) { - Q_UNUSED(me); + Q_UNUSED(globalPos); // Do nothing } -void QWaylandDrag::drop(const QMouseEvent *me) +void QWaylandDrag::drop(const QPoint &globalPos) { - Q_UNUSED(me); + Q_UNUSED(globalPos); // Do nothing } diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h index 994c65c4..19b1f92e 100644 --- a/src/client/qwaylanddnd_p.h +++ b/src/client/qwaylanddnd_p.h @@ -63,8 +63,8 @@ public: protected: void startDrag() Q_DECL_OVERRIDE; void cancel() Q_DECL_OVERRIDE; - void move(const QMouseEvent *me) Q_DECL_OVERRIDE; - void drop(const QMouseEvent *me) Q_DECL_OVERRIDE; + void move(const QPoint &globalPos) Q_DECL_OVERRIDE; + void drop(const QPoint &globalpos) Q_DECL_OVERRIDE; void endDrag() Q_DECL_OVERRIDE; diff --git a/src/client/qwaylandextendedoutput_p.h b/src/client/qwaylandextendedoutput_p.h deleted file mode 100644 index b3e4c469..00000000 --- a/src/client/qwaylandextendedoutput_p.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWAYLANDEXTENDEDOUTPUT_H -#define QWAYLANDEXTENDEDOUTPUT_H - -#include <QtWaylandClient/private/qwayland-output-extension.h> -#include <QtWaylandClient/private/qwaylandclientexport_p.h> - -QT_BEGIN_NAMESPACE - -namespace QtWaylandClient { - -class QWaylandDisplay; -class QWaylandScreen; -class QWaylandExtendedOutput; - -class Q_WAYLAND_CLIENT_EXPORT QWaylandExtendedOutput : public QtWayland::qt_extended_output -{ -public: - QWaylandExtendedOutput(QWaylandScreen *screen, struct ::qt_extended_output *extended_output); -}; - -} - -QT_END_NAMESPACE - -#endif // QWAYLANDEXTENDEDOUTPUT_H diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 009ef670..9ac678c9 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -42,6 +42,7 @@ #include "qwaylandscreen_p.h" #include "qwaylandcursor_p.h" #include "qwaylanddisplay_p.h" +#include "../shared/qwaylandxkb.h" #include <QtGui/private/qpixmap_raster_p.h> #include <qpa/qplatformwindow.h> @@ -302,16 +303,7 @@ Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const 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, XKB_MOD_NAME_SHIFT, cstate)) - ret |= Qt::ShiftModifier; - if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_CTRL, cstate)) - ret |= Qt::ControlModifier; - if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_ALT, cstate)) - ret |= Qt::AltModifier; - if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_LOGO, cstate)) - ret |= Qt::MetaModifier; + ret = QWaylandXkb::modifiers(mXkbState); #endif return ret; @@ -530,150 +522,6 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in window->handleMouse(mParent, e); } -#ifndef QT_NO_WAYLAND_XKB - -static const uint32_t KeyTbl[] = { - XKB_KEY_Escape, Qt::Key_Escape, - XKB_KEY_Tab, Qt::Key_Tab, - XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab, - XKB_KEY_BackSpace, Qt::Key_Backspace, - XKB_KEY_Return, Qt::Key_Return, - XKB_KEY_Insert, Qt::Key_Insert, - XKB_KEY_Delete, Qt::Key_Delete, - XKB_KEY_Clear, Qt::Key_Delete, - XKB_KEY_Pause, Qt::Key_Pause, - XKB_KEY_Print, Qt::Key_Print, - - XKB_KEY_Home, Qt::Key_Home, - XKB_KEY_End, Qt::Key_End, - XKB_KEY_Left, Qt::Key_Left, - XKB_KEY_Up, Qt::Key_Up, - XKB_KEY_Right, Qt::Key_Right, - XKB_KEY_Down, Qt::Key_Down, - XKB_KEY_Prior, Qt::Key_PageUp, - XKB_KEY_Next, Qt::Key_PageDown, - - XKB_KEY_Shift_L, Qt::Key_Shift, - XKB_KEY_Shift_R, Qt::Key_Shift, - XKB_KEY_Shift_Lock, Qt::Key_Shift, - XKB_KEY_Control_L, Qt::Key_Control, - XKB_KEY_Control_R, Qt::Key_Control, - XKB_KEY_Meta_L, Qt::Key_Meta, - XKB_KEY_Meta_R, Qt::Key_Meta, - XKB_KEY_Alt_L, Qt::Key_Alt, - XKB_KEY_Alt_R, Qt::Key_Alt, - XKB_KEY_Caps_Lock, Qt::Key_CapsLock, - XKB_KEY_Num_Lock, Qt::Key_NumLock, - XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock, - XKB_KEY_Super_L, Qt::Key_Super_L, - XKB_KEY_Super_R, Qt::Key_Super_R, - XKB_KEY_Menu, Qt::Key_Menu, - XKB_KEY_Hyper_L, Qt::Key_Hyper_L, - XKB_KEY_Hyper_R, Qt::Key_Hyper_R, - XKB_KEY_Help, Qt::Key_Help, - - XKB_KEY_KP_Space, Qt::Key_Space, - XKB_KEY_KP_Tab, Qt::Key_Tab, - XKB_KEY_KP_Enter, Qt::Key_Enter, - XKB_KEY_KP_Home, Qt::Key_Home, - XKB_KEY_KP_Left, Qt::Key_Left, - XKB_KEY_KP_Up, Qt::Key_Up, - XKB_KEY_KP_Right, Qt::Key_Right, - XKB_KEY_KP_Down, Qt::Key_Down, - XKB_KEY_KP_Prior, Qt::Key_PageUp, - XKB_KEY_KP_Next, Qt::Key_PageDown, - XKB_KEY_KP_End, Qt::Key_End, - XKB_KEY_KP_Begin, Qt::Key_Clear, - XKB_KEY_KP_Insert, Qt::Key_Insert, - XKB_KEY_KP_Delete, Qt::Key_Delete, - XKB_KEY_KP_Equal, Qt::Key_Equal, - XKB_KEY_KP_Multiply, Qt::Key_Asterisk, - XKB_KEY_KP_Add, Qt::Key_Plus, - XKB_KEY_KP_Separator, Qt::Key_Comma, - XKB_KEY_KP_Subtract, Qt::Key_Minus, - XKB_KEY_KP_Decimal, Qt::Key_Period, - XKB_KEY_KP_Divide, Qt::Key_Slash, - - XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr, - XKB_KEY_Multi_key, Qt::Key_Multi_key, - XKB_KEY_Codeinput, Qt::Key_Codeinput, - XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate, - XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate, - XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate, - - 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 -}; - -static int keysymToQtKey(xkb_keysym_t key) -{ - int code = 0; - int i = 0; - while (KeyTbl[i]) { - if (key == KeyTbl[i]) { - code = (int)KeyTbl[i+1]; - break; - } - i += 2; - } - - return code; -} - -static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) -{ - int code = 0; - - if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) { - code = Qt::Key_F1 + (int(keysym) - XKB_KEY_F1); - } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) { - if (keysym >= XKB_KEY_KP_0) { - // numeric keypad keys - code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0); - } else { - code = keysymToQtKey(keysym); - } - modifiers |= Qt::KeypadModifier; - } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f - && text.unicode()->unicode() != 0x7f - && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_currency)) { - code = text.unicode()->toUpper().unicode(); - } else { - // any other keys - code = keysymToQtKey(keysym); - } - - return code; -} - -#endif // QT_NO_WAYLAND_XKB - void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size) { #ifndef QT_NO_WAYLAND_XKB @@ -795,7 +643,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, if (utf32) text = QString::fromUcs4(&utf32, 1); - qtkey = keysymToQtKey(sym, modifiers, text); + qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text); QWindowSystemInterface::handleExtendedKeyEvent(window->window(), time, type, qtkey, diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index 9526aec4..82df8a30 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -128,7 +128,9 @@ QWaylandIntegration::QWaylandIntegration() mClipboard = new QWaylandClipboard(mDisplay); mDrag = new QWaylandDrag(mDisplay); - mInputContext.reset(new QWaylandInputContext(mDisplay)); + QString icStr = QPlatformInputContextFactory::requested(); + icStr.isNull() ? mInputContext.reset(new QWaylandInputContext(mDisplay)) + : mInputContext.reset(QPlatformInputContextFactory::create(icStr)); } QWaylandIntegration::~QWaylandIntegration() diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp index 8a01e366..1be90e8e 100644 --- a/src/client/qwaylandscreen.cpp +++ b/src/client/qwaylandscreen.cpp @@ -35,7 +35,6 @@ #include "qwaylanddisplay_p.h" #include "qwaylandcursor_p.h" -#include "qwaylandextendedoutput_p.h" #include "qwaylandwindow_p.h" #include <QtGui/QGuiApplication> @@ -52,7 +51,6 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin , QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2)) , m_outputId(id) , mWaylandDisplay(waylandDisplay) - , mExtendedOutput(0) , mScale(1) , mDepth(32) , mRefreshRate(60000) @@ -62,8 +60,6 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin , m_orientation(Qt::PrimaryOrientation) , mWaylandCursor(0) { - // handle case of output extension global being sent after outputs - createExtendedOutput(); } QWaylandScreen::~QWaylandScreen() @@ -118,7 +114,9 @@ QDpi QWaylandScreen::logicalDpi() const QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const { QList<QPlatformScreen *> list; - foreach (QWaylandScreen *screen, mWaylandDisplay->screens()) + const QList<QWaylandScreen*> screens = mWaylandDisplay->screens(); + list.reserve(screens.count()); + foreach (QWaylandScreen *screen, screens) list << screen; return list; } @@ -157,18 +155,6 @@ QPlatformCursor *QWaylandScreen::cursor() const return mWaylandCursor; } -QWaylandExtendedOutput *QWaylandScreen::extendedOutput() const -{ - return mExtendedOutput; -} - -void QWaylandScreen::createExtendedOutput() -{ - QtWayland::qt_output_extension *extension = mWaylandDisplay->outputExtension(); - if (!mExtendedOutput && extension) - mExtendedOutput = new QWaylandExtendedOutput(this, extension->get_extended_output(output())); -} - QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window) { QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(window); diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h index 06389f7e..3d38e30a 100644 --- a/src/client/qwaylandscreen_p.h +++ b/src/client/qwaylandscreen_p.h @@ -45,7 +45,6 @@ namespace QtWaylandClient { class QWaylandDisplay; class QWaylandCursor; -class QWaylandExtendedOutput; class Q_WAYLAND_CLIENT_EXPORT QWaylandScreen : public QPlatformScreen, QtWayland::wl_output { @@ -80,9 +79,6 @@ public: uint32_t outputId() const { return m_outputId; } ::wl_output *output() { return object(); } - QWaylandExtendedOutput *extendedOutput() const; - void createExtendedOutput(); - static QWaylandScreen *waylandScreenFromWindow(QWindow *window); private: @@ -98,7 +94,6 @@ private: int m_outputId; QWaylandDisplay *mWaylandDisplay; - QWaylandExtendedOutput *mExtendedOutput; QRect mGeometry; int mScale; int mDepth; diff --git a/src/client/qwaylandsubsurface.cpp b/src/client/qwaylandsubsurface.cpp index 81cfef25..ec813609 100644 --- a/src/client/qwaylandsubsurface.cpp +++ b/src/client/qwaylandsubsurface.cpp @@ -41,45 +41,18 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { -QWaylandSubSurface::QWaylandSubSurface(QWaylandWindow *window, struct ::qt_sub_surface *sub_surface) - : QtWayland::qt_sub_surface(sub_surface) +QWaylandSubSurface::QWaylandSubSurface(QWaylandWindow *window, QWaylandWindow *parent, ::wl_subsurface *sub_surface) + : QtWayland::wl_subsurface(sub_surface) , m_window(window) + , m_parent(parent) { + m_parent->mChildren << this; + set_desync(); } -void QWaylandSubSurface::setParent(const QWaylandWindow *parent) +QWaylandSubSurface::~QWaylandSubSurface() { - QWaylandSubSurface *parentSurface = parent ? parent->subSurfaceWindow() : 0; - if (parentSurface) { - int x = m_window->geometry().x() + parent->frameMargins().left(); - int y = m_window->geometry().y() + parent->frameMargins().top(); - parentSurface->attach_sub_surface(object(), x, y); - } -} - -static void setPositionToParent(QWaylandWindow *parentWaylandWindow) -{ - QObjectList children = parentWaylandWindow->window()->children(); - for (int i = 0; i < children.size(); i++) { - QWindow *childWindow = qobject_cast<QWindow *>(children.at(i)); - if (!childWindow) - continue; - - if (childWindow->handle()) { - QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(childWindow->handle()); - waylandWindow->subSurfaceWindow()->setParent(parentWaylandWindow); - setPositionToParent(waylandWindow); - } - } -} - -void QWaylandSubSurface::adjustPositionOfChildren() -{ - QWindow *window = m_window->window(); - if (window->parent()) { - qDebug() << "QWaylandSubSurface::adjustPositionOfChildren not called for toplevel window"; - } - setPositionToParent(m_window); + m_parent->mChildren.removeOne(this); } } diff --git a/src/client/qwaylandsubsurface_p.h b/src/client/qwaylandsubsurface_p.h index 23233085..75d8cf6a 100644 --- a/src/client/qwaylandsubsurface_p.h +++ b/src/client/qwaylandsubsurface_p.h @@ -39,8 +39,7 @@ #include <QtCore/qglobal.h> #include <QtWaylandClient/private/qwaylandclientexport_p.h> - -#include <QtWaylandClient/private/qwayland-sub-surface-extension.h> +#include <QtWaylandClient/private/qwayland-wayland.h> QT_BEGIN_NAMESPACE @@ -48,18 +47,19 @@ namespace QtWaylandClient { class QWaylandDisplay; class QWaylandWindow; -class QWaylandSubSurface; -class Q_WAYLAND_CLIENT_EXPORT QWaylandSubSurface : public QtWayland::qt_sub_surface +class Q_WAYLAND_CLIENT_EXPORT QWaylandSubSurface : public QtWayland::wl_subsurface { public: - QWaylandSubSurface(QWaylandWindow *window, struct ::qt_sub_surface *sub_surface); + QWaylandSubSurface(QWaylandWindow *window, QWaylandWindow *parent, ::wl_subsurface *subsurface); + ~QWaylandSubSurface(); - void setParent(const QWaylandWindow *parent); - void adjustPositionOfChildren(); + QWaylandWindow *window() const { return m_window; } + QWaylandWindow *parent() const { return m_parent; } private: QWaylandWindow *m_window; + QWaylandWindow *m_parent; }; QT_END_NAMESPACE diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index b98dd9da..ed7b656d 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -86,21 +86,49 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mMask() , mBackingStore(Q_NULLPTR) { - init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this))); - static WId id = 1; mWindowId = id++; - if (mDisplay->subSurfaceExtension()) - mSubSurfaceWindow = new QWaylandSubSurface(this, mDisplay->subSurfaceExtension()->get_sub_surface_aware_surface(object())); + initWindow(); +} + +QWaylandWindow::~QWaylandWindow() +{ + delete mWindowDecoration; + + if (isInitialized()) + reset(); - if (!(window->flags() & Qt::BypassWindowManagerHint)) { + QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices(); + for (int i = 0; i < inputDevices.size(); ++i) + inputDevices.at(i)->handleWindowDestroyed(this); + + const QWindow *parent = window(); + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + if (w->transientParent() == parent) + QWindowSystemInterface::handleCloseEvent(w); + } + + if (mMouseGrab == this) { + mMouseGrab = 0; + } +} + +void QWaylandWindow::initWindow() +{ + init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this))); + if (QPlatformWindow::parent()) { + QWaylandWindow *p = static_cast<QWaylandWindow *>(QPlatformWindow::parent()); + if (::wl_subsurface *ss = mDisplay->createSubSurface(this, p)) { + mSubSurfaceWindow = new QWaylandSubSurface(this, p, ss); + } + } else if (!(window()->flags() & Qt::BypassWindowManagerHint)) { mShellSurface = mDisplay->createShellSurface(this); } if (mShellSurface) { // Set initial surface title - mShellSurface->setTitle(window->title()); + mShellSurface->setTitle(window()->title()); // The appId is the desktop entry identifier that should follow the // reverse DNS convention (see http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html), @@ -122,14 +150,15 @@ QWaylandWindow::QWaylandWindow(QWindow *window) } } - if (QPlatformWindow::parent() && mSubSurfaceWindow) { - mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(QPlatformWindow::parent())); - } else if (window->transientParent() && mShellSurface) { - if (window->type() != Qt::Popup) { - mShellSurface->updateTransientParent(window->transientParent()); + if (mShellSurface) { + if (window()->transientParent()) { + if (window()->type() != Qt::Popup) { + mShellSurface->updateTransientParent(window()->transientParent()); + } + } else { + if (window()->type() != Qt::ToolTip) + mShellSurface->setTopLevel(); } - } else if (mShellSurface && window->type() != Qt::ToolTip) { - mShellSurface->setTopLevel(); } // Enable high-dpi rendering. Scale() returns the screen scale factor and will @@ -138,38 +167,25 @@ QWaylandWindow::QWaylandWindow(QWindow *window) if (mDisplay->compositorVersion() >= 3) set_buffer_scale(scale()); - setOrientationMask(window->screen()->orientationUpdateMask()); - setWindowFlags(window->flags()); - setGeometry_helper(window->geometry()); - setMask(window->mask()); - setWindowStateInternal(window->windowState()); - handleContentOrientationChange(window->contentOrientation()); + if (QScreen *s = window()->screen()) + setOrientationMask(s->orientationUpdateMask()); + setWindowFlags(window()->flags()); + setGeometry_helper(window()->geometry()); + setMask(window()->mask()); + setWindowStateInternal(window()->windowState()); + handleContentOrientationChange(window()->contentOrientation()); } -QWaylandWindow::~QWaylandWindow() +void QWaylandWindow::reset() { - delete mWindowDecoration; + delete mShellSurface; + mShellSurface = 0; + delete mSubSurfaceWindow; + mSubSurfaceWindow = 0; + destroy(); - if (isInitialized()) { - delete mShellSurface; - destroy(); - } if (mFrameCallback) wl_callback_destroy(mFrameCallback); - - QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices(); - for (int i = 0; i < inputDevices.size(); ++i) - inputDevices.at(i)->handleWindowDestroyed(this); - - const QWindow *parent = window(); - foreach (QWindow *w, QGuiApplication::topLevelWindows()) { - if (w->transientParent() == parent) - QWindowSystemInterface::handleCloseEvent(w); - } - - if (mMouseGrab == this) { - mMouseGrab = 0; - } } QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface) @@ -184,9 +200,17 @@ WId QWaylandWindow::winId() const void QWaylandWindow::setParent(const QPlatformWindow *parent) { - const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent); - if (subSurfaceWindow()) { - subSurfaceWindow()->setParent(parentWaylandWindow); + QWaylandWindow *oldparent = mSubSurfaceWindow ? mSubSurfaceWindow->parent() : 0; + if (oldparent == parent) + return; + + if (mSubSurfaceWindow && parent) { // new parent, but we were a subsurface already + delete mSubSurfaceWindow; + QWaylandWindow *p = const_cast<QWaylandWindow *>(static_cast<const QWaylandWindow *>(parent)); + mSubSurfaceWindow = new QWaylandSubSurface(this, p, mDisplay->createSubSurface(this, p)); + } else { // we're changing role, need to make a new wl_surface + reset(); + initWindow(); } } @@ -214,7 +238,10 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect) qBound(window()->minimumWidth(), rect.width(), window()->maximumWidth()), qBound(window()->minimumHeight(), rect.height(), window()->maximumHeight()))); - if (shellSurface() && window()->transientParent() && window()->type() != Qt::Popup) + if (mSubSurfaceWindow) { + QMargins m = QPlatformWindow::parent()->frameMargins(); + mSubSurfaceWindow->set_position(rect.x() + m.left(), rect.y() + m.top()); + } else if (shellSurface() && window()->transientParent() && window()->type() != Qt::Popup) shellSurface()->updateTransientParent(window()->transientParent()); } @@ -547,7 +574,10 @@ bool QWaylandWindow::createDecoration() decoration = false; if (window()->flags() & Qt::BypassWindowManagerHint) decoration = false; + if (mSubSurfaceWindow) + decoration = false; + bool hadDecoration = mWindowDecoration; if (decoration && !decorationPluginFailed) { if (!mWindowDecoration) { QStringList decorations = QWaylandDecorationFactory::keys(); @@ -578,15 +608,20 @@ bool QWaylandWindow::createDecoration() return false; } mWindowDecoration->setWaylandWindow(this); - if (subSurfaceWindow()) { - subSurfaceWindow()->adjustPositionOfChildren(); - } } } else { delete mWindowDecoration; mWindowDecoration = 0; } + if (hadDecoration != (bool)mWindowDecoration) { + foreach (QWaylandSubSurface *subsurf, mChildren) { + QPoint pos = subsurf->window()->geometry().topLeft(); + QMargins m = frameMargins(); + subsurf->set_position(pos.x() + m.left(), pos.y() + m.top()); + } + } + return mWindowDecoration; } diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 1898c495..6b9af103 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -190,6 +190,7 @@ protected: QWaylandDisplay *mDisplay; QWaylandShellSurface *mShellSurface; QWaylandSubSurface *mSubSurfaceWindow; + QVector<QWaylandSubSurface *> mChildren; QWaylandAbstractDecoration *mWindowDecoration; bool mMouseEventsInContentArea; @@ -223,6 +224,8 @@ protected: private: bool setWindowStateInternal(Qt::WindowState flags); void setGeometry_helper(const QRect &rect); + void initWindow(); + void reset(); void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e); @@ -231,6 +234,8 @@ private: static QMutex mFrameSyncMutex; static QWaylandWindow *mMouseGrab; + + friend class QWaylandSubSurface; }; inline QIcon QWaylandWindow::windowIcon() const diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h index 213474fa..103a1b38 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 28e8f9d4..04d1c4ae 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 fe48db06..1817fa07 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 ef78c884..c8edcb6b 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 e5ecb15b..a8dc41fd 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 653d74c1..db1e1fb4 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 35577737..cddd231d 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 93cfaf00..0c48df38 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 f057542c..f8c8bdc1 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 1efbd2ee..7360e7dc 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 dbcbb57b..00000000 --- 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 8d030dd9..00000000 --- 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 1c6a1417..50cc5bb7 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 e3c37009..8af6232a 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 59b69a3c..06096566 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 2ace8c00..c4df3126 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 ba9338d3..0cbe166e 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 1bf6e01f..b85081e8 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 beb11d09..b2725462 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 2b7f21ae..d23c6aeb 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 103b5994..d08fb4cd 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 ac34ae28..eb66f694 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 diff --git a/src/extensions/output-extension.xml b/src/extensions/output-extension.xml deleted file mode 100644 index b1a2f4db..00000000 --- a/src/extensions/output-extension.xml +++ /dev/null @@ -1,51 +0,0 @@ -<protocol name="output_extension"> - - <copyright> - Copyright (C) 2015 The Qt Company Ltd. - Contact: http://www.qt.io/licensing/ - - This file is part of the plugins of the Qt Toolkit. - - $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$ - </copyright> - - <interface name="qt_output_extension" version="1"> - <request name="get_extended_output"> - <arg name="id" type="new_id" interface="qt_extended_output"/> - <arg name="output" type="object" interface="wl_output"/> - </request> - </interface> - - <interface name="qt_extended_output" version="1"> - - </interface> -</protocol> diff --git a/src/shared/qwaylandxkb.cpp b/src/shared/qwaylandxkb.cpp new file mode 100644 index 00000000..c947902b --- /dev/null +++ b/src/shared/qwaylandxkb.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Jolla Ltd +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandxkb.h" + +#include <QString> + +#ifndef QT_NO_WAYLAND_XKB + +#include <xkbcommon/xkbcommon-keysyms.h> + +QT_BEGIN_NAMESPACE + +static const uint32_t KeyTbl[] = { + XKB_KEY_Escape, Qt::Key_Escape, + XKB_KEY_Tab, Qt::Key_Tab, + XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab, + XKB_KEY_BackSpace, Qt::Key_Backspace, + XKB_KEY_Return, Qt::Key_Return, + XKB_KEY_Insert, Qt::Key_Insert, + XKB_KEY_Delete, Qt::Key_Delete, + XKB_KEY_Clear, Qt::Key_Delete, + XKB_KEY_Pause, Qt::Key_Pause, + XKB_KEY_Print, Qt::Key_Print, + + XKB_KEY_Home, Qt::Key_Home, + XKB_KEY_End, Qt::Key_End, + XKB_KEY_Left, Qt::Key_Left, + XKB_KEY_Up, Qt::Key_Up, + XKB_KEY_Right, Qt::Key_Right, + XKB_KEY_Down, Qt::Key_Down, + XKB_KEY_Prior, Qt::Key_PageUp, + XKB_KEY_Next, Qt::Key_PageDown, + + XKB_KEY_Shift_L, Qt::Key_Shift, + XKB_KEY_Shift_R, Qt::Key_Shift, + XKB_KEY_Shift_Lock, Qt::Key_Shift, + XKB_KEY_Control_L, Qt::Key_Control, + XKB_KEY_Control_R, Qt::Key_Control, + XKB_KEY_Meta_L, Qt::Key_Meta, + XKB_KEY_Meta_R, Qt::Key_Meta, + XKB_KEY_Alt_L, Qt::Key_Alt, + XKB_KEY_Alt_R, Qt::Key_Alt, + XKB_KEY_Caps_Lock, Qt::Key_CapsLock, + XKB_KEY_Num_Lock, Qt::Key_NumLock, + XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock, + XKB_KEY_Super_L, Qt::Key_Super_L, + XKB_KEY_Super_R, Qt::Key_Super_R, + XKB_KEY_Menu, Qt::Key_Menu, + XKB_KEY_Hyper_L, Qt::Key_Hyper_L, + XKB_KEY_Hyper_R, Qt::Key_Hyper_R, + XKB_KEY_Help, Qt::Key_Help, + + XKB_KEY_KP_Space, Qt::Key_Space, + XKB_KEY_KP_Tab, Qt::Key_Tab, + XKB_KEY_KP_Enter, Qt::Key_Enter, + XKB_KEY_KP_Home, Qt::Key_Home, + XKB_KEY_KP_Left, Qt::Key_Left, + XKB_KEY_KP_Up, Qt::Key_Up, + XKB_KEY_KP_Right, Qt::Key_Right, + XKB_KEY_KP_Down, Qt::Key_Down, + XKB_KEY_KP_Prior, Qt::Key_PageUp, + XKB_KEY_KP_Next, Qt::Key_PageDown, + XKB_KEY_KP_End, Qt::Key_End, + XKB_KEY_KP_Begin, Qt::Key_Clear, + XKB_KEY_KP_Insert, Qt::Key_Insert, + XKB_KEY_KP_Delete, Qt::Key_Delete, + XKB_KEY_KP_Equal, Qt::Key_Equal, + XKB_KEY_KP_Multiply, Qt::Key_Asterisk, + XKB_KEY_KP_Add, Qt::Key_Plus, + XKB_KEY_KP_Separator, Qt::Key_Comma, + XKB_KEY_KP_Subtract, Qt::Key_Minus, + XKB_KEY_KP_Decimal, Qt::Key_Period, + XKB_KEY_KP_Divide, Qt::Key_Slash, + + XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr, + XKB_KEY_Multi_key, Qt::Key_Multi_key, + XKB_KEY_Codeinput, Qt::Key_Codeinput, + XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate, + XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate, + XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate, + + XKB_KEY_Mode_switch, Qt::Key_Mode_switch, + XKB_KEY_script_switch, Qt::Key_Mode_switch, + + 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 +}; + +static int lookupKeysym(xkb_keysym_t key) +{ + int code = 0; + int i = 0; + while (KeyTbl[i]) { + if (key == KeyTbl[i]) { + code = (int)KeyTbl[i+1]; + break; + } + i += 2; + } + + return code; +} + +int QWaylandXkb::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) +{ + int code = 0; + + if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) { + code = Qt::Key_F1 + (int(keysym) - XKB_KEY_F1); + } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) { + if (keysym >= XKB_KEY_KP_0) { + // numeric keypad keys + code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0); + } else { + code = lookupKeysym(keysym); + } + modifiers |= Qt::KeypadModifier; + } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f + && text.unicode()->unicode() != 0x7f + && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_currency)) { + code = text.unicode()->toUpper().unicode(); + } else { + // any other keys + code = lookupKeysym(keysym); + } + + return code; +} + +Qt::KeyboardModifiers QWaylandXkb::modifiers(struct xkb_state *state) +{ + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + + xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED | XKB_STATE_LOCKED); + + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, cstate)) + modifiers |= Qt::ShiftModifier; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, cstate)) + modifiers |= Qt::ControlModifier; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, cstate)) + modifiers |= Qt::AltModifier; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, cstate)) + modifiers |= Qt::MetaModifier; + + return modifiers; +} + +QT_END_NAMESPACE + +#endif // QT_NO_WAYLAND_XKB diff --git a/src/client/qwaylandextendedoutput.cpp b/src/shared/qwaylandxkb.h index d1e8ffe2..91e69ab0 100644 --- a/src/client/qwaylandextendedoutput.cpp +++ b/src/shared/qwaylandxkb.h @@ -1,7 +1,8 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2015 Jolla Ltd +** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. ** @@ -31,23 +32,25 @@ ** ****************************************************************************/ -#include "qwaylandextendedoutput_p.h" +#ifndef QWAYLANDXKB_H +#define QWAYLANDXKB_H -#include "qwaylandscreen_p.h" +#ifndef QT_NO_WAYLAND_XKB -#include <qpa/qwindowsysteminterface.h> - -#include <QtCore/QDebug> +#include <Qt> +#include <xkbcommon/xkbcommon.h> QT_BEGIN_NAMESPACE -namespace QtWaylandClient { - -QWaylandExtendedOutput::QWaylandExtendedOutput(QWaylandScreen *screen, ::qt_extended_output *extended_output) - : QtWayland::qt_extended_output(extended_output) +class QWaylandXkb { - Q_UNUSED(screen); -} +public: + static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text); + static Qt::KeyboardModifiers modifiers(struct xkb_state *state); +}; -} QT_END_NAMESPACE + +#endif // QT_NO_WAYLAND_XKB + +#endif diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp index 8932374c..c30ebc02 100644 --- a/tests/auto/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/tst_compositor.cpp @@ -251,6 +251,9 @@ void tst_WaylandCompositor::frameCallback() { bufferRef = ref; } + void unmap() Q_DECL_OVERRIDE + { + } QImage image() const { |