diff --git a/autotests/client/CMakeLists.txt b/autotests/client/CMakeLists.txt index 62ad2e6..b71fc8d 100644 --- a/autotests/client/CMakeLists.txt +++ b/autotests/client/CMakeLists.txt @@ -1,431 +1,431 @@ ######################################################## # Test WaylandConnectionThread ######################################################## set( testWaylandConnectionThread_SRCS test_wayland_connection_thread.cpp ) add_executable(testWaylandConnectionThread ${testWaylandConnectionThread_SRCS}) target_link_libraries( testWaylandConnectionThread Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server) add_test(NAME kwayland-testWaylandConnectionThread COMMAND testWaylandConnectionThread) ecm_mark_as_test(testWaylandConnectionThread) ######################################################## # Test WaylandRegistry ######################################################## set( testWaylandRegistry_SRCS test_wayland_registry.cpp ) add_executable(testWaylandRegistry ${testWaylandRegistry_SRCS}) target_link_libraries( testWaylandRegistry Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server) add_test(NAME kwayland-testWaylandRegistry COMMAND testWaylandRegistry) ecm_mark_as_test(testWaylandRegistry) ######################################################## # Test WaylandFullscreenShell ######################################################## if(Wayland_VERSION VERSION_GREATER "1.4.0") find_program(WESTON_EXECUTABLE weston DOC "Path to the weston executable.") if(WESTON_EXECUTABLE) set( testWaylandFullscreenShell_SRCS test_wayland_fullscreen_shell.cpp ) add_executable(testWaylandFullscreenShell ${testWaylandFullscreenShell_SRCS}) target_link_libraries( testWaylandFullscreenShell Qt5::Test KF5::WaylandClient Wayland::Client) add_test(NAME kwayland-testWaylandFullscreenShell COMMAND testWaylandFullscreenShell) ecm_mark_as_test(testWaylandFullscreenShell) else() message(STATUS "The weston executable was not found. Some autotests will not be executed.") endif() endif() ######################################################## # Test WaylandOutput ######################################################## set( testWaylandOutput_SRCS test_wayland_output.cpp ) add_executable(testWaylandOutput ${testWaylandOutput_SRCS}) target_link_libraries( testWaylandOutput Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server) add_test(NAME kwayland-testWaylandOutput COMMAND testWaylandOutput) ecm_mark_as_test(testWaylandOutput) ######################################################## # Test WaylandShell ######################################################## set( testWaylandShell_SRCS test_wayland_shell.cpp ) add_executable(testWaylandShell ${testWaylandShell_SRCS}) target_link_libraries( testWaylandShell Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server) add_test(NAME kwayland-testWaylandShell COMMAND testWaylandShell) ecm_mark_as_test(testWaylandShell) ######################################################## # Test WaylandSurface ######################################################## set( testWaylandSurface_SRCS test_wayland_surface.cpp ) add_executable(testWaylandSurface ${testWaylandSurface_SRCS}) target_link_libraries( testWaylandSurface Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server) add_test(NAME kwayland-testWaylandSurface COMMAND testWaylandSurface) ecm_mark_as_test(testWaylandSurface) ######################################################## # Test WaylandSeat ######################################################## if (HAVE_LINUX_INPUT_H) set( testWaylandSeat_SRCS test_wayland_seat.cpp ) add_executable(testWaylandSeat ${testWaylandSeat_SRCS}) target_link_libraries( testWaylandSeat Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server) add_test(NAME kwayland-testWaylandSeat COMMAND testWaylandSeat) ecm_mark_as_test(testWaylandSeat) endif() ######################################################## # Test ShmPool ######################################################## set( testShmPool_SRCS test_shm_pool.cpp ) add_executable(testShmPool ${testShmPool_SRCS}) target_link_libraries( testShmPool Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testShmPool COMMAND testShmPool) ecm_mark_as_test(testShmPool) ######################################################## # Test KWin OutputManagement ######################################################## set( test_wayland_outputmanagement_SRCS test_wayland_outputmanagement.cpp ) add_executable(testWaylandOutputManagement ${test_wayland_outputmanagement_SRCS}) target_link_libraries( testWaylandOutputManagement Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testWaylandOutputManagement COMMAND testWaylandOutputManagement) ecm_mark_as_test(testWaylandOutputManagement) ######################################################## # Test KWin OutputDevice ######################################################## set( test_wayland_outputdevice_SRCS test_wayland_outputdevice.cpp ) add_executable(testWaylandOutputDevice ${test_wayland_outputdevice_SRCS}) target_link_libraries( testWaylandOutputDevice Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testWaylandOutputDevice COMMAND testWaylandOutputDevice) ecm_mark_as_test(testWaylandOutputDevice) ######################################################## # Test Compositor ######################################################## set( testCompositor_SRCS test_compositor.cpp ) add_executable(testCompositor ${testCompositor_SRCS}) target_link_libraries( testCompositor Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testCompositor COMMAND testCompositor) ecm_mark_as_test(testCompositor) ######################################################## # Test SubCompositor ######################################################## set( testSubCompositor_SRCS test_wayland_subcompositor.cpp ) add_executable(testSubCompositor ${testSubCompositor_SRCS}) target_link_libraries( testSubCompositor Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testSubCompositor COMMAND testSubCompositor) ecm_mark_as_test(testSubCompositor) ######################################################## # Test SubSurface ######################################################## set( testSubSurface_SRCS test_wayland_subsurface.cpp ) add_executable(testSubSurface ${testSubSurface_SRCS}) target_link_libraries( testSubSurface Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testSubSurface COMMAND testSubSurface) ecm_mark_as_test(testSubSurface) ######################################################## # Test Region ######################################################## set( testRegion_SRCS test_wayland_region.cpp ) add_executable(testRegion ${testRegion_SRCS}) target_link_libraries( testRegion Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testRegion COMMAND testRegion) ecm_mark_as_test(testRegion) ######################################################## # Test Blur ######################################################## set( testBlur_SRCS test_wayland_blur.cpp ) add_executable(testBlur ${testBlur_SRCS}) target_link_libraries( testBlur Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testBlur COMMAND testBlur) ecm_mark_as_test(testBlur) ######################################################## # Test Contrast ######################################################## set( testContrast_SRCS test_wayland_contrast.cpp ) add_executable(testContrast ${testContrast_SRCS}) target_link_libraries( testContrast Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testContrast COMMAND testContrast) ecm_mark_as_test(testContrast) ######################################################## # Test Slide ######################################################## set( testSlide_SRCS test_wayland_slide.cpp ) add_executable(testSlide ${testSlide_SRCS}) target_link_libraries( testSlide Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testSlide COMMAND testSlide) ecm_mark_as_test(testSlide) ######################################################## # Test Window Management ######################################################## set( testWindowmanagement_SRCS test_wayland_windowmanagement.cpp ) add_executable(testWindowmanagement ${testWindowmanagement_SRCS}) target_link_libraries( testWindowmanagement Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testWindowmanagement COMMAND testWindowmanagement) ecm_mark_as_test(testWindowmanagement) ######################################################## # Test DataSource ######################################################## set( testDataSource_SRCS test_datasource.cpp ) add_executable(testDataSource ${testDataSource_SRCS}) target_link_libraries( testDataSource Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testDataSource COMMAND 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(NAME kwayland-testDataDevice COMMAND testDataDevice) ecm_mark_as_test(testDataDevice) ######################################################## # Test ServerSideDecoration ######################################################## set( testServerSideDecoration_SRCS test_server_side_decoration.cpp ) add_executable(testServerSideDecoration ${testServerSideDecoration_SRCS}) target_link_libraries( testServerSideDecoration Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testServerSideDecoration COMMAND testServerSideDecoration) ecm_mark_as_test(testServerSideDecoration) ######################################################## # Test Drag'N'Drop ######################################################## set( testDragAndDrop_SRCS test_drag_drop.cpp ) add_executable(testDragAndDrop ${testDragAndDrop_SRCS}) target_link_libraries( testDragAndDrop Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testDragAndDrop COMMAND testDragAndDrop) ecm_mark_as_test(testDragAndDrop) ######################################################## # Test PlasmaShell ######################################################## set( testPlasmaShell_SRCS test_plasmashell.cpp ) add_executable(testPlasmaShell ${testPlasmaShell_SRCS}) target_link_libraries( testPlasmaShell Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testPlasmaShell COMMAND testPlasmaShell) ecm_mark_as_test(testPlasmaShell) ######################################################## # Test Idle ######################################################## set( testIdle_SRCS test_idle.cpp ) add_executable(testIdle ${testIdle_SRCS}) target_link_libraries( testIdle Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testIdle COMMAND testIdle) ecm_mark_as_test(testIdle) ######################################################## # Test Shadow ######################################################## set( testShadow_SRCS test_shadow.cpp ) add_executable(testShadow ${testShadow_SRCS}) target_link_libraries( testShadow Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testShadow COMMAND testShadow) ecm_mark_as_test(testShadow) ######################################################## # Test FakeInput ######################################################## if (HAVE_LINUX_INPUT_H) set( testFakeInput_SRCS test_fake_input.cpp ) add_executable(testFakeInput ${testFakeInput_SRCS}) target_link_libraries( testFakeInput Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testFakeInput COMMAND testFakeInput) ecm_mark_as_test(testFakeInput) endif() ######################################################## # Test PlasmaWindowModel ######################################################## if (HAVE_LINUX_INPUT_H) set( testPlasmaWindowModel_SRCS test_plasma_window_model.cpp ) add_executable(testPlasmaWindowModel ${testPlasmaWindowModel_SRCS}) target_link_libraries( testPlasmaWindowModel Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testPlasmaWindowModel COMMAND testPlasmaWindowModel) ecm_mark_as_test(testPlasmaWindowModel) endif() ######################################################## # Test TextInput ######################################################## set( testTextInput_SRCS test_text_input.cpp ) add_executable(testTextInput ${testTextInput_SRCS}) target_link_libraries( testTextInput Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testTextInput COMMAND testTextInput) ecm_mark_as_test(testTextInput) ######################################################## # Test Error ######################################################## set( testError_SRCS test_error.cpp ) add_executable(testError ${testError_SRCS}) target_link_libraries( testError Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testError COMMAND testError) ecm_mark_as_test(testError) ######################################################## # Test Selection ######################################################## set( testSelection_SRCS test_selection.cpp ) add_executable(testSelection ${testSelection_SRCS}) target_link_libraries( testSelection Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) add_test(NAME kwayland-testSelection COMMAND testSelection) ecm_mark_as_test(testSelection) ######################################################## # Test XdgShellV5 ######################################################## set( testXdgShellV5_SRCS test_xdg_shell.cpp test_xdg_shell_v5.cpp ) add_executable(testXdgShellV5 ${testXdgShellV5_SRCS}) target_link_libraries( testXdgShellV5 Qt5::Test Qt5::Gui KF5::WaylandServer KF5::WaylandClient Wayland::Client) add_test(NAME kwayland-testXdgShellV5 COMMAND testXdgShellV5) ecm_mark_as_test(testXdgShellV5) ######################################################## # Test XdgForeign ######################################################## set( testXdgForeign_SRCS test_xdg_foreign.cpp ) add_executable(testXdgForeign ${testXdgForeign_SRCS}) target_link_libraries( testXdgForeign Qt5::Test Qt5::Gui KF5::WaylandServer KF5::WaylandClient Wayland::Client) add_test(NAME kwayland-testXdgForeign COMMAND testXdgForeign) ecm_mark_as_test(testXdgForeign) ######################################################## # Test XdgShellV6 ######################################################## set( testXdgShellV6_SRCS test_xdg_shell.cpp test_xdg_shell_v6.cpp ) add_executable(testXdgShellV6 ${testXdgShellV6_SRCS}) target_link_libraries( testXdgShellV6 Qt5::Test Qt5::Gui KF5::WaylandServer KF5::WaylandClient Wayland::Client) add_test(NAME kwayland-testXdgShellV6 COMMAND testXdgShellV6) ecm_mark_as_test(testXdgShellV6) ######################################################## # Test Pointer Constraints ######################################################## add_executable(testPointerConstraints test_pointer_constraints.cpp) target_link_libraries( testPointerConstraints Qt5::Test Qt5::Gui KF5::WaylandServer KF5::WaylandClient Wayland::Client) add_test(NAME kwayland-testPointerConstraints COMMAND testPointerConstraints) ecm_mark_as_test(testPointerConstraints) ######################################################## # Test Filter ######################################################## set( testFilter_SRCS test_wayland_filter.cpp ) add_executable(testFilter ${testFilter_SRCS}) target_link_libraries( testFilter Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Server) add_test(NAME kwayland-testFilter COMMAND testFilter) ecm_mark_as_test(testFilter) ######################################################## # Test Appmenu ######################################################## set( testAppmenu_SRCS test_wayland_appmenu.cpp ) add_executable(testAppmenu ${testAppmenu_SRCS}) target_link_libraries( testAppmenu Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testAppmenu COMMAND testAppmenu) ecm_mark_as_test(testAppmenu) ######################################################## # Test Appmenu ######################################################## set( testServerSideDecorationPalette_SRCS test_server_side_decoration_palette.cpp ) add_executable(testServerSideDecorationPalette ${testServerSideDecorationPalette_SRCS}) target_link_libraries( testServerSideDecorationPalette Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testServerSideDecorationPalette COMMAND testServerSideDecorationPalette) ecm_mark_as_test(testServerSideDecorationPalette) ######################################################## # Test RemoteAccess ######################################################## set( testRemoteAccess_SRCS test_remote_access.cpp ) add_executable(testRemoteAccess ${testRemoteAccess_SRCS}) target_link_libraries( testRemoteAccess Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) -add_test(kwayland-testRemoteAccess testRemoteAccess) +add_test(NAME kwayland-testRemoteAccess COMMAND testRemoteAccess) ecm_mark_as_test(testRemoteAccess) diff --git a/src/server/remote_access_interface.cpp b/src/server/remote_access_interface.cpp index 8d6fd40..5f7d453 100644 --- a/src/server/remote_access_interface.cpp +++ b/src/server/remote_access_interface.cpp @@ -1,380 +1,381 @@ /**************************************************************************** Copyright 2016 Oleg Chernovskiy 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 . ****************************************************************************/ #include "output_interface.h" #include "remote_access_interface.h" #include "remote_access_interface_p.h" #include "display.h" #include "global_p.h" #include "resource_p.h" #include "logging_p.h" #include #include #include #include namespace KWayland { namespace Server { class BufferHandle::Private // @see gbm_import_fd_data { public: // Note that on client side received fd number will be different // and meaningful only for client process! // Thus we can use server-side fd as an implicit unique id qint32 fd = 0; ///< also internal buffer id for client quint32 width = 0; quint32 height = 0; quint32 stride = 0; quint32 format = 0; }; BufferHandle::BufferHandle() : d(new Private) { } BufferHandle::~BufferHandle() { } void BufferHandle::setFd(qint32 fd) { d->fd = fd; } qint32 BufferHandle::fd() const { return d->fd; } void BufferHandle::setSize(quint32 width, quint32 height) { d->width = width; d->height = height; } quint32 BufferHandle::width() const { return d->width; } quint32 BufferHandle::height() const { return d->height; } void BufferHandle::setStride(quint32 stride) { d->stride = stride; } quint32 BufferHandle::stride() const { return d->stride; } void BufferHandle::setFormat(quint32 format) { d->format = format; } quint32 BufferHandle::format() const { return d->format; } /** * @brief helper struct for manual reference counting. * automatic counting via QSharedPointer is no-go here as we hold strong reference in sentBuffers. */ struct BufferHolder { const BufferHandle *buf; quint64 counter; }; class RemoteAccessManagerInterface::Private : public Global::Private { public: Private(RemoteAccessManagerInterface *q, Display *d); virtual ~Private() override; /** * @brief Send buffer ready notification to all connected clients * @param output wl_output interface to determine which screen sent this buf * @param buf buffer containing GBM-related params */ void sendBufferReady(const OutputInterface *output, const BufferHandle *buf); /** * @brief Release all bound buffers associated with this resource * @param resource one of bound clients */ void release(wl_resource *resource); /** * Clients of this interface. * This may be screenshot app, video capture app, * remote control app etc. */ QList clientResources; private: // methods static void unbind(wl_resource *resource); static Private *cast(wl_resource *r) { return reinterpret_cast(wl_resource_get_user_data(r)); } static void getBufferCallback(wl_client *client, wl_resource *resource, uint32_t buffer, int32_t internalBufId); static void releaseCallback(wl_client *client, wl_resource *resource); void bind(wl_client *client, uint32_t version, uint32_t id) override; /** * @brief Unreferences counter and frees buffer when it reaches zero * @param buf holder to decrease reference counter on * @return true if buffer was released, false otherwise */ bool unref(BufferHolder &buf); // fields static const struct org_kde_kwin_remote_access_manager_interface s_interface; static const quint32 s_version; RemoteAccessManagerInterface *q; /** * Buffers that were sent but still not acked by server * Keys are fd numbers as they are unique **/ QHash sentBuffers; }; const quint32 RemoteAccessManagerInterface::Private::s_version = 1; RemoteAccessManagerInterface::Private::Private(RemoteAccessManagerInterface *q, Display *d) : Global::Private(d, &org_kde_kwin_remote_access_manager_interface, s_version) , q(q) { } void RemoteAccessManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) { // create new client resource auto c = display->getConnection(client); wl_resource *resource = c->createResource(&org_kde_kwin_remote_access_manager_interface, qMin(version, s_version), id); if (!resource) { wl_client_post_no_memory(client); return; } wl_resource_set_implementation(resource, &s_interface, this, unbind); // add newly created client resource to the list clientResources << resource; } void RemoteAccessManagerInterface::Private::sendBufferReady(const OutputInterface *output, const BufferHandle *buf) { BufferHolder holder {buf, 0}; // notify clients qCDebug(KWAYLAND_SERVER) << "Server buffer sent: fd" << buf->fd(); for (auto res : clientResources) { auto client = wl_resource_get_client(res); auto boundScreens = output->clientResources(display->getConnection(client)); // clients don't necessarily bind outputs - if (boundScreens.isEmpty()) + if (boundScreens.isEmpty()) { return; + } // no reason for client to bind wl_output multiple times, send only to first one org_kde_kwin_remote_access_manager_send_buffer_ready(res, buf->fd(), boundScreens[0]); holder.counter++; } // store buffer locally, clients will ask it later sentBuffers[buf->fd()] = holder; } #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_kwin_remote_access_manager_interface RemoteAccessManagerInterface::Private::s_interface = { getBufferCallback, releaseCallback }; #endif void RemoteAccessManagerInterface::Private::getBufferCallback(wl_client *client, wl_resource *resource, uint32_t buffer, int32_t internalBufId) { Private *p = cast(resource); // client asks for buffer we earlier announced, we must have it if (Q_UNLIKELY(!p->sentBuffers.contains(internalBufId))) { // no such buffer (?) wl_resource_post_no_memory(resource); return; } BufferHolder &bh = p->sentBuffers[internalBufId]; auto rbuf = new RemoteBufferInterface(p->q, resource, bh.buf); rbuf->create(p->display->getConnection(client), wl_resource_get_version(resource), buffer); if (!rbuf->resource()) { wl_resource_post_no_memory(resource); delete rbuf; return; } QObject::connect(rbuf, &QObject::destroyed, [p, rbuf, resource, &bh] { if (!p->clientResources.contains(resource)) { // remote buffer destroy confirmed after client is already gone // all relevant buffers are already unreferenced return; } qCDebug(KWAYLAND_SERVER) << "Remote buffer returned, client" << wl_resource_get_id(resource) << ", id" << rbuf->id() << ", fd" << bh.buf->fd(); if (p->unref(bh)) { p->sentBuffers.remove(bh.buf->fd()); } }); // send buffer params rbuf->passFd(); } void RemoteAccessManagerInterface::Private::releaseCallback(wl_client *client, wl_resource *resource) { Q_UNUSED(client); unbind(resource); } bool RemoteAccessManagerInterface::Private::unref(BufferHolder &bh) { bh.counter--; if (!bh.counter) { // no more clients using this buffer qCDebug(KWAYLAND_SERVER) << "Buffer released, fd" << bh.buf->fd(); emit q->bufferReleased(bh.buf); return true; } return false; } void RemoteAccessManagerInterface::Private::unbind(wl_resource *resource) { // we're unbinding, all sent buffers for this client are now effectively invalid Private *p = cast(resource); p->release(resource); } void RemoteAccessManagerInterface::Private::release(wl_resource *resource) { // all holders should decrement their counter as one client is gone QMutableHashIterator itr(sentBuffers); while (itr.hasNext()) { BufferHolder &bh = itr.next().value(); if (unref(bh)) { itr.remove(); } } clientResources.removeAll(resource); } RemoteAccessManagerInterface::Private::~Private() { // server deletes created interfaces, release all held buffers auto c = clientResources; // shadow copy for (auto res : c) { release(res); } } RemoteAccessManagerInterface::RemoteAccessManagerInterface(Display *display, QObject *parent) : Global(new Private(this, display), parent) { } void RemoteAccessManagerInterface::sendBufferReady(const OutputInterface *output, const BufferHandle *buf) { Private *priv = reinterpret_cast(d.data()); priv->sendBufferReady(output, buf); } bool RemoteAccessManagerInterface::isBound() const { Private *priv = reinterpret_cast(d.data()); return !priv->clientResources.isEmpty(); } class RemoteBufferInterface::Private : public Resource::Private { public: Private(RemoteAccessManagerInterface *ram, RemoteBufferInterface *q, wl_resource *pResource, const BufferHandle *buf); ~Private(); void passFd(); private: static const struct org_kde_kwin_remote_buffer_interface s_interface; const BufferHandle *wrapped; }; #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_kwin_remote_buffer_interface RemoteBufferInterface::Private::s_interface = { resourceDestroyedCallback }; #endif RemoteBufferInterface::Private::Private(RemoteAccessManagerInterface *ram, RemoteBufferInterface *q, wl_resource *pResource, const BufferHandle *buf) : Resource::Private(q, ram, pResource, &org_kde_kwin_remote_buffer_interface, &s_interface), wrapped(buf) { } RemoteBufferInterface::Private::~Private() { } void RemoteBufferInterface::Private::passFd() { org_kde_kwin_remote_buffer_send_gbm_handle(resource, wrapped->fd(), wrapped->width(), wrapped->height(), wrapped->stride(), wrapped->format()); } RemoteBufferInterface::RemoteBufferInterface(RemoteAccessManagerInterface *ram, wl_resource *pResource, const BufferHandle *buf) : Resource(new Private(ram, this, pResource, buf), ram) { } RemoteBufferInterface::Private *RemoteBufferInterface::d_func() const { return reinterpret_cast(d.data()); } void RemoteBufferInterface::passFd() { d_func()->passFd(); } } }