diff options
Diffstat (limited to 'src/plugins/platforms/wayland/qwaylandintegration.cpp')
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandintegration.cpp | 482 |
1 files changed, 9 insertions, 473 deletions
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 61f696c..a6fdc2e 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,419 +1,17 @@ -#include "qfontconfigdatabase.h" - -#include <QImageReader> -#include <QWindowSystemInterface> -#include <QPlatformCursor> -#include <QPaintEngine> - -#include <QtGui/QPlatformWindowFormat> - -#include <QtGui/private/qpixmap_raster_p.h> -#include <QtGui/QPlatformWindow> - #include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" - -#include <unistd.h> -#include <fcntl.h> - -extern "C" { -#include <xf86drm.h> -} - -class QWaylandCursor : QPlatformCursor { -public: - QWaylandCursor(QWaylandDisplay *display, - QPlatformScreen *screen) - : QPlatformCursor(screen) - , mBuffer(0), mDisplay(display) { } - - void changeCursor(QCursor *cursor, QWidget *widget); - QWaylandShmBuffer *mBuffer; - QWaylandDisplay *mDisplay; -}; - -#define DATADIR "/usr/share" - -static const struct pointer_image { - const char *filename; - int hotspot_x, hotspot_y; -} pointer_images[] = { - /* FIXME: Half of these are wrong... */ - /* Qt::ArrowCursor */ - { DATADIR "/wayland/left_ptr.png", 10, 5 }, - /* Qt::UpArrowCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::CrossCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::WaitCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::IBeamCursor */ - { DATADIR "/wayland/xterm.png", 15, 15 }, - /* Qt::SizeVerCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::SizeHorCursor */ - { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, - /* Qt::SizeBDiagCursor */ - { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, - /* Qt::SizeFDiagCursor */ - { DATADIR "/wayland/bottom_side.png", 16, 20 }, - /* Qt::SizeAllCursor */ - { DATADIR "/wayland/left_side.png", 10, 20 }, - /* Qt::BlankCursor */ - { DATADIR "/wayland/right_side.png", 30, 19 }, - /* Qt::SplitVCursor */ - { DATADIR "/wayland/sb_v_double_arrow.png", 15, 15 }, - /* Qt::SplitHCursor */ - { DATADIR "/wayland/sb_h_double_arrow.png", 15, 15 }, - /* Qt::PointingHandCursor */ - { DATADIR "/wayland/hand2.png", 14, 8 }, - /* Qt::ForbiddenCursor */ - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - /* Qt::WhatsThisCursor */ - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - /* Qt::BusyCursor */ - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - /* Qt::OpenHandCursor */ - { DATADIR "/wayland/hand1.png", 18, 11 }, - /* Qt::ClosedHandCursor */ - { DATADIR "/wayland/grabbing.png", 20, 17 }, - /* Qt::DragCopyCursor */ - { DATADIR "/wayland/dnd-copy.png", 13, 13 }, - /* Qt::DragMoveCursor */ - { DATADIR "/wayland/dnd-move.png", 13, 13 }, - /* Qt::DragLinkCursor */ - { DATADIR "/wayland/dnd-link.png", 13, 13 }, -}; - -void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) -{ - const struct pointer_image *p; - - if (widget == NULL) - return; - - p = NULL; - - switch (cursor->shape()) { - case Qt::ArrowCursor: - p = &pointer_images[cursor->shape()]; - break; - case Qt::UpArrowCursor: - case Qt::CrossCursor: - case Qt::WaitCursor: - break; - case Qt::IBeamCursor: - p = &pointer_images[cursor->shape()]; - break; - case Qt::SizeVerCursor: /* 5 */ - case Qt::SizeHorCursor: - case Qt::SizeBDiagCursor: - case Qt::SizeFDiagCursor: - case Qt::SizeAllCursor: - case Qt::BlankCursor: /* 10 */ - break; - case Qt::SplitVCursor: - case Qt::SplitHCursor: - case Qt::PointingHandCursor: - p = &pointer_images[cursor->shape()]; - break; - case Qt::ForbiddenCursor: - case Qt::WhatsThisCursor: /* 15 */ - case Qt::BusyCursor: - break; - case Qt::OpenHandCursor: - case Qt::ClosedHandCursor: - case Qt::DragCopyCursor: - case Qt::DragMoveCursor: /* 20 */ - case Qt::DragLinkCursor: - p = &pointer_images[cursor->shape()]; - break; - - default: - case Qt::BitmapCursor: - break; - } - - if (!p) { - p = &pointer_images[0]; - qWarning("unhandled cursor %d", cursor->shape()); - } - - QImageReader reader(p->filename); - - if (mBuffer == NULL || mBuffer->mImage.size() != reader.size()) { - if (mBuffer) - delete mBuffer; - - mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(), - QImage::Format_ARGB32); - } - - reader.read(&mBuffer->mImage); - - mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); -} - -void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y) -{ - /* Qt doesn't tell us which input device we should set the cursor - * for, so set it for all devices. */ - for (int i = 0; i < mInputDevices.count(); i++) { - QWaylandInputDevice *inputDevice = mInputDevices.at(i); - inputDevice->attach(buffer, x, y); - } -} - -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_buffer *QWaylandDisplay::createDrmBuffer(int name, - int width, int height, - uint32_t stride, - struct wl_visual *visual) -{ - return wl_drm_create_buffer(mDrm, name, width, height, stride, visual); -} - -struct wl_visual *QWaylandDisplay::rgbVisual() -{ - return wl_display_get_rgb_visual(mDisplay); -} - -struct wl_visual *QWaylandDisplay::argbVisual() -{ - return wl_display_get_argb_visual(mDisplay); -} - -struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() -{ - return wl_display_get_premultiplied_argb_visual(mDisplay); -} - -void QWaylandDisplay::drmHandleDevice(void *data, - struct wl_drm *drm, const char *device) -{ - Q_UNUSED(drm); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - drm_magic_t magic; - - qwd->mDeviceName = strdup(device); - - qwd->mFd = open(qwd->mDeviceName, O_RDWR); - if (qwd->mFd < 0) { - qWarning("drm open failed: %m"); - return; - } - - if (drmGetMagic(qwd->mFd, &magic)) { - qWarning("DRI2: failed to get drm magic"); - return; - } - - wl_drm_authenticate(qwd->mDrm, magic); -} - -void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) -{ - Q_UNUSED(drm); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - EGLint major, minor; - const char *extensions; - - qwd->mEglDisplay = eglGetDRMDisplayMESA(qwd->mFd); - if (qwd->mEglDisplay == NULL) { - qWarning("failed to create display"); - return; - } - - if (!eglInitialize(qwd->mEglDisplay, &major, &minor)) { - qWarning("failed to initialize display"); - qwd->mEglDisplay = NULL; - return; - } - - extensions = eglQueryString(qwd->mEglDisplay, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) { - qWarning("EGL_KHR_surfaceless_opengles2 not available"); - eglTerminate(qwd->mEglDisplay); - qwd->mEglDisplay = NULL; - return; - } -} - -const struct wl_drm_listener QWaylandDisplay::drmListener = { - QWaylandDisplay::drmHandleDevice, - QWaylandDisplay::drmHandleAuthenticated -}; - -void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, - int32_t width, int32_t height) -{ - Q_UNUSED(data); - Q_UNUSED(shell); - Q_UNUSED(time); - Q_UNUSED(edges); - QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); - - ww->configure(time, edges, 0, 0, width, height); -} -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) -{ - Q_UNUSED(output); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - QWaylandScreen *screen; - - screen = new QWaylandScreen(); - screen->mGeometry = QRect(x, y, width, height); - screen->mDepth = 32; - screen->mFormat = QImage::Format_ARGB32_Premultiplied; - screen->mOutput = output; - - new QWaylandCursor(qwd, screen); - - qwd->mScreens.append(screen); -} - -const struct wl_output_listener QWaylandDisplay::outputListener = { - QWaylandDisplay::outputHandleGeometry -}; - -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, "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); - } -} - -static void roundtripCallback(void *data) -{ - bool *done = (bool *) data; - - *done = true; -} - -static void forceRoundtrip(struct wl_display *display) -{ - bool done; - - wl_display_sync_callback(display, roundtripCallback, &done); - wl_display_iterate(display, WL_DISPLAY_WRITABLE); - done = false; - while (!done) - wl_display_iterate(display, WL_DISPLAY_READABLE); -} - -static const char *socket_name = NULL; - -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) -{ - mDisplay = wl_display_connect(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_iterate(mDisplay, WL_DISPLAY_READABLE); - if (!mShm || !mDeviceName) - forceRoundtrip(mDisplay); - - /* Force a roundtrip to finish the drm authentication so we - * initialize EGL before proceeding */ - forceRoundtrip(mDisplay); - if (mEglDisplay == NULL) - qDebug("EGL not available"); - else - qDebug("EGL initialized"); +#include "qwaylanddisplay.h" +#include "qwaylandwindowsurface.h" +#include "qwaylandwindow.h" - int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); - mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); - connect(mReadNotifier, - SIGNAL(activated(int)), this, SLOT(eventDispatcher())); +#include "qfontconfigdatabase.h" - mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); - connect(mWriteNotifier, - SIGNAL(activated(int)), this, SLOT(flushRequests())); - mWriteNotifier->setEnabled(false); -} +#include <QtGui/QWindowSystemInterface> +#include <QtGui/QPlatformCursor> +#include <QtGui/QPlatformWindowFormat> -QWaylandDisplay::~QWaylandDisplay(void) -{ - close(mFd); - wl_display_destroy(mDisplay); -} +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtOpenGL/private/qpixmapdata_gl_p.h> QWaylandIntegration::QWaylandIntegration(bool useOpenGL) : mFontDb(new QFontconfigDatabase()) @@ -435,69 +33,7 @@ QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) return new QRasterPixmapData(type); } -QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) - : QPlatformWindow(window) - , mSurface(0) - , mDisplay(display) - , mGLContext(0) - , mBuffer(0) -{ - static WId id = 1; - - mWindowId = id++; -} - -QWaylandWindow::~QWaylandWindow() -{ - if (mGLContext) - delete mGLContext; -} -WId QWaylandWindow::winId() const -{ - return mWindowId; -} - -void QWaylandWindow::setParent(const QPlatformWindow *parent) -{ - QWaylandWindow *wParent = (QWaylandWindow *)parent; - - mParentWindow = wParent; -} - -void QWaylandWindow::setVisible(bool visible) -{ - if (visible) { - mSurface = mDisplay->createSurface(); - wl_surface_set_user_data(mSurface, this); - attach(mBuffer); - } else { - wl_surface_destroy(mSurface); - mSurface = NULL; - } -} - -void QWaylandWindow::attach(QWaylandBuffer *buffer) -{ - QRect geometry = widget()->geometry(); - - mBuffer = buffer; - if (mSurface) { - wl_surface_attach(mSurface, mBuffer->mBuffer,geometry.x(),geometry.y()); - wl_surface_map_toplevel(mSurface); - } -} - -void QWaylandWindow::configure(uint32_t time, uint32_t edges, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - Q_UNUSED(time); - Q_UNUSED(edges); - QRect geometry = QRect(x, y, width, height); - - QWindowSystemInterface::handleGeometryChange(widget(), geometry); -} QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { |