summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/client.pro7
-rw-r--r--src/client/configure.json7
-rw-r--r--src/client/qwaylandcursor.cpp12
-rw-r--r--src/client/qwaylandcursor_p.h3
-rw-r--r--src/client/qwaylanddatadevice.cpp16
-rw-r--r--src/client/qwaylanddisplay.cpp25
-rw-r--r--src/client/qwaylanddisplay_p.h7
-rw-r--r--src/client/qwaylandinputdevice.cpp101
-rw-r--r--src/client/qwaylandinputdevice_p.h31
-rw-r--r--src/client/qwaylandintegration.cpp14
-rw-r--r--src/client/qwaylandscreen.cpp13
-rw-r--r--src/client/qwaylandscreen_p.h1
-rw-r--r--src/client/qwaylandshmbackingstore.cpp4
-rw-r--r--src/client/qwaylandshmbackingstore_p.h2
-rw-r--r--src/client/qwaylandshmwindow.cpp4
-rw-r--r--src/client/qwaylandshmwindow_p.h2
-rw-r--r--src/client/qwaylandsurface.cpp8
-rw-r--r--src/client/qwaylandtabletv2.cpp332
-rw-r--r--src/client/qwaylandtabletv2_p.h191
-rw-r--r--src/client/qwaylandtouch.cpp16
-rw-r--r--src/client/qwaylandvulkanwindow.cpp4
-rw-r--r--src/client/qwaylandvulkanwindow_p.h2
-rw-r--r--src/client/qwaylandwindow.cpp72
-rw-r--r--src/client/qwaylandwindow_p.h7
24 files changed, 762 insertions, 119 deletions
diff --git a/src/client/client.pro b/src/client/client.pro
index 458e49360..793a44183 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -23,8 +23,8 @@ qtConfig(xkbcommon) {
QT_FOR_PRIVATE += xkbcommon_support-private
}
-qtHaveModule(linuxaccessibility_support_private): \
- QT_PRIVATE += linuxaccessibility_support_private
+qtHaveModule(linuxaccessibility_support-private): \
+ QT_PRIVATE += linuxaccessibility_support-private
QMAKE_USE += wayland-client
@@ -36,6 +36,7 @@ WAYLANDCLIENTSOURCES += \
../extensions/qt-key-unstable-v1.xml \
../extensions/qt-windowmanager.xml \
../3rdparty/protocol/wp-primary-selection-unstable-v1.xml \
+ ../3rdparty/protocol/tablet-unstable-v2.xml \
../3rdparty/protocol/text-input-unstable-v2.xml \
../3rdparty/protocol/xdg-output-unstable-v1.xml \
../3rdparty/protocol/wayland.xml
@@ -52,6 +53,7 @@ SOURCES += qwaylandintegration.cpp \
qwaylandextendedsurface.cpp \
qwaylandsubsurface.cpp \
qwaylandsurface.cpp \
+ qwaylandtabletv2.cpp \
qwaylandtouch.cpp \
qwaylandqtkey.cpp \
../shared/qwaylandmimehelper.cpp \
@@ -77,6 +79,7 @@ HEADERS += qwaylandintegration_p.h \
qwaylandextendedsurface_p.h \
qwaylandsubsurface_p.h \
qwaylandsurface_p.h \
+ qwaylandtabletv2_p.h \
qwaylandtouch_p.h \
qwaylandqtkey_p.h \
qwaylandabstractdecoration_p.h \
diff --git a/src/client/configure.json b/src/client/configure.json
index f49beaf70..7d4468240 100644
--- a/src/client/configure.json
+++ b/src/client/configure.json
@@ -149,12 +149,15 @@
"#endif"
]
},
- "use": "egl"
+ "use": "egl drm"
},
"vulkan-server-buffer": {
"label": "Vulkan Buffer Sharing",
"type": "compile",
"test": {
+ "head": [
+ "#define VK_USE_PLATFORM_WAYLAND_KHR 1"
+ ],
"include": [
"vulkan/vulkan.h"
],
@@ -250,7 +253,7 @@
},
"wayland-vulkan-server-buffer": {
"label": "Vulkan-based server buffer integration",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.vulkan-server-buffer",
+ "condition": "features.wayland-client && features.vulkan && features.opengl && features.egl && tests.vulkan-server-buffer",
"output": [ "privateFeature" ]
},
"wayland-shm-emulation-server-buffer": {
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
index 4356b23a0..1d3d88bea 100644
--- a/src/client/qwaylandcursor.cpp
+++ b/src/client/qwaylandcursor.cpp
@@ -219,7 +219,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
-::wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation)
+::wl_cursor *QWaylandCursorTheme::cursor(Qt::CursorShape shape)
{
struct wl_cursor *waylandCursor = nullptr;
@@ -237,15 +237,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
- int frame = wl_cursor_frame(waylandCursor, millisecondsIntoAnimation);
- ::wl_cursor_image *image = waylandCursor->images[frame];
- ::wl_buffer *buffer = wl_cursor_image_get_buffer(image);
- if (!buffer) {
- qCWarning(lcQpaWayland) << "Could not find buffer for cursor";
- return nullptr;
- }
-
- return image;
+ return waylandCursor;
}
QWaylandCursor::QWaylandCursor(QWaylandDisplay *display)
diff --git a/src/client/qwaylandcursor_p.h b/src/client/qwaylandcursor_p.h
index a4605f3d2..751ffa68b 100644
--- a/src/client/qwaylandcursor_p.h
+++ b/src/client/qwaylandcursor_p.h
@@ -75,7 +75,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme
public:
static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName);
~QWaylandCursorTheme();
- ::wl_cursor_image *cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation = 0);
+ ::wl_cursor *cursor(Qt::CursorShape shape);
private:
enum WaylandCursor {
@@ -129,7 +129,6 @@ public:
void setPos(const QPoint &pos) override;
static QSharedPointer<QWaylandBuffer> cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor);
- struct wl_cursor_image *cursorImage(Qt::CursorShape shape);
private:
QWaylandDisplay *mDisplay = nullptr;
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index f7d135e49..19944a349 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -157,7 +157,9 @@ void QWaylandDataDevice::data_device_drop()
return;
}
- QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
@@ -187,7 +189,9 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
}
- const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
@@ -203,7 +207,9 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
void QWaylandDataDevice::data_device_leave()
{
if (m_dragWindow)
- QWindowSystemInterface::handleDrag(m_dragWindow, nullptr, QPoint(), Qt::IgnoreAction);
+ QWindowSystemInterface::handleDrag(m_dragWindow, nullptr, QPoint(), Qt::IgnoreAction,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
if (!drag) {
@@ -232,7 +238,9 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
}
- QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index 0464d3a42..ffcc72ff9 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -69,6 +69,7 @@
#include "qwaylandextendedsurface_p.h"
#include "qwaylandsubsurface_p.h"
#include "qwaylandtouch_p.h"
+#include "qwaylandtabletv2_p.h"
#include "qwaylandqtkey_p.h"
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
@@ -188,6 +189,18 @@ QWaylandDisplay::~QWaylandDisplay(void)
wl_display_disconnect(mDisplay);
}
+void QWaylandDisplay::ensureScreen()
+{
+ if (!mScreens.empty() || mPlaceholderScreen)
+ return; // There are real screens or we already have a fake one
+
+ qCInfo(lcQpaWayland) << "Creating a fake screen in order for Qt not to crash";
+
+ mPlaceholderScreen = new QPlatformPlaceholderScreen();
+ QWindowSystemInterface::handleScreenAdded(mPlaceholderScreen);
+ Q_ASSERT(!QGuiApplication::screens().empty());
+}
+
void QWaylandDisplay::checkError() const
{
int ecode = wl_display_get_error(mDisplay);
@@ -253,8 +266,7 @@ void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bo
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
{
- for (int i = 0; i < mScreens.size(); ++i) {
- QWaylandScreen *screen = static_cast<QWaylandScreen *>(mScreens.at(i));
+ for (auto screen : qAsConst(mScreens)) {
if (screen->output() == output)
return screen;
}
@@ -267,6 +279,11 @@ void QWaylandDisplay::handleScreenInitialized(QWaylandScreen *screen)
return;
mScreens.append(screen);
QWindowSystemInterface::handleScreenAdded(screen);
+ if (mPlaceholderScreen) {
+ QWindowSystemInterface::handleScreenRemoved(mPlaceholderScreen);
+ // handleScreenRemoved deletes the platform screen
+ mPlaceholderScreen = nullptr;
+ }
}
void QWaylandDisplay::waitForScreens()
@@ -314,6 +331,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mTouchExtension.reset(new QWaylandTouchExtension(this, id));
} else if (interface == QStringLiteral("zqt_key_v1")) {
mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
+ } else if (interface == QStringLiteral("zwp_tablet_manager_v2")) {
+ mTabletManager.reset(new QWaylandTabletManagerV2(this, id, qMin(1, int(version))));
#if QT_CONFIG(wayland_client_primary_selection)
} else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
@@ -362,6 +381,8 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
for (QWaylandScreen *screen : qAsConst(mScreens)) {
if (screen->outputId() == id) {
mScreens.removeOne(screen);
+ // If this is the last screen, we have to add a fake screen, or Qt will break.
+ ensureScreen();
QWindowSystemInterface::handleScreenRemoved(screen);
break;
}
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 14bb77198..e99ec1983 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -76,6 +76,7 @@ QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
class QSocketNotifier;
class QPlatformScreen;
+class QPlatformPlaceholderScreen;
namespace QtWayland {
class qt_surface_extension;
@@ -96,6 +97,7 @@ class QWaylandDataDeviceManager;
#if QT_CONFIG(wayland_client_primary_selection)
class QWaylandPrimarySelectionDeviceManagerV1;
#endif
+class QWaylandTabletManagerV2;
class QWaylandTouchExtension;
class QWaylandQtKeyExtension;
class QWaylandWindow;
@@ -124,6 +126,8 @@ public:
#endif
QList<QWaylandScreen *> screens() const { return mScreens; }
+ QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
+ void ensureScreen();
QWaylandScreen *screenForOutput(struct wl_output *output) const;
void handleScreenInitialized(QWaylandScreen *screen);
@@ -157,6 +161,7 @@ public:
QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
#endif
QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
+ QWaylandTabletManagerV2 *tabletManager() const { return mTabletManager.data(); }
QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
@@ -228,6 +233,7 @@ private:
QScopedPointer<QWaylandShm> mShm;
QList<QWaylandScreen *> mWaitingScreens;
QList<QWaylandScreen *> mScreens;
+ QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
QList<QWaylandInputDevice *> mInputDevices;
QList<Listener> mRegistryListeners;
QWaylandIntegration *mWaylandIntegration = nullptr;
@@ -243,6 +249,7 @@ private:
QScopedPointer<QWaylandTouchExtension> mTouchExtension;
QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
+ QScopedPointer<QWaylandTabletManagerV2> mTabletManager;
#if QT_CONFIG(wayland_client_primary_selection)
QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
#endif
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index a9da452dc..e0f0c6c8e 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -50,6 +50,7 @@
#if QT_CONFIG(wayland_client_primary_selection)
#include "qwaylandprimaryselectionv1_p.h"
#endif
+#include "qwaylandtabletv2_p.h"
#include "qwaylandtouch_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
@@ -88,7 +89,7 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
// or the server didn't send an enter event first.
return;
}
- mRepeatTimer.setInterval(mRepeatRate);
+ mRepeatTimer.setInterval(1000 / mRepeatRate);
handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers,
mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
mRepeatKey.text, true);
@@ -143,6 +144,12 @@ QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const
QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
: mParent(seat)
{
+#if QT_CONFIG(cursor)
+ mCursor.frameTimer.setSingleShot(true);
+ mCursor.frameTimer.callOnTimeout([&]() {
+ cursorTimerCallback();
+ });
+#endif
}
QWaylandInputDevice::Pointer::~Pointer()
@@ -224,7 +231,7 @@ public:
if (animated) {
m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){
Q_UNUSED(time);
- m_pointer->updateCursor();
+ m_pointer->cursorFrameCallback();
}));
}
commit();
@@ -283,8 +290,8 @@ void QWaylandInputDevice::Pointer::updateCursorTheme()
if (!mCursor.theme)
return; // A warning has already been printed in loadCursorTheme
- if (auto *arrow = mCursor.theme->cursorImage(Qt::ArrowCursor)) {
- int arrowPixelSize = qMax(arrow->width, arrow->height); // Not all cursor themes are square
+ if (auto *arrow = mCursor.theme->cursor(Qt::ArrowCursor)) {
+ int arrowPixelSize = qMax(arrow->images[0]->width, arrow->images[0]->height); // Not all cursor themes are square
while (scale > 1 && arrowPixelSize / scale < cursorSize())
--scale;
} else {
@@ -326,12 +333,26 @@ void QWaylandInputDevice::Pointer::updateCursor()
// Set from shape using theme
uint time = seat()->mCursor.animationTimer.elapsed();
- if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) {
+
+ if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
+ uint duration = 0;
+ int frame = wl_cursor_frame_and_duration(waylandCursor, time, &duration);
+ ::wl_cursor_image *image = waylandCursor->images[frame];
+
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer) {
+ qCWarning(lcQpaWayland) << "Could not find buffer for cursor" << shape;
+ return;
+ }
int bufferScale = mCursor.themeBufferScale;
QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
QSize size = QSize(image->width, image->height) / bufferScale;
- bool animated = image->delay > 0;
+ bool animated = duration > 0;
+ if (animated) {
+ mCursor.gotFrameCallback = false;
+ mCursor.gotTimerCallback = false;
+ mCursor.frameTimer.start(duration);
+ }
getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
return;
}
@@ -346,6 +367,22 @@ CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface()
return mCursor.surface.get();
}
+void QWaylandInputDevice::Pointer::cursorTimerCallback()
+{
+ mCursor.gotTimerCallback = true;
+ if (mCursor.gotFrameCallback) {
+ updateCursor();
+ }
+}
+
+void QWaylandInputDevice::Pointer::cursorFrameCallback()
+{
+ mCursor.gotFrameCallback = true;
+ if (mCursor.gotTimerCallback) {
+ updateCursor();
+ }
+}
+
#endif // QT_CONFIG(cursor)
QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p)
@@ -382,6 +419,8 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
if (mQDisplay->textInputManager())
mTextInput.reset(new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat())));
+ if (auto *tm = mQDisplay->tabletManager())
+ mTabletSeat.reset(new QWaylandTabletSeatV2(tm, this));
}
QWaylandInputDevice::~QWaylandInputDevice()
@@ -594,8 +633,8 @@ class EnterEvent : public QWaylandPointerEvent
{
public:
EnterEvent(QWaylandWindow *surface, const QPointF &local, const QPointF &global)
- : QWaylandPointerEvent(QWaylandPointerEvent::Enter, Qt::NoScrollPhase, surface, 0,
- local, global, nullptr, Qt::NoModifier)
+ : QWaylandPointerEvent(QEvent::Enter, Qt::NoScrollPhase, surface, 0,
+ local, global, Qt::NoButton, Qt::NoButton, Qt::NoModifier)
{}
};
@@ -639,8 +678,8 @@ class LeaveEvent : public QWaylandPointerEvent
{
public:
LeaveEvent(QWaylandWindow *surface, const QPointF &localPos, const QPointF &globalPos)
- : QWaylandPointerEvent(QWaylandPointerEvent::Leave, Qt::NoScrollPhase, surface, 0,
- localPos, globalPos, nullptr, Qt::NoModifier)
+ : QWaylandPointerEvent(QEvent::Leave, Qt::NoScrollPhase, surface, 0,
+ localPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier)
{}
};
@@ -669,8 +708,8 @@ class MotionEvent : public QWaylandPointerEvent
public:
MotionEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Motion, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ : QWaylandPointerEvent(QEvent::MouseMove, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, Qt::NoButton, modifiers)
{
}
};
@@ -708,9 +747,10 @@ class PressEvent : public QWaylandPointerEvent
{
public:
PressEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
- const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Press, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QEvent::MouseButtonPress, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, button, modifiers)
{
}
};
@@ -719,9 +759,10 @@ class ReleaseEvent : public QWaylandPointerEvent
{
public:
ReleaseEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
- const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Release, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QEvent::MouseButtonRelease, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, button, modifiers)
{
}
};
@@ -782,9 +823,9 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
}
if (state)
- setFrameEvent(new PressEvent(window, time, pos, global, mButtons, mParent->modifiers()));
+ setFrameEvent(new PressEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers()));
else
- setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, mParent->modifiers()));
+ setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers()));
}
void QWaylandInputDevice::Pointer::invalidateFocus()
@@ -812,7 +853,7 @@ public:
WheelEvent(QWaylandWindow *surface, Qt::ScrollPhase phase, ulong timestamp, const QPointF &local,
const QPointF &global, const QPoint &pixelDelta, const QPoint &angleDelta,
Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Wheel, phase, surface, timestamp,
+ : QWaylandPointerEvent(QEvent::Wheel, phase, surface, timestamp,
local, global, pixelDelta, angleDelta, source, modifiers)
{
}
@@ -968,6 +1009,8 @@ bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const
case axis_source_finger:
case axis_source_continuous:
return !delta.isNull();
+ default:
+ return false;
}
}
@@ -1048,11 +1091,13 @@ void QWaylandInputDevice::Pointer::flushFrameEvent()
if (auto *event = mFrameData.event) {
if (auto window = event->surface) {
window->handleMouse(mParent, *event);
- } else if (mFrameData.event->type == QWaylandPointerEvent::Type::Release) {
+ } else if (mFrameData.event->type == QEvent::MouseButtonRelease) {
// If the window has been destroyed, we still need to report an up event, but it can't
// be handled by the destroyed window (obviously), so send the event here instead.
QWindowSystemInterface::handleMouseEvent(nullptr, event->timestamp, event->local,
- event->global, event->buttons, event->modifiers);
+ event->global, event->buttons,
+ event->button, event->type,
+ event->modifiers);// , Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
}
delete mFrameData.event;
mFrameData.event = nullptr;
@@ -1351,7 +1396,7 @@ void QWaylandInputDevice::Touch::touch_cancel()
void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition)
{
auto end = mTouch->mPendingTouchPoints.end();
- auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](auto tp){ return tp.id == id; });
+ auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](const QWindowSystemInterface::TouchPoint &tp){ return tp.id == id; });
if (it == end) {
it = mTouch->mPendingTouchPoints.insert(end, QWindowSystemInterface::TouchPoint());
it->id = id;
@@ -1372,8 +1417,7 @@ void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, co
return;
tp.area = QRectF(0, 0, 8, 8);
- QMargins margins = win->frameMargins();
- QPointF localPosition = surfacePosition - QPointF(margins.left(), margins.top());
+ QPointF localPosition = win->mapFromWlSurface(surfacePosition);
// TODO: This doesn't account for high dpi scaling for the delta, but at least it matches
// what we have for mouse input.
QPointF delta = localPosition - localPosition.toPoint();
@@ -1381,7 +1425,10 @@ void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, co
tp.area.moveCenter(globalPosition);
}
- tp.state = state;
+ // If the touch point was pressed earlier this frame, we don't want to overwrite its state.
+ if (tp.state != Qt::TouchPointPressed)
+ tp.state = state;
+
tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
}
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 60d6f2c17..448d0fce5 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -89,6 +89,7 @@ class QWaylandDisplay;
#if QT_CONFIG(wayland_client_primary_selection)
class QWaylandPrimarySelectionDeviceV1;
#endif
+class QWaylandTabletSeatV2;
class QWaylandTextInput;
#if QT_CONFIG(cursor)
class QWaylandCursorTheme;
@@ -127,6 +128,9 @@ public:
QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice() const;
#endif
+ void setTabletSeat(QWaylandTabletSeatV2 *tabletSeat);
+ QWaylandTabletSeatV2* tabletSeat() const;
+
void setTextInput(QWaylandTextInput *textInput);
QWaylandTextInput *textInput() const;
@@ -183,6 +187,7 @@ private:
Touch *mTouch = nullptr;
QScopedPointer<QWaylandTextInput> mTextInput;
+ QScopedPointer<QWaylandTabletSeatV2> mTabletSeat;
uint32_t mTime = 0;
uint32_t mSerial = 0;
@@ -286,6 +291,8 @@ public:
int idealCursorScale() const;
void updateCursorTheme();
void updateCursor();
+ void cursorTimerCallback();
+ void cursorFrameCallback();
CursorSurface *getOrCreateCursorSurface();
#endif
QWaylandInputDevice *seat() const { return mParent; }
@@ -325,6 +332,9 @@ public:
QWaylandCursorTheme *theme = nullptr;
int themeBufferScale = 0;
QScopedPointer<CursorSurface> surface;
+ QTimer frameTimer;
+ bool gotFrameCallback = false;
+ bool gotTimerCallback = false;
} mCursor;
#endif
QPointF mSurfacePos;
@@ -396,29 +406,21 @@ class QWaylandPointerEvent
{
Q_GADGET
public:
- enum Type {
- Enter,
- Leave,
- Motion,
- Press,
- Release,
- Wheel
- };
- Q_ENUM(Type)
-
- inline QWaylandPointerEvent(Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
+ inline QWaylandPointerEvent(QEvent::Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
ulong timestamp, const QPointF &localPos, const QPointF &globalPos,
- Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
: type(type)
, phase(phase)
, timestamp(timestamp)
, local(localPos)
, global(globalPos)
, buttons(buttons)
+ , button(button)
, modifiers(modifiers)
, surface(surface)
{}
- inline QWaylandPointerEvent(Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
+ inline QWaylandPointerEvent(QEvent::Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
ulong timestamp, const QPointF &local, const QPointF &global,
const QPoint &pixelDelta, const QPoint &angleDelta,
Qt::MouseEventSource source,
@@ -435,12 +437,13 @@ public:
, surface(surface)
{}
- Type type;
+ QEvent::Type type = QEvent::None;
Qt::ScrollPhase phase = Qt::NoScrollPhase;
ulong timestamp = 0;
QPointF local;
QPointF global;
Qt::MouseButtons buttons;
+ Qt::MouseButton button = Qt::NoButton; // Button that caused the event (QMouseEvent::button)
Qt::KeyboardModifiers modifiers;
QPoint pixelDelta;
QPoint angleDelta;
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 9bdd9cc12..85c1990b6 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -165,10 +165,10 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) cons
#if QT_CONFIG(vulkan)
if (window->surfaceType() == QSurface::VulkanSurface)
- return new QWaylandVulkanWindow(window);
+ return new QWaylandVulkanWindow(window, mDisplay.data());
#endif // QT_CONFIG(vulkan)
- return new QWaylandShmWindow(window);
+ return new QWaylandShmWindow(window, mDisplay.data());
}
#if QT_CONFIG(opengl)
@@ -182,7 +182,7 @@ QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGL
QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
- return new QWaylandShmBackingStore(window);
+ return new QWaylandShmBackingStore(window, mDisplay.data());
}
QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
@@ -200,10 +200,8 @@ void QWaylandIntegration::initialize()
QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data());
QObject::connect(sn, SIGNAL(activated(int)), mDisplay.data(), SLOT(flushRequests()));
- if (mDisplay->screens().isEmpty()) {
- qWarning() << "Running on a compositor with no screens is not supported";
- ::exit(EXIT_FAILURE);
- }
+ // Qt does not support running with no screens
+ mDisplay->ensureScreen();
}
QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
@@ -427,6 +425,8 @@ void QWaylandIntegration::initializeShellIntegration()
qCWarning(lcQpaWayland) << "Loading shell integration failed.";
qCWarning(lcQpaWayland) << "Attempted to load the following shells" << preferredShells;
}
+
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
}
QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id)
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index e70796832..4f0cd9b0a 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -165,11 +165,18 @@ QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const
{
QList<QPlatformScreen *> list;
const QList<QWaylandScreen*> screens = mWaylandDisplay->screens();
- list.reserve(screens.count());
+ auto *placeholder = mWaylandDisplay->placeholderScreen();
+
+ list.reserve(screens.count() + (placeholder ? 1 : 0));
+
for (QWaylandScreen *screen : qAsConst(screens)) {
if (screen->screen())
list << screen;
}
+
+ if (placeholder)
+ list << placeholder;
+
return list;
}
@@ -210,9 +217,11 @@ QPlatformCursor *QWaylandScreen::cursor() const
}
#endif // QT_CONFIG(cursor)
-QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
+QWaylandScreen *QWaylandScreen::waylandScreenFromWindow(QWindow *window)
{
QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(window);
+ if (platformScreen->isPlaceholder())
+ return nullptr;
return static_cast<QWaylandScreen *>(platformScreen);
}
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index e9e07d9cd..ae91c6211 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -57,7 +57,6 @@
#include <QtWaylandClient/private/qwayland-wayland.h>
#include <QtWaylandClient/private/qwayland-xdg-output-unstable-v1.h>
-
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index 9b5971a21..8d5b977d5 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -151,9 +151,9 @@ QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &marginsIn)
}
-QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
+QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window, QWaylandDisplay *display)
: QPlatformBackingStore(window)
- , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
+ , mDisplay(display)
{
}
diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h
index 8a85cd7f3..e01632daf 100644
--- a/src/client/qwaylandshmbackingstore_p.h
+++ b/src/client/qwaylandshmbackingstore_p.h
@@ -88,7 +88,7 @@ private:
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingStore
{
public:
- QWaylandShmBackingStore(QWindow *window);
+ QWaylandShmBackingStore(QWindow *window, QWaylandDisplay *display);
~QWaylandShmBackingStore() override;
QPaintDevice *paintDevice() override;
diff --git a/src/client/qwaylandshmwindow.cpp b/src/client/qwaylandshmwindow.cpp
index 52833803d..e305d028d 100644
--- a/src/client/qwaylandshmwindow.cpp
+++ b/src/client/qwaylandshmwindow.cpp
@@ -49,8 +49,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandShmWindow::QWaylandShmWindow(QWindow *window)
- : QWaylandWindow(window)
+QWaylandShmWindow::QWaylandShmWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
{
}
diff --git a/src/client/qwaylandshmwindow_p.h b/src/client/qwaylandshmwindow_p.h
index ae1727859..81251b3aa 100644
--- a/src/client/qwaylandshmwindow_p.h
+++ b/src/client/qwaylandshmwindow_p.h
@@ -61,7 +61,7 @@ namespace QtWaylandClient {
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow
{
public:
- QWaylandShmWindow(QWindow *window);
+ QWaylandShmWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandShmWindow() override;
WindowType windowType() const override;
diff --git a/src/client/qwaylandsurface.cpp b/src/client/qwaylandsurface.cpp
index c35f01b56..21e70ce4f 100644
--- a/src/client/qwaylandsurface.cpp
+++ b/src/client/qwaylandsurface.cpp
@@ -72,8 +72,12 @@ QWaylandSurface *QWaylandSurface::fromWlSurface(::wl_surface *surface)
void QWaylandSurface::handleScreenRemoved(QScreen *qScreen)
{
- auto *screen = static_cast<QWaylandScreen *>(qScreen->handle());
- if (m_screens.removeOne(screen))
+ auto *platformScreen = qScreen->handle();
+ if (platformScreen->isPlaceholder())
+ return;
+
+ auto *waylandScreen = static_cast<QWaylandScreen *>(qScreen->handle());
+ if (m_screens.removeOne(waylandScreen))
emit screensChanged();
}
diff --git a/src/client/qwaylandtabletv2.cpp b/src/client/qwaylandtabletv2.cpp
new file mode 100644
index 000000000..eb2e865f6
--- /dev/null
+++ b/src/client/qwaylandtabletv2.cpp
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandtabletv2_p.h"
+#include "qwaylandinputdevice_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandsurface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandTabletManagerV2::QWaylandTabletManagerV2(QWaylandDisplay *display, uint id, uint version)
+ : zwp_tablet_manager_v2(display->wl_registry(), id, qMin(version, uint(1)))
+{
+ // Create tabletSeats for all seats.
+ // This only works if we get the manager after all seats
+ const auto seats = display->inputDevices();
+ for (auto *seat : seats)
+ createTabletSeat(seat);
+}
+
+QWaylandTabletSeatV2 *QWaylandTabletManagerV2::createTabletSeat(QWaylandInputDevice *seat)
+{
+ return new QWaylandTabletSeatV2(this, seat);
+}
+
+QWaylandTabletSeatV2::QWaylandTabletSeatV2(QWaylandTabletManagerV2 *manager, QWaylandInputDevice *seat)
+ : QtWayland::zwp_tablet_seat_v2(manager->get_tablet_seat(seat->wl_seat()))
+{
+}
+
+QWaylandTabletSeatV2::~QWaylandTabletSeatV2()
+{
+ for (auto *tablet : m_tablets)
+ tablet->destroy();
+ for (auto *tool : m_tools)
+ tool->destroy();
+ for (auto *pad : m_pads)
+ pad->destroy();
+ destroy();
+}
+
+void QWaylandTabletSeatV2::zwp_tablet_seat_v2_tablet_added(zwp_tablet_v2 *id)
+{
+ auto *tablet = new QWaylandTabletV2(id);
+ m_tablets.push_back(tablet);
+ connect(tablet, &QWaylandTabletV2::destroyed, this, [this, tablet] { m_tablets.removeOne(tablet); });
+}
+
+void QWaylandTabletSeatV2::zwp_tablet_seat_v2_tool_added(zwp_tablet_tool_v2 *id)
+{
+ auto *tool = new QWaylandTabletToolV2(id);
+ m_tools.push_back(tool);
+ connect(tool, &QWaylandTabletToolV2::destroyed, this, [this, tool] { m_tools.removeOne(tool); });
+}
+
+void QWaylandTabletSeatV2::zwp_tablet_seat_v2_pad_added(zwp_tablet_pad_v2 *id)
+{
+ auto *pad = new QWaylandTabletPadV2(id);
+ m_pads.push_back(pad);
+ connect(pad, &QWaylandTabletPadV2::destroyed, this, [this, pad] { m_pads.removeOne(pad); });
+}
+
+QWaylandTabletV2::QWaylandTabletV2(::zwp_tablet_v2 *tablet)
+ : QtWayland::zwp_tablet_v2(tablet)
+{
+}
+
+void QWaylandTabletV2::zwp_tablet_v2_removed()
+{
+ destroy();
+ delete this;
+}
+
+QWaylandTabletToolV2::QWaylandTabletToolV2(::zwp_tablet_tool_v2 *tool)
+ : QtWayland::zwp_tablet_tool_v2(tool)
+{
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_type(uint32_t tool_type)
+{
+ m_toolType = type(tool_type);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_hardware_serial(uint32_t hardware_serial_hi, uint32_t hardware_serial_lo)
+{
+ m_uid = (quint64(hardware_serial_hi) << 32) + hardware_serial_lo;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_capability(uint32_t capability)
+{
+ if (capability == capability_rotation)
+ m_hasRotation = true;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_done()
+{
+ switch (m_toolType) {
+ case type::type_airbrush:
+ case type::type_brush:
+ case type::type_pencil:
+ case type::type_pen:
+ m_pointerType = QTabletEvent::PointerType::Pen;
+ break;
+ case type::type_eraser:
+ m_pointerType = QTabletEvent::PointerType::Eraser;
+ break;
+ case type::type_mouse:
+ case type::type_lens:
+ m_pointerType = QTabletEvent::PointerType::Cursor;
+ break;
+ case type::type_finger:
+ m_pointerType = QTabletEvent::PointerType::UnknownPointer;
+ break;
+ }
+ switch (m_toolType) {
+ case type::type_airbrush:
+ m_tabletDevice = QTabletEvent::TabletDevice::Airbrush;
+ break;
+ case type::type_brush:
+ case type::type_pencil:
+ case type::type_pen:
+ case type::type_eraser:
+ m_tabletDevice = m_hasRotation ? QTabletEvent::TabletDevice::RotationStylus : QTabletEvent::TabletDevice::Stylus;
+ break;
+ case type::type_lens:
+ m_tabletDevice = QTabletEvent::TabletDevice::Puck;
+ break;
+ case type::type_mouse:
+ case type::type_finger:
+ m_tabletDevice = QTabletEvent::TabletDevice::NoDevice;
+ break;
+ }
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_removed()
+{
+ destroy();
+ delete this;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_proximity_in(uint32_t serial, zwp_tablet_v2 *tablet, wl_surface *surface)
+{
+ Q_UNUSED(tablet);
+ Q_UNUSED(serial);
+ if (Q_UNLIKELY(!surface)) {
+ qCDebug(lcQpaWayland) << "Ignoring zwp_tablet_tool_v2_proximity_v2 with no surface";
+ return;
+ }
+ m_pending.enteredSurface = true;
+ m_pending.proximitySurface = QWaylandSurface::fromWlSurface(surface);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_proximity_out()
+{
+ m_pending.enteredSurface = false;
+ m_pending.proximitySurface = nullptr;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_down(uint32_t serial)
+{
+ Q_UNUSED(serial);
+ m_pending.down = true;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_up()
+{
+ m_pending.down = false;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_motion(wl_fixed_t x, wl_fixed_t y)
+{
+ m_pending.surfacePosition = QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y));
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_pressure(uint32_t pressure)
+{
+ const int maxPressure = 65535;
+ m_pending.pressure = qreal(pressure)/maxPressure;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_distance(uint32_t distance)
+{
+ m_pending.distance = distance;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_tilt(wl_fixed_t tilt_x, wl_fixed_t tilt_y)
+{
+ m_pending.xTilt = wl_fixed_to_double(tilt_x);
+ m_pending.yTilt = wl_fixed_to_double(tilt_y);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_rotation(wl_fixed_t degrees)
+{
+ m_pending.rotation = wl_fixed_to_double(degrees);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_slider(int32_t position)
+{
+ m_pending.slider = qreal(position) / 65535;
+}
+
+static Qt::MouseButton mouseButtonFromTablet(uint button)
+{
+ switch (button) {
+ case 0x110: return Qt::MouseButton::LeftButton; // BTN_LEFT
+ case 0x14b: return Qt::MouseButton::MiddleButton; // BTN_STYLUS
+ case 0x14c: return Qt::MouseButton::RightButton; // BTN_STYLUS2
+ default:
+ return Qt::NoButton;
+ }
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_button(uint32_t serial, uint32_t button, uint32_t state)
+{
+ Q_UNUSED(serial);
+ Qt::MouseButton mouseButton = mouseButtonFromTablet(button);
+ if (state == button_state_pressed)
+ m_pending.buttons |= mouseButton;
+ else
+ m_pending.buttons &= ~mouseButton;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_frame(uint32_t time)
+{
+ if (m_pending.proximitySurface && !m_applied.proximitySurface) {
+ QWindowSystemInterface::handleTabletEnterProximityEvent(m_tabletDevice, m_pointerType, m_uid);
+ m_applied.proximitySurface = m_pending.proximitySurface;
+ }
+
+ if (!(m_pending == m_applied) && m_pending.proximitySurface) {
+ if (!m_pending.proximitySurface) {
+ qCWarning(lcQpaWayland) << "Can't send tablet event with no proximity surface, ignoring";
+ return;
+ }
+ QWaylandWindow *waylandWindow = QWaylandWindow::fromWlSurface(m_pending.proximitySurface->object());
+ QWindow *window = waylandWindow->window();
+ ulong timestamp = time;
+ const QPointF localPosition = waylandWindow->mapFromWlSurface(m_pending.surfacePosition);
+
+ QPointF delta = localPosition - localPosition.toPoint();
+ QPointF globalPosition = window->mapToGlobal(localPosition.toPoint());
+ globalPosition += delta;
+
+ Qt::MouseButtons buttons = m_pending.down ? Qt::MouseButton::LeftButton : Qt::MouseButton::NoButton;
+ buttons |= m_pending.buttons;
+ qreal pressure = m_pending.pressure;
+ int xTilt = int(m_pending.xTilt);
+ int yTilt = int(m_pending.yTilt);
+ qreal tangentialPressure = m_pending.slider;
+ qreal rotation = m_pending.rotation;
+ int z = int(m_pending.distance);
+ QWindowSystemInterface::handleTabletEvent(window, timestamp, localPosition, globalPosition,
+ m_tabletDevice, m_pointerType, buttons, pressure,
+ xTilt, yTilt, tangentialPressure, rotation, z, m_uid);
+ }
+
+ if (!m_pending.proximitySurface && m_applied.enteredSurface) {
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(m_tabletDevice, m_pointerType, m_uid);
+ m_pending = State(); // Don't leave pressure etc. lying around when we enter the next surface
+ }
+
+ m_applied = m_pending;
+}
+
+// TODO: delete when upgrading to c++20
+bool QWaylandTabletToolV2::State::operator==(const QWaylandTabletToolV2::State &o) const {
+ return
+ down == o.down &&
+ proximitySurface.data() == o.proximitySurface.data() &&
+ enteredSurface == o.enteredSurface &&
+ surfacePosition == o.surfacePosition &&
+ distance == o.distance &&
+ pressure == o.pressure &&
+ rotation == o.rotation &&
+ xTilt == o.xTilt &&
+ yTilt == o.yTilt &&
+ slider == o.slider &&
+ buttons == o.buttons;
+}
+
+QWaylandTabletPadV2::QWaylandTabletPadV2(::zwp_tablet_pad_v2 *pad)
+ : QtWayland::zwp_tablet_pad_v2(pad)
+{
+}
+
+void QWaylandTabletPadV2::zwp_tablet_pad_v2_removed()
+{
+ destroy();
+ delete this;
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandtabletv2_p.h b/src/client/qwaylandtabletv2_p.h
new file mode 100644
index 000000000..b4daaf5db
--- /dev/null
+++ b/src/client/qwaylandtabletv2_p.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDTABLETV2_P_H
+#define QWAYLANDTABLETV2_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtWaylandClient/private/qwayland-tablet-unstable-v2.h>
+
+#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
+
+#include <QtGui/QTabletEvent>
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QPointF>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+class QWaylandInputDevice;
+class QWaylandSurface;
+
+class QWaylandTabletSeatV2;
+class QWaylandTabletV2;
+class QWaylandTabletToolV2;
+class QWaylandTabletPadV2;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletManagerV2 : public QtWayland::zwp_tablet_manager_v2
+{
+public:
+ explicit QWaylandTabletManagerV2(QWaylandDisplay *display, uint id, uint version);
+ QWaylandTabletSeatV2 *createTabletSeat(QWaylandInputDevice *seat);
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletSeatV2 : public QObject, public QtWayland::zwp_tablet_seat_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletSeatV2(QWaylandTabletManagerV2 *manager, QWaylandInputDevice *seat);
+ ~QWaylandTabletSeatV2() override;
+
+protected:
+ void zwp_tablet_seat_v2_tablet_added(struct ::zwp_tablet_v2 *id) override;
+ void zwp_tablet_seat_v2_tool_added(struct ::zwp_tablet_tool_v2 *id) override;
+ void zwp_tablet_seat_v2_pad_added(struct ::zwp_tablet_pad_v2 *id) override;
+
+private:
+ QVector<QWaylandTabletV2 *> m_tablets;
+ QVector<QWaylandTabletToolV2 *> m_tools;
+ QVector<QWaylandTabletPadV2 *> m_pads;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletV2 : public QObject, public QtWayland::zwp_tablet_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletV2(::zwp_tablet_v2 *tablet);
+
+protected:
+// void zwp_tablet_v2_name(const QString &name) override;
+// void zwp_tablet_v2_id(uint32_t vid, uint32_t pid) override;
+// void zwp_tablet_v2_path(const QString &path) override;
+// void zwp_tablet_v2_done() override;
+ void zwp_tablet_v2_removed() override;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletToolV2 : public QObject, public QtWayland::zwp_tablet_tool_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletToolV2(::zwp_tablet_tool_v2 *tool);
+
+protected:
+ void zwp_tablet_tool_v2_type(uint32_t tool_type) override;
+ void zwp_tablet_tool_v2_hardware_serial(uint32_t hardware_serial_hi, uint32_t hardware_serial_lo) override;
+// void zwp_tablet_tool_v2_hardware_id_wacom(uint32_t hardware_id_hi, uint32_t hardware_id_lo) override;
+ void zwp_tablet_tool_v2_capability(uint32_t capability) override;
+ void zwp_tablet_tool_v2_done() override;
+ void zwp_tablet_tool_v2_removed() override;
+ void zwp_tablet_tool_v2_proximity_in(uint32_t serial, struct ::zwp_tablet_v2 *tablet, struct ::wl_surface *surface) override;
+ void zwp_tablet_tool_v2_proximity_out() override;
+ void zwp_tablet_tool_v2_down(uint32_t serial) override;
+ void zwp_tablet_tool_v2_up() override;
+ void zwp_tablet_tool_v2_motion(wl_fixed_t x, wl_fixed_t y) override;
+ void zwp_tablet_tool_v2_pressure(uint32_t pressure) override;
+ void zwp_tablet_tool_v2_distance(uint32_t distance) override;
+ void zwp_tablet_tool_v2_tilt(wl_fixed_t tilt_x, wl_fixed_t tilt_y) override;
+ void zwp_tablet_tool_v2_rotation(wl_fixed_t degrees) override;
+ void zwp_tablet_tool_v2_slider(int32_t position) override;
+// void zwp_tablet_tool_v2_wheel(wl_fixed_t degrees, int32_t clicks) override;
+ void zwp_tablet_tool_v2_button(uint32_t serial, uint32_t button, uint32_t state) override;
+ void zwp_tablet_tool_v2_frame(uint32_t time) override;
+
+private:
+
+ // Static state (sent before done event)
+ QTabletEvent::PointerType m_pointerType = QTabletEvent::PointerType::UnknownPointer;
+ QTabletEvent::TabletDevice m_tabletDevice = QTabletEvent::TabletDevice::NoDevice;
+ type m_toolType = type_pen;
+ bool m_hasRotation = false;
+ quint64 m_uid = 0;
+
+ // Accumulated state (applied on frame event)
+ struct State {
+ bool down = false;
+ QPointer<QWaylandSurface> proximitySurface;
+ bool enteredSurface = false; // Not enough with just proximitySurface, if the surface is deleted, we still want to send a leave event
+ QPointF surfacePosition;
+ uint distance = 0;
+ qreal pressure = 0;
+ qreal rotation = 0;
+ qreal xTilt = 0;
+ qreal yTilt = 0;
+ qreal slider = 0;
+ Qt::MouseButtons buttons = Qt::MouseButton::NoButton; // Actual buttons, down state -> left mouse is mapped inside the frame handler
+ //auto operator<=>(const Point&) const = default; // TODO: use this when upgrading to C++20
+ bool operator==(const State &o) const;
+ } m_pending, m_applied;
+};
+
+// We don't actually use this, but need to handle the "removed" event to comply with the protocol
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletPadV2 : public QObject, public QtWayland::zwp_tablet_pad_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletPadV2(::zwp_tablet_pad_v2 *pad);
+
+protected:
+// void zwp_tablet_pad_v2_group(struct ::zwp_tablet_pad_group_v2 *pad_group) override;
+// void zwp_tablet_pad_v2_path(const QString &path) override;
+// void zwp_tablet_pad_v2_buttons(uint32_t buttons) override;
+// void zwp_tablet_pad_v2_done() override;
+// void zwp_tablet_pad_v2_button(uint32_t time, uint32_t button, uint32_t state) override;
+// void zwp_tablet_pad_v2_enter(uint32_t serial, struct ::zwp_tablet_v2 *tablet, struct ::wl_surface *surface) override;
+// void zwp_tablet_pad_v2_leave(uint32_t serial, struct ::wl_surface *surface) override;
+ void zwp_tablet_pad_v2_removed() override;
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTABLETV2_P_H
diff --git a/src/client/qwaylandtouch.cpp b/src/client/qwaylandtouch.cpp
index 0394aef31..8f56e7aa6 100644
--- a/src/client/qwaylandtouch.cpp
+++ b/src/client/qwaylandtouch.cpp
@@ -165,22 +165,28 @@ void QWaylandTouchExtension::sendTouchEvent()
QWindowSystemInterface::handleTouchEvent(mTargetWindow, mTimestamp, mTouchDevice, mTouchPoints);
- Qt::TouchPointStates states = 0;
+ Qt::TouchPointStates states = {};
for (int i = 0; i < mTouchPoints.count(); ++i)
states |= mTouchPoints.at(i).state;
if (mFlags & QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH) {
- if (states == Qt::TouchPointPressed)
+ const bool firstPress = states == Qt::TouchPointPressed;
+ if (firstPress)
mMouseSourceId = mTouchPoints.first().id;
for (int i = 0; i < mTouchPoints.count(); ++i) {
const QWindowSystemInterface::TouchPoint &tp(mTouchPoints.at(i));
if (tp.id == mMouseSourceId) {
- Qt::MouseButtons buttons = tp.state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton;
+ const bool released = tp.state == Qt::TouchPointReleased;
+ Qt::MouseButtons buttons = released ? Qt::NoButton : Qt::LeftButton;
+ QEvent::Type eventType = firstPress ? QEvent::MouseButtonPress
+ : released ? QEvent::MouseButtonRelease
+ : QEvent::MouseMove;
mLastMouseGlobal = tp.area.center();
QPoint globalPoint = mLastMouseGlobal.toPoint();
QPointF delta = mLastMouseGlobal - globalPoint;
mLastMouseLocal = mTargetWindow->mapFromGlobal(globalPoint) + delta;
- QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, buttons);
+ QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal,
+ buttons, Qt::LeftButton, eventType);
if (buttons == Qt::NoButton)
mMouseSourceId = -1;
break;
@@ -200,7 +206,7 @@ void QWaylandTouchExtension::touchCanceled()
mTouchPoints.clear();
mPrevTouchPoints.clear();
if (mMouseSourceId != -1)
- QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, Qt::NoButton);
+ QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease);
}
void QWaylandTouchExtension::touch_extension_configure(uint32_t flags)
diff --git a/src/client/qwaylandvulkanwindow.cpp b/src/client/qwaylandvulkanwindow.cpp
index 4c67b6b32..eb341529a 100644
--- a/src/client/qwaylandvulkanwindow.cpp
+++ b/src/client/qwaylandvulkanwindow.cpp
@@ -43,8 +43,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandVulkanWindow::QWaylandVulkanWindow(QWindow *window)
- : QWaylandWindow(window)
+QWaylandVulkanWindow::QWaylandVulkanWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
{
}
diff --git a/src/client/qwaylandvulkanwindow_p.h b/src/client/qwaylandvulkanwindow_p.h
index d0b2de75d..3fd394e62 100644
--- a/src/client/qwaylandvulkanwindow_p.h
+++ b/src/client/qwaylandvulkanwindow_p.h
@@ -50,7 +50,7 @@ namespace QtWaylandClient {
class QWaylandVulkanWindow : public QWaylandWindow
{
public:
- explicit QWaylandVulkanWindow(QWindow *window);
+ explicit QWaylandVulkanWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandVulkanWindow() override;
WindowType windowType() const override;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 950486c0c..8cc26d71c 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -73,9 +73,9 @@ Q_LOGGING_CATEGORY(lcWaylandBackingstore, "qt.qpa.wayland.backingstore")
QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
-QWaylandWindow::QWaylandWindow(QWindow *window)
+QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
: QPlatformWindow(window)
- , mDisplay(waylandScreen()->display())
+ , mDisplay(display)
, mFrameQueue(mDisplay->createEventQueue())
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
{
@@ -177,7 +177,7 @@ void QWaylandWindow::initWindow()
}
}
- mScale = waylandScreen()->scale();
+ mScale = waylandScreen() ? waylandScreen()->scale() : 1; // fallback to 1 if we don't have a real screen
// Enable high-dpi rendering. Scale() returns the screen scale factor and will
// typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
@@ -402,14 +402,14 @@ void QWaylandWindow::closePopups(QWaylandWindow *parent)
}
}
-QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
+QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
{
if (mSurface) {
if (auto *screen = mSurface->oldestEnteredScreen())
return screen;
}
- return waylandScreen();
+ return QPlatformWindow::screen();
}
void QWaylandWindow::setVisible(bool visible)
@@ -426,8 +426,7 @@ void QWaylandWindow::setVisible(bool visible)
// QWaylandShmBackingStore::beginPaint().
} else {
sendExposeEvent(QRect());
- if (window()->type() == Qt::Popup)
- closePopups(this);
+ closePopups(this);
reset();
}
}
@@ -673,6 +672,19 @@ QRect QWaylandWindow::windowContentGeometry() const
return QRect(QPoint(), surfaceSize());
}
+/*!
+ * Converts from wl_surface coordinates to Qt window coordinates. Qt window
+ * coordinates start inside (not including) the window decorations, while
+ * wl_surface coordinates start at the first pixel of the buffer. Potentially,
+ * this should be in the window shadow, although we don't have those. So for
+ * now, it's the first pixel of the decorations.
+ */
+QPointF QWaylandWindow::mapFromWlSurface(const QPointF &surfacePosition) const
+{
+ const QMargins margins = frameMargins();
+ return QPointF(surfacePosition.x() - margins.left(), surfacePosition.y() - margins.top());
+}
+
wl_surface *QWaylandWindow::wlSurface()
{
return mSurface ? mSurface->object() : nullptr;
@@ -690,7 +702,11 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
QWaylandScreen *QWaylandWindow::waylandScreen() const
{
- return static_cast<QWaylandScreen *>(QPlatformWindow::screen());
+ auto *platformScreen = QPlatformWindow::screen();
+ Q_ASSERT(platformScreen);
+ if (platformScreen->isPlaceholder())
+ return nullptr;
+ return static_cast<QWaylandScreen *>(platformScreen);
}
void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
@@ -853,7 +869,7 @@ QWaylandWindow *QWaylandWindow::transientParent() const
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{
- if (e.type == QWaylandPointerEvent::Leave) {
+ if (e.type == QEvent::Leave) {
if (mWindowDecoration) {
if (mMouseEventsInContentArea)
QWindowSystemInterface::handleLeaveEvent(window());
@@ -870,24 +886,26 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
handleMouseEventWithDecoration(inputDevice, e);
} else {
switch (e.type) {
- case QWaylandPointerEvent::Enter:
+ case QEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), e.local, e.global);
break;
- case QWaylandPointerEvent::Press:
- case QWaylandPointerEvent::Release:
- case QWaylandPointerEvent::Motion:
- QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, e.local, e.global, e.buttons, e.modifiers);
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, e.local, e.global, e.buttons, e.button, e.type, e.modifiers);
break;
- case QWaylandPointerEvent::Wheel:
+ case QEvent::Wheel:
QWindowSystemInterface::handleWheelEvent(window(), e.timestamp, e.local, e.global,
e.pixelDelta, e.angleDelta, e.modifiers,
e.phase, e.source, false);
break;
+ default:
+ Q_UNREACHABLE();
}
}
#if QT_CONFIG(cursor)
- if (e.type == QWaylandPointerEvent::Enter) {
+ if (e.type == QEvent::Enter) {
QRect contentGeometry = windowContentGeometry().marginsRemoved(frameMargins());
if (contentGeometry.contains(e.local.toPoint()))
restoreMouseCursor(inputDevice);
@@ -919,10 +937,8 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
geometry().size().width() - marg.right(),
geometry().size().height() - marg.bottom());
if (windowRect.contains(e.local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
- QPointF localTranslated = e.local;
+ const QPointF localTranslated = mapFromWlSurface(e.local);
QPointF globalTranslated = e.global;
- localTranslated.setX(localTranslated.x() - marg.left());
- localTranslated.setY(localTranslated.y() - marg.top());
globalTranslated.setX(globalTranslated.x() - marg.left());
globalTranslated.setY(globalTranslated.y() - marg.top());
if (!mMouseEventsInContentArea) {
@@ -933,21 +949,23 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
}
switch (e.type) {
- case QWaylandPointerEvent::Enter:
+ case QEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), localTranslated, globalTranslated);
break;
- case QWaylandPointerEvent::Press:
- case QWaylandPointerEvent::Release:
- case QWaylandPointerEvent::Motion:
- QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.modifiers);
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.button, e.type, e.modifiers);
break;
- case QWaylandPointerEvent::Wheel: {
+ case QEvent::Wheel: {
QWindowSystemInterface::handleWheelEvent(window(), e.timestamp,
localTranslated, globalTranslated,
e.pixelDelta, e.angleDelta, e.modifiers,
e.phase, e.source, false);
break;
}
+ default:
+ Q_UNREACHABLE();
}
mMouseEventsInContentArea = true;
@@ -962,7 +980,7 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
void QWaylandWindow::handleScreensChanged()
{
- QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
+ QPlatformScreen *newScreen = calculateScreenFromSurfaceEvents();
if (newScreen == mLastReportedScreen)
return;
@@ -970,7 +988,7 @@ void QWaylandWindow::handleScreensChanged()
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
mLastReportedScreen = newScreen;
- int scale = newScreen->scale();
+ int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale();
if (scale != mScale) {
mScale = scale;
if (mSurface && mDisplay->compositorVersion() >= 3)
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index c488c2e3f..35fa1fdfc 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -93,7 +93,7 @@ public:
Vulkan
};
- QWaylandWindow(QWindow *window);
+ QWaylandWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandWindow() override;
virtual WindowType windowType() const = 0;
@@ -129,6 +129,7 @@ public:
QMargins frameMargins() const override;
QSize surfaceSize() const;
QRect windowContentGeometry() const;
+ QPointF mapFromWlSurface(const QPointF &surfacePosition) const;
QWaylandSurface *waylandSurface() const { return mSurface.data(); }
::wl_surface *wlSurface();
@@ -241,7 +242,7 @@ protected:
bool mSentInitialResize = false;
QPoint mOffset;
int mScale = 1;
- QWaylandScreen *mLastReportedScreen = nullptr;
+ QPlatformScreen *mLastReportedScreen = nullptr;
QIcon mWindowIcon;
@@ -262,7 +263,7 @@ private:
void reset(bool sendDestroyEvent = true);
void sendExposeEvent(const QRect &rect);
static void closePopups(QWaylandWindow *parent);
- QWaylandScreen *calculateScreenFromSurfaceEvents() const;
+ QPlatformScreen *calculateScreenFromSurfaceEvents() const;
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
void handleScreensChanged();