diff options
author | Jan Arne Petersen <jan.petersen@kdab.com> | 2013-09-11 23:04:02 +0200 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@digia.com> | 2013-11-22 15:46:05 +0100 |
commit | 3194cb5c75a8a7e6deab8709fb9f39accc86b2af (patch) | |
tree | 39eb6020e9d6e10ec40a2041920b08c18585e705 /src/plugins/platforms | |
parent | c83b4313b34b142750601ac95c10015bb9993ce8 (diff) |
Add support for text protocol to platform plugin
Change-Id: I57b3efdc6f8200337afb58925b23896a8d8c7d1e
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/plugins/platforms')
8 files changed, 378 insertions, 5 deletions
diff --git a/src/plugins/platforms/wayland_common/qwaylandcursor.cpp b/src/plugins/platforms/wayland_common/qwaylandcursor.cpp index e0abba304..05ab6d496 100644 --- a/src/plugins/platforms/wayland_common/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandcursor.cpp @@ -133,6 +133,11 @@ void QWaylandDisplay::setCursor(struct wl_buffer *buffer, struct wl_cursor_image } } +QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const +{ + return mInputDevices.isEmpty() ? 0 : mInputDevices.first(); +} + void QWaylandCursor::pointerEvent(const QMouseEvent &event) { mLastPos = event.globalPos(); diff --git a/src/plugins/platforms/wayland_common/qwaylanddisplay.cpp b/src/plugins/platforms/wayland_common/qwaylanddisplay.cpp index 12be111dd..9f2d58390 100644 --- a/src/plugins/platforms/wayland_common/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland_common/qwaylanddisplay.cpp @@ -61,6 +61,8 @@ #include "qwaylandtouch.h" #include "qwaylandqtkey.h" +#include "qwayland-text.h" + #include <QtCore/QAbstractEventDispatcher> #include <QtGui/private/qguiapplication_p.h> @@ -243,6 +245,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin mTouchExtension = new QWaylandTouchExtension(this, id); } else if (interface == "qt_key_extension") { mQtKeyExtension = new QWaylandQtKeyExtension(this, id); + } else if (interface == "wl_text_input_manager") { + mTextInputManager = new QtWayland::wl_text_input_manager(registry, id); } foreach (Listener l, mRegistryListeners) diff --git a/src/plugins/platforms/wayland_common/qwaylanddisplay.h b/src/plugins/platforms/wayland_common/qwaylanddisplay.h index 6b2cc89d6..5916a5b41 100644 --- a/src/plugins/platforms/wayland_common/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland_common/qwaylanddisplay.h @@ -73,6 +73,7 @@ namespace QtWayland { class qt_shell; class qt_sub_surface_extension; class qt_surface_extension; + class wl_text_input_manager; } typedef void (*RegistryListener)(void *data, @@ -112,6 +113,7 @@ public: QtWayland::wl_shell *shell() { return mShell; } QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; } + QWaylandInputDevice *defaultInputDevice() const; QWaylandInputDevice *lastKeyboardFocusInputDevice() const; void setLastKeyboardFocusInputDevice(QWaylandInputDevice *device); @@ -122,6 +124,7 @@ public: QtWayland::qt_sub_surface_extension *subSurfaceExtension() const { return mSubSurfaceExtension; } QtWayland::qt_output_extension *outputExtension() const { return mOutputExtension; } QWaylandTouchExtension *touchExtension() const { return mTouchExtension; } + QtWayland::wl_text_input_manager *textInputManager() const { return mTextInputManager; } /* wl_registry_add_listener does not add but rather sets a listener, so this function is used * to enable many listeners at once. */ @@ -163,6 +166,7 @@ private: QWaylandTouchExtension *mTouchExtension; QWaylandQtKeyExtension *mQtKeyExtension; QWaylandWindowManagerIntegration *mWindowManagerIntegration; + QtWayland::wl_text_input_manager *mTextInputManager; QSocketNotifier *mReadNotifier; int mFd; diff --git a/src/plugins/platforms/wayland_common/qwaylandinputcontext.cpp b/src/plugins/platforms/wayland_common/qwaylandinputcontext.cpp new file mode 100644 index 000000000..d7b2ca896 --- /dev/null +++ b/src/plugins/platforms/wayland_common/qwaylandinputcontext.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Compositor. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandinputcontext.h" + +#include <QGuiApplication> +#include <QWindow> +#include <xkbcommon/xkbcommon.h> + +#include "qwaylanddisplay.h" +#include "qwaylandinputdevice.h" +#include "qwaylandwindow.h" + +QT_BEGIN_NAMESPACE + +static Qt::Key toQtKey(uint32_t sym) +{ + switch (static_cast<xkb_keysym_t>(sym)) { + case XKB_KEY_BackSpace: + return Qt::Key_Backspace; + case XKB_KEY_Return: + return Qt::Key_Return; + case XKB_KEY_Left: + return Qt::Key_Left; + case XKB_KEY_Up: + return Qt::Key_Up; + case XKB_KEY_Right: + return Qt::Key_Right; + case XKB_KEY_Down: + return Qt::Key_Down; + default: + return Qt::Key_unknown; + } +} + +static QEvent::Type toQEventType(uint32_t state) +{ + switch (static_cast<wl_keyboard_key_state>(state)) { + default: + case WL_KEYBOARD_KEY_STATE_PRESSED: + return QEvent::KeyPress; + case WL_KEYBOARD_KEY_STATE_RELEASED: + return QEvent::KeyRelease; + } +} + +QWaylandTextInput::QWaylandTextInput(struct ::wl_text_input *text_input) + : QtWayland::wl_text_input(text_input) + , m_commit() + , m_serial(0) + , m_resetSerial(0) +{ +} + +QString QWaylandTextInput::commitString() const +{ + return m_commit; +} + +void QWaylandTextInput::reset() +{ + wl_text_input::reset(); + updateState(); + m_resetSerial = m_serial; +} + +void QWaylandTextInput::updateState() +{ + if (!QGuiApplication::focusObject()) + return; + + QInputMethodQueryEvent event(Qt::ImQueryAll); + QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event); + + const QString &text = event.value(Qt::ImSurroundingText).toString(); + const int cursor = event.value(Qt::ImCursorPosition).toInt(); + const int anchor = event.value(Qt::ImAnchorPosition).toInt(); + + set_surrounding_text(text, text.leftRef(cursor).toUtf8().size(), text.leftRef(anchor).toUtf8().size()); + + commit_state(++m_serial); +} + +void QWaylandTextInput::text_input_commit_string(uint32_t serial, const QString &text) +{ + if (!QGuiApplication::focusObject()) + return; + + QInputMethodEvent event; + event.setCommitString(text); + QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event); +} + +void QWaylandTextInput::text_input_enter(wl_surface *) +{ + updateState(); + m_resetSerial = m_serial; +} + +void QWaylandTextInput::text_input_leave() +{ +} + +void QWaylandTextInput::text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) +{ + if (!QGuiApplication::focusObject()) + return; + + // TODO: Convert modifiers to Qt::KeyboardModifiers. + QKeyEvent event(toQEventType(state), toQtKey(sym), Qt::NoModifier); + QCoreApplication::sendEvent(qGuiApp->focusWindow(), &event); +} + +QWaylandInputContext::QWaylandInputContext(QWaylandDisplay *display) + : QPlatformInputContext() + , mDisplay(display) + , mTextInput() +{ +} + +bool QWaylandInputContext::isValid() const +{ + return mDisplay->textInputManager() != 0; +} + +void QWaylandInputContext::reset() +{ + if (!ensureTextInput()) + return; + + mTextInput->reset(); +} + +void QWaylandInputContext::commit() +{ + if (!ensureTextInput()) + return; + + if (!QGuiApplication::focusObject()) + return; + + QInputMethodEvent event; + event.setCommitString(mTextInput->commitString()); + QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event); + + mTextInput->reset(); +} + +void QWaylandInputContext::update(Qt::InputMethodQueries queries) +{ + if (!ensureTextInput()) + return; + + mTextInput->updateState(); +} + +void QWaylandInputContext::invokeAction(QInputMethod::Action, int cursorPosition) +{ + if (!ensureTextInput()) + return; + + mTextInput->invoke_action(0, cursorPosition); // FIXME button, to UTF8 cursor position +} + +void QWaylandInputContext::showInputPanel() +{ + if (!ensureTextInput()) + return; + + mTextInput->show_input_panel(); +} + +void QWaylandInputContext::hideInputPanel() +{ + if (!ensureTextInput()) + return; + + mTextInput->hide_input_panel(); +} + +bool QWaylandInputContext::isInputPanelVisible() const +{ + return false; +} + +void QWaylandInputContext::setFocusObject(QObject *object) +{ + if (!ensureTextInput()) + return; + + if (!object) { + mTextInput->deactivate(mDisplay->defaultInputDevice()->wl_seat()); + return; + } + + QWindow *window = QGuiApplication::focusWindow(); + if (!window || !window->handle()) + return; + + struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object(); + mTextInput->activate(mDisplay->defaultInputDevice()->wl_seat(), surface); +} + +bool QWaylandInputContext::ensureTextInput() +{ + if (mTextInput) + return true; + + if (!isValid()) + return false; + + mTextInput.reset(new QWaylandTextInput(mDisplay->textInputManager()->create_text_input())); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/wayland_common/qwaylandinputcontext.h b/src/plugins/platforms/wayland_common/qwaylandinputcontext.h new file mode 100644 index 000000000..43284eb9e --- /dev/null +++ b/src/plugins/platforms/wayland_common/qwaylandinputcontext.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Compositor. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDINPUTCONTEXT_H +#define QWAYLANDINPUTCONTEXT_H + +#include <qpa/qplatforminputcontext.h> + +#include <qwayland-text.h> + +QT_BEGIN_NAMESPACE + +class QWaylandDisplay; + +class QWaylandTextInput : public QtWayland::wl_text_input +{ +public: + QWaylandTextInput(struct ::wl_text_input *text_input); + + QString commitString() const; + + void reset(); + void updateState(); + +protected: + void text_input_commit_string(uint32_t serial, const QString &text) Q_DECL_OVERRIDE; + void text_input_enter(wl_surface *surface) Q_DECL_OVERRIDE; + void text_input_leave() Q_DECL_OVERRIDE; + void text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers); + +private: + QString m_commit; + + uint32_t m_serial; + uint32_t m_resetSerial; +}; + +class QWaylandInputContext : public QPlatformInputContext +{ + Q_OBJECT +public: + explicit QWaylandInputContext(QWaylandDisplay *display); + + bool isValid() const Q_DECL_OVERRIDE; + + void reset() Q_DECL_OVERRIDE; + void commit() Q_DECL_OVERRIDE; + void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE; + void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE; + + void showInputPanel() Q_DECL_OVERRIDE; + void hideInputPanel() Q_DECL_OVERRIDE; + bool isInputPanelVisible() const Q_DECL_OVERRIDE; + + void setFocusObject(QObject *object) Q_DECL_OVERRIDE; + +private: + bool ensureTextInput(); + + QWaylandDisplay *mDisplay; + QScopedPointer<QWaylandTextInput> mTextInput; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDINPUTCONTEXT_H diff --git a/src/plugins/platforms/wayland_common/qwaylandintegration.cpp b/src/plugins/platforms/wayland_common/qwaylandintegration.cpp index 5160d66f0..78494b543 100644 --- a/src/plugins/platforms/wayland_common/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandintegration.cpp @@ -42,6 +42,7 @@ #include "qwaylandintegration.h" #include "qwaylanddisplay.h" +#include "qwaylandinputcontext.h" #include "qwaylandshmbackingstore.h" #include "qwaylandshmwindow.h" #include "qwaylandnativeinterface.h" @@ -116,7 +117,7 @@ QWaylandIntegration::QWaylandIntegration() foreach (QPlatformScreen *screen, mDisplay->screens()) screenAdded(screen); - mInputContext = QPlatformInputContextFactory::create(); + mInputContext.reset(new QWaylandInputContext(mDisplay)); } QWaylandIntegration::~QWaylandIntegration() @@ -209,7 +210,7 @@ QPlatformDrag *QWaylandIntegration::drag() const QPlatformInputContext *QWaylandIntegration::inputContext() const { - return mInputContext; + return mInputContext.data(); } QVariant QWaylandIntegration::styleHint(StyleHint hint) const diff --git a/src/plugins/platforms/wayland_common/qwaylandintegration.h b/src/plugins/platforms/wayland_common/qwaylandintegration.h index e9f8b73ad..9a6b7cd2c 100644 --- a/src/plugins/platforms/wayland_common/qwaylandintegration.h +++ b/src/plugins/platforms/wayland_common/qwaylandintegration.h @@ -91,7 +91,7 @@ private: QPlatformDrag *mDrag; QWaylandDisplay *mDisplay; QPlatformNativeInterface *mNativeInterface; - QPlatformInputContext *mInputContext; + QScopedPointer<QPlatformInputContext> mInputContext; QPlatformAccessibility *mAccessibility; }; diff --git a/src/plugins/platforms/wayland_common/wayland_common.pro b/src/plugins/platforms/wayland_common/wayland_common.pro index 45fc7ce6e..fc00c7c3e 100644 --- a/src/plugins/platforms/wayland_common/wayland_common.pro +++ b/src/plugins/platforms/wayland_common/wayland_common.pro @@ -26,7 +26,8 @@ SOURCES += qwaylandintegration.cpp \ ../../../shared/qwaylandmimehelper.cpp \ qwaylanddecoration.cpp \ qwaylandeventthread.cpp\ - qwaylandwindowmanagerintegration.cpp + qwaylandwindowmanagerintegration.cpp \ + qwaylandinputcontext.cpp HEADERS += qwaylandintegration.h \ qwaylandnativeinterface.h \ @@ -52,7 +53,8 @@ HEADERS += qwaylandintegration.h \ ../../../shared/qwaylandmimehelper.h \ qwaylanddecoration.h \ qwaylandeventthread.h \ - qwaylandwindowmanagerintegration.h + qwaylandwindowmanagerintegration.h \ + qwaylandinputcontext.h contains(DEFINES, QT_WAYLAND_GL_SUPPORT) { SOURCES += qwaylandglintegration.cpp @@ -67,6 +69,7 @@ WAYLANDCLIENTSOURCES += \ ../../../extensions/touch-extension.xml \ ../../../extensions/qtkey-extension.xml \ ../../../extensions/windowmanager.xml \ + ../../../3rdparty/protocol/text.xml \ PLUGIN_TYPE = platforms |