Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
This commit is contained in:
commit
44950f9b00
@ -141,7 +141,7 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
|
||||
}
|
||||
|
||||
int pipefd[2];
|
||||
if (qt_safe_pipe(pipefd, O_NONBLOCK) == -1) {
|
||||
if (qt_safe_pipe(pipefd) == -1) {
|
||||
qWarning("QWaylandMimeData: pipe2() failed");
|
||||
return QVariant();
|
||||
}
|
||||
@ -163,23 +163,32 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
|
||||
|
||||
int QWaylandMimeData::readData(int fd, QByteArray &data) const
|
||||
{
|
||||
char buf[4096];
|
||||
int retryCount = 0;
|
||||
int n;
|
||||
while (true) {
|
||||
n = QT_READ(fd, buf, sizeof buf);
|
||||
if (n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && ++retryCount < 1000)
|
||||
usleep(1000);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (retryCount >= 1000)
|
||||
fd_set readset;
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(fd, &readset);
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout);
|
||||
if (ready < 0) {
|
||||
qWarning() << "QWaylandDataOffer: select() failed";
|
||||
return -1;
|
||||
} else if (ready == 0) {
|
||||
qWarning("QWaylandDataOffer: timeout reading from pipe");
|
||||
if (n > 0) {
|
||||
data.append(buf, n);
|
||||
n = readData(fd, data);
|
||||
return -1;
|
||||
} else {
|
||||
char buf[4096];
|
||||
int n = QT_READ(fd, buf, sizeof buf);
|
||||
|
||||
if (n > 0) {
|
||||
data.append(buf, n);
|
||||
n = readData(fd, data);
|
||||
} else if (n < 0) {
|
||||
qWarning("QWaylandDataOffer: read() failed");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -189,9 +189,9 @@ void QWaylandDisplay::checkError() const
|
||||
int ecode = wl_display_get_error(mDisplay);
|
||||
if ((ecode == EPIPE || ecode == ECONNRESET)) {
|
||||
// special case this to provide a nicer error
|
||||
qWarning("The Wayland connection broke. Did the Wayland compositor die?");
|
||||
qFatal("The Wayland connection broke. Did the Wayland compositor die?");
|
||||
} else {
|
||||
qErrnoWarning(ecode, "The Wayland connection experienced a fatal error");
|
||||
qFatal("The Wayland connection experienced a fatal error: %s", strerror(ecode));
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,25 +201,16 @@ void QWaylandDisplay::flushRequests()
|
||||
wl_display_read_events(mDisplay);
|
||||
}
|
||||
|
||||
if (wl_display_dispatch_pending(mDisplay) < 0) {
|
||||
if (wl_display_dispatch_pending(mDisplay) < 0)
|
||||
checkError();
|
||||
exitWithError();
|
||||
}
|
||||
|
||||
wl_display_flush(mDisplay);
|
||||
}
|
||||
|
||||
void QWaylandDisplay::blockingReadEvents()
|
||||
{
|
||||
if (wl_display_dispatch(mDisplay) < 0) {
|
||||
if (wl_display_dispatch(mDisplay) < 0)
|
||||
checkError();
|
||||
exitWithError();
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandDisplay::exitWithError()
|
||||
{
|
||||
::exit(1);
|
||||
}
|
||||
|
||||
wl_event_queue *QWaylandDisplay::createEventQueue()
|
||||
@ -248,10 +239,9 @@ void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bo
|
||||
else
|
||||
wl_display_cancel_read(mDisplay);
|
||||
|
||||
if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0) {
|
||||
if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0)
|
||||
checkError();
|
||||
exitWithError();
|
||||
}
|
||||
|
||||
if (!condition())
|
||||
break;
|
||||
}
|
||||
|
@ -208,7 +208,6 @@ public slots:
|
||||
|
||||
private:
|
||||
void waitForScreens();
|
||||
void exitWithError();
|
||||
void checkError() const;
|
||||
|
||||
void handleWaylandSync();
|
||||
|
@ -442,6 +442,21 @@ QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice
|
||||
return new Touch(device);
|
||||
}
|
||||
|
||||
QWaylandInputDevice::Keyboard *QWaylandInputDevice::keyboard() const
|
||||
{
|
||||
return mKeyboard;
|
||||
}
|
||||
|
||||
QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const
|
||||
{
|
||||
return mPointer;
|
||||
}
|
||||
|
||||
QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const
|
||||
{
|
||||
return mTouch;
|
||||
}
|
||||
|
||||
void QWaylandInputDevice::handleEndDrag()
|
||||
{
|
||||
if (mTouch)
|
||||
@ -774,8 +789,10 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
|
||||
|
||||
void QWaylandInputDevice::Pointer::invalidateFocus()
|
||||
{
|
||||
disconnect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
|
||||
mFocus = nullptr;
|
||||
if (mFocus) {
|
||||
disconnect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
|
||||
mFocus = nullptr;
|
||||
}
|
||||
mEnterSerial = 0;
|
||||
}
|
||||
|
||||
@ -1028,8 +1045,15 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
|
||||
|
||||
void QWaylandInputDevice::Pointer::flushFrameEvent()
|
||||
{
|
||||
if (mFrameData.event) {
|
||||
mFrameData.event->surface->handleMouse(mParent, *mFrameData.event);
|
||||
if (auto *event = mFrameData.event) {
|
||||
if (auto window = event->surface) {
|
||||
window->handleMouse(mParent, *event);
|
||||
} else if (mFrameData.event->type == QWaylandPointerEvent::Type::Release) {
|
||||
// If the window has been destroyed, we still need to report an up event, but it can't
|
||||
// be handled by the destroyed window (obviously), so send the event here instead.
|
||||
QWindowSystemInterface::handleMouseEvent(nullptr, event->timestamp, event->local,
|
||||
event->global, event->buttons, event->modifiers);
|
||||
}
|
||||
delete mFrameData.event;
|
||||
mFrameData.event = nullptr;
|
||||
}
|
||||
|
@ -148,6 +148,10 @@ public:
|
||||
virtual Pointer *createPointer(QWaylandInputDevice *device);
|
||||
virtual Touch *createTouch(QWaylandInputDevice *device);
|
||||
|
||||
Keyboard *keyboard() const;
|
||||
Pointer *pointer() const;
|
||||
Touch *touch() const;
|
||||
|
||||
private:
|
||||
QWaylandDisplay *mQDisplay = nullptr;
|
||||
struct wl_display *mDisplay = nullptr;
|
||||
@ -248,6 +252,8 @@ public:
|
||||
|
||||
Qt::KeyboardModifiers modifiers() const;
|
||||
|
||||
struct ::wl_keyboard *wl_keyboard() { return QtWayland::wl_keyboard::object(); }
|
||||
|
||||
private slots:
|
||||
void handleFocusDestroyed();
|
||||
void handleFocusLost();
|
||||
@ -284,6 +290,8 @@ public:
|
||||
#endif
|
||||
QWaylandInputDevice *seat() const { return mParent; }
|
||||
|
||||
struct ::wl_pointer *wl_pointer() { return QtWayland::wl_pointer::object(); }
|
||||
|
||||
protected:
|
||||
void pointer_enter(uint32_t serial, struct wl_surface *surface,
|
||||
wl_fixed_t sx, wl_fixed_t sy) override;
|
||||
@ -377,6 +385,8 @@ public:
|
||||
bool allTouchPointsReleased();
|
||||
void releasePoints();
|
||||
|
||||
struct ::wl_touch *wl_touch() { return QtWayland::wl_touch::object(); }
|
||||
|
||||
QWaylandInputDevice *mParent = nullptr;
|
||||
QPointer<QWaylandWindow> mFocus;
|
||||
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
|
||||
@ -436,7 +446,7 @@ public:
|
||||
QPoint pixelDelta;
|
||||
QPoint angleDelta;
|
||||
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
|
||||
QWaylandWindow *surface = nullptr;
|
||||
QPointer<QWaylandWindow> surface;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -310,11 +310,14 @@ QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) co
|
||||
return GenericWaylandTheme::createUnixTheme(name);
|
||||
}
|
||||
|
||||
// May be called from non-GUI threads
|
||||
QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() const
|
||||
{
|
||||
if (!mClientBufferIntegrationInitialized)
|
||||
// Do an inexpensive check first to avoid locking whenever possible
|
||||
if (Q_UNLIKELY(!mClientBufferIntegrationInitialized))
|
||||
const_cast<QWaylandIntegration *>(this)->initializeClientBufferIntegration();
|
||||
|
||||
Q_ASSERT(mClientBufferIntegrationInitialized);
|
||||
return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr;
|
||||
}
|
||||
|
||||
@ -334,9 +337,12 @@ QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const
|
||||
return mShellIntegration.data();
|
||||
}
|
||||
|
||||
// May be called from non-GUI threads
|
||||
void QWaylandIntegration::initializeClientBufferIntegration()
|
||||
{
|
||||
mClientBufferIntegrationInitialized = true;
|
||||
QMutexLocker lock(&mClientBufferInitLock);
|
||||
if (mClientBufferIntegrationInitialized)
|
||||
return;
|
||||
|
||||
QString targetKey = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION"));
|
||||
|
||||
@ -352,22 +358,25 @@ void QWaylandIntegration::initializeClientBufferIntegration()
|
||||
|
||||
if (targetKey.isEmpty()) {
|
||||
qWarning("Failed to determine what client buffer integration to use");
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList keys = QWaylandClientBufferIntegrationFactory::keys();
|
||||
qCDebug(lcQpaWayland) << "Available client buffer integrations:" << keys;
|
||||
|
||||
if (keys.contains(targetKey))
|
||||
mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()));
|
||||
|
||||
if (mClientBufferIntegration) {
|
||||
qCDebug(lcQpaWayland) << "Initializing client buffer integration" << targetKey;
|
||||
mClientBufferIntegration->initialize(mDisplay.data());
|
||||
} else {
|
||||
qCWarning(lcQpaWayland) << "Failed to load client buffer integration:" << targetKey;
|
||||
qCWarning(lcQpaWayland) << "Available client buffer integrations:" << keys;
|
||||
QStringList keys = QWaylandClientBufferIntegrationFactory::keys();
|
||||
qCDebug(lcQpaWayland) << "Available client buffer integrations:" << keys;
|
||||
|
||||
if (keys.contains(targetKey))
|
||||
mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()));
|
||||
|
||||
if (mClientBufferIntegration) {
|
||||
qCDebug(lcQpaWayland) << "Initializing client buffer integration" << targetKey;
|
||||
mClientBufferIntegration->initialize(mDisplay.data());
|
||||
} else {
|
||||
qCWarning(lcQpaWayland) << "Failed to load client buffer integration:" << targetKey;
|
||||
qCWarning(lcQpaWayland) << "Available client buffer integrations:" << keys;
|
||||
}
|
||||
}
|
||||
|
||||
// This must be set last to make sure other threads don't use the
|
||||
// integration before initialization is complete.
|
||||
mClientBufferIntegrationInitialized = true;
|
||||
}
|
||||
|
||||
void QWaylandIntegration::initializeServerBufferIntegration()
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <QtWaylandClient/qtwaylandclientglobal.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -152,6 +153,7 @@ private:
|
||||
mutable QScopedPointer<QPlatformAccessibility> mAccessibility;
|
||||
#endif
|
||||
bool mFailed = false;
|
||||
QMutex mClientBufferInitLock;
|
||||
bool mClientBufferIntegrationInitialized = false;
|
||||
bool mServerBufferIntegrationInitialized = false;
|
||||
bool mShellIntegrationInitialized = false;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "qwaylanddisplay_p.h"
|
||||
#include "qwaylandwindowmanagerintegration_p.h"
|
||||
#include "qwaylandscreen_p.h"
|
||||
#include "qwaylandinputdevice_p.h"
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
|
||||
@ -76,6 +77,27 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re
|
||||
if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration())
|
||||
return m_integration->clientBufferIntegration()->nativeResource(QWaylandClientBufferIntegration::EglDisplay);
|
||||
|
||||
if (lowerCaseResource == "wl_seat")
|
||||
return m_integration->display()->defaultInputDevice()->wl_seat();
|
||||
if (lowerCaseResource == "wl_keyboard") {
|
||||
auto *keyboard = m_integration->display()->defaultInputDevice()->keyboard();
|
||||
if (keyboard)
|
||||
return keyboard->wl_keyboard();
|
||||
return nullptr;
|
||||
}
|
||||
if (lowerCaseResource == "wl_pointer") {
|
||||
auto *pointer = m_integration->display()->defaultInputDevice()->pointer();
|
||||
if (pointer)
|
||||
return pointer->wl_pointer();
|
||||
return nullptr;
|
||||
}
|
||||
if (lowerCaseResource == "wl_touch") {
|
||||
auto *touch = m_integration->display()->defaultInputDevice()->touch();
|
||||
if (touch)
|
||||
return touch->wl_touch();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -205,6 +205,7 @@ void QWaylandWindow::initializeWlSurface()
|
||||
connect(mSurface.data(), &QWaylandSurface::screensChanged,
|
||||
this, &QWaylandWindow::handleScreensChanged);
|
||||
mSurface->m_window = this;
|
||||
emit wlSurfaceCreated();
|
||||
}
|
||||
|
||||
bool QWaylandWindow::shouldCreateShellSurface() const
|
||||
|
@ -203,6 +203,7 @@ public slots:
|
||||
void applyConfigure();
|
||||
|
||||
signals:
|
||||
void wlSurfaceCreated();
|
||||
void wlSurfaceDestroyed();
|
||||
|
||||
protected:
|
||||
|
@ -51,7 +51,26 @@ class QWaylandSharedMemoryFormatHelper
|
||||
{
|
||||
public:
|
||||
static inline wl_shm_format fromQImageFormat(QImage::Format format);
|
||||
static inline QImage::Format fromWaylandShmFormat(wl_shm_format format);
|
||||
static inline QImage::Format fromWaylandShmFormat(wl_shm_format format)
|
||||
{
|
||||
switch (format) {
|
||||
case WL_SHM_FORMAT_XRGB8888: return QImage::Format_RGB32;
|
||||
case WL_SHM_FORMAT_ARGB8888: return QImage::Format_ARGB32_Premultiplied;
|
||||
case WL_SHM_FORMAT_RGB565: return QImage::Format_RGB16;
|
||||
case WL_SHM_FORMAT_XRGB1555: return QImage::Format_RGB555;
|
||||
case WL_SHM_FORMAT_RGB888: return QImage::Format_RGB888;
|
||||
case WL_SHM_FORMAT_XRGB4444: return QImage::Format_RGB444;
|
||||
case WL_SHM_FORMAT_ARGB4444: return QImage::Format_ARGB4444_Premultiplied;
|
||||
case WL_SHM_FORMAT_XBGR8888: return QImage::Format_RGBX8888;
|
||||
case WL_SHM_FORMAT_ABGR8888: return QImage::Format_RGBA8888_Premultiplied;
|
||||
case WL_SHM_FORMAT_XBGR2101010: return QImage::Format_BGR30;
|
||||
case WL_SHM_FORMAT_ABGR2101010: return QImage::Format_A2BGR30_Premultiplied;
|
||||
case WL_SHM_FORMAT_XRGB2101010: return QImage::Format_RGB30;
|
||||
case WL_SHM_FORMAT_ARGB2101010: return QImage::Format_A2RGB30_Premultiplied;
|
||||
case WL_SHM_FORMAT_C8: return QImage::Format_Alpha8;
|
||||
default: return QImage::Format_Invalid;
|
||||
}
|
||||
}
|
||||
static inline QVector<wl_shm_format> supportedWaylandFormats();
|
||||
|
||||
private:
|
||||
@ -108,16 +127,6 @@ wl_shm_format QWaylandSharedMemoryFormatHelper::fromQImageFormat(QImage::Format
|
||||
return array.data[format];
|
||||
}
|
||||
|
||||
QImage::Format QWaylandSharedMemoryFormatHelper::fromWaylandShmFormat(wl_shm_format format)
|
||||
{
|
||||
Array array = getData();
|
||||
for (size_t i = 0; i < array.size; i++) {
|
||||
if (array.data[i] == format)
|
||||
return QImage::Format(i);
|
||||
}
|
||||
return QImage::Format_Invalid;
|
||||
}
|
||||
|
||||
QVector<wl_shm_format> QWaylandSharedMemoryFormatHelper::supportedWaylandFormats()
|
||||
{
|
||||
QVector<wl_shm_format> retFormats;
|
||||
|
@ -66,7 +66,7 @@ void tst_datadevicev1::initTestCase()
|
||||
{
|
||||
QCOMPOSITOR_TRY_VERIFY(pointer());
|
||||
QCOMPOSITOR_TRY_VERIFY(!pointer()->resourceMap().empty());
|
||||
QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 4);
|
||||
QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5);
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(keyboard());
|
||||
|
||||
@ -104,8 +104,11 @@ void tst_datadevicev1::pasteAscii()
|
||||
keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
|
||||
|
||||
pointer()->sendEnter(surface, {32, 32});
|
||||
pointer()->sendFrame(client);
|
||||
pointer()->sendButton(client, BTN_LEFT, 1);
|
||||
pointer()->sendFrame(client);
|
||||
pointer()->sendButton(client, BTN_LEFT, 0);
|
||||
pointer()->sendFrame(client);
|
||||
});
|
||||
QTRY_COMPARE(window.m_text, "normal ascii");
|
||||
}
|
||||
@ -139,8 +142,11 @@ void tst_datadevicev1::pasteUtf8()
|
||||
keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
|
||||
|
||||
pointer()->sendEnter(surface, {32, 32});
|
||||
pointer()->sendFrame(client);
|
||||
pointer()->sendButton(client, BTN_LEFT, 1);
|
||||
pointer()->sendFrame(client);
|
||||
pointer()->sendButton(client, BTN_LEFT, 0);
|
||||
pointer()->sendFrame(client);
|
||||
});
|
||||
QTRY_COMPARE(window.m_text, "face with tears of joy: 😂");
|
||||
}
|
||||
|
@ -196,8 +196,11 @@ void tst_output::removePrimaryScreen()
|
||||
exec([&] {
|
||||
auto *surface = xdgToplevel()->surface();
|
||||
pointer()->sendEnter(surface, {32, 32});
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_LEFT, 1);
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_LEFT, 0);
|
||||
pointer()->sendFrame(client());
|
||||
});
|
||||
|
||||
// Wait to make sure mouse events dont't cause a crash now that the screen has changed
|
||||
|
@ -268,7 +268,7 @@ void tst_primaryselectionv1::initTestCase()
|
||||
{
|
||||
QCOMPOSITOR_TRY_VERIFY(pointer());
|
||||
QCOMPOSITOR_TRY_VERIFY(!pointer()->resourceMap().empty());
|
||||
QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 4);
|
||||
QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5);
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(keyboard());
|
||||
}
|
||||
@ -329,8 +329,11 @@ void tst_primaryselectionv1::pasteAscii()
|
||||
device->sendSelection(offer);
|
||||
|
||||
pointer()->sendEnter(surface, {32, 32});
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_MIDDLE, 1);
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_MIDDLE, 0);
|
||||
pointer()->sendFrame(client());
|
||||
});
|
||||
QTRY_COMPARE(window.m_formats, QStringList{"text/plain"});
|
||||
QTRY_COMPARE(window.m_text, "normal ascii");
|
||||
@ -372,8 +375,11 @@ void tst_primaryselectionv1::pasteUtf8()
|
||||
device->sendSelection(offer);
|
||||
|
||||
pointer()->sendEnter(surface, {32, 32});
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_MIDDLE, 1);
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_MIDDLE, 0);
|
||||
pointer()->sendFrame(client());
|
||||
});
|
||||
QTRY_COMPARE(window.m_formats, QStringList({"text/plain", "text/plain;charset=utf-8"}));
|
||||
QTRY_COMPARE(window.m_text, "face with tears of joy: 😂");
|
||||
@ -428,8 +434,11 @@ void tst_primaryselectionv1::copy()
|
||||
auto *surface = xdgSurface()->m_surface;
|
||||
keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
|
||||
pointer()->sendEnter(surface, {32, 32});
|
||||
pointer()->sendFrame(client());
|
||||
mouseSerials << pointer()->sendButton(client(), BTN_MIDDLE, 1);
|
||||
pointer()->sendFrame(client());
|
||||
mouseSerials << pointer()->sendButton(client(), BTN_MIDDLE, 0);
|
||||
pointer()->sendFrame(client());
|
||||
});
|
||||
QCOMPOSITOR_TRY_VERIFY(primarySelectionDevice()->m_selectionSource);
|
||||
QCOMPOSITOR_TRY_VERIFY(mouseSerials.contains(primarySelectionDevice()->m_serial));
|
||||
|
@ -212,22 +212,20 @@ void tst_seatv4::simpleAxis_data()
|
||||
{
|
||||
QTest::addColumn<uint>("axis");
|
||||
QTest::addColumn<qreal>("value");
|
||||
QTest::addColumn<Qt::Orientation>("orientation");
|
||||
QTest::addColumn<QPoint>("angleDelta");
|
||||
|
||||
// Directions in regular windows/linux terms (no "natural" scrolling)
|
||||
QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << Qt::Vertical << QPoint{0, -12};
|
||||
QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << Qt::Vertical << QPoint{0, 12};
|
||||
QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << Qt::Horizontal << QPoint{-12, 0};
|
||||
QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << Qt::Horizontal << QPoint{12, 0};
|
||||
QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << Qt::Vertical << QPoint{0, 120};
|
||||
QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12};
|
||||
QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12};
|
||||
QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0};
|
||||
QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0};
|
||||
QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120};
|
||||
}
|
||||
|
||||
void tst_seatv4::simpleAxis()
|
||||
{
|
||||
QFETCH(uint, axis);
|
||||
QFETCH(qreal, value);
|
||||
QFETCH(Qt::Orientation, orientation);
|
||||
QFETCH(QPoint, angleDelta);
|
||||
|
||||
class WheelWindow : QRasterWindow {
|
||||
@ -256,27 +254,18 @@ void tst_seatv4::simpleAxis()
|
||||
// We didn't press any buttons
|
||||
QCOMPARE(event->buttons(), Qt::NoButton);
|
||||
|
||||
if (event->orientation() == Qt::Horizontal)
|
||||
QCOMPARE(event->delta(), event->angleDelta().x());
|
||||
else
|
||||
QCOMPARE(event->delta(), event->angleDelta().y());
|
||||
|
||||
// There has been no information about what created the event.
|
||||
// Documentation says not synthesized is appropriate in such cases
|
||||
QCOMPARE(event->source(), Qt::MouseEventNotSynthesized);
|
||||
|
||||
m_events.append(Event(event->pixelDelta(), event->angleDelta(), event->orientation()));
|
||||
m_events.append(Event{event->pixelDelta(), event->angleDelta()});
|
||||
}
|
||||
struct Event // Because I didn't find a convenient way to copy it entirely
|
||||
{
|
||||
// TODO: Constructors can be removed when we start supporting brace-initializers
|
||||
Event() = default;
|
||||
Event(const QPoint &pixelDelta, const QPoint &angleDelta, Qt::Orientation orientation)
|
||||
: pixelDelta(pixelDelta), angleDelta(angleDelta), orientation(orientation)
|
||||
{}
|
||||
|
||||
const QPoint pixelDelta;
|
||||
const QPoint angleDelta; // eights of a degree, positive is upwards, left
|
||||
const Qt::Orientation orientation{};
|
||||
};
|
||||
QVector<Event> m_events;
|
||||
};
|
||||
@ -299,7 +288,6 @@ void tst_seatv4::simpleAxis()
|
||||
QTRY_COMPARE(window.m_events.size(), 1);
|
||||
auto event = window.m_events.takeFirst();
|
||||
QCOMPARE(event.angleDelta, angleDelta);
|
||||
QCOMPARE(event.orientation, orientation);
|
||||
}
|
||||
|
||||
void tst_seatv4::invalidPointerEvents()
|
||||
|
@ -41,18 +41,11 @@ public:
|
||||
|
||||
removeAll<Seat>();
|
||||
|
||||
uint capabilities = MockCompositor::Seat::capability_pointer;
|
||||
uint capabilities = MockCompositor::Seat::capability_pointer | MockCompositor::Seat::capability_touch;
|
||||
int version = 5;
|
||||
add<Seat>(capabilities, version);
|
||||
});
|
||||
}
|
||||
|
||||
Pointer *pointer()
|
||||
{
|
||||
auto *seat = get<Seat>();
|
||||
Q_ASSERT(seat);
|
||||
return seat->m_pointer;
|
||||
}
|
||||
};
|
||||
|
||||
class tst_seatv5 : public QObject, private SeatV5Compositor
|
||||
@ -61,6 +54,8 @@ class tst_seatv5 : public QObject, private SeatV5Compositor
|
||||
private slots:
|
||||
void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); }
|
||||
void bindsToSeat();
|
||||
|
||||
// Pointer tests
|
||||
void createsPointer();
|
||||
void setsCursorOnEnter();
|
||||
void usesEnterSerial();
|
||||
@ -69,6 +64,10 @@ private slots:
|
||||
void fingerScroll();
|
||||
void fingerScrollSlow();
|
||||
void wheelDiscreteScroll();
|
||||
|
||||
// Touch tests
|
||||
void createsTouch();
|
||||
void singleTap();
|
||||
};
|
||||
|
||||
void tst_seatv5::bindsToSeat()
|
||||
@ -128,12 +127,8 @@ public:
|
||||
QRasterWindow::wheelEvent(event);
|
||||
// qDebug() << event << "angleDelta" << event->angleDelta() << "pixelDelta" << event->pixelDelta();
|
||||
|
||||
if (event->phase() == Qt::ScrollUpdate || event->phase() == Qt::NoScrollPhase) {
|
||||
// Angle delta should always be provided (says docs, but QPA sends compatibility events
|
||||
// for Qt4 with zero angleDelta, and with a delta)
|
||||
QVERIFY(!event->angleDelta().isNull() || event->delta());
|
||||
} else {
|
||||
// Shouldn't have deltas in the other phases
|
||||
if (event->phase() != Qt::ScrollUpdate && event->phase() != Qt::NoScrollPhase) {
|
||||
// Shouldn't have deltas in the these phases
|
||||
QCOMPARE(event->angleDelta(), QPoint(0, 0));
|
||||
QCOMPARE(event->pixelDelta(), QPoint(0, 0));
|
||||
}
|
||||
@ -145,13 +140,6 @@ public:
|
||||
// We didn't press any buttons
|
||||
QCOMPARE(event->buttons(), Qt::NoButton);
|
||||
|
||||
if (!event->angleDelta().isNull()) {
|
||||
if (event->orientation() == Qt::Horizontal)
|
||||
QCOMPARE(event->delta(), event->angleDelta().x());
|
||||
else
|
||||
QCOMPARE(event->delta(), event->angleDelta().y());
|
||||
}
|
||||
|
||||
m_events.append(Event{event});
|
||||
}
|
||||
struct Event // Because I didn't find a convenient way to copy it entirely
|
||||
@ -161,14 +149,12 @@ public:
|
||||
: phase(event->phase())
|
||||
, pixelDelta(event->pixelDelta())
|
||||
, angleDelta(event->angleDelta())
|
||||
, orientation(event->orientation())
|
||||
, source(event->source())
|
||||
{
|
||||
}
|
||||
const Qt::ScrollPhase phase{};
|
||||
const QPoint pixelDelta;
|
||||
const QPoint angleDelta; // eights of a degree, positive is upwards, left
|
||||
const Qt::Orientation orientation{};
|
||||
const Qt::MouseEventSource source{};
|
||||
};
|
||||
QVector<Event> m_events;
|
||||
@ -178,22 +164,20 @@ void tst_seatv5::simpleAxis_data()
|
||||
{
|
||||
QTest::addColumn<uint>("axis");
|
||||
QTest::addColumn<qreal>("value");
|
||||
QTest::addColumn<Qt::Orientation>("orientation");
|
||||
QTest::addColumn<QPoint>("angleDelta");
|
||||
|
||||
// Directions in regular windows/linux terms (no "natural" scrolling)
|
||||
QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << Qt::Vertical << QPoint{0, -12};
|
||||
QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << Qt::Vertical << QPoint{0, 12};
|
||||
QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << Qt::Horizontal << QPoint{-12, 0};
|
||||
QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << Qt::Horizontal << QPoint{12, 0};
|
||||
QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << Qt::Vertical << QPoint{0, 120};
|
||||
QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12};
|
||||
QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12};
|
||||
QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0};
|
||||
QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0};
|
||||
QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120};
|
||||
}
|
||||
|
||||
void tst_seatv5::simpleAxis()
|
||||
{
|
||||
QFETCH(uint, axis);
|
||||
QFETCH(qreal, value);
|
||||
QFETCH(Qt::Orientation, orientation);
|
||||
QFETCH(QPoint, angleDelta);
|
||||
|
||||
WheelWindow window;
|
||||
@ -220,7 +204,6 @@ void tst_seatv5::simpleAxis()
|
||||
// There has been no information about what created the event.
|
||||
// Documentation says not synthesized is appropriate in such cases
|
||||
QCOMPARE(e.source, Qt::MouseEventNotSynthesized);
|
||||
QCOMPARE(e.orientation, orientation);
|
||||
QCOMPARE(e.angleDelta, angleDelta);
|
||||
}
|
||||
|
||||
@ -263,7 +246,7 @@ void tst_seatv5::fingerScroll()
|
||||
{
|
||||
auto e = window.m_events.takeFirst();
|
||||
QCOMPARE(e.phase, Qt::ScrollUpdate);
|
||||
QCOMPARE(e.orientation, Qt::Vertical);
|
||||
QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll
|
||||
// QCOMPARE(e.angleDelta, angleDelta); // TODO: what should this be?
|
||||
QCOMPARE(e.pixelDelta, QPoint(0, 10));
|
||||
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
|
||||
@ -281,7 +264,7 @@ void tst_seatv5::fingerScroll()
|
||||
{
|
||||
auto e = window.m_events.takeFirst();
|
||||
QCOMPARE(e.phase, Qt::ScrollUpdate);
|
||||
QCOMPARE(e.orientation, Qt::Horizontal);
|
||||
QVERIFY(qAbs(e.angleDelta.x()) > qAbs(e.angleDelta.y())); // Horizontal scroll
|
||||
QCOMPARE(e.pixelDelta, QPoint(10, 0));
|
||||
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
|
||||
}
|
||||
@ -373,7 +356,7 @@ void tst_seatv5::wheelDiscreteScroll()
|
||||
{
|
||||
auto e = window.m_events.takeFirst();
|
||||
QCOMPARE(e.phase, Qt::NoScrollPhase);
|
||||
QCOMPARE(e.orientation, Qt::Vertical);
|
||||
QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll
|
||||
// According to the docs the angle delta is in eights of a degree and most mice have
|
||||
// 1 click = 15 degrees. The angle delta should therefore be:
|
||||
// 15 degrees / (1/8 eights per degrees) = 120 eights of degrees.
|
||||
@ -383,5 +366,70 @@ void tst_seatv5::wheelDiscreteScroll()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_seatv5::createsTouch()
|
||||
{
|
||||
QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().size(), 1);
|
||||
QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().first()->version(), 5);
|
||||
}
|
||||
|
||||
class TouchWindow : public QRasterWindow {
|
||||
public:
|
||||
TouchWindow()
|
||||
{
|
||||
resize(64, 64);
|
||||
show();
|
||||
}
|
||||
void touchEvent(QTouchEvent *event) override
|
||||
{
|
||||
QRasterWindow::touchEvent(event);
|
||||
m_events.append(Event{event});
|
||||
}
|
||||
struct Event // Because I didn't find a convenient way to copy it entirely
|
||||
{
|
||||
explicit Event() = default;
|
||||
explicit Event(const QTouchEvent *event)
|
||||
: type(event->type())
|
||||
, touchPointStates(event->touchPointStates())
|
||||
, touchPoints(event->touchPoints())
|
||||
{
|
||||
}
|
||||
const QEvent::Type type{};
|
||||
const Qt::TouchPointStates touchPointStates{};
|
||||
const QList<QTouchEvent::TouchPoint> touchPoints;
|
||||
};
|
||||
QVector<Event> m_events;
|
||||
};
|
||||
|
||||
void tst_seatv5::singleTap()
|
||||
{
|
||||
TouchWindow window;
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
|
||||
|
||||
exec([=] {
|
||||
auto *t = touch();
|
||||
auto *c = client();
|
||||
t->sendDown(xdgToplevel()->surface(), {32, 32}, 1);
|
||||
t->sendFrame(c);
|
||||
t->sendUp(c, 1);
|
||||
t->sendFrame(c);
|
||||
});
|
||||
|
||||
QTRY_VERIFY(!window.m_events.empty());
|
||||
{
|
||||
auto e = window.m_events.takeFirst();
|
||||
QCOMPARE(e.type, QEvent::TouchBegin);
|
||||
QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointPressed);
|
||||
QCOMPARE(e.touchPoints.length(), 1);
|
||||
QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top()));
|
||||
}
|
||||
{
|
||||
auto e = window.m_events.takeFirst();
|
||||
QCOMPARE(e.type, QEvent::TouchEnd);
|
||||
QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointReleased);
|
||||
QCOMPARE(e.touchPoints.length(), 1);
|
||||
QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top()));
|
||||
}
|
||||
}
|
||||
|
||||
QCOMPOSITOR_TEST_MAIN(tst_seatv5)
|
||||
#include "tst_seatv5.moc"
|
||||
|
@ -191,12 +191,15 @@ Seat::~Seat()
|
||||
{
|
||||
qDeleteAll(m_oldPointers);
|
||||
delete m_pointer;
|
||||
|
||||
qDeleteAll(m_oldTouchs);
|
||||
delete m_touch;
|
||||
|
||||
qDeleteAll(m_oldKeyboards);
|
||||
delete m_keyboard;
|
||||
}
|
||||
|
||||
void Seat::setCapabilities(uint capabilities) {
|
||||
// TODO: Add support for touch
|
||||
Q_ASSERT(~capabilities & capability_touch);
|
||||
|
||||
m_capabilities = capabilities;
|
||||
|
||||
if (m_capabilities & capability_pointer) {
|
||||
@ -207,6 +210,14 @@ void Seat::setCapabilities(uint capabilities) {
|
||||
m_pointer = nullptr;
|
||||
}
|
||||
|
||||
if (m_capabilities & capability_touch) {
|
||||
if (!m_touch)
|
||||
m_touch = (new Touch(this));
|
||||
} else if (m_touch) {
|
||||
m_oldTouchs << m_touch;
|
||||
m_touch = nullptr;
|
||||
}
|
||||
|
||||
if (m_capabilities & capability_keyboard) {
|
||||
if (!m_keyboard)
|
||||
m_keyboard = (new Keyboard(this));
|
||||
@ -234,9 +245,24 @@ void Seat::seat_get_pointer(Resource *resource, uint32_t id)
|
||||
m_pointer->add(resource->client(), id, resource->version());
|
||||
}
|
||||
|
||||
void Seat::seat_get_touch(QtWaylandServer::wl_seat::Resource *resource, uint32_t id)
|
||||
{
|
||||
if (~m_capabilities & capability_touch) {
|
||||
qWarning() << "Client requested a wl_touch without the capability being available."
|
||||
<< "This Could be a race condition when hotunplugging,"
|
||||
<< "but is most likely a client error";
|
||||
Touch *touch = new Touch(this);
|
||||
touch->add(resource->client(), id, resource->version());
|
||||
// TODO: mark as destroyed
|
||||
m_oldTouchs << touch;
|
||||
return;
|
||||
}
|
||||
m_touch->add(resource->client(), id, resource->version());
|
||||
}
|
||||
|
||||
void Seat::seat_get_keyboard(QtWaylandServer::wl_seat::Resource *resource, uint32_t id)
|
||||
{
|
||||
if (~m_capabilities & capability_pointer) {
|
||||
if (~m_capabilities & capability_keyboard) {
|
||||
qWarning() << "Client requested a wl_keyboard without the capability being available."
|
||||
<< "This Could be a race condition when hotunplugging,"
|
||||
<< "but is most likely a client error";
|
||||
@ -371,6 +397,40 @@ void Pointer::pointer_set_cursor(Resource *resource, uint32_t serial, wl_resourc
|
||||
emit setCursor(serial);
|
||||
}
|
||||
|
||||
uint Touch::sendDown(Surface *surface, const QPointF &position, int id)
|
||||
{
|
||||
wl_fixed_t x = wl_fixed_from_double(position.x());
|
||||
wl_fixed_t y = wl_fixed_from_double(position.y());
|
||||
uint serial = m_seat->m_compositor->nextSerial();
|
||||
auto time = m_seat->m_compositor->currentTimeMilliseconds();
|
||||
wl_client *client = surface->resource()->client();
|
||||
|
||||
const auto touchResources = resourceMap().values(client);
|
||||
for (auto *r : touchResources)
|
||||
wl_touch::send_down(r->handle, serial, time, surface->resource()->handle, id, x, y);
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
uint Touch::sendUp(wl_client *client, int id)
|
||||
{
|
||||
uint serial = m_seat->m_compositor->nextSerial();
|
||||
auto time = m_seat->m_compositor->currentTimeMilliseconds();
|
||||
|
||||
const auto touchResources = resourceMap().values(client);
|
||||
for (auto *r : touchResources)
|
||||
wl_touch::send_up(r->handle, serial, time, id);
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
void Touch::sendFrame(wl_client *client)
|
||||
{
|
||||
const auto touchResources = resourceMap().values(client);
|
||||
for (auto *r : touchResources)
|
||||
send_frame(r->handle);
|
||||
}
|
||||
|
||||
uint Keyboard::sendEnter(Surface *surface)
|
||||
{
|
||||
auto serial = m_seat->m_compositor->nextSerial();
|
||||
|
@ -38,6 +38,7 @@ namespace MockCompositor {
|
||||
class WlCompositor;
|
||||
class Output;
|
||||
class Pointer;
|
||||
class Touch;
|
||||
class Keyboard;
|
||||
class CursorRole;
|
||||
class ShmPool;
|
||||
@ -236,7 +237,7 @@ class Seat : public Global, public QtWaylandServer::wl_seat
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Seat(CoreCompositor *compositor, uint capabilities = Seat::capability_pointer | Seat::capability_keyboard, int version = 4);
|
||||
explicit Seat(CoreCompositor *compositor, uint capabilities = Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch, int version = 5);
|
||||
~Seat() override;
|
||||
void send_capabilities(Resource *resource, uint capabilities) = delete; // Use wrapper instead
|
||||
void send_capabilities(uint capabilities) = delete; // Use wrapper instead
|
||||
@ -247,6 +248,9 @@ public:
|
||||
Pointer* m_pointer = nullptr;
|
||||
QVector<Pointer *> m_oldPointers;
|
||||
|
||||
Touch* m_touch = nullptr;
|
||||
QVector<Touch *> m_oldTouchs;
|
||||
|
||||
Keyboard* m_keyboard = nullptr;
|
||||
QVector<Keyboard *> m_oldKeyboards;
|
||||
|
||||
@ -259,8 +263,8 @@ protected:
|
||||
}
|
||||
|
||||
void seat_get_pointer(Resource *resource, uint32_t id) override;
|
||||
void seat_get_touch(Resource *resource, uint32_t id) override;
|
||||
void seat_get_keyboard(Resource *resource, uint32_t id) override;
|
||||
// void seat_get_touch(Resource *resource, uint32_t id) override;
|
||||
|
||||
// void seat_release(Resource *resource) override;
|
||||
};
|
||||
@ -307,6 +311,18 @@ public:
|
||||
Surface *m_surface = nullptr;
|
||||
};
|
||||
|
||||
class Touch : public QObject, public QtWaylandServer::wl_touch
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Touch(Seat *seat) : m_seat(seat) {}
|
||||
uint sendDown(Surface *surface, const QPointF &position, int id);
|
||||
uint sendUp(wl_client *client, int id);
|
||||
void sendFrame(wl_client *client);
|
||||
|
||||
Seat *m_seat = nullptr;
|
||||
};
|
||||
|
||||
class Keyboard : public QObject, public QtWaylandServer::wl_keyboard
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -41,7 +41,7 @@ DefaultCompositor::DefaultCompositor()
|
||||
add<SubCompositor>();
|
||||
auto *output = add<Output>();
|
||||
output->m_data.physicalSize = output->m_data.mode.physicalSizeForDpi(96);
|
||||
add<Seat>(Seat::capability_pointer | Seat::capability_keyboard);
|
||||
add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch);
|
||||
add<XdgWmBase>();
|
||||
add<Shm>();
|
||||
// TODO: other shells, viewporter, xdgoutput etc
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
XdgToplevel *xdgToplevel(int i = 0) { return get<XdgWmBase>()->toplevel(i); }
|
||||
XdgPopup *xdgPopup(int i = 0) { return get<XdgWmBase>()->popup(i); }
|
||||
Pointer *pointer() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_pointer; }
|
||||
Touch *touch() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_touch; }
|
||||
Surface *cursorSurface() { auto *p = pointer(); return p ? p->cursorSurface() : nullptr; }
|
||||
Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; }
|
||||
uint sendXdgShellPing();
|
||||
@ -84,6 +85,7 @@ public:
|
||||
int main(int argc, char **argv) \
|
||||
{ \
|
||||
setenv("XDG_RUNTIME_DIR", ".", 1); \
|
||||
setenv("XDG_CURRENT_DESKTOP", "qtwaylandtests", 1); \
|
||||
setenv("QT_QPA_PLATFORM", "wayland", 1); \
|
||||
test tc; \
|
||||
QGuiApplication app(argc, argv); \
|
||||
|
@ -214,12 +214,13 @@ void tst_xdgshell::popup()
|
||||
uint clickSerial = exec([=] {
|
||||
auto *surface = xdgToplevel()->surface();
|
||||
auto *p = pointer();
|
||||
auto *c = client();
|
||||
p->sendEnter(surface, {100, 100});
|
||||
// p->sendFrame(); //TODO: uncomment when we support seat v5
|
||||
p->sendFrame(c);
|
||||
uint serial = p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
|
||||
p->sendButton(c, BTN_LEFT, Pointer::button_state_released);
|
||||
return serial;
|
||||
// p->sendFrame(); //TODO: uncomment when we support seat v5
|
||||
p->sendFrame(c);
|
||||
});
|
||||
|
||||
QTRY_VERIFY(window.m_popup);
|
||||
@ -298,13 +299,14 @@ void tst_xdgshell::tooltipOnPopup()
|
||||
exec([=] {
|
||||
auto *surface = xdgToplevel()->surface();
|
||||
auto *p = pointer();
|
||||
auto *c = client();
|
||||
p->sendEnter(surface, {100, 100});
|
||||
// p->sendFrame(); //TODO: uncomment when we support seat v5
|
||||
p->sendFrame(c);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
p->sendLeave(surface);
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
});
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
|
||||
@ -315,11 +317,12 @@ void tst_xdgshell::tooltipOnPopup()
|
||||
exec([=] {
|
||||
auto *surface = xdgPopup()->surface();
|
||||
auto *p = pointer();
|
||||
auto *c = client();
|
||||
p->sendEnter(surface, {100, 100});
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
});
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgPopup(1));
|
||||
@ -380,13 +383,14 @@ void tst_xdgshell::switchPopups()
|
||||
exec([=] {
|
||||
auto *surface = xdgToplevel()->surface();
|
||||
auto *p = pointer();
|
||||
auto *c = client();
|
||||
p->sendEnter(surface, {100, 100});
|
||||
// p->sendFrame(); //TODO: uncomment when we support seat v5
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
p->sendButton(c, BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(c, BTN_LEFT, Pointer::button_state_released);
|
||||
p->sendFrame(c);
|
||||
p->sendLeave(surface);
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
});
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
|
||||
@ -399,11 +403,12 @@ void tst_xdgshell::switchPopups()
|
||||
exec([=] {
|
||||
auto *surface = xdgToplevel()->surface();
|
||||
auto *p = pointer();
|
||||
auto *c = client();
|
||||
p->sendEnter(surface, {100, 100});
|
||||
// p->sendFrame();
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
|
||||
// p->sendFrame();
|
||||
p->sendFrame(c);
|
||||
p->sendButton(c, BTN_LEFT, Pointer::button_state_pressed);
|
||||
p->sendButton(c, BTN_LEFT, Pointer::button_state_released);
|
||||
p->sendFrame(c);
|
||||
});
|
||||
|
||||
// The client will now hide one popup and then show another
|
||||
|
Loading…
x
Reference in New Issue
Block a user