Merge remote-tracking branch 'origin/5.4' into dev

Conflicts:
	src/compositor/wayland_wrapper/qwlcompositor.cpp

Change-Id: Ica26e33eb2b77ed5be0e84e8f4256d2e85abfaf5
This commit is contained in:
Frederik Gladhorn 2014-09-19 18:04:22 +02:00
commit 03c1b4d4ca
39 changed files with 419 additions and 228 deletions

View File

@ -62,7 +62,10 @@ public:
virtual void initialize(QWaylandDisplay *display) = 0;
virtual bool isValid() const { return true; }
virtual bool supportsThreadedOpenGL() const { return false; }
virtual bool supportsWindowDecoration() const { return false; }
virtual QWaylandWindow *createEglWindow(QWindow *window) = 0;
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const = 0;

View File

@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
QWaylandHardwareIntegration::QWaylandHardwareIntegration(struct ::wl_registry *registry, int id)
: qt_hardware_integration(registry, id)
: qt_hardware_integration(registry, id, 1)
{
}

View File

@ -77,6 +77,11 @@ QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
return m_selectionOffer.data();
}
void QWaylandDataDevice::invalidateSelectionOffer()
{
m_selectionOffer.reset();
}
QWaylandDataSource *QWaylandDataDevice::selectionSource() const
{
return m_selectionSource.data();

View File

@ -65,6 +65,7 @@ public:
~QWaylandDataDevice();
QWaylandDataOffer *selectionOffer() const;
void invalidateSelectionOffer();
QWaylandDataSource *selectionSource() const;
void setSelectionSource(QWaylandDataSource *source);

View File

@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
: wl_data_device_manager(display->wl_registry(), id)
: wl_data_device_manager(display->wl_registry(), id, 1)
, m_display(display)
{
// Create transfer devices for all input devices.

View File

@ -94,30 +94,18 @@ QWaylandMimeData::~QWaylandMimeData()
void QWaylandMimeData::appendFormat(const QString &mimeType)
{
if (m_types.contains(mimeType))
close(m_types.take(mimeType)); // Unconsumed data
m_types << mimeType;
m_data.remove(mimeType); // Clear previous contents
int pipefd[2];
if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) {
qWarning("QWaylandMimeData: pipe2() failed");
return;
}
m_dataOffer->receive(mimeType, pipefd[1]);
m_display->forceRoundTrip();
close(pipefd[1]);
m_types.insert(mimeType, pipefd[0]);
}
bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
{
return m_types.contains(mimeType) || m_data.contains(mimeType);
return m_types.contains(mimeType);
}
QStringList QWaylandMimeData::formats_sys() const
{
return m_types.keys() << m_data.keys();
return m_types;
}
QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
@ -130,14 +118,24 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
if (!m_types.contains(mimeType))
return QVariant();
int pipefd[2];
if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) {
qWarning("QWaylandMimeData: pipe2() failed");
return QVariant();
}
m_dataOffer->receive(mimeType, pipefd[1]);
m_display->flushRequests();
close(pipefd[1]);
QByteArray content;
int fd = m_types.take(mimeType);
if (readData(fd, content) != 0) {
if (readData(pipefd[0], content) != 0) {
qWarning("QWaylandDataOffer: error reading data for mimeType %s", qPrintable(mimeType));
content = QByteArray();
}
close(fd);
close(pipefd[0]);
m_data.insert(mimeType, content);
return content;
}

View File

@ -87,7 +87,7 @@ private:
mutable QWaylandDataOffer *m_dataOffer;
QWaylandDisplay *m_display;
mutable QHash<QString, int> m_types;
mutable QStringList m_types;
mutable QHash<QString, QByteArray> m_data;
};

View File

@ -186,7 +186,7 @@ void QWaylandDecoration::paint(QPaintDevice *device)
// Title bar
QPoint gradCenter(top.center()+ QPoint(30, 60));
QLinearGradient grad(top.topLeft(), top.bottomLeft());
QColor base(backgroundColor());
QColor base(m_backgroundColor);
grad.setColorAt(0, base.lighter(100));
grad.setColorAt(1, base.darker(180));
QPainterPath roundedRect;
@ -335,6 +335,28 @@ bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPo
return true;
}
bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods)
{
Q_UNUSED(inputDevice);
Q_UNUSED(global);
Q_UNUSED(mods);
bool handled = state == Qt::TouchPointPressed;
if (handled) {
if (closeButtonRect().contains(local))
QWindowSystemInterface::handleCloseEvent(m_window);
else if (maximizeButtonRect().contains(local))
m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized);
else if (minimizeButtonRect().contains(local))
m_window->setWindowState(Qt::WindowMinimized);
else if (local.y() <= m_margins.top())
m_wayland_window->shellSurface()->move(inputDevice);
else
handled = false;
}
return handled;
}
bool QWaylandDecoration::inMouseButtonPressedState() const
{
return m_mouseButtons & Qt::NoButton;
@ -446,14 +468,4 @@ QRectF QWaylandDecoration::minimizeButtonRect() const
(m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
}
void QWaylandDecoration::setForegroundColor(const QColor &c)
{
m_foregroundColor = c;
}
void QWaylandDecoration::setBackgroundColor(const QColor &c)
{
m_backgroundColor = c;
}
QT_END_NAMESPACE

View File

@ -75,6 +75,7 @@ public:
bool isDirty() const;
bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods);
bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods);
bool inMouseButtonPressedState() const;
void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons);
@ -84,12 +85,6 @@ public:
QWaylandWindow *waylandWindow() const;
const QImage &contentImage();
void setForegroundColor(const QColor &c);
inline QColor foregroundColor() const;
void setBackgroundColor(const QColor &c);
inline QColor backgroundColor() const;
protected:
void paint(QPaintDevice *device);
@ -140,16 +135,6 @@ inline QWaylandWindow *QWaylandDecoration::waylandWindow() const
return m_wayland_window;
}
inline QColor QWaylandDecoration::foregroundColor() const
{
return m_foregroundColor;
}
inline QColor QWaylandDecoration::backgroundColor() const
{
return m_backgroundColor;
}
QT_END_NAMESPACE
#endif // QWAYLANDDECORATION_H

