summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wayland/qwaylanddisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/wayland/qwaylanddisplay.cpp')
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp241
1 files changed, 132 insertions, 109 deletions
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 27f43345d1..1c56561904 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -46,13 +46,23 @@
#include "qwaylandcursor.h"
#include "qwaylandinputdevice.h"
+#ifdef QT_WAYLAND_GL_SUPPORT
+#include "gl_integration/qwaylandglintegration.h"
+#endif
+
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtGui/QApplication>
+
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
+#include <errno.h>
-struct wl_surface *QWaylandDisplay::createSurface()
+struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
- return wl_compositor_create_surface(mCompositor);
+ struct wl_surface * surface = wl_compositor_create_surface(mCompositor);
+ wl_surface_set_user_data(surface, handle);
+ return surface;
}
struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd,
@@ -78,10 +88,12 @@ struct wl_visual *QWaylandDisplay::argbPremultipliedVisual()
return wl_display_get_premultiplied_argb_visual(mDisplay);
}
-struct wl_egl_display *QWaylandDisplay::nativeDisplay()
+#ifdef QT_WAYLAND_GL_SUPPORT
+QWaylandGLIntegration * QWaylandDisplay::eglIntegration()
{
- return mNativeEglDisplay;
+ return mEglIntegration;
}
+#endif
void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell,
uint32_t time, uint32_t edges,
@@ -101,147 +113,158 @@ const struct wl_shell_listener QWaylandDisplay::shellListener = {
QWaylandDisplay::shellHandleConfigure,
};
-void QWaylandDisplay::outputHandleGeometry(void *data,
- struct wl_output *output,
- int32_t x, int32_t y,
- int32_t width, int32_t height)
+QWaylandDisplay::QWaylandDisplay(void)
{
- QWaylandDisplay *waylandDisplay = (QWaylandDisplay *) data;
+ mDisplay = wl_display_connect(NULL);
+ if (mDisplay == NULL) {
+ qErrnoWarning(errno, "Failed to create display");
+ qFatal("No wayland connection available.");
+ }
- QRect outputRect = QRect(x, y, width, height);
- waylandDisplay->createNewScreen(output, outputRect);
-}
+ wl_display_add_global_listener(mDisplay, QWaylandDisplay::displayHandleGlobal, this);
-const struct wl_output_listener QWaylandDisplay::outputListener = {
- QWaylandDisplay::outputHandleGeometry
-};
+#ifdef QT_WAYLAND_GL_SUPPORT
+ mEglIntegration = QWaylandGLIntegration::createGLIntegration(this);
+#endif
-void QWaylandDisplay::displayHandleGlobal(struct wl_display *display,
- uint32_t id,
- const char *interface,
- uint32_t version, void *data)
-{
- Q_UNUSED(version);
- QWaylandDisplay *qwd = (QWaylandDisplay *) data;
-
- if (strcmp(interface, "compositor") == 0) {
- qwd->mCompositor = wl_compositor_create(display, id);
- } else if (strcmp(interface, "shm") == 0) {
- qwd->mShm = wl_shm_create(display, id);
- } else if (strcmp(interface, "shell") == 0) {
- qwd->mShell = wl_shell_create(display, id);
- wl_shell_add_listener(qwd->mShell, &shellListener, qwd);
- } else if (strcmp(interface, "output") == 0) {
- struct wl_output *output = wl_output_create(display, id);
- wl_output_add_listener(output, &outputListener, qwd);
- } else if (strcmp(interface, "input_device") == 0) {
- QWaylandInputDevice *inputDevice =
- new QWaylandInputDevice(display, id);
- qwd->mInputDevices.append(inputDevice);
- }
+ qRegisterMetaType<uint32_t>("uint32_t");
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+ mEglIntegration->initialize();
+#endif
+
+ connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(flushRequests()));
+
+ mFd = wl_display_get_fd(mDisplay, sourceUpdate, this);
+
+ mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this);
+ connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(readEvents()));
+
+ waitForScreens();
}
-void QWaylandDisplay::iterate()
+QWaylandDisplay::~QWaylandDisplay(void)
{
- wl_display_iterate(mDisplay, WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE);
+ close(mFd);
+#ifdef QT_WAYLAND_GL_SUPPORT
+ delete mEglIntegration;
+#endif
+ wl_display_destroy(mDisplay);
}
-void QWaylandDisplay::readEvents(void)
+void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry)
{
- wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
+ QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry);
+ mScreens.append(waylandScreen);
}
-int
-QWaylandDisplay::sourceUpdate(uint32_t mask, void *data)
+void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data)
{
- QWaylandDisplay *qwd = (QWaylandDisplay *) data;
-
- /* FIXME: We get a callback here when we ask wl_display for the
- * fd, but at that point we don't have the socket notifier as we
- * need the fd to create that. We'll probably need to split that
- * API into get_fd and set_update_func functions. */
- if (qwd->mWriteNotifier == NULL)
- return 0;
-
- qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE);
+ wl_display_sync_callback(mDisplay, func, data);
+}
- return 0;
+void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, struct wl_surface *surface, void *data)
+{
+ wl_display_frame_callback(mDisplay, surface, func, data);
}
-void QWaylandDisplay::flushRequests(void)
+void QWaylandDisplay::flushRequests()
{
- wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE);
+ if (mSocketMask & WL_DISPLAY_WRITABLE)
+ wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE);
}
-QWaylandDisplay::QWaylandDisplay(void)
- : mWriteNotifier(0)
+void QWaylandDisplay::readEvents()
{
-#ifdef QT_WAYLAND_GL_SUPPORT
- EGLint major, minor;
-#endif
- mDisplay = wl_display_connect(NULL);
- if (mDisplay == NULL) {
- fprintf(stderr, "failed to create display: %m\n");
+// verify that there is still data on the socket
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(mFd, &fds);
+ fd_set nds;
+ FD_ZERO(&nds);
+ fd_set rs = fds;
+ fd_set ws = nds;
+ fd_set es = nds;
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ int ret = ::select(mFd+1, &rs, &ws, &es, &timeout );
+
+ if (ret <= 0) {
+ //qDebug("QWaylandDisplay::readEvents() No data... blocking avoided");
return;
}
- wl_display_add_global_listener(mDisplay,
- QWaylandDisplay::displayHandleGlobal, this);
-
-#ifdef QT_WAYLAND_GL_SUPPORT
- mNativeEglDisplay = wl_egl_display_create(mDisplay);
-#else
- mNativeEglDisplay = 0;
-#endif
-
- readEvents();
+ wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
+}
-#ifdef QT_WAYLAND_GL_SUPPORT
- mEglDisplay = eglGetDisplay((EGLNativeDisplayType)mNativeEglDisplay);
- if (mEglDisplay == NULL) {
- qWarning("EGL not available");
- } else {
- if (!eglInitialize(mEglDisplay, &major, &minor)) {
- qWarning("failed to initialize EGL display");
- return;
- }
- }
-#else
- mEglDisplay = 0;
-#endif
+void QWaylandDisplay::blockingReadEvents()
+{
+ wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
+}
- int fd = wl_display_get_fd(mDisplay, sourceUpdate, this);
- mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
- connect(mReadNotifier,
- SIGNAL(activated(int)), this, SLOT(readEvents()));
+int QWaylandDisplay::sourceUpdate(uint32_t mask, void *data)
+{
+ QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data);
+ waylandDisplay->mSocketMask = mask;
- mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this);
- connect(mWriteNotifier,
- SIGNAL(activated(int)), this, SLOT(flushRequests()));
- mWriteNotifier->setEnabled(false);
+ return 0;
}
-QWaylandDisplay::~QWaylandDisplay(void)
+void QWaylandDisplay::outputHandleGeometry(void *data,
+ struct wl_output *output,
+ int32_t x, int32_t y,
+ int32_t width, int32_t height)
{
- close(mFd);
-#ifdef QT_WAYLAND_GL_SUPPORT
- eglTerminate(mEglDisplay);
-#endif
- wl_display_destroy(mDisplay);
+ //call back function called from another thread;
+ //but its safe to call createScreen from another thread since
+ //QWaylandScreen does a moveToThread
+ QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data);
+ QRect outputRect = QRect(x, y, width, height);
+ waylandDisplay->createNewScreen(output,outputRect);
}
-void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry)
+const struct wl_output_listener QWaylandDisplay::outputListener = {
+ QWaylandDisplay::outputHandleGeometry
+};
+
+void QWaylandDisplay::waitForScreens()
{
- QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry);
- mScreens.append(waylandScreen);
+ flushRequests();
+ while (mScreens.isEmpty())
+ blockingReadEvents();
}
-void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data)
+void QWaylandDisplay::displayHandleGlobal(struct wl_display *display,
+ uint32_t id,
+ const char *interface,
+ uint32_t version,
+ void *data)
{
- wl_display_sync_callback(mDisplay, func, data);
+ Q_UNUSED(display);
+ QWaylandDisplay *that = static_cast<QWaylandDisplay *>(data);
+ that->displayHandleGlobal(id, QByteArray(interface), version);
}
-void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data)
+void QWaylandDisplay::displayHandleGlobal(uint32_t id,
+ const QByteArray &interface,
+ uint32_t version)
{
- wl_display_frame_callback(mDisplay, func, data);
+ Q_UNUSED(version);
+
+ if (interface == "output") {
+ struct wl_output *output = wl_output_create(mDisplay, id);
+ wl_output_add_listener(output, &outputListener, this);
+ } else if (interface == "compositor") {
+ mCompositor = wl_compositor_create(mDisplay, id);
+ } else if (interface == "shm") {
+ mShm = wl_shm_create(mDisplay, id);
+ } else if (interface == "shell"){
+ mShell = wl_shell_create(mDisplay, id);
+ wl_shell_add_listener(mShell, &shellListener, this);
+ } else if (interface == "input_device") {
+ QWaylandInputDevice *inputDevice =
+ new QWaylandInputDevice(mDisplay, id);
+ mInputDevices.append(inputDevice);
+ }
}