commit kwayland for openSUSE:Factory
Hello community, here is the log from the commit of package kwayland for openSUSE:Factory checked in at 2016-10-28 12:24:12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kwayland (Old) and /work/SRC/openSUSE:Factory/.kwayland.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "kwayland" Changes: -------- --- /work/SRC/openSUSE:Factory/kwayland/kwayland.changes 2016-09-14 23:28:58.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.kwayland.new/kwayland.changes 2016-10-28 12:24:13.000000000 +0200 @@ -1,0 +2,13 @@ +Sun Oct 2 13:00:34 UTC 2016 - hrvoje.senjan@gmail.com + +- Update to 5.27.0 + * [server] Don't send key release for not pressed keys and + no double key press (kde#366625) + * [server] When replacing the clipboard selection previous + DataSource needs to be cancelled (kde#368391) + * Add support for Surface enter/leave events + * [client] Track all created Outputs and add static get method + * For more details please see: + https://www.kde.org/announcements/kde-frameworks-5.27.0.php + +------------------------------------------------------------------- Old: ---- kwayland-5.26.0.tar.xz New: ---- kwayland-5.27.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kwayland.spec ++++++ --- /var/tmp/diff_new_pack.pZHLJn/_old 2016-10-28 12:24:14.000000000 +0200 +++ /var/tmp/diff_new_pack.pZHLJn/_new 2016-10-28 12:24:14.000000000 +0200 @@ -16,9 +16,9 @@ # -%define _tar_path 5.26 +%define _tar_path 5.27 Name: kwayland -Version: 5.26.0 +Version: 5.27.0 Release: 0 Summary: KDE Wayland library License: LGPL-2.1+ ++++++ kwayland-5.26.0.tar.xz -> kwayland-5.27.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/CMakeLists.txt new/kwayland-5.27.0/CMakeLists.txt --- old/kwayland-5.26.0/CMakeLists.txt 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/CMakeLists.txt 2016-10-02 10:13:48.000000000 +0200 @@ -4,7 +4,7 @@ # ECM setup include(FeatureSummary) -find_package(ECM 5.26.0 NO_MODULE) +find_package(ECM 5.27.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) @@ -18,7 +18,7 @@ include(ECMPoQmTools) -set(KF5_VERSION "5.26.0") # handled by release scripts +set(KF5_VERSION "5.27.0") # handled by release scripts ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX KWAYLAND VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kwayland_version.h" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/autotests/client/test_datadevice.cpp new/kwayland-5.27.0/autotests/client/test_datadevice.cpp --- old/kwayland-5.26.0/autotests/client/test_datadevice.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/autotests/client/test_datadevice.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -53,6 +53,7 @@ void testDragInternally(); void testSetSelection(); void testSendSelectionOnSeat(); + void testReplaceSource(); void testDestroy(); private: @@ -455,6 +456,79 @@ m_seatInterface->setFocusedKeyboardSurface(serverSurface); } +void TestDataDevice::testReplaceSource() +{ + // this test verifies that replacing a data source cancels the previous source + using namespace KWayland::Client; + using namespace KWayland::Server; + // first add keyboard support to Seat + QSignalSpy keyboardChangedSpy(m_seat, &Seat::hasKeyboardChanged); + QVERIFY(keyboardChangedSpy.isValid()); + m_seatInterface->setHasKeyboard(true); + QVERIFY(keyboardChangedSpy.wait()); + // now create DataDevice, Keyboard and a Surface + QSignalSpy dataDeviceCreatedSpy(m_dataDeviceManagerInterface, &DataDeviceManagerInterface::dataDeviceCreated); + QVERIFY(dataDeviceCreatedSpy.isValid()); + QScopedPointer<DataDevice> dataDevice(m_dataDeviceManager->getDataDevice(m_seat)); + QVERIFY(dataDevice->isValid()); + QVERIFY(dataDeviceCreatedSpy.wait()); + auto serverDataDevice = dataDeviceCreatedSpy.first().first().value<DataDeviceInterface*>(); + QVERIFY(serverDataDevice); + QScopedPointer<Keyboard> keyboard(m_seat->createKeyboard()); + QVERIFY(keyboard->isValid()); + QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); + QVERIFY(surfaceCreatedSpy.isValid()); + QScopedPointer<Surface> surface(m_compositor->createSurface()); + QVERIFY(surface->isValid()); + QVERIFY(surfaceCreatedSpy.wait()); + + auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>(); + QVERIFY(serverSurface); + m_seatInterface->setFocusedKeyboardSurface(serverSurface); + + // now set the selection + QScopedPointer<DataSource> dataSource(m_dataDeviceManager->createDataSource()); + QVERIFY(dataSource->isValid()); + dataSource->offer(QStringLiteral("text/plain")); + dataDevice->setSelection(1, dataSource.data()); + QSignalSpy sourceCancelledSpy(dataSource.data(), &DataSource::cancelled); + QVERIFY(sourceCancelledSpy.isValid()); + // we should get a selection offered for that on the data device + QSignalSpy selectionOfferedSpy(dataDevice.data(), &DataDevice::selectionOffered); + QVERIFY(selectionOfferedSpy.isValid()); + QVERIFY(selectionOfferedSpy.wait()); + QCOMPARE(selectionOfferedSpy.count(), 1); + + // create a second data source and replace previous one + QScopedPointer<DataSource> dataSource2(m_dataDeviceManager->createDataSource()); + QVERIFY(dataSource2->isValid()); + dataSource2->offer(QStringLiteral("text/plain")); + QSignalSpy sourceCancelled2Spy(dataSource2.data(), &DataSource::cancelled); + QVERIFY(sourceCancelled2Spy.isValid()); + dataDevice->setSelection(1, dataSource2.data()); + QCOMPARE(selectionOfferedSpy.count(), 1); + QVERIFY(sourceCancelledSpy.wait()); + QCOMPARE(selectionOfferedSpy.count(), 2); + QVERIFY(sourceCancelled2Spy.isEmpty()); + + // create a new DataDevice and replace previous one + QScopedPointer<DataDevice> dataDevice2(m_dataDeviceManager->getDataDevice(m_seat)); + QVERIFY(dataDevice2->isValid()); + QScopedPointer<DataSource> dataSource3(m_dataDeviceManager->createDataSource()); + QVERIFY(dataSource3->isValid()); + dataSource3->offer(QStringLiteral("text/plain")); + dataDevice2->setSelection(1, dataSource3.data()); + QVERIFY(sourceCancelled2Spy.wait()); + + // try to crash by first destroying dataSource3 and setting a new DataSource + QScopedPointer<DataSource> dataSource4(m_dataDeviceManager->createDataSource()); + QVERIFY(dataSource4->isValid()); + dataSource4->offer(QStringLiteral("text/plain")); + dataSource3.reset(); + dataDevice2->setSelection(1, dataSource4.data()); + QVERIFY(selectionOfferedSpy.wait()); +} + void TestDataDevice::testDestroy() { using namespace KWayland::Client; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/autotests/client/test_wayland_output.cpp new/kwayland-5.27.0/autotests/client/test_wayland_output.cpp --- old/kwayland-5.26.0/autotests/client/test_wayland_output.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/autotests/client/test_wayland_output.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -185,7 +185,10 @@ QSignalSpy outputChanged(&output, SIGNAL(changed())); QVERIFY(outputChanged.isValid()); - output.setup(registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>())); + auto o = registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>()); + QVERIFY(!KWayland::Client::Output::get(o)); + output.setup(o); + QCOMPARE(KWayland::Client::Output::get(o), &output); wl_display_flush(m_connection->display()); QVERIFY(outputChanged.wait()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/autotests/client/test_wayland_seat.cpp new/kwayland-5.27.0/autotests/client/test_wayland_seat.cpp --- old/kwayland-5.26.0/autotests/client/test_wayland_seat.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/autotests/client/test_wayland_seat.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -1201,6 +1201,21 @@ QCOMPARE(keyChangedSpy.at(4).at(1).value<Keyboard::KeyState>(), Keyboard::KeyState::Released); QCOMPARE(keyChangedSpy.at(4).at(2).value<quint32>(), quint32(8)); + // releasing a key which is already released should not set a key changed + m_seatInterface->keyReleased(KEY_F1); + QVERIFY(!keyChangedSpy.wait(200)); + // let's press it again + m_seatInterface->keyPressed(KEY_F1); + QVERIFY(keyChangedSpy.wait()); + QCOMPARE(keyChangedSpy.count(), 6); + // press again should be ignored + m_seatInterface->keyPressed(KEY_F1); + QVERIFY(!keyChangedSpy.wait(200)); + // and release + m_seatInterface->keyReleased(KEY_F1); + QVERIFY(keyChangedSpy.wait()); + QCOMPARE(keyChangedSpy.count(), 7); + m_seatInterface->updateKeyboardModifiers(1, 2, 3, 4); QVERIFY(modifierSpy.wait()); QCOMPARE(modifierSpy.count(), 2); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/autotests/client/test_wayland_surface.cpp new/kwayland-5.27.0/autotests/client/test_wayland_surface.cpp --- old/kwayland-5.26.0/autotests/client/test_wayland_surface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/autotests/client/test_wayland_surface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -25,6 +25,7 @@ #include "../../src/client/compositor.h" #include "../../src/client/connection_thread.h" #include "../../src/client/event_queue.h" +#include "../../src/client/output.h" #include "../../src/client/surface.h" #include "../../src/client/region.h" #include "../../src/client/registry.h" @@ -59,6 +60,7 @@ void testSurfaceAt(); void testDestroyAttachedBuffer(); void testDestroyWithPendingCallback(); + void testOutput(); void testDisconnect(); private: @@ -956,5 +958,78 @@ m_queue->destroy(); } +void TestWaylandSurface::testOutput() +{ + // This test verifies that the enter/leave are sent correctly to the Client + using namespace KWayland::Client; + using namespace KWayland::Server; + qRegisterMetaType<KWayland::Client::Output*>(); + QScopedPointer<Surface> s(m_compositor->createSurface()); + QVERIFY(!s.isNull()); + QVERIFY(s->isValid()); + QVERIFY(s->outputs().isEmpty()); + QSignalSpy enteredSpy(s.data(), &Surface::outputEntered); + QVERIFY(enteredSpy.isValid()); + QSignalSpy leftSpy(s.data(), &Surface::outputLeft); + QVERIFY(leftSpy.isValid()); + // wait for the surface on the Server side + QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); + QVERIFY(surfaceCreatedSpy.isValid()); + QVERIFY(surfaceCreatedSpy.wait()); + auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>(); + QVERIFY(serverSurface); + QCOMPARE(serverSurface->outputs(), QVector<OutputInterface*>()); + + // create another registry to get notified about added outputs + Registry registry; + registry.setEventQueue(m_queue); + QSignalSpy allAnnounced(®istry, &Registry::interfacesAnnounced); + QVERIFY(allAnnounced.isValid()); + registry.create(m_connection); + QVERIFY(registry.isValid()); + registry.setup(); + QVERIFY(allAnnounced.wait()); + QSignalSpy outputAnnouncedSpy(®istry, &Registry::outputAnnounced); + QVERIFY(outputAnnouncedSpy.isValid()); + + auto serverOutput = m_display->createOutput(m_display); + serverOutput->create(); + QVERIFY(outputAnnouncedSpy.wait()); + QScopedPointer<Output> clientOutput(registry.createOutput(outputAnnouncedSpy.first().first().value<quint32>(), outputAnnouncedSpy.first().last().value<quint32>())); + QVERIFY(clientOutput->isValid()); + m_connection->flush(); + m_display->dispatchEvents(); + + // now enter it + serverSurface->setOutputs(QVector<OutputInterface*>{serverOutput}); + QCOMPARE(serverSurface->outputs(), QVector<OutputInterface*>{serverOutput}); + QVERIFY(enteredSpy.wait()); + QCOMPARE(enteredSpy.count(), 1); + QCOMPARE(enteredSpy.first().first().value<Output*>(), clientOutput.data()); + QCOMPARE(s->outputs(), QVector<Output*>{clientOutput.data()}); + + // adding to same should not trigger + serverSurface->setOutputs(QVector<OutputInterface*>{serverOutput}); + + // leave again + serverSurface->setOutputs(QVector<OutputInterface*>()); + QCOMPARE(serverSurface->outputs(), QVector<OutputInterface*>()); + QVERIFY(leftSpy.wait()); + QCOMPARE(enteredSpy.count(), 1); + QCOMPARE(leftSpy.count(), 1); + QCOMPARE(leftSpy.first().first().value<Output*>(), clientOutput.data()); + QCOMPARE(s->outputs(), QVector<Output*>()); + + // leave again should not trigger + serverSurface->setOutputs(QVector<OutputInterface*>()); + + // and enter again, just to verify + serverSurface->setOutputs(QVector<OutputInterface*>{serverOutput}); + QCOMPARE(serverSurface->outputs(), QVector<OutputInterface*>{serverOutput}); + QVERIFY(enteredSpy.wait()); + QCOMPARE(enteredSpy.count(), 2); + QCOMPARE(leftSpy.count(), 1); +} + QTEST_GUILESS_MAIN(TestWaylandSurface) #include "test_wayland_surface.moc" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/client/output.cpp new/kwayland-5.27.0/src/client/output.cpp --- old/kwayland-5.26.0/src/client/output.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/client/output.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -23,6 +23,7 @@ #include <QPoint> #include <QRect> #include <QSize> +#include <QVector> // wayland #include <wayland-client-protocol.h> @@ -40,6 +41,7 @@ { public: Private(Output *q); + ~Private(); void setup(wl_output *o); WaylandPointer<wl_output, wl_output_destroy> output; @@ -54,6 +56,8 @@ Modes modes; Modes::iterator currentMode = modes.end(); + static Output *get(wl_output *o); + private: static void geometryCallback(void *data, wl_output *output, int32_t x, int32_t y, int32_t physicalWidth, int32_t physicalHeight, int32_t subPixel, @@ -72,11 +76,35 @@ Output *q; static struct wl_output_listener s_outputListener; + + static QVector<Private*> s_allOutputs; }; +QVector<Output::Private*> Output::Private::s_allOutputs; + Output::Private::Private(Output *q) : q(q) { + s_allOutputs << this; +} + +Output::Private::~Private() +{ + s_allOutputs.removeOne(this); +} + +Output *Output::Private::get(wl_output *o) +{ + auto it = std::find_if(s_allOutputs.constBegin(), s_allOutputs.constEnd(), + [o] (Private *p) { + const wl_output *reference = p->output; + return reference == o; + } + ); + if (it != s_allOutputs.constEnd()) { + return (*it)->q; + } + return nullptr; } void Output::Private::setup(wl_output *o) @@ -358,5 +386,10 @@ return d->output; } +Output *Output::get(wl_output *o) +{ + return Private::get(o); +} + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/client/output.h new/kwayland-5.27.0/src/client/output.h --- old/kwayland-5.26.0/src/client/output.h 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/client/output.h 2016-10-02 10:13:48.000000000 +0200 @@ -198,6 +198,12 @@ **/ EventQueue *eventQueue() const; + /** + * @returns The Output for the @p native wl_output. @c null if there is no Output for it. + * @since 5.27 + **/ + static Output *get(wl_output *native); + Q_SIGNALS: /** * Emitted whenever at least one of the data changed. @@ -236,6 +242,7 @@ } } +Q_DECLARE_METATYPE(KWayland::Client::Output*) Q_DECLARE_METATYPE(KWayland::Client::Output::SubPixel) Q_DECLARE_METATYPE(KWayland::Client::Output::Transform) Q_DECLARE_METATYPE(KWayland::Client::Output::Mode) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/client/surface.cpp new/kwayland-5.27.0/src/client/surface.cpp --- old/kwayland-5.26.0/src/client/surface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/client/surface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -20,6 +20,7 @@ #include "surface.h" #include "buffer.h" #include "region.h" +#include "output.h" #include "wayland_pointer_p.h" #include <QGuiApplication> @@ -46,14 +47,20 @@ QSize size; bool foreign = false; qint32 scale = 1; + QVector<Output *> outputs; + + void setup(wl_surface *s); static QList<Surface*> s_surfaces; private: void handleFrameCallback(); static void frameCallback(void *data, wl_callback *callback, uint32_t time); + static void enterCallback(void *data, wl_surface *wl_surface, wl_output *output); + static void leaveCallback(void *data, wl_surface *wl_surface, wl_output *output); Surface *q; static const wl_callback_listener s_listener; + static const wl_surface_listener s_surfaceListener; }; QList<Surface*> Surface::Private::s_surfaces = QList<Surface*>(); @@ -130,9 +137,15 @@ void Surface::setup(wl_surface *surface) { - Q_ASSERT(surface); - Q_ASSERT(!d->surface); - d->surface.setup(surface); + d->setup(surface); +} + +void Surface::Private::setup(wl_surface *s) +{ + Q_ASSERT(s); + Q_ASSERT(!surface); + surface.setup(s); + wl_surface_add_listener(s, &s_surfaceListener, this); } void Surface::Private::frameCallback(void *data, wl_callback *callback, uint32_t time) @@ -155,8 +168,37 @@ const struct wl_callback_listener Surface::Private::s_listener = { frameCallback }; + +const struct wl_surface_listener Surface::Private::s_surfaceListener = { + enterCallback, + leaveCallback +}; #endif +void Surface::Private::enterCallback(void *data, wl_surface *surface, wl_output *output) +{ + Q_UNUSED(surface); + auto s = reinterpret_cast<Surface::Private*>(data); + Output *o = Output::get(output); + if (!o) { + return; + } + s->outputs << o; + emit s->q->outputEntered(o); +} + +void Surface::Private::leaveCallback(void *data, wl_surface *surface, wl_output *output) +{ + Q_UNUSED(surface); + auto s = reinterpret_cast<Surface::Private*>(data); + Output *o = Output::get(output); + if (!o) { + return; + } + s->outputs.removeOne(o); + emit s->q->outputLeft(o); +} + void Surface::Private::setupFrameCallback() { Q_ASSERT(!frameCallbackInstalled); @@ -293,5 +335,10 @@ wl_surface_set_buffer_scale(d->surface, scale); } +QVector<Output *> Surface::outputs() const +{ + return d->outputs; +} + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/client/surface.h new/kwayland-5.27.0/src/client/surface.h --- old/kwayland-5.26.0/src/client/surface.h 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/client/surface.h 2016-10-02 10:13:48.000000000 +0200 @@ -39,6 +39,7 @@ namespace Client { +class Output; class Region; /** @@ -238,6 +239,14 @@ quint32 id() const; /** + * @returns All Outputs the Surface is on, may be none. + * @see outputEntered + * @see outputLeft + * @since 5.27 + **/ + QVector<Output *> outputs() const; + + /** * All Surfaces which are currently created. * TODO: KF6 return QList<Surface*> instead of const-ref **/ @@ -258,6 +267,28 @@ void frameRendered(); void sizeChanged(const QSize&); + /** + * Emitted whenever a change in the Surface (e.g. creation, movement, resize) results in + * a part of the Surface being within the scanout region of the Output @p o. + * + * @param o The Output the Surface intersects with + * @see outputLeft + * @see outputs + * @since 5.27 + **/ + void outputEntered(KWayland::Client::Output *o); + + /** + * Emitted whenever a change in the Surface (e.g. creation, movement, resize, unmapping) + * results in the Surface no longer being within the scanout region of the Output @p o. + * + * @param o The Output the Surface no longer intersects with + * @see outputEntered + * @see outputs + * @since 5.27 + **/ + void outputLeft(KWayland::Client::Output *o); + private: class Private; QScopedPointer<Private> d; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/datadevice_interface.cpp new/kwayland-5.27.0/src/server/datadevice_interface.cpp --- old/kwayland-5.26.0/src/server/datadevice_interface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/datadevice_interface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -48,6 +48,8 @@ SurfaceInterface *icon = nullptr; DataSourceInterface *selection = nullptr; + QMetaObject::Connection selectionUnboundConnection; + QMetaObject::Connection selectionDestroyedConnection; struct Drag { SurfaceInterface *surface = nullptr; @@ -120,10 +122,22 @@ void DataDeviceInterface::Private::setSelection(DataSourceInterface *dataSource) { Q_Q(DataDeviceInterface); + QObject::disconnect(selectionUnboundConnection); + QObject::disconnect(selectionDestroyedConnection); + if (selection) { + selection->cancel(); + } selection = dataSource; if (selection) { + auto clearSelection = [this] { + setSelection(nullptr); + }; + selectionUnboundConnection = QObject::connect(selection, &Resource::unbound, q, clearSelection); + selectionDestroyedConnection = QObject::connect(selection, &QObject::destroyed, q, clearSelection); emit q->selectionChanged(selection); } else { + selectionUnboundConnection = QMetaObject::Connection(); + selectionDestroyedConnection = QMetaObject::Connection(); emit q->selectionCleared(); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/datasource_interface.cpp new/kwayland-5.27.0/src/server/datasource_interface.cpp --- old/kwayland-5.26.0/src/server/datasource_interface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/datasource_interface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -19,6 +19,7 @@ *********************************************************************/ #include "datasource_interface.h" #include "datadevicemanager_interface.h" +#include "clientconnection.h" #include "resource_p.h" // Qt #include <QStringList> @@ -103,7 +104,11 @@ void DataSourceInterface::cancel() { Q_D(); + if (!d->resource) { + return; + } wl_data_source_send_cancelled(d->resource); + client()->flush(); } QStringList DataSourceInterface::mimeTypes() const diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/output_interface.cpp new/kwayland-5.27.0/src/server/output_interface.cpp --- old/kwayland-5.26.0/src/server/output_interface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/output_interface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -506,6 +506,18 @@ return d->dpms.supported; } +QVector<wl_resource *> OutputInterface::clientResources(ClientConnection *client) const +{ + Q_D(); + QVector<wl_resource *> ret; + for (auto it = d->resources.constBegin(), end = d->resources.constEnd(); it != end; ++it) { + if (wl_resource_get_client((*it).resource) == client->client()) { + ret << (*it).resource; + } + } + return ret; +} + OutputInterface *OutputInterface::get(wl_resource* native) { return Private::get(native); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/output_interface.h new/kwayland-5.27.0/src/server/output_interface.h --- old/kwayland-5.26.0/src/server/output_interface.h 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/output_interface.h 2016-10-02 10:13:48.000000000 +0200 @@ -36,6 +36,7 @@ namespace Server { +class ClientConnection; class Display; /** @@ -125,6 +126,12 @@ **/ void setDpmsMode(DpmsMode mode); + /** + * @returns all wl_resources bound for the @p client + * @since 5.27 + **/ + QVector<wl_resource *> clientResources(ClientConnection *client) const; + static OutputInterface *get(wl_resource *native); Q_SIGNALS: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/seat_interface.cpp new/kwayland-5.27.0/src/server/seat_interface.cpp --- old/kwayland-5.26.0/src/server/seat_interface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/seat_interface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -132,14 +132,18 @@ it.value() = state; } -void SeatInterface::Private::updateKey(quint32 key, Keyboard::State state) +bool SeatInterface::Private::updateKey(quint32 key, Keyboard::State state) { auto it = keys.states.find(key); if (it == keys.states.end()) { keys.states.insert(key, state); - return; + return true; + } + if (it.value() == state) { + return false; } it.value() = state; + return true; } void SeatInterface::Private::sendName(wl_resource *r) @@ -321,6 +325,16 @@ void SeatInterface::Private::updateSelection(DataDeviceInterface *dataDevice, bool set) { if (keys.focus.surface && (keys.focus.surface->client() == dataDevice->client())) { + if (currentSelection) { + // cancel the previous selection + if (auto s = currentSelection->selection()) { + if (currentSelection != dataDevice) { + // only if current selection is not on the same device + // that would cancel the newly set source + s->cancel(); + } + } + } // new selection on a data device belonging to current keyboard focus currentSelection = dataDevice; } @@ -815,7 +829,9 @@ { Q_D(); d->keys.lastStateSerial = d->display->nextSerial(); - d->updateKey(key, Private::Keyboard::State::Pressed); + if (!d->updateKey(key, Private::Keyboard::State::Pressed)) { + return; + } if (d->keys.focus.keyboard && d->keys.focus.surface) { d->keys.focus.keyboard->keyPressed(key, d->keys.lastStateSerial); } @@ -825,7 +841,9 @@ { Q_D(); d->keys.lastStateSerial = d->display->nextSerial(); - d->updateKey(key, Private::Keyboard::State::Released); + if (!d->updateKey(key, Private::Keyboard::State::Released)) { + return; + } if (d->keys.focus.keyboard && d->keys.focus.surface) { d->keys.focus.keyboard->keyReleased(key, d->keys.lastStateSerial); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/seat_interface_p.h new/kwayland-5.27.0/src/server/seat_interface_p.h --- old/kwayland-5.26.0/src/server/seat_interface_p.h 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/seat_interface_p.h 2016-10-02 10:13:48.000000000 +0200 @@ -124,7 +124,7 @@ } keyRepeat; }; Keyboard keys; - void updateKey(quint32 key, Keyboard::State state); + bool updateKey(quint32 key, Keyboard::State state); struct TextInput { struct Focus { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/surface_interface.cpp new/kwayland-5.27.0/src/server/surface_interface.cpp --- old/kwayland-5.26.0/src/server/surface_interface.cpp 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/surface_interface.cpp 2016-10-02 10:13:48.000000000 +0200 @@ -688,6 +688,44 @@ d->trackedDamage = QRegion(); } +QVector<OutputInterface *> SurfaceInterface::outputs() const +{ + Q_D(); + return d->outputs; +} + +void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs) +{ + Q_D(); + QVector<OutputInterface *> removedOutputs = d->outputs; + for (auto it = outputs.constBegin(), end = outputs.constEnd(); it != end; ++it) { + const auto o = *it; + removedOutputs.removeOne(o); + } + for (auto it = removedOutputs.constBegin(), end = removedOutputs.constEnd(); it != end; ++it) { + const auto resources = (*it)->clientResources(client()); + for (wl_resource *r : resources) { + wl_surface_send_leave(d->resource, r); + } + } + // TODO: send leave when OutputInterface gets destroyed + + QVector<OutputInterface *> addedOutputsOutputs = outputs; + for (auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) { + const auto o = *it; + addedOutputsOutputs.removeOne(o); + } + for (auto it = addedOutputsOutputs.constBegin(), end = addedOutputsOutputs.constEnd(); it != end; ++it) { + const auto resources = (*it)->clientResources(client()); + for (wl_resource *r : resources) { + wl_surface_send_enter(d->resource, r); + } + } + // TODO: send enter when the client binds the OutputInterface another time + + d->outputs = outputs; +} + SurfaceInterface *SurfaceInterface::surfaceAt(const QPointF &position) { if (!isMapped()) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/surface_interface.h new/kwayland-5.27.0/src/server/surface_interface.h --- old/kwayland-5.26.0/src/server/surface_interface.h 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/surface_interface.h 2016-10-02 10:13:48.000000000 +0200 @@ -206,6 +206,24 @@ SurfaceInterface *surfaceAt(const QPointF &position); /** + * Sets the @p outputs this SurfaceInterface overlaps with, may be empty. + * + * The compositor should update whenever the SurfaceInterface becomes visible on + * an OutputInterface by e.g. getting (un)mapped, resized, moved, etc. + * + * @see outputs + * @since 5.27 + **/ + void setOutputs(const QVector<OutputInterface *> &outputs); + + /** + * @returns All OutputInterfaces the SurfaceInterface is on. + * @see setOutputs + * @since 5.27 + **/ + QVector<OutputInterface *> outputs() const; + + /** * @returns The SurfaceInterface for the @p native resource. **/ static SurfaceInterface *get(wl_resource *native); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kwayland-5.26.0/src/server/surface_interface_p.h new/kwayland-5.27.0/src/server/surface_interface_p.h --- old/kwayland-5.26.0/src/server/surface_interface_p.h 2016-09-06 00:44:32.000000000 +0200 +++ new/kwayland-5.27.0/src/server/surface_interface_p.h 2016-10-02 10:13:48.000000000 +0200 @@ -22,6 +22,8 @@ #include "surface_interface.h" #include "resource_p.h" +// Qt +#include <QVector> // Wayland #include <wayland-server.h> @@ -89,6 +91,8 @@ // waiting on the frame callback of the never visible surface bool subSurfaceIsMapped = true; + QVector<OutputInterface *> outputs; + private: SurfaceInterface *q_func() { return reinterpret_cast<SurfaceInterface *>(q);
participants (1)
-
root@hilbert.suse.de