2 * Copyright © 2020 Samsung Electronics co., Ltd. All Rights Reserved.
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:
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
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.
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"
34 namespace display_server
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 };
42 /* Begin Private Class Implementation */
43 DSWaylandCompositorPrivate::DSWaylandCompositorPrivate(DSWaylandCompositor *compositor)
44 : DSObjectPrivate(compositor),
46 m_clientCreatedListener({nullptr, nullptr}),
52 _socket_fd_handler(nullptr),
53 _compositor(compositor),
54 __wlExtension(nullptr),
59 DSLOG_ERR("DSWaylandCompositor", "ecore_init() fails.\n");
63 _display = wl_display_create();
64 DS_ASSERT(_display != nullptr);
66 m_clientCreatedListener.notify = DSWaylandCompositorPrivate::client_created_callback;
67 m_clientCreatedListener.parent = this;
68 wl_display_add_client_created_listener(_display, &m_clientCreatedListener);
71 DSWaylandCompositorPrivate::~DSWaylandCompositorPrivate()
73 //TODO : destroy all allocated resources
75 wl_list_remove(&m_clientCreatedListener.link);
81 if (_socket_fd_handler)
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;
90 wl_display_destroy(_display);
97 _compositor = nullptr;
103 void DSWaylandCompositorPrivate::client_created_callback(struct ::wl_listener *listener, void *data)
105 struct ::wl_client *wlClient = (struct ::wl_client *)data;
106 DS_ASSERT(wlClient != nullptr);
108 DSWaylandClient *client = nullptr;
109 DSWaylandCompositorPrivate *compPriv = reinterpret_cast<ClientCreatedListener *>(listener)->parent;
111 if (compPriv != nullptr)
113 client = new DSWaylandClient(compPriv->_compositor, wlClient);
114 DS_ASSERT(client != nullptr);
116 DSLOG_INF("DSWaylandCompositorPrivate", "Client created ! (pid:%d, uid:%d, gid:%d)",
117 client->pid(), client->uid(), client->gid());
121 void DSWaylandCompositorPrivate::initSocket(std::string sName, std::string sDir)
123 std::string socketPath = std::move(sDir);
125 socketPath.append(1, '/');
126 socketPath.append(_socketName);
130 DSUtilSocket *utilSocket = DSUtilSocket::getInstance();
131 utilSocket->initSocket(sName);
132 utilSocket->releaseInstance();
134 //TODO : set permissions for Owner, Group and Other
135 //TODO : set Smack attributes for socket
136 //TODO : set symbolic link for socket
139 bool DSWaylandCompositorPrivate::initCompositor()
143 DSLOG_ERR("DSWaylandCompositor", "_display(wl_display) is NULL !\n");
147 //Initialize needed interfaces
148 //TODO : get/set DSConfig::version("wl_compositor")
149 wl_compositor::init(_display, 4);
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);
155 if (_socketName.empty())
157 DSLOG_ERR("DSWaylandCompositor", "_socketName is empty()\n");
161 initSocket(_socketName, "/run");
163 //TODO : DSConfig::setEnv("WAYLAND_DISPLAY", _socketName);
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 ¬ify_func);
170 //TODO : add event dispatcher for wayland socket and other fd(s)
171 _loop = wl_display_get_event_loop(_display);
175 DSLOG_ERR("DSWaylandCompositor", "_loop is nullptr.\n");
179 _socketFD = wl_event_loop_get_fd(_loop);
183 DSLOG_ERR("DSWaylandCompositor", "_socketFD is invalid. (_socketFD=%d)\n", _socketFD);
187 auto evFlags = ECORE_FD_READ | ECORE_FD_ERROR;
189 _socket_fd_handler = ecore_main_fd_handler_add(_socketFD,
190 static_cast<Ecore_Fd_Handler_Flags >(evFlags),
191 __readEvents, this, NULL, NULL);
193 if (!_socket_fd_handler)
195 DSLOG_ERR("DSWaylandCompositor", "_socket_fd_handler is invalid.\n");
198 ecore_main_fd_handler_prepare_callback_set(_socket_fd_handler,
199 __prepareFunc, this);
204 bool DSWaylandCompositorPrivate::initExtension()
208 DSLOG_INF("DSWaylandCompositor", "Already initialize Extension");
212 __wlExtension = std::make_unique<DSWaylandExtension>(_compositor);
213 if (!__wlExtension) return false;
218 Eina_Bool DSWaylandCompositorPrivate::__readEvents(void *data, Ecore_Fd_Handler *hdlr)
220 DSWaylandCompositorPrivate *compPrivate = (DSWaylandCompositorPrivate *) data;
224 DSLOG_DBG("DSWaylandCompositor", "compPrivate is invalid.\n");
225 return ECORE_CALLBACK_RENEW;
230 /* dispatch pending wayland events */
231 int ret = wl_event_loop_dispatch(compPrivate->_loop, 0);
235 DSLOG_ERR("DSWaylandCompositor", "Failed on wl_event_loop_dispatch()\n");
238 return ECORE_CALLBACK_RENEW;
241 void DSWaylandCompositorPrivate::__prepareFunc(void *data, Ecore_Fd_Handler *hdlr)
243 DSWaylandCompositorPrivate *compPrivate = (DSWaylandCompositorPrivate *) data;
247 DSLOG_DBG("DSWaylandCompositor", "compPrivate is invalid.\n");
253 /* flush pending client events */
254 wl_display_flush_clients(compPrivate->_display);
257 void DSWaylandCompositorPrivate::compositor_bind_resource(wl_compositor::Resource *resource)
259 //TODO : Leave log (pid/uid/gid and process name)
260 //TODO : Update connected client list (add)
263 void DSWaylandCompositorPrivate::compositor_destroy_resource(wl_compositor::Resource *resource)
265 //TODO : Leave log (pid/uid/gid and process name)
266 //TODO : Update connected client list (remove)
269 void DSWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resource *resource, uint32_t id)
271 DS_GET_PUB(DSWaylandCompositor);
273 DSWaylandClient *waylandClient = DSWaylandClient::fromWlClient(resource->client());
274 auto waylandSruface = std::make_shared<DSWaylandSurface>(waylandClient, id);
276 pub->__surfaceList.push_front(waylandSruface);
278 // emit a signal of the surface created
279 pub->__surfaceCreatedSignal.emit(waylandSruface);
282 void DSWaylandCompositorPrivate::compositor_create_region(wl_compositor::Resource *resource, uint32_t id)
284 DS_GET_PUB(DSWaylandCompositor);
286 DSWaylandClient *waylandClient = DSWaylandClient::fromWlClient(resource->client());
287 auto waylandRegion = std::make_shared<DSWaylandRegion>(waylandClient, id);
289 pub->__regionList.push_front(waylandRegion);
292 /* Begin Public Class Implementation */
293 DSWaylandCompositor::DSWaylandCompositor(DSObject *parent)
294 : DS_INIT_PRIVATE_PTR(DSWaylandCompositor)
299 DSWaylandCompositor::~DSWaylandCompositor()
304 /* getInstance for DSWaylandCompositor singleton */
305 DSWaylandCompositor *DSWaylandCompositor::getInstance()
307 std::lock_guard<std::mutex> tLock(__mutex);
309 DSLOG_INF("DSWaylandCompositor",
310 "[Get] instance __refCount=%d !", __refCount);
312 if (!__comp && (__refCount == 0))
314 __comp = new DSWaylandCompositor(new DSObject);
315 DSLOG_INF("DSWaylandCompositor",
316 "DSWaylandCompositor instance has been created !");
323 /* releaseInstance for DSWaylandCompositor singleton */
324 void DSWaylandCompositor::releaseInstance()
326 std::lock_guard<std::mutex> tLock(__mutex);
331 DSLOG_INF("DSWaylandCompositor",
332 "[Release] instance __refCount=%d !", __refCount);
334 if ((0 == __refCount) && __comp)
338 DSLOG_INF("DSWaylandCompositor",
339 "DSWaylandCompositor instance has been removed !");
343 bool DSWaylandCompositor::create()
345 DS_GET_PRIV(DSWaylandCompositor);
349 res = priv->initCompositor();
352 DSLOG_ERR("DSWaylandCompositor", "Failed on initCompositor ! (res=%d)\n", res);
356 res = priv->initExtension();
359 DSLOG_ERR("DSWaylandCompositor", "Failed on initExtension ! (res=%d)\n", res);
363 priv->_created = true;
367 bool DSWaylandCompositor::isCreated()
369 DS_GET_PRIV(DSWaylandCompositor);
371 return priv->_created;
374 DSWaylandSeat *DSWaylandCompositorPrivate::addSeat(uint32_t cap)
376 DSWaylandSeat *dswlSeat = new DSWaylandSeat(_compositor, (DSWaylandSeat::seatCapability)cap);
380 DSLOG_ERR("DSWaylandCompositorPrivate", "Failed to create DSWaylandSeat !");
384 //TODO : check if the client is in clients already ?
385 _seats.push_back(dswlSeat);
387 DSLOG_INF("DSWaylandCompositorPrivate", "Seat(%p) has been added.", dswlSeat);
389 //TODO : emit seatAdded signal
394 void DSWaylandCompositorPrivate::removeSeat(DSWaylandSeat *dswlSeat)
396 DS_ASSERT(dswlSeat != nullptr);
398 //TODO : check if the client is in clients already ?
399 _seats.remove(dswlSeat);
400 DSLOG_INF("DSWaylandCompositorPrivate", "Seat(%p) has been removed.", dswlSeat);
402 //TODO : emit seatRemoved signal before deleting a seat;
406 bool DSWaylandCompositorPrivate::setShell(IDSWaylandShell *shell)
410 DSLOG_ERR("DSWaylandCompositor", "Already register IDSWaylandShell!");
418 IDSWaylandShell *DSWaylandCompositorPrivate::getShell(void)
424 std::string DSWaylandCompositor::socketName()
426 DS_GET_PRIV(DSWaylandCompositor);
428 return priv->_socketName;
431 struct ::wl_display *DSWaylandCompositor::display()
433 DS_GET_PRIV(DSWaylandCompositor);
435 return priv->_display;
438 uint32_t DSWaylandCompositor::nextSerial()
440 DS_GET_PRIV(DSWaylandCompositor);
442 return wl_display_next_serial(priv->_display);
445 uint32_t DSWaylandCompositor::currentTime()
447 return ecore_time_unix_get();
450 void DSWaylandCompositor::addClient(DSWaylandClient *client)
452 DS_GET_PRIV(DSWaylandCompositor);
454 priv->addClient(client);
457 void DSWaylandCompositor::removeClient(DSWaylandClient *client)
459 DS_GET_PRIV(DSWaylandCompositor);
461 priv->removeClient(client);
464 DSWaylandSeat *DSWaylandCompositor::addSeat(uint32_t cap)
466 DS_GET_PRIV(DSWaylandCompositor);
468 return priv->addSeat(cap);
471 void DSWaylandCompositor::removeSeat(DSWaylandSeat *seat)
473 DS_GET_PRIV(DSWaylandCompositor);
475 priv->removeSeat(seat);
478 std::list<DSWaylandClient *> DSWaylandCompositor::clients()
480 DS_GET_PRIV(DSWaylandCompositor);
482 return priv->_clients;
485 DSWaylandSeat *DSWaylandCompositor::defaultSeat()
487 DS_GET_PRIV(DSWaylandCompositor);
489 if (!priv->_seats.empty())
491 return priv->_seats.front();
497 bool DSWaylandCompositor::setShell(IDSWaylandShell *shell)
499 DS_GET_PRIV(DSWaylandCompositor);
500 return priv->setShell(shell);
503 IDSWaylandShell *DSWaylandCompositor::getShell(void)
505 DS_GET_PRIV(DSWaylandCompositor);
506 return priv->getShell();
509 DSWaylandSurface *DSWaylandCompositor::getSurface(uint32_t id)
511 for (auto s : __surfaceList)
513 if (s->getResourceId() == id)
522 void DSWaylandCompositor::sendSurfaceDestroy(DSWaylandSurface *dswSurface)
524 for (auto s : __surfaceList)
526 if (s.get() == dswSurface)
528 __surfaceDestroySignal.emit(s);
529 __surfaceList.remove(s);
535 void DSWaylandCompositor::regionDestroy(DSWaylandRegion *dswRegion)
537 for (auto s : __regionList)
539 if (s.get() == dswRegion)
541 __regionList.remove(s);
547 void DSWaylandCompositor::registerCallbackSurfaceCreated(DSObject *slot, std::function<void(std::shared_ptr<DSWaylandSurface>)> func)
549 this->__surfaceCreatedSignal.connect(slot, func);
552 void DSWaylandCompositor::registerCallbackSurfaceDestroy(DSObject *slot, std::function<void(std::shared_ptr<DSWaylandSurface>)> func)
554 __surfaceDestroySignal.connect(slot, func);