Send output enter/leave events to surfaces
ClosedPublic

Authored by davidedmundson on Aug 17 2017, 12:29 AM.

Details

Summary

A surface has an API to know which screen(s) it's on, this is useful
especially for knowing the scale it should render at.

In practice Qt currently doesn't do anything with this information; but
that's set to change.

Test_helpers is changed as we need to create output objects in order for
wl_surface to map them.

Closes task T4467

Test Plan

Attached unit test.
As mentioned above, it doesn't have any real world impact currently, so not a lot
to test.

Diff Detail

Repository
R108 KWin
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
Restricted Application added a project: KWin. · View Herald TranscriptAug 17 2017, 12:29 AM
Restricted Application added subscribers: KWin, kwin, plasma-devel. · View Herald Transcript

I'm wondering whether we should do it directly in Toplevel as we also have the XWayland windows which have a Surface.

Overall looks good! It's way more self contained than I expected when first thinking about it.

autotests/integration/test_helpers.cpp
110–113 ↗(On Diff #18276)

You also need to handle the outputRemoved. We have a few tests which add/remove Outputs.

shell_client.cpp
1533

two minor comments here: qAsConst and a whitespace after for :-)

I'm wondering whether we should do it directly in Toplevel as we also have the XWayland windows which have a Surface.

I don't think XWayland windows can really make use of this. X windows know the screen sizes and their own location, so it doesn't really map to anything.
A quick grep of xwayland confirmed there wasn't even a wl_surface_add_listener anywhere.

Restricted Application edited projects, added Plasma; removed KWin. · View Herald TranscriptAug 17 2017, 11:36 PM
davidedmundson marked 2 inline comments as done.Aug 17 2017, 11:36 PM

One question that I'm unsure of: subsurfaces.

A subsurface is still a surface, so from reading the API arguably they should also get enter/leave events...but at the same time it seems pointless.
From a Qt POV, subsurfaces always follow the screen of the parent window.

Any thoughts?

Restricted Application edited projects, added KWin; removed Plasma. · View Herald TranscriptAug 17 2017, 11:51 PM

One question that I'm unsure of: subsurfaces.

A subsurface is still a surface, so from reading the API arguably they should also get enter/leave events...but at the same time it seems pointless.
From a Qt POV, subsurfaces always follow the screen of the parent window.

Any thoughts?

I would say it doesn't make any sense to send it for sub-surfaces. Similar I don't think it makes sense for the cursor surface and other surface not as top level window.

I'm wondering whether we should do it directly in Toplevel as we also have the XWayland windows which have a Surface.

I don't think XWayland windows can really make use of this. X windows know the screen sizes and their own location, so it doesn't really map to anything.
A quick grep of xwayland confirmed there wasn't even a wl_surface_add_listener anywhere.

Point taken. My thinking was that XWayland might do something clever with it like scale up windows internally (send the windows a wrong geometry), but I guess that's just unreasonable wishful thinking. So good to go in ShellClient, if in a distant future XWayland becomes a valid target, we can move the code anyway.

graesslin accepted this revision.Aug 18 2017, 5:51 PM
This revision is now accepted and ready to land.Aug 18 2017, 5:51 PM
This revision was automatically updated to reflect the committed changes.

ASAN detected a heap-use-after-free:

