Add implementation for wl_data_device in Server and Client
On the client side anything related to wl_data_offer is not yet implemented.
This commit is contained in:
parent
435c88f1e0
commit
421cfaafc3
7 changed files with 664 additions and 5 deletions
|
@ -1,6 +1,7 @@
|
||||||
set(SERVER_LIB_SRCS
|
set(SERVER_LIB_SRCS
|
||||||
buffer_interface.cpp
|
buffer_interface.cpp
|
||||||
compositor_interface.cpp
|
compositor_interface.cpp
|
||||||
|
datadevice_interface.cpp
|
||||||
datadevicemanager_interface.cpp
|
datadevicemanager_interface.cpp
|
||||||
datasource_interface.cpp
|
datasource_interface.cpp
|
||||||
display.cpp
|
display.cpp
|
||||||
|
@ -47,6 +48,7 @@ set_target_properties(KF5WaylandServer PROPERTIES VERSION ${KWAYLAND_VERSION_S
|
||||||
# ${CMAKE_CURRENT_BINARY_DIR}/KWayland/Server/kwaylandserver_export.h
|
# ${CMAKE_CURRENT_BINARY_DIR}/KWayland/Server/kwaylandserver_export.h
|
||||||
# buffer_interface.h
|
# buffer_interface.h
|
||||||
# compositor_interface.h
|
# compositor_interface.h
|
||||||
|
# datadevice_interface.h
|
||||||
# datadevicemanager_interface.h
|
# datadevicemanager_interface.h
|
||||||
# datasource_interface.h
|
# datasource_interface.h
|
||||||
# display.h
|
# display.h
|
||||||
|
|
|
@ -145,3 +145,14 @@ add_executable(testDataSource ${testDataSource_SRCS})
|
||||||
target_link_libraries( testDataSource Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client)
|
target_link_libraries( testDataSource Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client)
|
||||||
add_test(kwayland-testDataSource testDataSource)
|
add_test(kwayland-testDataSource testDataSource)
|
||||||
ecm_mark_as_test(testDataSource)
|
ecm_mark_as_test(testDataSource)
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# Test DataDevice
|
||||||
|
########################################################
|
||||||
|
set( testDataDevice_SRCS
|
||||||
|
test_datadevice.cpp
|
||||||
|
)
|
||||||
|
add_executable(testDataDevice ${testDataDevice_SRCS})
|
||||||
|
target_link_libraries( testDataDevice Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client)
|
||||||
|
add_test(kwayland-testDataDevice testDataDevice)
|
||||||
|
ecm_mark_as_test(testDataDevice)
|
||||||
|
|
379
src/wayland/autotests/client/test_datadevice.cpp
Normal file
379
src/wayland/autotests/client/test_datadevice.cpp
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
/********************************************************************
|
||||||
|
Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) version 3, or any
|
||||||
|
later version accepted by the membership of KDE e.V. (or its
|
||||||
|
successor approved by the membership of KDE e.V.), which shall
|
||||||
|
act as a proxy defined in Section 6 of version 3 of the license.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
// Qt
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
// KWayland
|
||||||
|
#include "../../src/client/connection_thread.h"
|
||||||
|
#include "../../src/client/event_queue.h"
|
||||||
|
#include "../../src/client/datadevice.h"
|
||||||
|
#include "../../src/client/datadevicemanager.h"
|
||||||
|
#include "../../src/client/datasource.h"
|
||||||
|
#include "../../src/client/compositor.h"
|
||||||
|
#include "../../src/client/pointer.h"
|
||||||
|
#include "../../src/client/registry.h"
|
||||||
|
#include "../../src/client/seat.h"
|
||||||
|
#include "../../src/client/surface.h"
|
||||||
|
#include "../../src/server/display.h"
|
||||||
|
#include "../../src/server/datadevicemanager_interface.h"
|
||||||
|
#include "../../src/server/datasource_interface.h"
|
||||||
|
#include "../../src/server/compositor_interface.h"
|
||||||
|
#include "../../src/server/seat_interface.h"
|
||||||
|
#include "../../src/server/surface_interface.h"
|
||||||
|
// Wayland
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
class TestDataDevice : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private Q_SLOTS:
|
||||||
|
void init();
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
void testCreate();
|
||||||
|
void testDrag();
|
||||||
|
void testDragInternally();
|
||||||
|
void testSetSelection();
|
||||||
|
void testDestroy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
KWayland::Server::Display *m_display = nullptr;
|
||||||
|
KWayland::Server::DataDeviceManagerInterface *m_dataDeviceManagerInterface = nullptr;
|
||||||
|
KWayland::Server::CompositorInterface *m_compositorInterface = nullptr;
|
||||||
|
KWayland::Server::SeatInterface *m_seatInterface = nullptr;
|
||||||
|
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
||||||
|
KWayland::Client::DataDeviceManager *m_dataDeviceManager = nullptr;
|
||||||
|
KWayland::Client::Compositor *m_compositor = nullptr;
|
||||||
|
KWayland::Client::Seat *m_seat = nullptr;
|
||||||
|
KWayland::Client::EventQueue *m_queue = nullptr;
|
||||||
|
QThread *m_thread = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QString s_socketName = QStringLiteral("kwayland-test-wayland-datadevice-0");
|
||||||
|
|
||||||
|
void TestDataDevice::init()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
delete m_display;
|
||||||
|
m_display = new Display(this);
|
||||||
|
m_display->setSocketName(s_socketName);
|
||||||
|
m_display->start();
|
||||||
|
QVERIFY(m_display->isRunning());
|
||||||
|
|
||||||
|
// setup connection
|
||||||
|
m_connection = new KWayland::Client::ConnectionThread;
|
||||||
|
QSignalSpy connectedSpy(m_connection, SIGNAL(connected()));
|
||||||
|
m_connection->setSocketName(s_socketName);
|
||||||
|
|
||||||
|
m_thread = new QThread(this);
|
||||||
|
m_connection->moveToThread(m_thread);
|
||||||
|
m_thread->start();
|
||||||
|
|
||||||
|
m_connection->initConnection();
|
||||||
|
QVERIFY(connectedSpy.wait());
|
||||||
|
|
||||||
|
m_queue = new KWayland::Client::EventQueue(this);
|
||||||
|
QVERIFY(!m_queue->isValid());
|
||||||
|
m_queue->setup(m_connection);
|
||||||
|
QVERIFY(m_queue->isValid());
|
||||||
|
|
||||||
|
KWayland::Client::Registry registry;
|
||||||
|
QSignalSpy dataDeviceManagerSpy(®istry, SIGNAL(dataDeviceManagerAnnounced(quint32,quint32)));
|
||||||
|
QVERIFY(dataDeviceManagerSpy.isValid());
|
||||||
|
QSignalSpy seatSpy(®istry, SIGNAL(seatAnnounced(quint32,quint32)));
|
||||||
|
QVERIFY(seatSpy.isValid());
|
||||||
|
QSignalSpy compositorSpy(®istry, SIGNAL(compositorAnnounced(quint32,quint32)));
|
||||||
|
QVERIFY(compositorSpy.isValid());
|
||||||
|
QVERIFY(!registry.eventQueue());
|
||||||
|
registry.setEventQueue(m_queue);
|
||||||
|
QCOMPARE(registry.eventQueue(), m_queue);
|
||||||
|
registry.create(m_connection->display());
|
||||||
|
QVERIFY(registry.isValid());
|
||||||
|
registry.setup();
|
||||||
|
|
||||||
|
m_dataDeviceManagerInterface = m_display->createDataDeviceManager(m_display);
|
||||||
|
m_dataDeviceManagerInterface->create();
|
||||||
|
QVERIFY(m_dataDeviceManagerInterface->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataDeviceManagerSpy.wait());
|
||||||
|
m_dataDeviceManager = registry.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(),
|
||||||
|
dataDeviceManagerSpy.first().last().value<quint32>(), this);
|
||||||
|
|
||||||
|
m_seatInterface = m_display->createSeat(m_display);
|
||||||
|
m_seatInterface->setHasPointer(true);
|
||||||
|
m_seatInterface->create();
|
||||||
|
QVERIFY(m_seatInterface->isValid());
|
||||||
|
|
||||||
|
QVERIFY(seatSpy.wait());
|
||||||
|
m_seat = registry.createSeat(seatSpy.first().first().value<quint32>(),
|
||||||
|
seatSpy.first().last().value<quint32>(), this);
|
||||||
|
QVERIFY(m_seat->isValid());
|
||||||
|
QSignalSpy pointerChangedSpy(m_seat, SIGNAL(hasPointerChanged(bool)));
|
||||||
|
QVERIFY(pointerChangedSpy.isValid());
|
||||||
|
QVERIFY(pointerChangedSpy.wait());
|
||||||
|
|
||||||
|
m_compositorInterface = m_display->createCompositor(m_display);
|
||||||
|
m_compositorInterface->create();
|
||||||
|
QVERIFY(m_compositorInterface->isValid());
|
||||||
|
|
||||||
|
QVERIFY(compositorSpy.wait());
|
||||||
|
m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(),
|
||||||
|
compositorSpy.first().last().value<quint32>(), this);
|
||||||
|
QVERIFY(m_compositor->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDataDevice::cleanup()
|
||||||
|
{
|
||||||
|
if (m_dataDeviceManager) {
|
||||||
|
delete m_dataDeviceManager;
|
||||||
|
m_dataDeviceManager = nullptr;
|
||||||
|
}
|
||||||
|
if (m_seat) {
|
||||||
|
delete m_seat;
|
||||||
|
m_seat = nullptr;
|
||||||
|
}
|
||||||
|
if (m_compositor) {
|
||||||
|
delete m_compositor;
|
||||||
|
m_compositor = nullptr;
|
||||||
|
}
|
||||||
|
if (m_queue) {
|
||||||
|
delete m_queue;
|
||||||
|
m_queue = nullptr;
|
||||||
|
}
|
||||||
|
if (m_thread) {
|
||||||
|
m_thread->quit();
|
||||||
|
m_thread->wait();
|
||||||
|
delete m_thread;
|
||||||
|
m_thread = nullptr;
|
||||||
|
}
|
||||||
|
delete m_connection;
|
||||||
|
m_connection = nullptr;
|
||||||
|
|
||||||
|
delete m_display;
|
||||||
|
m_display = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDataDevice::testCreate()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
|
||||||
|
QSignalSpy dataDeviceCreatedSpy(m_dataDeviceManagerInterface, SIGNAL(dataDeviceCreated(KWayland::Server::DataDeviceInterface*)));
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<DataDevice> dataDevice(m_dataDeviceManager->getDataDevice(m_seat));
|
||||||
|
QVERIFY(dataDevice->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.wait());
|
||||||
|
QCOMPARE(dataDeviceCreatedSpy.count(), 1);
|
||||||
|
auto deviceInterface = dataDeviceCreatedSpy.first().first().value<DataDeviceInterface*>();
|
||||||
|
QVERIFY(deviceInterface);
|
||||||
|
QCOMPARE(deviceInterface->seat(), m_seatInterface);
|
||||||
|
QVERIFY(!deviceInterface->dragSource());
|
||||||
|
QVERIFY(!deviceInterface->origin());
|
||||||
|
QVERIFY(!deviceInterface->icon());
|
||||||
|
QVERIFY(!deviceInterface->selection());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDataDevice::testDrag()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
QScopedPointer<Pointer> pointer(m_seat->createPointer());
|
||||||
|
|
||||||
|
QSignalSpy dataDeviceCreatedSpy(m_dataDeviceManagerInterface, SIGNAL(dataDeviceCreated(KWayland::Server::DataDeviceInterface*)));
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<DataDevice> dataDevice(m_dataDeviceManager->getDataDevice(m_seat));
|
||||||
|
QVERIFY(dataDevice->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.wait());
|
||||||
|
QCOMPARE(dataDeviceCreatedSpy.count(), 1);
|
||||||
|
auto deviceInterface = dataDeviceCreatedSpy.first().first().value<DataDeviceInterface*>();
|
||||||
|
QVERIFY(deviceInterface);
|
||||||
|
|
||||||
|
QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, SIGNAL(dataSourceCreated(DataSourceInterface*)));
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<DataSource> dataSource(m_dataDeviceManager->createDataSource());
|
||||||
|
QVERIFY(dataSource->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataSourceCreatedSpy.wait());
|
||||||
|
QCOMPARE(dataSourceCreatedSpy.count(), 1);
|
||||||
|
auto sourceInterface = dataSourceCreatedSpy.first().first().value<DataSourceInterface*>();
|
||||||
|
QVERIFY(sourceInterface);
|
||||||
|
|
||||||
|
QSignalSpy surfaceCreatedSpy(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*)));
|
||||||
|
QVERIFY(surfaceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<Surface> surface(m_compositor->createSurface());
|
||||||
|
QVERIFY(surface->isValid());
|
||||||
|
|
||||||
|
QVERIFY(surfaceCreatedSpy.wait());
|
||||||
|
QCOMPARE(surfaceCreatedSpy.count(), 1);
|
||||||
|
auto surfaceInterface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
|
||||||
|
|
||||||
|
// now we have all we need to start a drag operation
|
||||||
|
QSignalSpy dragStartedSpy(deviceInterface, SIGNAL(dragStarted()));
|
||||||
|
QVERIFY(dragStartedSpy.isValid());
|
||||||
|
|
||||||
|
// first we need to fake the pointer enter
|
||||||
|
m_seatInterface->pointer()->setFocusedSurface(surfaceInterface);
|
||||||
|
m_seatInterface->pointer()->buttonPressed(1);
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
dataDevice->startDrag(1, dataSource.data(), surface.data());
|
||||||
|
QVERIFY(dragStartedSpy.wait());
|
||||||
|
QCOMPARE(dragStartedSpy.count(), 1);
|
||||||
|
QCOMPARE(deviceInterface->dragSource(), sourceInterface);
|
||||||
|
QCOMPARE(deviceInterface->origin(), surfaceInterface);
|
||||||
|
QVERIFY(!deviceInterface->icon());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDataDevice::testDragInternally()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
QScopedPointer<Pointer> pointer(m_seat->createPointer());
|
||||||
|
|
||||||
|
QSignalSpy dataDeviceCreatedSpy(m_dataDeviceManagerInterface, SIGNAL(dataDeviceCreated(KWayland::Server::DataDeviceInterface*)));
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<DataDevice> dataDevice(m_dataDeviceManager->getDataDevice(m_seat));
|
||||||
|
QVERIFY(dataDevice->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.wait());
|
||||||
|
QCOMPARE(dataDeviceCreatedSpy.count(), 1);
|
||||||
|
auto deviceInterface = dataDeviceCreatedSpy.first().first().value<DataDeviceInterface*>();
|
||||||
|
QVERIFY(deviceInterface);
|
||||||
|
|
||||||
|
QSignalSpy surfaceCreatedSpy(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*)));
|
||||||
|
QVERIFY(surfaceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<Surface> surface(m_compositor->createSurface());
|
||||||
|
QVERIFY(surface->isValid());
|
||||||
|
|
||||||
|
QVERIFY(surfaceCreatedSpy.wait());
|
||||||
|
QCOMPARE(surfaceCreatedSpy.count(), 1);
|
||||||
|
auto surfaceInterface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
|
||||||
|
|
||||||
|
QScopedPointer<Surface> iconSurface(m_compositor->createSurface());
|
||||||
|
QVERIFY(iconSurface->isValid());
|
||||||
|
|
||||||
|
QVERIFY(surfaceCreatedSpy.wait());
|
||||||
|
QCOMPARE(surfaceCreatedSpy.count(), 2);
|
||||||
|
auto iconSurfaceInterface = surfaceCreatedSpy.last().first().value<SurfaceInterface*>();
|
||||||
|
|
||||||
|
// now we have all we need to start a drag operation
|
||||||
|
QSignalSpy dragStartedSpy(deviceInterface, SIGNAL(dragStarted()));
|
||||||
|
QVERIFY(dragStartedSpy.isValid());
|
||||||
|
|
||||||
|
// first we need to fake the pointer enter
|
||||||
|
m_seatInterface->pointer()->setFocusedSurface(surfaceInterface);
|
||||||
|
m_seatInterface->pointer()->buttonPressed(1);
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
dataDevice->startDragInternally(1, surface.data(), iconSurface.data());
|
||||||
|
QVERIFY(dragStartedSpy.wait());
|
||||||
|
QCOMPARE(dragStartedSpy.count(), 1);
|
||||||
|
QVERIFY(!deviceInterface->dragSource());
|
||||||
|
QCOMPARE(deviceInterface->origin(), surfaceInterface);
|
||||||
|
QCOMPARE(deviceInterface->icon(), iconSurfaceInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDataDevice::testSetSelection()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
QScopedPointer<Pointer> pointer(m_seat->createPointer());
|
||||||
|
|
||||||
|
QSignalSpy dataDeviceCreatedSpy(m_dataDeviceManagerInterface, SIGNAL(dataDeviceCreated(KWayland::Server::DataDeviceInterface*)));
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<DataDevice> dataDevice(m_dataDeviceManager->getDataDevice(m_seat));
|
||||||
|
QVERIFY(dataDevice->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.wait());
|
||||||
|
QCOMPARE(dataDeviceCreatedSpy.count(), 1);
|
||||||
|
auto deviceInterface = dataDeviceCreatedSpy.first().first().value<DataDeviceInterface*>();
|
||||||
|
QVERIFY(deviceInterface);
|
||||||
|
|
||||||
|
QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, SIGNAL(dataSourceCreated(DataSourceInterface*)));
|
||||||
|
QVERIFY(dataDeviceCreatedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<DataSource> dataSource(m_dataDeviceManager->createDataSource());
|
||||||
|
QVERIFY(dataSource->isValid());
|
||||||
|
|
||||||
|
QVERIFY(dataSourceCreatedSpy.wait());
|
||||||
|
QCOMPARE(dataSourceCreatedSpy.count(), 1);
|
||||||
|
auto sourceInterface = dataSourceCreatedSpy.first().first().value<DataSourceInterface*>();
|
||||||
|
QVERIFY(sourceInterface);
|
||||||
|
|
||||||
|
// everything setup, now we can test setting the selection
|
||||||
|
QSignalSpy selectionChangedSpy(deviceInterface, SIGNAL(selectionChanged(KWayland::Server::DataSourceInterface*)));
|
||||||
|
QVERIFY(selectionChangedSpy.isValid());
|
||||||
|
QSignalSpy selectionClearedSpy(deviceInterface, SIGNAL(selectionCleared()));
|
||||||
|
QVERIFY(selectionClearedSpy.isValid());
|
||||||
|
|
||||||
|
QVERIFY(!deviceInterface->selection());
|
||||||
|
dataDevice->setSelection(1, dataSource.data());
|
||||||
|
QVERIFY(selectionChangedSpy.wait());
|
||||||
|
QCOMPARE(selectionChangedSpy.count(), 1);
|
||||||
|
QCOMPARE(selectionClearedSpy.count(), 0);
|
||||||
|
QCOMPARE(selectionChangedSpy.first().first().value<DataSourceInterface*>(), sourceInterface);
|
||||||
|
QCOMPARE(deviceInterface->selection(), sourceInterface);
|
||||||
|
|
||||||
|
// now clear the selection
|
||||||
|
dataDevice->clearSelection(1);
|
||||||
|
QVERIFY(selectionClearedSpy.wait());
|
||||||
|
QCOMPARE(selectionChangedSpy.count(), 1);
|
||||||
|
QCOMPARE(selectionClearedSpy.count(), 1);
|
||||||
|
QVERIFY(!deviceInterface->selection());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDataDevice::testDestroy()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
|
||||||
|
QScopedPointer<DataDevice> dataDevice(m_dataDeviceManager->getDataDevice(m_seat));
|
||||||
|
QVERIFY(dataDevice->isValid());
|
||||||
|
|
||||||
|
connect(m_connection, &ConnectionThread::connectionDied, m_dataDeviceManager, &DataDeviceManager::destroy);
|
||||||
|
connect(m_connection, &ConnectionThread::connectionDied, m_seat, &Seat::destroy);
|
||||||
|
connect(m_connection, &ConnectionThread::connectionDied, m_compositor, &Compositor::destroy);
|
||||||
|
connect(m_connection, &ConnectionThread::connectionDied, dataDevice.data(), &DataDevice::destroy);
|
||||||
|
connect(m_connection, &ConnectionThread::connectionDied, m_queue, &EventQueue::destroy);
|
||||||
|
|
||||||
|
QSignalSpy connectionDiedSpy(m_connection, SIGNAL(connectionDied()));
|
||||||
|
QVERIFY(connectionDiedSpy.isValid());
|
||||||
|
delete m_display;
|
||||||
|
m_display = nullptr;
|
||||||
|
QVERIFY(connectionDiedSpy.wait());
|
||||||
|
|
||||||
|
// now the data device should be destroyed;
|
||||||
|
QVERIFY(!dataDevice->isValid());
|
||||||
|
|
||||||
|
// calling destroy again should not fail
|
||||||
|
dataDevice->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(TestDataDevice)
|
||||||
|
#include "test_datadevice.moc"
|
181
src/wayland/datadevice_interface.cpp
Normal file
181
src/wayland/datadevice_interface.cpp
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/********************************************************************
|
||||||
|
Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) version 3, or any
|
||||||
|
later version accepted by the membership of KDE e.V. (or its
|
||||||
|
successor approved by the membership of KDE e.V.), which shall
|
||||||
|
act as a proxy defined in Section 6 of version 3 of the license.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#include "datadevice_interface.h"
|
||||||
|
#include "datasource_interface.h"
|
||||||
|
#include "seat_interface.h"
|
||||||
|
#include "surface_interface.h"
|
||||||
|
// Wayland
|
||||||
|
#include <wayland-server.h>
|
||||||
|
|
||||||
|
namespace KWayland
|
||||||
|
{
|
||||||
|
namespace Server
|
||||||
|
{
|
||||||
|
|
||||||
|
class DataDeviceInterface::Private
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Private(SeatInterface *seat, DataDeviceInterface *q);
|
||||||
|
~Private();
|
||||||
|
|
||||||
|
void create(wl_client *client, quint32 version, quint32 id);
|
||||||
|
|
||||||
|
SeatInterface *seat;
|
||||||
|
wl_resource *device = nullptr;
|
||||||
|
DataSourceInterface *source = nullptr;
|
||||||
|
SurfaceInterface *surface = nullptr;
|
||||||
|
SurfaceInterface *icon = nullptr;
|
||||||
|
|
||||||
|
DataSourceInterface *selection = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startDrag(DataSourceInterface *dataSource, SurfaceInterface *origin, SurfaceInterface *icon);
|
||||||
|
void setSelection(DataSourceInterface *dataSource);
|
||||||
|
static void startDragCallback(wl_client *client, wl_resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial);
|
||||||
|
static void setSelectionCallback(wl_client *client, wl_resource *resource, wl_resource *source, uint32_t serial);
|
||||||
|
static void unbind(wl_resource *resource);
|
||||||
|
static Private *cast(wl_resource *r) {
|
||||||
|
return reinterpret_cast<Private*>(wl_resource_get_user_data(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataDeviceInterface *q;
|
||||||
|
|
||||||
|
static const struct wl_data_device_interface s_interface;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct wl_data_device_interface DataDeviceInterface::Private::s_interface = {
|
||||||
|
startDragCallback,
|
||||||
|
setSelectionCallback
|
||||||
|
};
|
||||||
|
|
||||||
|
DataDeviceInterface::Private::Private(SeatInterface *seat, DataDeviceInterface *q)
|
||||||
|
: seat(seat)
|
||||||
|
, q(q)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DataDeviceInterface::Private::~Private()
|
||||||
|
{
|
||||||
|
if (device) {
|
||||||
|
wl_resource_destroy(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDeviceInterface::Private::startDragCallback(wl_client *client, wl_resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial)
|
||||||
|
{
|
||||||
|
Q_UNUSED(client)
|
||||||
|
Q_UNUSED(serial)
|
||||||
|
// TODO: verify serial
|
||||||
|
cast(resource)->startDrag(DataSourceInterface::get(source), SurfaceInterface::get(origin), SurfaceInterface::get(icon));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDeviceInterface::Private::startDrag(DataSourceInterface *dataSource, SurfaceInterface *origin, SurfaceInterface *i)
|
||||||
|
{
|
||||||
|
if (seat->pointer()->focusedSurface() != origin) {
|
||||||
|
wl_resource_post_error(device, 0, "Surface doesn't have pointer grab");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
source = dataSource;
|
||||||
|
surface = origin;
|
||||||
|
icon = i;
|
||||||
|
emit q->dragStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDeviceInterface::Private::setSelectionCallback(wl_client *client, wl_resource *resource, wl_resource *source, uint32_t serial)
|
||||||
|
{
|
||||||
|
Q_UNUSED(client)
|
||||||
|
Q_UNUSED(serial)
|
||||||
|
// TODO: verify serial
|
||||||
|
cast(resource)->setSelection(DataSourceInterface::get(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDeviceInterface::Private::setSelection(DataSourceInterface *dataSource)
|
||||||
|
{
|
||||||
|
selection = dataSource;
|
||||||
|
if (selection) {
|
||||||
|
emit q->selectionChanged(selection);
|
||||||
|
} else {
|
||||||
|
emit q->selectionCleared();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDeviceInterface::Private::unbind(wl_resource *resource)
|
||||||
|
{
|
||||||
|
auto s = cast(resource);
|
||||||
|
s->device = nullptr;
|
||||||
|
s->q->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDeviceInterface::Private::create(wl_client *client, quint32 version, quint32 id)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!device);
|
||||||
|
device = wl_resource_create(client, &wl_data_device_interface, version, id);
|
||||||
|
if (!device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_resource_set_implementation(device, &s_interface, this, unbind);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataDeviceInterface::DataDeviceInterface(SeatInterface *seat, DataDeviceManagerInterface *parent)
|
||||||
|
: QObject(/*parent*/)
|
||||||
|
, d(new Private(seat, this))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DataDeviceInterface::~DataDeviceInterface() = default;
|
||||||
|
|
||||||
|
void DataDeviceInterface::create(wl_client *client, quint32 version, quint32 id)
|
||||||
|
{
|
||||||
|
d->create(client, version, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
SeatInterface *DataDeviceInterface::seat() const
|
||||||
|
{
|
||||||
|
return d->seat;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource *DataDeviceInterface::resource() const
|
||||||
|
{
|
||||||
|
return d->device;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSourceInterface *DataDeviceInterface::dragSource() const
|
||||||
|
{
|
||||||
|
return d->source;
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceInterface *DataDeviceInterface::icon() const
|
||||||
|
{
|
||||||
|
return d->icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceInterface *DataDeviceInterface::origin() const
|
||||||
|
{
|
||||||
|
return d->surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSourceInterface *DataDeviceInterface::selection() const
|
||||||
|
{
|
||||||
|
return d->selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
75
src/wayland/datadevice_interface.h
Normal file
75
src/wayland/datadevice_interface.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/********************************************************************
|
||||||
|
Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) version 3, or any
|
||||||
|
later version accepted by the membership of KDE e.V. (or its
|
||||||
|
successor approved by the membership of KDE e.V.), which shall
|
||||||
|
act as a proxy defined in Section 6 of version 3 of the license.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef WAYLAND_SERVER_DATA_DEVICE_INTERFACE_H
|
||||||
|
#define WAYLAND_SERVER_DATA_DEVICE_INTERFACE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <KWayland/Server/kwaylandserver_export.h>
|
||||||
|
|
||||||
|
struct wl_client;
|
||||||
|
struct wl_resource;
|
||||||
|
|
||||||
|
namespace KWayland
|
||||||
|
{
|
||||||
|
namespace Server
|
||||||
|
{
|
||||||
|
|
||||||
|
class DataDeviceManagerInterface;
|
||||||
|
class DataSourceInterface;
|
||||||
|
class SeatInterface;
|
||||||
|
class SurfaceInterface;
|
||||||
|
|
||||||
|
class KWAYLANDSERVER_EXPORT DataDeviceInterface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
virtual ~DataDeviceInterface();
|
||||||
|
|
||||||
|
void create(wl_client *client, quint32 version, quint32 id);
|
||||||
|
|
||||||
|
SeatInterface *seat() const;
|
||||||
|
DataSourceInterface *dragSource() const;
|
||||||
|
SurfaceInterface *origin() const;
|
||||||
|
SurfaceInterface *icon() const;
|
||||||
|
|
||||||
|
DataSourceInterface *selection() const;
|
||||||
|
|
||||||
|
wl_resource *resource() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void dragStarted();
|
||||||
|
void selectionChanged(KWayland::Server::DataSourceInterface*);
|
||||||
|
void selectionCleared();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class DataDeviceManagerInterface;
|
||||||
|
explicit DataDeviceInterface(SeatInterface *seat, DataDeviceManagerInterface *parent);
|
||||||
|
|
||||||
|
class Private;
|
||||||
|
QScopedPointer<Private> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(KWayland::Server::DataDeviceInterface*)
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,6 +19,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
#include "datadevicemanager_interface.h"
|
#include "datadevicemanager_interface.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "seat_interface.h"
|
||||||
// Wayland
|
// Wayland
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void bind(wl_client *client, uint32_t version, uint32_t id);
|
void bind(wl_client *client, uint32_t version, uint32_t id);
|
||||||
void createDataSource(wl_client *client, wl_resource *resource, uint32_t id);
|
void createDataSource(wl_client *client, wl_resource *resource, uint32_t id);
|
||||||
|
void getDataDevice(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat);
|
||||||
|
|
||||||
static void bind(wl_client *client, void *data, uint32_t version, uint32_t id);
|
static void bind(wl_client *client, void *data, uint32_t version, uint32_t id);
|
||||||
static void unbind(wl_resource *resource);
|
static void unbind(wl_resource *resource);
|
||||||
|
@ -109,10 +111,18 @@ void DataDeviceManagerInterface::Private::createDataSource(wl_client *client, wl
|
||||||
|
|
||||||
void DataDeviceManagerInterface::Private::getDataDeviceCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat)
|
void DataDeviceManagerInterface::Private::getDataDeviceCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat)
|
||||||
{
|
{
|
||||||
Q_UNUSED(client)
|
cast(resource)->getDataDevice(client, resource, id, seat);
|
||||||
Q_UNUSED(resource)
|
}
|
||||||
Q_UNUSED(id)
|
|
||||||
Q_UNUSED(seat)
|
void DataDeviceManagerInterface::Private::getDataDevice(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat)
|
||||||
|
{
|
||||||
|
DataDeviceInterface *dataDevice = new DataDeviceInterface(SeatInterface::get(seat), q);
|
||||||
|
dataDevice->create(client, wl_resource_get_version(resource), id);
|
||||||
|
if (!dataDevice->resource()) {
|
||||||
|
wl_resource_post_no_memory(resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit q->dataDeviceCreated(dataDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataDeviceManagerInterface::Private::create()
|
void DataDeviceManagerInterface::Private::create()
|
||||||
|
|
|
@ -23,6 +23,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include <KWayland/Server/kwaylandserver_export.h>
|
#include <KWayland/Server/kwaylandserver_export.h>
|
||||||
|
#include "datadevice_interface.h"
|
||||||
#include "datasource_interface.h"
|
#include "datasource_interface.h"
|
||||||
|
|
||||||
namespace KWayland
|
namespace KWayland
|
||||||
|
@ -31,7 +32,6 @@ namespace Server
|
||||||
{
|
{
|
||||||
|
|
||||||
class Display;
|
class Display;
|
||||||
class DataSourceInterface;
|
|
||||||
|
|
||||||
class KWAYLANDSERVER_EXPORT DataDeviceManagerInterface : public QObject
|
class KWAYLANDSERVER_EXPORT DataDeviceManagerInterface : public QObject
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,7 @@ public:
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void dataSourceCreated(DataSourceInterface*);
|
void dataSourceCreated(DataSourceInterface*);
|
||||||
|
void dataDeviceCreated(KWayland::Server::DataDeviceInterface*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DataDeviceManagerInterface(Display *display, QObject *parent = nullptr);
|
explicit DataDeviceManagerInterface(Display *display, QObject *parent = nullptr);
|
||||||
|
|
Loading…
Reference in a new issue