1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Qt Compositor.
9 ** $QT_BEGIN_LICENSE:BSD$
10 ** You may use this file under the terms of the BSD license as follows:
12 ** "Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
15 ** * Redistributions of source code must retain the above copyright
16 ** notice, this list of conditions and the following disclaimer.
17 ** * Redistributions in binary form must reproduce the above copyright
18 ** notice, this list of conditions and the following disclaimer in
19 ** the documentation and/or other materials provided with the
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22 ** the names of its contributors may be used to endorse or promote
23 ** products derived from this software without specific prior written
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
41 #include "wlcompositor.h"
43 #include "waylandinput.h"
44 #include "wldisplay.h"
45 #include "wlshmbuffer.h"
46 #include "wlsurface.h"
47 #include "waylandcompositor.h"
48 #include "wldatadevicemanager.h"
49 #include "wldatadevice.h"
50 #include "wlextendedoutput.h"
51 #include "wlextendedsurface.h"
52 #include "wlsubsurface.h"
53 #include "wlshellsurface.h"
55 #include "wlinputdevice.h"
58 #include <QSocketNotifier>
70 #include <sys/select.h>
73 #include <wayland-server.h>
75 #include "hardware_integration/graphicshardwareintegration.h"
76 #include "waylandwindowmanagerintegration.h"
80 static Compositor *compositor;
82 void compositor_create_surface(struct wl_client *client,
83 struct wl_resource *resource, uint32_t id)
85 static_cast<Compositor *>(resource->data)->createSurface(client,id);
88 const static struct wl_compositor_interface compositor_interface = {
89 compositor_create_surface
92 void Compositor::bind_func(struct wl_client *client, void *data,
93 uint32_t version, uint32_t id)
96 wl_client_add_object(client,&wl_compositor_interface, &compositor_interface, id,data);
100 Compositor *Compositor::instance()
105 Compositor::Compositor(WaylandCompositor *qt_compositor)
106 : m_display(new Display)
107 , m_default_input_device(0)
110 , m_last_queued_buf(-1)
111 , m_qt_compositor(qt_compositor)
112 , m_orientation(Qt::UnknownOrientation)
113 , m_directRenderSurface(0)
114 #if defined (QT_COMPOSITOR_WAYLAND_GL)
115 , m_graphics_hw_integration(0)
117 , m_outputExtension(0)
118 , m_surfaceExtension(0)
119 , m_subSurfaceExtension(0)
120 , m_touchExtension(0)
124 qDebug() << "Compositor instance is" << this;
126 #if defined (QT_COMPOSITOR_WAYLAND_GL)
127 QWindow *window = qt_compositor->window();
128 if (window && window->surfaceType() != QWindow::RasterSurface)
129 m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor);
131 m_windowManagerIntegration = new WindowManagerServerIntegration(this);
133 wl_display_add_global(m_display->handle(),&wl_compositor_interface,this,Compositor::bind_func);
135 m_data_device_manager = new DataDeviceManager(this);
137 wl_display_add_global(m_display->handle(),&wl_output_interface, &m_output_global,OutputGlobal::output_bind_func);
139 wl_display_add_global(m_display->handle(), &wl_shell_interface, &m_shell, Shell::bind_func);
141 m_shell = new Shell();
142 m_outputExtension = new OutputExtensionGlobal(this);
143 m_surfaceExtension = new SurfaceExtensionGlobal(this);
145 if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) {
146 fprintf(stderr, "Fatal: Failed to open server socket\n");
150 m_loop = wl_display_get_event_loop(m_display->handle());
152 int fd = wl_event_loop_get_fd(m_loop);
154 QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, this);
155 connect(sockNot, SIGNAL(activated(int)), this, SLOT(processWaylandEvents()));
157 //initialize distancefieldglyphcache here
160 Compositor::~Compositor()
162 delete m_default_input_device;
163 delete m_data_device_manager;
168 void Compositor::frameFinished(Surface *surface)
170 if (surface && m_dirty_surfaces.contains(surface)) {
171 m_dirty_surfaces.remove(surface);
172 surface->sendFrameCallback();
173 } else if (!surface) {
174 QSet<Surface *> dirty = m_dirty_surfaces;
175 m_dirty_surfaces.clear();
176 foreach (Surface *surface, dirty)
177 surface->sendFrameCallback();
181 void Compositor::createSurface(struct wl_client *client, uint32_t id)
183 Surface *surface = new Surface(client,id, this);
184 printf("Compositor::createSurface: %p %d\n", client, id);
186 m_surfaces << surface;
188 m_qt_compositor->surfaceCreated(surface->handle());
191 struct wl_client *Compositor::getClientFromWinId(uint winId) const
193 Surface *surface = getSurfaceFromWinId(winId);
195 return surface->base()->resource.client;
200 Surface *Compositor::getSurfaceFromWinId(uint winId) const
202 foreach (Surface *surface, m_surfaces) {
203 if (surface->id() == winId)
210 QImage Compositor::image(uint winId) const
212 printf("Compositor::image(%x)\n", winId);
213 foreach (Surface *surface, m_surfaces) {
214 if (surface->id() == winId) {
215 return surface->image();
222 uint Compositor::currentTimeMsecs()
224 //### we throw away the time information
226 int ret = gettimeofday(&tv, 0);
228 return tv.tv_sec*1000 + tv.tv_usec/1000;
232 void Compositor::releaseBuffer(void *bufferHandle)
234 struct wl_buffer *buffer = static_cast<struct wl_buffer*>(bufferHandle);
236 //qDebug() << "WL_BUFFER_RELEASE" << buffer<< buffer->resource.client;
237 wl_resource_post_event(&buffer->resource, WL_BUFFER_RELEASE);
242 void Compositor::processWaylandEvents()
244 int ret = wl_event_loop_dispatch(m_loop, 0);
246 fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret);
249 void Compositor::surfaceDestroyed(Surface *surface)
251 m_surfaces.removeOne(surface);
252 m_dirty_surfaces.remove(surface);
253 if (m_directRenderSurface == surface)
254 setDirectRenderSurface(0);
257 void Compositor::markSurfaceAsDirty(Wayland::Surface *surface)
259 m_dirty_surfaces.insert(surface);
262 void Compositor::destroyClientForSurface(Surface *surface)
264 wl_client *client = surface->base()->resource.client;
267 m_windowManagerIntegration->removeClient(client);
268 wl_client_destroy(client);
272 QWindow *Compositor::window() const
274 return m_qt_compositor->window();
277 GraphicsHardwareIntegration * Compositor::graphicsHWIntegration() const
279 #ifdef QT_COMPOSITOR_WAYLAND_GL
280 return m_graphics_hw_integration;
286 void Compositor::initializeHardwareIntegration()
288 #ifdef QT_COMPOSITOR_WAYLAND_GL
289 if (m_graphics_hw_integration)
290 m_graphics_hw_integration->initializeHardware(m_display);
294 void Compositor::initializeDefaultInputDevice()
296 WaylandInputDevice *defaultInput = new WaylandInputDevice(m_qt_compositor);
297 m_default_input_device = defaultInput->handle();
300 void Compositor::initializeWindowManagerProtocol()
302 m_windowManagerIntegration->initialize(m_display);
305 void Compositor::enableSubSurfaceExtension()
307 if (!m_subSurfaceExtension) {
308 m_subSurfaceExtension = new SubSurfaceExtensionGlobal(this);
312 bool Compositor::setDirectRenderSurface(Surface *surface)
314 #ifdef QT_COMPOSITOR_WAYLAND_GL
315 if (m_graphics_hw_integration && m_graphics_hw_integration->setDirectRenderSurface(surface ? surface->handle() : 0)) {
316 m_directRenderSurface = surface;
325 QList<struct wl_client *> Compositor::clients() const
327 QList<struct wl_client *> list;
328 foreach (Surface *surface, m_surfaces) {
329 struct wl_client *client = surface->base()->resource.client;
330 if (!list.contains(client))
336 void Compositor::setScreenOrientation(Qt::ScreenOrientation orientation)
338 m_orientation = orientation;
340 QList<struct wl_client*> clientList = clients();
341 for (int i = 0; i < clientList.length(); ++i) {
342 struct wl_client *client = clientList.at(i);
343 Output *output = m_output_global.outputForClient(client);
345 if (output->extendedOutput()){
346 output->extendedOutput()->sendOutputOrientation(orientation);
351 Qt::ScreenOrientation Compositor::screenOrientation() const
353 return m_orientation;
356 void Compositor::setOutputGeometry(const QRect &geometry)
358 m_output_global.setGeometry(geometry);
361 InputDevice* Compositor::defaultInputDevice()
363 return m_default_input_device;
366 QList<Wayland::Surface *> Compositor::surfacesForClient(wl_client *client)
368 QList<Wayland::Surface *> ret;
370 for (int i=0; i < m_surfaces.count(); ++i) {
371 if (m_surfaces.at(i)->base()->resource.client == client) {
372 ret.append(m_surfaces.at(i));
378 void Compositor::enableTouchExtension()
380 if (!m_touchExtension) {
381 m_touchExtension = new TouchExtensionGlobal(this);
385 void Compositor::setRetainedSelectionWatcher(RetainedSelectionFunc func, void *param)
387 m_retainNotify = func;
388 m_retainNotifyParam = param;
391 bool Compositor::wantsRetainedSelection() const
393 return m_retainNotify != 0;
396 void Compositor::feedRetainedSelectionData(QMimeData *data)
398 if (m_retainNotify) {
399 m_retainNotify(data, m_retainNotifyParam);
403 void Compositor::overrideSelection(QMimeData *data)
405 m_data_device_manager->overrideSelection(*data);
408 bool Compositor::isDragging() const
413 void Compositor::sendDragMoveEvent(const QPoint &global, const QPoint &local,
419 // Drag::instance()->dragMove(global, local, surface);
422 void Compositor::sendDragEndEvent()
424 // Drag::instance()->dragEnd();
427 } // namespace Wayland