View File

@ -56,6 +56,7 @@
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandshellintegration_p.h"
#include "qwaylandclientbufferintegration_p.h"
#include "qwaylandextendedoutput_p.h"
#include "qwaylandextendedsurface_p.h"
@ -126,8 +127,6 @@ void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *devic
mLastKeyboardFocusInputDevice = device;
}
static QWaylandDisplay *display = 0;
QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
: mWaylandIntegration(waylandIntegration)
, mLastKeyboardFocusInputDevice(0)
@ -140,7 +139,6 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
, mTextInputManager(0)
, mHardwareIntegration(0)
{
display = this;
qRegisterMetaType<uint32_t>("uint32_t");
mEventThreadObject = new QWaylandEventThread(0);
@ -169,6 +167,8 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
QWaylandDisplay::~QWaylandDisplay(void)
{
qDeleteAll(mScreens);
mScreens.clear();
delete mDndSelectionHandler.take();
mEventThread->quit();
mEventThread->wait();
@ -177,20 +177,17 @@ QWaylandDisplay::~QWaylandDisplay(void)
void QWaylandDisplay::flushRequests()
{
if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) == -1 && (errno == EPIPE || errno == ECONNRESET)) {
qWarning("The Wayland connection broke. Did the Wayland compositor die?");
::exit(1);
}
if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0)
mEventThreadObject->checkErrorAndExit();
wl_display_flush(mDisplay);
}
void QWaylandDisplay::blockingReadEvents()
{
if (wl_display_dispatch_queue(mDisplay, mEventQueue) == -1 && (errno == EPIPE || errno == ECONNRESET)) {
qWarning("The Wayland connection broke. Did the Wayland compositor die?");
::exit(1);
}
if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0)
mEventThreadObject->checkErrorAndExit();
}
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
@ -229,37 +226,39 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
struct ::wl_registry *registry = object();
if (interface == QStringLiteral("wl_output")) {
mScreens.append(new QWaylandScreen(this, id));
QWaylandScreen *screen = new QWaylandScreen(this, id);
mScreens.append(screen);
// We need to get the output events before creating surfaces
forceRoundTrip();
mWaylandIntegration->screenAdded(screen);
} else if (interface == QStringLiteral("wl_compositor")) {
mCompositor.init(registry, id);
mCompositor.init(registry, id, 3);
} else if (interface == QStringLiteral("wl_shm")) {
mShm = static_cast<struct wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface,1));
} else if (interface == QStringLiteral("xdg_shell")
&& qEnvironmentVariableIsSet("QT_WAYLAND_USE_XDG_SHELL")) {
mShellXdg.reset(new QWaylandXdgShell(registry,id));
} else if (interface == QStringLiteral("wl_shell")){
mShell.reset(new QtWayland::wl_shell(registry, id));
mShell.reset(new QtWayland::wl_shell(registry, id, 1));
} else if (interface == QStringLiteral("wl_seat")) {
QWaylandInputDevice *inputDevice = new QWaylandInputDevice(this, id);
mInputDevices.append(inputDevice);
} else if (interface == QStringLiteral("wl_data_device_manager")) {
mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
} else if (interface == QStringLiteral("qt_output_extension")) {
mOutputExtension.reset(new QtWayland::qt_output_extension(registry, id));
mOutputExtension.reset(new QtWayland::qt_output_extension(registry, id, 1));
foreach (QPlatformScreen *screen, screens())
static_cast<QWaylandScreen *>(screen)->createExtendedOutput();
} else if (interface == QStringLiteral("qt_surface_extension")) {
mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id));
mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
} else if (interface == QStringLiteral("qt_sub_surface_extension")) {
mSubSurfaceExtension.reset(new QtWayland::qt_sub_surface_extension(registry, id));
mSubSurfaceExtension.reset(new QtWayland::qt_sub_surface_extension(registry, id, 1));
} else if (interface == QStringLiteral("qt_touch_extension")) {
mTouchExtension.reset(new QWaylandTouchExtension(this, id));
} else if (interface == QStringLiteral("qt_key_extension")) {
mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
} else if (interface == QStringLiteral("wl_text_input_manager")) {
mTextInputManager.reset(new QtWayland::wl_text_input_manager(registry, id));
mTextInputManager.reset(new QtWayland::wl_text_input_manager(registry, id, 1));
} else if (interface == QStringLiteral("qt_hardware_integration")) {
mHardwareIntegration.reset(new QWaylandHardwareIntegration(registry, id));
// make a roundtrip here since we need to receive the events sent by
@ -276,7 +275,17 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
void QWaylandDisplay::registry_global_remove(uint32_t id)
{
for (int i = 0, ie = mGlobals.count(); i != ie; ++i) {
if (mGlobals[i].id == id) {
RegistryGlobal &global = mGlobals[i];
if (global.id == id) {
if (global.interface == QStringLiteral("wl_output")) {
foreach (QWaylandScreen *screen, mScreens) {
if (screen->outputId() == id) {
delete screen;
mScreens.removeOne(screen);
break;
}
}
}
mGlobals.removeAt(i);
break;
}
@ -337,4 +346,16 @@ QtWayland::xdg_shell *QWaylandDisplay::shellXdg()
return mShellXdg.data();
}
bool QWaylandDisplay::supportsWindowDecoration() const
{
static bool disabled = qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").toInt();
// Stop early when disabled via the environment. Do not try to load the integration in
// order to play nice with SHM-only, buffer integration-less systems.
if (disabled)
return false;
static bool integrationSupport = clientBufferIntegration() && clientBufferIntegration()->supportsWindowDecoration();
return integrationSupport;
}
QT_END_NAMESPACE

View File

@ -97,7 +97,7 @@ public:
QWaylandDisplay(QWaylandIntegration *waylandIntegration);
~QWaylandDisplay(void);
QList<QPlatformScreen *> screens() const { return mScreens; }
QList<QWaylandScreen *> screens() const { return mScreens; }
QWaylandScreen *screenForOutput(struct wl_output *output) const;
@ -157,6 +157,8 @@ public:
void forceRoundTrip();
bool supportsWindowDecoration() const;
public slots:
void blockingReadEvents();
void flushRequests();
@ -177,7 +179,7 @@ private:
QWaylandEventThread *mEventThreadObject;
QScopedPointer<QtWayland::wl_shell> mShell;
QScopedPointer<QWaylandXdgShell> mShellXdg;
QList<QPlatformScreen *> mScreens;
QList<QWaylandScreen *> mScreens;
QList<QWaylandInputDevice *> mInputDevices;
QList<Listener> mRegistryListeners;
QWaylandIntegration *mWaylandIntegration;

View File

@ -71,12 +71,25 @@ void QWaylandEventThread::displayConnect()
QMetaObject::invokeMethod(this, "waylandDisplayConnect", Qt::QueuedConnection);
}
// ### be careful what you do, this function may also be called from other
// threads to clean up & exit.
void QWaylandEventThread::checkErrorAndExit()
{
int ecode = wl_display_get_error(m_display);
if ((ecode == EPIPE || ecode == ECONNRESET)) {
// special case this to provide a nicer error
qWarning("The Wayland connection broke. Did the Wayland compositor die?");
} else {
qErrnoWarning(ecode, "The Wayland connection experienced a fatal error");
}
::exit(1);
}
void QWaylandEventThread::readWaylandEvents()
{
if (wl_display_dispatch(m_display) == -1 && (errno == EPIPE || errno == ECONNRESET)) {
qWarning("The Wayland connection broke. Did the Wayland compositor die?");
::exit(1);
}
if (wl_display_dispatch(m_display) < 0)
checkErrorAndExit();
emit newEventsRead();
}

View File

@ -63,6 +63,8 @@ public:
wl_display *display() const;
void checkErrorAndExit();
private slots:
void readWaylandEvents();

View File

@ -220,6 +220,8 @@ public:
void touch_frame() Q_DECL_OVERRIDE;
void touch_cancel() Q_DECL_OVERRIDE;
bool allTouchPointsReleased();
QWaylandInputDevice *mParent;
QWaylandWindow *mFocus;
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
@ -228,7 +230,7 @@ public:
QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id)
: QObject()
, QtWayland::wl_seat(display->wl_registry(), id)
, QtWayland::wl_seat(display->wl_registry(), id, 2)
, mQDisplay(display)
, mDisplay(display->wl_display())
, mCaps(0)
@ -715,6 +717,11 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf
Q_UNUSED(time);
Q_UNUSED(surface);
if (surface) {
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
window->unfocus();
}
mFocus = NULL;
// Use a callback to set the focus because we may get a leave/enter pair, and
@ -851,8 +858,8 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
wl_fixed_t x,
wl_fixed_t y)
{
Q_UNUSED(serial);
Q_UNUSED(time);
mParent->mTime = time;
mParent->mSerial = serial;
mFocus = QWaylandWindow::fromWlSurface(surface);
mParent->handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed);
}
@ -863,6 +870,13 @@ void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_
Q_UNUSED(time);
mFocus = 0;
mParent->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
// As of Weston 1.5.90 there is no touch_frame after the last touch_up
// (i.e. when the last finger is released). To accommodate for this, issue a
// touch_frame. This cannot hurt since it is safe to call the touch_frame
// handler multiple times when there are no points left.
if (allTouchPointsReleased())
touch_frame();
}
void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
@ -912,7 +926,7 @@ void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::Touch
tp.area = QRectF(0, 0, 8, 8);
QMargins margins = win->frameMargins();
tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x+margins.left(), y+margins.top())));
tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x - margins.left(), y - margins.top())));
}
tp.state = state;
@ -921,6 +935,15 @@ void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::Touch
mTouch->mTouchPoints.append(tp);
}
bool QWaylandInputDevice::Touch::allTouchPointsReleased()
{
for (int i = 0; i < mTouchPoints.count(); ++i)
if (mTouchPoints.at(i).state != Qt::TouchPointReleased)
return false;
return true;
}
void QWaylandInputDevice::Touch::touch_frame()
{
// Copy all points, that are in the previous but not in the current list, as stationary.
@ -948,22 +971,24 @@ void QWaylandInputDevice::Touch::touch_frame()
QWindow *window = mFocus ? mFocus->window() : 0;
if (mFocus) {
const QWindowSystemInterface::TouchPoint &tp = mTouchPoints.last();
// When the touch event is received, the global pos is calculated with the margins
// in mind. Now we need to adjust again to get the correct local pos back.
QMargins margins = window->frameMargins();
QPoint p = tp.area.center().toPoint();
QPointF localPos(window->mapFromGlobal(QPoint(p.x() + margins.left(), p.y() + margins.top())));
if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers()))
return;
}
QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints);
bool allReleased = true;
for (int i = 0; i < mTouchPoints.count(); ++i)
if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
allReleased = false;
break;
}
mPrevTouchPoints = mTouchPoints;
mTouchPoints.clear();
if (allReleased) {
QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints);
if (allTouchPointsReleased())
mPrevTouchPoints.clear();
}
else
mPrevTouchPoints = mTouchPoints;
mTouchPoints.clear();
}
QT_END_NAMESPACE

