summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2010-10-08 20:02:01 (GMT)
committerJørgen Lind <jorgen.lind@nokia.com>2011-01-25 17:53:17 (GMT)
commita052aafacb81482f694c4c41d166439c30d12eb7 (patch)
treecf005a1cde12f37af99870dfa1ec8a2a3fd1fab3
parent9598483764d0c95751abcfb384422916b64fd283 (diff)
downloadQt-a052aafacb81482f694c4c41d166439c30d12eb7.zip
Qt-a052aafacb81482f694c4c41d166439c30d12eb7.tar.gz
Qt-a052aafacb81482f694c4c41d166439c30d12eb7.tar.bz2
Cursors, keyboard support, move/resize
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.cpp162
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.h58
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.cpp177
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.h18
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindowsurface.cpp79
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindowsurface.h17
-rw-r--r--src/plugins/platforms/wayland/wayland.pro2
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 &region, const QPoint &offset)
@@ -90,10 +125,12 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &region, 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)