2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2016-11-15 13:23:51 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
|
2016-11-15 13:23:51 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2016-11-15 13:23:51 +00:00
|
|
|
#include "kwin_wayland_test.h"
|
2022-03-23 10:13:38 +00:00
|
|
|
|
2016-11-15 13:23:51 +00:00
|
|
|
#include "cursor.h"
|
|
|
|
#include "keyboard_input.h"
|
2022-04-14 12:33:28 +00:00
|
|
|
#include "output.h"
|
2016-11-15 13:23:51 +00:00
|
|
|
#include "platform.h"
|
|
|
|
#include "pointer_input.h"
|
|
|
|
#include "wayland_server.h"
|
2022-04-22 17:39:12 +00:00
|
|
|
#include "window.h"
|
2016-11-15 13:23:51 +00:00
|
|
|
#include "workspace.h"
|
|
|
|
|
|
|
|
#include <KWayland/Client/compositor.h>
|
|
|
|
#include <KWayland/Client/keyboard.h>
|
|
|
|
#include <KWayland/Client/pointer.h>
|
|
|
|
#include <KWayland/Client/seat.h>
|
|
|
|
#include <KWayland/Client/shm_pool.h>
|
|
|
|
#include <KWayland/Client/surface.h>
|
2017-03-27 17:58:03 +00:00
|
|
|
#include <KWayland/Client/touch.h>
|
2016-11-15 13:23:51 +00:00
|
|
|
|
|
|
|
#include <linux/input.h>
|
|
|
|
|
|
|
|
using namespace KWin;
|
|
|
|
using namespace KWayland::Client;
|
|
|
|
|
|
|
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_window_selection-0");
|
|
|
|
|
|
|
|
class TestWindowSelection : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
|
|
void initTestCase();
|
|
|
|
void init();
|
|
|
|
void cleanup();
|
|
|
|
|
|
|
|
void testSelectOnWindowPointer();
|
|
|
|
void testSelectOnWindowKeyboard_data();
|
|
|
|
void testSelectOnWindowKeyboard();
|
2017-03-27 17:58:03 +00:00
|
|
|
void testSelectOnWindowTouch();
|
2016-11-15 13:23:51 +00:00
|
|
|
void testCancelOnWindowPointer();
|
|
|
|
void testCancelOnWindowKeyboard();
|
2016-11-23 14:53:17 +00:00
|
|
|
|
|
|
|
void testSelectPointPointer();
|
2017-03-27 17:58:03 +00:00
|
|
|
void testSelectPointTouch();
|
2016-11-15 13:23:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void TestWindowSelection::initTestCase()
|
|
|
|
{
|
2022-04-22 17:39:12 +00:00
|
|
|
qRegisterMetaType<KWin::Window *>();
|
2020-07-07 09:32:29 +00:00
|
|
|
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
|
|
|
QVERIFY(applicationStartedSpy.isValid());
|
2016-11-15 13:23:51 +00:00
|
|
|
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
2020-12-09 13:06:15 +00:00
|
|
|
QVERIFY(waylandServer()->init(s_socketName));
|
2019-08-26 21:16:53 +00:00
|
|
|
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
|
2017-09-18 19:05:34 +00:00
|
|
|
qputenv("XKB_DEFAULT_RULES", "evdev");
|
2016-11-15 13:23:51 +00:00
|
|
|
|
|
|
|
kwinApp()->start();
|
2020-07-07 09:32:29 +00:00
|
|
|
QVERIFY(applicationStartedSpy.wait());
|
2021-08-31 07:03:05 +00:00
|
|
|
const auto outputs = kwinApp()->platform()->enabledOutputs();
|
|
|
|
QCOMPARE(outputs.count(), 2);
|
|
|
|
QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
|
|
|
|
QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
|
2021-05-08 00:08:22 +00:00
|
|
|
Test::initWaylandWorkspace();
|
2016-11-15 13:23:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestWindowSelection::init()
|
|
|
|
{
|
2016-12-03 13:31:14 +00:00
|
|
|
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Seat));
|
2016-11-15 13:23:51 +00:00
|
|
|
QVERIFY(Test::waitForWaylandPointer());
|
|
|
|
|
2021-08-28 18:58:29 +00:00
|
|
|
workspace()->setActiveOutput(QPoint(640, 512));
|
2021-08-28 18:40:12 +00:00
|
|
|
KWin::Cursors::self()->mouse()->setPos(QPoint(640, 512));
|
2016-11-15 13:23:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestWindowSelection::cleanup()
|
|
|
|
{
|
|
|
|
Test::destroyWaylandConnection();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestWindowSelection::testSelectOnWindowPointer()
|
|
|
|
{
|
|
|
|
// this test verifies window selection through pointer works
|
2021-09-03 17:54:03 +00:00
|
|
|
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
|
2021-05-11 05:26:51 +00:00
|
|
|
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
|
2016-11-15 13:23:51 +00:00
|
|
|
QScopedPointer<Pointer> pointer(Test::waylandSeat()->createPointer());
|
|
|
|
QScopedPointer<Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
|
|
|
QSignalSpy pointerEnteredSpy(pointer.data(), &Pointer::entered);
|
|
|
|
QVERIFY(pointerEnteredSpy.isValid());
|
|
|
|
QSignalSpy pointerLeftSpy(pointer.data(), &Pointer::left);
|
|
|
|
QVERIFY(pointerLeftSpy.isValid());
|
|
|
|
QSignalSpy keyboardEnteredSpy(keyboard.data(), &Keyboard::entered);
|
|
|
|
QVERIFY(keyboardEnteredSpy.isValid());
|
|
|
|
QSignalSpy keyboardLeftSpy(keyboard.data(), &Keyboard::left);
|
|
|
|
QVERIFY(keyboardLeftSpy.isValid());
|
|
|
|
|
|
|
|
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
|
|
|
QVERIFY(client);
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
2020-04-02 16:18:01 +00:00
|
|
|
KWin::Cursors::self()->mouse()->setPos(client->frameGeometry().center());
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
Window *selectedWindow = nullptr;
|
|
|
|
auto callback = [&selectedWindow](Window *t) {
|
2016-11-15 13:23:51 +00:00
|
|
|
selectedWindow = t;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 0);
|
|
|
|
QVERIFY(pointerLeftSpy.wait());
|
|
|
|
if (keyboardLeftSpy.isEmpty()) {
|
|
|
|
QVERIFY(keyboardLeftSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
|
|
|
|
// simulate left button press
|
|
|
|
quint32 timestamp = 0;
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
// should not have ended the mode
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
2020-09-07 08:11:07 +00:00
|
|
|
QVERIFY(!input()->pointer()->focus());
|
2016-11-15 13:23:51 +00:00
|
|
|
|
|
|
|
// updating the pointer should not change anything
|
|
|
|
input()->pointer()->update();
|
2020-09-07 08:11:07 +00:00
|
|
|
QVERIFY(!input()->pointer()->focus());
|
2016-11-15 13:23:51 +00:00
|
|
|
// updating keyboard should also not change
|
|
|
|
input()->keyboard()->update();
|
|
|
|
|
|
|
|
// perform a right button click
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonPressed(BTN_RIGHT, timestamp++);
|
|
|
|
Test::pointerButtonReleased(BTN_RIGHT, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
// should not have ended the mode
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
// now release
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QCOMPARE(selectedWindow, client);
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
// should give back keyboard and pointer
|
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
if (keyboardEnteredSpy.count() != 2) {
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(pointerEnteredSpy.count(), 2);
|
|
|
|
QCOMPARE(keyboardEnteredSpy.count(), 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestWindowSelection::testSelectOnWindowKeyboard_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<qint32>("key");
|
|
|
|
|
|
|
|
QTest::newRow("enter") << KEY_ENTER;
|
|
|
|
QTest::newRow("keypad enter") << KEY_KPENTER;
|
|
|
|
QTest::newRow("space") << KEY_SPACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestWindowSelection::testSelectOnWindowKeyboard()
|
|
|
|
{
|
|
|
|
// this test verifies window selection through keyboard key
|
2021-09-03 17:54:03 +00:00
|
|
|
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
|
2021-05-11 05:26:51 +00:00
|
|
|
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
|
2016-11-15 13:23:51 +00:00
|
|
|
QScopedPointer<Pointer> pointer(Test::waylandSeat()->createPointer());
|
|
|
|
QScopedPointer<Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
|
|
|
QSignalSpy pointerEnteredSpy(pointer.data(), &Pointer::entered);
|
|
|
|
QVERIFY(pointerEnteredSpy.isValid());
|
|
|
|
QSignalSpy pointerLeftSpy(pointer.data(), &Pointer::left);
|
|
|
|
QVERIFY(pointerLeftSpy.isValid());
|
|
|
|
QSignalSpy keyboardEnteredSpy(keyboard.data(), &Keyboard::entered);
|
|
|
|
QVERIFY(keyboardEnteredSpy.isValid());
|
|
|
|
QSignalSpy keyboardLeftSpy(keyboard.data(), &Keyboard::left);
|
|
|
|
QVERIFY(keyboardLeftSpy.isValid());
|
|
|
|
|
|
|
|
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
|
|
|
QVERIFY(client);
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
2020-04-02 16:18:01 +00:00
|
|
|
QVERIFY(!client->frameGeometry().contains(KWin::Cursors::self()->mouse()->pos()));
|
2016-11-15 13:23:51 +00:00
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
Window *selectedWindow = nullptr;
|
|
|
|
auto callback = [&selectedWindow](Window *t) {
|
2016-11-15 13:23:51 +00:00
|
|
|
selectedWindow = t;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 0);
|
|
|
|
QVERIFY(keyboardLeftSpy.wait());
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 0);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
|
|
|
|
// simulate key press
|
|
|
|
quint32 timestamp = 0;
|
|
|
|
// move cursor through keys
|
2022-03-10 10:27:35 +00:00
|
|
|
auto keyPress = [×tamp](qint32 key) {
|
|
|
|
Test::keyboardKeyPressed(key, timestamp++);
|
|
|
|
Test::keyboardKeyReleased(key, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
};
|
2020-04-02 16:18:01 +00:00
|
|
|
while (KWin::Cursors::self()->mouse()->pos().x() >= client->frameGeometry().x() + client->frameGeometry().width()) {
|
2016-11-15 13:23:51 +00:00
|
|
|
keyPress(KEY_LEFT);
|
|
|
|
}
|
2020-04-02 16:18:01 +00:00
|
|
|
while (KWin::Cursors::self()->mouse()->pos().x() <= client->frameGeometry().x()) {
|
2016-11-15 13:23:51 +00:00
|
|
|
keyPress(KEY_RIGHT);
|
|
|
|
}
|
2020-04-02 16:18:01 +00:00
|
|
|
while (KWin::Cursors::self()->mouse()->pos().y() <= client->frameGeometry().y()) {
|
2016-11-15 13:23:51 +00:00
|
|
|
keyPress(KEY_DOWN);
|
|
|
|
}
|
2020-04-02 16:18:01 +00:00
|
|
|
while (KWin::Cursors::self()->mouse()->pos().y() >= client->frameGeometry().y() + client->frameGeometry().height()) {
|
2016-11-15 13:23:51 +00:00
|
|
|
keyPress(KEY_UP);
|
|
|
|
}
|
|
|
|
QFETCH(qint32, key);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::keyboardKeyPressed(key, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QCOMPARE(selectedWindow, client);
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
// should give back keyboard and pointer
|
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
if (keyboardEnteredSpy.count() != 2) {
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 0);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(pointerEnteredSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardEnteredSpy.count(), 2);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::keyboardKeyReleased(key, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
}
|
|
|
|
|
2017-03-27 17:58:03 +00:00
|
|
|
void TestWindowSelection::testSelectOnWindowTouch()
|
|
|
|
{
|
|
|
|
// this test verifies window selection through touch
|
|
|
|
QScopedPointer<Touch> touch(Test::waylandSeat()->createTouch());
|
|
|
|
QSignalSpy touchStartedSpy(touch.data(), &Touch::sequenceStarted);
|
|
|
|
QVERIFY(touchStartedSpy.isValid());
|
|
|
|
QSignalSpy touchCanceledSpy(touch.data(), &Touch::sequenceCanceled);
|
|
|
|
QVERIFY(touchCanceledSpy.isValid());
|
2021-09-03 17:54:03 +00:00
|
|
|
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
|
2021-05-11 05:26:51 +00:00
|
|
|
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
|
2017-03-27 17:58:03 +00:00
|
|
|
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
|
|
|
QVERIFY(client);
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
Window *selectedWindow = nullptr;
|
|
|
|
auto callback = [&selectedWindow](Window *t) {
|
2017-03-27 17:58:03 +00:00
|
|
|
selectedWindow = t;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
|
|
|
|
// simulate touch down
|
|
|
|
quint32 timestamp = 0;
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(0, client->frameGeometry().center(), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QVERIFY(!selectedWindow);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchUp(0, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QCOMPARE(selectedWindow, client);
|
|
|
|
|
|
|
|
// with movement
|
|
|
|
selectedWindow = nullptr;
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(0, client->frameGeometry().bottomRight() + QPoint(20, 20), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QVERIFY(!selectedWindow);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchMotion(0, client->frameGeometry().bottomRight() - QPoint(1, 1), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QVERIFY(!selectedWindow);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchUp(0, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(selectedWindow, client);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
|
|
|
|
// it cancels active touch sequence on the window
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(0, client->frameGeometry().center(), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QVERIFY(touchStartedSpy.wait());
|
|
|
|
selectedWindow = nullptr;
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(touchCanceledSpy.wait());
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
// this touch up does not yet select the window, it was started prior to the selection
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchUp(0, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QVERIFY(!selectedWindow);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(0, client->frameGeometry().center(), timestamp++);
|
|
|
|
Test::touchUp(0, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(selectedWindow, client);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
|
|
|
|
QCOMPARE(touchStartedSpy.count(), 1);
|
|
|
|
QCOMPARE(touchCanceledSpy.count(), 1);
|
|
|
|
}
|
|
|
|
|
2016-11-15 13:23:51 +00:00
|
|
|
void TestWindowSelection::testCancelOnWindowPointer()
|
|
|
|
{
|
|
|
|
// this test verifies that window selection cancels through right button click
|
2021-09-03 17:54:03 +00:00
|
|
|
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
|
2021-05-11 05:26:51 +00:00
|
|
|
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
|
2016-11-15 13:23:51 +00:00
|
|
|
QScopedPointer<Pointer> pointer(Test::waylandSeat()->createPointer());
|
|
|
|
QScopedPointer<Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
|
|
|
QSignalSpy pointerEnteredSpy(pointer.data(), &Pointer::entered);
|
|
|
|
QVERIFY(pointerEnteredSpy.isValid());
|
|
|
|
QSignalSpy pointerLeftSpy(pointer.data(), &Pointer::left);
|
|
|
|
QVERIFY(pointerLeftSpy.isValid());
|
|
|
|
QSignalSpy keyboardEnteredSpy(keyboard.data(), &Keyboard::entered);
|
|
|
|
QVERIFY(keyboardEnteredSpy.isValid());
|
|
|
|
QSignalSpy keyboardLeftSpy(keyboard.data(), &Keyboard::left);
|
|
|
|
QVERIFY(keyboardLeftSpy.isValid());
|
|
|
|
|
|
|
|
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
|
|
|
QVERIFY(client);
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
2020-04-02 16:18:01 +00:00
|
|
|
KWin::Cursors::self()->mouse()->setPos(client->frameGeometry().center());
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
Window *selectedWindow = nullptr;
|
|
|
|
auto callback = [&selectedWindow](Window *t) {
|
2016-11-15 13:23:51 +00:00
|
|
|
selectedWindow = t;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 0);
|
|
|
|
QVERIFY(pointerLeftSpy.wait());
|
|
|
|
if (keyboardLeftSpy.isEmpty()) {
|
|
|
|
QVERIFY(keyboardLeftSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
|
|
|
|
// simulate left button press
|
|
|
|
quint32 timestamp = 0;
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonPressed(BTN_RIGHT, timestamp++);
|
|
|
|
Test::pointerButtonReleased(BTN_RIGHT, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QVERIFY(!selectedWindow);
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
// should give back keyboard and pointer
|
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
if (keyboardEnteredSpy.count() != 2) {
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(pointerEnteredSpy.count(), 2);
|
|
|
|
QCOMPARE(keyboardEnteredSpy.count(), 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestWindowSelection::testCancelOnWindowKeyboard()
|
|
|
|
{
|
|
|
|
// this test verifies that cancel window selection through escape key works
|
2021-09-03 17:54:03 +00:00
|
|
|
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
|
2021-05-11 05:26:51 +00:00
|
|
|
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
|
2016-11-15 13:23:51 +00:00
|
|
|
QScopedPointer<Pointer> pointer(Test::waylandSeat()->createPointer());
|
|
|
|
QScopedPointer<Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
|
|
|
QSignalSpy pointerEnteredSpy(pointer.data(), &Pointer::entered);
|
|
|
|
QVERIFY(pointerEnteredSpy.isValid());
|
|
|
|
QSignalSpy pointerLeftSpy(pointer.data(), &Pointer::left);
|
|
|
|
QVERIFY(pointerLeftSpy.isValid());
|
|
|
|
QSignalSpy keyboardEnteredSpy(keyboard.data(), &Keyboard::entered);
|
|
|
|
QVERIFY(keyboardEnteredSpy.isValid());
|
|
|
|
QSignalSpy keyboardLeftSpy(keyboard.data(), &Keyboard::left);
|
|
|
|
QVERIFY(keyboardLeftSpy.isValid());
|
|
|
|
|
|
|
|
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
|
|
|
QVERIFY(client);
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
2020-04-02 16:18:01 +00:00
|
|
|
KWin::Cursors::self()->mouse()->setPos(client->frameGeometry().center());
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
Window *selectedWindow = nullptr;
|
|
|
|
auto callback = [&selectedWindow](Window *t) {
|
2016-11-15 13:23:51 +00:00
|
|
|
selectedWindow = t;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QVERIFY(!selectedWindow);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 0);
|
|
|
|
QVERIFY(pointerLeftSpy.wait());
|
|
|
|
if (keyboardLeftSpy.isEmpty()) {
|
|
|
|
QVERIFY(keyboardLeftSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
|
|
|
|
// simulate left button press
|
|
|
|
quint32 timestamp = 0;
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::keyboardKeyPressed(KEY_ESC, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QVERIFY(!selectedWindow);
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-15 13:23:51 +00:00
|
|
|
// should give back keyboard and pointer
|
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
if (keyboardEnteredSpy.count() != 2) {
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(pointerEnteredSpy.count(), 2);
|
|
|
|
QCOMPARE(keyboardEnteredSpy.count(), 2);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::keyboardKeyReleased(KEY_ESC, timestamp++);
|
2016-11-15 13:23:51 +00:00
|
|
|
}
|
|
|
|
|
2016-11-23 14:53:17 +00:00
|
|
|
void TestWindowSelection::testSelectPointPointer()
|
|
|
|
{
|
|
|
|
// this test verifies point selection through pointer works
|
2021-09-03 17:54:03 +00:00
|
|
|
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
|
2021-05-11 05:26:51 +00:00
|
|
|
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
|
2016-11-23 14:53:17 +00:00
|
|
|
QScopedPointer<Pointer> pointer(Test::waylandSeat()->createPointer());
|
|
|
|
QScopedPointer<Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
|
|
|
QSignalSpy pointerEnteredSpy(pointer.data(), &Pointer::entered);
|
|
|
|
QVERIFY(pointerEnteredSpy.isValid());
|
|
|
|
QSignalSpy pointerLeftSpy(pointer.data(), &Pointer::left);
|
|
|
|
QVERIFY(pointerLeftSpy.isValid());
|
|
|
|
QSignalSpy keyboardEnteredSpy(keyboard.data(), &Keyboard::entered);
|
|
|
|
QVERIFY(keyboardEnteredSpy.isValid());
|
|
|
|
QSignalSpy keyboardLeftSpy(keyboard.data(), &Keyboard::left);
|
|
|
|
QVERIFY(keyboardLeftSpy.isValid());
|
|
|
|
|
|
|
|
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
|
|
|
QVERIFY(client);
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
2020-04-02 16:18:01 +00:00
|
|
|
KWin::Cursors::self()->mouse()->setPos(client->frameGeometry().center());
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-23 14:53:17 +00:00
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
|
|
|
|
QPoint point;
|
2022-03-23 10:13:38 +00:00
|
|
|
auto callback = [&point](const QPoint &p) {
|
2016-11-23 14:53:17 +00:00
|
|
|
point = p;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractivePositionSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QCOMPARE(point, QPoint());
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 0);
|
|
|
|
QVERIFY(pointerLeftSpy.wait());
|
|
|
|
if (keyboardLeftSpy.isEmpty()) {
|
|
|
|
QVERIFY(keyboardLeftSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
|
|
|
|
// trying again should not be allowed
|
|
|
|
QPoint point2;
|
2022-03-23 10:13:38 +00:00
|
|
|
kwinApp()->platform()->startInteractivePositionSelection([&point2](const QPoint &p) {
|
2016-11-23 14:53:17 +00:00
|
|
|
point2 = p;
|
|
|
|
});
|
|
|
|
QCOMPARE(point2, QPoint(-1, -1));
|
|
|
|
|
|
|
|
// simulate left button press
|
|
|
|
quint32 timestamp = 0;
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
2016-11-23 14:53:17 +00:00
|
|
|
// should not have ended the mode
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QCOMPARE(point, QPoint());
|
2020-09-07 08:11:07 +00:00
|
|
|
QVERIFY(!input()->pointer()->focus());
|
2016-11-23 14:53:17 +00:00
|
|
|
|
|
|
|
// updating the pointer should not change anything
|
|
|
|
input()->pointer()->update();
|
2020-09-07 08:11:07 +00:00
|
|
|
QVERIFY(!input()->pointer()->focus());
|
2016-11-23 14:53:17 +00:00
|
|
|
// updating keyboard should also not change
|
|
|
|
input()->keyboard()->update();
|
|
|
|
|
|
|
|
// perform a right button click
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonPressed(BTN_RIGHT, timestamp++);
|
|
|
|
Test::pointerButtonReleased(BTN_RIGHT, timestamp++);
|
2016-11-23 14:53:17 +00:00
|
|
|
// should not have ended the mode
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QCOMPARE(point, QPoint());
|
|
|
|
// now release
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
2016-11-23 14:53:17 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QCOMPARE(point, input()->globalPointer().toPoint());
|
2020-09-07 08:11:07 +00:00
|
|
|
QCOMPARE(input()->pointer()->focus(), client);
|
2016-11-23 14:53:17 +00:00
|
|
|
// should give back keyboard and pointer
|
|
|
|
QVERIFY(pointerEnteredSpy.wait());
|
|
|
|
if (keyboardEnteredSpy.count() != 2) {
|
|
|
|
QVERIFY(keyboardEnteredSpy.wait());
|
|
|
|
}
|
|
|
|
QCOMPARE(pointerLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(keyboardLeftSpy.count(), 1);
|
|
|
|
QCOMPARE(pointerEnteredSpy.count(), 2);
|
|
|
|
QCOMPARE(keyboardEnteredSpy.count(), 2);
|
|
|
|
}
|
|
|
|
|
2017-03-27 17:58:03 +00:00
|
|
|
void TestWindowSelection::testSelectPointTouch()
|
|
|
|
{
|
|
|
|
// this test verifies point selection through touch works
|
|
|
|
QPoint point;
|
2022-03-23 10:13:38 +00:00
|
|
|
auto callback = [&point](const QPoint &p) {
|
2017-03-27 17:58:03 +00:00
|
|
|
point = p;
|
|
|
|
};
|
|
|
|
|
|
|
|
// start the interaction
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
kwinApp()->platform()->startInteractivePositionSelection(callback);
|
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
QCOMPARE(point, QPoint());
|
|
|
|
|
|
|
|
// let's create multiple touch points
|
|
|
|
quint32 timestamp = 0;
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(0, QPointF(0, 1), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(1, QPointF(10, 20), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchDown(2, QPointF(30, 40), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
|
|
|
|
|
|
|
// let's move our points
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchMotion(0, QPointF(5, 10), timestamp++);
|
|
|
|
Test::touchMotion(2, QPointF(20, 25), timestamp++);
|
|
|
|
Test::touchMotion(1, QPointF(25, 35), timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchUp(0, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchUp(2, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), true);
|
2022-03-10 10:27:35 +00:00
|
|
|
Test::touchUp(1, timestamp++);
|
2017-03-27 17:58:03 +00:00
|
|
|
QCOMPARE(input()->isSelectingWindow(), false);
|
|
|
|
QCOMPARE(point, QPoint(25, 35));
|
|
|
|
}
|
|
|
|
|
2016-11-15 13:23:51 +00:00
|
|
|
WAYLANDTEST_MAIN(TestWindowSelection)
|
|
|
|
#include "window_selection_test.moc"
|