View File

@ -42,13 +42,14 @@
#include "qwaylandintegration_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandshmwindow_p.h"
#include "qwaylandinputcontext_p.h"
#include "qwaylandshmbackingstore_p.h"
#include "qwaylandshmwindow_p.h"
#include "qwaylandnativeinterface_p.h"
#include "qwaylandclipboard_p.h"
#include "qwaylanddnd_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandscreen_p.h"
#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
@ -127,9 +128,6 @@ QWaylandIntegration::QWaylandIntegration()
mClipboard = new QWaylandClipboard(mDisplay);
mDrag = new QWaylandDrag(mDisplay);
foreach (QPlatformScreen *screen, mDisplay->screens())
screenAdded(screen);
mInputContext.reset(new QWaylandInputContext(mDisplay));
}
@ -162,14 +160,18 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co
case MultipleWindows:
case NonFullScreenWindows:
return true;
case RasterGLSurface:
return true;
default: return QPlatformIntegration::hasCapability(cap);
}
}
QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const
{
if (window->surfaceType() == QWindow::OpenGLSurface && mDisplay->clientBufferIntegration())
if ((window->surfaceType() == QWindow::OpenGLSurface || window->surfaceType() == QWindow::RasterGLSurface)
&& mDisplay->clientBufferIntegration())
return mDisplay->clientBufferIntegration()->createEglWindow(window);
return new QWaylandShmWindow(window);
}
@ -255,7 +257,7 @@ QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration()
if (!mClientBufferIntegrationInitialized)
const_cast<QWaylandIntegration *>(this)->initializeClientBufferIntegration();
return mClientBufferIntegration;
return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration : 0;
}
QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() const
@ -291,7 +293,7 @@ void QWaylandIntegration::initializeClientBufferIntegration()
}
if (targetKey.isEmpty()) {
qWarning("Failed to determin what client buffer integration to use");
qWarning("Failed to determine what client buffer integration to use");
return;
}