=================================================================
==10094==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300003b060 at pc 0x7fa28cc7782f bp 0x7fff015a5610 sp 0x7fff015a5608
READ of size 8 at 0x60300003b060 thread T0
    #0 0x7fa28cc7782e in QScopedPointer<KWayland::Server::Global::Private, QScopedPointerDeleter<KWayland::Server::Global::Private> >::data() const /usr/include/qt5/QtCore/qscopedpointer.h:140
    #1 0x7fa28cc8bcbb in KWayland::Server::OutputInterface::d_func() const /home/jenkins/workspace/Dependency Build Plasma kf5-qt5 SUSEQt5.9/kwayland/src/server/output_interface.cpp:528
    #2 0x7fa28cc8b96a in KWayland::Server::OutputInterface::clientResources(KWayland::Server::ClientConnection*) const /home/jenkins/workspace/Dependency Build Plasma kf5-qt5 SUSEQt5.9/kwayland/src/server/output_interface.cpp:511
    #3 0x7fa28cd9a61f in KWayland::Server::SurfaceInterface::setOutputs(QVector<KWayland::Server::OutputInterface*> const&) /home/jenkins/workspace/Dependency Build Plasma kf5-qt5 SUSEQt5.9/kwayland/src/server/surface_interface.cpp:792
    #4 0x7fa299ea0c9e in KWin::ShellClient::updateClientOutputs() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/shell_client.cpp:1540
    #5 0x7fa299eb54e4 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWin::ShellClient::*)()>::call(void (KWin::ShellClient::*)(), KWin::ShellClient*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:136
    #6 0x7fa299eb3844 in void QtPrivate::FunctionPointer<void (KWin::ShellClient::*)()>::call<QtPrivate::List<>, void>(void (KWin::ShellClient::*)(), KWin::ShellClient*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:169
    #7 0x7fa299eb1202 in QtPrivate::QSlotObject<void (KWin::ShellClient::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobject_impl.h:120
    #8 0x7fa288d0535b in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x2ac35b)
    #9 0x7fa29a048150 in KWin::Screens::changed() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/kwin_autogen/EWIEGA46WW/moc_screens.cpp:262
    #10 0x7fa2999f577a in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWin::Screens::*)()>::call(void (KWin::Screens::*)(), KWin::Screens*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:136
    #11 0x7fa2999f5071 in void QtPrivate::FunctionPointer<void (KWin::Screens::*)()>::call<QtPrivate::List<>, void>(void (KWin::Screens::*)(), KWin::Screens*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:169
    #12 0x7fa2999f4cc8 in QtPrivate::QSlotObject<void (KWin::Screens::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobject_impl.h:120
    #13 0x7fa288d05c41 in QObject::event(QEvent*) (/usr/lib64/libQt5Core.so.5+0x2acc41)
    #14 0x7fa28a17893b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x16193b)
    #15 0x7fa28a17fcb3 in QApplication::notify(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x168cb3)
    #16 0x7fa288cd7d47 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (/usr/lib64/libQt5Core.so.5+0x27ed47)
    #17 0x7fa288cda334 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (/usr/lib64/libQt5Core.so.5+0x281334)
    #18 0x7fa288d2aa53 in QEventDispatcherUNIX::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (/usr/lib64/libQt5Core.so.5+0x2d1a53)
    #19 0x7fa273f4900c in QUnixEventDispatcherQPA::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (/home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/plugins/qpa/KWinQpaPlugin.so+0xd900c)
    #20 0x7fa288cd6359 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (/usr/lib64/libQt5Core.so.5+0x27d359)
    #21 0x44c1d2 in QTestEventLoop::enterLoopMSecs(int) /usr/include/qt5/QtTest/qtesteventloop.h:105
    #22 0x44cda2 in QSignalSpy::wait(int) /usr/include/qt5/QtTest/qsignalspy.h:149
    #23 0x41fff3 in KWin::PointerInputTest::testUpdateFocusAfterScreenChange() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/autotests/integration/pointer_input.cpp:298
    #24 0x446379 in KWin::PointerInputTest::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/autotests/integration/testPointerInput_autogen/include/pointer_input.moc:155
    #25 0x7fa288ce7ca5 in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (/usr/lib64/libQt5Core.so.5+0x28eca5)
    #26 0x7fa2987c9939  (/usr/lib64/libQt5Test.so.5+0x14939)
    #27 0x7fa2987ca63f  (/usr/lib64/libQt5Test.so.5+0x1563f)
    #28 0x7fa2987cab70  (/usr/lib64/libQt5Test.so.5+0x15b70)
    #29 0x7fa2987cb12a in QTest::qExec(QObject*, int, char**) (/usr/lib64/libQt5Test.so.5+0x1612a)
    #30 0x4460a5 in main /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/autotests/integration/pointer_input.cpp:1188
    #31 0x7fa287e22469 in __libc_start_main (/lib64/libc.so.6+0x20469)
    #32 0x40fe49 in _start (/home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/autotests/integration/testPointerInput+0x40fe49)

0x60300003b060 is located 16 bytes inside of 24-byte region [0x60300003b050,0x60300003b068)
freed by thread T0 here:
    #0 0x7fa29b7ec970 in operator delete(void*) (/usr/lib64/libasan.so.4+0xde970)
    #1 0x7fa28cc859fb in KWayland::Server::OutputInterface::~OutputInterface() /home/jenkins/workspace/Dependency Build Plasma kf5-qt5 SUSEQt5.9/kwayland/src/server/output_interface.h:46
    #2 0x7fa299ed88b8 in void qDeleteAll<QList<KWayland::Server::OutputInterface*>::const_iterator>(QList<KWayland::Server::OutputInterface*>::const_iterator, QList<KWayland::Server::OutputInterface*>::const_iterator) /usr/include/qt5/QtCore/qalgorithms.h:320
    #3 0x7fa299ed1daf in void qDeleteAll<QList<KWayland::Server::OutputInterface*> >(QList<KWayland::Server::OutputInterface*> const&) /usr/include/qt5/QtCore/qalgorithms.h:328
    #4 0x7fa299ebd92a in operator() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/wayland_server.cpp:371
    #5 0x7fa299eccc4e in call /usr/include/qt5/QtCore/qobjectdefs_impl.h:130
    #6 0x7fa299ecb626 in call<QtPrivate::List<>, void> /usr/include/qt5/QtCore/qobjectdefs_impl.h:240
    #7 0x7fa299ec85a8 in impl /usr/include/qt5/QtCore/qobject_impl.h:168
    #8 0x7fa288d0535b in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x2ac35b)
    #9 0x7fa29a048150 in KWin::Screens::changed() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/kwin_autogen/EWIEGA46WW/moc_screens.cpp:262
    #10 0x7fa2999f577a in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWin::Screens::*)()>::call(void (KWin::Screens::*)(), KWin::Screens*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:136
    #11 0x7fa2999f5071 in void QtPrivate::FunctionPointer<void (KWin::Screens::*)()>::call<QtPrivate::List<>, void>(void (KWin::Screens::*)(), KWin::Screens*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:169
    #12 0x7fa2999f4cc8 in QtPrivate::QSlotObject<void (KWin::Screens::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobject_impl.h:120
    #13 0x7fa288d05c41 in QObject::event(QEvent*) (/usr/lib64/libQt5Core.so.5+0x2acc41)
    #14 0x7fa28a17893b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x16193b)

