Client tests: Add simple test for keyboard press

Change-Id: Ib28be5277af9145834c7808f993c747e21845616
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Johan Klokkhammer Helsing 2018-12-13 09:39:05 +01:00 committed by Johan Helsing
parent f91e358902
commit d2c9c5537d
5 changed files with 101 additions and 5 deletions

View File

@ -46,7 +46,7 @@ public:
removeAll<Seat>();
uint capabilities = MockCompositor::Seat::capability_pointer;
uint capabilities = Seat::capability_pointer | Seat::capability_keyboard;
int version = 4;
add<Seat>(capabilities, version);
});
@ -67,6 +67,8 @@ private slots:
void simpleAxis();
void invalidPointerEvents();
void scaledCursor();
void keyboardKeyPress();
};
void tst_seatv4::cleanup()
@ -287,5 +289,28 @@ void tst_seatv4::scaledCursor()
exec([&] { remove(output(1)); });
}
void tst_seatv4::keyboardKeyPress()
{
class Window : public QRasterWindow {
public:
void keyPressEvent(QKeyEvent *) override { m_pressed = true; }
bool m_pressed = false;
};
Window window;
window.resize(64, 64);
window.show();
QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
uint keyCode = 80; // arbitrarily chosen
exec([&] {
auto *surface = xdgSurface()->m_surface;
keyboard()->sendEnter(surface);
keyboard()->sendKey(client(), keyCode, Keyboard::key_state_pressed);
keyboard()->sendKey(client(), keyCode, Keyboard::key_state_released);
});
QTRY_VERIFY(window.m_pressed);
}
QCOMPOSITOR_TEST_MAIN(tst_seatv4)
#include "tst_seatv4.moc"

View File

@ -193,8 +193,8 @@ Seat::~Seat()
}
void Seat::setCapabilities(uint capabilities) {
// TODO: Add support for touch and keyboard
Q_ASSERT(capabilities == 0 || capabilities == capability_pointer);
// TODO: Add support for touch
Q_ASSERT(~capabilities & capability_touch);
m_capabilities = capabilities;
@ -206,6 +206,14 @@ void Seat::setCapabilities(uint capabilities) {
m_pointer = nullptr;
}
if (m_capabilities & capability_keyboard) {
if (!m_keyboard)
m_keyboard = (new Keyboard(this));
} else if (m_keyboard) {
m_oldKeyboards << m_keyboard;
m_keyboard = nullptr;
}
for (auto *resource : resourceMap())
wl_seat::send_capabilities(resource->handle, capabilities);
}
@ -225,6 +233,21 @@ void Seat::seat_get_pointer(Resource *resource, uint32_t id)
m_pointer->add(resource->client(), id, resource->version());
}
void Seat::seat_get_keyboard(QtWaylandServer::wl_seat::Resource *resource, uint32_t id)
{
if (~m_capabilities & capability_pointer) {
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";
Keyboard *keyboard = new Keyboard(this);
keyboard->add(resource->client(), id, resource->version());
// TODO: mark as destroyed
m_oldKeyboards << keyboard;
return;
}
m_keyboard->add(resource->client(), id, resource->version());
}
Surface *Pointer::cursorSurface()
{
return m_cursorRole ? m_cursorRole->m_surface : nullptr;
@ -296,6 +319,37 @@ void Pointer::pointer_set_cursor(Resource *resource, uint32_t serial, wl_resourc
emit setCursor(serial);
}
uint Keyboard::sendEnter(Surface *surface)
{
auto serial = m_seat->m_compositor->nextSerial();
wl_client *client = surface->resource()->client();
const auto pointerResources = resourceMap().values(client);
for (auto *r : pointerResources)
send_enter(r->handle, serial, surface->resource()->handle, QByteArray());
return serial;
}
uint Keyboard::sendLeave(Surface *surface)
{
auto serial = m_seat->m_compositor->nextSerial();
wl_client *client = surface->resource()->client();
const auto pointerResources = resourceMap().values(client);
for (auto *r : pointerResources)
send_leave(r->handle, serial, surface->resource()->handle);
return serial;
}
uint Keyboard::sendKey(wl_client *client, uint key, uint state)
{
Q_ASSERT(state == key_state_pressed || state == key_state_released);
auto time = m_seat->m_compositor->currentTimeMilliseconds();
uint serial = m_seat->m_compositor->nextSerial();
const auto pointerResources = resourceMap().values(client);
for (auto *r : pointerResources)
send_key(r->handle, serial, time, key, state);
return serial;
}
// Shm implementation
Shm::Shm(CoreCompositor *compositor, QVector<format> formats, int version)
: QtWaylandServer::wl_shm(compositor->m_display, version)

View File

@ -38,6 +38,7 @@ namespace MockCompositor {
class WlCompositor;
class Output;
class Pointer;
class Keyboard;
class CursorRole;
class ShmPool;
class ShmBuffer;
@ -245,6 +246,9 @@ public:
Pointer* m_pointer = nullptr;
QVector<Pointer *> m_oldPointers;
Keyboard* m_keyboard = nullptr;
QVector<Keyboard *> m_oldKeyboards;
uint m_capabilities = 0;
protected:
@ -254,7 +258,7 @@ protected:
}
void seat_get_pointer(Resource *resource, uint32_t id) override;
// void seat_get_keyboard(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;
@ -294,6 +298,18 @@ public:
Surface *m_surface = nullptr;
};
class Keyboard : public QObject, public QtWaylandServer::wl_keyboard
{
Q_OBJECT
public:
explicit Keyboard(Seat *seat) : m_seat(seat) {}
//TODO: Keymap event
uint sendEnter(Surface *surface);
uint sendLeave(Surface *surface);
uint sendKey(wl_client *client, uint key, uint state);
Seat *m_seat = nullptr;
};
class Shm : public Global, public QtWaylandServer::wl_shm
{
Q_OBJECT

View File

@ -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);
add<Seat>(Seat::capability_pointer | Seat::capability_keyboard);
add<XdgWmBase>();
add<Shm>();
// TODO: other shells, viewporter, xdgoutput etc

View File

@ -53,6 +53,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; }
Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; }
uint sendXdgShellPing();
void xdgPingAndWaitForPong();
// Things that can be changed run-time without confusing the client (i.e. don't require separate tests)