View File

@ -110,6 +110,8 @@ private:
bool mClientBufferIntegrationInitialized;
bool mServerBufferIntegrationInitialized;
bool mShellIntegrationInitialized;
friend class QWaylandDisplay;
};
QT_END_NAMESPACE

View File

@ -68,8 +68,6 @@ public:
void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
void emitWindowPropertyChanged(QPlatformWindow *window, const QString &name);
private:
static QWaylandScreen *qPlatformScreenForWindow(QWindow *window);
private:
QWaylandIntegration *m_integration;

View File

@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
QWaylandQtKeyExtension::QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_t id)
: QtWayland::qt_key_extension(display->wl_registry(), id)
: QtWayland::qt_key_extension(display->wl_registry(), id, 2)
, m_display(display)
{
}

View File

@ -54,7 +54,9 @@
QT_BEGIN_NAMESPACE
QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id)
: QtWayland::wl_output(waylandDisplay->wl_registry(), id)
: QPlatformScreen()
, QtWayland::wl_output(waylandDisplay->wl_registry(), id, 2)
, m_outputId(id)
, mWaylandDisplay(waylandDisplay)
, mExtendedOutput(0)
, mDepth(32)
@ -93,6 +95,14 @@ QImage::Format QWaylandScreen::format() const
return mFormat;
}
QSizeF QWaylandScreen::physicalSize() const
{
if (mPhysicalSize.isEmpty())
return QPlatformScreen::physicalSize();
else
return mPhysicalSize;
}
QDpi QWaylandScreen::logicalDpi() const
{
static int force_dpi = !qgetenv("QT_WAYLAND_FORCE_DPI").isEmpty() ? qgetenv("QT_WAYLAND_FORCE_DPI").toInt() : -1;
@ -151,16 +161,11 @@ void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refr
QSize size(width, height);
if (size != mGeometry.size()) {
if (size != mGeometry.size())
mGeometry.setSize(size);
QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry);
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry);
}
if (refresh != mRefreshRate) {
if (refresh != mRefreshRate)
mRefreshRate = refresh;
QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate());
}
}
void QWaylandScreen::output_geometry(int32_t x, int32_t y,
@ -200,14 +205,17 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y,
if (!model.isEmpty())
mOutputName = model;
QRect geom(x, y, width, height);
mPhysicalSize = QSize(width, height);
mGeometry.moveTopLeft(QPoint(x, y));
}
if (mGeometry == geom)
return;
mGeometry = geom;
QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry);
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry);
void QWaylandScreen::output_done()
{
// the done event is sent after all the geometry and the mode events are sent,
// and the last mode event to be sent is the active one, so we can trust the
// values of mGeometry and mRefreshRate here
QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry, mGeometry);
QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate());
}
QT_END_NAMESPACE

View File

@ -65,6 +65,8 @@ public:
int depth() const;
QImage::Format format() const;
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
void setOrientationUpdateMask(Qt::ScreenOrientations mask);
@ -77,6 +79,7 @@ public:
QPlatformCursor *cursor() const;
QWaylandCursor *waylandCursor() const { return mWaylandCursor; };
uint32_t outputId() const { return m_outputId; }
::wl_output *output() { return object(); }
QWaylandExtendedOutput *extendedOutput() const;
@ -92,7 +95,9 @@ private:
const QString &make,
const QString &model,
int32_t transform) Q_DECL_OVERRIDE;
void output_done() Q_DECL_OVERRIDE;
int m_outputId;
QWaylandDisplay *mWaylandDisplay;
QWaylandExtendedOutput *mExtendedOutput;
QRect mGeometry;

