diff options
-rw-r--r-- | config.tests/qpa/wayland/wayland.cpp | 7 | ||||
-rw-r--r-- | config.tests/qpa/wayland/wayland.pro | 6 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | src/plugins/platforms/platforms.pro | 4 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/main.cpp | 72 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandintegration.cpp | 399 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandintegration.h | 156 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindowsurface.cpp | 131 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindowsurface.h | 71 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/wayland.pro | 19 |
10 files changed, 870 insertions, 0 deletions
diff --git a/config.tests/qpa/wayland/wayland.cpp b/config.tests/qpa/wayland/wayland.cpp new file mode 100644 index 0000000..40ff2cb --- /dev/null +++ b/config.tests/qpa/wayland/wayland.cpp @@ -0,0 +1,7 @@ +#include "wayland-client.h" +#include "wayland-glib.h" + +int main(int, char **) +{ + return 0; +} diff --git a/config.tests/qpa/wayland/wayland.pro b/config.tests/qpa/wayland/wayland.pro new file mode 100644 index 0000000..83f5efe --- /dev/null +++ b/config.tests/qpa/wayland/wayland.pro @@ -0,0 +1,6 @@ +SOURCES = client.cpp +CONFIG -= qt + +QMAKE_CXXFLAGS += $$QT_CFLAGS_WAYLAND +LIBS += $$QT_LIBS_WAYLAND -lfreetype -lfontconfig -lwayland-client + @@ -6185,6 +6185,11 @@ if [ "$PLATFORM_QPA" = "yes" ]; then QMakeVar set QMAKE_LIBS_FONTCONFIG "$QT_LIBS_FONTCONFIG" CFG_LIBFREETYPE=system fi + + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/qpa/wayland "Wayland" $L_FLAGS $I_FLAGS $l_FLAGS; then + QT_CONFIG="$QT_CONFIG wayland" + fi + fi if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/mac/coreservices "CoreServices" $L_FLAGS $I_FLAGS $l_FLAGS $MAC_CONFIG_TEST_COMMANDLINE; then diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 26ccd44..57015e7 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -2,3 +2,7 @@ TEMPLATE = subdirs SUBDIRS += minimal +contains(QT_CONFIG, wayland) { + SUBDIRS += wayland +} + diff --git a/src/plugins/platforms/wayland/main.cpp b/src/plugins/platforms/wayland/main.cpp new file mode 100644 index 0000000..056cc64 --- /dev/null +++ b/src/plugins/platforms/wayland/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QPlatformIntegrationPlugin> +#include "qwaylandintegration.h" + +QT_BEGIN_NAMESPACE + +class QWaylandIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QWaylandIntegrationPlugin::keys() const +{ + QStringList list; + list << "Wayland"; + return list; +} + +QPlatformIntegration *QWaylandIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "wayland") + return new QWaylandIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(wayland, QWaylandIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp new file mode 100644 index 0000000..577dd28 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -0,0 +1,399 @@ +#include <QWindowSystemInterface> +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" +#include "qfontconfigdatabase.h" + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +#include <unistd.h> +#include <fcntl.h> + +extern "C" { +#include <xf86drm.h> +} + +struct wl_surface *QWaylandDisplay::createSurface() +{ + return wl_compositor_create_surface(mCompositor); +} + +struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); +} + +struct wl_visual *QWaylandDisplay::argbVisual() +{ + return wl_display_get_argb_visual(mDisplay); +} + +void QWaylandDisplay::drmHandleDevice(void *data, + struct wl_drm *drm, const char *device) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + qwd->mDeviceName = strdup(device); +} + +void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + qwd->mAuthenticated = true; +} + +const struct wl_drm_listener QWaylandDisplay::drmListener = { + QWaylandDisplay::drmHandleDevice, + QWaylandDisplay::drmHandleAuthenticated +}; + +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t width, int32_t height) +{ + Q_UNUSED(output); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + QWaylandScreen *screen; + + screen = new QWaylandScreen(); + screen->mGeometry = QRect(0, 0, width, height); + screen->mDepth = 32; + screen->mFormat = QImage::Format_ARGB32; + screen->mOutput = output; + + qwd->mScreens.append(screen); +} + +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + struct wl_surface *mPointerFocus; + struct wl_surface *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + + static void inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + static void inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); + static void inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state); + static void inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy); + static void inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, + uint32_t id) + : mDisplay(display) + , mInputDevice(wl_input_device_create(display, id)) + , mPointerFocus(NULL) + , mKeyboardFocus(NULL) + , mButtons(0) +{ + wl_input_device_add_listener(mInputDevice, + &inputDeviceListener, + this); + wl_input_device_set_user_data(mInputDevice, this); +} + +void QWaylandInputDevice::inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t surface_x, int32_t surface_y) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = + (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + + inputDevice->mSurfacePos = QPoint(surface_x, surface_y); + inputDevice->mGlobalPos = QPoint(x, y); + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = + (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + Qt::MouseButton qt_button; + + switch (button) { + case 272: + qt_button = Qt::LeftButton; + break; + case 273: + qt_button = Qt::RightButton; + break; + case 274: + qt_button = Qt::MidButton; + break; + default: + return; + } + + if (state) + inputDevice->mButtons |= qt_button; + else + inputDevice->mButtons &= ~qt_button; + + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state) +{ +} + +void QWaylandInputDevice::inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mPointerFocus) { + window = (QWaylandWindow *) + wl_surface_get_user_data(inputDevice->mPointerFocus); + QWindowSystemInterface::handleLeaveEvent(window->widget()); + inputDevice->mPointerFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + QWindowSystemInterface::handleEnterEvent(window->widget()); + inputDevice->mPointerFocus = surface; + } +} + +void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mKeyboardFocus) { + window = (QWaylandWindow *) + wl_surface_get_user_data(inputDevice->mKeyboardFocus); + inputDevice->mKeyboardFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + inputDevice->mKeyboardFocus = surface; + } +} + +const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { + QWaylandInputDevice::inputHandleMotion, + QWaylandInputDevice::inputHandleButton, + QWaylandInputDevice::inputHandleKey, + QWaylandInputDevice::inputHandlePointerFocus, + QWaylandInputDevice::inputHandleKeyboardFocus, +}; + +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, "drm") == 0) { + qwd->mDrm = wl_drm_create(display, id); + wl_drm_add_listener(qwd->mDrm, &drmListener, qwd); + } else if (strcmp(interface, "shm") == 0) { + qwd->mShm = wl_shm_create(display, id); + } 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); + } +} + +static void initial_roundtrip(void *data) +{ + bool *done = (bool *) data; + + *done = true; +} + +static const char socket_name[] = "\0wayland"; + +void QWaylandDisplay::eventDispatcher(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} + +int +QWaylandDisplay::sourceUpdate(uint32_t mask, 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); + + return 0; +} + +void QWaylandDisplay::flushRequests(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); +} + +QWaylandDisplay::QWaylandDisplay(void) + : mWriteNotifier(0) +{ + drm_magic_t magic; + bool done; + + mDisplay = wl_display_create(socket_name, sizeof socket_name); + if (mDisplay == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + return; + } + + wl_display_add_global_listener(mDisplay, + QWaylandDisplay::displayHandleGlobal, this); + + /* Process connection events. */ + wl_display_sync_callback(mDisplay, initial_roundtrip, &done); + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); + done = false; + while (!done) + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + + mFd = open(mDeviceName, O_RDWR); + if (mFd < 0) { + qWarning("drm open failed: %m\n"); + return; + } + + if (drmGetMagic(mFd, &magic)) { + qWarning("DRI2: failed to get drm magic"); + return; + } + + /* Wait for authenticated event */ + wl_drm_authenticate(mDrm, magic); + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); + while (!mAuthenticated) + 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(eventDispatcher())); + + mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); + connect(mWriteNotifier, + SIGNAL(activated(int)), this, SLOT(flushRequests())); + mWriteNotifier->setEnabled(false); +} + +QWaylandDisplay::~QWaylandDisplay(void) +{ + close(mFd); + wl_display_destroy(mDisplay); +} + +QWaylandIntegration::QWaylandIntegration() + : mFontDb(new QFontconfigDatabase()) + , mDisplay(new QWaylandDisplay()) +{ +} + +QList<QPlatformScreen *> +QWaylandIntegration::screens() const +{ + return mDisplay->screens(); +} + +QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) + : QPlatformWindow(window) + , mDisplay(display) +{ + mSurface = mDisplay->createSurface(); + wl_surface_set_user_data(mSurface, this); +} + +QWaylandWindow::~QWaylandWindow() +{ + /* mDisplay->destroySurface() */ +} + +QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QWaylandWindow(widget, mDisplay); +} + +QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QWaylandWindowSurface(widget, mDisplay); +} + +QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const +{ + return mFontDb; +} diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h new file mode 100644 index 0000000..d777175 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_WAYLAND_H +#define QPLATFORMINTEGRATION_WAYLAND_H + +#include <QSocketNotifier> +#include <QObject> +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +#include <wayland-client.h> + +QT_BEGIN_NAMESPACE + +class QWaylandInputDevice; + +class QWaylandDisplay : public QObject { + Q_OBJECT; + +public: + QWaylandDisplay(void); + ~QWaylandDisplay(void); + + QList<QPlatformScreen *> screens() const { return mScreens; } + struct wl_surface *createSurface(); + struct wl_buffer *createShmBuffer(int fd, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_visual *argbVisual(); + +public slots: + void eventDispatcher(void); + void flushRequests(void); + +private: + struct wl_display *mDisplay; + struct wl_compositor *mCompositor; + struct wl_drm *mDrm; + struct wl_shm *mShm; + char *mDeviceName; + int mFd; + bool mAuthenticated; + QList<QPlatformScreen *> mScreens; + QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; + QSocketNotifier *mWriteNotifier; + + static void displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data); + + static void drmHandleDevice(void *data, + struct wl_drm *drm, const char *device); + static void drmHandleAuthenticated(void *data, struct wl_drm *drm); + + static void outputHandleGeometry(void *data, + struct wl_output *output, + int32_t width, int32_t height); + + static int sourceUpdate(uint32_t mask, void *data); + + static const struct wl_drm_listener drmListener; + static const struct wl_output_listener outputListener; +}; + +class QWaylandScreen : public QPlatformScreen +{ +public: + QWaylandScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + struct wl_output *mOutput; +}; + + +class QWaylandWindow : public QPlatformWindow +{ +public: + QWaylandWindow(QWidget *window, QWaylandDisplay *display); + ~QWaylandWindow(); + struct wl_surface *surface() { return mSurface; } + +private: + struct wl_surface *mSurface; + QWaylandDisplay *mDisplay; +}; + +class QWaylandIntegration : public QPlatformIntegration +{ +public: + QWaylandIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const; + + QPlatformFontDatabase *fontDatabase() const; + +private: + QPlatformFontDatabase *mFontDb; + QWaylandDisplay *mDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp new file mode 100644 index 0000000..f0f5018 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +QWaylandWindowSurface::QWaylandWindowSurface(QWidget *window, + QWaylandDisplay *display) + : QWindowSurface(window) + , mImage(0) + , mDisplay(display) +{ + //qDebug() << "QWaylandWindowSurface::QWaylandWindowSurface:" << (long)this; +} + +QWaylandWindowSurface::~QWaylandWindowSurface() +{ +} + +QPaintDevice *QWaylandWindowSurface::paintDevice() +{ + //qDebug() << "QWaylandWindowSurface::paintDevice"; + return mImage; +} + +void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QVector<QRect> rects = region.rects(); + const QRect *r; + int i; + + for (i = 0; i < rects.size(); i++) { + r = &rects.at(i); + wl_surface_damage(ww->surface(), + r->x(), r->y(), r->width(), r->height()); + } +} + +void QWaylandWindowSurface::resize(const QSize &size) +{ + //qDebug() << "QWaylandWindowSurface::setGeometry:" << (long)this << rect; + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mImage != NULL && mImage->size() == size) + return; + + if (mImage != NULL) { + delete mImage; + munmap(mData, mSize); + } + + mStride = size.width() * 4; + mSize = mStride * size.height(); + char filename[] = "/tmp/wayland-shm-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) + qWarning("open %s failed: %s", filename, strerror(errno)); + if (ftruncate(fd, mSize) < 0) + qWarning("ftruncate failed: %s", strerror(errno)); + mData = (uchar *) + mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (mData == (uchar *) MAP_FAILED) + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + + mImage = new QImage(mData, size.width(), size.height(), mStride, format); + + struct wl_buffer *buffer = + mDisplay->createShmBuffer(fd, size.width(), size.height(), + mStride, mDisplay->argbVisual()); + wl_surface_attach(ww->surface(), buffer); + wl_surface_map(ww->surface(), 0, 0, size.width(), size.height()); + wl_buffer_destroy(buffer); + close(fd); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h new file mode 100644 index 0000000..1054c51 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_WAYLAND_H +#define QWINDOWSURFACE_WAYLAND_H + +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QWaylandWindowSurface : public QWindowSurface +{ +public: + QWaylandWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QImage *mImage; + uchar *mData; + int mSize; + int mStride; + QWaylandDisplay *mDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro new file mode 100644 index 0000000..62ff4df --- /dev/null +++ b/src/plugins/platforms/wayland/wayland.pro @@ -0,0 +1,19 @@ +TARGET = qwayland +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qwaylandintegration.cpp \ + qwaylandwindowsurface.cpp + +HEADERS = qwaylandintegration.h \ + qwaylandwindowsurface.h + +INCLUDEPATH += /usr/include/libdrm +LIBS += -lwayland-client -ldrm + +include (../fontdatabases/fontconfig/fontconfig.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target |