f09ef0548eed78afeba7e96d57d8edac32eb8d6e
[platform/core/uifw/libds.git] / src / DSWaylandServer / DSWaylandCompositor.cpp
1 /*
2 * Copyright © 2020 Samsung Electronics co., Ltd. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "DSWaylandCompositor.h"
25 #include "DSWaylandCompositorPrivate.h"
26 #include "DSWaylandExtension.h"
27 #include "DSWaylandClient.h"
28 #include "DSWaylandSeat.h"
29 #include "DSWaylandSurface.h"
30 #include "DSWaylandRegion.h"
31 #include "DSDebugLog.h"
32 #include "DSUtilSocket.h"
33
34 namespace display_server
35 {
36
37 /* reference count, mutex and compositor pointer for DSWaylandCompositor singleton */
38 int DSWaylandCompositor::__refCount { 0 };
39 std::mutex DSWaylandCompositor::__mutex;
40 DSWaylandCompositor* DSWaylandCompositor::__comp { nullptr };
41
42 /* Begin Private Class Implementation */
43 DSWaylandCompositorPrivate::DSWaylandCompositorPrivate(DSWaylandCompositor *compositor)
44     : DSObjectPrivate(compositor),
45       __p_ptr(compositor),
46       m_clientCreatedListener({nullptr, nullptr}),
47       _created(false),
48       _socketFD(-1),
49       _socketName(),
50       _display(nullptr),
51       _loop(nullptr),
52       _socket_fd_handler(nullptr),
53       _compositor(compositor),
54       __wlExtension(nullptr),
55       __shell(nullptr)
56 {
57         if (!ecore_init())
58         {
59                 DSLOG_ERR("DSWaylandCompositor", "ecore_init() fails.\n");
60                 return;
61         }
62
63         _display = wl_display_create();
64         DS_ASSERT(_display != nullptr);
65
66         m_clientCreatedListener.notify = DSWaylandCompositorPrivate::client_created_callback;
67         m_clientCreatedListener.parent = this;
68         wl_display_add_client_created_listener(_display, &m_clientCreatedListener);
69 }
70
71 DSWaylandCompositorPrivate::~DSWaylandCompositorPrivate()
72 {
73         //TODO : destroy all allocated resources
74
75         wl_list_remove(&m_clientCreatedListener.link);
76
77         _clients.clear();
78         _seats.clear();
79         _socketName.clear();
80
81         if (_socket_fd_handler)
82         {
83                 ecore_main_fd_handler_del(_socket_fd_handler);
84                 ecore_main_fd_handler_prepare_callback_set(_socket_fd_handler, nullptr, nullptr);
85                 _socket_fd_handler = nullptr;
86         }
87
88         if (_display)
89         {
90                 wl_display_destroy(_display);
91                 _display = nullptr;
92         }
93
94         _created = false;
95         _socketFD = -1;
96         _loop = nullptr;
97         _compositor = nullptr;
98         __p_ptr = nullptr;
99
100         ecore_shutdown();
101 }
102
103 void DSWaylandCompositorPrivate::client_created_callback(struct ::wl_listener *listener, void *data)
104 {
105         struct ::wl_client *wlClient = (struct ::wl_client *)data;
106         DS_ASSERT(wlClient != nullptr);
107
108         DSWaylandClient *client = nullptr;
109         DSWaylandCompositorPrivate *compPriv = reinterpret_cast<ClientCreatedListener *>(listener)->parent;
110
111         if (compPriv != nullptr)
112         {
113                 client = new DSWaylandClient(compPriv->_compositor, wlClient);
114                 DS_ASSERT(client != nullptr);
115
116                 DSLOG_INF("DSWaylandCompositorPrivate", "Client created ! (pid:%d, uid:%d, gid:%d)",
117                                         client->pid(), client->uid(), client->gid());
118         }
119 }
120
121 void DSWaylandCompositorPrivate::initSocket(std::string sName, std::string sDir)
122 {
123         std::string socketPath = std::move(sDir);
124
125         socketPath.append(1, '/');
126         socketPath.append(_socketName);
127
128         (void) socketPath;
129
130         DSUtilSocket *utilSocket = DSUtilSocket::getInstance();
131         utilSocket->initSocket(sName);
132         utilSocket->releaseInstance();
133
134         //TODO : set permissions for Owner, Group and Other
135         //TODO : set Smack attributes for socket
136         //TODO : set symbolic link for socket  
137 }
138
139 bool DSWaylandCompositorPrivate::initCompositor()
140 {
141         if (!_display)
142         {
143                 DSLOG_ERR("DSWaylandCompositor", "_display(wl_display) is NULL !\n");
144                 return false;
145         }
146
147         //Initialize needed interfaces
148         //TODO : get/set DSConfig::version("wl_compositor")
149         wl_compositor::init(_display, 4);
150
151         //TODO : get socketName from DSConfig::socketName()
152         //TODO : create socket with wl_display_add_socket() if socketName not empty
153         _socketName = wl_display_add_socket_auto(_display);
154
155         if (_socketName.empty())
156         {
157                 DSLOG_ERR("DSWaylandCompositor", "_socketName is empty()\n");
158                 return false;
159         }
160
161         initSocket(_socketName, "/run");
162
163         //TODO : DSConfig::setEnv("WAYLAND_DISPLAY", _socketName);
164
165         //TODO : initialize compositor signals (signals.surface.create/activate/kill)
166         //ex> implment using DSWaylandSignal class
167         //wl_signal_init(&cdata->signals.surface.create);
168         //-> DSWayalndSignal::add("surface_create", wl_notify_func_t *notify or &notify_func);
169
170         //TODO : add event dispatcher for wayland socket and other fd(s)
171         _loop = wl_display_get_event_loop(_display);
172
173         if (!_loop)
174         {
175                 DSLOG_ERR("DSWaylandCompositor", "_loop is nullptr.\n");
176                 return false;
177         }
178
179         _socketFD = wl_event_loop_get_fd(_loop);
180
181         if (0 > _socketFD)
182         {
183                 DSLOG_ERR("DSWaylandCompositor", "_socketFD is invalid. (_socketFD=%d)\n", _socketFD);
184                 return false;
185         }
186
187         auto evFlags = ECORE_FD_READ | ECORE_FD_ERROR;
188
189         _socket_fd_handler = ecore_main_fd_handler_add(_socketFD,
190                                                         static_cast<Ecore_Fd_Handler_Flags >(evFlags),
191                                                         __readEvents, this, NULL, NULL);
192
193         if (!_socket_fd_handler)
194         {
195                 DSLOG_ERR("DSWaylandCompositor", "_socket_fd_handler is invalid.\n");
196         }
197
198         ecore_main_fd_handler_prepare_callback_set(_socket_fd_handler,
199                                               __prepareFunc, this);
200
201         return true;
202 }
203
204 bool DSWaylandCompositorPrivate::initExtension()
205 {
206         if (__wlExtension)
207         {
208                 DSLOG_INF("DSWaylandCompositor", "Already initialize Extension");
209                 return true;
210         }
211
212         __wlExtension = std::make_unique<DSWaylandExtension>(_compositor);
213         if (!__wlExtension) return false;
214
215         return true;
216 }
217
218 Eina_Bool DSWaylandCompositorPrivate::__readEvents(void *data, Ecore_Fd_Handler *hdlr)
219 {
220         DSWaylandCompositorPrivate *compPrivate = (DSWaylandCompositorPrivate *) data;
221
222         if (!compPrivate)
223         {
224                 DSLOG_DBG("DSWaylandCompositor", "compPrivate is invalid.\n");
225                 return ECORE_CALLBACK_RENEW;
226         }
227
228         (void) hdlr;
229
230         /* dispatch pending wayland events */
231         int ret = wl_event_loop_dispatch(compPrivate->_loop, 0);
232
233         if (ret)
234         {
235                 DSLOG_ERR("DSWaylandCompositor", "Failed on wl_event_loop_dispatch()\n");
236         }
237
238         return ECORE_CALLBACK_RENEW;
239 }
240
241 void DSWaylandCompositorPrivate::__prepareFunc(void *data, Ecore_Fd_Handler *hdlr)
242 {
243         DSWaylandCompositorPrivate *compPrivate = (DSWaylandCompositorPrivate *) data;
244
245         if (!compPrivate)
246         {
247                 DSLOG_DBG("DSWaylandCompositor", "compPrivate is invalid.\n");
248                 return;
249         }
250
251         (void) hdlr;
252
253         /* flush pending client events */
254         wl_display_flush_clients(compPrivate->_display);
255 }
256
257 void DSWaylandCompositorPrivate::compositor_bind_resource(wl_compositor::Resource *resource)
258 {
259         //TODO : Leave log (pid/uid/gid and process name)
260         //TODO : Update connected client list (add)
261 }
262
263 void DSWaylandCompositorPrivate::compositor_destroy_resource(wl_compositor::Resource *resource)
264 {
265         //TODO : Leave log (pid/uid/gid and process name)
266         //TODO : Update connected client list (remove)
267 }
268
269 void DSWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resource *resource, uint32_t id)
270 {
271         DS_GET_PUB(DSWaylandCompositor);
272
273         DSWaylandClient *waylandClient = DSWaylandClient::fromWlClient(resource->client());
274         auto waylandSruface = std::make_shared<DSWaylandSurface>(waylandClient, id);
275
276         pub->__surfaceList.push_front(waylandSruface);
277
278         // emit a signal of the surface created
279         pub->__surfaceCreatedSignal.emit(waylandSruface);
280 }
281
282 void DSWaylandCompositorPrivate::compositor_create_region(wl_compositor::Resource *resource, uint32_t id)
283 {
284         DS_GET_PUB(DSWaylandCompositor);
285
286         DSWaylandClient *waylandClient = DSWaylandClient::fromWlClient(resource->client());
287         auto waylandRegion = std::make_shared<DSWaylandRegion>(waylandClient, id);
288
289         pub->__regionList.push_front(waylandRegion);
290 }
291
292 /* Begin Public Class Implementation */
293 DSWaylandCompositor::DSWaylandCompositor(DSObject *parent)
294     : DS_INIT_PRIVATE_PTR(DSWaylandCompositor)
295 {
296         //TODO
297 }
298         
299 DSWaylandCompositor::~DSWaylandCompositor()
300 {
301         //TODO
302 }
303
304 /* getInstance for DSWaylandCompositor singleton */
305 DSWaylandCompositor *DSWaylandCompositor::getInstance()
306 {
307         std::lock_guard<std::mutex> tLock(__mutex);
308
309         DSLOG_INF("DSWaylandCompositor",
310                         "[Get] instance __refCount=%d !", __refCount);
311
312         if (!__comp && (__refCount == 0))
313         {
314                 __comp = new DSWaylandCompositor(new DSObject);
315                 DSLOG_INF("DSWaylandCompositor",
316                         "DSWaylandCompositor instance has been created !");
317         }
318
319         ++__refCount;
320         return __comp;
321 }
322
323 /* releaseInstance for DSWaylandCompositor singleton */
324 void DSWaylandCompositor::releaseInstance()
325 {
326         std::lock_guard<std::mutex> tLock(__mutex);
327
328         --__refCount;
329         if (__refCount < 0)
330                 __refCount = 0;
331         DSLOG_INF("DSWaylandCompositor",
332                         "[Release] instance __refCount=%d !", __refCount);
333
334         if ((0 == __refCount) && __comp)
335         {
336                 delete __comp;
337                 __comp = nullptr;
338                 DSLOG_INF("DSWaylandCompositor",
339                         "DSWaylandCompositor instance has been removed !");
340         }
341 }
342
343 bool DSWaylandCompositor::create()
344 {
345         DS_GET_PRIV(DSWaylandCompositor);
346
347         bool res = false;
348
349         res = priv->initCompositor();
350         if (!res)
351         {
352                 DSLOG_ERR("DSWaylandCompositor", "Failed on initCompositor ! (res=%d)\n", res);
353                 return false;
354         }
355
356         res = priv->initExtension();
357         if (!res)
358         {
359                 DSLOG_ERR("DSWaylandCompositor", "Failed on initExtension ! (res=%d)\n", res);
360                 return false;
361         }
362
363         priv->_created = true;
364         return true;
365 }
366
367 bool DSWaylandCompositor::isCreated()
368 {
369         DS_GET_PRIV(DSWaylandCompositor);
370
371         return priv->_created;
372 }
373
374 DSWaylandSeat *DSWaylandCompositorPrivate::addSeat(uint32_t cap)
375 {
376         DSWaylandSeat *dswlSeat = new DSWaylandSeat(_compositor, (DSWaylandSeat::seatCapability)cap);
377
378         if (!dswlSeat)
379         {
380                 DSLOG_ERR("DSWaylandCompositorPrivate", "Failed to create DSWaylandSeat !");
381                 return nullptr;
382         }
383
384         //TODO : check if the client is in clients already ?
385         _seats.push_back(dswlSeat);
386
387         DSLOG_INF("DSWaylandCompositorPrivate", "Seat(%p) has been added.", dswlSeat);
388
389         //TODO : emit seatAdded signal
390
391         return dswlSeat;
392 }
393
394 void DSWaylandCompositorPrivate::removeSeat(DSWaylandSeat *dswlSeat)
395 {
396         DS_ASSERT(dswlSeat != nullptr);
397
398         //TODO : check if the client is in clients already ?
399         _seats.remove(dswlSeat);
400         DSLOG_INF("DSWaylandCompositorPrivate", "Seat(%p) has been removed.", dswlSeat);
401
402         //TODO : emit seatRemoved signal before deleting a seat;
403         delete dswlSeat;
404 }
405
406 bool DSWaylandCompositorPrivate::setShell(IDSWaylandShell *shell)
407 {
408         if (__shell)
409         {
410                 DSLOG_ERR("DSWaylandCompositor", "Already register IDSWaylandShell!");
411                 return false;
412         }
413
414         __shell = shell;
415         return true;
416 }
417
418 IDSWaylandShell *DSWaylandCompositorPrivate::getShell(void)
419 {
420         return __shell;
421 }
422
423
424 std::string DSWaylandCompositor::socketName()
425 {
426         DS_GET_PRIV(DSWaylandCompositor);
427
428         return priv->_socketName;
429 }
430
431 struct ::wl_display *DSWaylandCompositor::display()
432 {
433         DS_GET_PRIV(DSWaylandCompositor);
434
435         return priv->_display;
436 }
437
438 uint32_t DSWaylandCompositor::nextSerial()
439 {
440         DS_GET_PRIV(DSWaylandCompositor);
441
442         return wl_display_next_serial(priv->_display);
443 }
444
445 uint32_t DSWaylandCompositor::currentTime()
446 {
447         return ecore_time_unix_get();
448 }
449
450 void DSWaylandCompositor::addClient(DSWaylandClient *client)
451 {
452         DS_GET_PRIV(DSWaylandCompositor);
453
454         priv->addClient(client);
455 }
456
457 void DSWaylandCompositor::removeClient(DSWaylandClient *client)
458 {
459         DS_GET_PRIV(DSWaylandCompositor);
460
461         priv->removeClient(client);
462 }
463
464 DSWaylandSeat *DSWaylandCompositor::addSeat(uint32_t cap)
465 {
466         DS_GET_PRIV(DSWaylandCompositor);
467
468         return priv->addSeat(cap);
469 }
470
471 void DSWaylandCompositor::removeSeat(DSWaylandSeat *seat)
472 {
473         DS_GET_PRIV(DSWaylandCompositor);
474
475         priv->removeSeat(seat);
476 }
477
478 std::list<DSWaylandClient *> DSWaylandCompositor::clients()
479 {
480         DS_GET_PRIV(DSWaylandCompositor);
481
482         return priv->_clients;
483 }
484
485 DSWaylandSeat *DSWaylandCompositor::defaultSeat()
486 {
487         DS_GET_PRIV(DSWaylandCompositor);
488
489         if (!priv->_seats.empty())
490         {
491                 return priv->_seats.front();
492         }
493
494         return nullptr;
495 }
496
497 bool DSWaylandCompositor::setShell(IDSWaylandShell *shell)
498 {
499         DS_GET_PRIV(DSWaylandCompositor);
500         return priv->setShell(shell);
501 }
502
503 IDSWaylandShell *DSWaylandCompositor::getShell(void)
504 {
505         DS_GET_PRIV(DSWaylandCompositor);
506         return priv->getShell();
507 }
508
509 DSWaylandSurface *DSWaylandCompositor::getSurface(uint32_t id)
510 {
511         for (auto s : __surfaceList)
512         {
513                 if (s->getResourceId() == id)
514                 {
515                         return s.get();
516                 }
517         }
518
519         return nullptr;
520 }
521
522 void DSWaylandCompositor::sendSurfaceDestroy(DSWaylandSurface *dswSurface)
523 {
524         for (auto s : __surfaceList)
525         {
526                 if (s.get() == dswSurface)
527                 {
528                         __surfaceDestroySignal.emit(s);
529                         __surfaceList.remove(s);
530                         break;
531                 }
532         }
533 }
534
535 void DSWaylandCompositor::regionDestroy(DSWaylandRegion *dswRegion)
536 {
537         for (auto s : __regionList)
538         {
539                 if (s.get() == dswRegion)
540                 {
541                         __regionList.remove(s);
542                         break;
543                 }
544         }
545 }
546
547 void DSWaylandCompositor::registerCallbackSurfaceCreated(DSObject *slot, std::function<void(std::shared_ptr<DSWaylandSurface>)> func)
548 {
549         this->__surfaceCreatedSignal.connect(slot, func);
550 }
551
552 void DSWaylandCompositor::registerCallbackSurfaceDestroy(DSObject *slot, std::function<void(std::shared_ptr<DSWaylandSurface>)> func)
553 {
554         __surfaceDestroySignal.connect(slot, func);
555 }
556
557 }