Skip to content
Snippets Groups Projects
Commit 083ece74 authored by Laszlo Agocs's avatar Laszlo Agocs Committed by Jørgen Lind
Browse files

Add mouse event synthesizing to the touch extension protocol.


The compositor can now be configured to tell the clients to generate
mouse events when receiving touch events. In touchscreen-only systems
this can be used to reduce the number of Wayland events.

Change-Id: I231a15cd4ed463ee81c510c082a270efa255a1f3
Reviewed-by: default avatarJørgen Lind <jorgen.lind@nokia.com>
parent a39e3710
No related branches found
No related tags found
No related merge requests found
Showing with 85 additions and 10 deletions
......@@ -39,6 +39,7 @@
****************************************************************************/
#include "qopenglwindow.h"
#include <QTouchEvent>
QOpenGLWindow::QOpenGLWindow(const QSurfaceFormat &format, const QRect &geometry)
: m_format(format)
......@@ -51,3 +52,10 @@ QOpenGLWindow::QOpenGLWindow(const QSurfaceFormat &format, const QRect &geometry
m_context->setFormat(format);
m_context->create();
}
void QOpenGLWindow::touchEvent(QTouchEvent *event)
{
// Do not want any automatically synthesized mouse events
// so make sure the touch is always accepted.
event->accept();
}
......@@ -53,7 +53,8 @@ public:
QOpenGLContext* context() { return m_context; }
bool makeCurrent() { return m_context->makeCurrent(this); }
void swapBuffers() { m_context->swapBuffers(this); }
protected:
void touchEvent(QTouchEvent *event);
private:
QOpenGLContext *m_context;
QSurfaceFormat m_format;
......
......@@ -58,6 +58,11 @@ QWindowCompositor::QWindowCompositor(QOpenGLWindow *window)
// using a custom protocol extension.
// enableTouchExtension();
// Enable the following to have mouse events generated from touch
// on client side. This is not the same as synthesizing mouse events
// in the compositor because it avoids sending data through the wire.
// configureTouchExtension(WaylandCompositor::TouchExtMouseFromTouch);
enableSubSurfaceExtension();
m_window->makeCurrent();
......
......@@ -56,6 +56,14 @@
<arg name="rawdata" type="array" />
</event>
<enum name="flags">
<entry name="mouse_from_touch" value="0x1" />
</enum>
<event name="configure">
<arg name="flags" type="uint" />
</event>
<request name="dummy">
</request>
......
......@@ -193,3 +193,8 @@ void WaylandCompositor::enableTouchExtension()
{
m_compositor->enableTouchExtension();
}
void WaylandCompositor::configureTouchExtension(TouchExtensionFlags flags)
{
m_compositor->configureTouchExtension(flags);
}
......@@ -95,6 +95,11 @@ public:
void enableSubSurfaceExtension();
void enableTouchExtension();
enum TouchExtensionFlag {
TouchExtMouseFromTouch = 0x01
};
Q_DECLARE_FLAGS(TouchExtensionFlags, TouchExtensionFlag)
void configureTouchExtension(TouchExtensionFlags flags);
private:
static void retainedSelectionChanged(QMimeData *mimeData, void *param);
......@@ -104,4 +109,6 @@ private:
QByteArray m_socket_name;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(WaylandCompositor::TouchExtensionFlags)
#endif // QTCOMP_H
......@@ -384,6 +384,12 @@ void Compositor::enableTouchExtension()
}
}
void Compositor::configureTouchExtension(int flags)
{
if (m_touchExtension)
m_touchExtension->setFlags(flags);
}
void Compositor::setRetainedSelectionWatcher(RetainedSelectionFunc func, void *param)
{
m_retainNotify = func;
......
......@@ -119,6 +119,7 @@ public:
void enableTouchExtension();
TouchExtensionGlobal *touchExtension() { return m_touchExtension; }
void configureTouchExtension(int flags);
bool isDragging() const;
void sendDragMoveEvent(const QPoint &global, const QPoint &local, Surface *surface);
......
......@@ -56,7 +56,8 @@ const struct wl_touch_extension_interface TouchExtensionGlobal::touch_interface
static const int maxRawPos = 24;
TouchExtensionGlobal::TouchExtensionGlobal(Compositor *compositor)
: m_compositor(compositor)
: m_compositor(compositor),
m_flags(0)
{
wl_array_init(&m_rawdata_array);
m_rawdata_ptr = static_cast<float *>(wl_array_add(&m_rawdata_array, maxRawPos * sizeof(float) * 2));
......@@ -86,6 +87,7 @@ void TouchExtensionGlobal::bind_func(wl_client *client, void *data, uint32_t ver
resource->destroy = destroy_resource;
TouchExtensionGlobal *self = static_cast<TouchExtensionGlobal *>(resource->data);
self->m_resources.append(resource);
wl_resource_post_event(resource, WL_TOUCH_EXTENSION_CONFIGURE, self->m_flags);
}
static inline int toFixed(qreal f)
......
......@@ -59,9 +59,9 @@ public:
void postTouchEvent(QTouchEvent *event, Surface *surface);
private:
Compositor *m_compositor;
void setFlags(int flags) { m_flags = flags; }
private:
static void bind_func(struct wl_client *client, void *data,
uint32_t version, uint32_t id);
......@@ -69,6 +69,8 @@ private:
static const struct wl_touch_extension_interface touch_interface;
Compositor *m_compositor;
int m_flags;
QList<wl_resource *> m_resources;
wl_array m_rawdata_array;
float *m_rawdata_ptr;
......
......@@ -48,6 +48,8 @@ QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_
{
mDisplay = display;
mPointsLeft = 0;
mFlags = 0;
mTouch = static_cast<struct wl_touch_extension *>(wl_display_bind(display->wl_display(), id, &wl_touch_extension_interface));
wl_touch_extension_add_listener(mTouch, &touch_listener, this);
......@@ -92,6 +94,7 @@ void QWaylandTouchExtension::handle_touch(void *data, wl_touch_extension *ext, u
qWarning("wl_touch_extension: handle_touch: No pointer focus");
return;
}
self->mTargetWindow = win->window();
QWindowSystemInterface::TouchPoint tp;
tp.id = id;
......@@ -107,7 +110,7 @@ void QWaylandTouchExtension::handle_touch(void *data, wl_touch_extension *ext, u
// Got surface-relative coords but need a (virtual) screen position.
QPointF relPos = QPointF(fromFixed(x), fromFixed(y));
QPointF delta = relPos - relPos.toPoint();
tp.area.moveCenter(win->window()->mapToGlobal(relPos.toPoint()) + delta);
tp.area.moveCenter(self->mTargetWindow->mapToGlobal(relPos.toPoint()) + delta);
tp.normalPosition.setX(fromFixed(normalized_x));
tp.normalPosition.setY(fromFixed(normalized_y));
......@@ -159,20 +162,41 @@ void QWaylandTouchExtension::sendTouchEvent()
QWindowSystemInterface::handleTouchEvent(0, mTimestamp, mTouchDevice, mTouchPoints);
bool allReleased = true;
Qt::TouchPointStates states = 0;
for (int i = 0; i < mTouchPoints.count(); ++i)
if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
allReleased = false;
break;
states |= mTouchPoints.at(i).state;
if (mFlags & WL_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH) {
if (states == Qt::TouchPointPressed)
mMouseSourceId = mTouchPoints.first().id;
for (int i = 0; i < mTouchPoints.count(); ++i) {
const QWindowSystemInterface::TouchPoint &tp(mTouchPoints.at(i));
if (tp.id == mMouseSourceId) {
Qt::MouseButtons buttons = tp.state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton;
QPointF globalPos = tp.area.center();
QPointF delta = globalPos - globalPos.toPoint();
QPointF localPos = mTargetWindow->mapFromGlobal(globalPos.toPoint()) + delta;
QWindowSystemInterface::handleMouseEvent(0, mTimestamp, localPos, globalPos, buttons);
break;
}
}
}
mPrevTouchPoints = mTouchPoints;
mTouchPoints.clear();
if (allReleased)
if (states == Qt::TouchPointReleased)
mPrevTouchPoints.clear();
}
void QWaylandTouchExtension::handle_configure(void *data, wl_touch_extension *ext, uint32_t flags)
{
Q_UNUSED(ext);
QWaylandTouchExtension *self = static_cast<QWaylandTouchExtension *>(data);
self->mFlags = flags;
}
const struct wl_touch_extension_listener QWaylandTouchExtension::touch_listener = {
QWaylandTouchExtension::handle_touch,
QWaylandTouchExtension::handle_configure
};
......@@ -73,6 +73,9 @@ private:
int32_t velocity_y,
uint32_t flags,
struct wl_array *rawdata);
static void handle_configure(void *data,
struct wl_touch_extension *ext,
uint32_t flags);
void sendTouchEvent();
......@@ -81,6 +84,9 @@ private:
QTouchDevice *mTouchDevice;
uint32_t mTimestamp;
int mPointsLeft;
uint32_t mFlags;
int mMouseSourceId;
QWindow *mTargetWindow;
};
#endif // QWAYLANDTOUCH_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment