summaryrefslogtreecommitdiffstats
path: root/src/compositor
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor')
-rw-r--r--src/compositor/compositor.pro4
-rw-r--r--src/compositor/compositor_api/qwaylandclient.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp32
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor_p.h13
-rw-r--r--src/compositor/compositor_api/qwaylanddestroylistener_p.h2
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.cpp143
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard_p.h15
-rw-r--r--src/compositor/compositor_api/qwaylandoutput.cpp5
-rw-r--r--src/compositor/compositor_api/qwaylandpointer.cpp6
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp12
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp73
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.h4
-rw-r--r--src/compositor/compositor_api/qwaylandseat.cpp86
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp159
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h21
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h10
-rw-r--r--src/compositor/configure.json11
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-overview.qdoc110
-rw-r--r--src/compositor/extensions/extensions.pri8
-rw-r--r--src/compositor/extensions/pregenerated/3rdparty/.gitignore3
-rw-r--r--src/compositor/extensions/pregenerated/3rdparty/qwayland-server-xdg-shell-unstable-v5_p.h3
-rw-r--r--src/compositor/extensions/pregenerated/3rdparty/wayland-xdg-shell-unstable-v5-server-protocol_p.h2
-rw-r--r--src/compositor/extensions/qwaylandiviapplication.cpp17
-rw-r--r--src/compositor/extensions/qwaylandivisurface.cpp9
-rw-r--r--src/compositor/extensions/qwaylandshellsurface.cpp2
-rw-r--r--src/compositor/extensions/qwaylandtextinput.cpp11
-rw-r--r--src/compositor/extensions/qwaylandviewporter.cpp243
-rw-r--r--src/compositor/extensions/qwaylandviewporter.h63
-rw-r--r--src/compositor/extensions/qwaylandviewporter_p.h93
-rw-r--r--src/compositor/extensions/qwaylandwlscaler.cpp274
-rw-r--r--src/compositor/extensions/qwaylandwlscaler.h67
-rw-r--r--src/compositor/extensions/qwaylandwlscaler_p.h93
-rw-r--r--src/compositor/extensions/qwaylandwlshell.cpp13
-rw-r--r--src/compositor/extensions/qwaylandwlshell_p.h2
-rw-r--r--src/compositor/extensions/qwaylandwlshellintegration.cpp12
-rw-r--r--src/compositor/extensions/qwaylandwlshellintegration_p.h4
-rw-r--r--src/compositor/extensions/qwaylandxdgdecorationv1.cpp10
-rw-r--r--src/compositor/extensions/qwaylandxdgshell.cpp46
-rw-r--r--src/compositor/extensions/qwaylandxdgshellintegration.cpp22
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5.cpp27
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5integration.cpp24
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5integration_p.h4
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6.cpp42
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6integration.cpp22
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6integration_p.h4
-rw-r--r--src/compositor/global/global.pri1
-rw-r--r--src/compositor/global/qwaylandcompositorextension.cpp2
-rw-r--r--src/compositor/global/qwaylandutils_p.h73
-rw-r--r--src/compositor/hardware_integration/qwlclientbufferintegration_p.h2
-rw-r--r--src/compositor/wayland_wrapper/qwlclientbuffer.cpp2
-rw-r--r--src/compositor/wayland_wrapper/qwlclientbuffer_p.h4
-rw-r--r--src/compositor/wayland_wrapper/qwldatadevicemanager_p.h2
-rw-r--r--src/compositor/wayland_wrapper/qwldatasource.cpp3
-rw-r--r--src/compositor/wayland_wrapper/qwlregion.cpp6
-rw-r--r--src/compositor/wayland_wrapper/wayland_wrapper.pri10
55 files changed, 1590 insertions, 343 deletions
diff --git a/src/compositor/compositor.pro b/src/compositor/compositor.pro
index 47be591d7..b887cf281 100644
--- a/src/compositor/compositor.pro
+++ b/src/compositor/compositor.pro
@@ -3,6 +3,10 @@ MODULE = waylandcompositor
QT = core gui-private
+qtConfig(xkbcommon) {
+ QT_FOR_PRIVATE += xkbcommon_support-private
+}
+
qtHaveModule(quick): QT += quick
CONFIG -= precompile_header
diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp
index 7f0b225b2..d26dfc6d5 100644
--- a/src/compositor/compositor_api/qwaylandclient.cpp
+++ b/src/compositor/compositor_api/qwaylandclient.cpp
@@ -44,7 +44,7 @@
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
#include <wayland-util.h>
QT_BEGIN_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index a0d69c52e..8ff9e0905 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -72,7 +72,6 @@
#include "extensions/qwaylandqtwindowmanager.h"
-#include "qwaylandxkb_p.h"
#include "qwaylandsharedmemoryformathelper_p.h"
#include <QtCore/QCoreApplication>
@@ -129,12 +128,12 @@ public:
bool isDown = ke->keyType == QEvent::KeyPress;
#if QT_CONFIG(xkbcommon)
- QString text;
- Qt::KeyboardModifiers modifiers = QWaylandXkb::modifiers(keyb->xkbState());
+ xkb_state *xkbState = keyb->xkbState();
+ Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(xkbState);
- const xkb_keysym_t sym = xkb_state_key_get_one_sym(keyb->xkbState(), code);
- int qtkey;
- std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, modifiers);
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code);
+ int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, xkbState, code);
+ QString text = QXkbCommon::lookupString(xkbState, code);
ke->key = qtkey;
ke->modifiers = modifiers;
@@ -162,12 +161,24 @@ QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *composi
{
if (QGuiApplication::platformNativeInterface())
display = static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("server_wl_display"));
- if (!display)
+
+ if (!display) {
display = wl_display_create();
+ ownsDisplay = true;
+ }
+
eventHandler.reset(new QtWayland::WindowSystemEventHandler(compositor));
timer.start();
QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data());
+
+#if QT_CONFIG(xkbcommon)
+ mXkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
+ if (!mXkbContext) {
+ qWarning("Failed to create a XKB context: keymap will not be supported");
+ return;
+ }
+#endif
}
void QWaylandCompositorPrivate::init()
@@ -246,7 +257,8 @@ QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
// Some client buffer integrations need to clean up before the destroying the wl_display
client_buffer_integration.reset();
- wl_display_destroy(display);
+ if (ownsDisplay)
+ wl_display_destroy(display);
}
void QWaylandCompositorPrivate::preInit()
@@ -586,7 +598,7 @@ QByteArray QWaylandCompositor::socketName() const
* \qmlmethod QtWaylandCompositor::WaylandCompositor::addSocketDescriptor(fd)
* \since 5.12
*
- * Listen for client connections on a file descriptor referring to a
+ * Listen for client connections on a file descriptor, \a fd, referring to a
* server socket already bound and listening.
*
* Does not take ownership of the file descriptor; it must be closed
@@ -598,7 +610,7 @@ QByteArray QWaylandCompositor::socketName() const
*/
/*!
- * Listen for client connections on a file descriptor referring to a
+ * Listen for client connections on a file descriptor, \a fd, referring to a
* server socket already bound and listening.
*
* Does not take ownership of the file descriptor; it must be closed
diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h
index cdf4be6b4..2c9624216 100644
--- a/src/compositor/compositor_api/qwaylandcompositor_p.h
+++ b/src/compositor/compositor_api/qwaylandcompositor_p.h
@@ -60,6 +60,10 @@
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
+#if QT_CONFIG(xkbcommon)
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtWayland {
@@ -81,6 +85,10 @@ public:
QWaylandCompositorPrivate(QWaylandCompositor *compositor);
~QWaylandCompositorPrivate() override;
+#if QT_CONFIG(xkbcommon)
+ struct xkb_context *xkbContext() const { return mXkbContext.get(); }
+#endif
+
void preInit();
void init();
@@ -137,6 +145,7 @@ protected:
QList<int> externally_added_socket_fds;
#endif
struct wl_display *display = nullptr;
+ bool ownsDisplay = false;
QList<QWaylandSeat *> seats;
QList<QWaylandOutput *> outputs;
@@ -168,6 +177,10 @@ protected:
bool initialized = false;
QList<QPointer<QObject> > polish_objects;
+#if QT_CONFIG(xkbcommon)
+ QXkbCommon::ScopedXKBContext mXkbContext;
+#endif
+
Q_DECLARE_PUBLIC(QWaylandCompositor)
Q_DISABLE_COPY(QWaylandCompositorPrivate)
};
diff --git a/src/compositor/compositor_api/qwaylanddestroylistener_p.h b/src/compositor/compositor_api/qwaylanddestroylistener_p.h
index 7c6001c36..0bbeb69c0 100644
--- a/src/compositor/compositor_api/qwaylanddestroylistener_p.h
+++ b/src/compositor/compositor_api/qwaylanddestroylistener_p.h
@@ -55,7 +55,7 @@
#include <QtCore/private/qobject_p.h>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
QT_BEGIN_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp
index 68d855a66..2302c0b6a 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.cpp
+++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp
@@ -54,7 +54,6 @@
#if QT_CONFIG(xkbcommon)
#include <sys/mman.h>
#include <sys/types.h>
-#include <qwaylandxkb_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -67,12 +66,11 @@ QWaylandKeyboardPrivate::QWaylandKeyboardPrivate(QWaylandSeat *seat)
QWaylandKeyboardPrivate::~QWaylandKeyboardPrivate()
{
#if QT_CONFIG(xkbcommon)
- if (xkb_context) {
+ if (xkbContext()) {
if (keymap_area)
munmap(keymap_area, keymap_size);
- close(keymap_fd);
- xkb_context_unref(xkb_context);
- xkb_state_unref(xkb_state);
+ if (keymap_fd >= 0)
+ close(keymap_fd);
}
#endif
}
@@ -137,14 +135,14 @@ void QWaylandKeyboardPrivate::keyboard_bind_resource(wl_keyboard::Resource *reso
send_repeat_info(resource->handle, repeatRate, repeatDelay);
#if QT_CONFIG(xkbcommon)
- if (xkb_context) {
+ if (xkbContext()) {
send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
keymap_fd, keymap_size);
} else
#endif
{
int null_fd = open("/dev/null", O_RDONLY);
- send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */,
+ send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
null_fd, 0);
close(null_fd);
}
@@ -164,11 +162,8 @@ void QWaylandKeyboardPrivate::keyboard_release(wl_keyboard::Resource *resource)
void QWaylandKeyboardPrivate::keyEvent(uint code, uint32_t state)
{
-#if QT_CONFIG(xkbcommon)
- uint key = toWaylandXkbV1Key(code);
-#else
- uint key = code;
-#endif
+ uint key = toWaylandKey(code);
+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
keys << key;
} else {
@@ -180,30 +175,18 @@ void QWaylandKeyboardPrivate::sendKeyEvent(uint code, uint32_t state)
{
uint32_t time = compositor()->currentTimeMsecs();
uint32_t serial = compositor()->nextSerial();
-#if QT_CONFIG(xkbcommon)
- uint key = toWaylandXkbV1Key(code);
-#else
- uint key = code;
-#endif
+ uint key = toWaylandKey(code);
if (focusResource)
send_key(focusResource->handle, serial, time, key, state);
}
-void QWaylandKeyboardPrivate::modifiers(uint32_t serial, uint32_t mods_depressed,
- uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
-{
- if (focusResource) {
- send_modifiers(focusResource->handle, serial, mods_depressed, mods_latched, mods_locked, group);
- }
-}
-
#if QT_CONFIG(xkbcommon)
void QWaylandKeyboardPrivate::maybeUpdateXkbScanCodeTable()
{
if (!scanCodesByQtKey.isEmpty() || !xkbState())
return;
- if (xkb_keymap *keymap = xkb_state_get_keymap(xkb_state)) {
+ if (xkb_keymap *keymap = xkb_state_get_keymap(xkbState())) {
xkb_keymap_key_for_each(keymap, [](xkb_keymap *keymap, xkb_keycode_t keycode, void *d){
auto *scanCodesByQtKey = static_cast<QMap<ScanCodeKey, uint>*>(d);
uint numLayouts = xkb_keymap_num_layouts_for_key(keymap, keycode);
@@ -214,7 +197,7 @@ void QWaylandKeyboardPrivate::maybeUpdateXkbScanCodeTable()
continue;
Qt::KeyboardModifiers mods = {};
- int qtKey = QWaylandXkb::keysymToQtKey(syms[0], mods).first;
+ int qtKey = QXkbCommon::keysymToQtKey(syms[0], mods);
if (qtKey != 0)
scanCodesByQtKey->insert({layout, qtKey}, keycode);
}
@@ -226,15 +209,15 @@ void QWaylandKeyboardPrivate::maybeUpdateXkbScanCodeTable()
void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state)
{
#if QT_CONFIG(xkbcommon)
- if (!xkb_context)
+ if (!xkbContext())
return;
- xkb_state_update_key(xkb_state, code, state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP);
+ xkb_state_update_key(xkbState(), code, state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP);
- uint32_t modsDepressed = xkb_state_serialize_mods(xkb_state, (xkb_state_component)XKB_STATE_DEPRESSED);
- uint32_t modsLatched = xkb_state_serialize_mods(xkb_state, (xkb_state_component)XKB_STATE_LATCHED);
- uint32_t modsLocked = xkb_state_serialize_mods(xkb_state, (xkb_state_component)XKB_STATE_LOCKED);
- uint32_t group = xkb_state_serialize_group(xkb_state, (xkb_state_component)XKB_STATE_EFFECTIVE);
+ uint32_t modsDepressed = xkb_state_serialize_mods(xkbState(), XKB_STATE_MODS_DEPRESSED);
+ uint32_t modsLatched = xkb_state_serialize_mods(xkbState(), XKB_STATE_MODS_LATCHED);
+ uint32_t modsLocked = xkb_state_serialize_mods(xkbState(), XKB_STATE_MODS_LOCKED);
+ uint32_t group = xkb_state_serialize_layout(xkbState(), XKB_STATE_LAYOUT_EFFECTIVE);
if (this->modsDepressed == modsDepressed
&& this->modsLatched == modsLatched
@@ -247,7 +230,10 @@ void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state)
this->modsLocked = modsLocked;
this->group = group;
- modifiers(compositor()->nextSerial(), modsDepressed, modsLatched, modsLocked, group);
+ if (focusResource) {
+ send_modifiers(focusResource->handle, compositor()->nextSerial(), modsDepressed,
+ modsLatched, modsLocked, group);
+ }
#else
Q_UNUSED(code);
Q_UNUSED(state);
@@ -266,7 +252,7 @@ void QWaylandKeyboardPrivate::maybeUpdateKeymap()
pendingKeymap = false;
#if QT_CONFIG(xkbcommon)
- if (!xkb_context)
+ if (!xkbContext())
return;
createXKBKeymap();
@@ -274,7 +260,7 @@ void QWaylandKeyboardPrivate::maybeUpdateKeymap()
send_keymap(res->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymap_fd, keymap_size);
}
- xkb_state_update_mask(xkb_state, 0, modsLatched, modsLocked, 0, 0, 0);
+ xkb_state_update_mask(xkbState(), 0, modsLatched, modsLocked, 0, 0, 0);
if (focusResource)
send_modifiers(focusResource->handle,
compositor()->nextSerial(),
@@ -285,6 +271,24 @@ void QWaylandKeyboardPrivate::maybeUpdateKeymap()
#endif
}
+uint QWaylandKeyboardPrivate::toWaylandKey(const uint nativeScanCode)
+{
+#if QT_CONFIG(xkbcommon)
+ // In all current XKB keymaps there's a constant offset of 8 (for historical
+ // reasons) from hardware/evdev scancodes to XKB keycodes. On X11, we pass
+ // XKB keycodes (as sent by X server) via QKeyEvent::nativeScanCode. eglfs+evdev
+ // adds 8 for consistency, see qtbase/05c07c7636012ebb4131ca099ca4ea093af76410.
+ // eglfs+libinput also adds 8, for the same reason. Wayland protocol uses
+ // hardware/evdev scancodes, thus we need to minus 8 before sending the event
+ // out.
+ const uint offset = 8;
+ Q_ASSERT(nativeScanCode >= offset);
+ return nativeScanCode - offset;
+#else
+ return nativeScanCode;
+#endif
+}
+
#if QT_CONFIG(xkbcommon)
static int createAnonymousFile(size_t size)
{
@@ -316,18 +320,6 @@ static int createAnonymousFile(size_t size)
return fd;
}
-void QWaylandKeyboardPrivate::initXKB()
-{
- xkb_context = xkb_context_new(static_cast<xkb_context_flags>(0));
- if (!xkb_context) {
- qWarning("Failed to create a XKB context: keymap will not be supported");
- return;
- }
-
- createXKBKeymap();
-}
-
-
void QWaylandKeyboardPrivate::createXKBState(xkb_keymap *keymap)
{
char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
@@ -356,46 +348,41 @@ void QWaylandKeyboardPrivate::createXKBState(xkb_keymap *keymap)
strcpy(keymap_area, keymap_str);
free(keymap_str);
- if (xkb_state)
- xkb_state_unref(xkb_state);
- xkb_state = xkb_state_new(keymap);
-}
-
-uint QWaylandKeyboardPrivate::toWaylandXkbV1Key(const uint nativeScanCode)
-{
- const uint offset = 8;
- Q_ASSERT(nativeScanCode >= offset);
- return nativeScanCode - offset;
+ mXkbState.reset(xkb_state_new(keymap));
+ if (!mXkbState)
+ qWarning("Failed to create XKB state");
}
void QWaylandKeyboardPrivate::createXKBKeymap()
{
- if (!xkb_context)
+ if (!xkbContext())
return;
- auto keymap = seat->keymap();
- struct xkb_rule_names rule_names = { strdup(qPrintable(keymap->rules())),
- strdup(qPrintable(keymap->model())),
- strdup(qPrintable(keymap->layout())),
- strdup(qPrintable(keymap->variant())),
- strdup(qPrintable(keymap->options())) };
- struct xkb_keymap *xkbKeymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast<xkb_keymap_compile_flags>(0));
-
+ QWaylandKeymap *keymap = seat->keymap();
+ QByteArray rules = keymap->rules().toLocal8Bit();
+ QByteArray model = keymap->model().toLocal8Bit();
+ QByteArray layout = keymap->layout().toLocal8Bit();
+ QByteArray variant = keymap->variant().toLocal8Bit();
+ QByteArray options = keymap->options().toLocal8Bit();
+
+ struct xkb_rule_names rule_names = {
+ rules.constData(),
+ model.constData(),
+ layout.constData(),
+ variant.constData(),
+ options.constData()
+ };
+
+ QXkbCommon::ScopedXKBKeymap xkbKeymap(xkb_keymap_new_from_names(xkbContext(), &rule_names,
+ XKB_KEYMAP_COMPILE_NO_FLAGS));
if (xkbKeymap) {
scanCodesByQtKey.clear();
- createXKBState(xkbKeymap);
- xkb_keymap_unref(xkbKeymap);
+ createXKBState(xkbKeymap.get());
} else {
qWarning("Failed to load the '%s' XKB keymap.", qPrintable(keymap->layout()));
}
-
- free((char *)rule_names.rules);
- free((char *)rule_names.model);
- free((char *)rule_names.layout);
- free((char *)rule_names.variant);
- free((char *)rule_names.options);
}
-#endif
+#endif // QT_CONFIG(xkbcommon)
void QWaylandKeyboardPrivate::sendRepeatInfo()
{
@@ -430,7 +417,7 @@ QWaylandKeyboard::QWaylandKeyboard(QWaylandSeat *seat, QObject *parent)
connect(keymap, &QWaylandKeymap::rulesChanged, this, &QWaylandKeyboard::updateKeymap);
connect(keymap, &QWaylandKeymap::modelChanged, this, &QWaylandKeyboard::updateKeymap);
#if QT_CONFIG(xkbcommon)
- d->initXKB();
+ d->createXKBKeymap();
#endif
}
@@ -486,7 +473,7 @@ QWaylandClient *QWaylandKeyboard::focusClient() const
/*!
* Sends the current key modifiers to \a client with the given \a serial.
*/
-void QWaylandKeyboard::sendKeyModifiers(QWaylandClient *client, uint serial)
+void QWaylandKeyboard::sendKeyModifiers(QWaylandClient *client, uint32_t serial)
{
Q_D(QWaylandKeyboard);
QtWaylandServer::wl_keyboard::Resource *resource = d->resourceMap().value(client->client());
diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h
index 87e89e85e..4dfe0035e 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard_p.h
+++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h
@@ -51,6 +51,7 @@
//
// We mean it.
//
+#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <QtWaylandCompositor/private/qtwaylandcompositorglobal_p.h>
#include <QtWaylandCompositor/qwaylandseat.h>
@@ -64,6 +65,7 @@
#if QT_CONFIG(xkbcommon)
#include <xkbcommon/xkbcommon.h>
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#endif
@@ -83,11 +85,12 @@ public:
QWaylandCompositor *compositor() const { return seat->compositor(); }
void focused(QWaylandSurface* surface);
- void modifiers(uint32_t serial, uint32_t mods_depressed,
- uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
#if QT_CONFIG(xkbcommon)
- struct xkb_state *xkbState() const { return xkb_state; }
+ struct xkb_state *xkbState() const { return mXkbState.get(); }
+ struct xkb_context *xkbContext() const {
+ return QWaylandCompositorPrivate::get(seat->compositor())->xkbContext();
+ }
uint32_t xkbModsMask() const { return modsDepressed | modsLatched | modsLocked; }
void maybeUpdateXkbScanCodeTable();
#endif
@@ -107,11 +110,10 @@ protected:
private:
#if QT_CONFIG(xkbcommon)
- void initXKB();
void createXKBKeymap();
void createXKBState(xkb_keymap *keymap);
#endif
- static uint toWaylandXkbV1Key(const uint nativeScanCode);
+ static uint toWaylandKey(const uint nativeScanCode);
void sendRepeatInfo();
@@ -134,8 +136,7 @@ private:
char *keymap_area = nullptr;
using ScanCodeKey = std::pair<uint,int>; // group/layout and QtKey
QMap<ScanCodeKey, uint> scanCodesByQtKey;
- struct xkb_context *xkb_context = nullptr;
- struct xkb_state *xkb_state = nullptr;
+ QXkbCommon::ScopedXKBState mXkbState;
#endif
quint32 repeatRate = 40;
diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp
index 1f34f4eac..006edbe6a 100644
--- a/src/compositor/compositor_api/qwaylandoutput.cpp
+++ b/src/compositor/compositor_api/qwaylandoutput.cpp
@@ -47,6 +47,7 @@
#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <QtWaylandCompositor/private/qwaylandview_p.h>
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QtMath>
@@ -350,8 +351,8 @@ void QWaylandOutput::initialize()
*/
QWaylandOutput *QWaylandOutput::fromResource(wl_resource *resource)
{
- if (auto *r = QWaylandOutputPrivate::Resource::fromResource(resource))
- return static_cast<QWaylandOutputPrivate *>(r->output_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandOutputPrivate *>(resource))
+ return p->q_func();
return nullptr;
}
diff --git a/src/compositor/compositor_api/qwaylandpointer.cpp b/src/compositor/compositor_api/qwaylandpointer.cpp
index 77e736a58..96263e0c2 100644
--- a/src/compositor/compositor_api/qwaylandpointer.cpp
+++ b/src/compositor/compositor_api/qwaylandpointer.cpp
@@ -239,7 +239,7 @@ uint QWaylandPointer::sendMouseReleaseEvent(Qt::MouseButton button)
/*!
* Sets the current mouse focus to \a view and sends a mouse move event to it with the
- * local position \a localPos and output space position \a outputSpacePos.
+ * local position \a localPos in surface coordinates and output space position \a outputSpacePos.
*/
void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos)
{
@@ -253,7 +253,7 @@ void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &loca
if (view) {
// We adjust if the mouse position is on the edge
// to work around Qt's event propagation
- QSizeF size(view->surface()->size());
+ QSizeF size(view->surface()->destinationSize());
if (d->localPosition.x() == size.width())
d->localPosition.rx() -= 0.01;
if (d->localPosition.y() == size.height())
@@ -294,7 +294,7 @@ QWaylandView *QWaylandPointer::mouseFocus() const
}
/*!
- * Returns the current local position of the QWaylandPointer.
+ * Returns the current local position of the QWaylandPointer in surface coordinates.
*/
QPointF QWaylandPointer::currentLocalPosition() const
{
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
index 8e8a903e3..14b592efb 100644
--- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
@@ -53,6 +53,7 @@
#include "qwaylandquickitem.h"
#include "qwaylandoutput.h"
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
+#include <QtWaylandCompositor/QWaylandViewporter>
#include "qwaylandsurfacegrabber.h"
QT_BEGIN_NAMESPACE
@@ -60,8 +61,9 @@ QT_BEGIN_NAMESPACE
class QWaylandQuickCompositorPrivate : public QWaylandCompositorPrivate
{
public:
- QWaylandQuickCompositorPrivate(QWaylandCompositor *compositor)
+ explicit QWaylandQuickCompositorPrivate(QWaylandCompositor *compositor)
: QWaylandCompositorPrivate(compositor)
+ , m_viewporter(new QWaylandViewporter(compositor))
{
}
protected:
@@ -69,6 +71,8 @@ protected:
{
return new QWaylandQuickSurface();
}
+private:
+ QScopedPointer<QWaylandViewporter> m_viewporter;
};
QWaylandQuickCompositor::QWaylandQuickCompositor(QObject *parent)
@@ -86,15 +90,15 @@ QWaylandQuickCompositor::QWaylandQuickCompositor(QObject *parent)
* For instance, the following code would allow the clients to request \c wl_shell
* surfaces in the compositor using the \c wl_shell interface.
*
- * \code
- * import QtWayland.Compositor 1.0
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
*
* WaylandCompositor {
* WlShell {
* // ...
* }
* }
- * \endcode
+ * \endqml
*/
void QWaylandQuickCompositor::create()
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 2b24c13b7..7b0d5c5d5 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -64,7 +64,7 @@
#include <QtCore/QMutexLocker>
#include <QtCore/QMutex>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
#include <QThread>
#ifndef GL_TEXTURE_EXTERNAL_OES
@@ -295,7 +295,8 @@ public:
}
auto texture = buffer.toOpenGLTexture();
- m_sgTex = surfaceItem->window()->createTextureFromId(texture->textureId() , QSize(surfaceItem->width(), surfaceItem->height()), opt);
+ auto size = surface->bufferSize();
+ m_sgTex = surfaceItem->window()->createTextureFromId(texture->textureId(), size, opt);
}
}
emit textureChanged();
@@ -414,7 +415,11 @@ QWaylandSurface *QWaylandQuickItem::surface() const
void QWaylandQuickItem::setSurface(QWaylandSurface *surface)
{
Q_D(QWaylandQuickItem);
+ QWaylandCompositor *oldComp = d->view->surface() ? d->view->surface()->compositor() : nullptr;
d->view->setSurface(surface);
+ QWaylandCompositor *newComp = d->view->surface() ? d->view->surface()->compositor() : nullptr;
+ if (oldComp != newComp)
+ emit compositorChanged();
update();
}
@@ -821,7 +826,15 @@ void QWaylandQuickItem::setOutput(QWaylandOutput *output)
}
/*!
- * \property QWaylandQuickItem::isBufferLocked
+ * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::bufferLocked
+ *
+ * This property holds whether the item's buffer is currently locked. As long as
+ * the buffer is locked, it will not be released and returned to the client.
+ *
+ * The default is false.
+ */
+/*!
+ * \property QWaylandQuickItem::bufferLocked
*
* This property holds whether the item's buffer is currently locked. As long as
* the buffer is locked, it will not be released and returned to the client.
@@ -886,7 +899,7 @@ void QWaylandQuickItem::handleSurfaceChanged()
if (d->oldSurface) {
disconnect(d->oldSurface.data(), &QWaylandSurface::hasContentChanged, this, &QWaylandQuickItem::surfaceMappedChanged);
disconnect(d->oldSurface.data(), &QWaylandSurface::parentChanged, this, &QWaylandQuickItem::parentChanged);
- disconnect(d->oldSurface.data(), &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize);
+ disconnect(d->oldSurface.data(), &QWaylandSurface::destinationSizeChanged, this, &QWaylandQuickItem::updateSize);
disconnect(d->oldSurface.data(), &QWaylandSurface::bufferScaleChanged, this, &QWaylandQuickItem::updateSize);
disconnect(d->oldSurface.data(), &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer);
disconnect(d->oldSurface.data(), &QWaylandSurface::redraw, this, &QQuickItem::update);
@@ -903,7 +916,7 @@ void QWaylandQuickItem::handleSurfaceChanged()
if (QWaylandSurface *newSurface = d->view->surface()) {
connect(newSurface, &QWaylandSurface::hasContentChanged, this, &QWaylandQuickItem::surfaceMappedChanged);
connect(newSurface, &QWaylandSurface::parentChanged, this, &QWaylandQuickItem::parentChanged);
- connect(newSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize);
+ connect(newSurface, &QWaylandSurface::destinationSizeChanged, this, &QWaylandQuickItem::updateSize);
connect(newSurface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandQuickItem::updateSize);
connect(newSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer);
connect(newSurface, &QWaylandSurface::redraw, this, &QQuickItem::update);
@@ -992,7 +1005,7 @@ void QWaylandQuickItem::updateSize()
QSize size(0, 0);
if (surface())
- size = surface()->size() * (d->scaleFactor() / surface()->bufferScale());
+ size = surface()->destinationSize() * d->scaleFactor();
setImplicitSize(size.width(), size.height());
if (d->sizeFollowsSurface)
@@ -1054,6 +1067,14 @@ bool QWaylandQuickItem::inputRegionContains(const QPointF &localPosition)
}
/*!
+ * \qmlmethod point WaylandQuickItem::mapToSurface(point point)
+ *
+ * Maps the given \a point in this item's coordinate system to the equivalent
+ * point within the Wayland surface's coordinate system, and returns the mapped
+ * coordinate.
+ */
+
+/*!
* Maps the given \a point in this item's coordinate system to the equivalent
* point within the Wayland surface's coordinate system, and returns the mapped
* coordinate.
@@ -1061,16 +1082,42 @@ bool QWaylandQuickItem::inputRegionContains(const QPointF &localPosition)
QPointF QWaylandQuickItem::mapToSurface(const QPointF &point) const
{
Q_D(const QWaylandQuickItem);
- if (!surface() || surface()->size().isEmpty())
+ if (!surface() || surface()->destinationSize().isEmpty())
return point / d->scaleFactor();
- qreal xScale = width() / surface()->size().width() * surface()->bufferScale();
- qreal yScale = height() / surface()->size().height() * surface()->bufferScale();
+ qreal xScale = width() / surface()->destinationSize().width();
+ qreal yScale = height() / surface()->destinationSize().height();
return QPointF(point.x() / xScale, point.y() / yScale);
}
/*!
+ * \qmlmethod point WaylandQuickItem::mapFromSurface(point point)
+ * \since 5.13
+ *
+ * Maps the given \a point in the Wayland surfaces's coordinate system to the equivalent
+ * point within this item's coordinate system, and returns the mapped coordinate.
+ */
+
+/*!
+ * Maps the given \a point in the Wayland surfaces's coordinate system to the equivalent
+ * point within this item's coordinate system, and returns the mapped coordinate.
+ *
+ * \since 5.13
+ */
+QPointF QWaylandQuickItem::mapFromSurface(const QPointF &point) const
+{
+ Q_D(const QWaylandQuickItem);
+ if (!surface() || surface()->destinationSize().isEmpty())
+ return point * d->scaleFactor();
+
+ qreal xScale = width() / surface()->destinationSize().width();
+ qreal yScale = height() / surface()->destinationSize().height();
+
+ return QPointF(point.x() * xScale, point.y() * yScale);
+}
+
+/*!
* \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::sizeFollowsSurface
*
* This property specifies whether the size of the item should always match
@@ -1245,7 +1292,7 @@ void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
* If an animation is started, bufferLocked should be set to ensure the item keeps its content
* until the animation finishes
*
- * \sa isBufferLocked
+ * \sa bufferLocked
*/
/*!
@@ -1258,7 +1305,7 @@ void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
* If an animation is started, bufferLocked should be set to ensure the item keeps its content
* until the animation finishes
*
- * \sa QWaylandQuickkItem::bufferLocked
+ * \sa QWaylandQuickItem::bufferLocked
*/
QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
@@ -1301,6 +1348,10 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
d->provider->setSmooth(smooth());
node->setRect(rect);
+ qreal scale = surface()->bufferScale();
+ QRectF source = surface()->sourceGeometry();
+ node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
+
return node;
} else {
Q_ASSERT(!d->provider);
diff --git a/src/compositor/compositor_api/qwaylandquickitem.h b/src/compositor/compositor_api/qwaylandquickitem.h
index 23708353e..2aa8e1b73 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.h
+++ b/src/compositor/compositor_api/qwaylandquickitem.h
@@ -61,7 +61,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickItem : public QQuickItem
{
Q_OBJECT
Q_DECLARE_PRIVATE(QWaylandQuickItem)
- Q_PROPERTY(QWaylandCompositor *compositor READ compositor)
+ Q_PROPERTY(QWaylandCompositor *compositor READ compositor NOTIFY compositorChanged)
Q_PROPERTY(QWaylandSurface *surface READ surface WRITE setSurface NOTIFY surfaceChanged)
Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled)
Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged)
@@ -102,6 +102,7 @@ public:
bool inputRegionContains(const QPointF &localPosition) const;
bool inputRegionContains(const QPointF &localPosition);
Q_INVOKABLE QPointF mapToSurface(const QPointF &point) const;
+ Q_REVISION(13) Q_INVOKABLE QPointF mapFromSurface(const QPointF &point) const;
bool sizeFollowsSurface() const;
void setSizeFollowsSurface(bool sizeFollowsSurface);
@@ -176,6 +177,7 @@ private Q_SLOTS:
Q_SIGNALS:
void surfaceChanged();
+ void compositorChanged();
void touchEventsEnabledChanged();
void originChanged();
void surfaceDestroyed();
diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp
index a7b01ef03..bc5e1d8b2 100644
--- a/src/compositor/compositor_api/qwaylandseat.cpp
+++ b/src/compositor/compositor_api/qwaylandseat.cpp
@@ -54,6 +54,7 @@
#if QT_CONFIG(wayland_datadevice)
#include <QtWaylandCompositor/private/qwldatadevice_p.h>
#endif
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include "extensions/qwlqtkey_p.h"
#include "extensions/qwaylandtextinput.h"
@@ -176,7 +177,7 @@ void QWaylandSeatPrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t i
*/
/*!
- * Constructs a QWaylandSeat for the given \a compositor and with the given \a capabilityFlags.
+ * Constructs a QWaylandSeat for the given \a compositor and \a capabilityFlags.
*/
QWaylandSeat::QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags)
: QWaylandObject(*new QWaylandSeatPrivate(this))
@@ -195,6 +196,14 @@ QWaylandSeat::~QWaylandSeat()
{
}
+/*!
+ * Initializes parts of the seat corresponding to the capabilities set in the constructor, or
+ * through setCapabilities().
+ *
+ * \note Normally, this function is called automatically after the seat and compositor have been
+ * created, so calling it manually is usually unnecessary.
+ */
+
void QWaylandSeat::initialize()
{
Q_D(QWaylandSeat);
@@ -210,6 +219,11 @@ void QWaylandSeat::initialize()
d->isInitialized = true;
}
+/*!
+ * Returns true if the QWaylandSeat is initialized; false otherwise.
+ *
+ * The value \c true indicates that it's now possible for clients to start using the seat.
+ */
bool QWaylandSeat::isInitialized() const
{
Q_D(const QWaylandSeat);
@@ -534,6 +548,11 @@ bool QWaylandSeat::setKeyboardFocus(QWaylandSurface *surface)
return true;
}
+
+/*!
+ * Returns the keymap object for this QWaylandSeat.
+ */
+
QWaylandKeymap *QWaylandSeat::keymap()
{
Q_D(const QWaylandSeat);
@@ -631,8 +650,8 @@ bool QWaylandSeat::isOwner(QInputEvent *inputEvent) const
*/
QWaylandSeat *QWaylandSeat::fromSeatResource(struct ::wl_resource *resource)
{
- if (auto *r = QWaylandSeatPrivate::Resource::fromResource(resource))
- return static_cast<QWaylandSeatPrivate *>(r->seat_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandSeatPrivate *>(resource))
+ return p->q_func();
return nullptr;
}
@@ -653,4 +672,65 @@ void QWaylandSeat::handleMouseFocusDestroyed()
emit mouseFocusChanged(d->mouseFocus, oldFocus);
}
+
+/*! \qmlsignal void QtWaylandCompositor::QWaylandSeat::keyboardFocusChanged(QWaylandSurface newFocus, QWaylandSurface oldFocus)
+ *
+ * This signal is emitted when setKeyboardFocus() is called or when a WaylandQuickItem has focus
+ * and the user starts pressing keys.
+ *
+ * \a newFocus has the surface that received keyboard focus; or \c nullptr if no surface has
+ * focus.
+ * \a oldFocus has the surface that lost keyboard focus; or \c nullptr if no surface had focus.
+ */
+
+/*!
+ * \fn void QWaylandSeat::keyboardFocusChanged(QWaylandSurface *newFocus, QWaylandSurface *oldFocus)
+ *
+ * This signal is emitted when setKeyboardFocus() is called.
+ *
+ * \a newFocus has the surface that received keyboard focus; or \c nullptr if no surface has
+ * focus.
+ * \a oldFocus has the surface that lost keyboard focus; or \c nullptr if no surface had focus.
+ */
+
+/*! \qmlsignal void QtWaylandCompositor::QWaylandSeat::cursorSurfaceRequest(QWaylandSurface surface, int hotspotX, int hotspotY)
+ *
+ * This signal is emitted when the client has requested for a specific \a surface to be the mouse
+ * cursor. For example, when the user hovers over a particular surface, and you want the cursor
+ * to change into a resize arrow.
+ *
+ * Both \a hotspotX and \a hotspotY are offsets from the top-left of a pointer surface, where a
+ * click should happen. For example, if the requested cursor surface is an arrow, the parameters
+ * indicate where the arrow's tip is, on that surface.
+ */
+
+
+/*!
+ * \fn void QWaylandSeat::cursorSurfaceRequest(QWaylandSurface *surface, int hotspotX, int hotspotY)
+ *
+ * This signal is emitted when the client has requested for a specific \a surface to be the mouse
+ * cursor. For example, when the user hovers over a particular surface, and you want the cursor
+ * to change into a resize arrow.
+ */
+
+/*!
+ * \property QWaylandSeat::drag
+ *
+ * This property holds the drag and drop operations and sends signals when they start and end.
+ * The property stores details like what image should be under the mouse cursor when the user
+ * drags it.
+ */
+
+/*!
+ * \property QWaylandSeat::keymap
+ * This property holds the keymap object.
+ *
+ * A keymap provides a way to translate actual key scan codes into a meaningful value.
+ * For example, if you use a keymap with a Norwegian layout, the key to the right of
+ * the letter L produces an Ø.
+ *
+ * Keymaps can also be used to customize key functions, such as to specify whether
+ * Control and CAPS lock should be swapped, and so on.
+ */
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index f457c372c..c79787e6e 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -59,6 +59,7 @@
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <QtWaylandCompositor/private/qwaylandview_p.h>
#include <QtWaylandCompositor/private/qwaylandseat_p.h>
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <QtCore/private/qobject_p.h>
@@ -234,21 +235,29 @@ void QWaylandSurfacePrivate::surface_commit(Resource *)
// Needed in order to know whether we want to emit signals later
QSize oldBufferSize = bufferSize;
+ QRectF oldSourceGeometry = sourceGeometry;
+ QSize oldDestinationSize = destinationSize;
bool oldHasContent = hasContent;
int oldBufferScale = bufferScale;
// Update all internal state
if (pending.buffer.hasBuffer() || pending.newlyAttached)
bufferRef = pending.buffer;
+ bufferScale = pending.bufferScale;
bufferSize = bufferRef.size();
- damage = pending.damage.intersected(QRect(QPoint(), bufferSize));
+ QSize surfaceSize = bufferSize / bufferScale;
+ sourceGeometry = !pending.sourceGeometry.isValid() ? QRect(QPoint(), surfaceSize) : pending.sourceGeometry;
+ destinationSize = pending.destinationSize.isEmpty() ? sourceGeometry.size().toSize() : pending.destinationSize;
+ damage = pending.damage.intersected(QRect(QPoint(), destinationSize));
hasContent = bufferRef.hasContent();
- bufferScale = pending.bufferScale;
frameCallbacks << pendingFrameCallbacks;
- inputRegion = pending.inputRegion.intersected(QRect(QPoint(), bufferSize));
- opaqueRegion = pending.opaqueRegion.intersected(QRect(QPoint(), bufferSize));
+ inputRegion = pending.inputRegion.intersected(QRect(QPoint(), destinationSize));
+ opaqueRegion = pending.opaqueRegion.intersected(QRect(QPoint(), destinationSize));
QPoint offsetForNextFrame = pending.offset;
+ if (viewport)
+ viewport->checkCommittedState();
+
// Clear per-commit state
pending.buffer = QWaylandBufferRef();
pending.offset = QPoint();
@@ -268,12 +277,22 @@ void QWaylandSurfacePrivate::surface_commit(Resource *)
emit q->damaged(damage);
- if (oldBufferSize != bufferSize)
+ if (oldBufferSize != bufferSize) {
+ emit q->bufferSizeChanged();
+#if QT_DEPRECATED_SINCE(5, 13)
emit q->sizeChanged();
+#endif
+ }
if (oldBufferScale != bufferScale)
emit q->bufferScaleChanged();
+ if (oldDestinationSize != destinationSize)
+ emit q->destinationSizeChanged();
+
+ if (oldSourceGeometry != sourceGeometry)
+ emit q->sourceGeometryChanged();
+
if (oldHasContent != hasContent)
emit q->hasContentChanged();
@@ -431,9 +450,7 @@ QWaylandClient *QWaylandSurface::client() const
}
/*!
- * \property QWaylandSurface::waylandClient
- *
- * This property holds the \c wl_client using this QWaylandSurface.
+ * Holds the \c wl_client using this QWaylandSurface.
*/
::wl_client *QWaylandSurface::waylandClient() const
{
@@ -461,21 +478,109 @@ bool QWaylandSurface::hasContent() const
}
/*!
+ * \qmlproperty rect QtWaylandCompositor::WaylandSurface::sourceGeometry
+ * \since 5.13
+ *
+ * This property describes the portion of the attached Wayland buffer that should
+ * be drawn on the screen. The coordinates are from the corner of the buffer and are
+ * scaled by \l bufferScale.
+ *
+ * \sa bufferScale
+ * \sa bufferSize
+ * \sa destinationSize
+ */
+
+/*!
+ * \property QWaylandSurface::sourceGeometry
+ * \since 5.13
+ *
+ * This property describes the portion of the attached QWaylandBuffer that should
+ * be drawn on the screen. The coordinates are from the corner of the buffer and are
+ * scaled by \l bufferScale.
+ *
+ * \sa bufferScale
+ * \sa bufferSize
+ * \sa destinationSize
+ */
+QRectF QWaylandSurface::sourceGeometry() const
+{
+ Q_D(const QWaylandSurface);
+ return d->sourceGeometry;
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::WaylandSurface::destinationSize
+ * \since 5.13
+ *
+ * This property holds the size of this WaylandSurface in surface coordinates.
+ *
+ * \sa bufferScale
+ * \sa bufferSize
+ */
+
+/*!
+ * \property QWaylandSurface::destinationSize
+ * \since 5.13
+ *
+ * This property holds the size of this WaylandSurface in surface coordinates.
+ *
+ * \sa bufferScale
+ * \sa bufferSize
+ */
+QSize QWaylandSurface::destinationSize() const
+{
+ Q_D(const QWaylandSurface);
+ return d->destinationSize;
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::WaylandSurface::bufferSize
+ *
+ * This property holds the size of the current buffer of this WaylandSurface in pixels,
+ * not in surface coordinates.
+ *
+ * For the size in surface coordinates, use \l destinationSize instead.
+ *
+ * \sa destinationSize
+ * \sa bufferScale
+ */
+
+/*!
+ * \property QWaylandSurface::bufferSize
+ *
+ * This property holds the size of the current buffer of this QWaylandSurface in pixels,
+ * not in surface coordinates.
+ *
+ * For the size in surface coordinates, use \l destinationSize instead.
+ *
+ * \sa destinationSize
+ * \sa bufferScale
+ */
+QSize QWaylandSurface::bufferSize() const
+{
+ Q_D(const QWaylandSurface);
+ return d->bufferSize;
+}
+
+#if QT_DEPRECATED_SINCE(5, 13)
+/*!
* \qmlproperty size QtWaylandCompositor::WaylandSurface::size
+ * \obsolete use bufferSize or destinationSize instead
*
- * This property holds the WaylandSurface's size in pixels.
+ * This property has been deprecated, use \l bufferSize or \l destinationSize instead.
*/
/*!
* \property QWaylandSurface::size
+ * \obsolete use bufferSize or destinationSize instead
*
- * This property holds the QWaylandSurface's size in pixels.
+ * This property has been deprecated, use \l bufferSize or \l destinationSize instead.
*/
QSize QWaylandSurface::size() const
{
- Q_D(const QWaylandSurface);
- return d->bufferSize;
+ return bufferSize();
}
+#endif
/*!
* \qmlproperty size QtWaylandCompositor::WaylandSurface::bufferScale
@@ -740,12 +845,12 @@ QList<QWaylandView *> QWaylandSurface::views() const
}
/*!
- * Returns the QWaylandSurface corresponding to the Wayland resource \a res.
+ * Returns the QWaylandSurface corresponding to the Wayland resource \a resource.
*/
-QWaylandSurface *QWaylandSurface::fromResource(::wl_resource *res)
+QWaylandSurface *QWaylandSurface::fromResource(::wl_resource *resource)
{
- if (auto *r = QWaylandSurfacePrivate::Resource::fromResource(res))
- return static_cast<QWaylandSurfacePrivate *>(r->surface_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandSurfacePrivate *>(resource))
+ return p->q_func();
return nullptr;
}
@@ -759,11 +864,12 @@ struct wl_resource *QWaylandSurface::resource() const
}
/*!
- * Sets a \a role on the surface. A role defines how a surface will be mapped on screen, without a role
- * a surface is supposed to be hidden. Only one role at all times can be set on a surface. Although
+ * Sets a \a role on the surface. A role defines how a surface will be mapped on screen; without a role
+ * a surface is supposed to be hidden. Only one role can be set on a surface, at all times. Although
* setting the same role many times is allowed, attempting to change the role of a surface will trigger
* a protocol error to the \a errorResource and send an \a errorCode to the client.
*
+ * Returns true if a role can be assigned; false otherwise.
*/
bool QWaylandSurface::setRole(QWaylandSurfaceRole *role, wl_resource *errorResource, uint32_t errorCode)
{
@@ -904,4 +1010,21 @@ void QWaylandSurfacePrivate::Subsurface::subsurface_set_desync(wl_subsurface::Re
* This signal is emitted when a \a drag has started from this surface.
*/
+/*!
+ * \fn void damaged(const QRegion &rect)
+ *
+ * This signal is emitted when the client tells the compositor that a particular part of, or
+ * possibly the entire surface has been updated, so the compositor can redraw that part.
+ *
+ * While the compositor APIs take care of redrawing automatically, this function may be useful
+ * if you require a specific, custom behavior.
+ */
+
+/*!
+ * \fn void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
+ *
+ * This signal is emitted when the client has requested that this surface should be a
+ * subsurface of \a newParent.
+ */
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index a138b2af5..667f911c3 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -81,7 +81,12 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSurface : public QWaylandObject
Q_OBJECT
Q_DECLARE_PRIVATE(QWaylandSurface)
Q_PROPERTY(QWaylandClient *client READ client CONSTANT)
- Q_PROPERTY(QSize size READ size NOTIFY sizeChanged)
+ Q_PROPERTY(QRectF sourceGeometry READ sourceGeometry NOTIFY sourceGeometryChanged REVISION 13)
+ Q_PROPERTY(QSize destinationSize READ destinationSize NOTIFY destinationSizeChanged REVISION 13)
+ Q_PROPERTY(QSize bufferSize READ bufferSize NOTIFY bufferSizeChanged REVISION 13)
+#if QT_DEPRECATED_SINCE(5, 13)
+ Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) // Qt 6: Remove
+#endif
Q_PROPERTY(int bufferScale READ bufferScale NOTIFY bufferScaleChanged)
Q_PROPERTY(Qt::ScreenOrientation contentOrientation READ contentOrientation NOTIFY contentOrientationChanged)
Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged)
@@ -110,7 +115,12 @@ public:
bool hasContent() const;
- QSize size() const;
+ QRectF sourceGeometry() const;
+ QSize destinationSize() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED QSize size() const;
+#endif
+ QSize bufferSize() const;
int bufferScale() const;
Qt::ScreenOrientation contentOrientation() const;
@@ -155,7 +165,12 @@ Q_SIGNALS:
void damaged(const QRegion &rect);
void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent);
void childAdded(QWaylandSurface *child);
- void sizeChanged();
+ Q_REVISION(13) void sourceGeometryChanged();
+ Q_REVISION(13) void destinationSizeChanged();
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED void sizeChanged();
+#endif
+ Q_REVISION(13) void bufferSizeChanged();
void bufferScaleChanged();
void offsetForNextFrame(const QPoint &offset);
void contentOrientationChanged();
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index df868de63..1637d8704 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -73,6 +73,7 @@
#include <wayland-util.h>
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
+#include <QtWaylandCompositor/private/qwaylandviewporter_p.h>
QT_BEGIN_NAMESPACE
@@ -144,14 +145,17 @@ public: //member variables
QRegion damage;
QWaylandBufferRef bufferRef;
QWaylandSurfaceRole *role = nullptr;
+ QWaylandViewporterPrivate::Viewport *viewport = nullptr;
struct {
QWaylandBufferRef buffer;
QRegion damage;
QPoint offset;
- bool newlyAttached;
+ bool newlyAttached = false;
QRegion inputRegion;
- int bufferScale;
+ int bufferScale = 1;
+ QRectF sourceGeometry;
+ QSize destinationSize;
QRegion opaqueRegion;
} pending;
@@ -166,6 +170,8 @@ public: //member variables
QRegion inputRegion;
QRegion opaqueRegion;
+ QRectF sourceGeometry;
+ QSize destinationSize;
QSize bufferSize;
int bufferScale = 1;
bool isCursorSurface = false;
diff --git a/src/compositor/configure.json b/src/compositor/configure.json
index 9a6655241..aabd2472f 100644
--- a/src/compositor/configure.json
+++ b/src/compositor/configure.json
@@ -80,6 +80,12 @@
"type": "compile",
"test": "dmabuf_server_buffer",
"use": "egl"
+ },
+ "dmabuf-client-buffer": {
+ "label": "Linux Client dma-buf Buffer Sharing",
+ "type": "compile",
+ "test": "dmabuf_client_buffer",
+ "use": "egl"
}
},
@@ -128,6 +134,11 @@
"condition": "features.wayland-server && features.opengl && features.egl && tests.dmabuf-server-buffer",
"output": [ "privateFeature" ]
},
+ "wayland-dmabuf-client-buffer": {
+ "label": "Linux dma-buf client buffer integration",
+ "condition": "features.wayland-server && features.opengl && features.egl && tests.dmabuf-client-buffer",
+ "output": [ "privateFeature" ]
+ },
"wayland-shm-emulation-server-buffer": {
"label": "Shm emulation server buffer",
"condition": "features.wayland-server && features.opengl",
diff --git a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
index 6be6444cc..440a793cb 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
@@ -28,65 +28,53 @@
/*!
\page qtwaylandcompositor-index.html
\title Qt Wayland Compositor
- \brief An API to develop display servers supporting the Wayland protocol
-
- \l {https://wayland.freedesktop.org/} {Wayland} is a display server
- protocol to help in creating multi-process systems, where multiple client
- applications may render content on the same display, by going via
- a compositor process.
-
- Compared to a system with a single-process design, a multi-process system
- gives several benefits:
-
- \list
- \li Easier resource management, through the regular operating system mechanisms.
- \li Better security, as each application can run with its own permissions or
- sandbox.
- \li Clearer separation of application UI and compositor UI, so each
- can be modified independently.
- \endlist
-
- In a typical Wayland-based system, multiple client processes will render their
- own contents to off-screen buffers. The information about these buffers will
- then be passed to a display server process by using the Wayland protocol.
- Finally, the display server process will composite and position the contents
- on a physical display.
-
- Qt Wayland Compositor is a module that provides convenient and powerful
- QML and C++ APIs for developing custom display servers based on this protocol.
- The server displays content from client applications that support the Wayland
- protocol. The design philosophy of Wayland is to keep the core protocol simple
- and minimal, and to expand on this with use-case-specific extensions. Qt Wayland
- Compositor supports many common extensions by default, and also has APIs that
- enables the creation of new, custom extensions.
-
- In one typical use case, a display server written with Qt Wayland Compositor will
- be a subsystem inside a larger application manager process. Qt Wayland Compositor
- provides the APIs to communicate with clients and display their contents on screen,
- using C++ for low-level access and the full set of Qt Quick effects, animations and
- convenience when using the QML APIs. A typical application manager would, in addition
- to this, implement features such as application life cycle, virtual keyboard input,
- security and IPC. Qt provides APIs that can be used to develop the remaining parts
- of an application manager in other modules. The \l {https://www.qt.io/qt-automotive-suite/}
- {Qt Automotive Suite} provides a complete application manager which includes a
- display server developed using Qt Wayland Compositor.
+ \brief An API to develop display servers that support the Wayland protocol.
+
+ The Qt Wayland Compositor is a module that provides convenient and powerful
+ QML and C++ APIs for developing custom display servers based on the
+ \l {https://wayland.freedesktop.org/}{Wayland} protocol. The display server,
+ often called a compositor, displays content from client applications that
+ support the Wayland protocol.
+
+ Wayland's design philosophy is to keep the core protocol simple and minimal.
+ Developers can then expand on this core protocol with use-case-specific
+ extensions. Qt Wayland Compositor supports many common extensions by default,
+ and also has APIs to enable the creation of new, custom extensions.
+
+ Typically, a compositor written with Qt Wayland Compositor becomes a
+ subsystem inside a larger application manager process. Qt Wayland Compositor
+ provides the APIs to communicate with clients and display their content on
+ the screen. The QML APIs contain high-level APIs that easily integrate with
+ the rest of Qt, enabling convenient animations, effects, and UI through
+ Qt Quick. There are also C++ APIs available - if you need more low-level
+ access.
+
+ An application manager would typically implement additional features such as
+ application life cycle, virtual keyboard input, security, and Inter-Process
+ Communication (IPC). Qt provides the APIs that can be used to develop the
+ remaining parts of an application manager in other modules. The
+ \l {https://www.qt.io/qt-automotive-suite/}{Qt Automotive Suite} provides
+ \l{Qt Application Manager}, which is a complete application manager that
+ includes a compositor developed using Qt Wayland Compositor.
+
+ For more information on Wayland, see \l{Wayland and Qt}.
\section1 Features of Qt Wayland Compositor
- The Qt Wayland Compositor API includes features needed to create a display server.
+ The Qt Wayland Compositor includes features necessary to create a compositor:
\list
- \li A QML API that can be used to display and manipulate client content, fully
- integrated with all the features in Qt Quick.
- \li A C++ API for low-level access and control.
- \li Support for common extensions, including XDG Shell and IVI Application.
- \li APIs to easily expand support to include custom extensions.
+ \li A QML API to display and manipulate client content, fully integrated
+ with all the features in Qt Quick.
+ \li A C++ API for low-level access and control.
+ \li Support for common extensions, including XDG Shell and IVI Application.
+ \li APIs to easily expand the support for custom extensions.
\endlist
\section1 Environment Variables and Command-line Arguments
- The Qt Wayland Compositor API recognizes some environment variables and
- command-line arguments that can be used to customize its behavior.
+ The Qt Wayland Compositor recognizes the following environment variables and
+ command-line arguments:
\list
\li Environment variables:
@@ -107,8 +95,17 @@
\section1 Examples
- Take a look at the \l{Qt Wayland Compositor Examples} for a demonstration on
- how the APIs can be used to write custom display servers.
+ Take a look at the \l{Qt Wayland Compositor Examples} to learn how these APIs
+ can be used to write custom compositors.
+
+ \section1 API Reference
+
+ The Qt Wayland Compositor can be used from C++ or QML:
+
+ \list
+ \li \l{Qt Wayland Compositor QML Types}
+ \li \l{Qt Wayland Compositor C++ Classes}
+ \endlist
\section1 Licenses and Attributions
@@ -124,13 +121,4 @@
\generatelist{groupsbymodule attributions-qtwaylandcompositor}
- \section1 API Reference
-
- The Qt Wayland Compositor API can be used from C++ or QML.
-
- \list
- \li \l{Qt Wayland Compositor QML Types}
- \li \l{Qt Wayland Compositor C++ Classes}
- \endlist
-
*/
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri
index 5c708f891..361f93984 100644
--- a/src/compositor/extensions/extensions.pri
+++ b/src/compositor/extensions/extensions.pri
@@ -9,6 +9,8 @@ WAYLANDSERVERSOURCES += \
../extensions/qt-key-unstable-v1.xml \
../extensions/qt-windowmanager.xml \
../3rdparty/protocol/text-input-unstable-v2.xml \
+ ../3rdparty/protocol/viewporter.xml \
+ ../3rdparty/protocol/scaler.xml \
../3rdparty/protocol/xdg-shell-unstable-v6.xml \
../3rdparty/protocol/xdg-shell.xml \
../3rdparty/protocol/xdg-decoration-unstable-v1.xml \
@@ -27,6 +29,10 @@ HEADERS += \
extensions/qwaylandtextinputmanager_p.h \
extensions/qwaylandqtwindowmanager.h \
extensions/qwaylandqtwindowmanager_p.h \
+ extensions/qwaylandviewporter.h \
+ extensions/qwaylandviewporter_p.h \
+ extensions/qwaylandwlscaler.h \
+ extensions/qwaylandwlscaler_p.h \
extensions/qwaylandxdgshellv5.h \
extensions/qwaylandxdgshellv5_p.h \
extensions/qwaylandxdgshellv6.h \
@@ -49,6 +55,8 @@ SOURCES += \
extensions/qwaylandtextinput.cpp \
extensions/qwaylandtextinputmanager.cpp \
extensions/qwaylandqtwindowmanager.cpp \
+ extensions/qwaylandviewporter.cpp \
+ extensions/qwaylandwlscaler.cpp \
extensions/qwaylandxdgshellv5.cpp \
extensions/qwaylandxdgshellv6.cpp \
extensions/qwaylandxdgshell.cpp \
diff --git a/src/compositor/extensions/pregenerated/3rdparty/.gitignore b/src/compositor/extensions/pregenerated/3rdparty/.gitignore
new file mode 100644
index 000000000..db253cfaf
--- /dev/null
+++ b/src/compositor/extensions/pregenerated/3rdparty/.gitignore
@@ -0,0 +1,3 @@
+!qwayland-server-*.cpp
+!qwayland-server-*.h
+!wayland-*-protocol.cpp
diff --git a/src/compositor/extensions/pregenerated/3rdparty/qwayland-server-xdg-shell-unstable-v5_p.h b/src/compositor/extensions/pregenerated/3rdparty/qwayland-server-xdg-shell-unstable-v5_p.h
index 63817a5e3..8124860b9 100644
--- a/src/compositor/extensions/pregenerated/3rdparty/qwayland-server-xdg-shell-unstable-v5_p.h
+++ b/src/compositor/extensions/pregenerated/3rdparty/qwayland-server-xdg-shell-unstable-v5_p.h
@@ -71,6 +71,7 @@ namespace QtWaylandServer {
virtual ~Resource() {}
xdg_shell_v5 *xdg_shell_object;
+ xdg_shell_v5 *object() { return xdg_shell_object; }
struct ::wl_resource *handle;
struct ::wl_client *client() const { return wl_resource_get_client(handle); }
@@ -191,6 +192,7 @@ namespace QtWaylandServer {
virtual ~Resource() {}
xdg_surface_v5 *xdg_surface_object;
+ xdg_surface_v5 *object() { return xdg_surface_object; }
struct ::wl_resource *handle;
struct ::wl_client *client() const { return wl_resource_get_client(handle); }
@@ -364,6 +366,7 @@ namespace QtWaylandServer {
virtual ~Resource() {}
xdg_popup_v5 *xdg_popup_object;
+ xdg_popup_v5 *object() { return xdg_popup_object; }
struct ::wl_resource *handle;
struct ::wl_client *client() const { return wl_resource_get_client(handle); }
diff --git a/src/compositor/extensions/pregenerated/3rdparty/wayland-xdg-shell-unstable-v5-server-protocol_p.h b/src/compositor/extensions/pregenerated/3rdparty/wayland-xdg-shell-unstable-v5-server-protocol_p.h
index b979f048c..493fd52d4 100644
--- a/src/compositor/extensions/pregenerated/3rdparty/wayland-xdg-shell-unstable-v5-server-protocol_p.h
+++ b/src/compositor/extensions/pregenerated/3rdparty/wayland-xdg-shell-unstable-v5-server-protocol_p.h
@@ -6,7 +6,7 @@
#include <stdint.h>
#include <stddef.h>
-#include "wayland-server.h"
+#include "wayland-server-core.h"
#ifdef __cplusplus
extern "C" {
diff --git a/src/compositor/extensions/qwaylandiviapplication.cpp b/src/compositor/extensions/qwaylandiviapplication.cpp
index 57b1627b5..a2e9842db 100644
--- a/src/compositor/extensions/qwaylandiviapplication.cpp
+++ b/src/compositor/extensions/qwaylandiviapplication.cpp
@@ -62,8 +62,9 @@ QT_BEGIN_NAMESPACE
* To provide the functionality of the shell extension in a compositor, create
* an instance of the IviApplication component and add it to the list of extensions
* supported by the compositor:
- * \code
- * import QtWayland.Compositor 1.0
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
*
* WaylandCompositor {
* IviApplication {
@@ -74,7 +75,7 @@ QT_BEGIN_NAMESPACE
* }
* }
* }
- * \endcode
+ * \endqml
*/
/*!
@@ -131,6 +132,9 @@ const struct wl_interface *QWaylandIviApplication::interface()
return QWaylandIviApplicationPrivate::interface();
}
+/*!
+ * \internal
+ */
QByteArray QWaylandIviApplication::interfaceName()
{
return QWaylandIviApplicationPrivate::interfaceName();
@@ -140,16 +144,17 @@ QByteArray QWaylandIviApplication::interfaceName()
* \qmlsignal void QtWaylandCompositor::IviApplication::iviSurfaceRequested(WaylandSurface surface, int iviId, WaylandResource resource)
*
* This signal is emitted when the client has requested an \c ivi_surface to be associated
- * with \a surface, which is identified by \a id. The handler for this signal is
- * expected to create the ivi surface and initialize it within the scope of the
+ * with \a surface, which is identified by \a iviId. The handler for this signal is
+ * expected to create the ivi surface for \a resource and initialize it within the scope of the
* signal emission. If no ivi surface is created, a default one will be created instead.
+ *
*/
/*!
* \fn void QWaylandIviApplication::iviSurfaceRequested(QWaylandSurface *surface, uint iviId, const QWaylandResource &resource)
*
* This signal is emitted when the client has requested an \c ivi_surface to be associated
- * with \a surface, which is identified by \a id. The handler for this signal is
+ * with \a surface, which is identified by \a iviId. The handler for this signal is
* expected to create the ivi surface and initialize it within the scope of the
* signal emission. If no ivi surface is created, a default one will be created instead.
*/
diff --git a/src/compositor/extensions/qwaylandivisurface.cpp b/src/compositor/extensions/qwaylandivisurface.cpp
index b6398f060..0ae488def 100644
--- a/src/compositor/extensions/qwaylandivisurface.cpp
+++ b/src/compositor/extensions/qwaylandivisurface.cpp
@@ -47,6 +47,8 @@
#include <QtWaylandCompositor/QWaylandResource>
#include <QDebug>
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
+
QT_BEGIN_NAMESPACE
QWaylandSurfaceRole QWaylandIviSurfacePrivate::s_role("ivi_surface");
@@ -182,10 +184,9 @@ QWaylandSurfaceRole *QWaylandIviSurface::role()
*/
QWaylandIviSurface *QWaylandIviSurface::fromResource(wl_resource *resource)
{
- auto iviSurfaceResource = QWaylandIviSurfacePrivate::Resource::fromResource(resource);
- if (!iviSurfaceResource)
- return nullptr;
- return static_cast<QWaylandIviSurfacePrivate *>(iviSurfaceResource->ivi_surface_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandIviSurfacePrivate *>(resource))
+ return p->q_func();
+ return nullptr;
}
/*!
diff --git a/src/compositor/extensions/qwaylandshellsurface.cpp b/src/compositor/extensions/qwaylandshellsurface.cpp
index 3cfe44895..cb6d03646 100644
--- a/src/compositor/extensions/qwaylandshellsurface.cpp
+++ b/src/compositor/extensions/qwaylandshellsurface.cpp
@@ -87,7 +87,7 @@
*/
/*!
- * \property QWaylandWlShellSurface::windowType
+ * \property QWaylandShellSurface::windowType
*
* This property holds the window type of the QWaylandShellSurface.
*/
diff --git a/src/compositor/extensions/qwaylandtextinput.cpp b/src/compositor/extensions/qwaylandtextinput.cpp
index 6cf33d18d..f60a32a14 100644
--- a/src/compositor/extensions/qwaylandtextinput.cpp
+++ b/src/compositor/extensions/qwaylandtextinput.cpp
@@ -45,12 +45,15 @@
#include "qwaylandsurface.h"
#include "qwaylandview.h"
-#include "qwaylandxkb_p.h"
#include "qwaylandinputmethodeventbuilder_p.h"
#include <QGuiApplication>
#include <QInputMethodEvent>
+#if QT_CONFIG(xkbcommon)
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
QWaylandTextInputClientState::QWaylandTextInputClientState()
@@ -203,11 +206,15 @@ void QWaylandTextInputPrivate::sendKeyEvent(QKeyEvent *event)
// TODO add support for modifiers
- foreach (xkb_keysym_t keysym, QWaylandXkb::toKeysym(event)) {
+#if QT_CONFIG(xkbcommon)
+ for (xkb_keysym_t keysym : QXkbCommon::toKeysym(event)) {
send_keysym(focusResource->handle, event->timestamp(), keysym,
event->type() == QEvent::KeyPress ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED,
0);
}
+#else
+ Q_UNUSED(event);
+#endif
}
void QWaylandTextInputPrivate::sendInputPanelState()
diff --git a/src/compositor/extensions/qwaylandviewporter.cpp b/src/compositor/extensions/qwaylandviewporter.cpp
new file mode 100644
index 000000000..3856c135d
--- /dev/null
+++ b/src/compositor/extensions/qwaylandviewporter.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandviewporter_p.h"
+
+#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandCompositor>
+
+#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWaylandViewporter
+ \inmodule QtWaylandCompositor
+ \since 5.13
+ \brief Provides an extension for surface resizing and cropping.
+
+ The QWaylandViewporter extension provides a way for clients to resize and crop surface
+ contents.
+
+ QWaylandViewporter corresponds to the Wayland interface, \c wp_viewporter.
+*/
+
+/*!
+ Constructs a QWaylandViewporter object.
+*/
+QWaylandViewporter::QWaylandViewporter()
+ : QWaylandCompositorExtensionTemplate<QWaylandViewporter>(*new QWaylandViewporterPrivate)
+{
+}
+
+/*!
+ * Constructs a QWaylandViewporter object for the provided \a compositor.
+ */
+QWaylandViewporter::QWaylandViewporter(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate<QWaylandViewporter>(compositor, *new QWaylandViewporterPrivate())
+{
+}
+
+/*!
+ Initializes the extension.
+*/
+void QWaylandViewporter::initialize()
+{
+ Q_D(QWaylandViewporter);
+
+ QWaylandCompositorExtensionTemplate::initialize();
+ auto *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandViewporter";
+ return;
+ }
+ d->init(compositor->display(), 1);
+}
+
+/*!
+ Returns the Wayland interface for the QWaylandViewporter.
+*/
+const wl_interface *QWaylandViewporter::interface()
+{
+ return QWaylandViewporterPrivate::interface();
+}
+
+void QWaylandViewporterPrivate::wp_viewporter_destroy(Resource *resource)
+{
+ // Viewport objects are allowed ot outlive the viewporter
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandViewporterPrivate::wp_viewporter_get_viewport(Resource *resource, uint id, wl_resource *surfaceResource)
+{
+ auto *surface = QWaylandSurface::fromResource(surfaceResource);
+ if (!surface) {
+ qWarning() << "Couldn't find surface for viewporter";
+ return;
+ }
+
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(surface);
+ if (surfacePrivate->viewport) {
+ wl_resource_post_error(resource->handle, WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS,
+ "viewport already exists for surface");
+ return;
+ }
+
+ surfacePrivate->viewport = new Viewport(surface, resource->client(), id);
+}
+
+QWaylandViewporterPrivate::Viewport::Viewport(QWaylandSurface *surface, wl_client *client, int id)
+ : QtWaylandServer::wp_viewport(client, id, /*version*/ 1)
+ , m_surface(surface)
+{
+ Q_ASSERT(surface);
+}
+
+QWaylandViewporterPrivate::Viewport::~Viewport()
+{
+ if (m_surface) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ Q_ASSERT(surfacePrivate->viewport == this);
+ surfacePrivate->viewport = nullptr;
+ }
+}
+
+// This function has to be called immediately after a surface is committed, before no
+// other client events have been dispatched, or we may incorrectly error out on an
+// incomplete pending state. See comment below.
+void QWaylandViewporterPrivate::Viewport::checkCommittedState()
+{
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+
+ // We can't use the current state for destination/source when checking,
+ // as that has fallbacks to the buffer size so we can't distinguish
+ // between the set/unset case. We use the pending state because no other
+ // requests has modified it yet.
+ QSize destination = surfacePrivate->pending.destinationSize;
+ QRectF source = surfacePrivate->pending.sourceGeometry;
+
+ if (!destination.isValid() && source.size() != source.size().toSize()) {
+ wl_resource_post_error(resource()->handle, error_bad_size,
+ "non-integer size (%fx%f) with unset destination",
+ source.width(), source.height());
+ return;
+ }
+
+ QRectF max = QRectF(QPointF(), m_surface->bufferSize() / m_surface->bufferScale());
+ // We can't use QRectF.contains, because that would return false for values on the border
+ if (max.united(source) != max) {
+ wl_resource_post_error(resource()->handle, error_out_of_buffer,
+ "source %f,%f, %fx%f extends outside attached buffer %fx%f",
+ source.x(), source.y(), source.width(), source.height(),
+ max.width(), max.height());
+ return;
+ }
+}
+
+
+void QWaylandViewporterPrivate::Viewport::wp_viewport_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource);
+ delete this;
+}
+
+void QWaylandViewporterPrivate::Viewport::wp_viewport_destroy(Resource *resource)
+{
+ if (m_surface) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.destinationSize = QSize();
+ surfacePrivate->pending.sourceGeometry = QRectF();
+ }
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandViewporterPrivate::Viewport::wp_viewport_set_source(QtWaylandServer::wp_viewport::Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height)
+{
+ Q_UNUSED(resource);
+
+ if (!m_surface) {
+ wl_resource_post_error(resource->handle, error_no_surface,
+ "set_source requested for destroyed surface");
+ return;
+ }
+
+ QPointF position(wl_fixed_to_double(x), wl_fixed_to_double(y));
+ QSizeF size(wl_fixed_to_double(width), wl_fixed_to_double(height));
+ QRectF sourceGeometry(position, size);
+
+ if (sourceGeometry == QRectF(-1, -1, -1, -1)) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.sourceGeometry = QRectF();
+ return;
+ }
+
+ if (position.x() < 0 || position.y() < 0) {
+ wl_resource_post_error(resource->handle, error_bad_value,
+ "negative position in set_source");
+ return;
+ }
+
+ if (!size.isValid()) {
+ wl_resource_post_error(resource->handle, error_bad_value,
+ "negative size in set_source");
+ return;
+ }
+
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.sourceGeometry = sourceGeometry;
+}
+
+void QWaylandViewporterPrivate::Viewport::wp_viewport_set_destination(QtWaylandServer::wp_viewport::Resource *resource, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource);
+
+ if (!m_surface) {
+ wl_resource_post_error(resource->handle, error_no_surface,
+ "set_destination requested for destroyed surface");
+ return;
+ }
+
+ QSize destinationSize(width, height);
+ if (!destinationSize.isValid() && destinationSize != QSize(-1, -1)) {
+ wl_resource_post_error(resource->handle, error_bad_value,
+ "negative size in set_destination");
+ return;
+ }
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.destinationSize = destinationSize;
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandviewporter.h b/src/compositor/extensions/qwaylandviewporter.h
new file mode 100644
index 000000000..811c74145
--- /dev/null
+++ b/src/compositor/extensions/qwaylandviewporter.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDVIEWPORTER_H
+#define QWAYLANDVIEWPORTER_H
+
+#include <QtWaylandCompositor/QWaylandCompositorExtension>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandViewporterPrivate;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandViewporter
+ : public QWaylandCompositorExtensionTemplate<QWaylandViewporter>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandViewporter)
+
+public:
+ explicit QWaylandViewporter();
+ explicit QWaylandViewporter(QWaylandCompositor *compositor);
+
+ void initialize() override;
+
+ static const struct wl_interface *interface();
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDVIEWPORTER_H
diff --git a/src/compositor/extensions/qwaylandviewporter_p.h b/src/compositor/extensions/qwaylandviewporter_p.h
new file mode 100644
index 000000000..d22da6990
--- /dev/null
+++ b/src/compositor/extensions/qwaylandviewporter_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDVIEWPORTER_P_H
+#define QWAYLANDVIEWPORTER_P_H
+
+#include "qwaylandviewporter.h"
+
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-viewporter.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandSurface;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandViewporterPrivate
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::wp_viewporter
+{
+ Q_DECLARE_PUBLIC(QWaylandViewporter)
+public:
+ explicit QWaylandViewporterPrivate() = default;
+
+ class Q_WAYLAND_COMPOSITOR_EXPORT Viewport
+ : public QtWaylandServer::wp_viewport
+ {
+ public:
+ explicit Viewport(QWaylandSurface *surface, wl_client *client, int id);
+ ~Viewport() override;
+ void checkCommittedState();
+
+ protected:
+ void wp_viewport_destroy_resource(Resource *resource) override;
+ void wp_viewport_destroy(Resource *resource) override;
+ void wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override;
+ void wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height) override;
+
+ private:
+ QPointer<QWaylandSurface> m_surface = nullptr;
+ };
+
+protected:
+ void wp_viewporter_destroy(Resource *resource) override;
+ void wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDVIEWPORTER_P_H
diff --git a/src/compositor/extensions/qwaylandwlscaler.cpp b/src/compositor/extensions/qwaylandwlscaler.cpp
new file mode 100644
index 000000000..5c8e4b270
--- /dev/null
+++ b/src/compositor/extensions/qwaylandwlscaler.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandwlscaler_p.h"
+
+#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandCompositor>
+
+#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_DEPRECATED_SINCE(5, 13)
+/*!
+ \qmltype WlScaler
+ \inqmlmodule QtWayland.Compositor
+ \since 5.13
+ \brief Provides an extension for surface resizing and cropping.
+
+ The WlScaler extension provides a way for clients to resize and crop surface contents.
+
+ WlScaler corresponds to the Wayland interface, \c wl_scaler.
+
+ \c wl_scaler is a non-standard and deprecated protocol that has largely been replaced by
+ \c wp_viewporter. I.e. This extensions is only useful for supporting legacy clients.
+ \c wp_viewporter support is enabled automatically for all Qml compositors.
+
+ To provide the functionality of the extension in a compositor, create an instance of the
+ WlScaler component and add it to the list of extensions supported by the compositor:
+
+ \qml \QtMinorVersion
+ import QtWayland.Compositor 1.\1
+
+ WaylandCompositor {
+ // ...
+ WlScaler {}
+ }
+ \endqml
+
+ \deprecated
+*/
+
+/*!
+ \class QWaylandWlScaler
+ \inmodule QtWaylandCompositor
+ \since 5.13
+ \brief Provides an extension for surface resizing and croping.
+
+ The QWaylandWlScaler extension provides a way for clients to resize and crop surface
+ contents.
+
+ QWaylandWlScaler corresponds to the Wayland interface, \c wl_scaler.
+
+ \c wl_scaler is a non-standard and deprecated protocol that has largely been replaced by
+ \c wp_viewporter. I.e. This extensions is only useful for supporting legacy clients.
+
+ \sa QWaylandViewporter
+
+ \deprecated
+*/
+
+/*!
+ Constructs a QWaylandWlScaler object.
+*/
+QWaylandWlScaler::QWaylandWlScaler()
+ : QWaylandCompositorExtensionTemplate<QWaylandWlScaler>(*new QWaylandWlScalerPrivate)
+{
+}
+
+/*!
+ * Constructs a QWaylandWlScaler object for the provided \a compositor.
+ */
+QWaylandWlScaler::QWaylandWlScaler(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate<QWaylandWlScaler>(compositor, *new QWaylandWlScalerPrivate())
+{
+}
+
+/*!
+ Initializes the extension.
+*/
+void QWaylandWlScaler::initialize()
+{
+ Q_D(QWaylandWlScaler);
+
+ QWaylandCompositorExtensionTemplate::initialize();
+ auto *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandWlScaler";
+ return;
+ }
+ d->init(compositor->display(), 2);
+}
+
+/*!
+ Returns the Wayland interface for the QWaylandWlScaler.
+*/
+const wl_interface *QWaylandWlScaler::interface()
+{
+ return QWaylandWlScalerPrivate::interface();
+}
+
+void QWaylandWlScalerPrivate::scaler_destroy(Resource *resource)
+{
+ // Viewport objects are allowed ot outlive the scaler
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandWlScalerPrivate::scaler_get_viewport(Resource *resource, uint id, wl_resource *surfaceResource)
+{
+ auto *surface = QWaylandSurface::fromResource(surfaceResource);
+ if (!surface) {
+ qWarning() << "Couldn't find surface for viewporter";
+ return;
+ }
+
+ // Note: This will only protect us not creating scalers for surfaces with wp_viewport objects
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(surface);
+ if (surfacePrivate->viewport) {
+ wl_resource_post_error(resource->handle, WL_SCALER_ERROR_VIEWPORT_EXISTS,
+ "viewport already exists for surface");
+ return;
+ }
+
+ // We can't set viewport here, since it's of the new type for wp_viewporter
+// surfacePrivate->viewport = new Viewport(surface, resource->client(), id, resource->version());
+ new Viewport(surface, resource->client(), id, resource->version());
+}
+
+QWaylandWlScalerPrivate::Viewport::Viewport(QWaylandSurface *surface, wl_client *client, int id, int version)
+ : QtWaylandServer::wl_viewport(client, id, version)
+ , m_surface(surface)
+{
+ Q_ASSERT(surface);
+}
+
+//TODO: This isn't currently called
+// This function has to be called immediately after a surface is committed, before no
+// other client events have been dispatched, or we may incorrectly error out on an
+// incomplete pending state. See comment below.
+void QWaylandWlScalerPrivate::Viewport::checkCommittedState()
+{
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+
+ // We can't use the current state for destination/source when checking,
+ // as that has fallbacks to the buffer size so we can't distinguish
+ // between the set/unset case. We use the pending state because no other
+ // requests has modified it yet.
+ QSize destination = surfacePrivate->pending.destinationSize;
+ QRectF source = surfacePrivate->pending.sourceGeometry;
+
+ if (!destination.isValid() && source.size() != source.size().toSize()) {
+ //TODO: Do rounding to nearest integer
+ }
+
+ QRectF max = QRectF(QPointF(), m_surface->bufferSize() / m_surface->bufferScale());
+ // We can't use QRectF.contains, because that would return false for values on the border
+ if (max.united(source) != max) {
+ //TODO: surface contents are no undefined, surface size is still valid though
+ qCDebug(qLcWaylandCompositor) << "Source set outside buffer bounds (client error)";
+ }
+}
+
+
+void QWaylandWlScalerPrivate::Viewport::viewport_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource);
+ delete this;
+}
+
+void QWaylandWlScalerPrivate::Viewport::viewport_destroy(Resource *resource)
+{
+ if (m_surface) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.destinationSize = QSize();
+ surfacePrivate->pending.sourceGeometry = QRectF();
+ }
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandWlScalerPrivate::Viewport::viewport_set(QtWaylandServer::wl_viewport::Resource *resource, wl_fixed_t src_x, wl_fixed_t src_y, wl_fixed_t src_width, wl_fixed_t src_height, int32_t dst_width, int32_t dst_height)
+{
+ viewport_set_source(resource, src_x, src_y, src_width, src_height);
+ viewport_set_destination(resource, dst_width, dst_height);
+}
+
+void QWaylandWlScalerPrivate::Viewport::viewport_set_source(QtWaylandServer::wl_viewport::Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height)
+{
+ Q_UNUSED(resource);
+
+ if (!m_surface) {
+ qCDebug(qLcWaylandCompositor) << "set_source requested for destroyed surface";
+ return;
+ }
+
+ QPointF position(wl_fixed_to_double(x), wl_fixed_to_double(y));
+ QSizeF size(wl_fixed_to_double(width), wl_fixed_to_double(height));
+ QRectF sourceGeometry(position, size);
+
+ if (sourceGeometry == QRectF(-1, -1, -1, -1)) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.sourceGeometry = QRectF();
+ return;
+ }
+
+ if (position.x() < 0 || position.y() < 0) {
+ wl_resource_post_error(resource->handle, error_bad_value,
+ "negative position in set_source");
+ return;
+ }
+
+ if (!size.isValid()) {
+ wl_resource_post_error(resource->handle, error_bad_value,
+ "negative size in set_source");
+ return;
+ }
+
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.sourceGeometry = sourceGeometry;
+}
+
+void QWaylandWlScalerPrivate::Viewport::viewport_set_destination(QtWaylandServer::wl_viewport::Resource *resource, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource);
+
+ if (!m_surface) {
+ qCDebug(qLcWaylandCompositor) << "set_destination requested for destroyed surface";
+ return;
+ }
+
+ QSize destinationSize(width, height);
+ if (!destinationSize.isValid() && destinationSize != QSize(-1, -1)) {
+ wl_resource_post_error(resource->handle, error_bad_value,
+ "negative size in set_destination");
+ return;
+ }
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface);
+ surfacePrivate->pending.destinationSize = destinationSize;
+}
+#endif // QT_DEPRECATED_SINCE
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandwlscaler.h b/src/compositor/extensions/qwaylandwlscaler.h
new file mode 100644
index 000000000..4ecdf3968
--- /dev/null
+++ b/src/compositor/extensions/qwaylandwlscaler.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDWLSCALER_H
+#define QWAYLANDWLSCALER_H
+
+#include <QtWaylandCompositor/QWaylandCompositorExtension>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_DEPRECATED_SINCE(5, 13)
+class QWaylandWlScalerPrivate;
+
+// TODO: We should have used the QT_DEPRECATED macro here, but for some reason
+// header file generation stops working when that's added.
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlScaler
+ : public QWaylandCompositorExtensionTemplate<QWaylandWlScaler>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandWlScaler)
+
+public:
+ explicit QWaylandWlScaler();
+ explicit QWaylandWlScaler(QWaylandCompositor *compositor);
+
+ void initialize() override;
+
+ static const struct wl_interface *interface();
+};
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDWLSCALER_H
diff --git a/src/compositor/extensions/qwaylandwlscaler_p.h b/src/compositor/extensions/qwaylandwlscaler_p.h
new file mode 100644
index 000000000..d3c2edd76
--- /dev/null
+++ b/src/compositor/extensions/qwaylandwlscaler_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDWLSCALER_P_H
+#define QWAYLANDWLSCALER_P_H
+
+#include "qwaylandwlscaler.h"
+
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-scaler.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandSurface;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlScalerPrivate
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::wl_scaler
+{
+ Q_DECLARE_PUBLIC(QWaylandWlScaler)
+public:
+ explicit QWaylandWlScalerPrivate() = default;
+
+protected:
+ void scaler_destroy(Resource *resource) override;
+ void scaler_get_viewport(Resource *resource, uint32_t id, wl_resource *surface) override;
+
+private:
+ class Viewport : public QtWaylandServer::wl_viewport
+ {
+ public:
+ explicit Viewport(QWaylandSurface *surface, wl_client *client, int id, int version);
+ void checkCommittedState();
+
+ protected:
+ void viewport_destroy_resource(Resource *resource) override;
+ void viewport_destroy(Resource *resource) override;
+ void viewport_set(Resource *resource, wl_fixed_t src_x, wl_fixed_t src_y, wl_fixed_t src_width, wl_fixed_t src_height, int32_t dst_width, int32_t dst_height) override;
+ void viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override;
+ void viewport_set_destination(Resource *resource, int32_t width, int32_t height) override;
+
+ private:
+ QPointer<QWaylandSurface> m_surface = nullptr;
+ };
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDWLSCALER_P_H
diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp
index d932a06c9..9871a8a5a 100644
--- a/src/compositor/extensions/qwaylandwlshell.cpp
+++ b/src/compositor/extensions/qwaylandwlshell.cpp
@@ -44,6 +44,7 @@
#ifdef QT_WAYLAND_COMPOSITOR_QUICK
#include "qwaylandwlshellintegration_p.h"
#endif
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/QWaylandView>
@@ -266,15 +267,16 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_class(Resource *resource,
* To provide the functionality of the shell extension in a compositor, create
* an instance of the WlShell component and add it to the list of extensions
* supported by the compositor:
- * \code
- * import QtWayland.Compositor 1.0
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
*
* WaylandCompositor {
* WlShell {
* // ...
* }
* }
- * \endcode
+ * \endqml
*/
/*!
@@ -699,9 +701,8 @@ void QWaylandWlShellSurface::ping()
*/
QWaylandWlShellSurface *QWaylandWlShellSurface::fromResource(wl_resource *resource)
{
- QWaylandWlShellSurfacePrivate::Resource *res = QWaylandWlShellSurfacePrivate::Resource::fromResource(resource);
- if (res)
- return static_cast<QWaylandWlShellSurfacePrivate *>(res->shell_surface_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandWlShellSurfacePrivate *>(resource))
+ return p->q_func();
return nullptr;
}
diff --git a/src/compositor/extensions/qwaylandwlshell_p.h b/src/compositor/extensions/qwaylandwlshell_p.h
index b2beca169..dbf6e794f 100644
--- a/src/compositor/extensions/qwaylandwlshell_p.h
+++ b/src/compositor/extensions/qwaylandwlshell_p.h
@@ -47,7 +47,7 @@
#include <QtWaylandCompositor/QWaylandWlShellSurface>
#include <QtWaylandCompositor/QWaylandSeat>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
#include <QHash>
#include <QPoint>
#include <QSet>
diff --git a/src/compositor/extensions/qwaylandwlshellintegration.cpp b/src/compositor/extensions/qwaylandwlshellintegration.cpp
index 896b1587d..99a2e7655 100644
--- a/src/compositor/extensions/qwaylandwlshellintegration.cpp
+++ b/src/compositor/extensions/qwaylandwlshellintegration.cpp
@@ -84,8 +84,7 @@ void WlShellIntegration::handleStartResize(QWaylandSeat *seat, QWaylandWlShellSu
grabberState = GrabberState::Resize;
resizeState.seat = seat;
resizeState.resizeEdges = edges;
- float scaleFactor = m_item->view()->output()->scaleFactor();
- resizeState.initialSize = m_shellSurface->surface()->size() / scaleFactor;
+ resizeState.initialSize = m_shellSurface->surface()->destinationSize();
resizeState.initialized = false;
}
@@ -217,9 +216,7 @@ void WlShellIntegration::handleSetPopup(QWaylandSeat *seat, QWaylandSurface *par
t.clear(&t);
m_item->setRotation(0);
m_item->setScale(1.0);
- auto scaleFactor = m_item->output()->scaleFactor() / devicePixelRatio();
- m_item->setX(relativeToParent.x() * scaleFactor);
- m_item->setY(relativeToParent.y() * scaleFactor);
+ m_item->setPosition(m_item->mapFromSurface(relativeToParent));
m_item->setParentItem(parentItem);
}
@@ -267,7 +264,7 @@ void WlShellIntegration::handleShellSurfaceDestroyed()
void WlShellIntegration::handleSurfaceHasContentChanged()
{
- if (m_shellSurface && m_shellSurface->surface()->size().isEmpty()
+ if (m_shellSurface && m_shellSurface->surface()->destinationSize().isEmpty()
&& m_shellSurface->windowType() == Qt::WindowType::Popup) {
handlePopupClosed();
}
@@ -287,9 +284,8 @@ void WlShellIntegration::adjustOffsetForNextFrame(const QPointF &offset)
if (!m_item->view()->isPrimary())
return;
- float scaleFactor = m_item->view()->output()->scaleFactor();
QQuickItem *moveItem = m_item->moveItem();
- moveItem->setPosition(moveItem->position() + offset * scaleFactor / devicePixelRatio());
+ moveItem->setPosition(moveItem->position() + m_item->mapFromSurface(offset));
}
bool WlShellIntegration::mouseMoveEvent(QMouseEvent *event)
diff --git a/src/compositor/extensions/qwaylandwlshellintegration_p.h b/src/compositor/extensions/qwaylandwlshellintegration_p.h
index ff236e636..8af54dfc4 100644
--- a/src/compositor/extensions/qwaylandwlshellintegration_p.h
+++ b/src/compositor/extensions/qwaylandwlshellintegration_p.h
@@ -100,14 +100,14 @@ private:
struct {
QWaylandSeat *seat = nullptr;
QPointF initialOffset;
- bool initialized;
+ bool initialized = false;
} moveState;
struct {
QWaylandSeat *seat = nullptr;
QWaylandWlShellSurface::ResizeEdge resizeEdges;
QSizeF initialSize;
QPointF initialMousePos;
- bool initialized;
+ bool initialized = false;
} resizeState;
bool isPopup = false;
diff --git a/src/compositor/extensions/qwaylandxdgdecorationv1.cpp b/src/compositor/extensions/qwaylandxdgdecorationv1.cpp
index 1abd5e3fc..2d283ddf9 100644
--- a/src/compositor/extensions/qwaylandxdgdecorationv1.cpp
+++ b/src/compositor/extensions/qwaylandxdgdecorationv1.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
\qmltype XdgDecorationManagerV1
\inqmlmodule QtWayland.Compositor
\since 5.12
- \brief Provides an extension for negotiation of server-side and client-side window decorations
+ \brief Provides an extension for negotiation of server-side and client-side window decorations.
The XdgDecorationManagerV1 extension provides a way for a compositor to announce support for
server-side window decorations, and for xdg-shell clients to communicate whether they prefer
@@ -59,8 +59,8 @@ QT_BEGIN_NAMESPACE
To provide the functionality of the extension in a compositor, create an instance of the
XdgDecorationManagerV1 component and add it to the list of extensions supported by the compositor:
- \code
- import QtWayland.Compositor 1.3
+ \qml \QtMinorVersion
+ import QtWayland.Compositor 1.\1
WaylandCompositor {
// Xdg decoration manager assumes xdg-shell is being used
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
preferredMode: XdgToplevel.ServerSideDecoration
}
}
- \endcode
+ \endqml
\sa XdgToplevel::decorationMode
*/
@@ -82,7 +82,7 @@ QT_BEGIN_NAMESPACE
\class QWaylandXdgDecorationManagerV1
\inmodule QtWaylandCompositor
\since 5.12
- \brief Provides an extension for negotiation of server-side and client-side window decorations
+ \brief Provides an extension for negotiation of server-side and client-side window decorations.
The QWaylandXdgDecorationManagerV1 extension provides a way for a compositor to announce support
for server-side window decorations, and for xdg-shell clients to communicate whether they prefer
diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp
index bd332287e..eb7b958b4 100644
--- a/src/compositor/extensions/qwaylandxdgshell.cpp
+++ b/src/compositor/extensions/qwaylandxdgshell.cpp
@@ -40,6 +40,7 @@
#ifdef QT_WAYLAND_COMPOSITOR_QUICK
#include "qwaylandxdgshellintegration_p.h"
#endif
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/QWaylandSeat>
@@ -153,15 +154,16 @@ void QWaylandXdgShellPrivate::xdg_wm_base_pong(Resource *resource, uint32_t seri
* To provide the functionality of the shell extension in a compositor, create
* an instance of the XdgShell component and add it to the list of extensions
* supported by the compositor:
- * \code
- * import QtWayland.Compositor 1.3
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
*
* WaylandCompositor {
* XdgShell {
* // ...
* }
* }
- * \endcode
+ * \endqml
*/
/*!
@@ -311,7 +313,7 @@ QRect QWaylandXdgSurfacePrivate::calculateFallbackWindowGeometry() const
{
// TODO: The unset window geometry should include subsurfaces as well, so this solution
// won't work too well on those kinds of clients.
- return QRect(QPoint(0, 0), m_surface->size() / m_surface->bufferScale());
+ return QRect(QPoint(), m_surface->destinationSize());
}
void QWaylandXdgSurfacePrivate::updateFallbackWindowGeometry()
@@ -385,6 +387,7 @@ void QWaylandXdgSurfacePrivate::xdg_surface_get_popup(QtWaylandServer::xdg_surfa
"xdg_surface.get_popup without positioner");
return;
}
+
if (!positioner->m_data.isComplete()) {
QWaylandXdgPositionerData p = positioner->m_data;
wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POSITIONER,
@@ -393,6 +396,17 @@ void QWaylandXdgSurfacePrivate::xdg_surface_get_popup(QtWaylandServer::xdg_surfa
return;
}
+ QRect anchorBounds(QPoint(0, 0), parent->windowGeometry().size());
+ if (!anchorBounds.contains(positioner->m_data.anchorRect)) {
+ // TODO: this is a protocol error and should ideally be handled like this:
+ //wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POSITIONER,
+ // "xdg_positioner anchor rect extends beyound its parent's window geometry");
+ //return;
+ // However, our own clients currently do this, so we'll settle for a gentle warning instead.
+ qCWarning(qLcWaylandCompositor) << "Ignoring client protocol error: xdg_positioner anchor"
+ << "rect extends beyond its parent's window geometry";
+ }
+
if (!m_surface->setRole(QWaylandXdgPopup::role(), resource->handle, XDG_WM_BASE_ERROR_ROLE))
return;
@@ -510,7 +524,7 @@ void QWaylandXdgSurface::initialize(QWaylandXdgShell *xdgShell, QWaylandSurface
d->init(resource.resource());
setExtensionContainer(surface);
d->m_windowGeometry = d->calculateFallbackWindowGeometry();
- connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurface::handleSurfaceSizeChanged);
+ connect(surface, &QWaylandSurface::destinationSizeChanged, this, &QWaylandXdgSurface::handleSurfaceSizeChanged);
connect(surface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandXdgSurface::handleBufferScaleChanged);
emit shellChanged();
emit surfaceChanged();
@@ -674,10 +688,9 @@ QByteArray QWaylandXdgSurface::interfaceName()
*/
QWaylandXdgSurface *QWaylandXdgSurface::fromResource(wl_resource *resource)
{
- auto xsResource = QWaylandXdgSurfacePrivate::Resource::fromResource(resource);
- if (!xsResource)
- return nullptr;
- return static_cast<QWaylandXdgSurfacePrivate *>(xsResource->xdg_surface_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandXdgSurfacePrivate *>(resource))
+ return p->q_func();
+ return nullptr;
}
#ifdef QT_WAYLAND_COMPOSITOR_QUICK
@@ -1182,8 +1195,8 @@ QWaylandSurfaceRole *QWaylandXdgToplevel::role()
*/
QWaylandXdgToplevel *QWaylandXdgToplevel::fromResource(wl_resource *resource)
{
- if (auto *r = QWaylandXdgToplevelPrivate::Resource::fromResource(resource))
- return static_cast<QWaylandXdgToplevelPrivate *>(r->xdg_toplevel_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandXdgToplevelPrivate *>(resource))
+ return p->q_func();
return nullptr;
}
@@ -1869,16 +1882,13 @@ QWaylandXdgPopupPrivate::QWaylandXdgPopupPrivate(QWaylandXdgSurface *xdgSurface,
QWaylandXdgPositioner *positioner, const QWaylandResource &resource)
: m_xdgSurface(xdgSurface)
, m_parentXdgSurface(parentXdgSurface)
+ , m_positionerData(positioner->m_data)
{
+ Q_ASSERT(m_positionerData.isComplete());
init(resource.resource());
- m_positionerData = positioner->m_data;
-
- if (!m_positionerData.isComplete())
- qWarning() << "Trying to create xdg popup with incomplete positioner";
QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::Popup);
- //TODO: positioner rect may not extend parent's window geometry, enforce this?
//TODO: Need an API for sending a different initial configure
sendConfigure(QRect(m_positionerData.unconstrainedPosition(), m_positionerData.size));
}
@@ -2064,9 +2074,7 @@ void QWaylandXdgPositioner::xdg_positioner_set_offset(QtWaylandServer::xdg_posit
QWaylandXdgPositioner *QWaylandXdgPositioner::fromResource(wl_resource *resource)
{
- if (auto *r = Resource::fromResource(resource))
- return static_cast<QWaylandXdgPositioner *>(r->xdg_positioner_object);
- return nullptr;
+ return QtWayland::fromResource<QWaylandXdgPositioner *>(resource);
}
Qt::Edges QWaylandXdgPositioner::convertToEdges(anchor anchor)
diff --git a/src/compositor/extensions/qwaylandxdgshellintegration.cpp b/src/compositor/extensions/qwaylandxdgshellintegration.cpp
index cc8faf6c7..3de52944b 100644
--- a/src/compositor/extensions/qwaylandxdgshellintegration.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellintegration.cpp
@@ -73,7 +73,7 @@ XdgToplevelIntegration::XdgToplevelIntegration(QWaylandQuickShellSurfaceItem *it
connect(m_xdgSurface->shell(), &QWaylandXdgShell::popupCreated, this, [item](QWaylandXdgPopup *popup, QWaylandXdgSurface *){
handlePopupCreated(item, popup);
});
- connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgToplevelIntegration::handleSurfaceSizeChanged);
+ connect(m_xdgSurface->surface(), &QWaylandSurface::destinationSizeChanged, this, &XdgToplevelIntegration::handleSurfaceSizeChanged);
connect(m_toplevel, &QObject::destroyed, this, &XdgToplevelIntegration::handleToplevelDestroyed);
}
@@ -130,7 +130,7 @@ void XdgToplevelIntegration::handleStartResize(QWaylandSeat *seat, Qt::Edges edg
resizeState.resizeEdges = edges;
resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size();
resizeState.initialPosition = m_item->moveItem()->position();
- resizeState.initialSurfaceSize = m_item->surface()->size();
+ resizeState.initialSurfaceSize = m_item->surface()->destinationSize();
resizeState.initialized = false;
}
@@ -247,14 +247,14 @@ void XdgToplevelIntegration::handleActivatedChanged()
void XdgToplevelIntegration::handleSurfaceSizeChanged()
{
if (grabberState == GrabberState::Resize) {
- qreal x = resizeState.initialPosition.x();
- qreal y = resizeState.initialPosition.y();
+ qreal dx = 0;
+ qreal dy = 0;
if (resizeState.resizeEdges & Qt::TopEdge)
- y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height();
-
+ dy = resizeState.initialSurfaceSize.height() - m_item->surface()->destinationSize().height();
if (resizeState.resizeEdges & Qt::LeftEdge)
- x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width();
- m_item->moveItem()->setPosition(QPointF(x, y));
+ dx = resizeState.initialSurfaceSize.width() - m_item->surface()->destinationSize().width();
+ QPointF offset = m_item->mapFromSurface({dx, dy});
+ m_item->moveItem()->setPosition(resizeState.initialPosition + offset);
}
}
@@ -285,11 +285,11 @@ void XdgPopupIntegration::handleGeometryChanged()
{
if (m_item->view()->output()) {
const QPoint windowOffset = m_popup->parentXdgSurface()->windowGeometry().topLeft();
- const QPoint position = m_popup->unconstrainedPosition() + windowOffset;
+ const QPoint surfacePosition = m_popup->unconstrainedPosition() + windowOffset;
+ const QPoint itemPosition = m_item->mapFromSurface(surfacePosition).toPoint();
//TODO: positioner size or other size...?
- const float scaleFactor = m_item->view()->output()->scaleFactor();
//TODO check positioner constraints etc... sliding, flipping
- m_item->moveItem()->setPosition(position * scaleFactor);
+ m_item->moveItem()->setPosition(itemPosition);
} else {
qWarning() << "XdgPopupIntegration popup item without output" << m_item;
}
diff --git a/src/compositor/extensions/qwaylandxdgshellv5.cpp b/src/compositor/extensions/qwaylandxdgshellv5.cpp
index a6e88aabb..0628f55e7 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv5.cpp
@@ -43,6 +43,7 @@
#ifdef QT_WAYLAND_COMPOSITOR_QUICK
#include "qwaylandxdgshellv5integration_p.h"
#endif
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/QWaylandSurface>
@@ -249,7 +250,7 @@ QRect QWaylandXdgSurfaceV5Private::calculateFallbackWindowGeometry() const
{
// TODO: The unset window geometry should include subsurfaces as well, so this solution
// won't work too well on those kinds of clients.
- return QRect(QPoint(0, 0), m_surface->size() / m_surface->bufferScale());
+ return QRect(QPoint(), m_surface->destinationSize());
}
void QWaylandXdgSurfaceV5Private::updateFallbackWindowGeometry()
@@ -512,15 +513,17 @@ void QWaylandXdgPopupV5Private::xdg_popup_destroy(Resource *resource)
*
* To provide the functionality of the shell extension in a compositor, create
* an instance of the XdgShellV5 component and add it as a child of the
- * compositor: \code
- * import QtWayland.Compositor 1.0
+ * compositor:
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
*
* WaylandCompositor {
* XdgShellV5 {
* // ...
* }
* }
- * \endcode
+ * \endqml
*
* \deprecated
*/
@@ -837,7 +840,7 @@ void QWaylandXdgSurfaceV5::initialize(QWaylandXdgShellV5 *xdgShell, QWaylandSurf
d->init(resource.resource());
setExtensionContainer(surface);
d->m_windowGeometry = d->calculateFallbackWindowGeometry();
- connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurfaceV5::handleSurfaceSizeChanged);
+ connect(surface, &QWaylandSurface::destinationSizeChanged, this, &QWaylandXdgSurfaceV5::handleSurfaceSizeChanged);
connect(surface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandXdgSurfaceV5::handleBufferScaleChanged);
emit shellChanged();
emit surfaceChanged();
@@ -1179,10 +1182,9 @@ QWaylandSurfaceRole *QWaylandXdgSurfaceV5::role()
*/
QWaylandXdgSurfaceV5 *QWaylandXdgSurfaceV5::fromResource(wl_resource *resource)
{
- auto xsResource = QWaylandXdgSurfaceV5Private::Resource::fromResource(resource);
- if (!xsResource)
- return nullptr;
- return static_cast<QWaylandXdgSurfaceV5Private *>(xsResource->xdg_surface_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandXdgSurfaceV5Private *>(resource))
+ return p->q_func();
+ return nullptr;
}
QSize QWaylandXdgSurfaceV5::sizeForResize(const QSizeF &size, const QPointF &delta,
@@ -1497,10 +1499,9 @@ QWaylandSurfaceRole *QWaylandXdgPopupV5::role()
QWaylandXdgPopupV5 *QWaylandXdgPopupV5::fromResource(wl_resource *resource)
{
- auto popupResource = QWaylandXdgPopupV5Private::Resource::fromResource(resource);
- if (!popupResource)
- return nullptr;
- return static_cast<QWaylandXdgPopupV5Private *>(popupResource->xdg_popup_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandXdgPopupV5Private *>(resource))
+ return p->q_func();
+ return nullptr;
}
void QWaylandXdgPopupV5::sendPopupDone()
diff --git a/src/compositor/extensions/qwaylandxdgshellv5integration.cpp b/src/compositor/extensions/qwaylandxdgshellv5integration.cpp
index ea04a33d2..1d63632a3 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5integration.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv5integration.cpp
@@ -71,7 +71,7 @@ XdgShellV5Integration::XdgShellV5Integration(QWaylandQuickShellSurfaceItem *item
connect(m_xdgSurface, &QWaylandXdgSurfaceV5::unsetMaximized, this, &XdgShellV5Integration::handleUnsetMaximized);
connect(m_xdgSurface, &QWaylandXdgSurfaceV5::maximizedChanged, this, &XdgShellV5Integration::handleMaximizedChanged);
connect(m_xdgSurface, &QWaylandXdgSurfaceV5::activatedChanged, this, &XdgShellV5Integration::handleActivatedChanged);
- connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgShellV5Integration::handleSurfaceSizeChanged);
+ connect(m_xdgSurface->surface(), &QWaylandSurface::destinationSizeChanged, this, &XdgShellV5Integration::handleSurfaceSizeChanged);
connect(m_xdgSurface->shell(), &QWaylandXdgShellV5::xdgPopupCreated, this, [item](QWaylandXdgPopupV5 *popup){
handlePopupCreated(item, popup);
});
@@ -139,7 +139,7 @@ void XdgShellV5Integration::handleStartResize(QWaylandSeat *seat, QWaylandXdgSur
resizeState.resizeEdges = edges;
resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size();
resizeState.initialPosition = m_item->moveItem()->position();
- resizeState.initialSurfaceSize = m_item->surface()->size();
+ resizeState.initialSurfaceSize = m_item->surface()->destinationSize();
resizeState.initialized = false;
}
@@ -194,14 +194,14 @@ void XdgShellV5Integration::handleActivatedChanged()
void XdgShellV5Integration::handleSurfaceSizeChanged()
{
if (grabberState == GrabberState::Resize) {
- qreal x = resizeState.initialPosition.x();
- qreal y = resizeState.initialPosition.y();
+ qreal dx = 0;
+ qreal dy = 0;
if (resizeState.resizeEdges & QWaylandXdgSurfaceV5::ResizeEdge::TopEdge)
- y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height();
-
+ dy = resizeState.initialSurfaceSize.height() - m_item->surface()->destinationSize().height();
if (resizeState.resizeEdges & QWaylandXdgSurfaceV5::ResizeEdge::LeftEdge)
- x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width();
- m_item->moveItem()->setPosition(QPointF(x, y));
+ dx = resizeState.initialSurfaceSize.width() - m_item->surface()->destinationSize().width();
+ QPointF offset = m_item->mapFromSurface({dx, dy});
+ m_item->moveItem()->setPosition(resizeState.initialPosition + offset);
}
}
@@ -212,10 +212,12 @@ XdgPopupV5Integration::XdgPopupV5Integration(QWaylandQuickShellSurfaceItem *item
, m_xdgShell(QWaylandXdgPopupV5Private::get(m_xdgPopup)->m_xdgShell)
{
item->setSurface(m_xdgPopup->surface());
- if (item->view()->output())
- item->moveItem()->setPosition(QPointF(m_xdgPopup->position() * item->view()->output()->scaleFactor()));
- else
+ if (item->view()->output()) {
+ QPoint position = item->mapFromSurface(m_xdgPopup->position()).toPoint();
+ item->moveItem()->setPosition(position);
+ } else {
qWarning() << "XdgPopupV5Integration popup item without output" << item;
+ }
QWaylandClient *client = m_xdgPopup->surface()->client();
auto shell = m_xdgShell;
diff --git a/src/compositor/extensions/qwaylandxdgshellv5integration_p.h b/src/compositor/extensions/qwaylandxdgshellv5integration_p.h
index b2c16c6d9..5d0e1e142 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5integration_p.h
+++ b/src/compositor/extensions/qwaylandxdgshellv5integration_p.h
@@ -91,7 +91,7 @@ private:
struct {
QWaylandSeat *seat = nullptr;
QPointF initialOffset;
- bool initialized;
+ bool initialized = false;
} moveState;
struct {
@@ -101,7 +101,7 @@ private:
QPointF initialMousePos;
QPointF initialPosition;
QSize initialSurfaceSize;
- bool initialized;
+ bool initialized = false;
} resizeState;
struct {
diff --git a/src/compositor/extensions/qwaylandxdgshellv6.cpp b/src/compositor/extensions/qwaylandxdgshellv6.cpp
index 8338fe6e2..f971fe5b4 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv6.cpp
@@ -40,6 +40,7 @@
#ifdef QT_WAYLAND_COMPOSITOR_QUICK
#include "qwaylandxdgshellv6integration_p.h"
#endif
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/QWaylandSeat>
@@ -158,15 +159,16 @@ void QWaylandXdgShellV6Private::zxdg_shell_v6_pong(Resource *resource, uint32_t
* To provide the functionality of the shell extension in a compositor, create
* an instance of the XdgShellV6 component and add it to the list of extensions
* supported by the compositor:
- * \code
- * import QtWayland.Compositor 1.1
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
*
* WaylandCompositor {
* XdgShellV6 {
* // ...
* }
* }
- * \endcode
+ * \endqml
*/
/*!
@@ -316,7 +318,7 @@ QRect QWaylandXdgSurfaceV6Private::calculateFallbackWindowGeometry() const
{
// TODO: The unset window geometry should include subsurfaces as well, so this solution
// won't work too well on those kinds of clients.
- return QRect(QPoint(0, 0), m_surface->size() / m_surface->bufferScale());
+ return QRect(QPoint(), m_surface->destinationSize());
}
void QWaylandXdgSurfaceV6Private::updateFallbackWindowGeometry()
@@ -390,6 +392,7 @@ void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_get_popup(QtWaylandServer::zxd
"zxdg_surface_v6.get_popup without positioner");
return;
}
+
if (!positioner->m_data.isComplete()) {
QWaylandXdgPositionerV6Data p = positioner->m_data;
wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
@@ -398,6 +401,17 @@ void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_get_popup(QtWaylandServer::zxd
return;
}
+ QRect anchorBounds(QPoint(0, 0), parent->windowGeometry().size());
+ if (!anchorBounds.contains(positioner->m_data.anchorRect)) {
+ // TODO: this is a protocol error and should ideally be handled like this:
+ //wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
+ // "zxdg_positioner_v6 anchor rect extends beyound its parent's window geometry");
+ //return;
+ // However, our own clients currently do this, so we'll settle for a gentle warning instead.
+ qCWarning(qLcWaylandCompositor) << "Ignoring client protocol error: zxdg_positioner_v6 anchor"
+ << "rect extends beyond its parent's window geometry";
+ }
+
if (!m_surface->setRole(QWaylandXdgPopupV6::role(), resource->handle, ZXDG_SHELL_V6_ERROR_ROLE))
return;
@@ -515,7 +529,7 @@ void QWaylandXdgSurfaceV6::initialize(QWaylandXdgShellV6 *xdgShell, QWaylandSurf
d->init(resource.resource());
setExtensionContainer(surface);
d->m_windowGeometry = d->calculateFallbackWindowGeometry();
- connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurfaceV6::handleSurfaceSizeChanged);
+ connect(surface, &QWaylandSurface::destinationSizeChanged, this, &QWaylandXdgSurfaceV6::handleSurfaceSizeChanged);
connect(surface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandXdgSurfaceV6::handleBufferScaleChanged);
emit shellChanged();
emit surfaceChanged();
@@ -679,10 +693,9 @@ QByteArray QWaylandXdgSurfaceV6::interfaceName()
*/
QWaylandXdgSurfaceV6 *QWaylandXdgSurfaceV6::fromResource(wl_resource *resource)
{
- auto xsResource = QWaylandXdgSurfaceV6Private::Resource::fromResource(resource);
- if (!xsResource)
- return nullptr;
- return static_cast<QWaylandXdgSurfaceV6Private *>(xsResource->zxdg_surface_v6_object)->q_func();
+ if (auto p = QtWayland::fromResource<QWaylandXdgSurfaceV6Private *>(resource))
+ return p->q_func();
+ return nullptr;
}
#ifdef QT_WAYLAND_COMPOSITOR_QUICK
@@ -1800,16 +1813,13 @@ QWaylandXdgPopupV6Private::QWaylandXdgPopupV6Private(QWaylandXdgSurfaceV6 *xdgSu
QWaylandXdgPositionerV6 *positioner, const QWaylandResource &resource)
: m_xdgSurface(xdgSurface)
, m_parentXdgSurface(parentXdgSurface)
+ , m_positionerData(positioner->m_data)
{
+ Q_ASSERT(m_positionerData.isComplete());
init(resource.resource());
- m_positionerData = positioner->m_data;
-
- if (!m_positionerData.isComplete())
- qWarning() << "Trying to create xdg popup with incomplete positioner";
QWaylandXdgSurfaceV6Private::get(m_xdgSurface)->setWindowType(Qt::WindowType::Popup);
- //TODO: positioner rect may not extend parent's window geometry, enforce this?
//TODO: Need an API for sending a different initial configure
sendConfigure(QRect(m_positionerData.unconstrainedPosition(), m_positionerData.size));
}
@@ -1995,9 +2005,7 @@ void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_offset(QtWaylandServer::zxd
QWaylandXdgPositionerV6 *QWaylandXdgPositionerV6::fromResource(wl_resource *resource)
{
- if (auto *r = Resource::fromResource(resource))
- return static_cast<QWaylandXdgPositionerV6 *>(r->zxdg_positioner_v6_object);
- return nullptr;
+ return QtWayland::fromResource<QWaylandXdgPositionerV6 *>(resource);
}
QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandxdgshellv6integration.cpp b/src/compositor/extensions/qwaylandxdgshellv6integration.cpp
index 61a9092a3..66dbc6841 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6integration.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv6integration.cpp
@@ -73,7 +73,7 @@ XdgToplevelV6Integration::XdgToplevelV6Integration(QWaylandQuickShellSurfaceItem
connect(m_xdgSurface->shell(), &QWaylandXdgShellV6::popupCreated, this, [item](QWaylandXdgPopupV6 *popup, QWaylandXdgSurfaceV6 *){
handlePopupCreated(item, popup);
});
- connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgToplevelV6Integration::handleSurfaceSizeChanged);
+ connect(m_xdgSurface->surface(), &QWaylandSurface::destinationSizeChanged, this, &XdgToplevelV6Integration::handleSurfaceSizeChanged);
connect(m_toplevel, &QObject::destroyed, this, &XdgToplevelV6Integration::handleToplevelDestroyed);
}
@@ -130,7 +130,7 @@ void XdgToplevelV6Integration::handleStartResize(QWaylandSeat *seat, Qt::Edges e
resizeState.resizeEdges = edges;
resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size();
resizeState.initialPosition = m_item->moveItem()->position();
- resizeState.initialSurfaceSize = m_item->surface()->size();
+ resizeState.initialSurfaceSize = m_item->surface()->destinationSize();
resizeState.initialized = false;
}
@@ -247,14 +247,14 @@ void XdgToplevelV6Integration::handleActivatedChanged()
void XdgToplevelV6Integration::handleSurfaceSizeChanged()
{
if (grabberState == GrabberState::Resize) {
- qreal x = resizeState.initialPosition.x();
- qreal y = resizeState.initialPosition.y();
+ qreal dx = 0;
+ qreal dy = 0;
if (resizeState.resizeEdges & Qt::TopEdge)
- y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height();
-
+ dy = resizeState.initialSurfaceSize.height() - m_item->surface()->destinationSize().height();
if (resizeState.resizeEdges & Qt::LeftEdge)
- x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width();
- m_item->moveItem()->setPosition(QPointF(x, y));
+ dx = resizeState.initialSurfaceSize.width() - m_item->surface()->destinationSize().width();
+ QPointF offset = m_item->mapFromSurface({dx, dy});
+ m_item->moveItem()->setPosition(resizeState.initialPosition + offset);
}
}
@@ -285,11 +285,11 @@ void XdgPopupV6Integration::handleGeometryChanged()
{
if (m_item->view()->output()) {
const QPoint windowOffset = m_popup->parentXdgSurface()->windowGeometry().topLeft();
- const QPoint position = m_popup->unconstrainedPosition() + windowOffset;
+ const QPoint surfacePosition = m_popup->unconstrainedPosition() + windowOffset;
+ const QPoint itemPosition = m_item->mapFromSurface(surfacePosition).toPoint();
//TODO: positioner size or other size...?
- const float scaleFactor = m_item->view()->output()->scaleFactor();
//TODO check positioner constraints etc... sliding, flipping
- m_item->moveItem()->setPosition(position * scaleFactor);
+ m_item->moveItem()->setPosition(itemPosition);
} else {
qWarning() << "XdgPopupV6Integration popup item without output" << m_item;
}
diff --git a/src/compositor/extensions/qwaylandxdgshellv6integration_p.h b/src/compositor/extensions/qwaylandxdgshellv6integration_p.h
index 5b56af89b..049b901c9 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6integration_p.h
+++ b/src/compositor/extensions/qwaylandxdgshellv6integration_p.h
@@ -96,7 +96,7 @@ private:
struct {
QWaylandSeat *seat = nullptr;
QPointF initialOffset;
- bool initialized;
+ bool initialized = false;
} moveState;
struct {
@@ -106,7 +106,7 @@ private:
QPointF initialMousePos;
QPointF initialPosition;
QSize initialSurfaceSize;
- bool initialized;
+ bool initialized = false;
} resizeState;
struct {
diff --git a/src/compositor/global/global.pri b/src/compositor/global/global.pri
index 29d4f4376..172f916bf 100644
--- a/src/compositor/global/global.pri
+++ b/src/compositor/global/global.pri
@@ -4,6 +4,7 @@ HEADERS += \
global/qtwaylandcompositorglobal.h \
global/qwaylandcompositorextension.h \
global/qwaylandcompositorextension_p.h \
+ global/qwaylandutils_p.h \
global/qwaylandquickextension.h \
SOURCES += \
diff --git a/src/compositor/global/qwaylandcompositorextension.cpp b/src/compositor/global/qwaylandcompositorextension.cpp
index e50df48bd..912985399 100644
--- a/src/compositor/global/qwaylandcompositorextension.cpp
+++ b/src/compositor/global/qwaylandcompositorextension.cpp
@@ -44,7 +44,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
QT_BEGIN_NAMESPACE
diff --git a/src/compositor/global/qwaylandutils_p.h b/src/compositor/global/qwaylandutils_p.h
new file mode 100644
index 000000000..934e27617
--- /dev/null
+++ b/src/compositor/global/qwaylandutils_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module 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 QWAYLANDUTILS_P_H
+#define QWAYLANDUTILS_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 <QtCore/qglobal.h>
+
+struct wl_resource;
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWayland {
+
+template<typename return_type>
+return_type fromResource(struct ::wl_resource *resource) {
+ if (auto *r = std::remove_pointer<return_type>::type::Resource::fromResource(resource))
+ return static_cast<return_type>(r->object());
+ return nullptr;
+}
+
+} // namespace QtWayland
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDUTILS_P_H
diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
index 13a69fce9..7b458fbc2 100644
--- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
+++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
@@ -55,7 +55,7 @@
#include <QtWaylandCompositor/qwaylandsurface.h>
#include <QtWaylandCompositor/qwaylandbufferref.h>
#include <QtCore/QSize>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
QT_BEGIN_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
index 7df9ead3c..cb1ee3da0 100644
--- a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
+++ b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
@@ -47,7 +47,7 @@
#include <QtCore/QDebug>
-#include <wayland-server-protocol.h>
+#include <QtWaylandCompositor/private/wayland-wayland-server-protocol.h>
#include "qwaylandsharedmemoryformathelper_p.h"
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
diff --git a/src/compositor/wayland_wrapper/qwlclientbuffer_p.h b/src/compositor/wayland_wrapper/qwlclientbuffer_p.h
index ac8c1ed01..f31ef5d46 100644
--- a/src/compositor/wayland_wrapper/qwlclientbuffer_p.h
+++ b/src/compositor/wayland_wrapper/qwlclientbuffer_p.h
@@ -59,7 +59,7 @@
#include <QtWaylandCompositor/QWaylandSurface>
#include <QtWaylandCompositor/QWaylandBufferRef>
-#include <wayland-server.h>
+#include <wayland-server-core.h>
QT_BEGIN_NAMESPACE
@@ -110,7 +110,7 @@ protected:
void ref();
void deref();
void sendRelease();
- void setDestroyed();
+ virtual void setDestroyed();
struct ::wl_resource *m_buffer = nullptr;
QRegion m_damage;
diff --git a/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h b/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h
index eca6d4b54..aed4e9185 100644
--- a/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h
+++ b/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h
@@ -109,7 +109,7 @@ private:
QMimeData m_retainedData;
QSocketNotifier *m_retainedReadNotifier = nullptr;
QList<QSocketNotifier *> m_obsoleteRetainedReadNotifiers;
- int m_retainedReadIndex;
+ int m_retainedReadIndex = 0;
QByteArray m_retainedReadBuf;
bool m_compositorOwnsSelection = false;
diff --git a/src/compositor/wayland_wrapper/qwldatasource.cpp b/src/compositor/wayland_wrapper/qwldatasource.cpp
index baa47d6fc..f5f456790 100644
--- a/src/compositor/wayland_wrapper/qwldatasource.cpp
+++ b/src/compositor/wayland_wrapper/qwldatasource.cpp
@@ -41,6 +41,7 @@
#include "qwldataoffer_p.h"
#include "qwldatadevice_p.h"
#include "qwldatadevicemanager_p.h"
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
#include <unistd.h>
#include <QtWaylandCompositor/private/wayland-wayland-server-protocol.h>
@@ -101,7 +102,7 @@ void DataSource::setDevice(DataDevice *device)
DataSource *DataSource::fromResource(struct ::wl_resource *resource)
{
- return static_cast<DataSource *>(Resource::fromResource(resource)->data_source_object);
+ return QtWayland::fromResource<DataSource *>(resource);
}
void DataSource::data_source_offer(Resource *, const QString &mime_type)
diff --git a/src/compositor/wayland_wrapper/qwlregion.cpp b/src/compositor/wayland_wrapper/qwlregion.cpp
index 52c19e946..4383474cb 100644
--- a/src/compositor/wayland_wrapper/qwlregion.cpp
+++ b/src/compositor/wayland_wrapper/qwlregion.cpp
@@ -39,6 +39,8 @@
#include "qwlregion_p.h"
+#include <QtWaylandCompositor/private/qwaylandutils_p.h>
+
QT_BEGIN_NAMESPACE
namespace QtWayland {
@@ -54,9 +56,7 @@ Region::~Region()
Region *Region::fromResource(struct ::wl_resource *resource)
{
- if (auto *r = Resource::fromResource(resource))
- return static_cast<Region *>(r->region_object);
- return nullptr;
+ return QtWayland::fromResource<Region *>(resource);
}
void Region::region_destroy_resource(Resource *)
diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri
index 3041d7696..08dd38e82 100644
--- a/src/compositor/wayland_wrapper/wayland_wrapper.pri
+++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri
@@ -1,18 +1,16 @@
CONFIG += wayland-scanner
-WAYLANDSERVERSOURCES_SYSTEM += \
- ../3rdparty/protocol/wayland.xml \
+WAYLANDSERVERSOURCES += \
+ ../3rdparty/protocol/wayland.xml
HEADERS += \
wayland_wrapper/qwlbuffermanager_p.h \
wayland_wrapper/qwlclientbuffer_p.h \
- wayland_wrapper/qwlregion_p.h \
- ../shared/qwaylandxkb_p.h \
+ wayland_wrapper/qwlregion_p.h
SOURCES += \
wayland_wrapper/qwlbuffermanager.cpp \
wayland_wrapper/qwlclientbuffer.cpp \
- wayland_wrapper/qwlregion.cpp \
- ../shared/qwaylandxkb.cpp \
+ wayland_wrapper/qwlregion.cpp
qtConfig(wayland-datadevice) {
HEADERS += \