View File

@ -50,6 +50,7 @@ QWaylandShellSurface::QWaylandShellSurface(QWaylandWindow *window)
void QWaylandShellSurface::setWindowFlags(Qt::WindowFlags flags)
{
Q_UNUSED(flags);
}
void QWaylandShellSurface::sendProperty(const QString &name, const QVariant &value)

View File

@ -39,14 +39,12 @@
**
****************************************************************************/
#include "qwaylandshmbackingstore_p.h"
#include <QtCore/qdebug.h>
#include "qwaylandwindow_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandshmwindow_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylanddecoration_p.h"
#include <QtCore/qdebug.h>
#include <QtGui/QPainter>
#include <wayland-client.h>
@ -156,9 +154,7 @@ QWaylandShmBackingStore::~QWaylandShmBackingStore()
QPaintDevice *QWaylandShmBackingStore::paintDevice()
{
if (!windowDecoration())
return mBackBuffer->image();
return mBackBuffer->imageInsideMargins(windowDecorationMargins());
return contentSurface();
}
void QWaylandShmBackingStore::beginPaint(const QRegion &)
@ -166,13 +162,11 @@ void QWaylandShmBackingStore::beginPaint(const QRegion &)
mPainting = true;
ensureSize();
if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached() && mFrameCallback) {
QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
waylandWindow->waitForFrameSync();
}
QWaylandWindow *window = waylandWindow();
if (window->attached() && mBackBuffer == window->attached() && mFrameCallback)
window->waitForFrameSync();
waylandWindow()->setCanResize(false);
window->setCanResize(false);
}
void QWaylandShmBackingStore::endPaint()
@ -190,9 +184,15 @@ void QWaylandShmBackingStore::ensureSize()
void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
// Invoked when the window is of type RasterSurface or when the window is
// RasterGLSurface and there are no child widgets requiring OpenGL composition.
// For the case of RasterGLSurface + having to compose, the composeAndFlush() is
// called instead. The default implementation from QPlatformBackingStore is sufficient
// however so no need to reimplement that.
Q_UNUSED(window);
Q_UNUSED(offset);
Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm);
if (windowDecoration() && windowDecoration()->isDirty())
updateDecorations();
@ -260,6 +260,11 @@ QImage *QWaylandShmBackingStore::entireSurface() const
return mBackBuffer->image();
}
QImage *QWaylandShmBackingStore::contentSurface() const
{
return windowDecoration() ? mBackBuffer->imageInsideMargins(windowDecorationMargins()) : mBackBuffer->image();
}
void QWaylandShmBackingStore::updateDecorations()
{
QPainter decorationPainter(entireSurface());
@ -302,11 +307,19 @@ QMargins QWaylandShmBackingStore::windowDecorationMargins() const
return QMargins();
}
QWaylandShmWindow *QWaylandShmBackingStore::waylandWindow() const
QWaylandWindow *QWaylandShmBackingStore::waylandWindow() const
{
return static_cast<QWaylandShmWindow *>(window()->handle());
return static_cast<QWaylandWindow *>(window()->handle());
}
QImage QWaylandShmBackingStore::toImage() const
{
// Invoked from QPlatformBackingStore::composeAndFlush() that is called
// instead of flush() for widgets that have renderToTexture children
// (QOpenGLWidget, QQuickWidget).
return *contentSurface();
}
void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time)
{
@ -315,7 +328,7 @@ void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t t
static_cast<QWaylandShmBackingStore *>(data);
if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too
return;
QWaylandShmWindow *window = self->waylandWindow();
QWaylandWindow *window = self->waylandWindow();
wl_callback_destroy(self->mFrameCallback);
self->mFrameCallback = 0;

View File

@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QWaylandDisplay;
class QWaylandDecoration;
class QWaylandShmWindow;
class QWaylandWindow;
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer {
public:
@ -87,11 +87,14 @@ public:
QMargins windowDecorationMargins() const;
QImage *entireSurface() const;
QImage *contentSurface() const;
void ensureSize();
QWaylandShmWindow *waylandWindow() const;
QWaylandWindow *waylandWindow() const;
void iterateBuffer();
QImage toImage() const Q_DECL_OVERRIDE;
private:
void updateDecorations();

View File

@ -51,13 +51,11 @@ QT_BEGIN_NAMESPACE
QWaylandShmWindow::QWaylandShmWindow(QWindow *window)
: QWaylandWindow(window)
, mBackingStore(0)
{
}
QWaylandShmWindow::~QWaylandShmWindow()
{
}
QWaylandWindow::WindowType QWaylandShmWindow::windowType() const
@ -65,9 +63,4 @@ QWaylandWindow::WindowType QWaylandShmWindow::windowType() const
return QWaylandWindow::Shm;
}
void QWaylandShmWindow::setBackingStore(QWaylandShmBackingStore *backingStore)
{
mBackingStore = backingStore;
}
QT_END_NAMESPACE

View File

@ -47,8 +47,6 @@
QT_BEGIN_NAMESPACE
class QWaylandShmBackingStore;
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow
{
public:
@ -57,19 +55,8 @@ public:
WindowType windowType() const;
QSurfaceFormat format() const { return QSurfaceFormat(); }
void setBackingStore(QWaylandShmBackingStore *backingStore);
QWaylandShmBackingStore *backingStore() const;
private:
QWaylandShmBackingStore *mBackingStore;
};
inline QWaylandShmBackingStore *QWaylandShmWindow::backingStore() const
{
return mBackingStore;
}
QT_END_NAMESPACE
#endif // QWAYLANDSHMWINDOW_H

View File

@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id)
: QtWayland::qt_touch_extension(display->wl_registry(), id),
: QtWayland::qt_touch_extension(display->wl_registry(), id, 1),
mDisplay(display),
mTouchDevice(0),
mPointsLeft(0),

