summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/protocol/idle-inhibit-unstable-v1.xml83
-rw-r--r--src/3rdparty/protocol/qt_attribution.json20
-rw-r--r--src/3rdparty/protocol/wp-primary-selection-unstable-v1.xml225
-rw-r--r--src/client/client.pro8
-rw-r--r--src/client/configure.json12
-rw-r--r--src/client/qwaylandclipboard.cpp71
-rw-r--r--src/client/qwaylandcursor.cpp25
-rw-r--r--src/client/qwaylandcursor_p.h2
-rw-r--r--src/client/qwaylanddatadevice.cpp8
-rw-r--r--src/client/qwaylanddataoffer.cpp15
-rw-r--r--src/client/qwaylanddataoffer_p.h24
-rw-r--r--src/client/qwaylanddatasource.cpp3
-rw-r--r--src/client/qwaylanddisplay.cpp28
-rw-r--r--src/client/qwaylanddisplay_p.h12
-rw-r--r--src/client/qwaylandextendedsurface.cpp2
-rw-r--r--src/client/qwaylandinputcontext.cpp12
-rw-r--r--src/client/qwaylandinputdevice.cpp504
-rw-r--r--src/client/qwaylandinputdevice_p.h116
-rw-r--r--src/client/qwaylandintegration.cpp6
-rw-r--r--src/client/qwaylandnativeinterface.cpp24
-rw-r--r--src/client/qwaylandprimaryselectionv1.cpp162
-rw-r--r--src/client/qwaylandprimaryselectionv1_p.h148
-rw-r--r--src/client/qwaylandscreen.cpp3
-rw-r--r--src/client/qwaylandshmbackingstore.cpp30
-rw-r--r--src/client/qwaylandshmbackingstore_p.h5
-rw-r--r--src/client/qwaylandsurface.cpp122
-rw-r--r--src/client/qwaylandsurface_p.h97
-rw-r--r--src/client/qwaylandtouch.cpp1
-rw-r--r--src/client/qwaylandwindow.cpp176
-rw-r--r--src/client/qwaylandwindow_p.h19
-rw-r--r--src/compositor/compositor_api/compositor_api.pri15
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp12
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor_p.h4
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.cpp13
-rw-r--r--src/compositor/compositor_api/qwaylandoutput.cpp13
-rw-r--r--src/compositor/compositor_api/qwaylandoutput_p.h5
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp4
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp84
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem_p.h2
-rw-r--r--src/compositor/compositor_api/qwaylandseat.cpp33
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp32
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h4
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h3
-rw-r--r--src/compositor/compositor_api/qwaylandview.cpp3
-rw-r--r--src/compositor/configure.json7
-rw-r--r--src/compositor/extensions/extensions.pri31
-rw-r--r--src/compositor/extensions/qwaylandidleinhibitv1.cpp190
-rw-r--r--src/compositor/extensions/qwaylandidleinhibitv1.h62
-rw-r--r--src/compositor/extensions/qwaylandidleinhibitv1_p.h88
-rw-r--r--src/compositor/extensions/qwaylandqtwindowmanager.cpp3
-rw-r--r--src/compositor/extensions/qwaylandquickshellintegration.cpp256
-rw-r--r--src/compositor/extensions/qwaylandquickshellintegration.h76
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp66
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.h15
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h17
-rw-r--r--src/compositor/extensions/qwaylandquickxdgoutputv1.cpp73
-rw-r--r--src/compositor/extensions/qwaylandquickxdgoutputv1.h62
-rw-r--r--src/compositor/extensions/qwaylandtextinput.cpp4
-rw-r--r--src/compositor/extensions/qwaylandwlscaler_p.h2
-rw-r--r--src/compositor/extensions/qwaylandwlshell.cpp9
-rw-r--r--src/compositor/extensions/qwaylandwlshellintegration.cpp3
-rw-r--r--src/compositor/extensions/qwaylandxdgoutputv1.cpp595
-rw-r--r--src/compositor/extensions/qwaylandxdgoutputv1.h111
-rw-r--r--src/compositor/extensions/qwaylandxdgoutputv1_p.h112
-rw-r--r--src/compositor/extensions/qwaylandxdgshell.cpp24
-rw-r--r--src/compositor/extensions/qwaylandxdgshell.h1
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5.cpp33
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5_p.h2
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6.cpp24
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6.h1
-rw-r--r--src/compositor/extensions/qwltexturesharingextension.cpp8
-rw-r--r--src/compositor/global/qwaylandcompositorextension.cpp2
-rw-r--r--src/compositor/hardware_integration/qwlserverbufferintegration_p.h8
-rw-r--r--src/compositor/wayland_wrapper/qwlclientbuffer.cpp2
-rw-r--r--src/compositor/wayland_wrapper/qwldatadevicemanager.cpp7
-rw-r--r--src/compositor/wayland_wrapper/qwldataoffer.cpp3
-rw-r--r--src/extensions/README.md18
-rw-r--r--src/hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.cpp5
-rw-r--r--src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp5
-rw-r--r--src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp2
-rw-r--r--src/hardwareintegration/compositor/vulkan-server/vulkanserverbufferintegration.cpp5
-rw-r--r--src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp6
-rw-r--r--src/imports/compositor/qwaylandquickcompositorplugin.cpp15
-rw-r--r--src/imports/imports.pro12
-rw-r--r--src/imports/texture-sharing-extension/texture-sharing-extension.pro2
-rw-r--r--src/imports/texture-sharing/texture-sharing.pro2
-rw-r--r--src/plugins/hardwareintegration/hardwareintegration.pro2
-rw-r--r--src/plugins/plugins.pro13
-rw-r--r--src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp2
-rw-r--r--src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp6
-rw-r--r--src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h2
-rw-r--r--src/plugins/shellintegration/wl-shell/qwaylandwlshellintegration.cpp5
-rw-r--r--src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp19
-rw-r--r--src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp4
-rw-r--r--src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp3
-rw-r--r--src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgsurfacev5.cpp2
-rw-r--r--src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp2
-rw-r--r--src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp2
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp225
-rw-r--r--src/shared/qwaylandinputmethodeventbuilder.cpp2
-rw-r--r--src/src.pro30
101 files changed, 3860 insertions, 618 deletions
diff --git a/src/3rdparty/protocol/idle-inhibit-unstable-v1.xml b/src/3rdparty/protocol/idle-inhibit-unstable-v1.xml
new file mode 100644
index 000000000..9c06cdcba
--- /dev/null
+++ b/src/3rdparty/protocol/idle-inhibit-unstable-v1.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="idle_inhibit_unstable_v1">
+
+ <copyright>
+ Copyright © 2015 Samsung Electronics Co., Ltd
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zwp_idle_inhibit_manager_v1" version="1">
+ <description summary="control behavior when display idles">
+ This interface permits inhibiting the idle behavior such as screen
+ blanking, locking, and screensaving. The client binds the idle manager
+ globally, then creates idle-inhibitor objects for each surface.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the idle inhibitor object">
+ Destroy the inhibit manager.
+ </description>
+ </request>
+
+ <request name="create_inhibitor">
+ <description summary="create a new inhibitor object">
+ Create a new inhibitor object associated with the given surface.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/>
+ <arg name="surface" type="object" interface="wl_surface"
+ summary="the surface that inhibits the idle behavior"/>
+ </request>
+
+ </interface>
+
+ <interface name="zwp_idle_inhibitor_v1" version="1">
+ <description summary="context object for inhibiting idle behavior">
+ An idle inhibitor prevents the output that the associated surface is
+ visible on from being set to a state where it is not visually usable due
+ to lack of user interaction (e.g. blanked, dimmed, locked, set to power
+ save, etc.) Any screensaver processes are also blocked from displaying.
+
+ If the surface is destroyed, unmapped, becomes occluded, loses
+ visibility, or otherwise becomes not visually relevant for the user, the
+ idle inhibitor will not be honored by the compositor; if the surface
+ subsequently regains visibility the inhibitor takes effect once again.
+ Likewise, the inhibitor isn't honored if the system was already idled at
+ the time the inhibitor was established, although if the system later
+ de-idles and re-idles the inhibitor will take effect.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the idle inhibitor object">
+ Remove the inhibitor effect from the associated wl_surface.
+ </description>
+ </request>
+
+ </interface>
+</protocol>
diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json
index 7e068f755..c49ead4f3 100644
--- a/src/3rdparty/protocol/qt_attribution.json
+++ b/src/3rdparty/protocol/qt_attribution.json
@@ -56,6 +56,23 @@ Copyright (c) 2013 BMW Car IT GmbH"
},
{
+ "Id": "wayland-primary-selection-protocol",
+ "Name": "Wayland Primary Selection Protocol",
+ "QDocModule": "qtwaylandcompositor",
+ "QtUsage": "Used in the Qt Wayland platform plugin",
+ "Files": "wp-primary-selection-unstable-v1.xml",
+
+ "Description": "The primary selection extension allows copying text by selecting it and pasting it with the middle mouse button.",
+ "Homepage": "https://wayland.freedesktop.org",
+ "Version": "1",
+ "DownloadLocation": "https://cgit.freedesktop.org/wayland/wayland-protocols/plain/unstable/primary-selection/primary-selection-unstable-v1.xml",
+ "LicenseId": "MIT",
+ "License": "MIT License",
+ "LicenseFile": "MIT_LICENSE.txt",
+ "Copyright": "Copyright © 2015 2016 Red Hat"
+ },
+
+ {
"Id": "wayland-scaler-protocol",
"Name": "Wayland Scaler Protocol",
"QDocModule": "qtwaylandcompositor",
@@ -110,8 +127,9 @@ Copyright (c) 2013 BMW Car IT GmbH"
"Id": "wayland-xdg-output-protocol",
"Name": "Wayland XDG Output Protocol",
"QDocModule": "qtwaylandcompositor",
- "QtUsage": "Used in the Qt Wayland platform plugin.",
+ "QtUsage": "Used in the Qt Wayland Compositor API, and the Qt Wayland platform plugin.",
"Files": "xdg-output-unstable-v1.xml",
+
"Description": "The XDG Output protocol is an extended way to describe output regions under Wayland",
"Homepage": "https://wayland.freedesktop.org",
"Version": "unstable v1, version 2",
diff --git a/src/3rdparty/protocol/wp-primary-selection-unstable-v1.xml b/src/3rdparty/protocol/wp-primary-selection-unstable-v1.xml
new file mode 100644
index 000000000..e5a39e34c
--- /dev/null
+++ b/src/3rdparty/protocol/wp-primary-selection-unstable-v1.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wp_primary_selection_unstable_v1">
+ <copyright>
+ Copyright © 2015, 2016 Red Hat
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="Primary selection protocol">
+ This protocol provides the ability to have a primary selection device to
+ match that of the X server. This primary selection is a shortcut to the
+ common clipboard selection, where text just needs to be selected in order
+ to allow copying it elsewhere. The de facto way to perform this action
+ is the middle mouse button, although it is not limited to this one.
+
+ Clients wishing to honor primary selection should create a primary
+ selection source and set it as the selection through
+ wp_primary_selection_device.set_selection whenever the text selection
+ changes. In order to minimize calls in pointer-driven text selection,
+ it should happen only once after the operation finished. Similarly,
+ a NULL source should be set when text is unselected.
+
+ wp_primary_selection_offer objects are first announced through the
+ wp_primary_selection_device.data_offer event. Immediately after this event,
+ the primary data offer will emit wp_primary_selection_offer.offer events
+ to let know of the mime types being offered.
+
+ When the primary selection changes, the client with the keyboard focus
+ will receive wp_primary_selection_device.selection events. Only the client
+ with the keyboard focus will receive such events with a non-NULL
+ wp_primary_selection_offer. Across keyboard focus changes, previously
+ focused clients will receive wp_primary_selection_device.events with a
+ NULL wp_primary_selection_offer.
+
+ In order to request the primary selection data, the client must pass
+ a recent serial pertaining to the press event that is triggering the
+ operation, if the compositor deems the serial valid and recent, the
+ wp_primary_selection_source.send event will happen in the other end
+ to let the transfer begin. The client owning the primary selection
+ should write the requested data, and close the file descriptor
+ immediately.
+
+ If the primary selection owner client disappeared during the transfer,
+ the client reading the data will receive a
+ wp_primary_selection_device.selection event with a NULL
+ wp_primary_selection_offer, the client should take this as a hint
+ to finish the reads related to the no longer existing offer.
+
+ The primary selection owner should be checking for errors during
+ writes, merely cancelling the ongoing transfer if any happened.
+ </description>
+
+ <interface name="zwp_primary_selection_device_manager_v1" version="1">
+ <description summary="X primary selection emulation">
+ The primary selection device manager is a singleton global object that
+ provides access to the primary selection. It allows to create
+ wp_primary_selection_source objects, as well as retrieving the per-seat
+ wp_primary_selection_device objects.
+ </description>
+
+ <request name="create_source">
+ <description summary="create a new primary selection source">
+ Create a new primary selection source.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_primary_selection_source_v1"/>
+ </request>
+
+ <request name="get_device">
+ <description summary="create a new primary selection device">
+ Create a new data device for a given seat.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_primary_selection_device_v1"/>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the primary selection device manager">
+ Destroy the primary selection device manager.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwp_primary_selection_device_v1" version="1">
+ <request name="set_selection">
+ <description summary="set the primary selection">
+ Replaces the current selection. The previous owner of the primary
+ selection will receive a wp_primary_selection_source.cancelled event.
+
+ To unset the selection, set the source to NULL.
+ </description>
+ <arg name="source" type="object" interface="zwp_primary_selection_source_v1" allow-null="true"/>
+ <arg name="serial" type="uint" summary="serial of the event that triggered this request"/>
+ </request>
+
+ <event name="data_offer">
+ <description summary="introduce a new wp_primary_selection_offer">
+ Introduces a new wp_primary_selection_offer object that may be used
+ to receive the current primary selection. Immediately following this
+ event, the new wp_primary_selection_offer object will send
+ wp_primary_selection_offer.offer events to describe the offered mime
+ types.
+ </description>
+ <arg name="offer" type="new_id" interface="zwp_primary_selection_offer_v1"/>
+ </event>
+
+ <event name="selection">
+ <description summary="advertise a new primary selection">
+ The wp_primary_selection_device.selection event is sent to notify the
+ client of a new primary selection. This event is sent after the
+ wp_primary_selection.data_offer event introducing this object, and after
+ the offer has announced its mimetypes through
+ wp_primary_selection_offer.offer.
+
+ The data_offer is valid until a new offer or NULL is received
+ or until the client loses keyboard focus. The client must destroy the
+ previous selection data_offer, if any, upon receiving this event.
+ </description>
+ <arg name="id" type="object" interface="zwp_primary_selection_offer_v1" allow-null="true"/>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the primary selection device">
+ Destroy the primary selection device.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwp_primary_selection_offer_v1" version="1">
+ <description summary="offer to transfer primary selection contents">
+ A wp_primary_selection_offer represents an offer to transfer the contents
+ of the primary selection clipboard to the client. Similar to
+ wl_data_offer, the offer also describes the mime types that the data can
+ be converted to and provides the mechanisms for transferring the data
+ directly to the client.
+ </description>
+
+ <request name="receive">
+ <description summary="request that the data is transferred">
+ To transfer the contents of the primary selection clipboard, the client
+ issues this request and indicates the mime type that it wants to
+ receive. The transfer happens through the passed file descriptor
+ (typically created with the pipe system call). The source client writes
+ the data in the mime type representation requested and then closes the
+ file descriptor.
+
+ The receiving client reads from the read end of the pipe until EOF and
+ closes its end, at which point the transfer is complete.
+ </description>
+ <arg name="mime_type" type="string"/>
+ <arg name="fd" type="fd"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the primary selection offer">
+ Destroy the primary selection offer.
+ </description>
+ </request>
+
+ <event name="offer">
+ <description summary="advertise offered mime type">
+ Sent immediately after creating announcing the
+ wp_primary_selection_offer through
+ wp_primary_selection_device.data_offer. One event is sent per offered
+ mime type.
+ </description>
+ <arg name="mime_type" type="string"/>
+ </event>
+ </interface>
+
+ <interface name="zwp_primary_selection_source_v1" version="1">
+ <description summary="offer to replace the contents of the primary selection">
+ The source side of a wp_primary_selection_offer, it provides a way to
+ describe the offered data and respond to requests to transfer the
+ requested contents of the primary selection clipboard.
+ </description>
+
+ <request name="offer">
+ <description summary="add an offered mime type">
+ This request adds a mime type to the set of mime types advertised to
+ targets. Can be called several times to offer multiple types.
+ </description>
+ <arg name="mime_type" type="string"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the primary selection source">
+ Destroy the primary selection source.
+ </description>
+ </request>
+
+ <event name="send">
+ <description summary="send the primary selection contents">
+ Request for the current primary selection contents from the client.
+ Send the specified mime type over the passed file descriptor, then
+ close it.
+ </description>
+ <arg name="mime_type" type="string"/>
+ <arg name="fd" type="fd"/>
+ </event>
+
+ <event name="cancelled">
+ <description summary="request for primary selection contents was canceled">
+ This primary selection source is no longer valid. The client should
+ clean up and destroy this primary selection source.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/src/client/client.pro b/src/client/client.pro
index 4233ac950..d0ae9009e 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -31,6 +31,7 @@ WAYLANDCLIENTSOURCES += \
../extensions/touch-extension.xml \
../extensions/qt-key-unstable-v1.xml \
../extensions/qt-windowmanager.xml \
+ ../3rdparty/protocol/wp-primary-selection-unstable-v1.xml \
../3rdparty/protocol/text-input-unstable-v2.xml \
../3rdparty/protocol/xdg-output-unstable-v1.xml \
../3rdparty/protocol/wayland.xml
@@ -46,6 +47,7 @@ SOURCES += qwaylandintegration.cpp \
qwaylandshellsurface.cpp \
qwaylandextendedsurface.cpp \
qwaylandsubsurface.cpp \
+ qwaylandsurface.cpp \
qwaylandtouch.cpp \
qwaylandqtkey.cpp \
../shared/qwaylandmimehelper.cpp \
@@ -70,6 +72,7 @@ HEADERS += qwaylandintegration_p.h \
qwaylandshellsurface_p.h \
qwaylandextendedsurface_p.h \
qwaylandsubsurface_p.h \
+ qwaylandsurface_p.h \
qwaylandtouch_p.h \
qwaylandqtkey_p.h \
qwaylandabstractdecoration_p.h \
@@ -116,6 +119,11 @@ qtConfig(wayland-datadevice) {
qwaylanddatasource.cpp
}
+qtConfig(wayland-client-primary-selection) {
+ HEADERS += qwaylandprimaryselectionv1_p.h
+ SOURCES += qwaylandprimaryselectionv1.cpp
+}
+
qtConfig(draganddrop) {
HEADERS += \
qwaylanddnd_p.h
diff --git a/src/client/configure.json b/src/client/configure.json
index 7feeee4bf..403a2edcf 100644
--- a/src/client/configure.json
+++ b/src/client/configure.json
@@ -93,6 +93,11 @@
"condition": "features.draganddrop || features.clipboard",
"output": [ "privateFeature" ]
},
+ "wayland-client-primary-selection": {
+ "label": "primary-selection clipboard",
+ "condition": "features.clipboard",
+ "output": [ "privateFeature" ]
+ },
"wayland-client-fullscreen-shell-v1": {
"label": "fullscreen-shell-v1",
"condition": "features.wayland-client",
@@ -158,14 +163,9 @@
"condition": "features.wayland-client && features.opengl && features.egl && tests.dmabuf-server-buffer",
"output": [ "privateFeature" ]
},
- "wayland-client-texture-sharing-experimental" : {
- "label": "Texture sharing (experimental)",
- "autoDetect": "false",
- "output": [ "privateFeature" ]
- },
"wayland-vulkan-server-buffer": {
"label": "Vulkan-based server buffer integration",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.vulkan-server-buffer && features.wayland-client-texture-sharing-experimental",
+ "condition": "features.wayland-client && features.opengl && features.egl && tests.vulkan-server-buffer",
"output": [ "privateFeature" ]
},
"wayland-shm-emulation-server-buffer": {
diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp
index 60820da92..369c6ec07 100644
--- a/src/client/qwaylandclipboard.cpp
+++ b/src/client/qwaylandclipboard.cpp
@@ -43,6 +43,9 @@
#include "qwaylanddataoffer_p.h"
#include "qwaylanddatasource_p.h"
#include "qwaylanddatadevice_p.h"
+#if QT_CONFIG(wayland_client_primary_selection)
+#include "qwaylandprimaryselectionv1_p.h"
+#endif
QT_BEGIN_NAMESPACE
@@ -59,44 +62,74 @@ QWaylandClipboard::~QWaylandClipboard()
QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
{
- if (mode != QClipboard::Clipboard)
+ auto *seat = mDisplay->currentInputDevice();
+ if (!seat)
return &m_emptyData;
- QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
- if (!inputDevice || !inputDevice->dataDevice())
+ switch (mode) {
+ case QClipboard::Clipboard:
+ if (auto *dataDevice = seat->dataDevice()) {
+ if (auto *source = dataDevice->selectionSource())
+ return source->mimeData();
+ if (auto *offer = dataDevice->selectionOffer())
+ return offer->mimeData();
+ }
+ return &m_emptyData;
+ case QClipboard::Selection:
+#if QT_CONFIG(wayland_client_primary_selection)
+ if (auto *selectionDevice = seat->primarySelectionDevice()) {
+ if (auto *source = selectionDevice->selectionSource())
+ return source->mimeData();
+ if (auto *offer = selectionDevice->selectionOffer())
+ return offer->mimeData();
+ }
+#endif
+ return &m_emptyData;
+ default:
return &m_emptyData;
-
- QWaylandDataSource *source = inputDevice->dataDevice()->selectionSource();
- if (source) {
- return source->mimeData();
}
-
- if (inputDevice->dataDevice()->selectionOffer())
- return inputDevice->dataDevice()->selectionOffer()->mimeData();
-
- return &m_emptyData;
}
void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
- if (mode != QClipboard::Clipboard)
- return;
-
- QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
- if (!inputDevice || !inputDevice->dataDevice())
+ auto *seat = mDisplay->currentInputDevice();
+ if (!seat)
return;
static const QString plain = QStringLiteral("text/plain");
static const QString utf8 = QStringLiteral("text/plain;charset=utf-8");
+
if (data && data->hasFormat(plain) && !data->hasFormat(utf8))
data->setData(utf8, data->data(plain));
- inputDevice->dataDevice()->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : nullptr);
- emitChanged(mode);
+ switch (mode) {
+ case QClipboard::Clipboard:
+ if (auto *dataDevice = seat->dataDevice()) {
+ dataDevice->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : nullptr);
+ emitChanged(mode);
+ }
+ break;
+ case QClipboard::Selection:
+#if QT_CONFIG(wayland_client_primary_selection)
+ if (auto *selectionDevice = seat->primarySelectionDevice()) {
+ selectionDevice->setSelectionSource(data ? new QWaylandPrimarySelectionSourceV1(mDisplay->primarySelectionManager(), data) : nullptr);
+ emitChanged(mode);
+ }
+#endif
+ break;
+ default:
+ break;
+ }
}
bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const
{
+#if QT_CONFIG(wayland_client_primary_selection)
+ if (mode == QClipboard::Selection) {
+ auto *seat = mDisplay->currentInputDevice();
+ return seat && seat->primarySelectionDevice();
+ }
+#endif
return mode == QClipboard::Clipboard;
}
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
index 8b2ed036d..4356b23a0 100644
--- a/src/client/qwaylandcursor.cpp
+++ b/src/client/qwaylandcursor.cpp
@@ -48,6 +48,8 @@
#include <wayland-cursor.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -75,7 +77,10 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
if (struct wl_cursor *cursor = m_cursors.value(shape, nullptr))
return cursor;
- static const QMultiMap<WaylandCursor, QByteArray>cursorNamesMap {
+ static Q_CONSTEXPR struct ShapeAndName {
+ WaylandCursor shape;
+ const char name[33];
+ } cursorNamesMap[] = {
{ArrowCursor, "left_ptr"},
{ArrowCursor, "default"},
{ArrowCursor, "top_left_arrow"},
@@ -193,9 +198,14 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
{ResizeSouthWestCursor, "bottom_left_corner"},
};
- QList<QByteArray> cursorNames = cursorNamesMap.values(shape);
- for (auto &name : qAsConst(cursorNames)) {
- if (wl_cursor *cursor = wl_cursor_theme_get_cursor(m_theme, name.constData())) {
+ const auto byShape = [](ShapeAndName lhs, ShapeAndName rhs) {
+ return lhs.shape < rhs.shape;
+ };
+ Q_ASSERT(std::is_sorted(std::begin(cursorNamesMap), std::end(cursorNamesMap), byShape));
+ const auto p = std::equal_range(std::begin(cursorNamesMap), std::end(cursorNamesMap),
+ ShapeAndName{shape, ""}, byShape);
+ for (auto it = p.first; it != p.second; ++it) {
+ if (wl_cursor *cursor = wl_cursor_theme_get_cursor(m_theme, it->name)) {
m_cursors.insert(shape, cursor);
return cursor;
}
@@ -209,7 +219,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
-struct wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape)
+::wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation)
{
struct wl_cursor *waylandCursor = nullptr;
@@ -227,8 +237,9 @@ struct wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape)
return nullptr;
}
- struct wl_cursor_image *image = waylandCursor->images[0];
- struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ int frame = wl_cursor_frame(waylandCursor, millisecondsIntoAnimation);
+ ::wl_cursor_image *image = waylandCursor->images[frame];
+ ::wl_buffer *buffer = wl_cursor_image_get_buffer(image);
if (!buffer) {
qCWarning(lcQpaWayland) << "Could not find buffer for cursor";
return nullptr;
diff --git a/src/client/qwaylandcursor_p.h b/src/client/qwaylandcursor_p.h
index 6c48fb628..a4605f3d2 100644
--- a/src/client/qwaylandcursor_p.h
+++ b/src/client/qwaylandcursor_p.h
@@ -75,7 +75,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme
public:
static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName);
~QWaylandCursorTheme();
- struct wl_cursor_image *cursorImage(Qt::CursorShape shape);
+ ::wl_cursor_image *cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation = 0);
private:
enum WaylandCursor {
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index 6b2a408eb..e7afc3ca8 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -47,6 +47,7 @@
#include "qwaylandinputdevice_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandabstractdecoration_p.h"
+#include "qwaylandsurface_p.h"
#include <QtCore/QMimeData>
#include <QtGui/QGuiApplication>
@@ -107,12 +108,13 @@ void QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
- QWaylandWindow *origin = m_display->currentInputDevice()->pointerFocus();
+ auto *seat = m_display->currentInputDevice();
+ auto *origin = seat->pointerFocus();
if (!origin)
- origin = m_display->currentInputDevice()->touchFocus();
+ origin = seat->touchFocus();
if (origin)
- start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
+ start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
else
qCDebug(lcQpaWayland) << "Couldn't start a drag because the origin window could not be found.";
}
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
index 3da16ed00..4c06277fe 100644
--- a/src/client/qwaylanddataoffer.cpp
+++ b/src/client/qwaylanddataoffer.cpp
@@ -58,7 +58,8 @@ static QString utf8Text()
QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
: QtWayland::wl_data_offer(offer)
- , m_mimeData(new QWaylandMimeData(this, display))
+ , m_display(display)
+ , m_mimeData(new QWaylandMimeData(this))
{
}
@@ -81,14 +82,19 @@ QMimeData *QWaylandDataOffer::mimeData()
return m_mimeData.data();
}
+void QWaylandDataOffer::startReceiving(const QString &mimeType, int fd)
+{
+ receive(mimeType, fd);
+ wl_display_flush(m_display->wl_display());
+}
+
void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
{
m_mimeData->appendFormat(mime_type);
}
-QWaylandMimeData::QWaylandMimeData(QWaylandDataOffer *dataOffer, QWaylandDisplay *display)
+QWaylandMimeData::QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
: m_dataOffer(dataOffer)
- , m_display(display)
{
}
@@ -140,8 +146,7 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
return QVariant();
}
- m_dataOffer->receive(mime, pipefd[1]);
- wl_display_flush(m_display->wl_display());
+ m_dataOffer->startReceiving(mime, pipefd[1]);
close(pipefd[1]);
diff --git a/src/client/qwaylanddataoffer_p.h b/src/client/qwaylanddataoffer_p.h
index 5412400a5..9cf1483ca 100644
--- a/src/client/qwaylanddataoffer_p.h
+++ b/src/client/qwaylanddataoffer_p.h
@@ -65,27 +65,40 @@ namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandMimeData;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDataOffer : public QtWayland::wl_data_offer
+class QWaylandAbstractDataOffer
+{
+public:
+ virtual void startReceiving(const QString &mimeType, int fd) = 0;
+ virtual QMimeData *mimeData() = 0;
+
+ virtual ~QWaylandAbstractDataOffer() = default;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandDataOffer
+ : public QtWayland::wl_data_offer // needs to be the first because we do static casts from the user pointer to the wrapper
+ , public QWaylandAbstractDataOffer
{
public:
explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
~QWaylandDataOffer() override;
+ QMimeData *mimeData() override;
QString firstFormat() const;
- QMimeData *mimeData();
+ void startReceiving(const QString &mimeType, int fd) override;
protected:
void data_offer_offer(const QString &mime_type) override;
private:
+ QWaylandDisplay *m_display = nullptr;
QScopedPointer<QWaylandMimeData> m_mimeData;
};
class QWaylandMimeData : public QInternalMimeData {
public:
- explicit QWaylandMimeData(QWaylandDataOffer *dataOffer, QWaylandDisplay *display);
+ explicit QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer);
~QWaylandMimeData() override;
void appendFormat(const QString &mimeType);
@@ -98,13 +111,12 @@ protected:
private:
int readData(int fd, QByteArray &data) const;
- mutable QWaylandDataOffer *m_dataOffer = nullptr;
- QWaylandDisplay *m_display = nullptr;
+ QWaylandAbstractDataOffer *m_dataOffer = nullptr;
mutable QStringList m_types;
mutable QHash<QString, QByteArray> m_data;
};
-}
+} // namespace QtWaylandClient
QT_END_NAMESPACE
#endif
diff --git a/src/client/qwaylanddatasource.cpp b/src/client/qwaylanddatasource.cpp
index 0c6ad50e4..ea76943a7 100644
--- a/src/client/qwaylanddatasource.cpp
+++ b/src/client/qwaylanddatasource.cpp
@@ -60,7 +60,8 @@ QWaylandDataSource::QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceMana
{
if (!mimeData)
return;
- Q_FOREACH (const QString &format, mimeData->formats()) {
+ const auto formats = mimeData->formats();
+ for (const QString &format : formats) {
offer(format);
}
}
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index 78524f6fc..a17e8917a 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -41,6 +41,7 @@
#include "qwaylandintegration_p.h"
#include "qwaylandwindow_p.h"
+#include "qwaylandsurface_p.h"
#include "qwaylandabstractdecoration_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
@@ -51,7 +52,10 @@
#if QT_CONFIG(wayland_datadevice)
#include "qwaylanddatadevicemanager_p.h"
#include "qwaylanddatadevice_p.h"
-#endif
+#endif // QT_CONFIG(wayland_datadevice)
+#if QT_CONFIG(wayland_client_primary_selection)
+#include "qwaylandprimaryselectionv1_p.h"
+#endif // QT_CONFIG(wayland_client_primary_selection)
#if QT_CONFIG(cursor)
#include <wayland-cursor.h>
#endif
@@ -68,6 +72,7 @@
#include "qwaylandqtkey_p.h"
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
+#include <QtWaylandClient/private/qwayland-wp-primary-selection-unstable-v1.h>
#include <QtCore/private/qcore_unix_p.h>
@@ -109,7 +114,7 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
return nullptr;
}
- return mSubCompositor->get_subsurface(window->object(), parent->object());
+ return mSubCompositor->get_subsurface(window->wlSurface(), parent->wlSurface());
}
QWaylandShellIntegration *QWaylandDisplay::shellIntegration() const
@@ -162,13 +167,11 @@ QWaylandDisplay::~QWaylandDisplay(void)
if (mSyncCallback)
wl_callback_destroy(mSyncCallback);
- qDeleteAll(mInputDevices);
- mInputDevices.clear();
+ qDeleteAll(qExchange(mInputDevices, {}));
- foreach (QWaylandScreen *screen, mScreens) {
+ for (QWaylandScreen *screen : qExchange(mScreens, {})) {
QWindowSystemInterface::handleScreenRemoved(screen);
}
- mScreens.clear();
qDeleteAll(mWaitingScreens);
#if QT_CONFIG(wayland_datadevice)
@@ -307,6 +310,10 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mTouchExtension.reset(new QWaylandTouchExtension(this, id));
} else if (interface == QStringLiteral("zqt_key_v1")) {
mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
+#if QT_CONFIG(wayland_client_primary_selection)
+ } else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
+ mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
+#endif
} else if (interface == QStringLiteral("zwp_text_input_manager_v2") && !mClientSideInputContextRequested) {
mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
@@ -329,7 +336,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mGlobals.append(RegistryGlobal(id, interface, version, registry));
- foreach (Listener l, mRegistryListeners)
+ const auto copy = mRegistryListeners; // be prepared for listeners unregistering on notification
+ for (Listener l : copy)
(*l.listener)(l.data, registry, id, interface, version);
}
@@ -347,7 +355,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
}
}
- foreach (QWaylandScreen *screen, mScreens) {
+ for (QWaylandScreen *screen : qAsConst(mScreens)) {
if (screen->outputId() == id) {
mScreens.removeOne(screen);
QWindowSystemInterface::handleScreenRemoved(screen);
@@ -367,9 +375,9 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
}
}
-bool QWaylandDisplay::hasRegistryGlobal(const QString &interfaceName)
+bool QWaylandDisplay::hasRegistryGlobal(QStringView interfaceName) const
{
- Q_FOREACH (const RegistryGlobal &global, mGlobals)
+ for (const RegistryGlobal &global : mGlobals)
if (global.interface == interfaceName)
return true;
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 7cfbc19b8..14bb77198 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -93,11 +93,15 @@ class QWaylandScreen;
class QWaylandClientBufferIntegration;
class QWaylandWindowManagerIntegration;
class QWaylandDataDeviceManager;
+#if QT_CONFIG(wayland_client_primary_selection)
+class QWaylandPrimarySelectionDeviceManagerV1;
+#endif
class QWaylandTouchExtension;
class QWaylandQtKeyExtension;
class QWaylandWindow;
class QWaylandIntegration;
class QWaylandHardwareIntegration;
+class QWaylandSurface;
class QWaylandShellIntegration;
class QWaylandCursor;
class QWaylandCursorTheme;
@@ -149,6 +153,9 @@ public:
#if QT_CONFIG(wayland_datadevice)
QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); }
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+ QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
+#endif
QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
@@ -166,7 +173,7 @@ public:
: id(id_), interface(interface_), version(version_), registry(registry_) { }
};
QList<RegistryGlobal> globals() const { return mGlobals; }
- bool hasRegistryGlobal(const QString &interfaceName);
+ bool hasRegistryGlobal(QStringView interfaceName) const;
/* wl_registry_add_listener does not add but rather sets a listener, so this function is used
* to enable many listeners at once. */
@@ -236,6 +243,9 @@ private:
QScopedPointer<QWaylandTouchExtension> mTouchExtension;
QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
+#if QT_CONFIG(wayland_client_primary_selection)
+ QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
+#endif
QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManager;
QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
QScopedPointer<QtWayland::zxdg_output_manager_v1> mXdgOutputManager;
diff --git a/src/client/qwaylandextendedsurface.cpp b/src/client/qwaylandextendedsurface.cpp
index c5db6d7ba..a7836e292 100644
--- a/src/client/qwaylandextendedsurface.cpp
+++ b/src/client/qwaylandextendedsurface.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
QWaylandExtendedSurface::QWaylandExtendedSurface(QWaylandWindow *window)
- : QtWayland::qt_extended_surface(window->display()->windowExtension()->get_extended_surface(window->object()))
+ : QtWayland::qt_extended_surface(window->display()->windowExtension()->get_extended_surface(window->wlSurface()))
, m_window(window)
{
}
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
index c6f287dda..068c058e7 100644
--- a/src/client/qwaylandinputcontext.cpp
+++ b/src/client/qwaylandinputcontext.cpp
@@ -119,7 +119,7 @@ void QWaylandTextInput::updateState(Qt::InputMethodQueries queries, uint32_t fla
if (!QGuiApplication::focusWindow() || !QGuiApplication::focusWindow()->handle())
return;
- struct ::wl_surface *surface = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle())->object();
+ auto *surface = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle())->wlSurface();
if (!surface || (surface != m_surface))
return;
@@ -221,11 +221,11 @@ void QWaylandTextInput::zwp_text_input_v2_leave(uint32_t serial, ::wl_surface *s
void QWaylandTextInput::zwp_text_input_v2_modifiers_map(wl_array *map)
{
- QList<QByteArray> modifiersMap = QByteArray::fromRawData(static_cast<const char*>(map->data), map->size).split('\0');
+ const QList<QByteArray> modifiersMap = QByteArray::fromRawData(static_cast<const char*>(map->data), map->size).split('\0');
m_modifiersMap.clear();
- Q_FOREACH (const QByteArray &modifier, modifiersMap) {
+ for (const QByteArray &modifier : modifiersMap) {
if (modifier == "Shift")
m_modifiersMap.append(Qt::ShiftModifier);
else if (modifier == "Control")
@@ -428,7 +428,7 @@ static ::wl_surface *surfaceForWindow(QWindow *window)
return nullptr;
auto *waylandWindow = static_cast<QWaylandWindow *>(window->handle());
- return waylandWindow->wl_surface::object();
+ return waylandWindow->wlSurface();
}
void QWaylandInputContext::update(Qt::InputMethodQueries queries)
@@ -534,7 +534,7 @@ void QWaylandInputContext::setFocusObject(QObject *)
if (mCurrentWindow && mCurrentWindow->handle()) {
if (mCurrentWindow.data() != window || !inputMethodAccepted()) {
- struct ::wl_surface *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->object();
+ auto *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->wlSurface();
if (surface)
textInput()->disable(surface);
mCurrentWindow.clear();
@@ -543,7 +543,7 @@ void QWaylandInputContext::setFocusObject(QObject *)
if (window && window->handle() && inputMethodAccepted()) {
if (mCurrentWindow.data() != window) {
- struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object();
+ auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
if (surface) {
textInput()->enable(surface);
mCurrentWindow = window;
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index b5c18a074..f2dee75e6 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -41,11 +41,15 @@
#include "qwaylandintegration_p.h"
#include "qwaylandwindow_p.h"
+#include "qwaylandsurface_p.h"
#include "qwaylandbuffer_p.h"
#if QT_CONFIG(wayland_datadevice)
#include "qwaylanddatadevice_p.h"
#include "qwaylanddatadevicemanager_p.h"
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+#include "qwaylandprimaryselectionv1_p.h"
+#endif
#include "qwaylandtouch_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
@@ -73,6 +77,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+Q_LOGGING_CATEGORY(lcQpaWaylandInput, "qt.qpa.wayland.input");
+
QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
: mParent(p)
{
@@ -147,25 +153,45 @@ QWaylandInputDevice::Pointer::~Pointer()
wl_pointer_destroy(object());
}
+QWaylandWindow *QWaylandInputDevice::Pointer::focusWindow() const
+{
+ return mFocus ? mFocus->waylandWindow() : nullptr;
+}
+
#if QT_CONFIG(cursor)
-class CursorSurface : public QObject, public QtWayland::wl_surface
+class WlCallback : public QtWayland::wl_callback {
+public:
+ explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn, bool autoDelete = false)
+ : QtWayland::wl_callback(callback)
+ , m_fn(fn)
+ , m_autoDelete(autoDelete)
+ {}
+ ~WlCallback() override { wl_callback_destroy(object()); }
+ bool done() const { return m_done; }
+ void callback_done(uint32_t callback_data) override {
+ m_done = true;
+ m_fn(callback_data);
+ if (m_autoDelete)
+ delete this;
+ }
+private:
+ bool m_done = false;
+ std::function<void(uint32_t)> m_fn;
+ bool m_autoDelete = false;
+};
+
+class CursorSurface : public QWaylandSurface
{
public:
explicit CursorSurface(QWaylandInputDevice::Pointer *pointer, QWaylandDisplay *display)
- : m_pointer(pointer)
+ : QWaylandSurface(display)
+ , m_pointer(pointer)
{
- init(display->createSurface(this));
//TODO: When we upgrade to libwayland 1.10, use wl_surface_get_version instead.
m_version = display->compositorVersion();
- connect(qApp, &QGuiApplication::screenRemoved, this, [this](QScreen *screen) {
- int oldScale = outputScale();
- if (!m_screens.removeOne(static_cast<QWaylandScreen *>(screen->handle())))
- return;
-
- if (outputScale() != oldScale)
- m_pointer->updateCursor();
- });
+ connect(this, &QWaylandSurface::screensChanged,
+ m_pointer, &QWaylandInputDevice::Pointer::updateCursor);
}
void hide()
@@ -177,7 +203,7 @@ public:
}
// Size and hotspot are in surface coordinates
- void update(wl_buffer *buffer, const QPoint &hotspot, const QSize &size, int bufferScale)
+ void update(wl_buffer *buffer, const QPoint &hotspot, const QSize &size, int bufferScale, bool animated = false)
{
// Calling code needs to ensure buffer scale is supported if != 1
Q_ASSERT(bufferScale == 1 || m_version >= 3);
@@ -194,6 +220,13 @@ public:
attach(buffer, 0, 0);
damage(0, 0, size.width(), size.height());
+ m_frameCallback.reset();
+ if (animated) {
+ m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){
+ Q_UNUSED(time);
+ m_pointer->updateCursor();
+ }));
+ }
commit();
}
@@ -205,38 +238,12 @@ public:
return scale;
}
-protected:
- void surface_enter(struct ::wl_output *output) override
- {
- int oldScale = outputScale();
- auto *screen = QWaylandScreen::fromWlOutput(output);
- if (m_screens.contains(screen))
- return;
-
- m_screens.append(screen);
-
- if (outputScale() != oldScale)
- m_pointer->updateCursor();
- }
-
- void surface_leave(struct ::wl_output *output) override
- {
- int oldScale = outputScale();
- auto *screen = QWaylandScreen::fromWlOutput(output);
-
- if (!m_screens.removeOne(screen))
- return;
-
- if (outputScale() != oldScale)
- m_pointer->updateCursor();
- }
-
private:
+ QScopedPointer<WlCallback> m_frameCallback;
QWaylandInputDevice::Pointer *m_pointer = nullptr;
uint m_version = 0;
uint m_setSerial = 0;
QPoint m_hotspot;
- QVector<QWaylandScreen *> m_screens;
};
QString QWaylandInputDevice::Pointer::cursorThemeName() const
@@ -318,12 +325,14 @@ void QWaylandInputDevice::Pointer::updateCursor()
return;
// Set from shape using theme
- if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape)) {
+ uint time = seat()->mCursor.animationTimer.elapsed();
+ if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) {
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
int bufferScale = mCursor.themeBufferScale;
QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
QSize size = QSize(image->width, image->height) / bufferScale;
- getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale);
+ bool animated = image->delay > 0;
+ getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
return;
}
@@ -353,10 +362,10 @@ QWaylandInputDevice::Touch::~Touch()
}
QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id)
- : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 4))
+ : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 5))
, mQDisplay(display)
, mDisplay(display->wl_display())
- , mVersion(qMin(version, 4))
+ , mVersion(qMin(version, 5))
{
#if QT_CONFIG(wayland_datadevice)
if (mQDisplay->dndSelectionHandler()) {
@@ -364,6 +373,12 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
}
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+ // TODO: Could probably decouple this more if there was a signal for new seat added
+ if (auto *psm = mQDisplay->primarySelectionManager())
+ setPrimarySelectionDevice(psm->createDevice(this));
+#endif
+
if (mQDisplay->textInputManager())
mTextInput.reset(new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat())));
@@ -427,6 +442,21 @@ QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice
return new Touch(device);
}
+QWaylandInputDevice::Keyboard *QWaylandInputDevice::keyboard() const
+{
+ return mKeyboard;
+}
+
+QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const
+{
+ return mPointer;
+}
+
+QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const
+{
+ return mTouch;
+}
+
void QWaylandInputDevice::handleEndDrag()
{
if (mTouch)
@@ -447,6 +477,18 @@ QWaylandDataDevice *QWaylandInputDevice::dataDevice() const
}
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+void QWaylandInputDevice::setPrimarySelectionDevice(QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice)
+{
+ mPrimarySelectionDevice.reset(primarySelectionDevice);
+}
+
+QWaylandPrimarySelectionDeviceV1 *QWaylandInputDevice::primarySelectionDevice() const
+{
+ return mPrimarySelectionDevice.data();
+}
+#endif
+
void QWaylandInputDevice::setTextInput(QWaylandTextInput *textInput)
{
mTextInput.reset(textInput);
@@ -465,7 +507,7 @@ void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
QWaylandWindow *QWaylandInputDevice::pointerFocus() const
{
- return mPointer ? mPointer->mFocus : nullptr;
+ return mPointer ? mPointer->focusWindow() : nullptr;
}
QWaylandWindow *QWaylandInputDevice::keyboardFocus() const
@@ -524,6 +566,7 @@ void QWaylandInputDevice::setCursor(const QCursor *cursor, const QSharedPointer<
mCursor.shape = cursor ? cursor->shape() : Qt::ArrowCursor;
mCursor.hotspot = cursor ? cursor->hotSpot() : QPoint();
mCursor.fallbackOutputScale = fallbackOutputScale;
+ mCursor.animationTimer.start();
if (mCursor.shape == Qt::BitmapCursor) {
mCursor.bitmapBuffer = cachedBuffer ? cachedBuffer : QWaylandCursor::cursorBitmapBuffer(mQDisplay, cursor);
@@ -550,8 +593,9 @@ void QWaylandInputDevice::setCursor(const QCursor *cursor, const QSharedPointer<
class EnterEvent : public QWaylandPointerEvent
{
public:
- EnterEvent(const QPointF &l, const QPointF &g)
- : QWaylandPointerEvent(QWaylandPointerEvent::Enter, 0, l, g, nullptr, Qt::NoModifier)
+ EnterEvent(QWaylandWindow *surface, const QPointF &local, const QPointF &global)
+ : QWaylandPointerEvent(QWaylandPointerEvent::Enter, Qt::NoScrollPhase, surface, 0,
+ local, global, nullptr, Qt::NoModifier)
{}
};
@@ -562,6 +606,7 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
return;
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+
if (!window)
return; // Ignore foreign surfaces
@@ -571,9 +616,8 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
<< "attempting to work around it by invalidating the current focus";
invalidateFocus();
}
-
- mFocus = window;
- connect(mFocus.data(), &QWaylandWindow::wlSurfaceDestroyed, this, &Pointer::handleFocusDestroyed);
+ mFocus = window->waylandSurface();
+ connect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
mSurfacePos = QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy));
mGlobalPos = window->window()->mapToGlobal(mSurfacePos.toPoint());
@@ -587,12 +631,19 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
#endif
QWaylandWindow *grab = QWaylandWindow::mouseGrab();
- if (!grab) {
- EnterEvent evt(mSurfacePos, mGlobalPos);
- window->handleMouse(mParent, evt);
- }
+ if (!grab)
+ setFrameEvent(new EnterEvent(window, mSurfacePos, mGlobalPos));
}
+class LeaveEvent : public QWaylandPointerEvent
+{
+public:
+ LeaveEvent(QWaylandWindow *surface, const QPointF &localPos, const QPointF &globalPos)
+ : QWaylandPointerEvent(QWaylandPointerEvent::Leave, Qt::NoScrollPhase, surface, 0,
+ localPos, globalPos, nullptr, Qt::NoModifier)
+ {}
+};
+
void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surface *surface)
{
// The event may arrive after destroying the window, indicated by
@@ -604,10 +655,8 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
if (!window)
return; // Ignore foreign surfaces
- if (!QWaylandWindow::mouseGrab()) {
- QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
- window->handleMouseLeave(mParent);
- }
+ if (!QWaylandWindow::mouseGrab())
+ setFrameEvent(new LeaveEvent(window, mSurfacePos, mGlobalPos));
invalidateFocus();
mButtons = Qt::NoButton;
@@ -618,15 +667,17 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
class MotionEvent : public QWaylandPointerEvent
{
public:
- MotionEvent(ulong t, const QPointF &l, const QPointF &g, Qt::MouseButtons b, Qt::KeyboardModifiers m)
- : QWaylandPointerEvent(QWaylandPointerEvent::Motion, t, l, g, b, m)
+ MotionEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QWaylandPointerEvent::Motion, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, modifiers)
{
}
};
void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
- QWaylandWindow *window = mFocus;
+ QWaylandWindow *window = focusWindow();
if (!window) {
// We destroyed the pointer focus surface, but the server didn't get the message yet...
// or the server didn't send an enter event first. In either case, ignore the event.
@@ -648,18 +699,37 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
// so we just set it outside of the window boundaries.
pos = QPointF(-1, -1);
global = grab->window()->mapToGlobal(pos.toPoint());
- MotionEvent e(time, pos, global, mButtons, mParent->modifiers());
- grab->handleMouse(mParent, e);
- } else {
- MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
- window->handleMouse(mParent, e);
+ window = grab;
}
+ setFrameEvent(new MotionEvent(window, time, pos, global, mButtons, mParent->modifiers()));
}
+class PressEvent : public QWaylandPointerEvent
+{
+public:
+ PressEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QWaylandPointerEvent::Press, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, modifiers)
+ {
+ }
+};
+
+class ReleaseEvent : public QWaylandPointerEvent
+{
+public:
+ ReleaseEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QWaylandPointerEvent::Release, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, modifiers)
+ {
+ }
+};
+
void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time,
uint32_t button, uint32_t state)
{
- QWaylandWindow *window = mFocus;
+ QWaylandWindow *window = focusWindow();
if (!window) {
// We destroyed the pointer focus surface, but the server didn't get the message yet...
// or the server didn't send an enter event first. In either case, ignore the event.
@@ -701,66 +771,300 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
mParent->mQDisplay->setLastInputDevice(mParent, serial, window);
QWaylandWindow *grab = QWaylandWindow::mouseGrab();
- if (grab && grab != mFocus) {
- QPointF pos = QPointF(-1, -1);
- QPointF global = grab->window()->mapToGlobal(pos.toPoint());
- MotionEvent e(time, pos, global, mButtons, mParent->modifiers());
- grab->handleMouse(mParent, e);
- } else if (window) {
- MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
- window->handleMouse(mParent, e);
+
+ QPointF pos = mSurfacePos;
+ QPointF global = mGlobalPos;
+ if (grab && grab != focusWindow()) {
+ pos = QPointF(-1, -1);
+ global = grab->window()->mapToGlobal(pos.toPoint());
+
+ window = grab;
}
+
+ if (state)
+ setFrameEvent(new PressEvent(window, time, pos, global, mButtons, mParent->modifiers()));
+ else
+ setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, mParent->modifiers()));
}
void QWaylandInputDevice::Pointer::invalidateFocus()
{
- disconnect(mFocus.data(), &QWaylandWindow::wlSurfaceDestroyed, this, &Pointer::handleFocusDestroyed);
- mFocus = nullptr;
+ if (mFocus) {
+ disconnect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
+ mFocus = nullptr;
+ }
mEnterSerial = 0;
}
void QWaylandInputDevice::Pointer::releaseButtons()
{
mButtons = Qt::NoButton;
- MotionEvent e(mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
- if (mFocus)
- mFocus->handleMouse(mParent, e);
+
+ if (auto *window = focusWindow()) {
+ MotionEvent e(focusWindow(), mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
+ window->handleMouse(mParent, e);
+ }
}
class WheelEvent : public QWaylandPointerEvent
{
public:
- WheelEvent(ulong t, const QPointF &l, const QPointF &g, const QPoint &pd, const QPoint &ad, Qt::KeyboardModifiers m)
- : QWaylandPointerEvent(QWaylandPointerEvent::Wheel, t, l, g, pd, ad, m)
+ WheelEvent(QWaylandWindow *surface, Qt::ScrollPhase phase, ulong timestamp, const QPointF &local,
+ const QPointF &global, const QPoint &pixelDelta, const QPoint &angleDelta,
+ Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QWaylandPointerEvent::Wheel, phase, surface, timestamp,
+ local, global, pixelDelta, angleDelta, source, modifiers)
{
}
};
void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, int32_t value)
{
- QWaylandWindow *window = mFocus;
- if (!window) {
+ if (!focusWindow()) {
// We destroyed the pointer focus surface, but the server didn't get the message yet...
// or the server didn't send an enter event first. In either case, ignore the event.
return;
}
- QPoint pixelDelta;
- QPoint angleDelta;
+ // Get the delta and convert it into the expected range
+ switch (axis) {
+ case WL_POINTER_AXIS_VERTICAL_SCROLL:
+ mFrameData.delta.ry() += wl_fixed_to_double(value);
+ qCDebug(lcQpaWaylandInput) << "wl_pointer.axis vertical:" << mFrameData.delta.y();
+ break;
+ case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+ mFrameData.delta.rx() += wl_fixed_to_double(value);
+ qCDebug(lcQpaWaylandInput) << "wl_pointer.axis horizontal:" << mFrameData.delta.x();
+ break;
+ default:
+ //TODO: is this really needed?
+ qCWarning(lcQpaWaylandInput) << "wl_pointer.axis: Unknown axis:" << axis;
+ return;
+ }
- //normalize value and inverse axis
- int valueDelta = wl_fixed_to_int(value) * -12;
+ mParent->mTime = time;
- if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
- pixelDelta = QPoint();
- angleDelta.setX(valueDelta);
- } else {
- pixelDelta = QPoint();
- angleDelta.setY(valueDelta);
+ if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) {
+ qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
+ flushFrameEvent();
+ }
+}
+
+void QWaylandInputDevice::Pointer::pointer_frame()
+{
+ flushFrameEvent();
+}
+
+void QWaylandInputDevice::Pointer::pointer_axis_source(uint32_t source)
+{
+ switch (source) {
+ case axis_source_wheel:
+ qCDebug(lcQpaWaylandInput) << "Axis source wheel";
+ break;
+ case axis_source_finger:
+ qCDebug(lcQpaWaylandInput) << "Axis source finger";
+ break;
+ case axis_source_continuous:
+ qCDebug(lcQpaWaylandInput) << "Axis source continuous";
+ break;
+ }
+ mFrameData.axisSource = axis_source(source);
+}
+
+void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axis)
+{
+ if (!focusWindow())
+ return;
+
+ mParent->mTime = time;
+ switch (axis) {
+ case axis_vertical_scroll:
+ qCDebug(lcQpaWaylandInput) << "Received vertical wl_pointer.axis_stop";
+ mFrameData.delta.setY(0); //TODO: what's the point of doing this?
+ break;
+ case axis_horizontal_scroll:
+ qCDebug(lcQpaWaylandInput) << "Received horizontal wl_pointer.axis_stop";
+ mFrameData.delta.setX(0);
+ break;
+ default:
+ qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_stop: Unknown axis: " << axis
+ << "This is most likely a compositor bug";
+ return;
+ }
+
+ // May receive axis_stop for events we haven't sent a ScrollBegin for because
+ // most axis_sources do not mandate an axis_stop event to be sent.
+ if (!mScrollBeginSent) {
+ // TODO: For now, we just ignore these events, but we could perhaps take this as an
+ // indication that this compositor will in fact send axis_stop events for these sources
+ // and send a ScrollBegin the next time an axis_source event with this type is encountered.
+ return;
+ }
+
+ QWaylandWindow *target = QWaylandWindow::mouseGrab();
+ if (!target)
+ target = focusWindow();
+ Qt::KeyboardModifiers mods = mParent->modifiers();
+ WheelEvent wheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
+ QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods);
+ target->handleMouse(mParent, wheelEvent);
+ mScrollBeginSent = false;
+ mScrollDeltaRemainder = QPointF();
+}
+
+void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t value)
+{
+ if (!focusWindow())
+ return;
+
+ switch (axis) {
+ case axis_vertical_scroll:
+ qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete vertical:" << value;
+ mFrameData.discreteDelta.ry() += value;
+ break;
+ case axis_horizontal_scroll:
+ qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete horizontal:" << value;
+ mFrameData.discreteDelta.rx() += value;
+ break;
+ default:
+ //TODO: is this really needed?
+ qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_discrete: Unknown axis:" << axis;
+ return;
+ }
+}
+
+void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
+{
+ qCDebug(lcQpaWaylandInput) << "Setting frame event " << event->type;
+ if (mFrameData.event && mFrameData.event->type != event->type) {
+ qCDebug(lcQpaWaylandInput) << "Flushing; previous was " << mFrameData.event->type;
+ flushFrameEvent();
+ }
+
+ mFrameData.event = event;
+
+ if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) {
+ qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
+ flushFrameEvent();
+ }
+}
+
+void QWaylandInputDevice::Pointer::FrameData::resetScrollData()
+{
+ discreteDelta = QPoint();
+ delta = QPointF();
+ axisSource = axis_source_wheel;
+}
+
+bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const
+{
+ switch (axisSource) {
+ case axis_source_wheel_tilt: // sideways tilt of the wheel
+ case axis_source_wheel:
+ // In the case of wheel events, a pixel delta doesn't really make sense,
+ // and will make Qt think this is a continuous scroll event when it isn't,
+ // so just ignore it.
+ return false;
+ case axis_source_finger:
+ case axis_source_continuous:
+ return !delta.isNull();
+ }
+}
+
+QPoint QWaylandInputDevice::Pointer::FrameData::pixelDeltaAndError(QPointF *accumulatedError) const
+{
+ if (!hasPixelDelta())
+ return QPoint();
+
+ Q_ASSERT(accumulatedError);
+ // Add accumulated rounding error before rounding again
+ QPoint pixelDelta = (delta + *accumulatedError).toPoint();
+ *accumulatedError += delta - pixelDelta;
+ Q_ASSERT(qAbs(accumulatedError->x()) < 1.0);
+ Q_ASSERT(qAbs(accumulatedError->y()) < 1.0);
+ return pixelDelta;
+}
+
+QPoint QWaylandInputDevice::Pointer::FrameData::angleDelta() const
+{
+ if (discreteDelta.isNull()) {
+ // If we didn't get any discrete events, then we need to fall back to
+ // the continuous information.
+ return (delta * -12).toPoint(); //TODO: why multiply by 12?
}
- WheelEvent e(time, mSurfacePos, mGlobalPos, pixelDelta, angleDelta, mParent->modifiers());
- window->handleMouse(mParent, e);
+ // The angle delta is in eights of degrees, and our docs says most mice have
+ // 1 click = 15 degrees. It's also in the opposite direction of surface space.
+ return -discreteDelta * 15 * 8;
+}
+
+Qt::MouseEventSource QWaylandInputDevice::Pointer::FrameData::wheelEventSource() const
+{
+ switch (axisSource) {
+ case axis_source_wheel_tilt: // sideways tilt of the wheel
+ case axis_source_wheel:
+ return Qt::MouseEventNotSynthesized;
+ case axis_source_finger:
+ case axis_source_continuous:
+ default: // Whatever other sources might be added are probably not mouse wheels
+ return Qt::MouseEventSynthesizedBySystem;
+ }
+}
+
+void QWaylandInputDevice::Pointer::flushScrollEvent()
+{
+ QPoint angleDelta = mFrameData.angleDelta();
+
+ // Angle delta is required for Qt wheel events, so don't try to send events if it's zero
+ if (!angleDelta.isNull()) {
+ QWaylandWindow *target = QWaylandWindow::mouseGrab();
+ if (!target)
+ target = focusWindow();
+
+ if (isDefinitelyTerminated(mFrameData.axisSource) && !mScrollBeginSent) {
+ qCDebug(lcQpaWaylandInput) << "Flushing scroll event sending ScrollBegin";
+ target->handleMouse(mParent, WheelEvent(focusWindow(), Qt::ScrollBegin, mParent->mTime,
+ mSurfacePos, mGlobalPos, QPoint(), QPoint(),
+ Qt::MouseEventNotSynthesized,
+ mParent->modifiers()));
+ mScrollBeginSent = true;
+ mScrollDeltaRemainder = QPointF();
+ }
+
+ Qt::ScrollPhase phase = mScrollBeginSent ? Qt::ScrollUpdate : Qt::NoScrollPhase;
+ QPoint pixelDelta = mFrameData.pixelDeltaAndError(&mScrollDeltaRemainder);
+ Qt::MouseEventSource source = mFrameData.wheelEventSource();
+
+ qCDebug(lcQpaWaylandInput) << "Flushing scroll event" << phase << pixelDelta << angleDelta;
+ target->handleMouse(mParent, WheelEvent(focusWindow(), phase, mParent->mTime, mSurfacePos, mGlobalPos,
+ pixelDelta, angleDelta, source, mParent->modifiers()));
+ }
+
+ mFrameData.resetScrollData();
+}
+
+void QWaylandInputDevice::Pointer::flushFrameEvent()
+{
+ if (auto *event = mFrameData.event) {
+ if (auto window = event->surface) {
+ window->handleMouse(mParent, *event);
+ } else if (mFrameData.event->type == QWaylandPointerEvent::Type::Release) {
+ // If the window has been destroyed, we still need to report an up event, but it can't
+ // be handled by the destroyed window (obviously), so send the event here instead.
+ QWindowSystemInterface::handleMouseEvent(nullptr, event->timestamp, event->local,
+ event->global, event->buttons, event->modifiers);
+ }
+ delete mFrameData.event;
+ mFrameData.event = nullptr;
+ }
+
+ //TODO: do modifiers get passed correctly here?
+ flushScrollEvent();
+}
+
+bool QWaylandInputDevice::Pointer::isDefinitelyTerminated(QtWayland::wl_pointer::axis_source source) const
+{
+ return source == axis_source_finger;
}
void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size)
@@ -927,7 +1231,7 @@ void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
// surface, so we still need to disconnect the signal
auto *window = qobject_cast<QWaylandWindow *>(sender());
disconnect(window, &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
- Q_ASSERT(window->object() == mFocus);
+ Q_ASSERT(window->wlSurface() == mFocus);
handleFocusLost();
}
@@ -938,6 +1242,10 @@ void QWaylandInputDevice::Keyboard::handleFocusLost()
if (auto *dataDevice = mParent->dataDevice())
dataDevice->invalidateSelectionOffer();
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+ if (auto *device = mParent->primarySelectionDevice())
+ device->invalidateSelectionOffer();
+#endif
mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
mRepeatTimer.stop();
}
@@ -1044,7 +1352,7 @@ void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::Touch
//is it possible that mTouchFocus is null;
if (!win && mPointer)
- win = mPointer->mFocus;
+ win = mPointer->focusWindow();
if (!win && mKeyboard)
win = mKeyboard->focusWindow();
if (!win || !win->window())
@@ -1072,7 +1380,7 @@ bool QWaylandInputDevice::Touch::allTouchPointsReleased()
void QWaylandInputDevice::Touch::releasePoints()
{
- Q_FOREACH (const QWindowSystemInterface::TouchPoint &previousPoint, mPrevTouchPoints) {
+ for (const QWindowSystemInterface::TouchPoint &previousPoint : qAsConst(mPrevTouchPoints)) {
QWindowSystemInterface::TouchPoint tp = previousPoint;
tp.state = Qt::TouchPointReleased;
mTouchPoints.append(tp);
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 39ca9dca5..7fbb5667f 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -69,7 +69,8 @@
#endif
#include <QtCore/QDebug>
-#include <QPointer>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QPointer>
#if QT_CONFIG(cursor)
struct wl_cursor_image;
@@ -77,11 +78,17 @@ struct wl_cursor_image;
QT_BEGIN_NAMESPACE
+namespace QtWayland {
+class zwp_primary_selection_device_v1;
+} //namespace QtWayland
+
namespace QtWaylandClient {
-class QWaylandWindow;
-class QWaylandDisplay;
class QWaylandDataDevice;
+class QWaylandDisplay;
+#if QT_CONFIG(wayland_client_primary_selection)
+class QWaylandPrimarySelectionDeviceV1;
+#endif
class QWaylandTextInput;
#if QT_CONFIG(cursor)
class QWaylandCursorTheme;
@@ -115,6 +122,11 @@ public:
QWaylandDataDevice *dataDevice() const;
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+ void setPrimarySelectionDevice(QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice);
+ QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice() const;
+#endif
+
void setTextInput(QWaylandTextInput *textInput);
QWaylandTextInput *textInput() const;
@@ -136,6 +148,10 @@ public:
virtual Pointer *createPointer(QWaylandInputDevice *device);
virtual Touch *createTouch(QWaylandInputDevice *device);
+ Keyboard *keyboard() const;
+ Pointer *pointer() const;
+ Touch *touch() const;
+
private:
QWaylandDisplay *mQDisplay = nullptr;
struct wl_display *mDisplay = nullptr;
@@ -150,6 +166,7 @@ private:
Qt::CursorShape shape = Qt::ArrowCursor;
int fallbackOutputScale = 1;
QPoint hotspot;
+ QElapsedTimer animationTimer;
} mCursor;
#endif
@@ -157,6 +174,10 @@ private:
QWaylandDataDevice *mDataDevice = nullptr;
#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+ QScopedPointer<QWaylandPrimarySelectionDeviceV1> mPrimarySelectionDevice;
+#endif
+
Keyboard *mKeyboard = nullptr;
Pointer *mPointer = nullptr;
Touch *mTouch = nullptr;
@@ -231,6 +252,8 @@ public:
Qt::KeyboardModifiers modifiers() const;
+ struct ::wl_keyboard *wl_keyboard() { return QtWayland::wl_keyboard::object(); }
+
private slots:
void handleFocusDestroyed();
void handleFocusLost();
@@ -256,6 +279,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, pub
public:
explicit Pointer(QWaylandInputDevice *seat);
~Pointer() override;
+ QWaylandWindow *focusWindow() const;
#if QT_CONFIG(cursor)
QString cursorThemeName() const;
int cursorSize() const; // in surface coordinates
@@ -266,6 +290,8 @@ public:
#endif
QWaylandInputDevice *seat() const { return mParent; }
+ struct ::wl_pointer *wl_pointer() { return QtWayland::wl_pointer::object(); }
+
protected:
void pointer_enter(uint32_t serial, struct wl_surface *surface,
wl_fixed_t sx, wl_fixed_t sy) override;
@@ -277,6 +303,10 @@ protected:
void pointer_axis(uint32_t time,
uint32_t axis,
wl_fixed_t value) override;
+ void pointer_axis_source(uint32_t source) override;
+ void pointer_axis_stop(uint32_t time, uint32_t axis) override;
+ void pointer_axis_discrete(uint32_t axis, int32_t value) override;
+ void pointer_frame() override;
private slots:
void handleFocusDestroyed() { invalidateFocus(); }
@@ -288,7 +318,7 @@ public:
void releaseButtons();
QWaylandInputDevice *mParent = nullptr;
- QPointer<QWaylandWindow> mFocus;
+ QPointer<QWaylandSurface> mFocus;
uint32_t mEnterSerial = 0;
#if QT_CONFIG(cursor)
struct {
@@ -304,6 +334,30 @@ public:
wl_buffer *mCursorBuffer = nullptr;
Qt::CursorShape mCursorShape = Qt::BitmapCursor;
#endif
+
+ struct FrameData {
+ QWaylandPointerEvent *event = nullptr;
+
+ QPointF delta;
+ QPoint discreteDelta;
+ axis_source axisSource = axis_source_wheel;
+
+ void resetScrollData();
+ bool hasPixelDelta() const;
+ QPoint pixelDeltaAndError(QPointF *accumulatedError) const;
+ QPoint pixelDelta() const { return hasPixelDelta() ? delta.toPoint() : QPoint(); }
+ QPoint angleDelta() const;
+ Qt::MouseEventSource wheelEventSource() const;
+ } mFrameData;
+
+ bool mScrollBeginSent = false;
+ QPointF mScrollDeltaRemainder;
+
+ void setFrameEvent(QWaylandPointerEvent *event);
+ void flushScrollEvent();
+ void flushFrameEvent();
+private: //TODO: should other methods be private as well?
+ bool isDefinitelyTerminated(axis_source source) const;
};
class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Touch : public QtWayland::wl_touch
@@ -331,6 +385,8 @@ public:
bool allTouchPointsReleased();
void releasePoints();
+ struct ::wl_touch *wl_touch() { return QtWayland::wl_touch::object(); }
+
QWaylandInputDevice *mParent = nullptr;
QPointer<QWaylandWindow> mFocus;
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
@@ -339,38 +395,58 @@ public:
class QWaylandPointerEvent
{
+ Q_GADGET
public:
enum Type {
Enter,
+ Leave,
Motion,
+ Press,
+ Release,
Wheel
};
- inline QWaylandPointerEvent(Type t, ulong ts, const QPointF &l, const QPointF &g, Qt::MouseButtons b, Qt::KeyboardModifiers m)
- : type(t)
- , timestamp(ts)
- , local(l)
- , global(g)
- , buttons(b)
- , modifiers(m)
+ Q_ENUM(Type)
+
+ inline QWaylandPointerEvent(Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
+ ulong timestamp, const QPointF &localPos, const QPointF &globalPos,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ : type(type)
+ , phase(phase)
+ , timestamp(timestamp)
+ , local(localPos)
+ , global(globalPos)
+ , buttons(buttons)
+ , modifiers(modifiers)
+ , surface(surface)
{}
- inline QWaylandPointerEvent(Type t, ulong ts, const QPointF &l, const QPointF &g, const QPoint &pd, const QPoint &ad, Qt::KeyboardModifiers m)
- : type(t)
- , timestamp(ts)
- , local(l)
- , global(g)
- , modifiers(m)
- , pixelDelta(pd)
- , angleDelta(ad)
+ inline QWaylandPointerEvent(Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
+ ulong timestamp, const QPointF &local, const QPointF &global,
+ const QPoint &pixelDelta, const QPoint &angleDelta,
+ Qt::MouseEventSource source,
+ Qt::KeyboardModifiers modifiers)
+ : type(type)
+ , phase(phase)
+ , timestamp(timestamp)
+ , local(local)
+ , global(global)
+ , modifiers(modifiers)
+ , pixelDelta(pixelDelta)
+ , angleDelta(angleDelta)
+ , source(source)
+ , surface(surface)
{}
Type type;
- ulong timestamp;
+ Qt::ScrollPhase phase = Qt::NoScrollPhase;
+ ulong timestamp = 0;
QPointF local;
QPointF global;
Qt::MouseButtons buttons;
Qt::KeyboardModifiers modifiers;
QPoint pixelDelta;
QPoint angleDelta;
+ Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+ QPointer<QWaylandWindow> surface;
};
}
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 85fcef43f..f6a80e18f 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -272,7 +272,7 @@ QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
if (!mAccessibility) {
#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
- Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QXcbIntegration",
+ Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QWaylandIntegration",
"Initializing accessibility without event-dispatcher!");
mAccessibility.reset(new QSpiAccessibleBridge());
#else
@@ -352,7 +352,7 @@ void QWaylandIntegration::initializeClientBufferIntegration()
&& mDisplay->hardwareIntegration()->clientBufferIntegration() != QLatin1String("linux-dmabuf-unstable-v1")) {
targetKey = mDisplay->hardwareIntegration()->clientBufferIntegration();
} else {
- targetKey = QLatin1Literal("wayland-egl");
+ targetKey = QLatin1String("wayland-egl");
}
}
@@ -430,7 +430,7 @@ void QWaylandIntegration::initializeShellIntegration()
preferredShells << QLatin1String("wl-shell") << QLatin1String("ivi-shell");
}
- Q_FOREACH (QString preferredShell, preferredShells) {
+ for (const QString &preferredShell : qAsConst(preferredShells)) {
mShellIntegration.reset(createShellIntegration(preferredShell));
if (mShellIntegration) {
qCDebug(lcQpaWayland, "Using the '%s' shell integration", qPrintable(preferredShell));
diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp
index 76acb526b..b4ecc0090 100644
--- a/src/client/qwaylandnativeinterface.cpp
+++ b/src/client/qwaylandnativeinterface.cpp
@@ -47,6 +47,7 @@
#include "qwaylanddisplay_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandscreen_p.h"
+#include "qwaylandinputdevice_p.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QScreen>
#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
@@ -76,6 +77,27 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re
if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration())
return m_integration->clientBufferIntegration()->nativeResource(QWaylandClientBufferIntegration::EglDisplay);
+ if (lowerCaseResource == "wl_seat")
+ return m_integration->display()->defaultInputDevice()->wl_seat();
+ if (lowerCaseResource == "wl_keyboard") {
+ auto *keyboard = m_integration->display()->defaultInputDevice()->keyboard();
+ if (keyboard)
+ return keyboard->wl_keyboard();
+ return nullptr;
+ }
+ if (lowerCaseResource == "wl_pointer") {
+ auto *pointer = m_integration->display()->defaultInputDevice()->pointer();
+ if (pointer)
+ return pointer->wl_pointer();
+ return nullptr;
+ }
+ if (lowerCaseResource == "wl_touch") {
+ auto *touch = m_integration->display()->defaultInputDevice()->touch();
+ if (touch)
+ return touch->wl_touch();
+ return nullptr;
+ }
+
return nullptr;
}
@@ -89,7 +111,7 @@ void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourc
return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
if (lowerCaseResource == "surface") {
QWaylandWindow *w = static_cast<QWaylandWindow*>(window->handle());
- return w ? w->object() : nullptr;
+ return w ? w->wlSurface() : nullptr;
}
if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration())
diff --git a/src/client/qwaylandprimaryselectionv1.cpp b/src/client/qwaylandprimaryselectionv1.cpp
new file mode 100644
index 000000000..3ddf6dac3
--- /dev/null
+++ b/src/client/qwaylandprimaryselectionv1.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandprimaryselectionv1_p.h"
+#include "qwaylandinputdevice_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandmimehelper_p.h"
+
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatformclipboard.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandPrimarySelectionDeviceManagerV1::QWaylandPrimarySelectionDeviceManagerV1(QWaylandDisplay *display, uint id, uint version)
+ : zwp_primary_selection_device_manager_v1(display->wl_registry(), id, qMin(version, uint(1)))
+ , m_display(display)
+{
+ // Create devices for all seats.
+ // This only works if we get the global before all devices
+ const auto seats = m_display->inputDevices();
+ for (auto *seat : seats)
+ seat->setPrimarySelectionDevice(createDevice(seat));
+}
+
+QWaylandPrimarySelectionDeviceV1 *QWaylandPrimarySelectionDeviceManagerV1::createDevice(QWaylandInputDevice *seat)
+{
+ return new QWaylandPrimarySelectionDeviceV1(this, seat);
+}
+
+QWaylandPrimarySelectionOfferV1::QWaylandPrimarySelectionOfferV1(QWaylandDisplay *display, ::zwp_primary_selection_offer_v1 *offer)
+ : zwp_primary_selection_offer_v1(offer)
+ , m_display(display)
+ , m_mimeData(new QWaylandMimeData(this))
+{}
+
+void QWaylandPrimarySelectionOfferV1::startReceiving(const QString &mimeType, int fd)
+{
+ receive(mimeType, fd);
+ wl_display_flush(m_display->wl_display());
+}
+
+void QWaylandPrimarySelectionOfferV1::zwp_primary_selection_offer_v1_offer(const QString &mime_type)
+{
+ m_mimeData->appendFormat(mime_type);
+}
+
+QWaylandPrimarySelectionDeviceV1::QWaylandPrimarySelectionDeviceV1(
+ QWaylandPrimarySelectionDeviceManagerV1 *manager, QWaylandInputDevice *seat)
+ : QtWayland::zwp_primary_selection_device_v1(manager->get_device(seat->wl_seat()))
+ , m_display(manager->display())
+ , m_seat(seat)
+{
+}
+
+QWaylandPrimarySelectionDeviceV1::~QWaylandPrimarySelectionDeviceV1()
+{
+ destroy();
+}
+
+void QWaylandPrimarySelectionDeviceV1::setSelectionSource(QWaylandPrimarySelectionSourceV1 *source)
+{
+ if (source) {
+ connect(source, &QWaylandPrimarySelectionSourceV1::cancelled, this, [this]() {
+ m_selectionSource.reset();
+ QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Selection);
+ });
+ }
+ set_selection(source ? source->object() : nullptr, m_seat->serial());
+ m_selectionSource.reset(source);
+}
+
+void QWaylandPrimarySelectionDeviceV1::zwp_primary_selection_device_v1_data_offer(zwp_primary_selection_offer_v1 *offer)
+{
+ new QWaylandPrimarySelectionOfferV1(m_display, offer);
+}
+
+void QWaylandPrimarySelectionDeviceV1::zwp_primary_selection_device_v1_selection(zwp_primary_selection_offer_v1 *id)
+{
+
+ if (id)
+ m_selectionOffer.reset(static_cast<QWaylandPrimarySelectionOfferV1 *>(zwp_primary_selection_offer_v1_get_user_data(id)));
+ else
+ m_selectionOffer.reset();
+
+ QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Selection);
+}
+
+QWaylandPrimarySelectionSourceV1::QWaylandPrimarySelectionSourceV1(QWaylandPrimarySelectionDeviceManagerV1 *manager, QMimeData *mimeData)
+ : QtWayland::zwp_primary_selection_source_v1(manager->create_source())
+ , m_mimeData(mimeData)
+{
+ if (!mimeData)
+ return;
+ for (auto &format : mimeData->formats())
+ offer(format);
+}
+
+QWaylandPrimarySelectionSourceV1::~QWaylandPrimarySelectionSourceV1()
+{
+ destroy();
+}
+
+void QWaylandPrimarySelectionSourceV1::zwp_primary_selection_source_v1_send(const QString &mime_type, int32_t fd)
+{
+ QByteArray content = QWaylandMimeHelper::getByteArray(m_mimeData, mime_type);
+ if (!content.isEmpty()) {
+ // Create a sigpipe handler that does nothing, or clients may be forced to terminate
+ // if the pipe is closed in the other end.
+ struct sigaction action, oldAction;
+ action.sa_handler = SIG_IGN;
+ sigemptyset (&action.sa_mask);
+ action.sa_flags = 0;
+
+ sigaction(SIGPIPE, &action, &oldAction);
+ write(fd, content.constData(), size_t(content.size()));
+ sigaction(SIGPIPE, &oldAction, nullptr);
+ }
+ close(fd);
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandprimaryselectionv1_p.h b/src/client/qwaylandprimaryselectionv1_p.h
new file mode 100644
index 000000000..b165c51b8
--- /dev/null
+++ b/src/client/qwaylandprimaryselectionv1_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDPRIMARYSELECTIONV1_P_H
+#define QWAYLANDPRIMARYSELECTIONV1_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtWaylandClient/private/qwayland-wp-primary-selection-unstable-v1.h>
+
+#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
+#include <QtWaylandClient/private/qwaylanddataoffer_p.h>
+
+#include <QtCore/QObject>
+
+QT_REQUIRE_CONFIG(wayland_client_primary_selection);
+
+QT_BEGIN_NAMESPACE
+
+class QMimeData;
+
+namespace QtWaylandClient {
+
+class QWaylandInputDevice;
+class QWaylandPrimarySelectionDeviceV1;
+
+class QWaylandPrimarySelectionDeviceManagerV1 : public QtWayland::zwp_primary_selection_device_manager_v1
+{
+public:
+ explicit QWaylandPrimarySelectionDeviceManagerV1(QWaylandDisplay *display, uint id, uint version);
+ QWaylandPrimarySelectionDeviceV1 *createDevice(QWaylandInputDevice *seat);
+ QWaylandDisplay *display() const { return m_display; }
+
+private:
+ QWaylandDisplay *m_display = nullptr;
+};
+
+class QWaylandPrimarySelectionOfferV1 : public QtWayland::zwp_primary_selection_offer_v1, public QWaylandAbstractDataOffer
+{
+public:
+ explicit QWaylandPrimarySelectionOfferV1(QWaylandDisplay *display, ::zwp_primary_selection_offer_v1 *offer);
+ ~QWaylandPrimarySelectionOfferV1() override { destroy(); }
+ void startReceiving(const QString &mimeType, int fd) override;
+ QMimeData *mimeData() override { return m_mimeData.data(); }
+
+protected:
+ void zwp_primary_selection_offer_v1_offer(const QString &mime_type) override;
+
+private:
+ QWaylandDisplay *m_display = nullptr;
+ QScopedPointer<QWaylandMimeData> m_mimeData;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandPrimarySelectionSourceV1 : public QObject, public QtWayland::zwp_primary_selection_source_v1
+{
+ Q_OBJECT
+public:
+ explicit QWaylandPrimarySelectionSourceV1(QWaylandPrimarySelectionDeviceManagerV1 *manager, QMimeData *mimeData);
+ ~QWaylandPrimarySelectionSourceV1() override;
+
+ QMimeData *mimeData() const { return m_mimeData; }
+
+signals:
+ void cancelled();
+
+protected:
+ void zwp_primary_selection_source_v1_send(const QString &mime_type, int32_t fd) override;
+ void zwp_primary_selection_source_v1_cancelled() override { emit cancelled(); }
+
+private:
+ QWaylandDisplay *m_display = nullptr;
+ QMimeData *m_mimeData = nullptr;
+};
+
+class QWaylandPrimarySelectionDeviceV1 : public QObject, public QtWayland::zwp_primary_selection_device_v1
+{
+ Q_OBJECT
+ QWaylandPrimarySelectionDeviceV1(QWaylandPrimarySelectionDeviceManagerV1 *manager, QWaylandInputDevice *seat);
+
+public:
+ ~QWaylandPrimarySelectionDeviceV1() override;
+ QWaylandPrimarySelectionOfferV1 *selectionOffer() const { return m_selectionOffer.data(); }
+ void invalidateSelectionOffer() { m_selectionOffer.reset(); }
+ QWaylandPrimarySelectionSourceV1 *selectionSource() const { return m_selectionSource.data(); }
+ void setSelectionSource(QWaylandPrimarySelectionSourceV1 *source);
+
+protected:
+ void zwp_primary_selection_device_v1_data_offer(struct ::zwp_primary_selection_offer_v1 *offer) override;
+ void zwp_primary_selection_device_v1_selection(struct ::zwp_primary_selection_offer_v1 *id) override;
+
+private:
+ QWaylandDisplay *m_display = nullptr;
+ QWaylandInputDevice *m_seat = nullptr;
+ QScopedPointer<QWaylandPrimarySelectionOfferV1> m_selectionOffer;
+ QScopedPointer<QWaylandPrimarySelectionSourceV1> m_selectionSource;
+ friend class QWaylandPrimarySelectionDeviceManagerV1;
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDPRIMARYSELECTIONV1_P_H
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index d116a807b..e70796832 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -175,7 +175,8 @@ QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const
void QWaylandScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
{
- foreach (QWindow *window, QGuiApplication::allWindows()) {
+ const auto allWindows = QGuiApplication::allWindows();
+ for (QWindow *window : allWindows) {
QWaylandWindow *w = static_cast<QWaylandWindow *>(window->handle());
if (w && w->waylandScreen() == this)
w->setOrientationMask(mask);
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index 34044ec9b..9b5971a21 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -243,12 +243,13 @@ void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
{
- foreach (QWaylandShmBuffer *b, mBuffers) {
+ const auto copy = mBuffers; // remove when ported to vector<unique_ptr> + remove_if
+ for (QWaylandShmBuffer *b : copy) {
if (!b->busy()) {
if (b->size() == size) {
return b;
} else {
- mBuffers.removeOne(b);
+ mBuffers.remove(b);
if (mBackBuffer == b)
mBackBuffer = nullptr;
delete b;
@@ -256,11 +257,11 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
}
}
- static const int MAX_BUFFERS = 5;
- if (mBuffers.count() < MAX_BUFFERS) {
+ static const size_t MAX_BUFFERS = 5;
+ if (mBuffers.size() < MAX_BUFFERS) {
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
QWaylandShmBuffer *b = new QWaylandShmBuffer(mDisplay, size, format, waylandWindow()->scale());
- mBuffers.prepend(b);
+ mBuffers.push_front(b);
return b;
}
return nullptr;
@@ -288,20 +289,23 @@ void QWaylandShmBackingStore::resize(const QSize &size)
buffer = getBuffer(sizeWithMargins);
}
- qsizetype oldSize = mBackBuffer ? mBackBuffer->image()->sizeInBytes() : 0;
+ qsizetype oldSizeInBytes = mBackBuffer ? mBackBuffer->image()->sizeInBytes() : 0;
+ qsizetype newSizeInBytes = buffer->image()->sizeInBytes();
+
// mBackBuffer may have been deleted here but if so it means its size was different so we wouldn't copy it anyway
- if (mBackBuffer != buffer && oldSize == buffer->image()->sizeInBytes()) {
- memcpy(buffer->image()->bits(), mBackBuffer->image()->constBits(), buffer->image()->sizeInBytes());
- }
+ if (mBackBuffer != buffer && oldSizeInBytes == newSizeInBytes)
+ memcpy(buffer->image()->bits(), mBackBuffer->image()->constBits(), newSizeInBytes);
+
mBackBuffer = buffer;
+
// ensure the new buffer is at the beginning of the list so next time getBuffer() will pick
// it if possible
- if (mBuffers.first() != buffer) {
- mBuffers.removeOne(buffer);
- mBuffers.prepend(buffer);
+ if (mBuffers.front() != buffer) {
+ mBuffers.remove(buffer);
+ mBuffers.push_front(buffer);
}
- if (windowDecoration() && window()->isVisible())
+ if (windowDecoration() && window()->isVisible() && oldSizeInBytes != newSizeInBytes)
windowDecoration()->update();
}
diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h
index 88ecfc5ec..8a85cd7f3 100644
--- a/src/client/qwaylandshmbackingstore_p.h
+++ b/src/client/qwaylandshmbackingstore_p.h
@@ -57,7 +57,8 @@
#include <QtGui/QImage>
#include <qpa/qplatformwindow.h>
#include <QMutex>
-#include <QLinkedList>
+
+#include <list>
QT_BEGIN_NAMESPACE
@@ -116,7 +117,7 @@ private:
QWaylandShmBuffer *getBuffer(const QSize &size);
QWaylandDisplay *mDisplay = nullptr;
- QLinkedList<QWaylandShmBuffer *> mBuffers;
+ std::list<QWaylandShmBuffer *> mBuffers;
QWaylandShmBuffer *mFrontBuffer = nullptr;
QWaylandShmBuffer *mBackBuffer = nullptr;
bool mPainting = false;
diff --git a/src/client/qwaylandsurface.cpp b/src/client/qwaylandsurface.cpp
new file mode 100644
index 000000000..c35f01b56
--- /dev/null
+++ b/src/client/qwaylandsurface.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandsurface_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandscreen_p.h"
+
+#include <QtGui/QGuiApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandSurface::QWaylandSurface(QWaylandDisplay *display)
+ : wl_surface(display->createSurface(this))
+{
+ connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandSurface::handleScreenRemoved);
+}
+
+QWaylandSurface::~QWaylandSurface()
+{
+ destroy();
+}
+
+QWaylandScreen *QWaylandSurface::oldestEnteredScreen()
+{
+ return m_screens.value(0, nullptr);
+}
+
+QWaylandSurface *QWaylandSurface::fromWlSurface(::wl_surface *surface)
+{
+ if (auto *s = QtWayland::wl_surface::fromObject(surface))
+ return static_cast<QWaylandSurface *>(s);
+ return nullptr;
+}
+
+void QWaylandSurface::handleScreenRemoved(QScreen *qScreen)
+{
+ auto *screen = static_cast<QWaylandScreen *>(qScreen->handle());
+ if (m_screens.removeOne(screen))
+ emit screensChanged();
+}
+
+void QWaylandSurface::surface_enter(wl_output *output)
+{
+ auto addedScreen = QWaylandScreen::fromWlOutput(output);
+
+ if (!addedScreen)
+ return;
+
+ if (m_screens.contains(addedScreen)) {
+ qCWarning(lcQpaWayland)
+ << "Ignoring unexpected wl_surface.enter received for output with id:"
+ << wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output))
+ << "screen name:" << addedScreen->name() << "screen model:" << addedScreen->model()
+ << "This is most likely a bug in the compositor.";
+ return;
+ }
+
+ m_screens.append(addedScreen);
+ emit screensChanged();
+}
+
+void QWaylandSurface::surface_leave(wl_output *output)
+{
+ auto *removedScreen = QWaylandScreen::fromWlOutput(output);
+
+ if (!removedScreen)
+ return;
+
+ bool wasRemoved = m_screens.removeOne(removedScreen);
+ if (!wasRemoved) {
+ qCWarning(lcQpaWayland)
+ << "Ignoring unexpected wl_surface.leave received for output with id:"
+ << wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output))
+ << "screen name:" << removedScreen->name()
+ << "screen model:" << removedScreen->model()
+ << "This is most likely a bug in the compositor.";
+ return;
+ }
+ emit screensChanged();
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandsurface_p.h b/src/client/qwaylandsurface_p.h
new file mode 100644
index 000000000..541010934
--- /dev/null
+++ b/src/client/qwaylandsurface_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests 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 QWAYLANDSURFACE_P_H
+#define QWAYLANDSURFACE_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 <QtGui/QScreen>
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandScreen;
+class QWaylandWindow;
+class QWaylandDisplay;
+
+class QWaylandSurface : public QObject, public QtWayland::wl_surface
+{
+ Q_OBJECT
+public:
+ explicit QWaylandSurface(QWaylandDisplay *display);
+ ~QWaylandSurface() override;
+ QWaylandScreen *oldestEnteredScreen();
+ QWaylandWindow *waylandWindow() const { return m_window; }
+
+ static QWaylandSurface *fromWlSurface(::wl_surface *surface);
+
+signals:
+ void screensChanged();
+
+private slots:
+ void handleScreenRemoved(QScreen *qScreen);
+
+protected:
+ void surface_enter(struct ::wl_output *output) override;
+ void surface_leave(struct ::wl_output *output) override;
+
+ QVector<QWaylandScreen *> m_screens; //As seen by wl_surface.enter/leave events. Chronological order.
+ QWaylandWindow *m_window = nullptr;
+
+ friend class QWaylandWindow; // TODO: shouldn't need to be friends
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDSURFACE_P_H
diff --git a/src/client/qwaylandtouch.cpp b/src/client/qwaylandtouch.cpp
index 48c869a60..0394aef31 100644
--- a/src/client/qwaylandtouch.cpp
+++ b/src/client/qwaylandtouch.cpp
@@ -40,6 +40,7 @@
#include "qwaylandtouch_p.h"
#include "qwaylandinputdevice_p.h"
#include "qwaylanddisplay_p.h"
+#include "qwaylandsurface_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 40289d814..60317cda7 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -41,6 +41,7 @@
#include "qwaylandbuffer_p.h"
#include "qwaylanddisplay_p.h"
+#include "qwaylandsurface_p.h"
#include "qwaylandinputdevice_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandshellsurface_p.h"
@@ -80,7 +81,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
{
static WId id = 1;
mWindowId = id++;
- connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandWindow::handleScreenRemoved);
initializeWlSurface();
}
@@ -90,11 +90,12 @@ QWaylandWindow::~QWaylandWindow()
delete mWindowDecoration;
- if (isInitialized())
+ if (mSurface)
reset(false);
const QWindow *parent = window();
- foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
+ const auto tlw = QGuiApplication::topLevelWindows();
+ for (QWindow *w : tlw) {
if (w->transientParent() == parent)
QWindowSystemInterface::handleCloseEvent(w);
}
@@ -115,7 +116,7 @@ void QWaylandWindow::initWindow()
if (window()->type() == Qt::Desktop)
return;
- if (!isInitialized()) {
+ if (!mSurface) {
initializeWlSurface();
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
QGuiApplication::sendEvent(window(), &e);
@@ -181,7 +182,7 @@ void QWaylandWindow::initWindow()
// typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
// to inform the compositor that high-resolution buffers will be provided.
if (mDisplay->compositorVersion() >= 3)
- set_buffer_scale(scale());
+ mSurface->set_buffer_scale(scale());
if (QScreen *s = window()->screen())
setOrientationMask(s->orientationUpdateMask());
@@ -199,8 +200,11 @@ void QWaylandWindow::initWindow()
void QWaylandWindow::initializeWlSurface()
{
- Q_ASSERT(!isInitialized());
- init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
+ Q_ASSERT(!mSurface);
+ mSurface.reset(new QWaylandSurface(mDisplay));
+ connect(mSurface.data(), &QWaylandSurface::screensChanged,
+ this, &QWaylandWindow::handleScreensChanged);
+ mSurface->m_window = this;
emit wlSurfaceCreated();
}
@@ -228,7 +232,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
void QWaylandWindow::reset(bool sendDestroyEvent)
{
- if (isInitialized() && sendDestroyEvent) {
+ if (mSurface && sendDestroyEvent) {
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
QGuiApplication::sendEvent(window(), &e);
}
@@ -236,11 +240,10 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
mShellSurface = nullptr;
delete mSubSurfaceWindow;
mSubSurfaceWindow = nullptr;
- if (isInitialized()) {
+ if (mSurface) {
emit wlSurfaceDestroyed();
- destroy();
+ mSurface.reset();
}
- mScreens.clear();
if (mFrameCallback) {
wl_callback_destroy(mFrameCallback);
@@ -260,7 +263,9 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
{
- return static_cast<QWaylandWindow *>(static_cast<QtWayland::wl_surface *>(wl_surface_get_user_data(surface)));
+ if (auto *s = QWaylandSurface::fromWlSurface(surface))
+ return s->m_window;
+ return nullptr;
}
WId QWaylandWindow::winId() const
@@ -392,7 +397,12 @@ void QWaylandWindow::closePopups(QWaylandWindow *parent)
QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
{
- return mScreens.isEmpty() ? waylandScreen() : mScreens.first();
+ if (mSurface) {
+ if (auto *screen = mSurface->oldestEnteredScreen())
+ return screen;
+ }
+
+ return waylandScreen();
}
void QWaylandWindow::setVisible(bool visible)
@@ -436,18 +446,18 @@ void QWaylandWindow::setMask(const QRegion &mask)
mMask = mask;
- if (!isInitialized())
+ if (!mSurface)
return;
if (mMask.isEmpty()) {
- set_input_region(nullptr);
+ mSurface->set_input_region(nullptr);
} else {
struct ::wl_region *region = mDisplay->createRegion(mMask);
- set_input_region(region);
+ mSurface->set_input_region(region);
wl_region_destroy(region);
}
- wl_surface::commit();
+ mSurface->commit();
}
void QWaylandWindow::applyConfigureWhenPossible()
@@ -501,58 +511,6 @@ void QWaylandWindow::applyConfigure()
QWindowSystemInterface::flushWindowSystemEvents();
}
-void QWaylandWindow::surface_enter(wl_output *output)
-{
- QWaylandScreen *oldScreen = calculateScreenFromSurfaceEvents();
- auto addedScreen = QWaylandScreen::fromWlOutput(output);
-
- if (mScreens.contains(addedScreen)) {
- qCWarning(lcQpaWayland)
- << "Ignoring unexpected wl_surface.enter received for output with id:"
- << wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output))
- << "screen name:" << addedScreen->name() << "screen model:" << addedScreen->model()
- << "This is most likely a bug in the compositor.";
- return;
- }
-
- mScreens.append(addedScreen);
-
- QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
- if (oldScreen != newScreen) //currently this will only happen if the first wl_surface.enter is for a non-primary screen
- handleScreenChanged();
-}
-
-void QWaylandWindow::surface_leave(wl_output *output)
-{
- QWaylandScreen *oldScreen = calculateScreenFromSurfaceEvents();
- auto *removedScreen = QWaylandScreen::fromWlOutput(output);
- bool wasRemoved = mScreens.removeOne(removedScreen);
- if (!wasRemoved) {
- qCWarning(lcQpaWayland)
- << "Ignoring unexpected wl_surface.leave received for output with id:"
- << wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output))
- << "screen name:" << removedScreen->name()
- << "screen model:" << removedScreen->model()
- << "This is most likely a bug in the compositor.";
- return;
- }
-
- QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
- if (oldScreen != newScreen)
- handleScreenChanged();
-}
-
-void QWaylandWindow::handleScreenRemoved(QScreen *qScreen)
-{
- QWaylandScreen *oldScreen = calculateScreenFromSurfaceEvents();
- bool wasRemoved = mScreens.removeOne(static_cast<QWaylandScreen *>(qScreen->handle()));
- if (wasRemoved) {
- QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
- if (oldScreen != newScreen)
- handleScreenChanged();
- }
-}
-
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
{
Q_ASSERT(!buffer->committed());
@@ -560,9 +518,9 @@ void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
handleUpdate();
buffer->setBusy();
- QtWayland::wl_surface::attach(buffer->buffer(), x, y);
+ mSurface->attach(buffer->buffer(), x, y);
} else {
- QtWayland::wl_surface::attach(nullptr, 0, 0);
+ mSurface->attach(nullptr, 0, 0);
}
}
@@ -574,7 +532,7 @@ void QWaylandWindow::attachOffset(QWaylandBuffer *buffer)
void QWaylandWindow::damage(const QRect &rect)
{
- damage(rect.x(), rect.y(), rect.width(), rect.height());
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
}
void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
@@ -604,20 +562,20 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
qCDebug(lcWaylandBackingstore) << "Buffer already committed, ignoring.";
return;
}
- if (!isInitialized())
+ if (!mSurface)
return;
attachOffset(buffer);
for (const QRect &rect: damage)
- wl_surface::damage(rect.x(), rect.y(), rect.width(), rect.height());
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
Q_ASSERT(!buffer->committed());
buffer->setCommitted();
- wl_surface::commit();
+ mSurface->commit();
}
void QWaylandWindow::commit()
{
- wl_surface::commit();
+ mSurface->commit();
}
const wl_callback_listener QWaylandWindow::callbackListener = {
@@ -707,6 +665,11 @@ QRect QWaylandWindow::windowContentGeometry() const
return QRect(QPoint(), surfaceSize());
}
+wl_surface *QWaylandWindow::wlSurface()
+{
+ return mSurface ? mSurface->object() : nullptr;
+}
+
QWaylandShellSurface *QWaylandWindow::shellSurface() const
{
return mShellSurface;
@@ -748,9 +711,9 @@ void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orient
default:
Q_UNREACHABLE();
}
- set_buffer_transform(transform);
+ mSurface->set_buffer_transform(transform);
// set_buffer_transform is double buffered, we need to commit.
- wl_surface::commit();
+ mSurface->commit();
}
void QWaylandWindow::setOrientationMask(Qt::ScreenOrientations mask)
@@ -839,7 +802,7 @@ bool QWaylandWindow::createDecoration()
}
if (hadDecoration != (bool)mWindowDecoration) {
- foreach (QWaylandSubSurface *subsurf, mChildren) {
+ for (QWaylandSubSurface *subsurf : qAsConst(mChildren)) {
QPoint pos = subsurf->window()->geometry().topLeft();
QMargins m = frameMargins();
subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
@@ -882,6 +845,18 @@ QWaylandWindow *QWaylandWindow::transientParent() const
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{
+ if (e.type == QWaylandPointerEvent::Leave) {
+ if (mWindowDecoration) {
+ if (mMouseEventsInContentArea)
+ QWindowSystemInterface::handleLeaveEvent(window());
+ } else {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ }
+#if QT_CONFIG(cursor)
+ restoreMouseCursor(inputDevice);
+#endif
+ return;
+ }
if (mWindowDecoration) {
handleMouseEventWithDecoration(inputDevice, e);
@@ -890,11 +865,15 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
case QWaylandPointerEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), e.local, e.global);
break;
+ case QWaylandPointerEvent::Press:
+ case QWaylandPointerEvent::Release:
case QWaylandPointerEvent::Motion:
QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, e.local, e.global, e.buttons, e.modifiers);
break;
case QWaylandPointerEvent::Wheel:
- QWindowSystemInterface::handleWheelEvent(window(), e.timestamp, e.local, e.global, e.pixelDelta, e.angleDelta, e.modifiers);
+ QWindowSystemInterface::handleWheelEvent(window(), e.timestamp, e.local, e.global,
+ e.pixelDelta, e.angleDelta, e.modifiers,
+ e.phase, e.source, false);
break;
}
}
@@ -908,20 +887,6 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
#endif
}
-void QWaylandWindow::handleMouseLeave(QWaylandInputDevice *inputDevice)
-{
- if (mWindowDecoration) {
- if (mMouseEventsInContentArea) {
- QWindowSystemInterface::handleLeaveEvent(window());
- }
- } else {
- QWindowSystemInterface::handleLeaveEvent(window());
- }
-#if QT_CONFIG(cursor)
- restoreMouseCursor(inputDevice);
-#endif
-}
-
bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods)
{
if (!mWindowDecoration)
@@ -963,12 +928,18 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
case QWaylandPointerEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), localTranslated, globalTranslated);
break;
+ case QWaylandPointerEvent::Press:
+ case QWaylandPointerEvent::Release:
case QWaylandPointerEvent::Motion:
QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.modifiers);
break;
- case QWaylandPointerEvent::Wheel:
- QWindowSystemInterface::handleWheelEvent(window(), e.timestamp, localTranslated, globalTranslated, e.pixelDelta, e.angleDelta, e.modifiers);
+ case QWaylandPointerEvent::Wheel: {
+ QWindowSystemInterface::handleWheelEvent(window(), e.timestamp,
+ localTranslated, globalTranslated,
+ e.pixelDelta, e.angleDelta, e.modifiers,
+ e.phase, e.source, false);
break;
+ }
}
mMouseEventsInContentArea = true;
@@ -981,16 +952,21 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
}
}
-void QWaylandWindow::handleScreenChanged()
+void QWaylandWindow::handleScreensChanged()
{
QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
+
+ if (newScreen == mLastReportedScreen)
+ return;
+
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
+ mLastReportedScreen = newScreen;
int scale = newScreen->scale();
if (scale != mScale) {
mScale = scale;
- if (isInitialized() && mDisplay->compositorVersion() >= 3)
- set_buffer_scale(mScale);
+ if (mSurface && mDisplay->compositorVersion() >= 3)
+ mSurface->set_buffer_scale(mScale);
ensureSize();
}
}
@@ -1174,7 +1150,7 @@ void QWaylandWindow::handleUpdate()
QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection);
}
- mFrameCallback = frame();
+ mFrameCallback = mSurface->frame();
wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
mWaitingForFrameCallback = true;
mWaitingForUpdate = false;
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 9a1040288..471ace4cd 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -79,8 +79,9 @@ class QWaylandInputDevice;
class QWaylandScreen;
class QWaylandShmBackingStore;
class QWaylandPointerEvent;
+class QWaylandSurface;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow, public QtWayland::wl_surface
+class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow
{
Q_OBJECT
public:
@@ -108,12 +109,10 @@ public:
void applyConfigureWhenPossible(); //rename to possible?
- using QtWayland::wl_surface::attach;
void attach(QWaylandBuffer *buffer, int x, int y);
void attachOffset(QWaylandBuffer *buffer);
QPoint attachOffset() const;
- using QtWayland::wl_surface::damage;
void damage(const QRect &rect);
void safeCommit(QWaylandBuffer *buffer, const QRegion &damage);
@@ -128,6 +127,8 @@ public:
QSize surfaceSize() const;
QRect windowContentGeometry() const;
+ QWaylandSurface *waylandSurface() const { return mSurface.data(); }
+ ::wl_surface *wlSurface();
static QWaylandWindow *fromWlSurface(::wl_surface *surface);
QWaylandDisplay *display() const { return mDisplay; }
@@ -157,7 +158,6 @@ public:
QWaylandAbstractDecoration *decoration() const;
void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
- void handleMouseLeave(QWaylandInputDevice *inputDevice);
bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
Qt::TouchPointState state, Qt::KeyboardModifiers mods);
@@ -207,11 +207,8 @@ signals:
void wlSurfaceDestroyed();
protected:
- void surface_enter(struct ::wl_output *output) override;
- void surface_leave(struct ::wl_output *output) override;
-
- QVector<QWaylandScreen *> mScreens; //As seen by wl_surface.enter/leave events. Chronological order.
QWaylandDisplay *mDisplay = nullptr;
+ QScopedPointer<QWaylandSurface> mSurface;
QWaylandShellSurface *mShellSurface = nullptr;
QWaylandSubSurface *mSubSurfaceWindow = nullptr;
QVector<QWaylandSubSurface *> mChildren;
@@ -242,6 +239,7 @@ protected:
bool mSentInitialResize = false;
QPoint mOffset;
int mScale = 1;
+ QWaylandScreen *mLastReportedScreen = nullptr;
QIcon mWindowIcon;
@@ -253,9 +251,6 @@ protected:
QWaylandBuffer *mQueuedBuffer = nullptr;
QRegion mQueuedBufferDamage;
-private slots:
- void handleScreenRemoved(QScreen *qScreen);
-
private:
void setGeometry_helper(const QRect &rect);
void initWindow();
@@ -268,7 +263,7 @@ private:
QWaylandScreen *calculateScreenFromSurfaceEvents() const;
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
- void handleScreenChanged();
+ void handleScreensChanged();
bool mInResizeFromApplyConfigure = false;
QRect mLastExposeGeometry;
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 8dbe12ac1..9c44d0ec1 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -64,23 +64,28 @@ qtConfig(draganddrop) {
compositor_api/qwaylanddrag.cpp
}
-qtHaveModule(quick):qtConfig(opengl) {
+qtHaveModule(quick) {
DEFINES += QT_WAYLAND_COMPOSITOR_QUICK
SOURCES += \
compositor_api/qwaylandquickcompositor.cpp \
compositor_api/qwaylandquicksurface.cpp \
compositor_api/qwaylandquickoutput.cpp \
- compositor_api/qwaylandquickitem.cpp \
- compositor_api/qwaylandquickhardwarelayer.cpp
+ compositor_api/qwaylandquickitem.cpp
HEADERS += \
compositor_api/qwaylandquickcompositor.h \
compositor_api/qwaylandquicksurface.h \
compositor_api/qwaylandquickoutput.h \
compositor_api/qwaylandquickitem.h \
- compositor_api/qwaylandquickitem_p.h \
- compositor_api/qwaylandquickhardwarelayer_p.h
+ compositor_api/qwaylandquickitem_p.h
+
+ qtConfig(opengl) {
+ SOURCES += \
+ compositor_api/qwaylandquickhardwarelayer.cpp
+ HEADERS += \
+ compositor_api/qwaylandquickhardwarelayer_p.h
+ }
QT += qml qml-private quick quick-private
}
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 530cf8ed6..e2d617c37 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -200,8 +200,8 @@ void QWaylandCompositorPrivate::init()
buffer_manager = new QtWayland::BufferManager(q);
wl_display_init_shm(display);
- QVector<wl_shm_format> formats = QWaylandSharedMemoryFormatHelper::supportedWaylandFormats();
- foreach (wl_shm_format format, formats)
+ const QVector<wl_shm_format> formats = QWaylandSharedMemoryFormatHelper::supportedWaylandFormats();
+ for (wl_shm_format format : formats)
wl_display_add_shm_format(display, format);
if (!socket_name.isEmpty()) {
@@ -234,7 +234,7 @@ void QWaylandCompositorPrivate::init()
initialized = true;
- Q_FOREACH (QPointer<QObject> object, polish_objects) {
+ for (const QPointer<QObject> &object : qExchange(polish_objects, {})) {
if (object) {
QEvent polishEvent(QEvent::Polish);
QCoreApplication::sendEvent(object.data(), &polishEvent);
@@ -302,7 +302,7 @@ void QWaylandCompositorPrivate::addPolishObject(QObject *object)
if (initialized) {
QCoreApplication::postEvent(object, new QEvent(QEvent::Polish));
} else {
- polish_objects.append(object);
+ polish_objects.push_back(object);
}
}
@@ -706,7 +706,7 @@ QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* c
{
Q_D(const QWaylandCompositor);
QList<QWaylandSurface *> surfs;
- foreach (QWaylandSurface *surface, d->all_surfaces) {
+ for (QWaylandSurface *surface : d->all_surfaces) {
if (surface->client() == client)
surfs.append(surface);
}
@@ -728,7 +728,7 @@ QList<QWaylandSurface *> QWaylandCompositor::surfaces() const
QWaylandOutput *QWaylandCompositor::outputFor(QWindow *window) const
{
Q_D(const QWaylandCompositor);
- foreach (QWaylandOutput *output, d->outputs) {
+ for (QWaylandOutput *output : d->outputs) {
if (output->window() == window)
return output;
}
diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h
index 2c9624216..2437533dd 100644
--- a/src/compositor/compositor_api/qwaylandcompositor_p.h
+++ b/src/compositor/compositor_api/qwaylandcompositor_p.h
@@ -60,6 +60,8 @@
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
+#include <vector>
+
#if QT_CONFIG(xkbcommon)
#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#endif
@@ -175,7 +177,7 @@ protected:
bool retainSelection = false;
bool preInitialized = false;
bool initialized = false;
- QList<QPointer<QObject> > polish_objects;
+ std::vector<QPointer<QObject> > polish_objects;
#if QT_CONFIG(xkbcommon)
QXkbCommon::ScopedXKBContext mXkbContext;
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp
index 2302c0b6a..c5ec008d7 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.cpp
+++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp
@@ -256,7 +256,8 @@ void QWaylandKeyboardPrivate::maybeUpdateKeymap()
return;
createXKBKeymap();
- foreach (Resource *res, resourceMap()) {
+ const auto resMap = resourceMap();
+ for (Resource *res : resMap) {
send_keymap(res->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymap_fd, keymap_size);
}
@@ -365,6 +366,13 @@ void QWaylandKeyboardPrivate::createXKBKeymap()
QByteArray variant = keymap->variant().toLocal8Bit();
QByteArray options = keymap->options().toLocal8Bit();
+ if (!layout.isEmpty() && !layout.contains("us")) {
+ // This is needed for shortucts like "ctrl+c" to function even when
+ // user has selected only non-latin keyboard layouts, e.g. 'ru'.
+ layout.append(",us");
+ variant.append(",");
+ }
+
struct xkb_rule_names rule_names = {
rules.constData(),
model.constData(),
@@ -386,7 +394,8 @@ void QWaylandKeyboardPrivate::createXKBKeymap()
void QWaylandKeyboardPrivate::sendRepeatInfo()
{
- Q_FOREACH (Resource *resource, resourceMap()) {
+ const auto resMap = resourceMap();
+ for (Resource *resource : resMap) {
if (resource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
send_repeat_info(resource->handle, repeatRate, repeatDelay);
}
diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp
index 006edbe6a..601f692af 100644
--- a/src/compositor/compositor_api/qwaylandoutput.cpp
+++ b/src/compositor/compositor_api/qwaylandoutput.cpp
@@ -48,6 +48,7 @@
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <QtWaylandCompositor/private/qwaylandview_p.h>
#include <QtWaylandCompositor/private/qwaylandutils_p.h>
+#include <QtWaylandCompositor/private/qwaylandxdgoutputv1_p.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QtMath>
@@ -162,6 +163,9 @@ void QWaylandOutputPrivate::sendGeometryInfo()
if (resource->version() >= 2)
send_done(resource->handle);
}
+
+ if (xdgOutput)
+ QWaylandXdgOutputV1Private::get(xdgOutput)->sendDone();
}
void QWaylandOutputPrivate::sendMode(const Resource *resource, const QWaylandOutputMode &mode)
@@ -185,6 +189,9 @@ void QWaylandOutputPrivate::sendModesInfo()
if (resource->version() >= 2)
send_done(resource->handle);
}
+
+ if (xdgOutput)
+ QWaylandXdgOutputV1Private::get(xdgOutput)->sendDone();
}
void QWaylandOutputPrivate::handleWindowPixelSizeChanged()
@@ -831,7 +838,8 @@ void QWaylandOutput::setScaleFactor(int scale)
d->scaleFactor = scale;
- Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) {
+ const auto resMap = d->resourceMap();
+ for (QWaylandOutputPrivate::Resource *resource : resMap) {
if (resource->version() >= 2) {
d->send_scale(resource->handle, scale);
d->send_done(resource->handle);
@@ -839,6 +847,9 @@ void QWaylandOutput::setScaleFactor(int scale)
}
Q_EMIT scaleFactorChanged();
+
+ if (d->xdgOutput)
+ QWaylandXdgOutputV1Private::get(d->xdgOutput)->sendDone();
}
/*!
diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h
index 4badd3797..58188ac38 100644
--- a/src/compositor/compositor_api/qwaylandoutput_p.h
+++ b/src/compositor/compositor_api/qwaylandoutput_p.h
@@ -57,6 +57,7 @@
#include <QtWaylandCompositor/QWaylandOutput>
#include <QtWaylandCompositor/QWaylandClient>
#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandXdgOutputV1>
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
@@ -110,6 +111,8 @@ public:
void handleWindowPixelSizeChanged();
+ QPointer<QWaylandXdgOutputV1> xdgOutput;
+
protected:
void output_bind_resource(Resource *resource) override;
@@ -137,6 +140,8 @@ private:
Q_DECLARE_PUBLIC(QWaylandOutput)
Q_DISABLE_COPY(QWaylandOutputPrivate)
+
+ friend class QWaylandXdgOutputManagerV1Private;
};
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
index 14b592efb..1b3f93e5c 100644
--- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
@@ -128,6 +128,7 @@ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const
return;
}
+#if QT_CONFIG(opengl)
QWaylandQuickOutput *output = static_cast<QWaylandQuickOutput *>(defaultOutput());
if (!output) {
emit grabber->failed(QWaylandSurfaceGrabber::RendererNotReady);
@@ -169,6 +170,9 @@ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const
state->grabber = grabber;
state->buffer = buffer;
static_cast<QQuickWindow *>(output->window())->scheduleRenderJob(state, QQuickWindow::NoStage);
+#else
+ emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 62a89057a..ee15a0871 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -73,6 +73,7 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(opengl)
static const struct {
const char * const vertexShaderSourceFile;
const char * const fragmentShaderSourceFile;
@@ -259,6 +260,7 @@ void QWaylandBufferMaterial::ensureTextures(int count)
m_textures << nullptr;
}
}
+#endif // QT_CONFIG(opengl)
QMutex *QWaylandQuickItemPrivate::mutex = nullptr;
@@ -284,10 +286,12 @@ public:
if (m_ref.hasBuffer()) {
if (buffer.isSharedMemory()) {
m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image());
- if (m_sgTex) {
+#if QT_CONFIG(opengl)
+ if (m_sgTex)
m_sgTex->bind();
- }
+#endif
} else {
+#if QT_CONFIG(opengl)
QQuickWindow::CreateTextureOptions opt;
QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
if (surface && surface->useTextureAlpha()) {
@@ -297,6 +301,9 @@ public:
auto texture = buffer.toOpenGLTexture();
auto size = surface->bufferSize();
m_sgTex = surfaceItem->window()->createTextureFromId(texture->textureId(), size, opt);
+#else
+ qCWarning(qLcWaylandCompositor) << "Without OpenGL support only shared memory textures are supported";
+#endif
}
}
emit textureChanged();
@@ -603,13 +610,17 @@ void QWaylandQuickItem::wheelEvent(QWheelEvent *event)
{
Q_D(QWaylandQuickItem);
if (d->shouldSendInputEvents()) {
- if (!inputRegionContains(event->pos())) {
+ if (!inputRegionContains(event->position())) {
event->ignore();
return;
}
QWaylandSeat *seat = compositor()->seatFor(event);
- seat->sendMouseWheelEvent(event->orientation(), event->delta());
+ // TODO: fix this to send a single event, when diagonal scrolling is supported
+ if (event->angleDelta().x() != 0)
+ seat->sendMouseWheelEvent(Qt::Horizontal, event->angleDelta().x());
+ if (event->angleDelta().y() != 0)
+ seat->sendMouseWheelEvent(Qt::Vertical, event->angleDelta().y());
} else {
event->ignore();
}
@@ -1327,7 +1338,11 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
const QRectF rect = invertY ? QRectF(0, height(), width(), -height())
: QRectF(0, 0, width(), height());
- if (ref.isSharedMemory() || bufferTypes[ref.bufferFormatEgl()].canProvideTexture) {
+ if (ref.isSharedMemory()
+#if QT_CONFIG(opengl)
+ || bufferTypes[ref.bufferFormatEgl()].canProvideTexture
+#endif
+ ) {
// This case could covered by the more general path below, but this is more efficient (especially when using ShaderEffect items).
QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
@@ -1353,45 +1368,48 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
return node;
- } else {
- Q_ASSERT(!d->provider);
+ }
- QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode);
+#if QT_CONFIG(opengl)
+ Q_ASSERT(!d->provider);
- if (!node) {
- node = new QSGGeometryNode;
- d->newTexture = true;
- }
+ QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode);
- QSGGeometry *geometry = node->geometry();
- QWaylandBufferMaterial *material = static_cast<QWaylandBufferMaterial *>(node->material());
+ if (!node) {
+ node = new QSGGeometryNode;
+ d->newTexture = true;
+ }
- if (!geometry)
- geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
+ QSGGeometry *geometry = node->geometry();
+ QWaylandBufferMaterial *material = static_cast<QWaylandBufferMaterial *>(node->material());
- if (!material)
- material = new QWaylandBufferMaterial(ref.bufferFormatEgl());
+ if (!geometry)
+ geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
- if (d->newTexture) {
- d->newTexture = false;
- for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++)
- if (auto texture = ref.toOpenGLTexture(plane))
- material->setTextureForPlane(plane, texture);
- material->bind();
- }
+ if (!material)
+ material = new QWaylandBufferMaterial(ref.bufferFormatEgl());
- QSGGeometry::updateTexturedRectGeometry(geometry, rect, QRectF(0, 0, 1, 1));
+ if (d->newTexture) {
+ d->newTexture = false;
+ for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++)
+ if (auto texture = ref.toOpenGLTexture(plane))
+ material->setTextureForPlane(plane, texture);
+ material->bind();
+ }
- node->setGeometry(geometry);
- node->setFlag(QSGNode::OwnsGeometry, true);
+ QSGGeometry::updateTexturedRectGeometry(geometry, rect, QRectF(0, 0, 1, 1));
- node->setMaterial(material);
- node->setFlag(QSGNode::OwnsMaterial, true);
+ node->setGeometry(geometry);
+ node->setFlag(QSGNode::OwnsGeometry, true);
- return node;
- }
+ node->setMaterial(material);
+ node->setFlag(QSGNode::OwnsMaterial, true);
- Q_UNREACHABLE();
+ return node;
+#else
+ qCWarning(qLcWaylandCompositor) << "Without OpenGL support only shared memory textures are supported";
+ return nullptr;
+#endif // QT_CONFIG(opengl)
}
void QWaylandQuickItem::setTouchEventsEnabled(bool enabled)
diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h
index 3d710d71b..2ec02ca6d 100644
--- a/src/compositor/compositor_api/qwaylandquickitem_p.h
+++ b/src/compositor/compositor_api/qwaylandquickitem_p.h
@@ -64,6 +64,7 @@ class QWaylandSurfaceTextureProvider;
class QMutex;
class QOpenGLTexture;
+#if QT_CONFIG(opengl)
class QWaylandBufferMaterialShader : public QSGMaterialShader
{
public:
@@ -102,6 +103,7 @@ private:
const QWaylandBufferRef::BufferFormatEgl m_format;
QVarLengthArray<QOpenGLTexture*, 3> m_textures;
};
+#endif // QT_CONFIG(opengl)
class QWaylandQuickItemPrivate : public QQuickItemPrivate
{
diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp
index bc5e1d8b2..0a6248d11 100644
--- a/src/compositor/compositor_api/qwaylandseat.cpp
+++ b/src/compositor/compositor_api/qwaylandseat.cpp
@@ -289,6 +289,10 @@ void QWaylandSeat::sendKeyReleaseEvent(uint code)
* Sends a touch point event to the \a surface on a touch device with the given
* \a id, \a point and \a state.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
+ * as it might lead to conflicting touch ids.
+ *
* Returns the serial for the touch up or touch down event.
*/
uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state)
@@ -310,6 +314,10 @@ uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const Q
* \note You need to send a touch frame event when you are done sending touch
* events.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l WaylandQuickItem::touchEventsEnabled, as it might lead to
+ * conflicting touch ids.
+ *
* Returns the serial for the touch down event.
*/
@@ -320,6 +328,10 @@ uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const Q
* \note You need to send a touch frame event when you are done sending touch
* events.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
+ * as it might lead to conflicting touch ids.
+ *
* Returns the serial for the touch down event.
*/
uint QWaylandSeat::sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position)
@@ -336,6 +348,10 @@ uint QWaylandSeat::sendTouchPointPressed(QWaylandSurface *surface, int id, const
* \note You need to send a touch frame event when you are done sending touch
* events.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l WaylandQuickItem::touchEventsEnabled, as it might lead to
+ * conflicting touch ids.
+ *
* Returns the serial for the touch up event.
*/
@@ -346,6 +362,10 @@ uint QWaylandSeat::sendTouchPointPressed(QWaylandSurface *surface, int id, const
* \note You need to send a touch frame event when you are done sending touch
* events.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
+ * as it might lead to conflicting touch ids.
+ *
* Returns the serial for the touch up event.
*/
uint QWaylandSeat::sendTouchPointReleased(QWaylandSurface *surface, int id, const QPointF &position)
@@ -362,6 +382,10 @@ uint QWaylandSeat::sendTouchPointReleased(QWaylandSurface *surface, int id, cons
* \note You need to send a touch frame event when you are done sending touch
* events.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l WaylandQuickItem::touchEventsEnabled, as it might lead to
+ * conflicting touch ids.
+ *
* Returns the serial for the touch motion event.
*/
@@ -372,6 +396,10 @@ uint QWaylandSeat::sendTouchPointReleased(QWaylandSurface *surface, int id, cons
* \note You need to send a touch frame event when you are done sending touch
* events.
*
+ * \warning This API should not be used in combination with forwarding of touch
+ * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
+ * as it might lead to conflicting touch ids.
+ *
* Returns the serial for the touch motion event.
*/
uint QWaylandSeat::sendTouchPointMoved(QWaylandSurface *surface, int id, const QPointF &position)
@@ -415,6 +443,11 @@ void QWaylandSeat::sendTouchCancelEvent(QWaylandClient *client)
/*!
* Sends the \a event to the specified \a surface on the touch device.
+ *
+ * \warning This API will automatically map \l QTouchEvent::TouchPoint::id to a
+ * sequential id before sending it to the client. It should therefore not be
+ * used in combination with the other API using explicit ids, as collisions
+ * might occur.
*/
void QWaylandSeat::sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event)
{
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index c79787e6e..2265b41c0 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -136,9 +136,9 @@ QWaylandSurfacePrivate::~QWaylandSurfacePrivate()
bufferRef = QWaylandBufferRef();
- foreach (QtWayland::FrameCallback *c, pendingFrameCallbacks)
+ for (QtWayland::FrameCallback *c : qAsConst(pendingFrameCallbacks))
c->destroy();
- foreach (QtWayland::FrameCallback *c, frameCallbacks)
+ for (QtWayland::FrameCallback *c : qAsConst(frameCallbacks))
c->destroy();
}
@@ -151,7 +151,8 @@ void QWaylandSurfacePrivate::removeFrameCallback(QtWayland::FrameCallback *callb
void QWaylandSurfacePrivate::notifyViewsAboutDestruction()
{
Q_Q(QWaylandSurface);
- foreach (QWaylandView *view, views) {
+ const auto viewsCopy = views; // Views will be removed from the list when marked as destroyed
+ for (QWaylandView *view : viewsCopy) {
QWaylandViewPrivate::get(view)->markSurfaceAsDestroyed(q);
}
if (hasContent) {
@@ -673,7 +674,7 @@ QWaylandCompositor *QWaylandSurface::compositor() const
void QWaylandSurface::frameStarted()
{
Q_D(QWaylandSurface);
- foreach (QtWayland::FrameCallback *c, d->frameCallbacks)
+ for (QtWayland::FrameCallback *c : qAsConst(d->frameCallbacks))
c->canSend = true;
}
@@ -763,6 +764,29 @@ bool QWaylandSurface::isCursorSurface() const
return d->isCursorSurface;
}
+/*!
+ * \qmlproperty bool QtWaylandCompositor::WaylandSurface::inhibitsIdle
+ *
+ * This property holds whether this surface is intended to inhibit the idle
+ * behavior of the compositor such as screen blanking, locking and screen saving.
+ *
+ * \sa IdleInhibitManagerV1
+ */
+
+/*!
+ * \property QWaylandSurface::inhibitsIdle
+ *
+ * This property holds whether this surface is intended to inhibit the idle
+ * behavior of the compositor such as screen blanking, locking and screen saving.
+ *
+ * \sa QWaylandIdleInhibitManagerV1
+ */
+bool QWaylandSurface::inhibitsIdle() const
+{
+ Q_D(const QWaylandSurface);
+ return !d->idleInhibitors.isEmpty();
+}
+
#if QT_CONFIG(im)
QWaylandInputMethodControl *QWaylandSurface::inputMethodControl() const
{
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index 667f911c3..f8cdc4434 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -92,6 +92,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSurface : public QWaylandObject
Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged)
Q_PROPERTY(bool hasContent READ hasContent NOTIFY hasContentChanged)
Q_PROPERTY(bool cursorSurface READ isCursorSurface WRITE markAsCursorSurface NOTIFY cursorSurfaceChanged)
+ Q_PROPERTY(bool inhibitsIdle READ inhibitsIdle NOTIFY inhibitsIdleChanged REVISION 14)
public:
enum Origin {
@@ -148,6 +149,8 @@ public:
void markAsCursorSurface(bool cursorSurface);
bool isCursorSurface() const;
+ bool inhibitsIdle() const;
+
#if QT_CONFIG(im)
QWaylandInputMethodControl *inputMethodControl() const;
#endif
@@ -181,6 +184,7 @@ Q_SIGNALS:
void subsurfacePlaceBelow(QWaylandSurface *sibling);
void dragStarted(QWaylandDrag *drag);
void cursorSurfaceChanged();
+ void inhibitsIdleChanged();
void configure(bool hasBuffer);
void redraw();
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 1637d8704..97cb19d9b 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -74,6 +74,7 @@
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
#include <QtWaylandCompositor/private/qwaylandviewporter_p.h>
+#include <QtWaylandCompositor/private/qwaylandidleinhibitv1_p.h>
QT_BEGIN_NAMESPACE
@@ -167,6 +168,8 @@ public: //member variables
QList<QPointer<QWaylandSurface>> subsurfaceChildren;
+ QVector<QWaylandIdleInhibitManagerV1Private::Inhibitor *> idleInhibitors;
+
QRegion inputRegion;
QRegion opaqueRegion;
diff --git a/src/compositor/compositor_api/qwaylandview.cpp b/src/compositor/compositor_api/qwaylandview.cpp
index 1a6bf1a64..12889bdfa 100644
--- a/src/compositor/compositor_api/qwaylandview.cpp
+++ b/src/compositor/compositor_api/qwaylandview.cpp
@@ -246,7 +246,8 @@ bool QWaylandView::advance()
return false;
if (d->surface && d->surface->primaryView() == this) {
- Q_FOREACH (QWaylandView *view, d->surface->views()) {
+ const auto views = d->surface->views();
+ for (QWaylandView *view : views) {
if (view != this && view->allowDiscardFrontBuffer() && view->d_func()->currentBuffer == d->currentBuffer)
view->discardCurrentBuffer();
}
diff --git a/src/compositor/configure.json b/src/compositor/configure.json
index c26a416e0..db80543f7 100644
--- a/src/compositor/configure.json
+++ b/src/compositor/configure.json
@@ -144,14 +144,9 @@
"condition": "features.wayland-server && features.opengl && features.egl && tests.dmabuf-client-buffer",
"output": [ "privateFeature" ]
},
- "wayland-compositor-texture-sharing-experimental" : {
- "label": "Texture sharing (experimental)",
- "autoDetect": "false",
- "output": [ "privateFeature" ]
- },
"wayland-vulkan-server-buffer": {
"label": "Vulkan-based server buffer integration",
- "condition": "features.wayland-server && features.opengl && features.egl && tests.vulkan-server-buffer && features.wayland-compositor-texture-sharing-experimental",
+ "condition": "features.wayland-server && features.opengl && features.egl && tests.vulkan-server-buffer",
"output": [ "privateFeature" ]
},
"wayland-shm-emulation-server-buffer": {
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri
index d8f0069de..61ab043ea 100644
--- a/src/compositor/extensions/extensions.pri
+++ b/src/compositor/extensions/extensions.pri
@@ -14,7 +14,9 @@ WAYLANDSERVERSOURCES += \
../3rdparty/protocol/xdg-shell-unstable-v6.xml \
../3rdparty/protocol/xdg-shell.xml \
../3rdparty/protocol/xdg-decoration-unstable-v1.xml \
+ ../3rdparty/protocol/xdg-output-unstable-v1.xml \
../3rdparty/protocol/ivi-application.xml \
+ ../3rdparty/protocol/idle-inhibit-unstable-v1.xml \
HEADERS += \
extensions/qwlqttouch_p.h \
@@ -41,7 +43,11 @@ HEADERS += \
extensions/qwaylandxdgshell_p.h \
extensions/qwaylandxdgdecorationv1.h \
extensions/qwaylandxdgdecorationv1_p.h \
+ extensions/qwaylandxdgoutputv1.h \
+ extensions/qwaylandxdgoutputv1_p.h \
extensions/qwaylandshellsurface.h \
+ extensions/qwaylandidleinhibitv1.h \
+ extensions/qwaylandidleinhibitv1_p.h \
extensions/qwaylandiviapplication.h \
extensions/qwaylandiviapplication_p.h \
extensions/qwaylandivisurface.h \
@@ -61,32 +67,43 @@ SOURCES += \
extensions/qwaylandxdgshellv6.cpp \
extensions/qwaylandxdgshell.cpp \
extensions/qwaylandxdgdecorationv1.cpp \
+ extensions/qwaylandxdgoutputv1.cpp \
extensions/qwaylandshellsurface.cpp \
+ extensions/qwaylandidleinhibitv1.cpp \
extensions/qwaylandiviapplication.cpp \
extensions/qwaylandivisurface.cpp \
-qtHaveModule(quick):contains(QT_CONFIG, opengl) {
+qtHaveModule(quick) {
HEADERS += \
+ extensions/qwaylandquickshellintegration.h \
extensions/qwaylandquickshellsurfaceitem.h \
extensions/qwaylandquickshellsurfaceitem_p.h \
extensions/qwaylandivisurfaceintegration_p.h \
extensions/qwaylandwlshellintegration_p.h \
+ extensions/qwaylandquickxdgoutputv1.h \
extensions/qwaylandxdgshellv5integration_p.h \
extensions/qwaylandxdgshellv6integration_p.h \
- extensions/qwaylandxdgshellintegration_p.h
+ extensions/qwaylandxdgshellintegration_p.h \
SOURCES += \
+ extensions/qwaylandquickshellintegration.cpp \
extensions/qwaylandquickshellsurfaceitem.cpp \
extensions/qwaylandivisurfaceintegration.cpp \
extensions/qwaylandwlshellintegration.cpp \
+ extensions/qwaylandquickxdgoutputv1.cpp \
extensions/qwaylandxdgshellv5integration.cpp \
extensions/qwaylandxdgshellv6integration.cpp \
- extensions/qwaylandxdgshellintegration.cpp
+ extensions/qwaylandxdgshellintegration.cpp \
- qtConfig(wayland-compositor-texture-sharing-experimental) {
- HEADERS += extensions/qwltexturesharingextension_p.h
- SOURCES += extensions/qwltexturesharingextension.cpp
- WAYLANDSERVERSOURCES += ../extensions/qt-texture-sharing-unstable-v1.xml
+ qtConfig(opengl) {
+ WAYLANDSERVERSOURCES += \
+ ../extensions/qt-texture-sharing-unstable-v1.xml
+
+ HEADERS += \
+ extensions/qwltexturesharingextension_p.h
+
+ SOURCES += \
+ extensions/qwltexturesharingextension.cpp
}
}
diff --git a/src/compositor/extensions/qwaylandidleinhibitv1.cpp b/src/compositor/extensions/qwaylandidleinhibitv1.cpp
new file mode 100644
index 000000000..b97f58130
--- /dev/null
+++ b/src/compositor/extensions/qwaylandidleinhibitv1.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
+
+#include "qwaylandidleinhibitv1_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWaylandIdleInhibitManagerV1
+ \inmodule QtWaylandCompositor
+ \since 5.14
+ \brief Provides an extension that allows to inhibit the idle behavior of the compositor
+ \sa QWaylandSurface::inhibitsIdle
+
+ The QWaylandIdleInhibitV1 extension provides a way for a client to inhibit the idle behavior of
+ the compositor when a specific surface is visually relevant to the user.
+
+ QWaylandIdleInhibitManagerV1 corresponds to the Wayland interface, \c zwp_idle_inhibit_manager_v1.
+
+ Inhibited surfaces have the QWaylandSurface::inhibitsIdle property set to \c true.
+*/
+
+/*!
+ \qmltype IdleInhibitManagerV1
+ \inqmlmodule QtWayland.Compositor
+ \since 5.14
+ \brief Provides an extension that allows to inhibit the idle behavior of the compositor
+ \sa WaylandSurface::inhibitsIdle
+
+ The IdleInhibitManagerV1 extension provides a way for a client to inhibit the idle behavior of
+ the compositor when a specific surface is visually relevant to the user.
+
+ IdleInhibitManagerV1 corresponds to the Wayland interface, \c zwp_idle_inhibit_manager_v1.
+
+ To provide the functionality of the extension in a compositor, create an instance of the
+ IdleInhibitManagerV1 component and add it to the list of extensions supported by the compositor:
+
+ \qml \QtMinorVersion
+ import QtWayland.Compositor 1.\1
+
+ WaylandCompositor {
+ IdleInhibitManagerV1 {
+ // ...
+ }
+ }
+ \endqml
+
+ Inhibited surfaces have the WaylandSurface::inhibitsIdle property set to \c true.
+*/
+
+/*!
+ Constructs a QWaylandIdleInhibitManagerV1 object.
+*/
+QWaylandIdleInhibitManagerV1::QWaylandIdleInhibitManagerV1()
+ : QWaylandCompositorExtensionTemplate<QWaylandIdleInhibitManagerV1>(*new QWaylandIdleInhibitManagerV1Private())
+{
+}
+
+/*!
+ Constructs a QWaylandIdleInhibitManagerV1 object for the provided \a compositor.
+*/
+QWaylandIdleInhibitManagerV1::QWaylandIdleInhibitManagerV1(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate<QWaylandIdleInhibitManagerV1>(compositor, *new QWaylandIdleInhibitManagerV1Private())
+{
+}
+
+/*!
+ Destructs a QWaylandIdleInhibitManagerV1 object.
+*/
+QWaylandIdleInhibitManagerV1::~QWaylandIdleInhibitManagerV1() = default;
+
+/*!
+ Initializes the extension.
+*/
+void QWaylandIdleInhibitManagerV1::initialize()
+{
+ Q_D(QWaylandIdleInhibitManagerV1);
+
+ QWaylandCompositorExtensionTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qCWarning(qLcWaylandCompositor) << "Failed to find QWaylandCompositor when initializing QWaylandIdleInhibitManagerV1";
+ return;
+ }
+ d->init(compositor->display(), d->interfaceVersion());
+}
+
+/*!
+ Returns the Wayland interface for the QWaylandIdleInhibitManagerV1.
+*/
+const wl_interface *QWaylandIdleInhibitManagerV1::interface()
+{
+ return QWaylandIdleInhibitManagerV1Private::interface();
+}
+
+
+void QWaylandIdleInhibitManagerV1Private::zwp_idle_inhibit_manager_v1_create_inhibitor(Resource *resource, uint id, wl_resource *surfaceResource)
+{
+ auto *surface = QWaylandSurface::fromResource(surfaceResource);
+ if (!surface) {
+ qCWarning(qLcWaylandCompositor) << "Couldn't find surface requested for creating an inhibitor";
+ wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "invalid wl_surface@%d", wl_resource_get_id(surfaceResource));
+ return;
+ }
+
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(surface);
+ if (!surfacePrivate) {
+ wl_resource_post_no_memory(resource->handle);
+ return;
+ }
+
+ auto *inhibitor = new Inhibitor(surface, resource->client(), id, resource->version());
+ if (!inhibitor) {
+ wl_resource_post_no_memory(resource->handle);
+ return;
+ }
+ surfacePrivate->idleInhibitors.append(inhibitor);
+
+ if (surfacePrivate->idleInhibitors.size() == 1)
+ Q_EMIT surface->inhibitsIdleChanged();
+}
+
+
+QWaylandIdleInhibitManagerV1Private::Inhibitor::Inhibitor(QWaylandSurface *surface,
+ wl_client *client,
+ quint32 id, quint32 version)
+ : QtWaylandServer::zwp_idle_inhibitor_v1(client, id, qMin<quint32>(version, interfaceVersion()))
+ , m_surface(surface)
+{
+ Q_ASSERT(surface);
+}
+
+void QWaylandIdleInhibitManagerV1Private::Inhibitor::zwp_idle_inhibitor_v1_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource);
+ delete this;
+}
+
+void QWaylandIdleInhibitManagerV1Private::Inhibitor::zwp_idle_inhibitor_v1_destroy(Resource *resource)
+{
+ if (m_surface) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface.data());
+ Q_ASSERT(surfacePrivate->idleInhibitors.contains(this));
+ surfacePrivate->idleInhibitors.removeOne(this);
+
+ if (surfacePrivate->idleInhibitors.isEmpty())
+ Q_EMIT m_surface.data()->inhibitsIdleChanged();
+ }
+
+ wl_resource_destroy(resource->handle);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandidleinhibitv1.h b/src/compositor/extensions/qwaylandidleinhibitv1.h
new file mode 100644
index 000000000..53c09d084
--- /dev/null
+++ b/src/compositor/extensions/qwaylandidleinhibitv1.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 QWAYLANDIDLEINHIBITV1_H
+#define QWAYLANDIDLEINHIBITV1_H
+
+#include <QtWaylandCompositor/QWaylandCompositorExtension>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandIdleInhibitManagerV1Private;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIdleInhibitManagerV1 : public QWaylandCompositorExtensionTemplate<QWaylandIdleInhibitManagerV1>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandIdleInhibitManagerV1)
+public:
+ QWaylandIdleInhibitManagerV1();
+ explicit QWaylandIdleInhibitManagerV1(QWaylandCompositor *compositor);
+ ~QWaylandIdleInhibitManagerV1();
+
+ void initialize() override;
+
+ static const struct wl_interface *interface();
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDIDLEINHIBITV1_H
diff --git a/src/compositor/extensions/qwaylandidleinhibitv1_p.h b/src/compositor/extensions/qwaylandidleinhibitv1_p.h
new file mode 100644
index 000000000..380551804
--- /dev/null
+++ b/src/compositor/extensions/qwaylandidleinhibitv1_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 QWAYLANDIDLEINHIBITV1_P_H
+#define QWAYLANDIDLEINHIBITV1_P_H
+
+#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1>
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-idle-inhibit-unstable-v1.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 Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIdleInhibitManagerV1Private
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::zwp_idle_inhibit_manager_v1
+{
+ Q_DECLARE_PUBLIC(QWaylandIdleInhibitManagerV1)
+public:
+ explicit QWaylandIdleInhibitManagerV1Private() = default;
+
+ class Q_WAYLAND_COMPOSITOR_EXPORT Inhibitor
+ : public QtWaylandServer::zwp_idle_inhibitor_v1
+ {
+ public:
+ explicit Inhibitor(QWaylandSurface *surface, wl_client *client, quint32 id, quint32 version);
+
+ protected:
+ void zwp_idle_inhibitor_v1_destroy_resource(Resource *resource) override;
+ void zwp_idle_inhibitor_v1_destroy(Resource *resource) override;
+
+ private:
+ QPointer<QWaylandSurface> m_surface;
+ };
+
+ static QWaylandIdleInhibitManagerV1Private *get(QWaylandIdleInhibitManagerV1 *manager) { return manager ? manager->d_func() : nullptr; }
+
+protected:
+ void zwp_idle_inhibit_manager_v1_create_inhibitor(Resource *resource, uint32_t id, wl_resource *surfaceResource) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDIDLEINHIBITV1_P_H
diff --git a/src/compositor/extensions/qwaylandqtwindowmanager.cpp b/src/compositor/extensions/qwaylandqtwindowmanager.cpp
index 86678b2e6..c3cf3488b 100644
--- a/src/compositor/extensions/qwaylandqtwindowmanager.cpp
+++ b/src/compositor/extensions/qwaylandqtwindowmanager.cpp
@@ -109,7 +109,8 @@ void QWaylandQtWindowManager::setShowIsFullScreen(bool value)
return;
d->showIsFullScreen = value;
- Q_FOREACH (QWaylandQtWindowManagerPrivate::Resource *resource, d->resourceMap().values()) {
+ const auto resMap = d->resourceMap();
+ for (QWaylandQtWindowManagerPrivate::Resource *resource : resMap) {
d->send_hints(resource->handle, static_cast<int32_t>(d->showIsFullScreen));
}
Q_EMIT showIsFullScreenChanged();
diff --git a/src/compositor/extensions/qwaylandquickshellintegration.cpp b/src/compositor/extensions/qwaylandquickshellintegration.cpp
new file mode 100644
index 000000000..961b7b111
--- /dev/null
+++ b/src/compositor/extensions/qwaylandquickshellintegration.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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$
+**
+****************************************************************************/
+
+#include "qwaylandquickshellintegration.h"
+
+/*!
+ * \class QWaylandQuickShellIntegration
+ * \inmodule QtWaylandCompositor
+ * \since 5.14
+ * \brief Provides support for shell surface integration with QtQuick
+ *
+ * Shell surface implementations should inherit from this class in order to provide
+ * an integration between the shell surface and QtQuick.
+ *
+ * \sa QWaylandShellSurface
+ * \sa QWaylandShellSurfaceItem
+ */
+
+QWaylandQuickShellIntegration::QWaylandQuickShellIntegration(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive touch events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::touchEvent()
+ */
+bool QWaylandQuickShellIntegration::touchEvent(QTouchEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive hover-enter events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Hover events are only provided if \l {QWaylandQuickShellSurfaceItem::} {acceptHoverEvents()}
+ * is \a true.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::hoverEnterEvent()
+ */
+bool QWaylandQuickShellIntegration::hoverEnterEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive hover-leave events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Hover events are only provided if \l {QWaylandQuickShellSurfaceItem::} {acceptHoverEvents()}
+ * is \a true.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::hoverLeaveEvent()
+ */
+bool QWaylandQuickShellIntegration::hoverLeaveEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive hover-move events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Hover events are only provided if \l {QWaylandQuickShellSurfaceItem::} {acceptHoverEvents()}
+ * is \a true.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::hoverMoveEvent()
+ */
+bool QWaylandQuickShellIntegration::hoverMoveEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive key press events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::keyPressEvent()
+ */
+bool QWaylandQuickShellIntegration::keyPressEvent(QKeyEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive key release events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::keyReleaseEvent()
+ */
+bool QWaylandQuickShellIntegration::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive mouse double click events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::mouseDoubleClickEvent()
+ */
+bool QWaylandQuickShellIntegration::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive mouse move events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::mouseMoveEvent()
+ */
+bool QWaylandQuickShellIntegration::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive mouse press events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::mousePressEvent()
+ */
+bool QWaylandQuickShellIntegration::mousePressEvent(QMouseEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*!
+ * This method can be reimplemented in a subclass to receive mouse release events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::mouseReleaseEvent()
+ */
+bool QWaylandQuickShellIntegration::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+#if QT_CONFIG(wheelevent)
+/*!
+ * This method can be reimplemented in a subclass to receive wheel events
+ * for a shell surface.
+ *
+ * The event information is provided by the \a event parameter.
+ *
+ * Return \a false if you want QWaylandQuickShellSurfaceItem to handle
+ * the event.
+ *
+ * \sa QWaylandQuickShellSurfaceItem::wheelEvent()
+ */
+bool QWaylandQuickShellIntegration::wheelEvent(QWheelEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+#endif
diff --git a/src/compositor/extensions/qwaylandquickshellintegration.h b/src/compositor/extensions/qwaylandquickshellintegration.h
new file mode 100644
index 000000000..e1a4c2384
--- /dev/null
+++ b/src/compositor/extensions/qwaylandquickshellintegration.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QWAYLANDQUICKSHELLINTEGRATION_H
+#define QWAYLANDQUICKSHELLINTEGRATION_H
+
+#include <QtCore/QObject>
+#include <QtGui/QMouseEvent>
+#include <QtWaylandCompositor/qtwaylandcompositorglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellIntegration : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QWaylandQuickShellIntegration(QObject *parent = nullptr);
+
+ virtual bool touchEvent(QTouchEvent *event);
+
+ virtual bool hoverEnterEvent(QHoverEvent *event);
+ virtual bool hoverLeaveEvent(QHoverEvent *event);
+ virtual bool hoverMoveEvent(QHoverEvent *event);
+
+ virtual bool keyPressEvent(QKeyEvent *event);
+ virtual bool keyReleaseEvent(QKeyEvent *event);
+
+ virtual bool mouseDoubleClickEvent(QMouseEvent *event);
+ virtual bool mouseMoveEvent(QMouseEvent *event);
+ virtual bool mousePressEvent(QMouseEvent *event);
+ virtual bool mouseReleaseEvent(QMouseEvent *event);
+
+#if QT_CONFIG(wheelevent)
+ virtual bool wheelEvent(QWheelEvent *event);
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDQUICKSHELLINTEGRATION_H
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
index 84e9c356d..110c3d0a3 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
@@ -208,6 +208,56 @@ void QWaylandQuickShellSurfaceItem::setAutoCreatePopupItems(bool enabled)
emit autoCreatePopupItemsChanged();
}
+void QWaylandQuickShellSurfaceItem::touchEvent(QTouchEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->touchEvent(event))
+ QWaylandQuickItem::touchEvent(event);
+}
+
+void QWaylandQuickShellSurfaceItem::hoverEnterEvent(QHoverEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->hoverEnterEvent(event))
+ QWaylandQuickItem::hoverEnterEvent(event);
+}
+
+void QWaylandQuickShellSurfaceItem::hoverLeaveEvent(QHoverEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->hoverLeaveEvent(event))
+ QWaylandQuickItem::hoverLeaveEvent(event);
+}
+
+void QWaylandQuickShellSurfaceItem::hoverMoveEvent(QHoverEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->hoverMoveEvent(event))
+ QWaylandQuickItem::hoverMoveEvent(event);
+}
+
+
+void QWaylandQuickShellSurfaceItem::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->keyPressEvent(event))
+ QWaylandQuickItem::keyPressEvent(event);
+}
+
+void QWaylandQuickShellSurfaceItem::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->keyReleaseEvent(event))
+ QWaylandQuickItem::keyReleaseEvent(event);
+}
+
+void QWaylandQuickShellSurfaceItem::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->mouseDoubleClickEvent(event))
+ QWaylandQuickItem::mouseDoubleClickEvent(event);
+}
+
void QWaylandQuickShellSurfaceItem::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QWaylandQuickShellSurfaceItem);
@@ -215,6 +265,13 @@ void QWaylandQuickShellSurfaceItem::mouseMoveEvent(QMouseEvent *event)
QWaylandQuickItem::mouseMoveEvent(event);
}
+void QWaylandQuickShellSurfaceItem::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->mousePressEvent(event))
+ QWaylandQuickItem::mousePressEvent(event);
+}
+
void QWaylandQuickShellSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QWaylandQuickShellSurfaceItem);
@@ -222,6 +279,15 @@ void QWaylandQuickShellSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
QWaylandQuickItem::mouseReleaseEvent(event);
}
+#if QT_CONFIG(wheelevent)
+void QWaylandQuickShellSurfaceItem::wheelEvent(QWheelEvent *event)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (!d->m_shellIntegration->wheelEvent(event))
+ QWaylandQuickItem::wheelEvent(event);
+}
+#endif
+
/*!
\class QWaylandQuickShellEventFilter
\brief QWaylandQuickShellEventFilter implements a Wayland popup grab
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
index d14fa3fce..73a4900bb 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
@@ -76,8 +76,23 @@ Q_SIGNALS:
protected:
QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent);
+ void touchEvent(QTouchEvent *event) override;
+
+ void hoverEnterEvent(QHoverEvent *event) override;
+ void hoverLeaveEvent(QHoverEvent *event) override;
+ void hoverMoveEvent(QHoverEvent *event) override;
+
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
+
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+
+#if QT_CONFIG(wheelevent)
+ void wheelEvent(QWheelEvent *event) override;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h
index 7a458381e..f622368ab 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h
@@ -41,6 +41,7 @@
#define QWAYLANDQUICKSHELLSURFACEITEM_P_H
#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem>
+#include <QtWaylandCompositor/QWaylandQuickShellIntegration>
#include <QtWaylandCompositor/private/qwaylandquickitem_p.h>
#include <QtCore/QBasicTimer>
@@ -59,7 +60,6 @@ QT_BEGIN_NAMESPACE
// We mean it.
//
-class QWaylandQuickShellIntegration;
class QWaylandShellSurface;
class QWaylandQuickShellSurfaceItem;
@@ -74,16 +74,13 @@ public:
QWaylandQuickShellIntegration *m_shellIntegration = nullptr;
QWaylandShellSurface *m_shellSurface = nullptr;
QQuickItem *m_moveItem = nullptr;
- bool m_autoCreatePopupItems = false;
-};
+ bool m_autoCreatePopupItems =
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ true;
+#else
+ false;
+#endif
-class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellIntegration : public QObject
-{
- Q_OBJECT
-public:
- QWaylandQuickShellIntegration(QObject *parent = nullptr) : QObject(parent) {}
- virtual bool mouseMoveEvent(QMouseEvent *) { return false; }
- virtual bool mouseReleaseEvent(QMouseEvent *) { return false; }
};
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellEventFilter : public QObject
diff --git a/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp b/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp
new file mode 100644
index 000000000..eb6717a78
--- /dev/null
+++ b/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 <QWaylandCompositor>
+#include <QWaylandOutput>
+
+#include "qwaylandquickxdgoutputv1.h"
+#include "qwaylandxdgoutputv1_p.h"
+
+QWaylandQuickXdgOutputV1::QWaylandQuickXdgOutputV1()
+ : QWaylandXdgOutputV1()
+{
+}
+
+void QWaylandQuickXdgOutputV1::componentComplete()
+{
+ // Try to find the manager from the compositor extensions
+ if (!manager()) {
+ for (auto *p = parent(); p != nullptr; p = p->parent()) {
+ if (auto *c = qobject_cast<QWaylandCompositor *>(p)) {
+ for (auto *extension : c->extensions()) {
+ if (auto *m = qobject_cast<QWaylandXdgOutputManagerV1 *>(extension)) {
+ QWaylandXdgOutputV1Private::get(this)->setManager(m);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Try to find the output from the parents
+ if (!output()) {
+ for (auto *p = parent(); p != nullptr; p = p->parent()) {
+ if (auto *o = qobject_cast<QWaylandOutput *>(p)) {
+ QWaylandXdgOutputV1Private::get(this)->setOutput(o);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/compositor/extensions/qwaylandquickxdgoutputv1.h b/src/compositor/extensions/qwaylandquickxdgoutputv1.h
new file mode 100644
index 000000000..c8b16ab8e
--- /dev/null
+++ b/src/compositor/extensions/qwaylandquickxdgoutputv1.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 QWAYLANDQUICKXDGOUTPUT_V1
+#define QWAYLANDQUICKXDGOUTPUT_V1
+
+#include <QtQml/QQmlListProperty>
+#include <QtQml/QQmlParserStatus>
+#include <QtWaylandCompositor/QWaylandXdgOutputV1>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickXdgOutputV1
+ : public QWaylandXdgOutputV1
+ , public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+public:
+ explicit QWaylandQuickXdgOutputV1();
+
+protected:
+ void classBegin() override {}
+ void componentComplete() override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDQUICKXDGOUTPUT_V1
diff --git a/src/compositor/extensions/qwaylandtextinput.cpp b/src/compositor/extensions/qwaylandtextinput.cpp
index f60a32a14..b46caa641 100644
--- a/src/compositor/extensions/qwaylandtextinput.cpp
+++ b/src/compositor/extensions/qwaylandtextinput.cpp
@@ -162,7 +162,7 @@ void QWaylandTextInputPrivate::sendInputMethodEvent(QInputMethodEvent *event)
afterCommit.cursorPosition += event->commitString().length();
afterCommit.anchorPosition = afterCommit.cursorPosition;
- foreach (const QInputMethodEvent::Attribute &attribute, event->attributes()) {
+ for (const QInputMethodEvent::Attribute &attribute : event->attributes()) {
if (attribute.type == QInputMethodEvent::Selection) {
afterCommit.cursorPosition = attribute.start;
afterCommit.anchorPosition = attribute.length;
@@ -174,7 +174,7 @@ void QWaylandTextInputPrivate::sendInputMethodEvent(QInputMethodEvent *event)
}
}
send_commit_string(focusResource->handle, event->commitString());
- foreach (const QInputMethodEvent::Attribute &attribute, event->attributes()) {
+ for (const QInputMethodEvent::Attribute &attribute : event->attributes()) {
if (attribute.type == QInputMethodEvent::Cursor) {
int index = QWaylandInputMethodEventBuilder::indexToWayland(event->preeditString(), attribute.start);
send_preedit_cursor(focusResource->handle, index);
diff --git a/src/compositor/extensions/qwaylandwlscaler_p.h b/src/compositor/extensions/qwaylandwlscaler_p.h
index d3c2edd76..10a66f884 100644
--- a/src/compositor/extensions/qwaylandwlscaler_p.h
+++ b/src/compositor/extensions/qwaylandwlscaler_p.h
@@ -55,6 +55,7 @@
QT_BEGIN_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 13)
class QWaylandSurface;
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlScalerPrivate
@@ -87,6 +88,7 @@ private:
QPointer<QWaylandSurface> m_surface = nullptr;
};
};
+#endif
QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp
index 9871a8a5a..8cd2c7310 100644
--- a/src/compositor/extensions/qwaylandwlshell.cpp
+++ b/src/compositor/extensions/qwaylandwlshell.cpp
@@ -332,7 +332,7 @@ QList<QWaylandWlShellSurface *> QWaylandWlShell::shellSurfacesForClient(QWayland
{
Q_D(const QWaylandWlShell);
QList<QWaylandWlShellSurface *> surfsForClient;
- Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) {
+ for (QWaylandWlShellSurface *shellSurface : d->m_shellSurfaces) {
if (shellSurface->surface() && shellSurface->surface()->client() == client)
surfsForClient.append(shellSurface);
}
@@ -343,7 +343,7 @@ QList<QWaylandWlShellSurface *> QWaylandWlShell::mappedPopups() const
{
Q_D(const QWaylandWlShell);
QList<QWaylandWlShellSurface *> popupSurfaces;
- Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) {
+ for (QWaylandWlShellSurface *shellSurface : d->m_shellSurfaces) {
if (shellSurface->windowType() == Qt::WindowType::Popup
&& shellSurface->surface() && shellSurface->surface()->hasContent()) {
popupSurfaces.append(shellSurface);
@@ -355,7 +355,7 @@ QList<QWaylandWlShellSurface *> QWaylandWlShell::mappedPopups() const
QWaylandClient *QWaylandWlShell::popupClient() const
{
Q_D(const QWaylandWlShell);
- Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) {
+ for (QWaylandWlShellSurface *shellSurface : d->m_shellSurfaces) {
if (shellSurface->windowType() == Qt::WindowType::Popup
&& shellSurface->surface() && shellSurface->surface()->hasContent()) {
return shellSurface->surface()->client();
@@ -366,7 +366,8 @@ QWaylandClient *QWaylandWlShell::popupClient() const
void QWaylandWlShell::closeAllPopups()
{
- Q_FOREACH (QWaylandWlShellSurface* shellSurface, mappedPopups())
+ const auto mapped = mappedPopups();
+ for (QWaylandWlShellSurface *shellSurface : mapped)
shellSurface->sendPopupDone();
}
diff --git a/src/compositor/extensions/qwaylandwlshellintegration.cpp b/src/compositor/extensions/qwaylandwlshellintegration.cpp
index 99a2e7655..b732069c4 100644
--- a/src/compositor/extensions/qwaylandwlshellintegration.cpp
+++ b/src/compositor/extensions/qwaylandwlshellintegration.cpp
@@ -198,7 +198,8 @@ void WlShellIntegration::handleSetPopup(QWaylandSeat *seat, QWaylandSurface *par
// Find the parent item on the same output
QWaylandQuickShellSurfaceItem *parentItem = nullptr;
- Q_FOREACH (QWaylandView *view, parent->views()) {
+ const auto views = parent->views();
+ for (QWaylandView *view : views) {
if (view->output() == m_item->view()->output()) {
QWaylandQuickShellSurfaceItem *item = qobject_cast<QWaylandQuickShellSurfaceItem*>(view->renderObject());
if (item) {
diff --git a/src/compositor/extensions/qwaylandxdgoutputv1.cpp b/src/compositor/extensions/qwaylandxdgoutputv1.cpp
new file mode 100644
index 000000000..2ab26c162
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgoutputv1.cpp
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 <QWaylandCompositor>
+
+#include "qwaylandxdgoutputv1_p.h"
+#include "qwaylandoutput_p.h"
+
+#include <wayland-server.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ * \qmltype XdgOutputManagerV1
+ * \inqmlmodule QtWayland.Compositor
+ * \since 5.14
+ * \brief Provides an extension for describing outputs in a desktop oriented fashion
+ *
+ * The XdgOutputManagerV1 extension provides a way for a compositor to describe outputs in a way
+ * that is more in line with the concept of an output on desktop oriented systems.
+ *
+ * Some information may not make sense in other applications such as IVI systems.
+ *
+ * Typically the global compositor space on a desktop system is made of a
+ * contiguous or overlapping set of rectangular regions.
+ *
+ * XdgOutputManagerV1 corresponds to the Wayland interface, \c zxdg_output_manager_v1.
+ *
+ * To provide the functionality of the extension in a compositor, create an instance of the
+ * XdgOutputManagerV1 component and add it to the list of extensions supported by the compositor,
+ * and associated each XdgOutputV1 with its WaylandOutput:
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
+ *
+ * WaylandCompositor {
+ * XdgOutputManagerV1 {
+ * WaylandOutput {
+ * id: output1
+ *
+ * position: Qt.point(0, 0)
+ * window: Window {}
+ *
+ * XdgOutputV1 {
+ * name: "WL-1"
+ * logicalPosition: output1.position
+ * logicalSize: Qt.size(output1.geometry.width / output1.scaleFactor,
+ * output1.geometry.height / output1.scaleFactor)
+ * }
+ * }
+ *
+ * WaylandOutput {
+ * id: output2
+ *
+ * position: Qt.point(800, 0)
+ * window: Window {}
+ *
+ * XdgOutputV1 {
+ * name: "WL-2"
+ * logicalPosition: output2.position
+ * logicalSize: Qt.size(output2.geometry.width / output2.scaleFactor,
+ * output2.geometry.height / output2.scaleFactor)
+ * }
+ * }
+ * }
+ * }
+ * \endqml
+ */
+
+/*!
+ * \class QWaylandXdgOutputManagerV1
+ * \inmodule QtWaylandCompositor
+ * \since 5.14
+ * \brief Provides an extension for describing outputs in a desktop oriented fashion
+ *
+ * The QWaylandXdgOutputManagerV1 extension provides a way for a compositor to describe outputs in a way
+ * that is more in line with the concept of an output on desktop oriented systems.
+ *
+ * Some information may not make sense in other applications such as IVI systems.
+ *
+ * QWaylandXdgOutputManagerV1 corresponds to the Wayland interface, \c zxdg_output_manager_v1.
+ */
+
+/*!
+ * Constructs a QWaylandXdgOutputManagerV1 object.
+ */
+QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1()
+ : QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>(*new QWaylandXdgOutputManagerV1Private())
+{
+}
+
+/*!
+ * Constructs a QWaylandXdgOutputManagerV1 object for the provided \a compositor.
+ */
+QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>(compositor, *new QWaylandXdgOutputManagerV1Private())
+{
+}
+
+// QWaylandXdgOutputManagerV1Private
+
+/*!
+ * Initializes the extension.
+ */
+void QWaylandXdgOutputManagerV1::initialize()
+{
+ Q_D(QWaylandXdgOutputManagerV1);
+
+ QWaylandCompositorExtensionTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qCWarning(qLcWaylandCompositor) << "Failed to find QWaylandCompositor when initializing QWaylandXdgOutputManagerV1";
+ return;
+ }
+ d->init(compositor->display(), d->interfaceVersion());
+}
+
+/*!
+ * Returns the Wayland interface for QWaylandXdgOutputManagerV1.
+ */
+const wl_interface *QWaylandXdgOutputManagerV1::interface()
+{
+ return QWaylandXdgOutputManagerV1Private::interface();
+}
+
+// QWaylandXdgOutputManagerV1Private
+
+void QWaylandXdgOutputManagerV1Private::registerXdgOutput(QWaylandOutput *output, QWaylandXdgOutputV1 *xdgOutput)
+{
+ if (!xdgOutputs.contains(output)) {
+ xdgOutputs[output] = xdgOutput;
+ QWaylandOutputPrivate::get(output)->xdgOutput = xdgOutput;
+ }
+}
+
+void QWaylandXdgOutputManagerV1Private::unregisterXdgOutput(QWaylandOutput *output)
+{
+ xdgOutputs.remove(output);
+}
+
+void QWaylandXdgOutputManagerV1Private::zxdg_output_manager_v1_get_xdg_output(Resource *resource,
+ uint32_t id,
+ wl_resource *outputResource)
+{
+ Q_Q(QWaylandXdgOutputManagerV1);
+
+ // Verify if the associated output exist
+ auto *output = QWaylandOutput::fromResource(outputResource);
+ if (!output) {
+ qCWarning(qLcWaylandCompositor,
+ "The client is requesting a QWaylandXdgOutputV1 for a "
+ "QWaylandOutput that doesn't exist");
+ wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "output not found");
+ return;
+ }
+
+ // Do we have a QWaylandXdgOutputV1 for this output?
+ if (!xdgOutputs.contains(output)) {
+ qCWarning(qLcWaylandCompositor,
+ "The client is requesting a QWaylandXdgOutputV1 that the compositor "
+ "didn't create before");
+ wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "compositor didn't create a QWaylandXdgOutputV1 for this zxdg_output_v1 object");
+ return;
+ }
+
+ // Bind QWaylandXdgOutputV1 and initialize
+ auto *xdgOutput = xdgOutputs[output];
+ auto *xdgOutputPrivate = QWaylandXdgOutputV1Private::get(xdgOutput);
+ Q_ASSERT(xdgOutputPrivate);
+ xdgOutputPrivate->setManager(q);
+ xdgOutputPrivate->setOutput(output);
+ xdgOutputPrivate->add(resource->client(), id, qMin(resource->version(), QWaylandXdgOutputV1Private::interfaceVersion()));
+}
+
+// QWaylandXdgOutputV1
+
+QWaylandXdgOutputV1::QWaylandXdgOutputV1()
+ : QObject(*new QWaylandXdgOutputV1Private)
+{
+}
+
+QWaylandXdgOutputV1::QWaylandXdgOutputV1(QWaylandOutput *output, QWaylandXdgOutputManagerV1 *manager)
+ : QObject(*new QWaylandXdgOutputV1Private)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ // Set members before emitting changed signals so that handlers will
+ // see both already set and not nullptr, avoiding potential crashes
+ d->manager = manager;
+ d->output = output;
+
+ QWaylandXdgOutputManagerV1Private::get(d->manager)->registerXdgOutput(output, this);
+
+ emit managerChanged();
+ emit outputChanged();
+}
+
+QWaylandXdgOutputV1::~QWaylandXdgOutputV1()
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->manager)
+ QWaylandXdgOutputManagerV1Private::get(d->manager)->unregisterXdgOutput(d->output);
+}
+
+/*!
+ * \qmlproperty XdgOutputManagerV1 QtWaylandCompositor::XdgOutputV1::manager
+ * \readonly
+ *
+ * This property holds the object that manages this XdgOutputV1.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::manager
+ * \readonly
+ *
+ * This property holds the object that manages this QWaylandXdgOutputV1.
+ */
+QWaylandXdgOutputManagerV1 *QWaylandXdgOutputV1::manager() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->manager;
+}
+
+/*!
+ * \qmlproperty WaylandOutput QtWaylandCompositor::XdgOutputV1::output
+ * \readonly
+ *
+ * This property holds the WaylandOutput associated with this XdgOutputV1.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::output
+ * \readonly
+ *
+ * This property holds the QWaylandOutput associated with this QWaylandXdgOutputV1.
+ */
+QWaylandOutput *QWaylandXdgOutputV1::output() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->output;
+}
+
+/*!
+ * \qmlproperty string QtWaylandCompositor::XdgOutputV1::name
+ *
+ * This property holds the name of this output.
+ *
+ * The naming convention is compositor defined, but limited to alphanumeric
+ * characters and dashes ("-"). Each name is unique and will also remain
+ * consistent across sessions with the same hardware and software configuration.
+ *
+ * Examples of names include "HDMI-A-1", "WL-1", "X11-1" etc...
+ * However don't assume the name reflects the underlying technology.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::name
+ *
+ * This property holds the name of this output.
+ *
+ * The naming convention is compositor defined, but limited to alphanumeric
+ * characters and dashes ("-"). Each name is unique and will also remain
+ * consistent across sessions with the same hardware and software configuration.
+ *
+ * Examples of names include "HDMI-A-1", "WL-1", "X11-1" etc...
+ * However don't assume the name reflects the underlying technology.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+QString QWaylandXdgOutputV1::name() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->name;
+}
+
+void QWaylandXdgOutputV1::setName(const QString &name)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->name == name)
+ return;
+
+ // Can't change after clients bound to xdg-output
+ if (d->initialized) {
+ qCWarning(qLcWaylandCompositor, "QWaylandXdgOutputV1::name cannot be changed after initialization");
+ return;
+ }
+
+ d->name = name;
+ emit nameChanged();
+}
+
+/*!
+ * \qmlproperty string QtWaylandCompositor::XdgOutputV1::description
+ *
+ * This property holds the description of this output.
+ *
+ * No convention is defined for the description.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::description
+ *
+ * This property holds the description of this output.
+ *
+ * No convention is defined for the description.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+QString QWaylandXdgOutputV1::description() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->description;
+}
+
+void QWaylandXdgOutputV1::setDescription(const QString &description)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->description == description)
+ return;
+
+ // Can't change after clients bound to xdg-output
+ if (d->initialized) {
+ qCWarning(qLcWaylandCompositor, "QWaylandXdgOutputV1::description cannot be changed after initialization");
+ return;
+ }
+
+ d->description = description;
+ emit descriptionChanged();
+}
+
+/*!
+ * \qmlproperty point QtWaylandCompositor::XdgOutputV1::logicalPosition
+ *
+ * This property holds the coordinates of the output within the global compositor space.
+ *
+ * The default value is 0,0.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::logicalPosition
+ *
+ * This property holds the coordinates of the output within the global compositor space.
+ *
+ * The default value is 0,0.
+ */
+QPoint QWaylandXdgOutputV1::logicalPosition() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->logicalPos;
+}
+
+void QWaylandXdgOutputV1::setLogicalPosition(const QPoint &position)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->logicalPos == position)
+ return;
+
+ d->logicalPos = position;
+ if (d->initialized) {
+ d->sendLogicalPosition(position);
+ d->sendDone();
+ }
+ emit logicalPositionChanged();
+ emit logicalGeometryChanged();
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::XdgOutputV1::logicalSize
+ *
+ * This property holds the size of the output in the global compositor space.
+ *
+ * The default value is -1,-1 which is invalid.
+ *
+ * Please remember that this is the logical size, not the physical size.
+ * For example, for a WaylandOutput mode 3840x2160 and a scale factor 2:
+ * \list
+ * \li A compositor not scaling the surface buffers, will report a logical size of 3840x2160.
+ * \li A compositor automatically scaling the surface buffers, will report a logical size of 1920x1080.
+ * \li A compositor using a fractional scale of 1.5, will report a logical size of 2560x1620.
+ * \endlist
+ */
+/*!
+ * \property QWaylandXdgOutputV1::logicalSize
+ *
+ * This property holds the size of the output in the global compositor space.
+ *
+ * The default value is -1,-1 which is invalid.
+ *
+ * Please remember that this is the logical size, not the physical size.
+ * For example, for a WaylandOutput mode 3840x2160 and a scale factor 2:
+ * \list
+ * \li A compositor not scaling the surface buffers, will report a logical size of 3840x2160.
+ * \li A compositor automatically scaling the surface buffers, will report a logical size of 1920x1080.
+ * \li A compositor using a fractional scale of 1.5, will report a logical size of 2560x1620.
+ * \endlist
+ */
+QSize QWaylandXdgOutputV1::logicalSize() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->logicalSize;
+}
+
+void QWaylandXdgOutputV1::setLogicalSize(const QSize &size)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->logicalSize == size)
+ return;
+
+ d->logicalSize = size;
+ if (d->initialized) {
+ d->sendLogicalSize(size);
+ d->sendDone();
+ }
+ emit logicalSizeChanged();
+ emit logicalGeometryChanged();
+}
+
+/*!
+ * \qmlproperty rect QtWaylandCompositor::XdgOutputV1::logicalGeometry
+ * \readonly
+ *
+ * This property holds the position and size of the output in the global compositor space.
+ * It's the combination of the logical position and logical size.
+ *
+ * \sa XdgOutputV1::logicalPosition
+ * \sa XdgOutputV1::logicalSize
+ */
+/*!
+ * \property QWaylandXdgOutputV1::logicalGeometry
+ * \readonly
+ *
+ * This property holds the position and size of the output in the global compositor space.
+ * It's the combination of the logical position and logical size.
+ *
+ * \sa QWaylandXdgOutputV1::logicalPosition
+ * \sa QWaylandXdgOutputV1::logicalSize
+ */
+QRect QWaylandXdgOutputV1::logicalGeometry() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return QRect(d->logicalPos, d->logicalSize);
+}
+
+// QWaylandXdgOutputV1Private
+
+void QWaylandXdgOutputV1Private::sendLogicalPosition(const QPoint &position)
+{
+ const auto values = resourceMap().values();
+ for (auto *resource : values)
+ send_logical_position(resource->handle, position.x(), position.y());
+ needToSendDone = true;
+}
+
+void QWaylandXdgOutputV1Private::sendLogicalSize(const QSize &size)
+{
+ const auto values = resourceMap().values();
+ for (auto *resource : values)
+ send_logical_size(resource->handle, size.width(), size.height());
+ needToSendDone = true;
+}
+
+void QWaylandXdgOutputV1Private::sendDone()
+{
+ if (needToSendDone) {
+ const auto values = resourceMap().values();
+ for (auto *resource : values) {
+ if (resource->version() < 3)
+ send_done(resource->handle);
+ }
+ needToSendDone = false;
+ }
+}
+
+void QWaylandXdgOutputV1Private::setManager(QWaylandXdgOutputManagerV1 *_manager)
+{
+ Q_Q(QWaylandXdgOutputV1);
+
+ if (!_manager) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a null QWaylandXdgOutputManagerV1 to QWaylandXdgOutputV1 %p", this);
+ return;
+ }
+
+ if (manager == _manager)
+ return;
+
+ if (manager) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a different QWaylandXdgOutputManagerV1 to QWaylandXdgOutputV1 %p "
+ "after initialization", this);
+ return;
+ }
+
+ manager = _manager;
+ emit q->managerChanged();
+}
+
+void QWaylandXdgOutputV1Private::setOutput(QWaylandOutput *_output)
+{
+ Q_Q(QWaylandXdgOutputV1);
+
+ if (!_output) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a null QWaylandOutput to QWaylandXdgOutputV1 %p", this);
+ return;
+ }
+
+ if (output == _output)
+ return;
+
+ if (output) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a different QWaylandOutput to QWaylandXdgOutputV1 %p "
+ "after initialization", this);
+ return;
+ }
+
+ // Assign output above manager, to make both values valid in handlers
+ output = _output;
+
+ if (!manager) {
+ // Try to find the manager from the output parents
+ for (auto *p = output->parent(); p != nullptr; p = p->parent()) {
+ if (auto *m = qobject_cast<QWaylandXdgOutputManagerV1 *>(p)) {
+ manager = m;
+ emit q->managerChanged();
+ break;
+ }
+ }
+ }
+
+ emit q->outputChanged();
+
+ // Register the output
+ if (manager)
+ QWaylandXdgOutputManagerV1Private::get(manager)->registerXdgOutput(output, q);
+}
+
+void QWaylandXdgOutputV1Private::zxdg_output_v1_bind_resource(Resource *resource)
+{
+ send_logical_position(resource->handle, logicalPos.x(), logicalPos.y());
+ send_logical_size(resource->handle, logicalSize.width(), logicalSize.height());
+ if (resource->version() >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
+ send_name(resource->handle, name);
+ if (resource->version() >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION)
+ send_description(resource->handle, description);
+ send_done(resource->handle);
+
+ initialized = true;
+}
+
+void QWaylandXdgOutputV1Private::zxdg_output_v1_destroy(Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandxdgoutputv1.h b/src/compositor/extensions/qwaylandxdgoutputv1.h
new file mode 100644
index 000000000..c5f03758a
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgoutputv1.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 QWAYLANDXDGOUTPUTV1_H
+#define QWAYLANDXDGOUTPUTV1_H
+
+#include <QRect>
+#include <QWaylandCompositorExtension>
+#include <QtWaylandCompositor/qwaylandquickchildren.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandOutput;
+
+class QWaylandXdgOutputManagerV1Private;
+class QWaylandXdgOutputV1Private;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputManagerV1
+ : public QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgOutputManagerV1)
+public:
+ explicit QWaylandXdgOutputManagerV1();
+ QWaylandXdgOutputManagerV1(QWaylandCompositor *compositor);
+
+ void initialize() override;
+
+ static const wl_interface *interface();
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputV1 : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgOutputV1)
+ Q_WAYLAND_COMPOSITOR_DECLARE_QUICK_CHILDREN(QWaylandXdgOutputV1)
+ Q_PROPERTY(QWaylandXdgOutputManagerV1 *manager READ manager NOTIFY managerChanged)
+ Q_PROPERTY(QWaylandOutput *output READ output NOTIFY outputChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged)
+ Q_PROPERTY(QPoint logicalPosition READ logicalPosition WRITE setLogicalPosition NOTIFY logicalPositionChanged)
+ Q_PROPERTY(QSize logicalSize READ logicalSize WRITE setLogicalSize NOTIFY logicalSizeChanged)
+ Q_PROPERTY(QRect logicalGeometry READ logicalGeometry NOTIFY logicalGeometryChanged)
+public:
+ QWaylandXdgOutputV1();
+ QWaylandXdgOutputV1(QWaylandOutput *output, QWaylandXdgOutputManagerV1 *manager);
+ ~QWaylandXdgOutputV1() override;
+
+ QWaylandXdgOutputManagerV1 *manager() const;
+ QWaylandOutput *output() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString description() const;
+ void setDescription(const QString &name);
+
+ QPoint logicalPosition() const;
+ void setLogicalPosition(const QPoint &position);
+
+ QSize logicalSize() const;
+ void setLogicalSize(const QSize &size);
+
+ QRect logicalGeometry() const;
+
+Q_SIGNALS:
+ void managerChanged();
+ void outputChanged();
+ void logicalPositionChanged();
+ void logicalSizeChanged();
+ void logicalGeometryChanged();
+ void nameChanged();
+ void descriptionChanged();
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGOUTPUTV1_H
diff --git a/src/compositor/extensions/qwaylandxdgoutputv1_p.h b/src/compositor/extensions/qwaylandxdgoutputv1_p.h
new file mode 100644
index 000000000..2e8a6fff9
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgoutputv1_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 QWAYLANDXDGOUTPUTV1_P_H
+#define QWAYLANDXDGOUTPUTV1_P_H
+
+#include <QWaylandOutput>
+#include <QWaylandXdgOutputV1>
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-xdg-output-unstable-v1.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 Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputManagerV1Private
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::zxdg_output_manager_v1
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgOutputManagerV1)
+public:
+ explicit QWaylandXdgOutputManagerV1Private() = default;
+
+ void registerXdgOutput(QWaylandOutput *output, QWaylandXdgOutputV1 *xdgOutput);
+ void unregisterXdgOutput(QWaylandOutput *output);
+
+ static QWaylandXdgOutputManagerV1Private *get(QWaylandXdgOutputManagerV1 *manager) { return manager ? manager->d_func() : nullptr; }
+
+protected:
+ void zxdg_output_manager_v1_get_xdg_output(Resource *resource, uint32_t id,
+ wl_resource *outputResource) override;
+
+private:
+ QHash<QWaylandOutput *, QWaylandXdgOutputV1 *> xdgOutputs;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputV1Private
+ : public QObjectPrivate
+ , public QtWaylandServer::zxdg_output_v1
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgOutputV1)
+public:
+ explicit QWaylandXdgOutputV1Private() = default;
+
+ void sendLogicalPosition(const QPoint &position);
+ void sendLogicalSize(const QSize &size);
+ void sendDone();
+
+ void setManager(QWaylandXdgOutputManagerV1 *manager);
+ void setOutput(QWaylandOutput *output);
+
+ static QWaylandXdgOutputV1Private *get(QWaylandXdgOutputV1 *xdgOutput) { return xdgOutput ? xdgOutput->d_func() : nullptr; }
+
+ bool initialized = false;
+ QWaylandOutput *output = nullptr;
+ QWaylandXdgOutputManagerV1 *manager = nullptr;
+ QPoint logicalPos;
+ QSize logicalSize;
+ QString name;
+ QString description;
+ bool needToSendDone = false;
+
+protected:
+ void zxdg_output_v1_bind_resource(Resource *resource) override;
+ void zxdg_output_v1_destroy(Resource *resource) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGOUTPUTV1_P_H
diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp
index eb7b958b4..eece3f3d6 100644
--- a/src/compositor/extensions/qwaylandxdgshell.cpp
+++ b/src/compositor/extensions/qwaylandxdgshell.cpp
@@ -1279,7 +1279,9 @@ QWaylandXdgToplevel *QWaylandXdgToplevel::fromResource(wl_resource *resource)
QList<int> QWaylandXdgToplevel::statesAsInts() const
{
QList<int> list;
- Q_FOREACH (uint state, states()) {
+ const auto s = states();
+ list.reserve(s.size());
+ for (auto state : s) {
list << static_cast<int>(state);
}
return list;
@@ -1871,6 +1873,26 @@ uint QWaylandXdgPopup::sendConfigure(const QRect &geometry)
}
/*!
+ * \qmlmethod void QtWaylandCompositor::XdgPopup::sendPopupDone()
+ * \since 5.14
+ *
+ * Dismiss the popup. According to the \c xdg-shell protocol this should make the
+ * client destroy the popup.
+ */
+
+/*!
+ * \since 5.14
+ *
+ * Dismiss the popup. According to the \c xdg-shell protocol this should make the
+ * client destroy the popup.
+ */
+void QWaylandXdgPopup::sendPopupDone()
+{
+ Q_D(QWaylandXdgPopup);
+ d->send_popup_done();
+}
+
+/*!
* Returns the surface role for the QWaylandPopup.
*/
QWaylandSurfaceRole *QWaylandXdgPopup::role()
diff --git a/src/compositor/extensions/qwaylandxdgshell.h b/src/compositor/extensions/qwaylandxdgshell.h
index 774dd2282..f45038eb9 100644
--- a/src/compositor/extensions/qwaylandxdgshell.h
+++ b/src/compositor/extensions/qwaylandxdgshell.h
@@ -260,6 +260,7 @@ public:
QPoint unconstrainedPosition() const;
Q_INVOKABLE uint sendConfigure(const QRect &geometry);
+ Q_REVISION(14) Q_INVOKABLE void sendPopupDone();
static QWaylandSurfaceRole *role();
diff --git a/src/compositor/extensions/qwaylandxdgshellv5.cpp b/src/compositor/extensions/qwaylandxdgshellv5.cpp
index 0628f55e7..a40c21682 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv5.cpp
@@ -115,9 +115,9 @@ QWaylandXdgPopupV5 *QWaylandXdgShellV5Private::topmostPopupForClient(wl_client *
return clientPopups.empty() ? nullptr : clientPopups.last();
}
-QWaylandXdgSurfaceV5 *QWaylandXdgShellV5Private::xdgSurfaceFromSurface(QWaylandSurface *surface)
+QWaylandXdgSurfaceV5 *QWaylandXdgShellV5Private::xdgSurfaceFromSurface(QWaylandSurface *surface) const
{
- Q_FOREACH (QWaylandXdgSurfaceV5 *xdgSurface, m_xdgSurfaces) {
+ for (QWaylandXdgSurfaceV5 *xdgSurface : m_xdgSurfaces) {
if (surface == xdgSurface->surface())
return xdgSurface;
}
@@ -414,7 +414,7 @@ void QWaylandXdgSurfaceV5Private::xdg_surface_ack_configure(Resource *resource,
break;
}
- QVector<uint> changedStates;
+ std::vector<uint> changedStates;
std::set_symmetric_difference(
m_lastAckedConfigure.states.begin(), m_lastAckedConfigure.states.end(),
config.states.begin(), config.states.end(),
@@ -423,7 +423,7 @@ void QWaylandXdgSurfaceV5Private::xdg_surface_ack_configure(Resource *resource,
m_lastAckedConfigure = config;
if (!changedStates.empty()) {
- Q_FOREACH (uint state, changedStates) {
+ for (uint state : changedStates) {
switch (state) {
case QWaylandXdgSurfaceV5::State::MaximizedState:
emit q->maximizedChanged();
@@ -580,7 +580,7 @@ void QWaylandXdgShellV5::initialize()
QWaylandClient *QWaylandXdgShellV5::popupClient() const
{
Q_D(const QWaylandXdgShellV5);
- Q_FOREACH (QWaylandXdgPopupV5 *popup, d->m_xdgPopups) {
+ for (QWaylandXdgPopupV5 *popup : d->m_xdgPopups) {
if (popup->surface()->hasContent())
return popup->surface()->client();
}
@@ -627,15 +627,19 @@ uint QWaylandXdgShellV5::ping(QWaylandClient *client)
return serial;
}
+// ### remove once QMap has rbegin()/rend()
+template <typename Iterator>
+std::reverse_iterator<Iterator> make_reverse(Iterator it)
+{
+ return std::reverse_iterator<Iterator>(std::move(it));
+}
+
void QWaylandXdgShellV5::closeAllPopups()
{
Q_D(QWaylandXdgShellV5);
- Q_FOREACH (struct wl_client *client, d->m_xdgPopups.keys()) {
- QList<QWaylandXdgPopupV5 *> popups = d->m_xdgPopups.values(client);
- std::reverse(popups.begin(), popups.end());
- Q_FOREACH (QWaylandXdgPopupV5 *currentTopmostPopup, popups) {
- currentTopmostPopup->sendPopupDone();
- }
+ // Close pop-ups from top-most to bottom-most, lest we get protocol errors:
+ for (auto rit = make_reverse(d->m_xdgPopups.end()), rend = make_reverse(d->m_xdgPopups.begin()); rit != rend; ++rit) {
+ (*rit)->sendPopupDone();
}
}
@@ -987,7 +991,9 @@ void QWaylandXdgSurfaceV5::initialize()
QList<int> QWaylandXdgSurfaceV5::statesAsInts() const
{
QList<int> list;
- Q_FOREACH (uint state, states()) {
+ const auto s = states();
+ list.reserve(s.size());
+ for (auto state : s) {
list << static_cast<int>(state);
}
return list;
@@ -1238,7 +1244,8 @@ uint QWaylandXdgSurfaceV5::sendConfigure(const QSize &size, const QVector<uint>
uint QWaylandXdgSurfaceV5::sendConfigure(const QSize &size, const QVector<QWaylandXdgSurfaceV5::State> &states)
{
QVector<uint> asUints;
- Q_FOREACH (QWaylandXdgSurfaceV5::State state, states) {
+ asUints.reserve(states.size());
+ for (QWaylandXdgSurfaceV5::State state : states) {
asUints << state;
}
return sendConfigure(size, asUints);
diff --git a/src/compositor/extensions/qwaylandxdgshellv5_p.h b/src/compositor/extensions/qwaylandxdgshellv5_p.h
index 8f5af746b..d10359e68 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5_p.h
+++ b/src/compositor/extensions/qwaylandxdgshellv5_p.h
@@ -81,7 +81,7 @@ public:
QMultiMap<struct wl_client *, QWaylandXdgSurfaceV5 *> m_xdgSurfaces;
QMultiMap<struct wl_client *, QWaylandXdgPopupV5 *> m_xdgPopups;
- QWaylandXdgSurfaceV5 *xdgSurfaceFromSurface(QWaylandSurface *surface);
+ QWaylandXdgSurfaceV5 *xdgSurfaceFromSurface(QWaylandSurface *surface) const;
protected:
void xdg_shell_destroy(Resource *resource) override;
diff --git a/src/compositor/extensions/qwaylandxdgshellv6.cpp b/src/compositor/extensions/qwaylandxdgshellv6.cpp
index f971fe5b4..96d6f5509 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv6.cpp
@@ -1214,7 +1214,9 @@ QWaylandSurfaceRole *QWaylandXdgToplevelV6::role()
QList<int> QWaylandXdgToplevelV6::statesAsInts() const
{
QList<int> list;
- Q_FOREACH (uint state, states()) {
+ const auto s = states();
+ list.reserve(s.size());
+ for (auto state : s) {
list << static_cast<int>(state);
}
return list;
@@ -1802,6 +1804,26 @@ uint QWaylandXdgPopupV6::sendConfigure(const QRect &geometry)
}
/*!
+ * \qmlmethod void QtWaylandCompositor::XdgPopupV6::sendPopupDone()
+ * \since 5.14
+ *
+ * Dismiss the popup. According to the \c xdg-shell-unstable-v6 protocol this should make the
+ * client destroy the popup.
+ */
+
+/*!
+ * \since 5.14
+ *
+ * Dismiss the popup. According to the \c xdg-shell-unstable-v6 protocol this should make the
+ * client destroy the popup.
+ */
+void QWaylandXdgPopupV6::sendPopupDone()
+{
+ Q_D(QWaylandXdgPopupV6);
+ d->send_popup_done();
+}
+
+/*!
* Returns the surface role for the QWaylandPopupV6.
*/
QWaylandSurfaceRole *QWaylandXdgPopupV6::role()
diff --git a/src/compositor/extensions/qwaylandxdgshellv6.h b/src/compositor/extensions/qwaylandxdgshellv6.h
index b9c47c578..64c82306c 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6.h
+++ b/src/compositor/extensions/qwaylandxdgshellv6.h
@@ -246,6 +246,7 @@ public:
QPoint unconstrainedPosition() const;
Q_INVOKABLE uint sendConfigure(const QRect &geometry);
+ Q_REVISION(14) Q_INVOKABLE void sendPopupDone();
static QWaylandSurfaceRole *role();
diff --git a/src/compositor/extensions/qwltexturesharingextension.cpp b/src/compositor/extensions/qwltexturesharingextension.cpp
index 251c5fec0..cf9fd0116 100644
--- a/src/compositor/extensions/qwltexturesharingextension.cpp
+++ b/src/compositor/extensions/qwltexturesharingextension.cpp
@@ -177,7 +177,7 @@ public:
return new SharedTextureFactory(m_buffer);
}
// qDebug() << "Shared buffer NOT found for" << m_id;
- m_errorString = QLatin1Literal("Shared buffer not found");
+ m_errorString = QLatin1String("Shared buffer not found");
return nullptr;
}
@@ -282,7 +282,7 @@ void QWaylandTextureSharingExtension::initialize()
setImageSearchPath(image_search_path);
if (m_image_dirs.isEmpty())
- m_image_dirs << QLatin1Literal(":/") << QLatin1Literal("./");
+ m_image_dirs << QLatin1String(":/") << QLatin1String("./");
auto suffixes = QTextureFileReader::supportedFileFormats();
suffixes.append(QImageReader::supportedImageFormats());
@@ -295,7 +295,7 @@ void QWaylandTextureSharingExtension::initialize()
if (ctx) {
QQmlEngine *engine = ctx->engine();
if (engine) {
- auto *provider = static_cast<QWaylandSharedTextureProvider*>(engine->imageProvider(QLatin1Literal("wlshared")));
+ auto *provider = static_cast<QWaylandSharedTextureProvider*>(engine->imageProvider(QLatin1String("wlshared")));
if (provider)
provider->setExtensionReady(this);
}
@@ -308,7 +308,7 @@ QString QWaylandTextureSharingExtension::getExistingFilePath(const QString &key)
// paths containing '../'. We handle that here, at the price of also blocking directory
// names ending with two or more dots.
- if (key.contains(QLatin1Literal("../")))
+ if (key.contains(QLatin1String("../")))
return QString();
for (auto dir : m_image_dirs) {
diff --git a/src/compositor/global/qwaylandcompositorextension.cpp b/src/compositor/global/qwaylandcompositorextension.cpp
index 912985399..36daebce7 100644
--- a/src/compositor/global/qwaylandcompositorextension.cpp
+++ b/src/compositor/global/qwaylandcompositorextension.cpp
@@ -146,7 +146,7 @@ QWaylandObject::QWaylandObject(QObjectPrivate &d, QObject *parent)
QWaylandObject::~QWaylandObject()
{
- foreach (QWaylandCompositorExtension *extension, extension_vector)
+ for (QWaylandCompositorExtension *extension : qAsConst(extension_vector))
QWaylandCompositorExtensionPrivate::get(extension)->extension_container = nullptr;
}
diff --git a/src/compositor/hardware_integration/qwlserverbufferintegration_p.h b/src/compositor/hardware_integration/qwlserverbufferintegration_p.h
index b8d9fa99d..e8f774e60 100644
--- a/src/compositor/hardware_integration/qwlserverbufferintegration_p.h
+++ b/src/compositor/hardware_integration/qwlserverbufferintegration_p.h
@@ -55,7 +55,8 @@
#include <QtCore/QSize>
#include <QtGui/qopengl.h>
-#include <QtWaylandCompositor/private/qtwaylandcompositorglobal_p.h>
+#include <QtWaylandCompositor/qtwaylandcompositorglobal.h>
+
struct wl_client;
struct wl_resource;
@@ -85,9 +86,8 @@ public:
virtual bool bufferInUse() { return true; }
virtual QOpenGLTexture *toOpenGlTexture() = 0;
-#if QT_CONFIG(wayland_compositor_texture_sharing_experimental)
virtual void releaseOpenGlTexture() {}
-#endif
+
virtual bool isYInverted() const;
QSize size() const;
@@ -107,7 +107,6 @@ public:
virtual bool supportsFormat(ServerBuffer::Format format) const = 0;
virtual ServerBuffer *createServerBufferFromImage(const QImage &qimage, ServerBuffer::Format format) = 0;
-#if QT_CONFIG(wayland_compositor_texture_sharing_experimental)
virtual ServerBuffer *createServerBufferFromData(const QByteArray &data, const QSize &size, uint glInternalFormat)
{
Q_UNUSED(data);
@@ -115,7 +114,6 @@ public:
Q_UNUSED(glInternalFormat);
return nullptr;
}
-#endif
};
}
diff --git a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
index cb1ee3da0..ef6b26483 100644
--- a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
+++ b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
@@ -81,7 +81,7 @@ void ClientBuffer::setDestroyed()
m_committed = false;
m_buffer = nullptr;
- if (!m_refCount)
+ if (!m_refCount.loadAcquire())
delete this;
}
diff --git a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp
index e30bc84f8..624a24b06 100644
--- a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp
+++ b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp
@@ -186,12 +186,12 @@ struct wl_display *DataDeviceManager::display() const
void DataDeviceManager::overrideSelection(const QMimeData &mimeData)
{
- QStringList formats = mimeData.formats();
+ const QStringList formats = mimeData.formats();
if (formats.isEmpty())
return;
m_retainedData.clear();
- foreach (const QString &format, formats)
+ for (const QString &format : formats)
m_retainedData.setData(format, mimeData.data(format));
QWaylandCompositorPrivate::get(m_compositor)->feedRetainedSelectionData(&m_retainedData);
@@ -217,7 +217,8 @@ bool DataDeviceManager::offerFromCompositorToClient(wl_resource *clientDataDevic
wl_resource_create(client, &wl_data_offer_interface, -1, 0);
wl_resource_set_implementation(selectionOffer, &compositor_offer_interface, this, nullptr);
wl_data_device_send_data_offer(clientDataDeviceResource, selectionOffer);
- foreach (const QString &format, m_retainedData.formats()) {
+ const auto formats = m_retainedData.formats();
+ for (const QString &format : formats) {
QByteArray ba = format.toLatin1();
wl_data_offer_send_offer(selectionOffer, ba.constData());
}
diff --git a/src/compositor/wayland_wrapper/qwldataoffer.cpp b/src/compositor/wayland_wrapper/qwldataoffer.cpp
index 9fea664ac..ddc5545e3 100644
--- a/src/compositor/wayland_wrapper/qwldataoffer.cpp
+++ b/src/compositor/wayland_wrapper/qwldataoffer.cpp
@@ -55,7 +55,8 @@ DataOffer::DataOffer(DataSource *dataSource, QtWaylandServer::wl_data_device::Re
{
// FIXME: connect to dataSource and reset m_dataSource on destroy
target->data_device_object->send_data_offer(target->handle, resource()->handle);
- Q_FOREACH (const QString &mimeType, dataSource->mimeTypes()) {
+ const auto mimeTypes = dataSource->mimeTypes();
+ for (const QString &mimeType : mimeTypes) {
send_offer(mimeType);
}
}
diff --git a/src/extensions/README.md b/src/extensions/README.md
index f75e0f236..8024ffa80 100644
--- a/src/extensions/README.md
+++ b/src/extensions/README.md
@@ -3,12 +3,10 @@
The protocol extensions in this folder are considered implementation details of
Qt. I.e. they may removed, renamed or changed without warning.
-## Suffixed protocols
-
-For protocols that have a version suffix, however, we will strive to not break
-backwards compatibility without bumping the suffix (renaming the protocol).
-E.g.: If your client sees a `zqt_key_v1` global, it can safely bind to it:
-the key event will always take the same number of arguments, regardless of
+However, starting with Qt 5.4, we promise not to break backwards compatibility
+without renaming (or removing) the protocol. I.e., if your client sees a global
+from one of these extensions, it can safely bind to it: the existing events
+and requests will always take the same number of arguments, regardless of
compositor version.
This is important also within a Qt-only scope if there are multiple versions of
@@ -16,3 +14,11 @@ Qt on the system. Consider for instance an application statically linked to Qt
(such as Qt Creator) running against a Qt compositor installed by the distro).
In such cases we don't want the compositor and client to disagree on the
protocol definition.
+
+## Protocol versioning.
+
+Protocol extensions in this folder should be versioned (e.g. `zqt_key_v1`).
+If it is necessary to break protocol compatibility, they will be renamed by
+incrementing the version number. For legacy reasons, there are also unversioned
+protocols in this folder. Those protocols should be renamed to be versioned
+if compatibility is broken.
diff --git a/src/hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.cpp b/src/hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.cpp
index 7e1d5966f..4b2be50e6 100644
--- a/src/hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.cpp
+++ b/src/hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.cpp
@@ -37,15 +37,12 @@
**
****************************************************************************/
-#define GL_GLEXT_PROTOTYPES
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
#include "vulkanserverbufferintegration.h"
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QDebug>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLTexture>
+#include <QtGui/qopengl.h>
#include <QtGui/QImage>
#include <QtCore/QCoreApplication>
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
index 24dadff4d..030422c56 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
@@ -137,9 +137,8 @@ void QWaylandEglWindow::updateSurface(bool create)
m_resize = true;
}
- } else if (create && wl_surface::isInitialized()) {
- ::wl_surface *wlSurface = wl_surface::object();
- m_waylandEglWindow = wl_egl_window_create(wlSurface, sizeWithMargins.width(), sizeWithMargins.height());
+ } else if (create && wlSurface()) {
+ m_waylandEglWindow = wl_egl_window_create(wlSurface(), sizeWithMargins.width(), sizeWithMargins.height());
}
if (!m_eglSurface && m_waylandEglWindow && create) {
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
index bc1f74af9..5bd2760d0 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
@@ -192,7 +192,7 @@ public:
}
void blit(QWaylandEglWindow *window)
{
- Q_ASSERT(window->wl_surface::isInitialized());
+ Q_ASSERT(window->wlSurface());
QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context());
QSize surfaceSize = window->surfaceSize();
diff --git a/src/hardwareintegration/compositor/vulkan-server/vulkanserverbufferintegration.cpp b/src/hardwareintegration/compositor/vulkan-server/vulkanserverbufferintegration.cpp
index 7f9f8a151..df197ca23 100644
--- a/src/hardwareintegration/compositor/vulkan-server/vulkanserverbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/vulkan-server/vulkanserverbufferintegration.cpp
@@ -37,10 +37,6 @@
**
****************************************************************************/
-#define GL_GLEXT_PROTOTYPES
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
#include "vulkanserverbufferintegration.h"
#include "vulkanwrapper.h"
@@ -48,6 +44,7 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLTexture>
#include <QtGui/QOffscreenSurface>
+#include <QtGui/qopengl.h>
#include <unistd.h>
#include <fcntl.h>
diff --git a/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp b/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp
index fe66adf55..771e1015c 100644
--- a/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp
+++ b/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp
@@ -40,14 +40,13 @@
// NOTE: Some of the code below is adapted from the public domain code at https://vulkan-tutorial.com/
#define GL_GLEXT_PROTOTYPES
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <QtVulkanSupport/private/qvkconvenience_p.h>
#include "vulkanwrapper.h"
#include <QImage>
#include <QOpenGLContext>
+#include <QtGui/qopengl.h>
+#include <QtVulkanSupport/private/qvkconvenience_p.h>
#include <set>
@@ -707,7 +706,6 @@ VulkanImageWrapper *VulkanWrapper::createTextureImage(const QImage &img)
VulkanImageWrapper *VulkanWrapper::createTextureImageFromData(const uchar *pixels, uint bufferSize, const QSize &size, uint glInternalFormat)
{
VkFormat vkFormat = VkFormat(QVkConvenience::vkFormatFromGlFormat(glInternalFormat));
-
if (vkFormat == VK_FORMAT_UNDEFINED)
return nullptr;
diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
index c7553d932..223ca0bc5 100644
--- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp
+++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
@@ -66,6 +66,8 @@
#include <QtWaylandCompositor/QWaylandXdgShellV6>
#include <QtWaylandCompositor/QWaylandXdgShell>
#include <QtWaylandCompositor/QWaylandXdgDecorationManagerV1>
+#include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1>
+#include <QtWaylandCompositor/QWaylandQuickXdgOutputV1>
#include <QtWaylandCompositor/QWaylandIviApplication>
#include <QtWaylandCompositor/QWaylandIviSurface>
@@ -76,13 +78,17 @@ QT_BEGIN_NAMESPACE
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CONTAINER_CLASS(QWaylandQuickCompositor)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandQtWindowManager)
+Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandIdleInhibitManagerV1)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandIviApplication)
+#if QT_DEPRECATED_SINCE(5, 13)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWlScaler)
+#endif
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWlShell)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV5)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV6)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShell)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgDecorationManagerV1)
+Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgOutputManagerV1)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandTextInputManager)
class QmlUrlResolver
@@ -137,7 +143,9 @@ public:
qmlRegisterType<QWaylandQuickCompositorQuickExtensionContainer>(uri, 1, 0, "WaylandCompositor");
qmlRegisterType<QWaylandQuickItem>(uri, 1, 0, "WaylandQuickItem");
qmlRegisterType<QWaylandQuickItem, 13>(uri, 1, 13, "WaylandQuickItem");
+#if QT_CONFIG(opengl)
qmlRegisterType<QWaylandQuickHardwareLayer>(uri, 1, 2, "WaylandHardwareLayer");
+#endif
qmlRegisterType<QWaylandMouseTracker>(uri, 1, 0, "WaylandMouseTracker");
qmlRegisterType<QWaylandQuickOutput>(uri, 1, 0, "WaylandOutput");
qmlRegisterType<QWaylandQuickSurface>(uri, 1, 0, "WaylandSurface");
@@ -182,7 +190,14 @@ public:
qmlRegisterType<QWaylandXdgDecorationManagerV1QuickExtension>(uri, 1, 3, "XdgDecorationManagerV1");
+#if QT_DEPRECATED_SINCE(5, 13)
qmlRegisterType<QWaylandWlScalerQuickExtension>(uri, 1, 13, "WlScaler");
+#endif
+
+ qmlRegisterType<QWaylandIdleInhibitManagerV1QuickExtension>(uri, 1, 14, "IdleInhibitManagerV1");
+
+ qmlRegisterType<QWaylandXdgOutputManagerV1QuickExtension>(uri, 1, 14, "XdgOutputManagerV1");
+ qmlRegisterType<QWaylandQuickXdgOutputV1>(uri, 1, 14, "XdgOutputV1");
}
};
//![class decl]
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index c8394f0c1..7452a9283 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,8 +1,12 @@
TEMPLATE = subdirs
-qtHaveModule(quick): {
+qtHaveModule(quick):qtHaveModule(waylandcompositor) {
SUBDIRS += \
- compositor \
- texture-sharing \
- texture-sharing-extension
+ compositor
+
+ qtConfig(opengl):qtHaveModule(waylandclient) {
+ SUBDIRS += \
+ texture-sharing \
+ texture-sharing-extension
+ }
}
diff --git a/src/imports/texture-sharing-extension/texture-sharing-extension.pro b/src/imports/texture-sharing-extension/texture-sharing-extension.pro
index 577ab58e7..68a8cf757 100644
--- a/src/imports/texture-sharing-extension/texture-sharing-extension.pro
+++ b/src/imports/texture-sharing-extension/texture-sharing-extension.pro
@@ -8,6 +8,4 @@ SOURCES += \
QT += quick-private qml gui-private core-private waylandcompositor waylandcompositor-private
-requires(qtConfig(wayland-compositor-texture-sharing-experimental))
-
load(qml_plugin)
diff --git a/src/imports/texture-sharing/texture-sharing.pro b/src/imports/texture-sharing/texture-sharing.pro
index eb5c0a9af..bec769ecb 100644
--- a/src/imports/texture-sharing/texture-sharing.pro
+++ b/src/imports/texture-sharing/texture-sharing.pro
@@ -15,8 +15,6 @@ SOURCES += \
QT += quick-private qml gui-private core-private waylandclient waylandclient-private
CONFIG += wayland-scanner
-requires(qtConfig(wayland-client-texture-sharing-experimental))
-
WAYLANDCLIENTSOURCES += ../../extensions/qt-texture-sharing-unstable-v1.xml
diff --git a/src/plugins/hardwareintegration/hardwareintegration.pro b/src/plugins/hardwareintegration/hardwareintegration.pro
index cb7a4b263..12658adff 100644
--- a/src/plugins/hardwareintegration/hardwareintegration.pro
+++ b/src/plugins/hardwareintegration/hardwareintegration.pro
@@ -1,4 +1,4 @@
TEMPLATE=subdirs
-SUBDIRS += client
+qtHaveModule(waylandclient): SUBDIRS += client
qtHaveModule(waylandcompositor): SUBDIRS += compositor
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 9b66b851e..e121d92d3 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,6 +1,11 @@
TEMPLATE=subdirs
+
+qtHaveModule(waylandclient) {
+ SUBDIRS += \
+ platforms \
+ decorations \
+ shellintegration
+}
+
SUBDIRS += \
- platforms \
- hardwareintegration \
- decorations \
- shellintegration
+ hardwareintegration
diff --git a/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp b/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp
index 9a829f6e9..26f598895 100644
--- a/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp
+++ b/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp
@@ -51,7 +51,7 @@ QWaylandFullScreenShellV1Surface::QWaylandFullScreenShellV1Surface(QtWayland::zw
, m_window(window)
{
auto screen = static_cast<QWaylandScreen *>(m_window->screen());
- m_shell->present_surface(m_window->object(),
+ m_shell->present_surface(m_window->wlSurface(),
QtWayland::zwp_fullscreen_shell_v1::present_method_default,
screen->output());
}
diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp
index efb61dc9f..ea725ac31 100644
--- a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp
+++ b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp
@@ -48,6 +48,8 @@
#include "qwaylandivisurface_p.h"
+#include <mutex>
+
#include <unistd.h>
QT_BEGIN_NAMESPACE
@@ -95,7 +97,7 @@ uint32_t QWaylandIviShellIntegration::getNextUniqueSurfaceId()
{
const uint32_t PID_MAX_EXPONENTIATION = 22; // 22 bit shift operation
const uint32_t ID_LIMIT = 1 << (32 - PID_MAX_EXPONENTIATION); // 10 bit is unique id
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);
if (m_lastSurfaceId == 0) {
QByteArray env = qgetenv("QT_IVI_SURFACE_ID");
@@ -132,7 +134,7 @@ QWaylandShellSurface *QWaylandIviShellIntegration::createShellSurface(QWaylandWi
if (surfaceId == 0)
return nullptr;
- struct ivi_surface *surface = m_iviApplication->surface_create(surfaceId, window->object());
+ struct ivi_surface *surface = m_iviApplication->surface_create(surfaceId, window->wlSurface());
if (!m_iviController)
return new QWaylandIviSurface(surface, window);
diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h
index fc16d2f64..13282e438 100644
--- a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h
+++ b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h
@@ -71,7 +71,7 @@ private:
uint32_t m_lastSurfaceId = 0;
uint32_t m_surfaceNumber = 0;
bool m_useEnvSurfaceId = false;
- QMutex m_mutex{QMutex::Recursive};
+ QRecursiveMutex m_mutex;
};
}
diff --git a/src/plugins/shellintegration/wl-shell/qwaylandwlshellintegration.cpp b/src/plugins/shellintegration/wl-shell/qwaylandwlshellintegration.cpp
index 1edb24b3c..ab8098062 100644
--- a/src/plugins/shellintegration/wl-shell/qwaylandwlshellintegration.cpp
+++ b/src/plugins/shellintegration/wl-shell/qwaylandwlshellintegration.cpp
@@ -49,7 +49,8 @@ namespace QtWaylandClient {
bool QWaylandWlShellIntegration::initialize(QWaylandDisplay *display)
{
- Q_FOREACH (QWaylandDisplay::RegistryGlobal global, display->globals()) {
+ const auto globals = display->globals();
+ for (QWaylandDisplay::RegistryGlobal global : globals) {
if (global.interface == QLatin1String("wl_shell")) {
m_wlShell = new QtWayland::wl_shell(display->wl_registry(), global.id, 1);
break;
@@ -70,7 +71,7 @@ bool QWaylandWlShellIntegration::initialize(QWaylandDisplay *display)
QWaylandShellSurface *QWaylandWlShellIntegration::createShellSurface(QWaylandWindow *window)
{
- return new QWaylandWlShellSurface(m_wlShell->get_shell_surface(window->object()), window);
+ return new QWaylandWlShellSurface(m_wlShell->get_shell_surface(window->wlSurface()), window);
}
void *QWaylandWlShellIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
diff --git a/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp b/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
index 4506c312a..48e14c753 100644
--- a/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
+++ b/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
@@ -62,9 +62,9 @@ QWaylandWlShellSurface::QWaylandWlShellSurface(struct ::wl_shell_surface *shell_
Qt::WindowType type = window->window()->type();
auto *transientParent = window->transientParent();
- if (type == Qt::Popup && transientParent && transientParent->object())
+ if (type == Qt::Popup && transientParent && transientParent->wlSurface())
setPopup(transientParent, m_window->display()->lastInputDevice(), m_window->display()->lastInputSerial());
- else if (transientParent && transientParent->object())
+ else if (transientParent && transientParent->wlSurface())
updateTransientParent(transientParent->window());
else
setTopLevel();
@@ -234,11 +234,9 @@ void QWaylandWlShellSurface::updateTransientParent(QWindow *parent)
|| testShowWithoutActivating(m_window->window()))
flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
- Q_ASSERT(parent_wayland_window->object());
- set_transient(parent_wayland_window->object(),
- transientPos.x(),
- transientPos.y(),
- flags);
+ auto *parentSurface = parent_wayland_window->wlSurface();
+ Q_ASSERT(parentSurface);
+ set_transient(parentSurface, transientPos.x(), transientPos.y(), flags);
}
void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, uint serial)
@@ -261,9 +259,10 @@ void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevic
transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
}
- Q_ASSERT(parent_wayland_window->object());
- set_popup(device->wl_seat(), serial, parent_wayland_window->object(),
- transientPos.x(), transientPos.y(), 0);
+ auto *parentSurface = parent_wayland_window->wlSurface();
+ Q_ASSERT(parentSurface);
+ uint flags = 0;
+ set_popup(device->wl_seat(), serial, parentSurface, transientPos.x(), transientPos.y(), flags);
}
void QWaylandWlShellSurface::shell_surface_ping(uint32_t serial)
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
index 3eda43d7c..7e242c4a5 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
@@ -74,7 +74,7 @@ QWaylandXdgPopupV5 *QWaylandXdgShellV5::createXdgPopup(QWaylandWindow *window, Q
if (!parentWindow)
return nullptr;
- ::wl_surface *parentSurface = parentWindow->object();
+ ::wl_surface *parentSurface = parentWindow->wlSurface();
if (m_popupSerial == 0)
m_popupSerial = inputDevice->serial();
@@ -84,7 +84,7 @@ QWaylandXdgPopupV5 *QWaylandXdgShellV5::createXdgPopup(QWaylandWindow *window, Q
int x = position.x() + parentWindow->frameMargins().left();
int y = position.y() + parentWindow->frameMargins().top();
- auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->object(), parentSurface, seat, m_popupSerial, x, y), window);
+ auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), window);
m_popups.append(window);
QObject::connect(popup, &QWaylandXdgPopupV5::destroyed, [this, window](){
m_popups.removeOne(window);
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
index 410f27001..4e25949fa 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
@@ -51,7 +51,8 @@ namespace QtWaylandClient {
bool QWaylandXdgShellV5Integration::initialize(QWaylandDisplay *display)
{
- Q_FOREACH (QWaylandDisplay::RegistryGlobal global, display->globals()) {
+ const auto globals = display->globals();
+ for (QWaylandDisplay::RegistryGlobal global : globals) {
if (global.interface == QLatin1String("xdg_shell")) {
m_xdgShell.reset(new QWaylandXdgShellV5(display->wl_registry(), global.id));
break;
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgsurfacev5.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgsurfacev5.cpp
index e9f64e2e6..e8bff9193 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgsurfacev5.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgsurfacev5.cpp
@@ -54,7 +54,7 @@ namespace QtWaylandClient {
QWaylandXdgSurfaceV5::QWaylandXdgSurfaceV5(QWaylandXdgShellV5 *shell, QWaylandWindow *window)
: QWaylandShellSurface(window)
- , QtWayland::xdg_surface_v5(shell->get_xdg_surface(window->object()))
+ , QtWayland::xdg_surface_v5(shell->get_xdg_surface(window->wlSurface()))
, m_window(window)
, m_shell(shell)
{
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
index 980e4a601..e81aa9038 100644
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
@@ -425,7 +425,7 @@ QWaylandXdgShellV6::~QWaylandXdgShellV6()
QWaylandXdgSurfaceV6 *QWaylandXdgShellV6::getXdgSurface(QWaylandWindow *window)
{
- return new QWaylandXdgSurfaceV6(this, get_xdg_surface(window->object()), window);
+ return new QWaylandXdgSurfaceV6(this, get_xdg_surface(window->wlSurface()), window);
}
void QWaylandXdgShellV6::zxdg_shell_v6_ping(uint32_t serial)
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index f55298134..ca8da80b7 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -463,7 +463,7 @@ QWaylandXdgShell::~QWaylandXdgShell()
QWaylandXdgSurface *QWaylandXdgShell::getXdgSurface(QWaylandWindow *window)
{
- return new QWaylandXdgSurface(this, get_xdg_surface(window->object()), window);
+ return new QWaylandXdgSurface(this, get_xdg_surface(window->wlSurface()), window);
}
void QWaylandXdgShell::xdg_wm_base_ping(uint32_t serial)
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index 7f3dc5ad6..9691b857f 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -40,7 +40,8 @@
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
-#include <QtCore/QList>
+
+#include <vector>
class Scanner
{
@@ -63,7 +64,7 @@ private:
struct WaylandEnum {
QByteArray name;
- QList<WaylandEnumEntry> entries;
+ std::vector<WaylandEnumEntry> entries;
};
struct WaylandArgument {
@@ -78,16 +79,16 @@ private:
bool request;
QByteArray name;
QByteArray type;
- QList<WaylandArgument> arguments;
+ std::vector<WaylandArgument> arguments;
};
struct WaylandInterface {
QByteArray name;
int version;
- QList<WaylandEnum> enums;
- QList<WaylandEvent> events;
- QList<WaylandEvent> requests;
+ std::vector<WaylandEnum> enums;
+ std::vector<WaylandEvent> events;
+ std::vector<WaylandEvent> requests;
};
bool isServerSide();
@@ -101,11 +102,11 @@ private:
Scanner::WaylandInterface readInterface(QXmlStreamReader &xml);
QByteArray waylandToCType(const QByteArray &waylandType, const QByteArray &interface);
QByteArray waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray);
- const Scanner::WaylandArgument *newIdArgument(const QList<WaylandArgument> &arguments);
+ const Scanner::WaylandArgument *newIdArgument(const std::vector<WaylandArgument> &arguments);
void printEvent(const WaylandEvent &e, bool omitNames = false, bool withResource = false);
void printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent = true);
- void printEnums(const QList<WaylandEnum> &enums);
+ void printEnums(const std::vector<WaylandEnum> &enums);
QByteArray stripInterfaceName(const QByteArray &name);
bool ignoreInterface(const QByteArray &name);
@@ -189,19 +190,22 @@ bool Scanner::boolValue(const QXmlStreamReader &xml, const char *name)
Scanner::WaylandEvent Scanner::readEvent(QXmlStreamReader &xml, bool request)
{
- WaylandEvent event;
- event.request = request;
- event.name = byteArrayValue(xml, "name");
- event.type = byteArrayValue(xml, "type");
+ WaylandEvent event = {
+ .request = request,
+ .name = byteArrayValue(xml, "name"),
+ .type = byteArrayValue(xml, "type"),
+ .arguments = {},
+ };
while (xml.readNextStartElement()) {
if (xml.name() == "arg") {
- WaylandArgument argument;
- argument.name = byteArrayValue(xml, "name");
- argument.type = byteArrayValue(xml, "type");
- argument.interface = byteArrayValue(xml, "interface");
- argument.summary = byteArrayValue(xml, "summary");
- argument.allowNull = boolValue(xml, "allowNull");
- event.arguments << argument;
+ WaylandArgument argument = {
+ .name = byteArrayValue(xml, "name"),
+ .type = byteArrayValue(xml, "type"),
+ .interface = byteArrayValue(xml, "interface"),
+ .summary = byteArrayValue(xml, "summary"),
+ .allowNull = boolValue(xml, "allowNull"),
+ };
+ event.arguments.push_back(std::move(argument));
}
xml.skipCurrentElement();
@@ -211,16 +215,19 @@ Scanner::WaylandEvent Scanner::readEvent(QXmlStreamReader &xml, bool request)
Scanner::WaylandEnum Scanner::readEnum(QXmlStreamReader &xml)
{
- WaylandEnum result;
- result.name = byteArrayValue(xml, "name");
+ WaylandEnum result = {
+ .name = byteArrayValue(xml, "name"),
+ .entries = {},
+ };
while (xml.readNextStartElement()) {
if (xml.name() == "entry") {
- WaylandEnumEntry entry;
- entry.name = byteArrayValue(xml, "name");
- entry.value = byteArrayValue(xml, "value");
- entry.summary = byteArrayValue(xml, "summary");
- result.entries << entry;
+ WaylandEnumEntry entry = {
+ .name = byteArrayValue(xml, "name"),
+ .value = byteArrayValue(xml, "value"),
+ .summary = byteArrayValue(xml, "summary"),
+ };
+ result.entries.push_back(std::move(entry));
}
xml.skipCurrentElement();
@@ -231,17 +238,21 @@ Scanner::WaylandEnum Scanner::readEnum(QXmlStreamReader &xml)
Scanner::WaylandInterface Scanner::readInterface(QXmlStreamReader &xml)
{
- WaylandInterface interface;
- interface.name = byteArrayValue(xml, "name");
- interface.version = intValue(xml, "version", 1);
+ WaylandInterface interface = {
+ .name = byteArrayValue(xml, "name"),
+ .version = intValue(xml, "version", 1),
+ .enums = {},
+ .events = {},
+ .requests = {},
+ };
while (xml.readNextStartElement()) {
if (xml.name() == "event")
- interface.events << readEvent(xml, false);
+ interface.events.push_back(readEvent(xml, false));
else if (xml.name() == "request")
- interface.requests << readEvent(xml, true);
+ interface.requests.push_back(readEvent(xml, true));
else if (xml.name() == "enum")
- interface.enums << readEnum(xml);
+ interface.enums.push_back(readEnum(xml));
else
xml.skipCurrentElement();
}
@@ -283,11 +294,11 @@ QByteArray Scanner::waylandToQtType(const QByteArray &waylandType, const QByteAr
return waylandToCType(waylandType, interface);
}
-const Scanner::WaylandArgument *Scanner::newIdArgument(const QList<WaylandArgument> &arguments)
+const Scanner::WaylandArgument *Scanner::newIdArgument(const std::vector<WaylandArgument> &arguments)
{
- for (int i = 0; i < arguments.size(); ++i) {
- if (arguments.at(i).type == "new_id")
- return &arguments.at(i);
+ for (const WaylandArgument &a : arguments) {
+ if (a.type == "new_id")
+ return &a;
}
return nullptr;
}
@@ -305,8 +316,7 @@ void Scanner::printEvent(const WaylandEvent &e, bool omitNames, bool withResourc
needsComma = true;
}
}
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
bool isNewId = a.type == "new_id";
if (isNewId && !isServerSide() && (a.interface.isEmpty() != e.request))
continue;
@@ -346,9 +356,8 @@ void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *inte
printf(" %svoid *data,\n", indent);
printf(" %sstruct ::%s *object", indent, interfaceName);
}
- for (int i = 0; i < e.arguments.size(); ++i) {
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
- const WaylandArgument &a = e.arguments.at(i);
bool isNewId = a.type == "new_id";
if (isServerSide() && isNewId) {
printf(" %suint32_t %s", indent, a.name.constData());
@@ -360,17 +369,13 @@ void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *inte
printf(")");
}
-void Scanner::printEnums(const QList<WaylandEnum> &enums)
+void Scanner::printEnums(const std::vector<WaylandEnum> &enums)
{
- for (int i = 0; i < enums.size(); ++i) {
+ for (const WaylandEnum &e : enums) {
printf("\n");
- const WaylandEnum &e = enums.at(i);
printf(" enum %s {\n", e.name.constData());
- for (int i = 0; i < e.entries.size(); ++i) {
- const WaylandEnumEntry &entry = e.entries.at(i);
- printf(" %s_%s = %s", e.name.constData(), entry.name.constData(), entry.value.constData());
- if (i < e.entries.size() - 1)
- printf(",");
+ for (const WaylandEnumEntry &entry : e.entries) {
+ printf(" %s_%s = %s,", e.name.constData(), entry.name.constData(), entry.value.constData());
if (!entry.summary.isNull())
printf(" // %s", entry.summary.constData());
printf("\n");
@@ -424,11 +429,11 @@ bool Scanner::process()
//QByteArray preProcessorProtocolName = QByteArray(m_protocolName).replace('-', '_').toUpper();
QByteArray preProcessorProtocolName = QByteArray(m_protocolName).toUpper();
- QList<WaylandInterface> interfaces;
+ std::vector<WaylandInterface> interfaces;
while (m_xml->readNextStartElement()) {
if (m_xml->name() == "interface")
- interfaces << readInterface(*m_xml);
+ interfaces.push_back(readInterface(*m_xml));
else
m_xml->skipCurrentElement();
}
@@ -478,12 +483,16 @@ bool Scanner::process()
printf("\n");
printf("namespace QtWaylandServer {\n");
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+ bool needsNewLine = false;
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
+ if (needsNewLine)
+ printf("\n");
+ needsNewLine = true;
+
const char *interfaceName = interface.name.constData();
QByteArray stripped = stripInterfaceName(interface.name);
@@ -538,11 +547,11 @@ bool Scanner::process()
printEnums(interface.enums);
- bool hasEvents = !interface.events.isEmpty();
+ bool hasEvents = !interface.events.empty();
if (hasEvents) {
printf("\n");
- foreach (const WaylandEvent &e, interface.events) {
+ for (const WaylandEvent &e : interface.events) {
printf(" void send_");
printEvent(e);
printf(";\n");
@@ -559,11 +568,11 @@ bool Scanner::process()
printf(" virtual void %s_bind_resource(Resource *resource);\n", interfaceNameStripped);
printf(" virtual void %s_destroy_resource(Resource *resource);\n", interfaceNameStripped);
- bool hasRequests = !interface.requests.isEmpty();
+ bool hasRequests = !interface.requests.empty();
if (hasRequests) {
printf("\n");
- foreach (const WaylandEvent &e, interface.requests) {
+ for (const WaylandEvent &e : interface.requests) {
printf(" virtual void %s_", interfaceNameStripped);
printEvent(e);
printf(";\n");
@@ -584,8 +593,7 @@ bool Scanner::process()
printf(" static const struct ::%s_interface m_%s_interface;\n", interfaceName, interfaceName);
printf("\n");
- for (int i = 0; i < interface.requests.size(); ++i) {
- const WaylandEvent &e = interface.requests.at(i);
+ for (const WaylandEvent &e : interface.requests) {
printf(" static void ");
printEventHandlerSignature(e, interfaceName);
@@ -603,9 +611,6 @@ bool Scanner::process()
printf(" };\n");
printf(" DisplayDestroyedListener m_displayDestroyedListener;\n");
printf(" };\n");
-
- if (j < interfaces.size() - 1)
- printf("\n");
}
printf("}\n");
@@ -629,8 +634,7 @@ bool Scanner::process()
printf("namespace QtWaylandServer {\n");
bool needsNewLine = false;
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
@@ -778,7 +782,7 @@ bool Scanner::process()
printf(" }\n");
printf("\n");
- bool hasRequests = !interface.requests.isEmpty();
+ bool hasRequests = !interface.requests.empty();
QByteArray interfaceMember = hasRequests ? "&m_" + interface.name + "_interface" : QByteArray("nullptr");
@@ -816,17 +820,18 @@ bool Scanner::process()
if (hasRequests) {
printf("\n");
printf(" const struct ::%s_interface %s::m_%s_interface = {", interfaceName, interfaceName, interfaceName);
- for (int i = 0; i < interface.requests.size(); ++i) {
- if (i > 0)
+ bool needsComma = false;
+ for (const WaylandEvent &e : interface.requests) {
+ if (needsComma)
printf(",");
+ needsComma = true;
printf("\n");
- const WaylandEvent &e = interface.requests.at(i);
printf(" %s::handle_%s", interfaceName, e.name.constData());
}
printf("\n");
printf(" };\n");
- foreach (const WaylandEvent &e, interface.requests) {
+ for (const WaylandEvent &e : interface.requests) {
printf("\n");
printf(" void %s::%s_", interfaceName, interfaceNameStripped);
printEvent(e, true);
@@ -836,11 +841,10 @@ bool Scanner::process()
}
printf("\n");
- for (int i = 0; i < interface.requests.size(); ++i) {
+ for (const WaylandEvent &e : interface.requests) {
printf("\n");
printf(" void %s::", interfaceName);
- const WaylandEvent &e = interface.requests.at(i);
printEventHandlerSignature(e, interfaceName, false);
printf("\n");
@@ -849,9 +853,8 @@ bool Scanner::process()
printf(" Resource *r = Resource::fromResource(resource);\n");
printf(" static_cast<%s *>(r->%s_object)->%s_%s(\n", interfaceName, interfaceNameStripped, interfaceNameStripped, e.name.constData());
printf(" r");
- for (int i = 0; i < e.arguments.size(); ++i) {
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
- const WaylandArgument &a = e.arguments.at(i);
QByteArray cType = waylandToCType(a.type, a.interface);
QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
const char *argumentName = a.name.constData();
@@ -865,17 +868,15 @@ bool Scanner::process()
}
}
- for (int i = 0; i < interface.events.size(); ++i) {
+ for (const WaylandEvent &e : interface.events) {
printf("\n");
- const WaylandEvent &e = interface.events.at(i);
printf(" void %s::send_", interfaceName);
printEvent(e);
printf("\n");
printf(" {\n");
printf(" send_%s(\n", e.name.constData());
printf(" m_resource->handle");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
printf(" %s", a.name.constData());
}
@@ -888,8 +889,7 @@ bool Scanner::process()
printf("\n");
printf(" {\n");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
if (a.type != "array")
continue;
QByteArray array = a.name + "_data";
@@ -905,8 +905,7 @@ bool Scanner::process()
printf(" %s_send_%s(\n", interfaceName, e.name.constData());
printf(" resource");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
QByteArray cType = waylandToCType(a.type, a.interface);
QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
@@ -962,12 +961,17 @@ bool Scanner::process()
}
printf("\n");
printf("namespace QtWayland {\n");
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+
+ bool needsNewLine = false;
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
+ if (needsNewLine)
+ printf("\n");
+ needsNewLine = true;
+
const char *interfaceName = interface.name.constData();
QByteArray stripped = stripInterfaceName(interface.name);
@@ -994,9 +998,9 @@ bool Scanner::process()
printEnums(interface.enums);
- if (!interface.requests.isEmpty()) {
+ if (!interface.requests.empty()) {
printf("\n");
- foreach (const WaylandEvent &e, interface.requests) {
+ for (const WaylandEvent &e : interface.requests) {
const WaylandArgument *new_id = newIdArgument(e.arguments);
QByteArray new_id_str = "void ";
if (new_id) {
@@ -1011,12 +1015,12 @@ bool Scanner::process()
}
}
- bool hasEvents = !interface.events.isEmpty();
+ bool hasEvents = !interface.events.empty();
if (hasEvents) {
printf("\n");
printf(" protected:\n");
- foreach (const WaylandEvent &e, interface.events) {
+ for (const WaylandEvent &e : interface.events) {
printf(" virtual void %s_", interfaceNameStripped);
printEvent(e);
printf(";\n");
@@ -1028,8 +1032,7 @@ bool Scanner::process()
if (hasEvents) {
printf(" void init_listener();\n");
printf(" static const struct %s_listener m_%s_listener;\n", interfaceName, interfaceName);
- for (int i = 0; i < interface.events.size(); ++i) {
- const WaylandEvent &e = interface.events.at(i);
+ for (const WaylandEvent &e : interface.events) {
printf(" static void ");
printEventHandlerSignature(e, interfaceName);
@@ -1038,9 +1041,6 @@ bool Scanner::process()
}
printf(" struct ::%s *m_%s;\n", interfaceName, interfaceName);
printf(" };\n");
-
- if (j < interfaces.size() - 1)
- printf("\n");
}
printf("}\n");
printf("\n");
@@ -1077,18 +1077,23 @@ bool Scanner::process()
printf("#endif\n");
printf("}\n");
printf("\n");
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+
+ bool needsNewLine = false;
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
+ if (needsNewLine)
+ printf("\n");
+ needsNewLine = true;
+
const char *interfaceName = interface.name.constData();
QByteArray stripped = stripInterfaceName(interface.name);
const char *interfaceNameStripped = stripped.constData();
- bool hasEvents = !interface.events.isEmpty();
+ bool hasEvents = !interface.events.empty();
printf(" %s::%s(struct ::wl_registry *registry, int id, int version)\n", interfaceName, interfaceName);
printf(" {\n");
@@ -1152,9 +1157,8 @@ bool Scanner::process()
printf(" return &::%s_interface;\n", interfaceName);
printf(" }\n");
- for (int i = 0; i < interface.requests.size(); ++i) {
+ for (const WaylandEvent &e : interface.requests) {
printf("\n");
- const WaylandEvent &e = interface.requests.at(i);
const WaylandArgument *new_id = newIdArgument(e.arguments);
QByteArray new_id_str = "void ";
if (new_id) {
@@ -1167,8 +1171,7 @@ bool Scanner::process()
printEvent(e);
printf("\n");
printf(" {\n");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
if (a.type != "array")
continue;
QByteArray array = a.name + "_data";
@@ -1180,12 +1183,11 @@ bool Scanner::process()
printf(" %s.alloc = 0;\n", arrayName);
printf("\n");
}
- int actualArgumentCount = new_id ? e.arguments.size() - 1 : e.arguments.size();
+ int actualArgumentCount = new_id ? int(e.arguments.size()) - 1 : int(e.arguments.size());
printf(" %s%s_%s(\n", new_id ? "return " : "", interfaceName, e.name.constData());
printf(" m_%s%s", interfaceName, actualArgumentCount > 0 ? "," : "");
bool needsComma = false;
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
bool isNewId = a.type == "new_id";
if (isNewId && !a.interface.isEmpty())
continue;
@@ -1215,8 +1217,7 @@ bool Scanner::process()
if (hasEvents) {
printf("\n");
- for (int i = 0; i < interface.events.size(); ++i) {
- const WaylandEvent &e = interface.events.at(i);
+ for (const WaylandEvent &e : interface.events) {
printf(" void %s::%s_", interfaceName, interfaceNameStripped);
printEvent(e, true);
printf("\n");
@@ -1229,17 +1230,17 @@ bool Scanner::process()
printf(" {\n");
printf(" Q_UNUSED(object);\n");
printf(" static_cast<%s *>(data)->%s_%s(", interfaceName, interfaceNameStripped, e.name.constData());
- for (int i = 0; i < e.arguments.size(); ++i) {
+ bool needsComma = false;
+ for (const WaylandArgument &a : e.arguments) {
+ if (needsComma)
+ printf(",");
+ needsComma = true;
printf("\n");
- const WaylandArgument &a = e.arguments.at(i);
const char *argumentName = a.name.constData();
if (a.type == "string")
printf(" QString::fromUtf8(%s)", argumentName);
else
printf(" %s", argumentName);
-
- if (i < e.arguments.size() - 1)
- printf(",");
}
printf(");\n");
@@ -1247,9 +1248,8 @@ bool Scanner::process()
printf("\n");
}
printf(" const struct %s_listener %s::m_%s_listener = {\n", interfaceName, interfaceName, interfaceName);
- for (int i = 0; i < interface.events.size(); ++i) {
- const WaylandEvent &e = interface.events.at(i);
- printf(" %s::handle_%s%s\n", interfaceName, e.name.constData(), i < interface.events.size() - 1 ? "," : "");
+ for (const WaylandEvent &e : interface.events) {
+ printf(" %s::handle_%s,\n", interfaceName, e.name.constData());
}
printf(" };\n");
printf("\n");
@@ -1259,9 +1259,6 @@ bool Scanner::process()
printf(" %s_add_listener(m_%s, &m_%s_listener, this);\n", interfaceName, interfaceName, interfaceName);
printf(" }\n");
}
-
- if (j < interfaces.size() - 1)
- printf("\n");
}
printf("}\n");
printf("\n");
diff --git a/src/shared/qwaylandinputmethodeventbuilder.cpp b/src/shared/qwaylandinputmethodeventbuilder.cpp
index 88056637d..526d0ef46 100644
--- a/src/shared/qwaylandinputmethodeventbuilder.cpp
+++ b/src/shared/qwaylandinputmethodeventbuilder.cpp
@@ -157,7 +157,7 @@ QInputMethodEvent QWaylandInputMethodEventBuilder::buildPreedit(const QString &t
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant()));
}
- Q_FOREACH (const QInputMethodEvent::Attribute &attr, m_preeditStyles) {
+ for (const QInputMethodEvent::Attribute &attr : qAsConst(m_preeditStyles)) {
int start = indexFromWayland(text, attr.start);
int length = indexFromWayland(text, attr.start + attr.length) - start;
attributes.append(QInputMethodEvent::Attribute(attr.type, start, length, attr.value));
diff --git a/src/src.pro b/src/src.pro
index d4244de33..3d68c69fb 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -3,21 +3,22 @@ include($$OUT_PWD/client/qtwaylandclient-config.pri)
include($$OUT_PWD/compositor/qtwaylandcompositor-config.pri)
QT_FOR_CONFIG += waylandclient-private waylandcompositor-private
-qtConfig(wayland-client) {
+qtConfig(wayland-client)|qtConfig(wayland-server) {
sub_qtwaylandscanner.subdir = qtwaylandscanner
sub_qtwaylandscanner.target = sub-qtwaylandscanner
SUBDIRS += sub_qtwaylandscanner
- sub_client.subdir = client
- sub_client.depends = sub-qtwaylandscanner
- sub_client.target = sub-client
- SUBDIRS += sub_client
+ qtConfig(wayland-client) {
+ sub_client.subdir = client
+ sub_client.depends = sub-qtwaylandscanner
+ sub_client.target = sub-client
+ SUBDIRS += sub_client
+ }
sub_plugins.subdir = plugins
- sub_plugins.depends += sub-qtwaylandscanner sub-client
- qtConfig(wayland-server) {
- sub_plugins.depends += sub-compositor
- }
+ sub_plugins.depends += sub-qtwaylandscanner
+ qtConfig(wayland-client):sub_plugins.depends += sub-client
+ qtConfig(wayland-server):sub_plugins.depends += sub-compositor
sub_plugins.target = sub-plugins
SUBDIRS += sub_plugins
@@ -26,10 +27,11 @@ qtConfig(wayland-client) {
sub_compositor.depends = sub-qtwaylandscanner
sub_compositor.target = sub-compositor
SUBDIRS += sub_compositor
-
- sub_imports.subdir = imports
- sub_imports.depends += sub-compositor sub-client
- sub_imports.target = sub-imports
- SUBDIRS += sub_imports
}
+
+ sub_imports.subdir = imports
+ qtConfig(wayland-client):sub_imports.depends += sub-client
+ qtConfig(wayland-server):sub_imports.depends += sub-compositor
+ sub_imports.target = sub-imports
+ SUBDIRS += sub_imports
}