diff options
Diffstat (limited to 'src/compositor/compositor_api/qwaylandinput.cpp')
-rw-r--r-- | src/compositor/compositor_api/qwaylandinput.cpp | 405 |
1 files changed, 328 insertions, 77 deletions
diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp index 4e106f5fe..be566c70d 100644 --- a/src/compositor/compositor_api/qwaylandinput.cpp +++ b/src/compositor/compositor_api/qwaylandinput.cpp @@ -3,52 +3,135 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** $QT_BEGIN_LICENSE:LGPL3$ +** 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. ** -** "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. +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** -** 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." +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qwaylandinput.h" +#include "qwaylandinput_p.h" -#include "qwlinputdevice_p.h" -#include "qwlkeyboard_p.h" #include "qwaylandcompositor.h" -#include "qwlsurface_p.h" -#include "qwlcompositor_p.h" -#include "qwaylandsurfaceview.h" +#include "qwaylandview.h" +#include <QtWaylandCompositor/QWaylandDrag> +#include <QtWaylandCompositor/QWaylandTouch> +#include <QtWaylandCompositor/QWaylandPointer> +#include <QtWaylandCompositor/private/qwlinputmethod_p.h> +#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwldatadevice_p.h> + +#include "extensions/qwlqtkey_p.h" QT_BEGIN_NAMESPACE +QWaylandInputDevicePrivate::QWaylandInputDevicePrivate(QWaylandInputDevice *inputdevice, QWaylandCompositor *compositor) + : QObjectPrivate() + , QtWaylandServer::wl_seat(compositor->display(), 3) + , compositor(compositor) + , mouseFocus(Q_NULLPTR) + , capabilities() + , data_device() + , drag_handle(new QWaylandDrag(inputdevice)) +{ +} + +QWaylandInputDevicePrivate::~QWaylandInputDevicePrivate() +{ +} + +void QWaylandInputDevicePrivate::setCapabilities(QWaylandInputDevice::CapabilityFlags caps) +{ + Q_Q(QWaylandInputDevice); + if (capabilities != caps) { + QWaylandInputDevice::CapabilityFlags changed = caps ^ capabilities; + + if (changed & QWaylandInputDevice::Pointer) { + pointer.reset(pointer.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreatePointerDevice(q) : 0); + } + + if (changed & QWaylandInputDevice::Keyboard) { + keyboard.reset(keyboard.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateKeyboardDevice(q) : 0); + } + + if (changed & QWaylandInputDevice::Touch) { + touch.reset(touch.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateTouchDevice(q) : 0); + } + + capabilities = caps; + QList<Resource *> resources = resourceMap().values(); + for (int i = 0; i < resources.size(); i++) { + wl_seat::send_capabilities(resources.at(i)->handle, (uint32_t)capabilities); + } + } +} + +void QWaylandInputDevicePrivate::clientRequestedDataDevice(QtWayland::DataDeviceManager *, struct wl_client *client, uint32_t id) +{ + Q_Q(QWaylandInputDevice); + if (!data_device) + data_device.reset(new QtWayland::DataDevice(q)); + data_device->add(client, id, 1); +} + +void QWaylandInputDevicePrivate::seat_destroy_resource(wl_seat::Resource *) +{ +// cleanupDataDeviceForClient(resource->client(), true); +} + +void QWaylandInputDevicePrivate::seat_bind_resource(wl_seat::Resource *resource) +{ + // The order of capabilities matches the order defined in the wayland protocol + wl_seat::send_capabilities(resource->handle, (uint32_t)capabilities); +} + +void QWaylandInputDevicePrivate::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) +{ + if (!pointer.isNull()) { + pointer->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); + } +} + +void QWaylandInputDevicePrivate::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) +{ + if (!keyboard.isNull()) { + keyboard->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); + } +} + +void QWaylandInputDevicePrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t id) +{ + if (!touch.isNull()) { + touch->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); + } +} + QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, const QString &options, const QString &model, const QString &rules) : m_layout(layout) , m_variant(variant) @@ -59,134 +142,302 @@ QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, co } +/*! + * \class QWaylandInputDevice + * \inmodule QtWaylandCompositor + * \brief The QWaylandInputDevice class provides access to keyboard, mouse and touch input. + * + * The QWaylandInputDevice provides access to different types of user input and maintains + * a keyboard focus and a mouse pointer. It corresponds to the wl_seat interface in the Wayland protocol. + */ -QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags caps) - : d(new QtWayland::InputDevice(this,compositor->handle(), caps)) -{ -} +/*! + * \enum QWaylandInputDevice::CapabilityFlag + * + * This enum type describes the capabilities of a QWaylandInputDevice. + * + * \value Pointer The QWaylandInputDevice supports pointer input. + * \value Keyboard The QWaylandInputDevice supports keyboard input. + * \value Touch The QWaylandInputDevice supports touch input. + */ -QWaylandInputDevice::~QWaylandInputDevice() +/*! + * Constructs a QWaylandInputDevice for the given \a compositor and with the given \a capabilityFlags. + */ +QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags) + : QWaylandObject(*new QWaylandInputDevicePrivate(this,compositor)) { - delete d; + d_func()->setCapabilities(capabilityFlags); } -void QWaylandInputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) +/*! + * Destroys the QWaylandInputDevice + */ +QWaylandInputDevice::~QWaylandInputDevice() { - d->sendMousePressEvent(button,localPos,globalPos); } -void QWaylandInputDevice::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) +/*! + * Sends a mouse press event for \a button to the QWaylandInputDevice's pointer device. + */ +void QWaylandInputDevice::sendMousePressEvent(Qt::MouseButton button) { - d->sendMouseReleaseEvent(button,localPos,globalPos); + Q_D(QWaylandInputDevice); + d->pointer->sendMousePressEvent(button); } -void QWaylandInputDevice::sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos) +/*! + * Sends a mouse release event for \a button to the QWaylandInputDevice's pointer device. + */ +void QWaylandInputDevice::sendMouseReleaseEvent(Qt::MouseButton button) { - d->sendMouseMoveEvent(localPos,globalPos); + Q_D(QWaylandInputDevice); + d->pointer->sendMouseReleaseEvent(button); } -/** Convenience function that will set the mouse focus to the surface, then send the mouse move event. - * If the mouse focus is the same surface as the surface passed in, then only the move event is sent +/*! + * Sets the mouse focus to \a view and sends a mouse move event to the pointer device with the + * local position \a localPos and output space position \a outputSpacePos. **/ -void QWaylandInputDevice::sendMouseMoveEvent(QWaylandSurfaceView *surface, const QPointF &localPos, const QPointF &globalPos) +void QWaylandInputDevice::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos) { - d->sendMouseMoveEvent(surface,localPos,globalPos); + Q_D(QWaylandInputDevice); + d->pointer->sendMouseMoveEvent(view, localPos, outputSpacePos); } +/*! + * Sends a mouse wheel event to the QWaylandInputDevice's pointer device with the given \a orientation and \a delta. + */ void QWaylandInputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta) { - d->sendMouseWheelEvent(orientation, delta); + Q_D(QWaylandInputDevice); + d->pointer->sendMouseWheelEvent(orientation, delta); } +/*! + * Sends a key press event with the key \a code to the keyboard device. + */ void QWaylandInputDevice::sendKeyPressEvent(uint code) { - d->keyboardDevice()->sendKeyPressEvent(code); + Q_D(QWaylandInputDevice); + d->keyboard->sendKeyPressEvent(code); } +/*! + * Sends a key release event with the key \a code to the keyboard device. + */ void QWaylandInputDevice::sendKeyReleaseEvent(uint code) { - d->keyboardDevice()->sendKeyReleaseEvent(code); + Q_D(QWaylandInputDevice); + d->keyboard->sendKeyReleaseEvent(code); } -void QWaylandInputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state) +/*! + * Sends a touch point event with the given \a id and \a state to the touch device. The position + * of the touch point is given by \a point. + */ +void QWaylandInputDevice::sendTouchPointEvent(int id, const QPointF &point, Qt::TouchPointState state) { - d->sendTouchPointEvent(id,x,y,state); + Q_D(QWaylandInputDevice); + if (d->touch.isNull()) { + return; + } + d->touch->sendTouchPointEvent(id, point,state); } +/*! + * Sends a frame event to the touch device. + */ void QWaylandInputDevice::sendTouchFrameEvent() { - d->sendTouchFrameEvent(); + Q_D(QWaylandInputDevice); + if (!d->touch.isNull()) { + d->touch->sendFrameEvent(); + } } +/*! + * Sends a cancel event to the touch device. + */ void QWaylandInputDevice::sendTouchCancelEvent() { - d->sendTouchCancelEvent(); + Q_D(QWaylandInputDevice); + if (!d->touch.isNull()) { + d->touch->sendCancelEvent(); + } } +/*! + * Sends the \a event to the touch device. + */ void QWaylandInputDevice::sendFullTouchEvent(QTouchEvent *event) { - d->sendFullTouchEvent(event); + Q_D(QWaylandInputDevice); + if (!mouseFocus()) { + qWarning("Cannot send touch event, no pointer focus, fix the compositor"); + return; + } + + if (!d->touch) + return; + + d->touch->sendFullTouchEvent(event); } +/*! + * Sends the \a event to the keyboard device. + */ void QWaylandInputDevice::sendFullKeyEvent(QKeyEvent *event) { - d->sendFullKeyEvent(event); + Q_D(QWaylandInputDevice); + if (!keyboardFocus()) { + qWarning("Cannot send key event, no keyboard focus, fix the compositor"); + return; + } + + QtWayland::QtKeyExtensionGlobal *ext = QtWayland::QtKeyExtensionGlobal::findIn(d->compositor); + if (ext && ext->postQtKeyEvent(event, keyboardFocus())) + return; + + if (!d->keyboard.isNull() && !event->isAutoRepeat()) { + if (event->type() == QEvent::KeyPress) + d->keyboard->sendKeyPressEvent(event->nativeScanCode()); + else if (event->type() == QEvent::KeyRelease) + d->keyboard->sendKeyReleaseEvent(event->nativeScanCode()); + } } -void QWaylandInputDevice::sendFullKeyEvent(QWaylandSurface *surface, QKeyEvent *event) +/*! + * Returns the keyboard for this input device. + */ +QWaylandKeyboard *QWaylandInputDevice::keyboard() const { - d->sendFullKeyEvent(surface->handle(), event); + Q_D(const QWaylandInputDevice); + return d->keyboard.data(); } +/*! + * Returns the current focused surface for keyboard input. + */ QWaylandSurface *QWaylandInputDevice::keyboardFocus() const { - QtWayland::Surface *wlsurface = d->keyboardFocus(); - if (wlsurface) - return wlsurface->waylandSurface(); - return 0; + Q_D(const QWaylandInputDevice); + if (d->keyboard.isNull() || !d->keyboard->focus()) + return Q_NULLPTR; + + return d->keyboard->focus(); } +/*! + * Sets the current keyboard focus to \a surface. + */ bool QWaylandInputDevice::setKeyboardFocus(QWaylandSurface *surface) { - QtWayland::Surface *wlsurface = surface?surface->handle():0; - return d->setKeyboardFocus(wlsurface); + Q_D(QWaylandInputDevice); + if (surface && surface->isDestroyed()) + return false; + + if (surface == keyboardFocus()) + return true; + + if (!d->keyboard.isNull() && d->keyboard->setFocus(surface)) { + if (d->data_device) + d->data_device->setFocus(d->keyboard->focusClient()); + return true; + } + return false; } +/*! + * Sets the key map of this QWaylandInputDevice to \a keymap. + */ void QWaylandInputDevice::setKeymap(const QWaylandKeymap &keymap) { - if (handle()->keyboardDevice()) - handle()->keyboardDevice()->setKeymap(keymap); + if (keyboard()) + keyboard()->setKeymap(keymap); } -QWaylandSurfaceView *QWaylandInputDevice::mouseFocus() const +/*! + * Returns the pointer device for this QWaylandInputDevice. + */ +QWaylandPointer *QWaylandInputDevice::pointer() const { - return d->mouseFocus(); + Q_D(const QWaylandInputDevice); + return d->pointer.data(); } -void QWaylandInputDevice::setMouseFocus(QWaylandSurfaceView *surface, const QPointF &localPos, const QPointF &globalPos) +/*! + * Returns the view that currently has mouse focus. + */ +QWaylandView *QWaylandInputDevice::mouseFocus() const { - d->setMouseFocus(surface,localPos,globalPos); + Q_D(const QWaylandInputDevice); + return d->mouseFocus; } +/*! + * Sets the current mouse focus to \a view. + */ +void QWaylandInputDevice::setMouseFocus(QWaylandView *view) +{ + Q_D(QWaylandInputDevice); + if (view == d->mouseFocus) + return; + + QWaylandView *oldFocus = d->mouseFocus; + d->mouseFocus = view; + emit mouseFocusChanged(d->mouseFocus, oldFocus); +} + +/*! + * Returns the compositor for this QWaylandInputDevice. + */ QWaylandCompositor *QWaylandInputDevice::compositor() const { - return d->compositor()->waylandCompositor(); + Q_D(const QWaylandInputDevice); + return d->compositor; } -QtWayland::InputDevice *QWaylandInputDevice::handle() const +/*! + * Returns the drag object for this QWaylandInputDevice. + */ +QWaylandDrag *QWaylandInputDevice::drag() const { - return d; + Q_D(const QWaylandInputDevice); + return d->drag_handle.data(); } -QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() +/*! + * Returns the capability flags for this QWaylandInputDevice. + */ +QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() const { - return d->capabilities(); + Q_D(const QWaylandInputDevice); + return d->capabilities; } -bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent) +/*! + * \internal + */ +bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent) const { Q_UNUSED(inputEvent); return true; } +/*! + * Returns the QWaylandInputDevice corresponding to the \a resource. The \a resource is expected + * to have the type wl_seat. + */ +QWaylandInputDevice *QWaylandInputDevice::fromSeatResource(struct ::wl_resource *resource) +{ + return static_cast<QWaylandInputDevicePrivate *>(QWaylandInputDevicePrivate::Resource::fromResource(resource)->seat_object)->q_func(); +} + +/*! + * \fn void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) + * + * This signal is emitted when the mouse focus has changed from \a oldFocus to \a newFocus. + */ + QT_END_NAMESPACE |