View File

@ -42,6 +42,7 @@
#include "qwaylandwindow_p.h"
#include "qwaylandbuffer_p.h"
#include "qwaylanddatadevice_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandinputdevice_p.h"
#include "qwaylandscreen_p.h"
@ -132,6 +133,8 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
QWaylandWindow::~QWaylandWindow()
{
delete mWindowDecoration;
if (isInitialized()) {
delete mShellSurface;
destroy();
@ -458,6 +461,8 @@ void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orient
case Qt::InvertedPortraitOrientation:
transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
break;
default:
Q_UNREACHABLE();
}
set_buffer_transform(transform);
// set_buffer_transform is double buffered, we need to commit.
@ -498,8 +503,7 @@ bool QWaylandWindow::createDecoration()
}
}
static bool disableWaylandDecorations = !qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").isEmpty();
if (disableWaylandDecorations)
if (!mDisplay->supportsWindowDecoration())
return false;
bool decoration = false;
@ -596,6 +600,13 @@ void QWaylandWindow::handleMouseLeave(QWaylandInputDevice *inputDevice)
restoreMouseCursor(inputDevice);
}
bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods)
{
if (!mWindowDecoration)
return false;
return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods);
}
void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
if (mWindowDecoration->handleMouse(inputDevice,local,global,b,mods))
@ -648,6 +659,14 @@ void QWaylandWindow::requestActivateWindow()
// we rely on compositor setting keyboard focus based on window stacking.
}
void QWaylandWindow::unfocus()
{
QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
if (inputDevice && inputDevice->dataDevice()) {
inputDevice->dataDevice()->invalidateSelectionOffer();
}
}
bool QWaylandWindow::isExposed() const
{
if (mShellSurface)
@ -677,18 +696,21 @@ bool QWaylandWindow::setWindowStateInternal(Qt::WindowState state)
// here. We use then this mState variable.
mState = state;
createDecoration();
switch (state) {
case Qt::WindowFullScreen:
mShellSurface->setFullscreen();
break;
case Qt::WindowMaximized:
mShellSurface->setMaximized();
break;
case Qt::WindowMinimized:
mShellSurface->setMinimized();
break;
default:
mShellSurface->setNormal();
if (mShellSurface) {
switch (state) {
case Qt::WindowFullScreen:
mShellSurface->setFullscreen();
break;
case Qt::WindowMaximized:
mShellSurface->setMaximized();
break;
case Qt::WindowMinimized:
mShellSurface->setMinimized();
break;
default:
mShellSurface->setNormal();
}
}
QWindowSystemInterface::handleWindowStateChanged(window(), mState);

View File

@ -63,6 +63,7 @@ class QWaylandSubSurface;
class QWaylandDecoration;
class QWaylandInputDevice;
class QWaylandScreen;
class QWaylandShmBackingStore;
class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure
{
@ -143,6 +144,7 @@ public:
void requestActivateWindow() Q_DECL_OVERRIDE;
bool isExposed() const Q_DECL_OVERRIDE;
void unfocus();
QWaylandDecoration *decoration() const;
void setDecoration(QWaylandDecoration *decoration);
@ -157,6 +159,9 @@ public:
void handleMouseEnter(QWaylandInputDevice *inputDevice);
void handleMouseLeave(QWaylandInputDevice *inputDevice);
bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
Qt::TouchPointState state, Qt::KeyboardModifiers mods);
bool createDecoration();
inline bool isMaximized() const { return mState == Qt::WindowMaximized; }
@ -181,6 +186,12 @@ public:
QVariant property(const QString &name);
QVariant property(const QString &name, const QVariant &defaultValue);
void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; }
QWaylandShmBackingStore *backingStore() const { return mBackingStore; }
bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
void propagateSizeHints() Q_DECL_OVERRIDE { }
public slots:
void requestResize();
@ -219,6 +230,8 @@ protected:
Qt::WindowState mState;
QRegion mMask;
QWaylandShmBackingStore *mBackingStore;
private:
bool setWindowStateInternal(Qt::WindowState flags);
void setGeometry_helper(const QRect &rect);

View File

@ -95,7 +95,7 @@ void QWaylandWindowManagerIntegration::wlHandleListenerGlobal(void *data, wl_reg
{
Q_UNUSED(version);
if (interface == QStringLiteral("qt_windowmanager"))
static_cast<QWaylandWindowManagerIntegration *>(data)->init(registry, id);
static_cast<QWaylandWindowManagerIntegration *>(data)->init(registry, id, 1);
}
void QWaylandWindowManagerIntegration::windowmanager_hints(int32_t showIsFullScreen)

View File

@ -57,7 +57,7 @@ QWaylandXdgShell::QWaylandXdgShell(struct ::xdg_shell *shell)
}
QWaylandXdgShell::QWaylandXdgShell(struct ::wl_registry *registry, uint32_t id)
: QtWayland::xdg_shell(registry, id)
: QtWayland::xdg_shell(registry, id, 1)
{
use_unstable_version(QtWayland::xdg_shell::version_current);
}

View File

@ -822,13 +822,13 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" class %s %s\n {\n", clientExport.constData(), interfaceName);
printf(" public:\n");
printf(" %s(struct ::wl_registry *registry, int id);\n", interfaceName);
printf(" %s(struct ::wl_registry *registry, int id, int version);\n", interfaceName);
printf(" %s(struct ::%s *object);\n", interfaceName, interfaceName);
printf(" %s();\n", interfaceName);
printf("\n");
printf(" virtual ~%s();\n", interfaceName);
printf("\n");
printf(" void init(struct ::wl_registry *registry, int id);\n");
printf(" void init(struct ::wl_registry *registry, int id, int version);\n");
printf(" void init(struct ::%s *object);\n", interfaceName);
printf("\n");
printf(" struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName);
@ -908,9 +908,9 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
bool hasEvents = !interface.events.isEmpty();
printf(" %s::%s(struct ::wl_registry *registry, int id)\n", interfaceName, interfaceName);
printf(" %s::%s(struct ::wl_registry *registry, int id, int version)\n", interfaceName, interfaceName);
printf(" {\n");
printf(" init(registry, id);\n");
printf(" init(registry, id, version);\n");
printf(" }\n");
printf("\n");
@ -933,9 +933,9 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" }\n");
printf("\n");
printf(" void %s::init(struct ::wl_registry *registry, int id)\n", interfaceName);
printf(" void %s::init(struct ::wl_registry *registry, int id, int version)\n", interfaceName);
printf(" {\n");
printf(" m_%s = static_cast<struct ::%s *>(wl_registry_bind(registry, id, &%s_interface, %s_interface.version));\n", interfaceName, interfaceName, interfaceName, interfaceName);
printf(" m_%s = static_cast<struct ::%s *>(wl_registry_bind(registry, id, &%s_interface, version));\n", interfaceName, interfaceName, interfaceName);
if (hasEvents)
printf(" init_listener();\n");
printf(" }\n");

