1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qwaylanddisplay.h"
44 #include "qwaylandwindow.h"
45 #include "qwaylandscreen.h"
46 #include "qwaylandcursor.h"
47 #include "qwaylandinputdevice.h"
48 #include "qwaylandclipboard.h"
49 #include "qwaylanddatadevicemanager.h"
50 #include "qwaylandshell.h"
52 #ifdef QT_WAYLAND_GL_SUPPORT
53 #include "gl_integration/qwaylandglintegration.h"
56 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
57 #include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
60 #include "qwaylandextendedoutput.h"
61 #include "qwaylandextendedsurface.h"
62 #include "qwaylandsubsurface.h"
63 #include "qwaylandtouch.h"
65 #include <QtCore/QAbstractEventDispatcher>
66 #include <QtGui/private/qguiapplication_p.h>
73 #include <QtCore/QDebug>
75 struct wl_surface *QWaylandDisplay::createSurface(void *handle)
77 struct wl_surface * surface = wl_compositor_create_surface(mCompositor);
78 wl_surface_set_user_data(surface, handle);
82 #ifdef QT_WAYLAND_GL_SUPPORT
83 QWaylandGLIntegration * QWaylandDisplay::eglIntegration()
85 return mEglIntegration;
89 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
90 QWaylandWindowManagerIntegration *QWaylandDisplay::windowManagerIntegration()
92 return mWindowManagerIntegration;
96 QWaylandInputDevice *QWaylandDisplay::lastKeyboardFocusInputDevice() const
98 return mLastKeyboardFocusInputDevice;
101 void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *device)
103 qDebug() << "setting last keyboard focus input device" << device;
104 mLastKeyboardFocusInputDevice = device;
107 static QWaylandDisplay *display = 0;
109 static int dummyUpdate(uint32_t, void *)
114 QWaylandDisplay::QWaylandDisplay(void)
115 : mLastKeyboardFocusInputDevice(0)
116 , mDndSelectionHandler(0)
117 , mWindowExtension(0)
118 , mSubSurfaceExtension(0)
119 , mOutputExtension(0)
123 qRegisterMetaType<uint32_t>("uint32_t");
125 mDisplay = wl_display_connect(NULL);
126 if (mDisplay == NULL) {
127 qErrnoWarning(errno, "Failed to create display");
128 qFatal("No wayland connection available.");
131 wl_display_add_global_listener(mDisplay, QWaylandDisplay::displayHandleGlobal, this);
133 mFd = wl_display_get_fd(mDisplay, dummyUpdate, 0);
135 #ifdef WAYLAND_CLIENT_THREAD_AFFINITY
136 mWritableNotificationFd = wl_display_get_write_notification_fd(mDisplay);
137 QSocketNotifier *wn = new QSocketNotifier(mWritableNotificationFd, QSocketNotifier::Read, this);
138 connect(wn, SIGNAL(activated(int)), this, SLOT(flushRequests()));
140 QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
141 connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(flushRequests()));
144 mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this);
145 connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(readEvents()));
147 #ifdef QT_WAYLAND_GL_SUPPORT
148 mEglIntegration = QWaylandGLIntegration::createGLIntegration(this);
151 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
152 mWindowManagerIntegration = QWaylandWindowManagerIntegration::createIntegration(this);
155 blockingReadEvents();
157 #ifdef QT_WAYLAND_GL_SUPPORT
158 mEglIntegration->initialize();
164 QWaylandDisplay::~QWaylandDisplay(void)
166 #ifdef QT_WAYLAND_GL_SUPPORT
167 delete mEglIntegration;
169 wl_display_destroy(mDisplay);
172 void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry)
174 QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry);
175 mScreens.append(waylandScreen);
178 void QWaylandDisplay::flushRequests()
180 wl_display_flush(mDisplay);
183 void QWaylandDisplay::readEvents()
199 int ret = ::select(mFd+1, &rs, &ws, &es, &timeout );
205 wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
208 void QWaylandDisplay::blockingReadEvents()
210 wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
213 QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
215 for (int i = 0; i < mScreens.size(); ++i) {
216 QWaylandScreen *screen = static_cast<QWaylandScreen *>(mScreens.at(i));
217 if (screen->output() == output)
223 void QWaylandDisplay::outputHandleGeometry(void *data,
225 int32_t x, int32_t y,
226 int32_t physicalWidth,
227 int32_t physicalHeight,
229 const char *make, const char *model)
234 QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data);
235 QRect outputRect = QRect(x, y, physicalWidth, physicalHeight);
236 waylandDisplay->createNewScreen(output,outputRect);
239 void QWaylandDisplay::mode(void *data,
240 struct wl_output *wl_output,
254 const struct wl_output_listener QWaylandDisplay::outputListener = {
255 QWaylandDisplay::outputHandleGeometry,
256 QWaylandDisplay::mode
259 void QWaylandDisplay::waitForScreens()
262 while (mScreens.isEmpty())
263 blockingReadEvents();
266 void QWaylandDisplay::displayHandleGlobal(struct wl_display *display,
268 const char *interface,
273 QWaylandDisplay *that = static_cast<QWaylandDisplay *>(data);
274 that->displayHandleGlobal(id, QByteArray(interface), version);
277 void QWaylandDisplay::displayHandleGlobal(uint32_t id,
278 const QByteArray &interface,
282 if (interface == "wl_output") {
283 struct wl_output *output = static_cast<struct wl_output *>(wl_display_bind(mDisplay,id,&wl_output_interface));
284 wl_output_add_listener(output, &outputListener, this);
285 } else if (interface == "wl_compositor") {
286 mCompositor = static_cast<struct wl_compositor *>(wl_display_bind(mDisplay, id,&wl_compositor_interface));
287 } else if (interface == "wl_shm") {
288 mShm = static_cast<struct wl_shm *>(wl_display_bind(mDisplay, id, &wl_shm_interface));
289 } else if (interface == "wl_shell"){
290 mShell = new QWaylandShell(this,id,version);
291 } else if (interface == "wl_input_device") {
292 QWaylandInputDevice *inputDevice =
293 new QWaylandInputDevice(this, id);
294 mInputDevices.append(inputDevice);
295 } else if (interface == "wl_data_device_manager") {
296 mDndSelectionHandler = new QWaylandDataDeviceManager(this, id);
297 } else if (interface == "wl_output_extension") {
298 mOutputExtension = new QWaylandOutputExtension(this,id);
299 } else if (interface == "wl_surface_extension") {
300 mWindowExtension = new QWaylandSurfaceExtension(this,id);
301 } else if (interface == "wl_sub_surface_extension") {
302 mSubSurfaceExtension = new QWaylandSubSurfaceExtension(this,id);
303 } else if (interface == "wl_touch_extension") {
304 mTouchExtension = new QWaylandTouchExtension(this, id);
308 uint32_t QWaylandDisplay::currentTimeMillisec()
310 //### we throw away the time information
312 int ret = gettimeofday(&tv, 0);
314 return tv.tv_sec*1000 + tv.tv_usec/1000;
318 void QWaylandDisplay::forceRoundTrip()
320 wl_display_roundtrip(mDisplay);