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