View File

@ -135,8 +135,13 @@ QSharedPointer<MockSurface> MockCompositor::surface()
QSharedPointer<MockSurface> result;
lock();
QVector<Impl::Surface *> surfaces = m_compositor->surfaces();
if (!surfaces.isEmpty())
result = surfaces.first()->mockSurface();
foreach (Impl::Surface *surface, surfaces) {
// we don't want to mistake the cursor surface for a window surface
if (surface->isMapped()) {
result = surface->mockSurface();
break;
}
}
unlock();
return result;
}
@ -189,11 +194,6 @@ void *MockCompositor::run(void *data)
return 0;
}
void MockCompositor::discardSurfaces()
{
m_compositor->discardSurfaces();
}
namespace Impl {
Compositor::Compositor()
@ -209,6 +209,8 @@ Compositor::Compositor()
wl_display_add_global(m_display, &wl_compositor_interface, this, bindCompositor);
m_data_device_manager.reset(new DataDeviceManager(this, m_display));
wl_display_init_shm(m_display);
m_seat.reset(new Seat(this, m_display));
@ -298,10 +300,5 @@ void Compositor::removeSurface(Surface *surface)
m_pointer->setFocus(0, QPoint());
}
void Compositor::discardSurfaces()
{
m_surfaces.clear();
}
}

View File

@ -61,6 +61,7 @@ typedef void (**Implementation)(void);
class Keyboard;
class Pointer;
class Seat;
class DataDeviceManager;
class Surface;
class Compositor
@ -81,7 +82,6 @@ public:
void addSurface(Surface *surface);
void removeSurface(Surface *surface);
void discardSurfaces();
static void setKeyboardFocus(void *data, const QList<QVariant> &parameters);
static void sendMousePress(void *data, const QList<QVariant> &parameters);
@ -112,6 +112,7 @@ private:
QScopedPointer<Seat> m_seat;
Pointer *m_pointer;
Keyboard *m_keyboard;
QScopedPointer<DataDeviceManager> m_data_device_manager;
QVector<Surface *> m_surfaces;
};
@ -155,7 +156,6 @@ public:
void sendKeyRelease(const QSharedPointer<MockSurface> &surface, uint code);
QSharedPointer<MockSurface> surface();
void discardSurfaces();
void lock();
void unlock();

View File

@ -130,6 +130,8 @@ void Seat::seat_get_pointer(Resource *resource, uint32_t id)
Keyboard::Keyboard(Compositor *compositor)
: wl_keyboard()
, m_compositor(compositor)
, m_focusResource(Q_NULLPTR)
, m_focus(Q_NULLPTR)
{
}
@ -174,6 +176,8 @@ void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource)
Pointer::Pointer(Compositor *compositor)
: wl_pointer()
, m_compositor(compositor)
, m_focusResource(Q_NULLPTR)
, m_focus(Q_NULLPTR)
{
}
@ -223,4 +227,35 @@ void Pointer::pointer_destroy_resource(wl_pointer::Resource *resource)
m_focusResource = 0;
}
DataDevice::DataDevice(Compositor *compositor)
: wl_data_device()
, m_compositor(compositor)
{
}
DataDevice::~DataDevice()
{
}
DataDeviceManager::DataDeviceManager(Compositor *compositor, wl_display *display)
: wl_data_device_manager(display)
, m_compositor(compositor)
{
}
DataDeviceManager::~DataDeviceManager()
{
}
void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat)
{
if (!m_data_device)
m_data_device.reset(new DataDevice(m_compositor));
m_data_device->add(resource->client(), id);
}
}

View File

@ -120,6 +120,31 @@ private:
Surface *m_focus;
};
class DataDevice : public QtWaylandServer::wl_data_device
{
public:
DataDevice(Compositor *compositor);
~DataDevice();
private:
Compositor *m_compositor;
};
class DataDeviceManager : public QtWaylandServer::wl_data_device_manager
{
public:
DataDeviceManager(Compositor *compositor, struct ::wl_display *display);
~DataDeviceManager();
protected:
void data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) Q_DECL_OVERRIDE;
private:
Compositor *m_compositor;
QScopedPointer<DataDevice> m_data_device;
};
}
#endif // MOCKINPUT_H

View File

