1 /********************************************************************
2 Copyright © 2020 Roman Gilg <subdiff@gmail.com>
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), which shall
10 act as a proxy defined in Section 6 of version 3 of the license.
11 
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library.  If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
20 #include "compositor.h"
21 
22 #include "client.h"
23 #include "display.h"
24 #include "region.h"
25 #include "surface_p.h"
26 
27 #include "wayland/global.h"
28 
29 #include <algorithm>
30 #include <vector>
31 
32 namespace Wrapland::Server
33 {
34 
35 constexpr uint32_t CompositorVersion = 4;
36 using CompositorGlobal = Wayland::Global<Compositor, CompositorVersion>;
37 using CompositorBind = Wayland::Bind<CompositorGlobal>;
38 
39 class Compositor::Private : public CompositorGlobal
40 {
41 public:
42     Private(Compositor* q, Display* display);
43     ~Private() override;
44 
45     std::vector<Surface*> surfaces;
46 
47 private:
48     static void createSurfaceCallback(CompositorBind* bind, uint32_t id);
49     static void createRegionCallback(CompositorBind* bind, uint32_t id);
50 
51     static const struct wl_compositor_interface s_interface;
52 };
53 
Private(Compositor * q,Display * display)54 Compositor::Private::Private(Compositor* q, Display* display)
55     : CompositorGlobal(q, display, &wl_compositor_interface, &s_interface)
56 {
57 }
58 
59 Compositor::Private::~Private() = default;
60 
61 const struct wl_compositor_interface Compositor::Private::s_interface = {
62     cb<createSurfaceCallback>,
63     cb<createRegionCallback>,
64 };
65 
Compositor(Display * display,QObject * parent)66 Compositor::Compositor(Display* display, QObject* parent)
67     : QObject(parent)
68     , d_ptr(new Private(this, display))
69 {
70     d_ptr->create();
71 }
72 
73 Compositor::~Compositor() = default;
74 
createSurfaceCallback(CompositorBind * bind,uint32_t id)75 void Compositor::Private::createSurfaceCallback(CompositorBind* bind, uint32_t id)
76 {
77     auto priv = bind->global()->handle()->d_ptr.get();
78 
79     auto surface = new Surface(bind->client()->handle(), bind->version(), id);
80     // TODO(romangg): error handling (when resource not created)
81 
82     priv->surfaces.push_back(surface);
83     connect(surface, &Surface::resourceDestroyed, priv->handle(), [priv, surface] {
84         priv->surfaces.erase(std::remove(priv->surfaces.begin(), priv->surfaces.end(), surface),
85                              priv->surfaces.end());
86     });
87 
88     Q_EMIT priv->handle()->surfaceCreated(surface);
89 }
90 
createRegionCallback(CompositorBind * bind,uint32_t id)91 void Compositor::Private::createRegionCallback(CompositorBind* bind, uint32_t id)
92 {
93     auto compositor = bind->global()->handle();
94 
95     auto region = new Region(bind->client()->handle(), bind->version(), id);
96     // TODO(romangg): error handling (when resource not created)
97 
98     Q_EMIT compositor->regionCreated(region);
99 }
100 
getSurface(uint32_t id,Client * client)101 Surface* Compositor::getSurface(uint32_t id, Client* client)
102 {
103     auto it = std::find_if(
104         d_ptr->surfaces.cbegin(), d_ptr->surfaces.cend(), [id, client](Surface* surface) {
105             return surface->d_ptr->client()->handle() == client && surface->d_ptr->id() == id;
106         });
107     return it != d_ptr->surfaces.cend() ? *it : nullptr;
108 }
109 
110 }
111