previously allocated by thread T0 here:
    #0 0x7fa29b7ebc70 in operator new(unsigned long) (/usr/lib64/libasan.so.4+0xddc70)
    #1 0x7fa28cc17b08 in KWayland::Server::Display::createOutput(QObject*) /home/jenkins/workspace/Dependency Build Plasma kf5-qt5 SUSEQt5.9/kwayland/src/server/display.cpp:209
    #2 0x7fa299ebdeb9 in KWin::WaylandServer::syncOutputsToWayland() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/wayland_server.cpp:381
    #3 0x7fa299ebdae2 in KWin::WaylandServer::initOutputs() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/wayland_server.cpp:362
    #4 0x7fa299ee3416 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWin::WaylandServer::*)()>::call(void (KWin::WaylandServer::*)(), KWin::WaylandServer*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:136
    #5 0x7fa299ee0bb9 in void QtPrivate::FunctionPointer<void (KWin::WaylandServer::*)()>::call<QtPrivate::List<>, void>(void (KWin::WaylandServer::*)(), KWin::WaylandServer*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:169
    #6 0x7fa299edb94c in QtPrivate::QSlotObject<void (KWin::WaylandServer::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobject_impl.h:120
    #7 0x7fa288d0535b in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x2ac35b)
    #8 0x7fa29a032d5c in KWin::Application::screensCreated() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/kwin_autogen/EWIEGA46WW/moc_main.cpp:275
    #9 0x7fa2999a3574 in KWin::Application::createScreens() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/main.cpp:301
    #10 0x4728a6 in KWin::WaylandTestApplication::continueStartupWithScreens() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/autotests/integration/kwin_wayland_test.cpp:118
    #11 0x47df94 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWin::WaylandTestApplication::*)()>::call(void (KWin::WaylandTestApplication::*)(), KWin::WaylandTestApplication*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:136
    #12 0x47d78c in void QtPrivate::FunctionPointer<void (KWin::WaylandTestApplication::*)()>::call<QtPrivate::List<>, void>(void (KWin::WaylandTestApplication::*)(), KWin::WaylandTestApplication*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:169
    #13 0x47cbf8 in QtPrivate::QSlotObject<void (KWin::WaylandTestApplication::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobject_impl.h:120
    #14 0x7fa288d0535b in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x2ac35b)
    #15 0x7fa29a0417fa in KWin::Platform::screensQueried() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/kwin_autogen/EWIEGA46WW/moc_platform.cpp:297
    #16 0x7fa273015d1d in KWin::VirtualBackend::init() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/plugins/platforms/virtual/virtual_backend.cpp:74
    #17 0x4726b4 in KWin::WaylandTestApplication::createBackend() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/autotests/integration/kwin_wayland_test.cpp:112
    #18 0x47228b in KWin::WaylandTestApplication::performStartup() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/autotests/integration/kwin_wayland_test.cpp:99
    #19 0x7fa29999d7fa in KWin::Application::start() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/main.cpp:156
    #20 0x419ec2 in KWin::PointerInputTest::initTestCase() /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/autotests/integration/pointer_input.cpp:103
    #21 0x44624d in KWin::PointerInputTest::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) /home/jenkins/workspace/Plasma kwin kf5-qt5 SUSEQt5.9/build/autotests/integration/testPointerInput_autogen/include/pointer_input.moc:149
    #22 0x7fa288ce7ca5 in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (/usr/lib64/libQt5Core.so.5+0x28eca5)
    #23 0x7fa2987caaf3  (/usr/lib64/libQt5Test.so.5+0x15af3)
    #24 0x7fa2987cb12a in QTest::qExec(QObject*, int, char**) (/usr/lib64/libQt5Test.so.5+0x1612a)