@ -40,6 +40,7 @@
****************************************************************************/
#include "mockcompositor.h"
#include "mocksurface.h"
namespace Impl {
@ -173,6 +174,8 @@ static void get_shell_surface(wl_client *client, wl_resource *compositorResource
Q_UNUSED(compositorResource);
wl_client_add_object(client, &wl_shell_surface_interface, &shellSurfaceInterface, id, surfaceResource->data);
Surface *surf = Surface::fromResource(surfaceResource);
surf->map();
}
void Compositor::bindShell(wl_client *client, void *compositorData, uint32_t version, uint32_t id)

View File

@ -46,10 +46,11 @@ namespace Impl {
Surface::Surface(wl_client *client, uint32_t id, Compositor *compositor)
: QtWaylandServer::wl_surface(client, id)
, m_buffer(Q_NULLPTR)
, m_compositor(compositor)
, m_mockSurface(new MockSurface(this))
, m_mapped(false)
{
wl_list_init(&m_frameCallbackList);
}
Surface::~Surface()
@ -57,6 +58,21 @@ Surface::~Surface()
m_mockSurface->m_surface = 0;
}
void Surface::map()
{
m_mapped = true;
}
bool Surface::isMapped() const
{
return m_mapped;
}
Surface *Surface::fromResource(struct ::wl_resource *resource)
{
return static_cast<Surface *>(Resource::fromResource(resource)->surface_object);
}
void Surface::surface_destroy_resource(Resource *)
{
compositor()->removeSurface(this);
@ -88,47 +104,44 @@ void Surface::surface_damage(Resource *resource,
Q_UNUSED(y);
Q_UNUSED(width);
Q_UNUSED(height);
if (!m_buffer)
return;
#if WAYLAND_VERSION_CHECK(1, 2, 0)
struct ::wl_shm_buffer *shm_buffer = wl_shm_buffer_get(m_buffer);
#else
struct ::wl_buffer *shm_buffer = 0;
if (wl_buffer_is_shm(static_cast<struct ::wl_buffer*>(m_buffer->data)))
shm_buffer = static_cast<struct ::wl_buffer*>(m_buffer->data);
#endif
if (shm_buffer) {
int stride = wl_shm_buffer_get_stride(shm_buffer);
uint format = wl_shm_buffer_get_format(shm_buffer);
Q_UNUSED(format);
void *data = wl_shm_buffer_get_data(shm_buffer);
const uchar *char_data = static_cast<const uchar *>(data);
QImage img(char_data, wl_shm_buffer_get_width(shm_buffer), wl_shm_buffer_get_height(shm_buffer), stride, QImage::Format_ARGB32_Premultiplied);
m_mockSurface->image = img;
}
wl_resource *frameCallback;
wl_list_for_each(frameCallback, &m_frameCallbackList, link) {
wl_callback_send_done(frameCallback, m_compositor->time());
wl_resource_destroy(frameCallback);
}
wl_list_init(&m_frameCallbackList);
}
void Surface::surface_frame(Resource *resource,
uint32_t callback)
{
wl_resource *frameCallback = wl_client_add_object(resource->client(), &wl_callback_interface, 0, callback, this);
wl_list_insert(&m_frameCallbackList, &frameCallback->link);
m_frameCallbackList << frameCallback;
}
void Surface::surface_commit(Resource *resource)
{
Q_UNUSED(resource);
if (m_buffer) {
#if WAYLAND_VERSION_CHECK(1, 2, 0)
struct ::wl_shm_buffer *shm_buffer = wl_shm_buffer_get(m_buffer);
#else
struct ::wl_buffer *shm_buffer = 0;
if (wl_buffer_is_shm(static_cast<struct ::wl_buffer*>(m_buffer->data)))
shm_buffer = static_cast<struct ::wl_buffer*>(m_buffer->data);
#endif
if (shm_buffer) {
int stride = wl_shm_buffer_get_stride(shm_buffer);
uint format = wl_shm_buffer_get_format(shm_buffer);
Q_UNUSED(format);
void *data = wl_shm_buffer_get_data(shm_buffer);
const uchar *char_data = static_cast<const uchar *>(data);
QImage img(char_data, wl_shm_buffer_get_width(shm_buffer), wl_shm_buffer_get_height(shm_buffer), stride, QImage::Format_ARGB32_Premultiplied);
m_mockSurface->image = img;
}
}
foreach (wl_resource *frameCallback, m_frameCallbackList) {
wl_callback_send_done(frameCallback, m_compositor->time());
wl_resource_destroy(frameCallback);
}
m_frameCallbackList.clear();
}
}

View File

@ -54,6 +54,9 @@ public:
~Surface();
Compositor *compositor() const { return m_compositor; }
static Surface *fromResource(struct ::wl_resource *resource);
void map();
bool isMapped() const;
QSharedPointer<MockSurface> mockSurface() const { return m_mockSurface; }
@ -74,8 +77,8 @@ private:
Compositor *m_compositor;
QSharedPointer<MockSurface> m_mockSurface;
wl_list m_frameCallbackList;
QList<wl_resource *> m_frameCallbackList;
bool m_mapped;
};
}

View File

@ -149,11 +149,7 @@ private:
void tst_WaylandClient::screen()
{
QCoreApplication::processEvents(QEventLoop::AllEvents);
QTRY_COMPARE(QGuiApplication::primaryScreen()->size(), screenSize);
// discard the cursor surface created by the QWaylandInputDevice
compositor->discardSurfaces();
}
void tst_WaylandClient::createDestroyWindow()
@ -252,6 +248,11 @@ int main(int argc, char **argv)
setenv("XDG_RUNTIME_DIR", ".", 1);
setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin
// wayland-egl hangs in the test setup when we try to initialize. Until it gets
// figured out, avoid clientBufferIntegration() from being called in
// QWaylandWindow::createDecorations().
setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1);
MockCompositor compositor;
compositor.setOutputGeometry(QRect(QPoint(), screenSize));