diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-10-08 20:02:01 (GMT) |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2011-01-25 17:53:17 (GMT) |
commit | a052aafacb81482f694c4c41d166439c30d12eb7 (patch) | |
tree | cf005a1cde12f37af99870dfa1ec8a2a3fd1fab3 /src/plugins/platforms | |
parent | 9598483764d0c95751abcfb384422916b64fd283 (diff) | |
download | Qt-a052aafacb81482f694c4c41d166439c30d12eb7.zip Qt-a052aafacb81482f694c4c41d166439c30d12eb7.tar.gz Qt-a052aafacb81482f694c4c41d166439c30d12eb7.tar.bz2 |
Cursors, keyboard support, move/resize
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 162 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandinputdevice.h | 58 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandintegration.cpp | 177 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandintegration.h | 18 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindowsurface.cpp | 79 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindowsurface.h | 17 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/wayland.pro | 2 |
7 files changed, 426 insertions, 87 deletions
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 5bddf2f..fd7a649 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -1,49 +1,14 @@ #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> - -class QWaylandInputDevice { -public: - QWaylandInputDevice(struct wl_display *display, uint32_t id); - -private: - struct wl_display *mDisplay; - struct wl_input_device *mInputDevice; - QWaylandWindow *mPointerFocus; - QWaylandWindow *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); -}; +#include <X11/extensions/XKBcommon.h> +#include <X11/keysym.h> QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, uint32_t id) @@ -53,10 +18,20 @@ QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, , mKeyboardFocus(NULL) , mButtons(0) { + struct xkb_rule_names names; + wl_input_device_add_listener(mInputDevice, &inputDeviceListener, this); wl_input_device_set_user_data(mInputDevice, this); + + names.rules = "evdev"; + names.model = "pc105"; + names.layout = "us"; + names.variant = ""; + names.options = ""; + + mXkb = xkb_compile_keymap_from_rules(&names); } void QWaylandInputDevice::inputHandleMotion(void *data, @@ -71,6 +46,7 @@ void QWaylandInputDevice::inputHandleMotion(void *data, inputDevice->mSurfacePos = QPoint(surface_x, surface_y); inputDevice->mGlobalPos = QPoint(x, y); + inputDevice->mTime = time; QWindowSystemInterface::handleMouseEvent(window->widget(), time, inputDevice->mSurfacePos, @@ -95,7 +71,7 @@ void QWaylandInputDevice::inputHandleButton(void *data, qt_button = Qt::RightButton; break; case 274: - qt_button = Qt::MidButton; + qt_button = Qt::MiddleButton; break; default: return; @@ -106,6 +82,7 @@ void QWaylandInputDevice::inputHandleButton(void *data, else inputDevice->mButtons &= ~qt_button; + inputDevice->mTime = time; QWindowSystemInterface::handleMouseEvent(window->widget(), time, inputDevice->mSurfacePos, @@ -113,6 +90,72 @@ void QWaylandInputDevice::inputHandleButton(void *data, inputDevice->mButtons); } +static Qt::KeyboardModifiers translateModifiers(int s) +{ + const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK; + const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK; + + Qt::KeyboardModifiers ret = 0; + if (s & XKB_COMMON_SHIFT_MASK) + ret |= Qt::ShiftModifier; + if (s & XKB_COMMON_CONTROL_MASK) + ret |= Qt::ControlModifier; + if (s & qt_alt_mask) + ret |= Qt::AltModifier; + if (s & qt_meta_mask) + ret |= Qt::MetaModifier; + + return ret; +} + +static uint32_t translateKey(uint32_t sym, char *string, size_t size) +{ + string[0] = '\0'; + + switch (sym) { + case XK_Escape: return Qt::Key_Escape; + case XK_Tab: return Qt::Key_Tab; + case XK_ISO_Left_Tab: return Qt::Key_Backtab; + case XK_BackSpace: return Qt::Key_Backspace; + case XK_Return: return Qt::Key_Return; + case XK_Insert: return Qt::Key_Insert; + case XK_Delete: return Qt::Key_Delete; + case XK_Clear: return Qt::Key_Delete; + case XK_Pause: return Qt::Key_Pause; + case XK_Print: return Qt::Key_Print; + + case XK_Home: return Qt::Key_Home; + case XK_End: return Qt::Key_End; + case XK_Left: return Qt::Key_Left; + case XK_Up: return Qt::Key_Up; + case XK_Right: return Qt::Key_Right; + case XK_Down: return Qt::Key_Down; + case XK_Prior: return Qt::Key_PageUp; + case XK_Next: return Qt::Key_PageDown; + + case XK_Shift_L: return Qt::Key_Shift; + case XK_Shift_R: return Qt::Key_Shift; + case XK_Shift_Lock: return Qt::Key_Shift; + case XK_Control_L: return Qt::Key_Control; + case XK_Control_R: return Qt::Key_Control; + case XK_Meta_L: return Qt::Key_Meta; + case XK_Meta_R: return Qt::Key_Meta; + case XK_Alt_L: return Qt::Key_Alt; + case XK_Alt_R: return Qt::Key_Alt; + case XK_Caps_Lock: return Qt::Key_CapsLock; + case XK_Num_Lock: return Qt::Key_NumLock; + case XK_Scroll_Lock: return Qt::Key_ScrollLock; + case XK_Super_L: return Qt::Key_Super_L; + case XK_Super_R: return Qt::Key_Super_R; + case XK_Menu: return Qt::Key_Menu; + + default: + string[0] = sym; + string[1] = '\0'; + return toupper(sym); + } +} + void QWaylandInputDevice::inputHandleKey(void *data, struct wl_input_device *input_device, uint32_t time, uint32_t key, uint32_t state) @@ -120,6 +163,39 @@ void QWaylandInputDevice::inputHandleKey(void *data, Q_UNUSED(input_device); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window = inputDevice->mKeyboardFocus; + uint32_t code, sym, level; + Qt::KeyboardModifiers modifiers; + QEvent::Type type; + char s[2]; + + code = key + inputDevice->mXkb->min_key_code; + + level = 0; + if (inputDevice->mModifiers & Qt::ShiftModifier && + XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1) + level = 1; + + sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0); + + modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]); + + if (state) { + inputDevice->mModifiers |= modifiers; + type = QEvent::KeyPress; + } else { + inputDevice->mModifiers &= ~modifiers; + type = QEvent::KeyRelease; + } + + sym = translateKey(sym, s, sizeof s); + + qWarning("keycode %d, sym %d, string %d, modifiers 0x%x", + code, sym, s[0], (int) inputDevice->mModifiers); + + QWindowSystemInterface::handleKeyEvent(window->widget(), + time, type, sym, + inputDevice->mModifiers, + QString::fromLatin1(s)); } void QWaylandInputDevice::inputHandlePointerFocus(void *data, @@ -131,8 +207,6 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window; - qWarning("pointer focus %p", surface); - if (inputDevice->mPointerFocus) { window = inputDevice->mPointerFocus; QWindowSystemInterface::handleLeaveEvent(window->widget()); @@ -144,6 +218,8 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, QWindowSystemInterface::handleEnterEvent(window->widget()); inputDevice->mPointerFocus = window; } + + inputDevice->mTime = time; } void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, @@ -175,9 +251,7 @@ const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = QWaylandInputDevice::inputHandleKeyboardFocus, }; - -QWaylandInputDevice * -waylandInputDeviceCreate(struct wl_display *display, uint32_t id) +void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) { - return new QWaylandInputDevice(display, id); + wl_input_device_attach(mInputDevice, mTime, buffer->mBuffer, x, y); } diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h new file mode 100644 index 0000000..749ef70 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -0,0 +1,58 @@ +#ifndef QWAYLANDINPUTDEVICE_H +#define QWAYLANDINPUTDEVICE_H + +#include <QSocketNotifier> +#include <QObject> +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +#include <wayland-client.h> +#include "qwaylandwindowsurface.h" + +QT_BEGIN_NAMESPACE + +class QWaylandWindow; + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + void attach(QWaylandBuffer *buffer, int x, int y); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + QWaylandWindow *mPointerFocus; + QWaylandWindow *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + struct xkb_desc *mXkb; + Qt::KeyboardModifiers mModifiers; + uint32_t mTime; + + 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); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 21e7be7..a728f78 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,4 +1,6 @@ +#include <QImageReader> #include <QWindowSystemInterface> +#include <QPlatformCursor> #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" #include "qfontconfigdatabase.h" @@ -13,6 +15,150 @@ extern "C" { #include <xf86drm.h> } +class QWaylandCursor : QPlatformCursor { +public: + QWaylandCursor(QWaylandDisplay *display, + QPlatformScreen *screen) + : QPlatformCursor(screen) + , mDisplay(display) { } + + void changeCursor(QCursor *cursor, QWidget *widget); + QWaylandBuffer *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 QWaylandBuffer(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); @@ -53,6 +199,21 @@ const struct wl_drm_listener QWaylandDisplay::drmListener = { QWaylandDisplay::drmHandleAuthenticated }; +void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); + + ww->configure(time, edges, x, y, width, height); +} + +const struct wl_shell_listener QWaylandDisplay::shellListener = { + QWaylandDisplay::shellHandleConfigure, +}; + void QWaylandDisplay::outputHandleGeometry(void *data, struct wl_output *output, int32_t width, int32_t height) @@ -67,6 +228,8 @@ void QWaylandDisplay::outputHandleGeometry(void *data, screen->mFormat = QImage::Format_ARGB32_Premultiplied; screen->mOutput = output; + new QWaylandCursor(qwd, screen); + qwd->mScreens.append(screen); } @@ -89,12 +252,15 @@ void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, 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 = - waylandInputDeviceCreate(display, id); + new QWaylandInputDevice(display, id); qwd->mInputDevices.append(inputDevice); } } @@ -242,6 +408,15 @@ void QWaylandWindow::setVisible(bool visible) } } +void QWaylandWindow::configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + QRect geometry = QRect(x, y, width, height); + + QWindowSystemInterface::handleGeometryChange(widget(), geometry); +} + QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index ed9ca3b..9f0b371 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -48,13 +48,11 @@ #include <QtGui/QPlatformScreen> #include <wayland-client.h> +#include "qwaylandinputdevice.h" QT_BEGIN_NAMESPACE -class QWaylandInputDevice; - -QWaylandInputDevice * -waylandInputDeviceCreate(struct wl_display *display, uint32_t id); +class QWaylandBuffer; class QWaylandDisplay : public QObject { Q_OBJECT; @@ -70,6 +68,8 @@ public: struct wl_visual *visual); struct wl_visual *argbVisual(); + void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + public slots: void eventDispatcher(void); void flushRequests(void); @@ -79,6 +79,7 @@ private: struct wl_compositor *mCompositor; struct wl_drm *mDrm; struct wl_shm *mShm; + struct wl_shell *mShell; char *mDeviceName; int mFd; bool mAuthenticated; @@ -100,10 +101,17 @@ private: struct wl_output *output, int32_t width, int32_t height); + static void shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t x, int32_t y, + 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; + static const struct wl_shell_listener shellListener; }; class QWaylandScreen : public QPlatformScreen @@ -132,6 +140,8 @@ public: struct wl_surface *surface() { return mSurface; } void setVisible(bool visible); + void configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, int32_t width, int32_t height); WId winId() const; private: diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 41f72d0..a988d63 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -52,10 +52,46 @@ QT_BEGIN_NAMESPACE +QWaylandBuffer::QWaylandBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) +{ + int stride = size.width() * 4; + int alloc = stride * 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, alloc) < 0) { + qWarning("ftruncate failed: %s", strerror(errno)); + close(fd); + return; + } + uchar *data = (uchar *) + mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (data == (uchar *) MAP_FAILED) { + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + close(fd); + return; + } + + mImage = QImage(data, size.width(), size.height(), stride, format); + mBuffer = display->createShmBuffer(fd, size.width(), size.height(), + stride, display->argbVisual()); + close(fd); +} + +QWaylandBuffer::~QWaylandBuffer(void) +{ + munmap((void *) mImage.constBits(), mImage.byteCount()); + wl_buffer_destroy(mBuffer); +} + QWaylandWindowSurface::QWaylandWindowSurface(QWidget *window, QWaylandDisplay *display) : QWindowSurface(window) - , mImage(0) + , mBuffer(0) , mDisplay(display) { //qDebug() << "QWaylandWindowSurface::QWaylandWindowSurface:" << (long)this; @@ -67,8 +103,7 @@ QWaylandWindowSurface::~QWaylandWindowSurface() QPaintDevice *QWaylandWindowSurface::paintDevice() { - //qDebug() << "QWaylandWindowSurface::paintDevice"; - return mImage; + return &mBuffer->mImage; } void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) @@ -90,10 +125,12 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const void QWaylandWindowSurface::attach(void) { QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QRect geometry = window()->geometry(); - if (ww->surface()) { - wl_surface_attach(ww->surface(), mBuffer); - wl_surface_map(ww->surface(), 0, 0, mImage->width(), mImage->height()); + if (ww->surface() && mBuffer) { + wl_surface_attach(ww->surface(), mBuffer->mBuffer); + wl_surface_map(ww->surface(), geometry.x(), geometry.y(), + mBuffer->mImage.width(), mBuffer->mImage.height()); } } @@ -103,35 +140,13 @@ void QWaylandWindowSurface::resize(const QSize &size) QWindowSurface::resize(size); QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - if (mImage != NULL && mImage->size() == size) + if (mBuffer != NULL && mBuffer->mImage.size() == size) return; - if (mImage != NULL) { - delete mImage; - munmap(mData, mSize); - wl_buffer_destroy(mBuffer); - } - - 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); + if (mBuffer != NULL) + delete mBuffer; - mBuffer = mDisplay->createShmBuffer(fd, size.width(), size.height(), - mStride, mDisplay->argbVisual()); - close(fd); + mBuffer = new QWaylandBuffer(mDisplay, size, format); attach(); } diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 1da6ab4..711b0c1 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -48,6 +48,17 @@ QT_BEGIN_NAMESPACE +class QWaylandDisplay; + +class QWaylandBuffer { +public: + QWaylandBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandBuffer(); + QImage mImage; + struct wl_buffer *mBuffer; +}; + class QWaylandWindowSurface : public QWindowSurface { public: @@ -60,12 +71,8 @@ public: void attach(void); private: - QImage *mImage; - uchar *mData; - int mSize; - int mStride; + QWaylandBuffer *mBuffer; QWaylandDisplay *mDisplay; - struct wl_buffer *mBuffer; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index c1f5bae..f5751e2 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -12,7 +12,7 @@ HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h INCLUDEPATH += /usr/include/libdrm -LIBS += -lwayland-client -ldrm +LIBS += -lwayland-client -ldrm -lxkbcommon include (../fontdatabases/fontconfig/fontconfig.pri) |