summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/protocol/qt_attribution.json18
-rw-r--r--src/3rdparty/protocol/tablet-unstable-v2.xml1178
-rw-r--r--src/client/client.pro17
-rw-r--r--src/client/configure.json108
-rw-r--r--src/client/qwaylanddatadevice.cpp16
-rw-r--r--src/client/qwaylanddisplay.cpp25
-rw-r--r--src/client/qwaylanddisplay_p.h7
-rw-r--r--src/client/qwaylandinputdevice.cpp46
-rw-r--r--src/client/qwaylandinputdevice_p.h26
-rw-r--r--src/client/qwaylandintegration.cpp69
-rw-r--r--src/client/qwaylandintegration_p.h4
-rw-r--r--src/client/qwaylandnativeinterface.cpp12
-rw-r--r--src/client/qwaylandscreen.cpp13
-rw-r--r--src/client/qwaylandscreen_p.h1
-rw-r--r--src/client/qwaylandshmbackingstore.cpp4
-rw-r--r--src/client/qwaylandshmbackingstore_p.h2
-rw-r--r--src/client/qwaylandshmwindow.cpp4
-rw-r--r--src/client/qwaylandshmwindow_p.h2
-rw-r--r--src/client/qwaylandsurface.cpp8
-rw-r--r--src/client/qwaylandtabletv2.cpp332
-rw-r--r--src/client/qwaylandtabletv2_p.h191
-rw-r--r--src/client/qwaylandtouch.cpp16
-rw-r--r--src/client/qwaylandvulkaninstance.cpp132
-rw-r--r--src/client/qwaylandvulkaninstance_p.h80
-rw-r--r--src/client/qwaylandvulkanwindow.cpp84
-rw-r--r--src/client/qwaylandvulkanwindow_p.h68
-rw-r--r--src/client/qwaylandwindow.cpp69
-rw-r--r--src/client/qwaylandwindow_p.h10
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp4
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp5
-rw-r--r--src/compositor/configure.json122
-rw-r--r--src/compositor/extensions/qwaylandxdgshell.cpp6
-rw-r--r--src/compositor/extensions/qwaylandxdgshell_p.h4
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6.cpp6
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6_p.h4
-rw-r--r--src/compositor/extensions/qwltexturesharingextension.cpp4
-rw-r--r--src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp2
-rw-r--r--src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp4
-rw-r--r--src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h2
-rw-r--r--src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp2
-rw-r--r--src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxwindow.cpp2
-rw-r--r--src/plugins/hardwareintegration/compositor/brcm-egl/brcm-egl.pro2
-rw-r--r--src/plugins/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pro4
-rw-r--r--src/plugins/hardwareintegration/compositor/drm-egl-server/drm-egl-server.pro4
-rw-r--r--src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro4
-rw-r--r--src/plugins/hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pro4
-rw-r--r--src/plugins/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pro2
-rw-r--r--src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro4
-rw-r--r--src/plugins/hardwareintegration/compositor/vulkan-server/vulkan-server.pro4
-rw-r--r--src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro2
-rw-r--r--src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro2
-rw-r--r--src/plugins/hardwareintegration/compositor/xcomposite-egl/xcomposite-egl.pro2
-rw-r--r--src/plugins/hardwareintegration/compositor/xcomposite-glx/xcomposite-glx.pro2
-rw-r--r--src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp5
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp60
55 files changed, 2619 insertions, 191 deletions
diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json
index c49ead4f3..dad8c4256 100644
--- a/src/3rdparty/protocol/qt_attribution.json
+++ b/src/3rdparty/protocol/qt_attribution.json
@@ -90,6 +90,24 @@ Copyright (c) 2013 BMW Car IT GmbH"
},
{
+ "Id": "wayland-tablet-protocol",
+ "Name": "Wayland Tablet Protocol",
+ "QDocModule": "qtwaylandcompositor",
+ "QtUsage": "Used in the Qt Wayland platform plugin",
+ "Files": "tablet-unstable-v2.xml",
+
+ "Description": "",
+ "Homepage": "https://wayland.freedesktop.org",
+ "Version": "unstable v2, version 1",
+ "DownloadLocation": "https://cgit.freedesktop.org/wayland/wayland-protocols/plain/unstable/tablet/tablet-unstable-v2.xml",
+ "LicenseId": "MIT",
+ "License": "MIT License",
+ "LicenseFile": "MIT_LICENSE.txt",
+ "Copyright": "Copyright 2014 © Stephen "Lyude" Chandler Paul
+Copyright 2015-2016 © Red Hat, Inc."
+ },
+
+ {
"Id": "wayland-viewporter-protocol",
"Name": "Wayland Viewporter Protocol",
"QDocModule": "qtwaylandcompositor",
diff --git a/src/3rdparty/protocol/tablet-unstable-v2.xml b/src/3rdparty/protocol/tablet-unstable-v2.xml
new file mode 100644
index 000000000..b286d964a
--- /dev/null
+++ b/src/3rdparty/protocol/tablet-unstable-v2.xml
@@ -0,0 +1,1178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="tablet_unstable_v2">
+
+ <copyright>
+ Copyright 2014 © Stephen "Lyude" Chandler Paul
+ Copyright 2015-2016 © Red Hat, Inc.
+
+ 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="Wayland protocol for graphics tablets">
+ This description provides a high-level overview of the interplay between
+ the interfaces defined this protocol. For details, see the protocol
+ specification.
+
+ More than one tablet may exist, and device-specifics matter. Tablets are
+ not represented by a single virtual device like wl_pointer. A client
+ binds to the tablet manager object which is just a proxy object. From
+ that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)
+ and that returns the actual interface that has all the tablets. With
+ this indirection, we can avoid merging wp_tablet into the actual Wayland
+ protocol, a long-term benefit.
+
+ The wp_tablet_seat sends a "tablet added" event for each tablet
+ connected. That event is followed by descriptive events about the
+ hardware; currently that includes events for name, vid/pid and
+ a wp_tablet.path event that describes a local path. This path can be
+ used to uniquely identify a tablet or get more information through
+ libwacom. Emulated or nested tablets can skip any of those, e.g. a
+ virtual tablet may not have a vid/pid. The sequence of descriptive
+ events is terminated by a wp_tablet.done event to signal that a client
+ may now finalize any initialization for that tablet.
+
+ Events from tablets require a tool in proximity. Tools are also managed
+ by the tablet seat; a "tool added" event is sent whenever a tool is new
+ to the compositor. That event is followed by a number of descriptive
+ events about the hardware; currently that includes capabilities,
+ hardware id and serial number, and tool type. Similar to the tablet
+ interface, a wp_tablet_tool.done event is sent to terminate that initial
+ sequence.
+
+ Any event from a tool happens on the wp_tablet_tool interface. When the
+ tool gets into proximity of the tablet, a proximity_in event is sent on
+ the wp_tablet_tool interface, listing the tablet and the surface. That
+ event is followed by a motion event with the coordinates. After that,
+ it's the usual motion, axis, button, etc. events. The protocol's
+ serialisation means events are grouped by wp_tablet_tool.frame events.
+
+ Two special events (that don't exist in X) are down and up. They signal
+ "tip touching the surface". For tablets without real proximity
+ detection, the sequence is: proximity_in, motion, down, frame.
+
+ When the tool leaves proximity, a proximity_out event is sent. If any
+ button is still down, a button release event is sent before this
+ proximity event. These button events are sent in the same frame as the
+ proximity event to signal to the client that the buttons were held when
+ the tool left proximity.
+
+ If the tool moves out of the surface but stays in proximity (i.e.
+ between windows), compositor-specific grab policies apply. This usually
+ means that the proximity-out is delayed until all buttons are released.
+
+ Moving a tool physically from one tablet to the other has no real effect
+ on the protocol, since we already have the tool object from the "tool
+ added" event. All the information is already there and the proximity
+ events on both tablets are all a client needs to reconstruct what
+ happened.
+
+ Some extra axes are normalized, i.e. the client knows the range as
+ specified in the protocol (e.g. [0, 65535]), the granularity however is
+ unknown. The current normalized axes are pressure, distance, and slider.
+
+ Other extra axes are in physical units as specified in the protocol.
+ The current extra axes with physical units are tilt, rotation and
+ wheel rotation.
+
+ Since tablets work independently of the pointer controlled by the mouse,
+ the focus handling is independent too and controlled by proximity.
+ The wp_tablet_tool.set_cursor request sets a tool-specific cursor.
+ This cursor surface may be the same as the mouse cursor, and it may be
+ the same across tools but it is possible to be more fine-grained. For
+ example, a client may set different cursors for the pen and eraser.
+
+ Tools are generally independent of tablets and it is
+ compositor-specific policy when a tool can be removed. Common approaches
+ will likely include some form of removing a tool when all tablets the
+ tool was used on are removed.
+
+ 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>
+
+ <interface name="zwp_tablet_manager_v2" version="1">
+ <description summary="controller object for graphic tablet devices">
+ An object that provides access to the graphics tablets available on this
+ system. All tablets are associated with a seat, to get access to the
+ actual tablets, use wp_tablet_manager.get_tablet_seat.
+ </description>
+
+ <request name="get_tablet_seat">
+ <description summary="get the tablet seat">
+ Get the wp_tablet_seat object for the given seat. This object
+ provides access to all graphics tablets in this seat.
+ </description>
+ <arg name="tablet_seat" type="new_id" interface="zwp_tablet_seat_v2"/>
+ <arg name="seat" type="object" interface="wl_seat" summary="The wl_seat object to retrieve the tablets for" />
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="release the memory for the tablet manager object">
+ Destroy the wp_tablet_manager object. Objects created from this
+ object are unaffected and should be destroyed separately.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwp_tablet_seat_v2" version="1">
+ <description summary="controller object for graphic tablet devices of a seat">
+ An object that provides access to the graphics tablets available on this
+ seat. After binding to this interface, the compositor sends a set of
+ wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="release the memory for the tablet seat object">
+ Destroy the wp_tablet_seat object. Objects created from this
+ object are unaffected and should be destroyed separately.
+ </description>
+ </request>
+
+ <event name="tablet_added">
+ <description summary="new device notification">
+ This event is sent whenever a new tablet becomes available on this
+ seat. This event only provides the object id of the tablet, any
+ static information about the tablet (device name, vid/pid, etc.) is
+ sent through the wp_tablet interface.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_tablet_v2" summary="the newly added graphics tablet"/>
+ </event>
+
+ <event name="tool_added">
+ <description summary="a new tool has been used with a tablet">
+ This event is sent whenever a tool that has not previously been used
+ with a tablet comes into use. This event only provides the object id
+ of the tool; any static information about the tool (capabilities,
+ type, etc.) is sent through the wp_tablet_tool interface.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_tablet_tool_v2" summary="the newly added tablet tool"/>
+ </event>
+
+ <event name="pad_added">
+ <description summary="new pad notification">
+ This event is sent whenever a new pad is known to the system. Typically,
+ pads are physically attached to tablets and a pad_added event is
+ sent immediately after the wp_tablet_seat.tablet_added.
+ However, some standalone pad devices logically attach to tablets at
+ runtime, and the client must wait for wp_tablet_pad.enter to know
+ the tablet a pad is attached to.
+
+ This event only provides the object id of the pad. All further
+ features (buttons, strips, rings) are sent through the wp_tablet_pad
+ interface.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_tablet_pad_v2" summary="the newly added pad"/>
+ </event>
+ </interface>
+
+ <interface name="zwp_tablet_tool_v2" version="1">
+ <description summary="a physical tablet tool">
+ An object that represents a physical tool that has been, or is
+ currently in use with a tablet in this seat. Each wp_tablet_tool
+ object stays valid until the client destroys it; the compositor
+ reuses the wp_tablet_tool object to indicate that the object's
+ respective physical tool has come into proximity of a tablet again.
+
+ A wp_tablet_tool object's relation to a physical tool depends on the
+ tablet's ability to report serial numbers. If the tablet supports
+ this capability, then the object represents a specific physical tool
+ and can be identified even when used on multiple tablets.
+
+ A tablet tool has a number of static characteristics, e.g. tool type,
+ hardware_serial and capabilities. These capabilities are sent in an
+ event sequence after the wp_tablet_seat.tool_added event before any
+ actual events from this tool. This initial event sequence is
+ terminated by a wp_tablet_tool.done event.
+
+ Tablet tool events are grouped by wp_tablet_tool.frame events.
+ Any events received before a wp_tablet_tool.frame event should be
+ considered part of the same hardware state change.
+ </description>
+
+ <request name="set_cursor">
+ <description summary="set the tablet tool's surface">
+ Sets the surface of the cursor used for this tool on the given
+ tablet. This request only takes effect if the tool is in proximity
+ of one of the requesting client's surfaces or the surface parameter
+ is the current pointer surface. If there was a previous surface set
+ with this request it is replaced. If surface is NULL, the cursor
+ image is hidden.
+
+ The parameters hotspot_x and hotspot_y define the position of the
+ pointer surface relative to the pointer location. Its top-left corner
+ is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the
+ coordinates of the pointer location, in surface-local coordinates.
+
+ On surface.attach requests to the pointer surface, hotspot_x and
+ hotspot_y are decremented by the x and y parameters passed to the
+ request. Attach must be confirmed by wl_surface.commit as usual.
+
+ The hotspot can also be updated by passing the currently set pointer
+ surface to this request with new values for hotspot_x and hotspot_y.
+
+ The current and pending input regions of the wl_surface are cleared,
+ and wl_surface.set_input_region is ignored until the wl_surface is no
+ longer used as the cursor. When the use as a cursor ends, the current
+ and pending input regions become undefined, and the wl_surface is
+ unmapped.
+
+ This request gives the surface the role of a wp_tablet_tool cursor. A
+ surface may only ever be used as the cursor surface for one
+ wp_tablet_tool. If the surface already has another role or has
+ previously been used as cursor surface for a different tool, a
+ protocol error is raised.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the enter event"/>
+ <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
+ <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
+ <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the tool object">
+ This destroys the client's resource for this tool object.
+ </description>
+ </request>
+
+ <enum name="type">
+ <description summary="a physical tool type">
+ Describes the physical type of a tool. The physical type of a tool
+ generally defines its base usage.
+
+ The mouse tool represents a mouse-shaped tool that is not a relative
+ device but bound to the tablet's surface, providing absolute
+ coordinates.
+
+ The lens tool is a mouse-shaped tool with an attached lens to
+ provide precision focus.
+ </description>
+ <entry name="pen" value="0x140" summary="Pen"/>
+ <entry name="eraser" value="0x141" summary="Eraser"/>
+ <entry name="brush" value="0x142" summary="Brush"/>
+ <entry name="pencil" value="0x143" summary="Pencil"/>
+ <entry name="airbrush" value="0x144" summary="Airbrush"/>
+ <entry name="finger" value="0x145" summary="Finger"/>
+ <entry name="mouse" value="0x146" summary="Mouse"/>
+ <entry name="lens" value="0x147" summary="Lens"/>
+ </enum>
+
+ <event name="type">
+ <description summary="tool type">
+ The tool type is the high-level type of the tool and usually decides
+ the interaction expected from this tool.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+ </description>
+ <arg name="tool_type" type="uint" enum="type" summary="the physical tool type"/>
+ </event>
+
+ <event name="hardware_serial">
+ <description summary="unique hardware serial number of the tool">
+ If the physical tool can be identified by a unique 64-bit serial
+ number, this event notifies the client of this serial number.
+
+ If multiple tablets are available in the same seat and the tool is
+ uniquely identifiable by the serial number, that tool may move
+ between tablets.
+
+ Otherwise, if the tool has no serial number and this event is
+ missing, the tool is tied to the tablet it first comes into
+ proximity with. Even if the physical tool is used on multiple
+ tablets, separate wp_tablet_tool objects will be created, one per
+ tablet.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+ </description>
+ <arg name="hardware_serial_hi" type="uint" summary="the unique serial number of the tool, most significant bits"/>
+ <arg name="hardware_serial_lo" type="uint" summary="the unique serial number of the tool, least significant bits"/>
+ </event>
+
+ <event name="hardware_id_wacom">
+ <description summary="hardware id notification in Wacom's format">
+ This event notifies the client of a hardware id available on this tool.
+
+ The hardware id is a device-specific 64-bit id that provides extra
+ information about the tool in use, beyond the wl_tool.type
+ enumeration. The format of the id is specific to tablets made by
+ Wacom Inc. For example, the hardware id of a Wacom Grip
+ Pen (a stylus) is 0x802.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+ </description>
+ <arg name="hardware_id_hi" type="uint" summary="the hardware id, most significant bits"/>
+ <arg name="hardware_id_lo" type="uint" summary="the hardware id, least significant bits"/>
+ </event>
+
+ <enum name="capability">
+ <description summary="capability flags for a tool">
+ Describes extra capabilities on a tablet.
+
+ Any tool must provide x and y values, extra axes are
+ device-specific.
+ </description>
+ <entry name="tilt" value="1" summary="Tilt axes"/>
+ <entry name="pressure" value="2" summary="Pressure axis"/>
+ <entry name="distance" value="3" summary="Distance axis"/>
+ <entry name="rotation" value="4" summary="Z-rotation axis"/>
+ <entry name="slider" value="5" summary="Slider axis"/>
+ <entry name="wheel" value="6" summary="Wheel axis"/>
+ </enum>
+
+ <event name="capability">
+ <description summary="tool capability notification">
+ This event notifies the client of any capabilities of this tool,
+ beyond the main set of x/y axes and tip up/down detection.
+
+ One event is sent for each extra capability available on this tool.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+ </description>
+ <arg name="capability" type="uint" enum="capability" summary="the capability"/>
+ </event>
+
+ <event name="done">
+ <description summary="tool description events sequence complete">
+ This event signals the end of the initial burst of descriptive
+ events. A client may consider the static description of the tool to
+ be complete and finalize initialization of the tool.
+ </description>
+ </event>
+
+ <event name="removed">
+ <description summary="tool removed">
+ This event is sent when the tool is removed from the system and will
+ send no further events. Should the physical tool come back into
+ proximity later, a new wp_tablet_tool object will be created.
+
+ It is compositor-dependent when a tool is removed. A compositor may
+ remove a tool on proximity out, tablet removal or any other reason.
+ A compositor may also keep a tool alive until shutdown.
+
+ If the tool is currently in proximity, a proximity_out event will be
+ sent before the removed event. See wp_tablet_tool.proximity_out for
+ the handling of any buttons logically down.
+
+ When this event is received, the client must wp_tablet_tool.destroy
+ the object.
+ </description>
+ </event>
+
+ <event name="proximity_in">
+ <description summary="proximity in event">
+ Notification that this tool is focused on a certain surface.
+
+ This event can be received when the tool has moved from one surface to
+ another, or when the tool has come back into proximity above the
+ surface.
+
+ If any button is logically down when the tool comes into proximity,
+ the respective button event is sent after the proximity_in event but
+ within the same frame as the proximity_in event.
+ </description>
+ <arg name="serial" type="uint"/>
+ <arg name="tablet" type="object" interface="zwp_tablet_v2" summary="The tablet the tool is in proximity of"/>
+ <arg name="surface" type="object" interface="wl_surface" summary="The current surface the tablet tool is over"/>
+ </event>
+
+ <event name="proximity_out">
+ <description summary="proximity out event">
+ Notification that this tool has either left proximity, or is no
+ longer focused on a certain surface.
+
+ When the tablet tool leaves proximity of the tablet, button release
+ events are sent for each button that was held down at the time of
+ leaving proximity. These events are sent before the proximity_out
+ event but within the same wp_tablet.frame.
+
+ If the tool stays within proximity of the tablet, but the focus
+ changes from one surface to another, a button release event may not
+ be sent until the button is actually released or the tool leaves the
+ proximity of the tablet.
+ </description>
+ </event>
+
+ <event name="down">
+ <description summary="tablet tool is making contact">
+ Sent whenever the tablet tool comes in contact with the surface of the
+ tablet.
+
+ If the tool is already in contact with the tablet when entering the
+ input region, the client owning said region will receive a
+ wp_tablet.proximity_in event, followed by a wp_tablet.down
+ event and a wp_tablet.frame event.
+
+ Note that this event describes logical contact, not physical
+ contact. On some devices, a compositor may not consider a tool in
+ logical contact until a minimum physical pressure threshold is
+ exceeded.
+ </description>
+ <arg name="serial" type="uint"/>
+ </event>
+
+ <event name="up">
+ <description summary="tablet tool is no longer making contact">
+ Sent whenever the tablet tool stops making contact with the surface of
+ the tablet, or when the tablet tool moves out of the input region
+ and the compositor grab (if any) is dismissed.
+
+ If the tablet tool moves out of the input region while in contact
+ with the surface of the tablet and the compositor does not have an
+ ongoing grab on the surface, the client owning said region will
+ receive a wp_tablet.up event, followed by a wp_tablet.proximity_out
+ event and a wp_tablet.frame event. If the compositor has an ongoing
+ grab on this device, this event sequence is sent whenever the grab
+ is dismissed in the future.
+
+ Note that this event describes logical contact, not physical
+ contact. On some devices, a compositor may not consider a tool out
+ of logical contact until physical pressure falls below a specific
+ threshold.
+ </description>
+ </event>
+
+ <event name="motion">
+ <description summary="motion event">
+ Sent whenever a tablet tool moves.
+ </description>
+ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
+ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
+ </event>
+
+ <event name="pressure">
+ <description summary="pressure change event">
+ Sent whenever the pressure axis on a tool changes. The value of this
+ event is normalized to a value between 0 and 65535.
+
+ Note that pressure may be nonzero even when a tool is not in logical
+ contact. See the down and up events for more details.
+ </description>
+ <arg name="pressure" type="uint" summary="The current pressure value"/>
+ </event>
+
+ <event name="distance">
+ <description summary="distance change event">
+ Sent whenever the distance axis on a tool changes. The value of this
+ event is normalized to a value between 0 and 65535.
+
+ Note that distance may be nonzero even when a tool is not in logical
+ contact. See the down and up events for more details.
+ </description>
+ <arg name="distance" type="uint" summary="The current distance value"/>
+ </event>
+
+ <event name="tilt">
+ <description summary="tilt change event">
+ Sent whenever one or both of the tilt axes on a tool change. Each tilt
+ value is in degrees, relative to the z-axis of the tablet.
+ The angle is positive when the top of a tool tilts along the
+ positive x or y axis.
+ </description>
+ <arg name="tilt_x" type="fixed" summary="The current value of the X tilt axis"/>
+ <arg name="tilt_y" type="fixed" summary="The current value of the Y tilt axis"/>
+ </event>
+
+ <event name="rotation">
+ <description summary="z-rotation change event">
+ Sent whenever the z-rotation axis on the tool changes. The
+ rotation value is in degrees clockwise from the tool's
+ logical neutral position.
+ </description>
+ <arg name="degrees" type="fixed" summary="The current rotation of the Z axis"/>
+ </event>
+
+ <event name="slider">
+ <description summary="Slider position change event">
+ Sent whenever the slider position on the tool changes. The
+ value is normalized between -65535 and 65535, with 0 as the logical
+ neutral position of the slider.
+
+ The slider is available on e.g. the Wacom Airbrush tool.
+ </description>
+ <arg name="position" type="int" summary="The current position of slider"/>
+ </event>
+
+ <event name="wheel">
+ <description summary="Wheel delta event">
+ Sent whenever the wheel on the tool emits an event. This event
+ contains two values for the same axis change. The degrees value is
+ in the same orientation as the wl_pointer.vertical_scroll axis. The
+ clicks value is in discrete logical clicks of the mouse wheel. This
+ value may be zero if the movement of the wheel was less
+ than one logical click.
+
+ Clients should choose either value and avoid mixing degrees and
+ clicks. The compositor may accumulate values smaller than a logical
+ click and emulate click events when a certain threshold is met.
+ Thus, wl_tablet_tool.wheel events with non-zero clicks values may
+ have different degrees values.
+ </description>
+ <arg name="degrees" type="fixed" summary="The wheel delta in degrees"/>
+ <arg name="clicks" type="int" summary="The wheel delta in discrete clicks"/>
+ </event>
+
+ <enum name="button_state">
+ <description summary="physical button state">
+ Describes the physical state of a button that produced the button event.
+ </description>
+ <entry name="released" value="0" summary="button is not pressed"/>
+ <entry name="pressed" value="1" summary="button is pressed"/>
+ </enum>
+
+ <event name="button">
+ <description summary="button event">
+ Sent whenever a button on the tool is pressed or released.
+
+ If a button is held down when the tool moves in or out of proximity,
+ button events are generated by the compositor. See
+ wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for
+ details.
+ </description>
+ <arg name="serial" type="uint"/>
+ <arg name="button" type="uint" summary="The button whose state has changed"/>
+ <arg name="state" type="uint" enum="button_state" summary="Whether the button was pressed or released"/>
+ </event>
+
+ <event name="frame">
+ <description summary="frame event">
+ Marks the end of a series of axis and/or button updates from the
+ tablet. The Wayland protocol requires axis updates to be sent
+ sequentially, however all events within a frame should be considered
+ one hardware event.
+ </description>
+ <arg name="time" type="uint" summary="The time of the event with millisecond granularity"/>
+ </event>
+
+ <enum name="error">
+ <entry name="role" value="0" summary="given wl_surface has another role"/>
+ </enum>
+ </interface>
+
+ <interface name="zwp_tablet_v2" version="1">
+ <description summary="graphics tablet device">
+ The wp_tablet interface represents one graphics tablet device. The
+ tablet interface itself does not generate events; all events are
+ generated by wp_tablet_tool objects when in proximity above a tablet.
+
+ A tablet has a number of static characteristics, e.g. device name and
+ pid/vid. These capabilities are sent in an event sequence after the
+ wp_tablet_seat.tablet_added event. This initial event sequence is
+ terminated by a wp_tablet.done event.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the tablet object">
+ This destroys the client's resource for this tablet object.
+ </description>
+ </request>
+
+ <event name="name">
+ <description summary="tablet device name">
+ This event is sent in the initial burst of events before the
+ wp_tablet.done event.
+ </description>
+ <arg name="name" type="string" summary="the device name"/>
+ </event>
+
+ <event name="id">
+ <description summary="tablet device USB vendor/product id">
+ This event is sent in the initial burst of events before the
+ wp_tablet.done event.
+ </description>
+ <arg name="vid" type="uint" summary="USB vendor id"/>
+ <arg name="pid" type="uint" summary="USB product id"/>
+ </event>
+
+ <event name="path">
+ <description summary="path to the device">
+ A system-specific device path that indicates which device is behind
+ this wp_tablet. This information may be used to gather additional
+ information about the device, e.g. through libwacom.
+
+ A device may have more than one device path. If so, multiple
+ wp_tablet.path events are sent. A device may be emulated and not
+ have a device path, and in that case this event will not be sent.
+
+ The format of the path is unspecified, it may be a device node, a
+ sysfs path, or some other identifier. It is up to the client to
+ identify the string provided.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet.done event.
+ </description>
+ <arg name="path" type="string" summary="path to local device"/>
+ </event>
+
+ <event name="done">
+ <description summary="tablet description events sequence complete">
+ This event is sent immediately to signal the end of the initial
+ burst of descriptive events. A client may consider the static
+ description of the tablet to be complete and finalize initialization
+ of the tablet.
+ </description>
+ </event>
+
+ <event name="removed">
+ <description summary="tablet removed event">
+ Sent when the tablet has been removed from the system. When a tablet
+ is removed, some tools may be removed.
+
+ When this event is received, the client must wp_tablet.destroy
+ the object.
+ </description>
+ </event>
+ </interface>
+
+ <interface name="zwp_tablet_pad_ring_v2" version="1">
+ <description summary="pad ring">
+ A circular interaction area, such as the touch ring on the Wacom Intuos
+ Pro series tablets.
+
+ Events on a ring are logically grouped by the wl_tablet_pad_ring.frame
+ event.
+ </description>
+
+ <request name="set_feedback">
+ <description summary="set compositor feedback">
+ Request that the compositor use the provided feedback string
+ associated with this ring. This request should be issued immediately
+ after a wp_tablet_pad_group.mode_switch event from the corresponding
+ group is received, or whenever the ring is mapped to a different
+ action. See wp_tablet_pad_group.mode_switch for more details.
+
+ Clients are encouraged to provide context-aware descriptions for
+ the actions associated with the ring; compositors may use this
+ information to offer visual feedback about the button layout
+ (eg. on-screen displays).
+
+ The provided string 'description' is a UTF-8 encoded string to be
+ associated with this ring, and is considered user-visible; general
+ internationalization rules apply.
+
+ The serial argument will be that of the last
+ wp_tablet_pad_group.mode_switch event received for the group of this
+ ring. Requests providing other serials than the most recent one will be
+ ignored.
+ </description>
+ <arg name="description" type="string" summary="ring description"/>
+ <arg name="serial" type="uint" summary="serial of the mode switch event"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the ring object">
+ This destroys the client's resource for this ring object.
+ </description>
+ </request>
+
+ <enum name="source">
+ <description summary="ring axis source">
+ Describes the source types for ring events. This indicates to the
+ client how a ring event was physically generated; a client may
+ adjust the user interface accordingly. For example, events
+ from a "finger" source may trigger kinetic scrolling.
+ </description>
+ <entry name="finger" value="1" summary="finger"/>
+ </enum>
+
+ <event name="source">
+ <description summary="ring event source">
+ Source information for ring events.
+
+ This event does not occur on its own. It is sent before a
+ wp_tablet_pad_ring.frame event and carries the source information
+ for all events within that frame.
+
+ The source specifies how this event was generated. If the source is
+ wp_tablet_pad_ring.source.finger, a wp_tablet_pad_ring.stop event
+ will be sent when the user lifts the finger off the device.
+
+ This event is optional. If the source is unknown for an interaction,
+ no event is sent.
+ </description>
+ <arg name="source" type="uint" enum="source" summary="the event source"/>
+ </event>
+
+ <event name="angle">
+ <description summary="angle changed">
+ Sent whenever the angle on a ring changes.
+
+ The angle is provided in degrees clockwise from the logical
+ north of the ring in the pad's current rotation.
+ </description>
+ <arg name="degrees" type="fixed" summary="the current angle in degrees"/>
+ </event>
+
+ <event name="stop">
+ <description summary="interaction stopped">
+ Stop notification for ring events.
+
+ For some wp_tablet_pad_ring.source types, a wp_tablet_pad_ring.stop
+ event is sent to notify a client that the interaction with the ring
+ has terminated. This enables the client to implement kinetic scrolling.
+ See the wp_tablet_pad_ring.source documentation for information on
+ when this event may be generated.
+
+ Any wp_tablet_pad_ring.angle events with the same source after this
+ event should be considered as the start of a new interaction.
+ </description>
+ </event>
+
+ <event name="frame">
+ <description summary="end of a ring event sequence">
+ Indicates the end of a set of ring events that logically belong
+ together. A client is expected to accumulate the data in all events
+ within the frame before proceeding.
+
+ All wp_tablet_pad_ring events before a wp_tablet_pad_ring.frame event belong
+ logically together. For example, on termination of a finger interaction
+ on a ring the compositor will send a wp_tablet_pad_ring.source event,
+ a wp_tablet_pad_ring.stop event and a wp_tablet_pad_ring.frame event.
+
+ A wp_tablet_pad_ring.frame event is sent for every logical event
+ group, even if the group only contains a single wp_tablet_pad_ring
+ event. Specifically, a client may get a sequence: angle, frame,
+ angle, frame, etc.
+ </description>
+ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
+ </event>
+ </interface>
+
+ <interface name="zwp_tablet_pad_strip_v2" version="1">
+ <description summary="pad strip">
+ A linear interaction area, such as the strips found in Wacom Cintiq
+ models.
+
+ Events on a strip are logically grouped by the wl_tablet_pad_strip.frame
+ event.
+ </description>
+
+ <request name="set_feedback">
+ <description summary="set compositor feedback">
+ Requests the compositor to use the provided feedback string
+ associated with this strip. This request should be issued immediately
+ after a wp_tablet_pad_group.mode_switch event from the corresponding
+ group is received, or whenever the strip is mapped to a different
+ action. See wp_tablet_pad_group.mode_switch for more details.
+
+ Clients are encouraged to provide context-aware descriptions for
+ the actions associated with the strip, and compositors may use this
+ information to offer visual feedback about the button layout
+ (eg. on-screen displays).
+
+ The provided string 'description' is a UTF-8 encoded string to be
+ associated with this ring, and is considered user-visible; general
+ internationalization rules apply.
+
+ The serial argument will be that of the last
+ wp_tablet_pad_group.mode_switch event received for the group of this
+ strip. Requests providing other serials than the most recent one will be
+ ignored.
+ </description>
+ <arg name="description" type="string" summary="strip description"/>
+ <arg name="serial" type="uint" summary="serial of the mode switch event"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the strip object">
+ This destroys the client's resource for this strip object.
+ </description>
+ </request>
+
+ <enum name="source">
+ <description summary="strip axis source">
+ Describes the source types for strip events. This indicates to the
+ client how a strip event was physically generated; a client may
+ adjust the user interface accordingly. For example, events
+ from a "finger" source may trigger kinetic scrolling.
+ </description>
+ <entry name="finger" value="1" summary="finger"/>
+ </enum>
+
+ <event name="source">
+ <description summary="strip event source">
+ Source information for strip events.
+
+ This event does not occur on its own. It is sent before a
+ wp_tablet_pad_strip.frame event and carries the source information
+ for all events within that frame.
+
+ The source specifies how this event was generated. If the source is
+ wp_tablet_pad_strip.source.finger, a wp_tablet_pad_strip.stop event
+ will be sent when the user lifts their finger off the device.
+
+ This event is optional. If the source is unknown for an interaction,
+ no event is sent.
+ </description>
+ <arg name="source" type="uint" enum="source" summary="the event source"/>
+ </event>
+
+ <event name="position">
+ <description summary="position changed">
+ Sent whenever the position on a strip changes.
+
+ The position is normalized to a range of [0, 65535], the 0-value
+ represents the top-most and/or left-most position of the strip in
+ the pad's current rotation.
+ </description>
+ <arg name="position" type="uint" summary="the current position"/>
+ </event>
+
+ <event name="stop">
+ <description summary="interaction stopped">
+ Stop notification for strip events.
+
+ For some wp_tablet_pad_strip.source types, a wp_tablet_pad_strip.stop
+ event is sent to notify a client that the interaction with the strip
+ has terminated. This enables the client to implement kinetic
+ scrolling. See the wp_tablet_pad_strip.source documentation for
+ information on when this event may be generated.
+
+ Any wp_tablet_pad_strip.position events with the same source after this
+ event should be considered as the start of a new interaction.
+ </description>
+ </event>
+
+ <event name="frame">
+ <description summary="end of a strip event sequence">
+ Indicates the end of a set of events that represent one logical
+ hardware strip event. A client is expected to accumulate the data
+ in all events within the frame before proceeding.
+
+ All wp_tablet_pad_strip events before a wp_tablet_pad_strip.frame event belong
+ logically together. For example, on termination of a finger interaction
+ on a strip the compositor will send a wp_tablet_pad_strip.source event,
+ a wp_tablet_pad_strip.stop event and a wp_tablet_pad_strip.frame
+ event.
+
+ A wp_tablet_pad_strip.frame event is sent for every logical event
+ group, even if the group only contains a single wp_tablet_pad_strip
+ event. Specifically, a client may get a sequence: position, frame,
+ position, frame, etc.
+ </description>
+ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
+ </event>
+ </interface>
+
+ <interface name="zwp_tablet_pad_group_v2" version="1">
+ <description summary="a set of buttons, rings and strips">
+ A pad group describes a distinct (sub)set of buttons, rings and strips
+ present in the tablet. The criteria of this grouping is usually positional,
+ eg. if a tablet has buttons on the left and right side, 2 groups will be
+ presented. The physical arrangement of groups is undisclosed and may
+ change on the fly.
+
+ Pad groups will announce their features during pad initialization. Between
+ the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the
+ pad group will announce the buttons, rings and strips contained in it,
+ plus the number of supported modes.
+
+ Modes are a mechanism to allow multiple groups of actions for every element
+ in the pad group. The number of groups and available modes in each is
+ persistent across device plugs. The current mode is user-switchable, it
+ will be announced through the wp_tablet_pad_group.mode_switch event both
+ whenever it is switched, and after wp_tablet_pad.enter.
+
+ The current mode logically applies to all elements in the pad group,
+ although it is at clients' discretion whether to actually perform different
+ actions, and/or issue the respective .set_feedback requests to notify the
+ compositor. See the wp_tablet_pad_group.mode_switch event for more details.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the pad object">
+ Destroy the wp_tablet_pad_group object. Objects created from this object
+ are unaffected and should be destroyed separately.
+ </description>
+ </request>
+
+ <event name="buttons">
+ <description summary="buttons announced">
+ Sent on wp_tablet_pad_group initialization to announce the available
+ buttons in the group. Button indices start at 0, a button may only be
+ in one group at a time.
+
+ This event is first sent in the initial burst of events before the
+ wp_tablet_pad_group.done event.
+
+ Some buttons are reserved by the compositor. These buttons may not be
+ assigned to any wp_tablet_pad_group. Compositors may broadcast this
+ event in the case of changes to the mapping of these reserved buttons.
+ If the compositor happens to reserve all buttons in a group, this event
+ will be sent with an empty array.
+ </description>
+ <arg name="buttons" type="array" summary="buttons in this group"/>
+ </event>
+
+ <event name="ring">
+ <description summary="ring announced">
+ Sent on wp_tablet_pad_group initialization to announce available rings.
+ One event is sent for each ring available on this pad group.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad_group.done event.
+ </description>
+ <arg name="ring" type="new_id" interface="zwp_tablet_pad_ring_v2"/>
+ </event>
+
+ <event name="strip">
+ <description summary="strip announced">
+ Sent on wp_tablet_pad initialization to announce available strips.
+ One event is sent for each strip available on this pad group.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad_group.done event.
+ </description>
+ <arg name="strip" type="new_id" interface="zwp_tablet_pad_strip_v2"/>
+ </event>
+
+ <event name="modes">
+ <description summary="mode-switch ability announced">
+ Sent on wp_tablet_pad_group initialization to announce that the pad
+ group may switch between modes. A client may use a mode to store a
+ specific configuration for buttons, rings and strips and use the
+ wl_tablet_pad_group.mode_switch event to toggle between these
+ configurations. Mode indices start at 0.
+
+ Switching modes is compositor-dependent. See the
+ wp_tablet_pad_group.mode_switch event for more details.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad_group.done event. This event is only sent when more than
+ more than one mode is available.
+ </description>
+ <arg name="modes" type="uint" summary="the number of modes"/>
+ </event>
+
+ <event name="done">
+ <description summary="tablet group description events sequence complete">
+ This event is sent immediately to signal the end of the initial
+ burst of descriptive events. A client may consider the static
+ description of the tablet to be complete and finalize initialization
+ of the tablet group.
+ </description>
+ </event>
+
+ <event name="mode_switch">
+ <description summary="mode switch event">
+ Notification that the mode was switched.
+
+ A mode applies to all buttons, rings and strips in a group
+ simultaneously, but a client is not required to assign different actions
+ for each mode. For example, a client may have mode-specific button
+ mappings but map the ring to vertical scrolling in all modes. Mode
+ indices start at 0.
+
+ Switching modes is compositor-dependent. The compositor may provide
+ visual cues to the client about the mode, e.g. by toggling LEDs on
+ the tablet device. Mode-switching may be software-controlled or
+ controlled by one or more physical buttons. For example, on a Wacom
+ Intuos Pro, the button inside the ring may be assigned to switch
+ between modes.
+
+ The compositor will also send this event after wp_tablet_pad.enter on
+ each group in order to notify of the current mode. Groups that only
+ feature one mode will use mode=0 when emitting this event.
+
+ If a button action in the new mode differs from the action in the
+ previous mode, the client should immediately issue a
+ wp_tablet_pad.set_feedback request for each changed button.
+
+ If a ring or strip action in the new mode differs from the action
+ in the previous mode, the client should immediately issue a
+ wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback request
+ for each changed ring or strip.
+ </description>
+ <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
+ <arg name="serial" type="uint"/>
+ <arg name="mode" type="uint" summary="the new mode of the pad"/>
+ </event>
+ </interface>
+
+ <interface name="zwp_tablet_pad_v2" version="1">
+ <description summary="a set of buttons, rings and strips">
+ A pad device is a set of buttons, rings and strips
+ usually physically present on the tablet device itself. Some
+ exceptions exist where the pad device is physically detached, e.g. the
+ Wacom ExpressKey Remote.
+
+ Pad devices have no axes that control the cursor and are generally
+ auxiliary devices to the tool devices used on the tablet surface.
+
+ A pad device has a number of static characteristics, e.g. the number
+ of rings. These capabilities are sent in an event sequence after the
+ wp_tablet_seat.pad_added event before any actual events from this pad.
+ This initial event sequence is terminated by a wp_tablet_pad.done
+ event.
+
+ All pad features (buttons, rings and strips) are logically divided into
+ groups and all pads have at least one group. The available groups are
+ notified through the wp_tablet_pad.group event; the compositor will
+ emit one event per group before emitting wp_tablet_pad.done.
+
+ Groups may have multiple modes. Modes allow clients to map multiple
+ actions to a single pad feature. Only one mode can be active per group,
+ although different groups may have different active modes.
+ </description>
+
+ <request name="set_feedback">
+ <description summary="set compositor feedback">
+ Requests the compositor to use the provided feedback string
+ associated with this button. This request should be issued immediately
+ after a wp_tablet_pad_group.mode_switch event from the corresponding
+ group is received, or whenever a button is mapped to a different
+ action. See wp_tablet_pad_group.mode_switch for more details.
+
+ Clients are encouraged to provide context-aware descriptions for
+ the actions associated with each button, and compositors may use
+ this information to offer visual feedback on the button layout
+ (e.g. on-screen displays).
+
+ Button indices start at 0. Setting the feedback string on a button
+ that is reserved by the compositor (i.e. not belonging to any
+ wp_tablet_pad_group) does not generate an error but the compositor
+ is free to ignore the request.
+
+ The provided string 'description' is a UTF-8 encoded string to be
+ associated with this ring, and is considered user-visible; general
+ internationalization rules apply.
+
+ The serial argument will be that of the last
+ wp_tablet_pad_group.mode_switch event received for the group of this
+ button. Requests providing other serials than the most recent one will
+ be ignored.
+ </description>
+ <arg name="button" type="uint" summary="button index"/>
+ <arg name="description" type="string" summary="button description"/>
+ <arg name="serial" type="uint" summary="serial of the mode switch event"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the pad object">
+ Destroy the wp_tablet_pad object. Objects created from this object
+ are unaffected and should be destroyed separately.
+ </description>
+ </request>
+
+ <event name="group">
+ <description summary="group announced">
+ Sent on wp_tablet_pad initialization to announce available groups.
+ One event is sent for each pad group available.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad.done event. At least one group will be announced.
+ </description>
+ <arg name="pad_group" type="new_id" interface="zwp_tablet_pad_group_v2"/>
+ </event>
+
+ <event name="path">
+ <description summary="path to the device">
+ A system-specific device path that indicates which device is behind
+ this wp_tablet_pad. This information may be used to gather additional
+ information about the device, e.g. through libwacom.
+
+ The format of the path is unspecified, it may be a device node, a
+ sysfs path, or some other identifier. It is up to the client to
+ identify the string provided.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad.done event.
+ </description>
+ <arg name="path" type="string" summary="path to local device"/>
+ </event>
+
+ <event name="buttons">
+ <description summary="buttons announced">
+ Sent on wp_tablet_pad initialization to announce the available
+ buttons.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad.done event. This event is only sent when at least one
+ button is available.
+ </description>
+ <arg name="buttons" type="uint" summary="the number of buttons"/>
+ </event>
+
+ <event name="done">
+ <description summary="pad description event sequence complete">
+ This event signals the end of the initial burst of descriptive
+ events. A client may consider the static description of the pad to
+ be complete and finalize initialization of the pad.
+ </description>
+ </event>
+
+ <enum name="button_state">
+ <description summary="physical button state">
+ Describes the physical state of a button that caused the button
+ event.
+ </description>
+ <entry name="released" value="0" summary="the button is not pressed"/>
+ <entry name="pressed" value="1" summary="the button is pressed"/>
+ </enum>
+
+ <event name="button">
+ <description summary="physical button state">
+ Sent whenever the physical state of a button changes.
+ </description>
+ <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
+ <arg name="button" type="uint" summary="the index of the button that changed state"/>
+ <arg name="state" type="uint" enum="button_state"/>
+ </event>
+
+ <event name="enter">
+ <description summary="enter event">
+ Notification that this pad is focused on the specified surface.
+ </description>
+ <arg name="serial" type="uint" summary="serial number of the enter event"/>
+ <arg name="tablet" type="object" interface="zwp_tablet_v2" summary="the tablet the pad is attached to"/>
+ <arg name="surface" type="object" interface="wl_surface" summary="surface the pad is focused on"/>
+ </event>
+
+ <event name="leave">
+ <description summary="enter event">
+ Notification that this pad is no longer focused on the specified
+ surface.
+ </description>
+ <arg name="serial" type="uint" summary="serial number of the leave event"/>
+ <arg name="surface" type="object" interface="wl_surface" summary="surface the pad is no longer focused on"/>
+ </event>
+
+ <event name="removed">
+ <description summary="pad removed event">
+ Sent when the pad has been removed from the system. When a tablet
+ is removed its pad(s) will be removed too.
+
+ When this event is received, the client must destroy all rings, strips
+ and groups that were offered by this pad, and issue wp_tablet_pad.destroy
+ the pad itself.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/src/client/client.pro b/src/client/client.pro
index 32156470c..793a44183 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -5,6 +5,10 @@ QT += core-private gui-private
QT_FOR_PRIVATE += service_support-private
QT_PRIVATE += fontdatabase_support-private eventdispatcher_support-private theme_support-private
+qtConfig(vulkan) {
+ QT_PRIVATE += vulkan_support-private
+}
+
# We have a bunch of C code with casts, so we can't have this option
QMAKE_CXXFLAGS_WARN_ON -= -Wcast-qual
@@ -32,6 +36,7 @@ WAYLANDCLIENTSOURCES += \
../extensions/qt-key-unstable-v1.xml \
../extensions/qt-windowmanager.xml \
../3rdparty/protocol/wp-primary-selection-unstable-v1.xml \
+ ../3rdparty/protocol/tablet-unstable-v2.xml \
../3rdparty/protocol/text-input-unstable-v2.xml \
../3rdparty/protocol/xdg-output-unstable-v1.xml \
../3rdparty/protocol/wayland.xml
@@ -48,6 +53,7 @@ SOURCES += qwaylandintegration.cpp \
qwaylandextendedsurface.cpp \
qwaylandsubsurface.cpp \
qwaylandsurface.cpp \
+ qwaylandtabletv2.cpp \
qwaylandtouch.cpp \
qwaylandqtkey.cpp \
../shared/qwaylandmimehelper.cpp \
@@ -73,6 +79,7 @@ HEADERS += qwaylandintegration_p.h \
qwaylandextendedsurface_p.h \
qwaylandsubsurface_p.h \
qwaylandsurface_p.h \
+ qwaylandtabletv2_p.h \
qwaylandtouch_p.h \
qwaylandqtkey_p.h \
qwaylandabstractdecoration_p.h \
@@ -97,6 +104,16 @@ include(shellintegration/shellintegration.pri)
include(inputdeviceintegration/inputdeviceintegration.pri)
include(global/global.pri)
+qtConfig(vulkan) {
+ HEADERS += \
+ qwaylandvulkaninstance_p.h \
+ qwaylandvulkanwindow_p.h
+
+ SOURCES += \
+ qwaylandvulkaninstance.cpp \
+ qwaylandvulkanwindow.cpp
+}
+
qtConfig(cursor) {
QMAKE_USE += wayland-cursor
diff --git a/src/client/configure.json b/src/client/configure.json
index 062139685..7d4468240 100644
--- a/src/client/configure.json
+++ b/src/client/configure.json
@@ -9,7 +9,24 @@
"libraries": {
"wayland-client": {
"label": "Wayland client library",
- "test": "wayland",
+ "headers": "wayland-version.h",
+ "test": {
+ "main": [
+ "#if WAYLAND_VERSION_MAJOR < 1",
+ "# error Wayland 1.8.0 or higher required",
+ "#endif",
+ "#if WAYLAND_VERSION_MAJOR == 1",
+ "# if WAYLAND_VERSION_MINOR < 8",
+ "# error Wayland 1.8.0 or higher required",
+ "# endif",
+ "# if WAYLAND_VERSION_MINOR == 8",
+ "# if WAYLAND_VERSION_MICRO < 0",
+ "# error Wayland 1.8.0 or higher required",
+ "# endif",
+ "# endif",
+ "#endif"
+ ]
+ },
"sources": [
{ "type": "pkgConfig", "args": "wayland-client" },
"-lwayland-client"
@@ -17,7 +34,10 @@
},
"wayland-cursor": {
"label": "Wayland cursor library",
- "test": "wayland_cursor",
+ "headers": "wayland-cursor.h",
+ "test": {
+ "main": "struct wl_cursor_image *image = 0;"
+ },
"use": "wayland-client",
"sources": [
{ "type": "pkgConfig", "args": "wayland-cursor" },
@@ -26,7 +46,10 @@
},
"wayland-egl": {
"label": "Wayland EGL library",
- "test": "wayland_egl",
+ "headers": "wayland-egl.h",
+ "test": {
+ "main": "struct wl_egl_window *window = wl_egl_window_create(0, 100, 100);"
+ },
"sources": [
{ "type": "pkgConfig", "args": "wayland-egl" },
"-lwayland-egl",
@@ -35,7 +58,11 @@
},
"xcomposite": {
"label": "XComposite",
- "test": "xcomposite",
+ "headers": "X11/extensions/Xcomposite.h",
+ "test": {
+ "main": "XCompositeRedirectWindow((Display *)0,(Window) 0, CompositeRedirectManual);"
+
+ },
"sources": [
{ "type": "pkgConfig", "args": "xcomposite" },
"-lxcomposite"
@@ -43,7 +70,14 @@
},
"glx": {
"label": "GLX",
- "test": "glx",
+ "headers": "GL/glx.h",
+ "test": {
+ "main": [
+ "Display *dpy = XOpenDisplay(0);",
+ "int items = 0;",
+ "GLXFBConfig *fbc = glXChooseFBConfig(dpy, DefaultScreen(dpy), 0 , &items);"
+ ]
+ },
"sources": [
{ "type": "pkgConfig", "args": "x11 gl" },
"-lX11 -lGl"
@@ -61,25 +95,79 @@
"drm-egl-server": {
"label": "DRM EGL Server",
"type": "compile",
- "test": "drm_egl_server",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h"
+ ],
+ "main": [
+ "#ifdef EGL_MESA_drm_image",
+ "return 0;",
+ "#else",
+ "#error Requires EGL_MESA_drm_image to be defined",
+ "return 1;",
+ "#endif"
+ ]
+ },
"use": "egl"
},
"libhybris-egl-server": {
"label": "libhybris EGL Server",
"type": "compile",
- "test": "libhybris_egl_server",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h",
+ "hybris/eglplatformcommon/hybris_nativebufferext.h"
+ ],
+ "main": [
+ "#ifdef EGL_HYBRIS_native_buffer",
+ "return 0;",
+ "#else",
+ "#error Requires EGL_HYBRIS_native_buffer to be defined",
+ "return 1;",
+ "#endif"
+ ]
+ },
"use": "egl"
},
"dmabuf-server-buffer": {
"label": "Linux dma-buf Buffer Sharing",
"type": "compile",
- "test": "dmabuf_server_buffer",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h",
+ "drm_fourcc.h"
+ ],
+ "main": [
+ "#ifdef EGL_LINUX_DMA_BUF_EXT",
+ "return 0;",
+ "#else",
+ "#error Requires EGL_LINUX_DMA_BUF_EXT",
+ "return 1;",
+ "#endif"
+ ]
+ },
"use": "egl drm"
},
"vulkan-server-buffer": {
"label": "Vulkan Buffer Sharing",
"type": "compile",
- "test": "vulkan_server_buffer"
+ "test": {
+ "head": [
+ "#define VK_USE_PLATFORM_WAYLAND_KHR 1"
+ ],
+ "include": [
+ "vulkan/vulkan.h"
+ ],
+ "main": [
+ "VkExportMemoryAllocateInfoKHR exportAllocInfo = {};",
+ "exportAllocInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;",
+ "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
+ "return 0;"
+ ]
+ }
}
},
@@ -165,7 +253,7 @@
},
"wayland-vulkan-server-buffer": {
"label": "Vulkan-based server buffer integration",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.vulkan-server-buffer",
+ "condition": "features.wayland-client && features.vulkan && features.opengl && features.egl && tests.vulkan-server-buffer",
"output": [ "privateFeature" ]
},
"wayland-shm-emulation-server-buffer": {
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index f7d135e49..19944a349 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -157,7 +157,9 @@ void QWaylandDataDevice::data_device_drop()
return;
}
- QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
@@ -187,7 +189,9 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
}
- const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
@@ -203,7 +207,9 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
void QWaylandDataDevice::data_device_leave()
{
if (m_dragWindow)
- QWindowSystemInterface::handleDrag(m_dragWindow, nullptr, QPoint(), Qt::IgnoreAction);
+ QWindowSystemInterface::handleDrag(m_dragWindow, nullptr, QPoint(), Qt::IgnoreAction,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
if (!drag) {
@@ -232,7 +238,9 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
}
- QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index 0464d3a42..ffcc72ff9 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -69,6 +69,7 @@
#include "qwaylandextendedsurface_p.h"
#include "qwaylandsubsurface_p.h"
#include "qwaylandtouch_p.h"
+#include "qwaylandtabletv2_p.h"
#include "qwaylandqtkey_p.h"
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
@@ -188,6 +189,18 @@ QWaylandDisplay::~QWaylandDisplay(void)
wl_display_disconnect(mDisplay);
}
+void QWaylandDisplay::ensureScreen()
+{
+ if (!mScreens.empty() || mPlaceholderScreen)
+ return; // There are real screens or we already have a fake one
+
+ qCInfo(lcQpaWayland) << "Creating a fake screen in order for Qt not to crash";
+
+ mPlaceholderScreen = new QPlatformPlaceholderScreen();
+ QWindowSystemInterface::handleScreenAdded(mPlaceholderScreen);
+ Q_ASSERT(!QGuiApplication::screens().empty());
+}
+
void QWaylandDisplay::checkError() const
{
int ecode = wl_display_get_error(mDisplay);
@@ -253,8 +266,7 @@ void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bo
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
{
- for (int i = 0; i < mScreens.size(); ++i) {
- QWaylandScreen *screen = static_cast<QWaylandScreen *>(mScreens.at(i));
+ for (auto screen : qAsConst(mScreens)) {
if (screen->output() == output)
return screen;
}
@@ -267,6 +279,11 @@ void QWaylandDisplay::handleScreenInitialized(QWaylandScreen *screen)
return;
mScreens.append(screen);
QWindowSystemInterface::handleScreenAdded(screen);
+ if (mPlaceholderScreen) {
+ QWindowSystemInterface::handleScreenRemoved(mPlaceholderScreen);
+ // handleScreenRemoved deletes the platform screen
+ mPlaceholderScreen = nullptr;
+ }
}
void QWaylandDisplay::waitForScreens()
@@ -314,6 +331,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mTouchExtension.reset(new QWaylandTouchExtension(this, id));
} else if (interface == QStringLiteral("zqt_key_v1")) {
mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
+ } else if (interface == QStringLiteral("zwp_tablet_manager_v2")) {
+ mTabletManager.reset(new QWaylandTabletManagerV2(this, id, qMin(1, int(version))));
#if QT_CONFIG(wayland_client_primary_selection)
} else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
@@ -362,6 +381,8 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
for (QWaylandScreen *screen : qAsConst(mScreens)) {
if (screen->outputId() == id) {
mScreens.removeOne(screen);
+ // If this is the last screen, we have to add a fake screen, or Qt will break.
+ ensureScreen();
QWindowSystemInterface::handleScreenRemoved(screen);
break;
}
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 14bb77198..e99ec1983 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -76,6 +76,7 @@ QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
class QSocketNotifier;
class QPlatformScreen;
+class QPlatformPlaceholderScreen;
namespace QtWayland {
class qt_surface_extension;
@@ -96,6 +97,7 @@ class QWaylandDataDeviceManager;
#if QT_CONFIG(wayland_client_primary_selection)
class QWaylandPrimarySelectionDeviceManagerV1;
#endif
+class QWaylandTabletManagerV2;
class QWaylandTouchExtension;
class QWaylandQtKeyExtension;
class QWaylandWindow;
@@ -124,6 +126,8 @@ public:
#endif
QList<QWaylandScreen *> screens() const { return mScreens; }
+ QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
+ void ensureScreen();
QWaylandScreen *screenForOutput(struct wl_output *output) const;
void handleScreenInitialized(QWaylandScreen *screen);
@@ -157,6 +161,7 @@ public:
QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
#endif
QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
+ QWaylandTabletManagerV2 *tabletManager() const { return mTabletManager.data(); }
QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
@@ -228,6 +233,7 @@ private:
QScopedPointer<QWaylandShm> mShm;
QList<QWaylandScreen *> mWaitingScreens;
QList<QWaylandScreen *> mScreens;
+ QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
QList<QWaylandInputDevice *> mInputDevices;
QList<Listener> mRegistryListeners;
QWaylandIntegration *mWaylandIntegration = nullptr;
@@ -243,6 +249,7 @@ private:
QScopedPointer<QWaylandTouchExtension> mTouchExtension;
QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
+ QScopedPointer<QWaylandTabletManagerV2> mTabletManager;
#if QT_CONFIG(wayland_client_primary_selection)
QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
#endif
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 320e34040..e0f0c6c8e 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -50,6 +50,7 @@
#if QT_CONFIG(wayland_client_primary_selection)
#include "qwaylandprimaryselectionv1_p.h"
#endif
+#include "qwaylandtabletv2_p.h"
#include "qwaylandtouch_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
@@ -418,6 +419,8 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
if (mQDisplay->textInputManager())
mTextInput.reset(new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat())));
+ if (auto *tm = mQDisplay->tabletManager())
+ mTabletSeat.reset(new QWaylandTabletSeatV2(tm, this));
}
QWaylandInputDevice::~QWaylandInputDevice()
@@ -630,8 +633,8 @@ class EnterEvent : public QWaylandPointerEvent
{
public:
EnterEvent(QWaylandWindow *surface, const QPointF &local, const QPointF &global)
- : QWaylandPointerEvent(QWaylandPointerEvent::Enter, Qt::NoScrollPhase, surface, 0,
- local, global, nullptr, Qt::NoModifier)
+ : QWaylandPointerEvent(QEvent::Enter, Qt::NoScrollPhase, surface, 0,
+ local, global, Qt::NoButton, Qt::NoButton, Qt::NoModifier)
{}
};
@@ -675,8 +678,8 @@ class LeaveEvent : public QWaylandPointerEvent
{
public:
LeaveEvent(QWaylandWindow *surface, const QPointF &localPos, const QPointF &globalPos)
- : QWaylandPointerEvent(QWaylandPointerEvent::Leave, Qt::NoScrollPhase, surface, 0,
- localPos, globalPos, nullptr, Qt::NoModifier)
+ : QWaylandPointerEvent(QEvent::Leave, Qt::NoScrollPhase, surface, 0,
+ localPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier)
{}
};
@@ -705,8 +708,8 @@ class MotionEvent : public QWaylandPointerEvent
public:
MotionEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Motion, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ : QWaylandPointerEvent(QEvent::MouseMove, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, Qt::NoButton, modifiers)
{
}
};
@@ -744,9 +747,10 @@ class PressEvent : public QWaylandPointerEvent
{
public:
PressEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
- const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Press, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QEvent::MouseButtonPress, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, button, modifiers)
{
}
};
@@ -755,9 +759,10 @@ class ReleaseEvent : public QWaylandPointerEvent
{
public:
ReleaseEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
- const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Release, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QEvent::MouseButtonRelease, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, button, modifiers)
{
}
};
@@ -818,9 +823,9 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
}
if (state)
- setFrameEvent(new PressEvent(window, time, pos, global, mButtons, mParent->modifiers()));
+ setFrameEvent(new PressEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers()));
else
- setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, mParent->modifiers()));
+ setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers()));
}
void QWaylandInputDevice::Pointer::invalidateFocus()
@@ -848,7 +853,7 @@ public:
WheelEvent(QWaylandWindow *surface, Qt::ScrollPhase phase, ulong timestamp, const QPointF &local,
const QPointF &global, const QPoint &pixelDelta, const QPoint &angleDelta,
Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Wheel, phase, surface, timestamp,
+ : QWaylandPointerEvent(QEvent::Wheel, phase, surface, timestamp,
local, global, pixelDelta, angleDelta, source, modifiers)
{
}
@@ -1004,6 +1009,8 @@ bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const
case axis_source_finger:
case axis_source_continuous:
return !delta.isNull();
+ default:
+ return false;
}
}
@@ -1084,11 +1091,13 @@ void QWaylandInputDevice::Pointer::flushFrameEvent()
if (auto *event = mFrameData.event) {
if (auto window = event->surface) {
window->handleMouse(mParent, *event);
- } else if (mFrameData.event->type == QWaylandPointerEvent::Type::Release) {
+ } else if (mFrameData.event->type == QEvent::MouseButtonRelease) {
// If the window has been destroyed, we still need to report an up event, but it can't
// be handled by the destroyed window (obviously), so send the event here instead.
QWindowSystemInterface::handleMouseEvent(nullptr, event->timestamp, event->local,
- event->global, event->buttons, event->modifiers);
+ event->global, event->buttons,
+ event->button, event->type,
+ event->modifiers);// , Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
}
delete mFrameData.event;
mFrameData.event = nullptr;
@@ -1408,8 +1417,7 @@ void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, co
return;
tp.area = QRectF(0, 0, 8, 8);
- QMargins margins = win->frameMargins();
- QPointF localPosition = surfacePosition - QPointF(margins.left(), margins.top());
+ QPointF localPosition = win->mapFromWlSurface(surfacePosition);
// TODO: This doesn't account for high dpi scaling for the delta, but at least it matches
// what we have for mouse input.
QPointF delta = localPosition - localPosition.toPoint();
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index a567c57b4..448d0fce5 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -89,6 +89,7 @@ class QWaylandDisplay;
#if QT_CONFIG(wayland_client_primary_selection)
class QWaylandPrimarySelectionDeviceV1;
#endif
+class QWaylandTabletSeatV2;
class QWaylandTextInput;
#if QT_CONFIG(cursor)
class QWaylandCursorTheme;
@@ -127,6 +128,9 @@ public:
QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice() const;
#endif
+ void setTabletSeat(QWaylandTabletSeatV2 *tabletSeat);
+ QWaylandTabletSeatV2* tabletSeat() const;
+
void setTextInput(QWaylandTextInput *textInput);
QWaylandTextInput *textInput() const;
@@ -183,6 +187,7 @@ private:
Touch *mTouch = nullptr;
QScopedPointer<QWaylandTextInput> mTextInput;
+ QScopedPointer<QWaylandTabletSeatV2> mTabletSeat;
uint32_t mTime = 0;
uint32_t mSerial = 0;
@@ -401,29 +406,21 @@ class QWaylandPointerEvent
{
Q_GADGET
public:
- enum Type {
- Enter,
- Leave,
- Motion,
- Press,
- Release,
- Wheel
- };
- Q_ENUM(Type)
-
- inline QWaylandPointerEvent(Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
+ inline QWaylandPointerEvent(QEvent::Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
ulong timestamp, const QPointF &localPos, const QPointF &globalPos,
- Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
: type(type)
, phase(phase)
, timestamp(timestamp)
, local(localPos)
, global(globalPos)
, buttons(buttons)
+ , button(button)
, modifiers(modifiers)
, surface(surface)
{}
- inline QWaylandPointerEvent(Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
+ inline QWaylandPointerEvent(QEvent::Type type, Qt::ScrollPhase phase, QWaylandWindow *surface,
ulong timestamp, const QPointF &local, const QPointF &global,
const QPoint &pixelDelta, const QPoint &angleDelta,
Qt::MouseEventSource source,
@@ -440,12 +437,13 @@ public:
, surface(surface)
{}
- Type type;
+ QEvent::Type type = QEvent::None;
Qt::ScrollPhase phase = Qt::NoScrollPhase;
ulong timestamp = 0;
QPointF local;
QPointF global;
Qt::MouseButtons buttons;
+ Qt::MouseButton button = Qt::NoButton; // Button that caused the event (QMouseEvent::button)
Qt::KeyboardModifiers modifiers;
QPoint pixelDelta;
QPoint angleDelta;
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index f6a80e18f..85c1990b6 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -86,7 +86,7 @@
#include "qwaylandinputdeviceintegration_p.h"
#include "qwaylandinputdeviceintegrationfactory_p.h"
-#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
+#if QT_CONFIG(accessibility_atspi_bridge)
#include <QtLinuxAccessibilitySupport/private/bridge_p.h>
#endif
@@ -94,41 +94,14 @@
#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#endif
-QT_BEGIN_NAMESPACE
-
-namespace QtWaylandClient {
-
-class GenericWaylandTheme: public QGenericUnixTheme
-{
-public:
- static QStringList themeNames()
- {
- QStringList result;
-
- if (QGuiApplication::desktopSettingsAware()) {
- const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment();
-
- if (desktopEnvironment == QByteArrayLiteral("KDE")) {
-#if QT_CONFIG(settings)
- result.push_back(QStringLiteral("kde"));
+#if QT_CONFIG(vulkan)
+#include "qwaylandvulkaninstance_p.h"
+#include "qwaylandvulkanwindow_p.h"
#endif
- } else if (!desktopEnvironment.isEmpty() &&
- desktopEnvironment != QByteArrayLiteral("UNKNOWN") &&
- desktopEnvironment != QByteArrayLiteral("GNOME") &&
- desktopEnvironment != QByteArrayLiteral("UNITY") &&
- desktopEnvironment != QByteArrayLiteral("MATE") &&
- desktopEnvironment != QByteArrayLiteral("XFCE") &&
- desktopEnvironment != QByteArrayLiteral("LXDE"))
- // Ignore X11 desktop environments
- result.push_back(QString::fromLocal8Bit(desktopEnvironment.toLower()));
- }
- if (result.isEmpty())
- result.push_back(QLatin1String(QGenericUnixTheme::name));
+QT_BEGIN_NAMESPACE
- return result;
- }
-};
+namespace QtWaylandClient {
QWaylandIntegration::QWaylandIntegration()
#if defined(Q_OS_MACOS)
@@ -190,7 +163,12 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) cons
&& mDisplay->clientBufferIntegration())
return mDisplay->clientBufferIntegration()->createEglWindow(window);
- return new QWaylandShmWindow(window);
+#if QT_CONFIG(vulkan)
+ if (window->surfaceType() == QSurface::VulkanSurface)
+ return new QWaylandVulkanWindow(window, mDisplay.data());
+#endif // QT_CONFIG(vulkan)
+
+ return new QWaylandShmWindow(window, mDisplay.data());
}
#if QT_CONFIG(opengl)
@@ -204,7 +182,7 @@ QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGL
QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
- return new QWaylandShmBackingStore(window);
+ return new QWaylandShmBackingStore(window, mDisplay.data());
}
QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
@@ -222,10 +200,8 @@ void QWaylandIntegration::initialize()
QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data());
QObject::connect(sn, SIGNAL(activated(int)), mDisplay.data(), SLOT(flushRequests()));
- if (mDisplay->screens().isEmpty()) {
- qWarning() << "Running on a compositor with no screens is not supported";
- ::exit(EXIT_FAILURE);
- }
+ // Qt does not support running with no screens
+ mDisplay->ensureScreen();
}
QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
@@ -271,7 +247,7 @@ QVariant QWaylandIntegration::styleHint(StyleHint hint) const
QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
if (!mAccessibility) {
-#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
+#if QT_CONFIG(accessibility_atspi_bridge)
Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QWaylandIntegration",
"Initializing accessibility without event-dispatcher!");
mAccessibility.reset(new QSpiAccessibleBridge());
@@ -302,14 +278,21 @@ QList<int> QWaylandIntegration::possibleKeys(const QKeyEvent *event) const
QStringList QWaylandIntegration::themeNames() const
{
- return GenericWaylandTheme::themeNames();
+ return QGenericUnixTheme::themeNames();
}
QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) const
{
- return GenericWaylandTheme::createUnixTheme(name);
+ return QGenericUnixTheme::createUnixTheme(name);
}
+#if QT_CONFIG(vulkan)
+QPlatformVulkanInstance *QWaylandIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ return new QWaylandVulkanInstance(instance);
+}
+#endif // QT_CONFIG(vulkan)
+
// May be called from non-GUI threads
QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() const
{
@@ -442,6 +425,8 @@ void QWaylandIntegration::initializeShellIntegration()
qCWarning(lcQpaWayland) << "Loading shell integration failed.";
qCWarning(lcQpaWayland) << "Attempted to load the following shells" << preferredShells;
}
+
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
}
QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id)
diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h
index a66999c7f..ff70ae25d 100644
--- a/src/client/qwaylandintegration_p.h
+++ b/src/client/qwaylandintegration_p.h
@@ -113,6 +113,10 @@ public:
QPlatformTheme *createPlatformTheme(const QString &name) const override;
+#if QT_CONFIG(vulkan)
+ QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
+#endif
+
QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, int version, uint32_t id);
virtual QWaylandClientBufferIntegration *clientBufferIntegration() const;
diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp
index b4ecc0090..bf54a1a00 100644
--- a/src/client/qwaylandnativeinterface.cpp
+++ b/src/client/qwaylandnativeinterface.cpp
@@ -51,6 +51,9 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QScreen>
#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
+#if QT_CONFIG(vulkan)
+#include <QtWaylandClient/private/qwaylandvulkanwindow_p.h>
+#endif
#include <QtPlatformHeaders/qwaylandwindowfunctions.h>
@@ -117,6 +120,15 @@ void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourc
if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration())
return m_integration->clientBufferIntegration()->nativeResource(QWaylandClientBufferIntegration::EglDisplay);
+#if QT_CONFIG(vulkan)
+ if (lowerCaseResource == "vksurface") {
+ if (window->surfaceType() == QSurface::VulkanSurface && window->handle()) {
+ // return a pointer to the VkSurfaceKHR value, not the value itself
+ return static_cast<QWaylandVulkanWindow *>(window->handle())->surface();
+ }
+ }
+#endif
+
if (auto shellIntegration = m_integration->shellIntegration())
return shellIntegration->nativeResourceForWindow(resourceString, window);
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index e70796832..4f0cd9b0a 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -165,11 +165,18 @@ QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const
{
QList<QPlatformScreen *> list;
const QList<QWaylandScreen*> screens = mWaylandDisplay->screens();
- list.reserve(screens.count());
+ auto *placeholder = mWaylandDisplay->placeholderScreen();
+
+ list.reserve(screens.count() + (placeholder ? 1 : 0));
+
for (QWaylandScreen *screen : qAsConst(screens)) {
if (screen->screen())
list << screen;
}
+
+ if (placeholder)
+ list << placeholder;
+
return list;
}
@@ -210,9 +217,11 @@ QPlatformCursor *QWaylandScreen::cursor() const
}
#endif // QT_CONFIG(cursor)
-QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
+QWaylandScreen *QWaylandScreen::waylandScreenFromWindow(QWindow *window)
{
QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(window);
+ if (platformScreen->isPlaceholder())
+ return nullptr;
return static_cast<QWaylandScreen *>(platformScreen);
}
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index e9e07d9cd..ae91c6211 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -57,7 +57,6 @@
#include <QtWaylandClient/private/qwayland-wayland.h>
#include <QtWaylandClient/private/qwayland-xdg-output-unstable-v1.h>
-
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index 9b5971a21..8d5b977d5 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -151,9 +151,9 @@ QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &marginsIn)
}
-QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
+QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window, QWaylandDisplay *display)
: QPlatformBackingStore(window)
- , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
+ , mDisplay(display)
{
}
diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h
index 8a85cd7f3..e01632daf 100644
--- a/src/client/qwaylandshmbackingstore_p.h
+++ b/src/client/qwaylandshmbackingstore_p.h
@@ -88,7 +88,7 @@ private:
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingStore
{
public:
- QWaylandShmBackingStore(QWindow *window);
+ QWaylandShmBackingStore(QWindow *window, QWaylandDisplay *display);
~QWaylandShmBackingStore() override;
QPaintDevice *paintDevice() override;
diff --git a/src/client/qwaylandshmwindow.cpp b/src/client/qwaylandshmwindow.cpp
index 52833803d..e305d028d 100644
--- a/src/client/qwaylandshmwindow.cpp
+++ b/src/client/qwaylandshmwindow.cpp
@@ -49,8 +49,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandShmWindow::QWaylandShmWindow(QWindow *window)
- : QWaylandWindow(window)
+QWaylandShmWindow::QWaylandShmWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
{
}
diff --git a/src/client/qwaylandshmwindow_p.h b/src/client/qwaylandshmwindow_p.h
index ae1727859..81251b3aa 100644
--- a/src/client/qwaylandshmwindow_p.h
+++ b/src/client/qwaylandshmwindow_p.h
@@ -61,7 +61,7 @@ namespace QtWaylandClient {
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow
{
public:
- QWaylandShmWindow(QWindow *window);
+ QWaylandShmWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandShmWindow() override;
WindowType windowType() const override;
diff --git a/src/client/qwaylandsurface.cpp b/src/client/qwaylandsurface.cpp
index c35f01b56..21e70ce4f 100644
--- a/src/client/qwaylandsurface.cpp
+++ b/src/client/qwaylandsurface.cpp
@@ -72,8 +72,12 @@ QWaylandSurface *QWaylandSurface::fromWlSurface(::wl_surface *surface)
void QWaylandSurface::handleScreenRemoved(QScreen *qScreen)
{
- auto *screen = static_cast<QWaylandScreen *>(qScreen->handle());
- if (m_screens.removeOne(screen))
+ auto *platformScreen = qScreen->handle();
+ if (platformScreen->isPlaceholder())
+ return;
+
+ auto *waylandScreen = static_cast<QWaylandScreen *>(qScreen->handle());
+ if (m_screens.removeOne(waylandScreen))
emit screensChanged();
}
diff --git a/src/client/qwaylandtabletv2.cpp b/src/client/qwaylandtabletv2.cpp
new file mode 100644
index 000000000..eb2e865f6
--- /dev/null
+++ b/src/client/qwaylandtabletv2.cpp
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandtabletv2_p.h"
+#include "qwaylandinputdevice_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandsurface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandTabletManagerV2::QWaylandTabletManagerV2(QWaylandDisplay *display, uint id, uint version)
+ : zwp_tablet_manager_v2(display->wl_registry(), id, qMin(version, uint(1)))
+{
+ // Create tabletSeats for all seats.
+ // This only works if we get the manager after all seats
+ const auto seats = display->inputDevices();
+ for (auto *seat : seats)
+ createTabletSeat(seat);
+}
+
+QWaylandTabletSeatV2 *QWaylandTabletManagerV2::createTabletSeat(QWaylandInputDevice *seat)
+{
+ return new QWaylandTabletSeatV2(this, seat);
+}
+
+QWaylandTabletSeatV2::QWaylandTabletSeatV2(QWaylandTabletManagerV2 *manager, QWaylandInputDevice *seat)
+ : QtWayland::zwp_tablet_seat_v2(manager->get_tablet_seat(seat->wl_seat()))
+{
+}
+
+QWaylandTabletSeatV2::~QWaylandTabletSeatV2()
+{
+ for (auto *tablet : m_tablets)
+ tablet->destroy();
+ for (auto *tool : m_tools)
+ tool->destroy();
+ for (auto *pad : m_pads)
+ pad->destroy();
+ destroy();
+}
+
+void QWaylandTabletSeatV2::zwp_tablet_seat_v2_tablet_added(zwp_tablet_v2 *id)
+{
+ auto *tablet = new QWaylandTabletV2(id);
+ m_tablets.push_back(tablet);
+ connect(tablet, &QWaylandTabletV2::destroyed, this, [this, tablet] { m_tablets.removeOne(tablet); });
+}
+
+void QWaylandTabletSeatV2::zwp_tablet_seat_v2_tool_added(zwp_tablet_tool_v2 *id)
+{
+ auto *tool = new QWaylandTabletToolV2(id);
+ m_tools.push_back(tool);
+ connect(tool, &QWaylandTabletToolV2::destroyed, this, [this, tool] { m_tools.removeOne(tool); });
+}
+
+void QWaylandTabletSeatV2::zwp_tablet_seat_v2_pad_added(zwp_tablet_pad_v2 *id)
+{
+ auto *pad = new QWaylandTabletPadV2(id);
+ m_pads.push_back(pad);
+ connect(pad, &QWaylandTabletPadV2::destroyed, this, [this, pad] { m_pads.removeOne(pad); });
+}
+
+QWaylandTabletV2::QWaylandTabletV2(::zwp_tablet_v2 *tablet)
+ : QtWayland::zwp_tablet_v2(tablet)
+{
+}
+
+void QWaylandTabletV2::zwp_tablet_v2_removed()
+{
+ destroy();
+ delete this;
+}
+
+QWaylandTabletToolV2::QWaylandTabletToolV2(::zwp_tablet_tool_v2 *tool)
+ : QtWayland::zwp_tablet_tool_v2(tool)
+{
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_type(uint32_t tool_type)
+{
+ m_toolType = type(tool_type);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_hardware_serial(uint32_t hardware_serial_hi, uint32_t hardware_serial_lo)
+{
+ m_uid = (quint64(hardware_serial_hi) << 32) + hardware_serial_lo;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_capability(uint32_t capability)
+{
+ if (capability == capability_rotation)
+ m_hasRotation = true;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_done()
+{
+ switch (m_toolType) {
+ case type::type_airbrush:
+ case type::type_brush:
+ case type::type_pencil:
+ case type::type_pen:
+ m_pointerType = QTabletEvent::PointerType::Pen;
+ break;
+ case type::type_eraser:
+ m_pointerType = QTabletEvent::PointerType::Eraser;
+ break;
+ case type::type_mouse:
+ case type::type_lens:
+ m_pointerType = QTabletEvent::PointerType::Cursor;
+ break;
+ case type::type_finger:
+ m_pointerType = QTabletEvent::PointerType::UnknownPointer;
+ break;
+ }
+ switch (m_toolType) {
+ case type::type_airbrush:
+ m_tabletDevice = QTabletEvent::TabletDevice::Airbrush;
+ break;
+ case type::type_brush:
+ case type::type_pencil:
+ case type::type_pen:
+ case type::type_eraser:
+ m_tabletDevice = m_hasRotation ? QTabletEvent::TabletDevice::RotationStylus : QTabletEvent::TabletDevice::Stylus;
+ break;
+ case type::type_lens:
+ m_tabletDevice = QTabletEvent::TabletDevice::Puck;
+ break;
+ case type::type_mouse:
+ case type::type_finger:
+ m_tabletDevice = QTabletEvent::TabletDevice::NoDevice;
+ break;
+ }
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_removed()
+{
+ destroy();
+ delete this;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_proximity_in(uint32_t serial, zwp_tablet_v2 *tablet, wl_surface *surface)
+{
+ Q_UNUSED(tablet);
+ Q_UNUSED(serial);
+ if (Q_UNLIKELY(!surface)) {
+ qCDebug(lcQpaWayland) << "Ignoring zwp_tablet_tool_v2_proximity_v2 with no surface";
+ return;
+ }
+ m_pending.enteredSurface = true;
+ m_pending.proximitySurface = QWaylandSurface::fromWlSurface(surface);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_proximity_out()
+{
+ m_pending.enteredSurface = false;
+ m_pending.proximitySurface = nullptr;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_down(uint32_t serial)
+{
+ Q_UNUSED(serial);
+ m_pending.down = true;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_up()
+{
+ m_pending.down = false;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_motion(wl_fixed_t x, wl_fixed_t y)
+{
+ m_pending.surfacePosition = QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y));
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_pressure(uint32_t pressure)
+{
+ const int maxPressure = 65535;
+ m_pending.pressure = qreal(pressure)/maxPressure;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_distance(uint32_t distance)
+{
+ m_pending.distance = distance;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_tilt(wl_fixed_t tilt_x, wl_fixed_t tilt_y)
+{
+ m_pending.xTilt = wl_fixed_to_double(tilt_x);
+ m_pending.yTilt = wl_fixed_to_double(tilt_y);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_rotation(wl_fixed_t degrees)
+{
+ m_pending.rotation = wl_fixed_to_double(degrees);
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_slider(int32_t position)
+{
+ m_pending.slider = qreal(position) / 65535;
+}
+
+static Qt::MouseButton mouseButtonFromTablet(uint button)
+{
+ switch (button) {
+ case 0x110: return Qt::MouseButton::LeftButton; // BTN_LEFT
+ case 0x14b: return Qt::MouseButton::MiddleButton; // BTN_STYLUS
+ case 0x14c: return Qt::MouseButton::RightButton; // BTN_STYLUS2
+ default:
+ return Qt::NoButton;
+ }
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_button(uint32_t serial, uint32_t button, uint32_t state)
+{
+ Q_UNUSED(serial);
+ Qt::MouseButton mouseButton = mouseButtonFromTablet(button);
+ if (state == button_state_pressed)
+ m_pending.buttons |= mouseButton;
+ else
+ m_pending.buttons &= ~mouseButton;
+}
+
+void QWaylandTabletToolV2::zwp_tablet_tool_v2_frame(uint32_t time)
+{
+ if (m_pending.proximitySurface && !m_applied.proximitySurface) {
+ QWindowSystemInterface::handleTabletEnterProximityEvent(m_tabletDevice, m_pointerType, m_uid);
+ m_applied.proximitySurface = m_pending.proximitySurface;
+ }
+
+ if (!(m_pending == m_applied) && m_pending.proximitySurface) {
+ if (!m_pending.proximitySurface) {
+ qCWarning(lcQpaWayland) << "Can't send tablet event with no proximity surface, ignoring";
+ return;
+ }
+ QWaylandWindow *waylandWindow = QWaylandWindow::fromWlSurface(m_pending.proximitySurface->object());
+ QWindow *window = waylandWindow->window();
+ ulong timestamp = time;
+ const QPointF localPosition = waylandWindow->mapFromWlSurface(m_pending.surfacePosition);
+
+ QPointF delta = localPosition - localPosition.toPoint();
+ QPointF globalPosition = window->mapToGlobal(localPosition.toPoint());
+ globalPosition += delta;
+
+ Qt::MouseButtons buttons = m_pending.down ? Qt::MouseButton::LeftButton : Qt::MouseButton::NoButton;
+ buttons |= m_pending.buttons;
+ qreal pressure = m_pending.pressure;
+ int xTilt = int(m_pending.xTilt);
+ int yTilt = int(m_pending.yTilt);
+ qreal tangentialPressure = m_pending.slider;
+ qreal rotation = m_pending.rotation;
+ int z = int(m_pending.distance);
+ QWindowSystemInterface::handleTabletEvent(window, timestamp, localPosition, globalPosition,
+ m_tabletDevice, m_pointerType, buttons, pressure,
+ xTilt, yTilt, tangentialPressure, rotation, z, m_uid);
+ }
+
+ if (!m_pending.proximitySurface && m_applied.enteredSurface) {
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(m_tabletDevice, m_pointerType, m_uid);
+ m_pending = State(); // Don't leave pressure etc. lying around when we enter the next surface
+ }
+
+ m_applied = m_pending;
+}
+
+// TODO: delete when upgrading to c++20
+bool QWaylandTabletToolV2::State::operator==(const QWaylandTabletToolV2::State &o) const {
+ return
+ down == o.down &&
+ proximitySurface.data() == o.proximitySurface.data() &&
+ enteredSurface == o.enteredSurface &&
+ surfacePosition == o.surfacePosition &&
+ distance == o.distance &&
+ pressure == o.pressure &&
+ rotation == o.rotation &&
+ xTilt == o.xTilt &&
+ yTilt == o.yTilt &&
+ slider == o.slider &&
+ buttons == o.buttons;
+}
+
+QWaylandTabletPadV2::QWaylandTabletPadV2(::zwp_tablet_pad_v2 *pad)
+ : QtWayland::zwp_tablet_pad_v2(pad)
+{
+}
+
+void QWaylandTabletPadV2::zwp_tablet_pad_v2_removed()
+{
+ destroy();
+ delete this;
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandtabletv2_p.h b/src/client/qwaylandtabletv2_p.h
new file mode 100644
index 000000000..b4daaf5db
--- /dev/null
+++ b/src/client/qwaylandtabletv2_p.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDTABLETV2_P_H
+#define QWAYLANDTABLETV2_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtWaylandClient/private/qwayland-tablet-unstable-v2.h>
+
+#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
+
+#include <QtGui/QTabletEvent>
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QPointF>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+class QWaylandInputDevice;
+class QWaylandSurface;
+
+class QWaylandTabletSeatV2;
+class QWaylandTabletV2;
+class QWaylandTabletToolV2;
+class QWaylandTabletPadV2;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletManagerV2 : public QtWayland::zwp_tablet_manager_v2
+{
+public:
+ explicit QWaylandTabletManagerV2(QWaylandDisplay *display, uint id, uint version);
+ QWaylandTabletSeatV2 *createTabletSeat(QWaylandInputDevice *seat);
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletSeatV2 : public QObject, public QtWayland::zwp_tablet_seat_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletSeatV2(QWaylandTabletManagerV2 *manager, QWaylandInputDevice *seat);
+ ~QWaylandTabletSeatV2() override;
+
+protected:
+ void zwp_tablet_seat_v2_tablet_added(struct ::zwp_tablet_v2 *id) override;
+ void zwp_tablet_seat_v2_tool_added(struct ::zwp_tablet_tool_v2 *id) override;
+ void zwp_tablet_seat_v2_pad_added(struct ::zwp_tablet_pad_v2 *id) override;
+
+private:
+ QVector<QWaylandTabletV2 *> m_tablets;
+ QVector<QWaylandTabletToolV2 *> m_tools;
+ QVector<QWaylandTabletPadV2 *> m_pads;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletV2 : public QObject, public QtWayland::zwp_tablet_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletV2(::zwp_tablet_v2 *tablet);
+
+protected:
+// void zwp_tablet_v2_name(const QString &name) override;
+// void zwp_tablet_v2_id(uint32_t vid, uint32_t pid) override;
+// void zwp_tablet_v2_path(const QString &path) override;
+// void zwp_tablet_v2_done() override;
+ void zwp_tablet_v2_removed() override;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletToolV2 : public QObject, public QtWayland::zwp_tablet_tool_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletToolV2(::zwp_tablet_tool_v2 *tool);
+
+protected:
+ void zwp_tablet_tool_v2_type(uint32_t tool_type) override;
+ void zwp_tablet_tool_v2_hardware_serial(uint32_t hardware_serial_hi, uint32_t hardware_serial_lo) override;
+// void zwp_tablet_tool_v2_hardware_id_wacom(uint32_t hardware_id_hi, uint32_t hardware_id_lo) override;
+ void zwp_tablet_tool_v2_capability(uint32_t capability) override;
+ void zwp_tablet_tool_v2_done() override;
+ void zwp_tablet_tool_v2_removed() override;
+ void zwp_tablet_tool_v2_proximity_in(uint32_t serial, struct ::zwp_tablet_v2 *tablet, struct ::wl_surface *surface) override;
+ void zwp_tablet_tool_v2_proximity_out() override;
+ void zwp_tablet_tool_v2_down(uint32_t serial) override;
+ void zwp_tablet_tool_v2_up() override;
+ void zwp_tablet_tool_v2_motion(wl_fixed_t x, wl_fixed_t y) override;
+ void zwp_tablet_tool_v2_pressure(uint32_t pressure) override;
+ void zwp_tablet_tool_v2_distance(uint32_t distance) override;
+ void zwp_tablet_tool_v2_tilt(wl_fixed_t tilt_x, wl_fixed_t tilt_y) override;
+ void zwp_tablet_tool_v2_rotation(wl_fixed_t degrees) override;
+ void zwp_tablet_tool_v2_slider(int32_t position) override;
+// void zwp_tablet_tool_v2_wheel(wl_fixed_t degrees, int32_t clicks) override;
+ void zwp_tablet_tool_v2_button(uint32_t serial, uint32_t button, uint32_t state) override;
+ void zwp_tablet_tool_v2_frame(uint32_t time) override;
+
+private:
+
+ // Static state (sent before done event)
+ QTabletEvent::PointerType m_pointerType = QTabletEvent::PointerType::UnknownPointer;
+ QTabletEvent::TabletDevice m_tabletDevice = QTabletEvent::TabletDevice::NoDevice;
+ type m_toolType = type_pen;
+ bool m_hasRotation = false;
+ quint64 m_uid = 0;
+
+ // Accumulated state (applied on frame event)
+ struct State {
+ bool down = false;
+ QPointer<QWaylandSurface> proximitySurface;
+ bool enteredSurface = false; // Not enough with just proximitySurface, if the surface is deleted, we still want to send a leave event
+ QPointF surfacePosition;
+ uint distance = 0;
+ qreal pressure = 0;
+ qreal rotation = 0;
+ qreal xTilt = 0;
+ qreal yTilt = 0;
+ qreal slider = 0;
+ Qt::MouseButtons buttons = Qt::MouseButton::NoButton; // Actual buttons, down state -> left mouse is mapped inside the frame handler
+ //auto operator<=>(const Point&) const = default; // TODO: use this when upgrading to C++20
+ bool operator==(const State &o) const;
+ } m_pending, m_applied;
+};
+
+// We don't actually use this, but need to handle the "removed" event to comply with the protocol
+class Q_WAYLAND_CLIENT_EXPORT QWaylandTabletPadV2 : public QObject, public QtWayland::zwp_tablet_pad_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletPadV2(::zwp_tablet_pad_v2 *pad);
+
+protected:
+// void zwp_tablet_pad_v2_group(struct ::zwp_tablet_pad_group_v2 *pad_group) override;
+// void zwp_tablet_pad_v2_path(const QString &path) override;
+// void zwp_tablet_pad_v2_buttons(uint32_t buttons) override;
+// void zwp_tablet_pad_v2_done() override;
+// void zwp_tablet_pad_v2_button(uint32_t time, uint32_t button, uint32_t state) override;
+// void zwp_tablet_pad_v2_enter(uint32_t serial, struct ::zwp_tablet_v2 *tablet, struct ::wl_surface *surface) override;
+// void zwp_tablet_pad_v2_leave(uint32_t serial, struct ::wl_surface *surface) override;
+ void zwp_tablet_pad_v2_removed() override;
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTABLETV2_P_H
diff --git a/src/client/qwaylandtouch.cpp b/src/client/qwaylandtouch.cpp
index 0394aef31..8f56e7aa6 100644
--- a/src/client/qwaylandtouch.cpp
+++ b/src/client/qwaylandtouch.cpp
@@ -165,22 +165,28 @@ void QWaylandTouchExtension::sendTouchEvent()
QWindowSystemInterface::handleTouchEvent(mTargetWindow, mTimestamp, mTouchDevice, mTouchPoints);
- Qt::TouchPointStates states = 0;
+ Qt::TouchPointStates states = {};
for (int i = 0; i < mTouchPoints.count(); ++i)
states |= mTouchPoints.at(i).state;
if (mFlags & QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH) {
- if (states == Qt::TouchPointPressed)
+ const bool firstPress = states == Qt::TouchPointPressed;
+ if (firstPress)
mMouseSourceId = mTouchPoints.first().id;
for (int i = 0; i < mTouchPoints.count(); ++i) {
const QWindowSystemInterface::TouchPoint &tp(mTouchPoints.at(i));
if (tp.id == mMouseSourceId) {
- Qt::MouseButtons buttons = tp.state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton;
+ const bool released = tp.state == Qt::TouchPointReleased;
+ Qt::MouseButtons buttons = released ? Qt::NoButton : Qt::LeftButton;
+ QEvent::Type eventType = firstPress ? QEvent::MouseButtonPress
+ : released ? QEvent::MouseButtonRelease
+ : QEvent::MouseMove;
mLastMouseGlobal = tp.area.center();
QPoint globalPoint = mLastMouseGlobal.toPoint();
QPointF delta = mLastMouseGlobal - globalPoint;
mLastMouseLocal = mTargetWindow->mapFromGlobal(globalPoint) + delta;
- QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, buttons);
+ QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal,
+ buttons, Qt::LeftButton, eventType);
if (buttons == Qt::NoButton)
mMouseSourceId = -1;
break;
@@ -200,7 +206,7 @@ void QWaylandTouchExtension::touchCanceled()
mTouchPoints.clear();
mPrevTouchPoints.clear();
if (mMouseSourceId != -1)
- QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, Qt::NoButton);
+ QWindowSystemInterface::handleMouseEvent(mTargetWindow, mTimestamp, mLastMouseLocal, mLastMouseGlobal, Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease);
}
void QWaylandTouchExtension::touch_extension_configure(uint32_t flags)
diff --git a/src/client/qwaylandvulkaninstance.cpp b/src/client/qwaylandvulkaninstance.cpp
new file mode 100644
index 000000000..5edbd4757
--- /dev/null
+++ b/src/client/qwaylandvulkaninstance.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of 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 "qwaylandvulkaninstance_p.h"
+#include "qwaylandwindow_p.h"
+#include "qwaylandscreen_p.h"
+#include "qwaylanddisplay_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandVulkanInstance::QWaylandVulkanInstance(QVulkanInstance *instance)
+ : m_instance(instance)
+{
+ loadVulkanLibrary(QStringLiteral("vulkan"));
+}
+
+QWaylandVulkanInstance::~QWaylandVulkanInstance() = default;
+
+void QWaylandVulkanInstance::createOrAdoptInstance()
+{
+ QByteArrayList extraExtensions;
+ extraExtensions << QByteArrayLiteral("VK_KHR_wayland_surface");
+ initInstance(m_instance, extraExtensions);
+
+ if (!m_vkInst)
+ return;
+
+ m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"));
+ if (!m_getPhysDevPresSupport)
+ qWarning() << "Failed to find vkGetPhysicalDeviceWaylandPresentationSupportKHR";
+}
+
+bool QWaylandVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ QWindow *window)
+{
+ if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport)
+ return true;
+
+ auto *w = static_cast<QWaylandWindow *>(window->handle());
+ if (!w) {
+ qWarning() << "Attempted to call supportsPresent() without a valid platform window";
+ return false;
+ }
+ wl_display *display = w->display()->wl_display();
+ bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex, display);
+
+ VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window);
+ VkBool32 supported = false;
+ m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported);
+ ok &= bool(supported);
+
+ return ok;
+}
+
+VkSurfaceKHR QWaylandVulkanInstance::createSurface(QWaylandWindow *window)
+{
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
+
+ if (!m_createSurface) {
+ m_createSurface = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkCreateWaylandSurfaceKHR"));
+ }
+ if (!m_createSurface) {
+ qWarning() << "Failed to find vkCreateWaylandSurfaceKHR";
+ return surface;
+ }
+
+ VkWaylandSurfaceCreateInfoKHR surfaceInfo;
+ memset(&surfaceInfo, 0, sizeof(surfaceInfo));
+ surfaceInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
+ surfaceInfo.display = window->display()->wl_display();
+ surfaceInfo.surface = window->wlSurface();
+ VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create Vulkan surface: %d", err);
+
+ return surface;
+}
+
+void QWaylandVulkanInstance::presentAboutToBeQueued(QWindow *window)
+{
+ auto *w = static_cast<QWaylandWindow *>(window->handle());
+ if (!w) {
+ qWarning() << "Attempted to call presentAboutToBeQueued() without a valid platform window";
+ return;
+ }
+ w->handleUpdate();
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandvulkaninstance_p.h b/src/client/qwaylandvulkaninstance_p.h
new file mode 100644
index 000000000..b68293b78
--- /dev/null
+++ b/src/client/qwaylandvulkaninstance_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of 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 QWAYLANDVULKANINSTANCE_P_H
+#define QWAYLANDVULKANINSTANCE_P_H
+
+#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_WAYLAND_KHR)
+#error "vulkan.h included without Wayland WSI"
+#endif
+
+#define VK_USE_PLATFORM_WAYLAND_KHR
+
+#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
+#include <QLibrary>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandWindow;
+
+class QWaylandVulkanInstance : public QBasicPlatformVulkanInstance
+{
+public:
+ explicit QWaylandVulkanInstance(QVulkanInstance *instance);
+ ~QWaylandVulkanInstance() override;
+
+ void createOrAdoptInstance() override;
+ bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+ void presentAboutToBeQueued(QWindow *window) override;
+
+ VkSurfaceKHR createSurface(QWaylandWindow *window);
+
+private:
+ QVulkanInstance *m_instance = nullptr;
+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR m_getPhysDevPresSupport = nullptr;
+ PFN_vkCreateWaylandSurfaceKHR m_createSurface = nullptr;
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDVULKANINSTANCE_P_H
diff --git a/src/client/qwaylandvulkanwindow.cpp b/src/client/qwaylandvulkanwindow.cpp
new file mode 100644
index 000000000..eb341529a
--- /dev/null
+++ b/src/client/qwaylandvulkanwindow.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 "qwaylandvulkanwindow_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandVulkanWindow::QWaylandVulkanWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
+{
+}
+
+QWaylandVulkanWindow::~QWaylandVulkanWindow()
+{
+ if (m_surface) {
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (inst)
+ static_cast<QWaylandVulkanInstance *>(inst->handle())->destroySurface(m_surface);
+ }
+}
+
+QWaylandWindow::WindowType QWaylandVulkanWindow::windowType() const
+{
+ return QWaylandWindow::Vulkan;
+}
+
+VkSurfaceKHR *QWaylandVulkanWindow::surface()
+{
+ if (m_surface)
+ return &m_surface;
+
+ QVulkanInstance *vulkanInstance = window()->vulkanInstance();
+ if (!vulkanInstance) {
+ qWarning() << "Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?";
+ return nullptr;
+ }
+
+ auto *waylandVulkanInstance = static_cast<QWaylandVulkanInstance *>(vulkanInstance->handle());
+ m_surface = waylandVulkanInstance->createSurface(this);
+
+ return &m_surface;
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandvulkanwindow_p.h b/src/client/qwaylandvulkanwindow_p.h
new file mode 100644
index 000000000..3fd394e62
--- /dev/null
+++ b/src/client/qwaylandvulkanwindow_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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 QWAYLANDVULKANWINDOW_P_H
+#define QWAYLANDVULKANWINDOW_P_H
+
+#include "qwaylandwindow_p.h"
+#include "qwaylandvulkaninstance_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandVulkanWindow : public QWaylandWindow
+{
+public:
+ explicit QWaylandVulkanWindow(QWindow *window, QWaylandDisplay *display);
+ ~QWaylandVulkanWindow() override;
+
+ WindowType windowType() const override;
+
+ VkSurfaceKHR *surface();
+
+private:
+ VkSurfaceKHR m_surface = VK_NULL_HANDLE;
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDVULKANWINDOW_P_H
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 0df99d9fe..8cc26d71c 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -73,9 +73,9 @@ Q_LOGGING_CATEGORY(lcWaylandBackingstore, "qt.qpa.wayland.backingstore")
QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
-QWaylandWindow::QWaylandWindow(QWindow *window)
+QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
: QPlatformWindow(window)
- , mDisplay(waylandScreen()->display())
+ , mDisplay(display)
, mFrameQueue(mDisplay->createEventQueue())
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
{
@@ -177,7 +177,7 @@ void QWaylandWindow::initWindow()
}
}
- mScale = waylandScreen()->scale();
+ mScale = waylandScreen() ? waylandScreen()->scale() : 1; // fallback to 1 if we don't have a real screen
// Enable high-dpi rendering. Scale() returns the screen scale factor and will
// typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
@@ -402,14 +402,14 @@ void QWaylandWindow::closePopups(QWaylandWindow *parent)
}
}
-QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
+QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
{
if (mSurface) {
if (auto *screen = mSurface->oldestEnteredScreen())
return screen;
}
- return waylandScreen();
+ return QPlatformWindow::screen();
}
void QWaylandWindow::setVisible(bool visible)
@@ -672,6 +672,19 @@ QRect QWaylandWindow::windowContentGeometry() const
return QRect(QPoint(), surfaceSize());
}
+/*!
+ * Converts from wl_surface coordinates to Qt window coordinates. Qt window
+ * coordinates start inside (not including) the window decorations, while
+ * wl_surface coordinates start at the first pixel of the buffer. Potentially,
+ * this should be in the window shadow, although we don't have those. So for
+ * now, it's the first pixel of the decorations.
+ */
+QPointF QWaylandWindow::mapFromWlSurface(const QPointF &surfacePosition) const
+{
+ const QMargins margins = frameMargins();
+ return QPointF(surfacePosition.x() - margins.left(), surfacePosition.y() - margins.top());
+}
+
wl_surface *QWaylandWindow::wlSurface()
{
return mSurface ? mSurface->object() : nullptr;
@@ -689,7 +702,11 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
QWaylandScreen *QWaylandWindow::waylandScreen() const
{
- return static_cast<QWaylandScreen *>(QPlatformWindow::screen());
+ auto *platformScreen = QPlatformWindow::screen();
+ Q_ASSERT(platformScreen);
+ if (platformScreen->isPlaceholder())
+ return nullptr;
+ return static_cast<QWaylandScreen *>(platformScreen);
}
void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
@@ -852,7 +869,7 @@ QWaylandWindow *QWaylandWindow::transientParent() const
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{
- if (e.type == QWaylandPointerEvent::Leave) {
+ if (e.type == QEvent::Leave) {
if (mWindowDecoration) {
if (mMouseEventsInContentArea)
QWindowSystemInterface::handleLeaveEvent(window());
@@ -869,24 +886,26 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
handleMouseEventWithDecoration(inputDevice, e);
} else {
switch (e.type) {
- case QWaylandPointerEvent::Enter:
+ case QEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), e.local, e.global);
break;
- case QWaylandPointerEvent::Press:
- case QWaylandPointerEvent::Release:
- case QWaylandPointerEvent::Motion:
- QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, e.local, e.global, e.buttons, e.modifiers);
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, e.local, e.global, e.buttons, e.button, e.type, e.modifiers);
break;
- case QWaylandPointerEvent::Wheel:
+ case QEvent::Wheel:
QWindowSystemInterface::handleWheelEvent(window(), e.timestamp, e.local, e.global,
e.pixelDelta, e.angleDelta, e.modifiers,
e.phase, e.source, false);
break;
+ default:
+ Q_UNREACHABLE();
}
}
#if QT_CONFIG(cursor)
- if (e.type == QWaylandPointerEvent::Enter) {
+ if (e.type == QEvent::Enter) {
QRect contentGeometry = windowContentGeometry().marginsRemoved(frameMargins());
if (contentGeometry.contains(e.local.toPoint()))
restoreMouseCursor(inputDevice);
@@ -918,10 +937,8 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
geometry().size().width() - marg.right(),
geometry().size().height() - marg.bottom());
if (windowRect.contains(e.local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
- QPointF localTranslated = e.local;
+ const QPointF localTranslated = mapFromWlSurface(e.local);
QPointF globalTranslated = e.global;
- localTranslated.setX(localTranslated.x() - marg.left());
- localTranslated.setY(localTranslated.y() - marg.top());
globalTranslated.setX(globalTranslated.x() - marg.left());
globalTranslated.setY(globalTranslated.y() - marg.top());
if (!mMouseEventsInContentArea) {
@@ -932,21 +949,23 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
}
switch (e.type) {
- case QWaylandPointerEvent::Enter:
+ case QEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), localTranslated, globalTranslated);
break;
- case QWaylandPointerEvent::Press:
- case QWaylandPointerEvent::Release:
- case QWaylandPointerEvent::Motion:
- QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.modifiers);
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.button, e.type, e.modifiers);
break;
- case QWaylandPointerEvent::Wheel: {
+ case QEvent::Wheel: {
QWindowSystemInterface::handleWheelEvent(window(), e.timestamp,
localTranslated, globalTranslated,
e.pixelDelta, e.angleDelta, e.modifiers,
e.phase, e.source, false);
break;
}
+ default:
+ Q_UNREACHABLE();
}
mMouseEventsInContentArea = true;
@@ -961,7 +980,7 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
void QWaylandWindow::handleScreensChanged()
{
- QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
+ QPlatformScreen *newScreen = calculateScreenFromSurfaceEvents();
if (newScreen == mLastReportedScreen)
return;
@@ -969,7 +988,7 @@ void QWaylandWindow::handleScreensChanged()
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
mLastReportedScreen = newScreen;
- int scale = newScreen->scale();
+ int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale();
if (scale != mScale) {
mScale = scale;
if (mSurface && mDisplay->compositorVersion() >= 3)
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 5f15ca304..35fa1fdfc 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -89,10 +89,11 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformW
public:
enum WindowType {
Shm,
- Egl
+ Egl,
+ Vulkan
};
- QWaylandWindow(QWindow *window);
+ QWaylandWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandWindow() override;
virtual WindowType windowType() const = 0;
@@ -128,6 +129,7 @@ public:
QMargins frameMargins() const override;
QSize surfaceSize() const;
QRect windowContentGeometry() const;
+ QPointF mapFromWlSurface(const QPointF &surfacePosition) const;
QWaylandSurface *waylandSurface() const { return mSurface.data(); }
::wl_surface *wlSurface();
@@ -240,7 +242,7 @@ protected:
bool mSentInitialResize = false;
QPoint mOffset;
int mScale = 1;
- QWaylandScreen *mLastReportedScreen = nullptr;
+ QPlatformScreen *mLastReportedScreen = nullptr;
QIcon mWindowIcon;
@@ -261,7 +263,7 @@ private:
void reset(bool sendDestroyEvent = true);
void sendExposeEvent(const QRect &rect);
static void closePopups(QWaylandWindow *parent);
- QWaylandScreen *calculateScreenFromSurfaceEvents() const;
+ QPlatformScreen *calculateScreenFromSurfaceEvents() const;
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
void handleScreensChanged();
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index e021b742b..e6402007e 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -196,11 +196,11 @@ void QWaylandCompositorPrivate::init()
if (!socket_name.isEmpty()) {
if (wl_display_add_socket(display, socket_name.constData()))
- qFatal("Fatal: Failed to open server socket\n");
+ qFatal("Fatal: Failed to open server socket: \"%s\". XDG_RUNTIME_DIR is: \"%s\"\n", socket_name.constData(), getenv("XDG_RUNTIME_DIR"));
} else {
const char *autoSocketName = wl_display_add_socket_auto(display);
if (!autoSocketName)
- qFatal("Fatal: Failed to open server socket\n");
+ qFatal("Fatal: Failed to open default server socket. XDG_RUNTIME_DIR is: \"%s\"\n", getenv("XDG_RUNTIME_DIR"));
socket_name = autoSocketName;
emit q->socketNameChanged(socket_name);
}
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 6c4ca8b13..357805393 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -74,7 +74,7 @@ static const struct {
QSGMaterialType materialType;
} bufferTypes[] = {
// BufferFormatEgl_Null
- { "", "", 0, 0, false, 0, {} },
+ { "", "", 0, 0, false, {}, {} },
// BufferFormatEgl_RGB
{
@@ -289,8 +289,9 @@ public:
}
auto texture = buffer.toOpenGLTexture();
+ GLuint textureId = texture->textureId();
auto size = surface->bufferSize();
- m_sgTex = surfaceItem->window()->createTextureFromId(texture->textureId(), size, opt);
+ m_sgTex = surfaceItem->window()->createTextureFromNativeObject(QQuickWindow::NativeObjectTexture, &textureId, 0, size, opt);
#else
qCWarning(qLcWaylandCompositor) << "Without OpenGL support only shared memory textures are supported";
#endif
diff --git a/src/compositor/configure.json b/src/compositor/configure.json
index 0dbb33643..42df2ddf0 100644
--- a/src/compositor/configure.json
+++ b/src/compositor/configure.json
@@ -9,14 +9,34 @@
"libraries": {
"wayland-server": {
"label": "wayland-server",
- "test": "wayland",
+ "headers": "wayland-version.h",
+ "test": {
+ "main": [
+ "#if WAYLAND_VERSION_MAJOR < 1",
+ "# error Wayland 1.8.0 or higher required",
+ "#endif",
+ "#if WAYLAND_VERSION_MAJOR == 1",
+ "# if WAYLAND_VERSION_MINOR < 8",
+ "# error Wayland 1.8.0 or higher required",
+ "# endif",
+ "# if WAYLAND_VERSION_MINOR == 8",
+ "# if WAYLAND_VERSION_MICRO < 0",
+ "# error Wayland 1.8.0 or higher required",
+ "# endif",
+ "# endif",
+ "#endif"
+ ]
+ },
"sources": [
{ "type": "pkgConfig", "args": "wayland-server" },
"-lwayland-server"
]
},
"wayland-egl": {
- "test": "wayland_egl",
+ "headers": "wayland-egl.h",
+ "test": {
+ "main": "struct wl_egl_window *window = wl_egl_window_create(0, 100, 100);"
+ },
"sources": [
{ "type": "pkgConfig", "args": "wayland-egl" },
"-lwayland-egl",
@@ -45,14 +65,24 @@
]
},
"xcomposite": {
- "test": "xcomposite",
+ "headers": "X11/extensions/Xcomposite.h",
+ "test": {
+ "main": "XCompositeRedirectWindow((Display *)0,(Window) 0, CompositeRedirectManual);"
+ },
"sources": [
{ "type": "pkgConfig", "args": "xcomposite" },
"-lxcomposite"
]
},
"glx": {
- "test": "glx",
+ "headers": "GL/glx.h",
+ "test": {
+ "main": [
+ "Display *dpy = XOpenDisplay(0);",
+ "int items = 0;",
+ "GLXFBConfig *fbc = glXChooseFBConfig(dpy, DefaultScreen(dpy), 0 , &items);"
+ ]
+ },
"sources": [
{ "type": "pkgConfig", "args": "x11 gl" },
"-lX11 -lGl"
@@ -68,30 +98,102 @@
},
"drm-egl-server": {
"type": "compile",
- "test": "drm_egl_server",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h"
+ ],
+ "main": [
+ "#ifdef EGL_MESA_drm_image",
+ "return 0;",
+ "#else",
+ "#error Requires EGL_MESA_drm_image to be defined",
+ "return 1;",
+ "#endif"
+ ]
+ },
"use": "egl"
},
"libhybris-egl-server": {
"type": "compile",
- "test": "libhybris_egl_server",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h",
+ "hybris/eglplatformcommon/hybris_nativebufferext.h"
+ ],
+ "main": [
+ "#ifdef EGL_HYBRIS_native_buffer",
+ "return 0;",
+ "#else",
+ "#error Requires EGL_HYBRIS_native_buffer to be defined",
+ "return 1;",
+ "#endif"
+ ]
+ },
"use": "egl"
},
"dmabuf-server-buffer": {
"label": "Linux dma-buf Buffer Sharing",
"type": "compile",
- "test": "dmabuf_server_buffer",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h",
+ "drm_fourcc.h"
+ ],
+ "main": [
+ "#ifdef EGL_LINUX_DMA_BUF_EXT",
+ "return 0;",
+ "#else",
+ "#error Requires EGL_LINUX_DMA_BUF_EXT",
+ "return 1;",
+ "#endif"
+ ]
+ },
"use": "egl drm"
},
"dmabuf-client-buffer": {
"label": "Linux Client dma-buf Buffer Sharing",
"type": "compile",
- "test": "dmabuf_client_buffer",
+ "test": {
+ "include": [
+ "EGL/egl.h",
+ "EGL/eglext.h",
+ "drm_mode.h",
+ "drm_fourcc.h"
+ ],
+ "main": [
+ "// test if DMA BUF is supported",
+ "#ifndef EGL_LINUX_DMA_BUF_EXT",
+ "#error DMA BUF Extension not available",
+ "#endif",
+ "// test if DMA BUF import modifier extension is supported",
+ "#ifndef EGL_EXT_image_dma_buf_import_modifiers",
+ "#error DMA BUF Import modifier extension not available",
+ "#endif",
+ "return 0;"
+ ]
+ },
"use": "egl drm"
},
"vulkan-server-buffer": {
"label": "Vulkan Buffer Sharing",
"type": "compile",
- "test": "vulkan_server_buffer"
+ "test": {
+ "head": [
+ "#define VK_USE_PLATFORM_WAYLAND_KHR 1"
+ ],
+ "include": [
+ "vulkan/vulkan.h"
+ ],
+ "main": [
+ "VkExportMemoryAllocateInfoKHR exportAllocInfo = {};",
+ "exportAllocInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;",
+ "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
+ "return 0;"
+ ]
+ }
}
},
@@ -147,7 +249,7 @@
},
"wayland-vulkan-server-buffer": {
"label": "Vulkan-based server buffer integration",
- "condition": "features.wayland-server && features.opengl && features.egl && tests.vulkan-server-buffer",
+ "condition": "features.wayland-server && features.vulkan && features.opengl && features.egl && tests.vulkan-server-buffer",
"output": [ "privateFeature" ]
},
"wayland-shm-emulation-server-buffer": {
diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp
index 1b8a3c2e2..6b7e86003 100644
--- a/src/compositor/extensions/qwaylandxdgshell.cpp
+++ b/src/compositor/extensions/qwaylandxdgshell.cpp
@@ -1725,7 +1725,7 @@ Qt::Orientations QWaylandXdgPopup::slideConstraints() const
Q_D(const QWaylandXdgPopup);
const uint flags = d->m_positionerData.constraintAdjustments;
- Qt::Orientations constraints = 0;
+ Qt::Orientations constraints = {};
if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
constraints |= Qt::Horizontal;
@@ -1755,7 +1755,7 @@ Qt::Orientations QWaylandXdgPopup::flipConstraints() const
Q_D(const QWaylandXdgPopup);
const uint flags = d->m_positionerData.constraintAdjustments;
- Qt::Orientations constraints = 0;
+ Qt::Orientations constraints = {};
if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
constraints |= Qt::Horizontal;
@@ -1785,7 +1785,7 @@ Qt::Orientations QWaylandXdgPopup::resizeConstraints() const
Q_D(const QWaylandXdgPopup);
const uint flags = d->m_positionerData.constraintAdjustments;
- Qt::Orientations constraints = 0;
+ Qt::Orientations constraints = {};
if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
constraints |= Qt::Horizontal;
diff --git a/src/compositor/extensions/qwaylandxdgshell_p.h b/src/compositor/extensions/qwaylandxdgshell_p.h
index 3223abf3a..de48f481d 100644
--- a/src/compositor/extensions/qwaylandxdgshell_p.h
+++ b/src/compositor/extensions/qwaylandxdgshell_p.h
@@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE
struct Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPositionerData {
QSize size;
QRect anchorRect;
- Qt::Edges anchorEdges = 0;
- Qt::Edges gravityEdges = 0;
+ Qt::Edges anchorEdges = {};
+ Qt::Edges gravityEdges = {};
uint constraintAdjustments = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE;
QPoint offset;
QWaylandXdgPositionerData();
diff --git a/src/compositor/extensions/qwaylandxdgshellv6.cpp b/src/compositor/extensions/qwaylandxdgshellv6.cpp
index 934dccb06..94c430aad 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv6.cpp
@@ -1656,7 +1656,7 @@ Qt::Orientations QWaylandXdgPopupV6::slideConstraints() const
Q_D(const QWaylandXdgPopupV6);
const uint flags = d->m_positionerData.constraintAdjustments;
- Qt::Orientations constraints = 0;
+ Qt::Orientations constraints = {};
if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X)
constraints |= Qt::Horizontal;
@@ -1686,7 +1686,7 @@ Qt::Orientations QWaylandXdgPopupV6::flipConstraints() const
Q_D(const QWaylandXdgPopupV6);
const uint flags = d->m_positionerData.constraintAdjustments;
- Qt::Orientations constraints = 0;
+ Qt::Orientations constraints = {};
if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X)
constraints |= Qt::Horizontal;
@@ -1716,7 +1716,7 @@ Qt::Orientations QWaylandXdgPopupV6::resizeConstraints() const
Q_D(const QWaylandXdgPopupV6);
const uint flags = d->m_positionerData.constraintAdjustments;
- Qt::Orientations constraints = 0;
+ Qt::Orientations constraints = {};
if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X)
constraints |= Qt::Horizontal;
diff --git a/src/compositor/extensions/qwaylandxdgshellv6_p.h b/src/compositor/extensions/qwaylandxdgshellv6_p.h
index 457bc2201..f13e73da4 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6_p.h
+++ b/src/compositor/extensions/qwaylandxdgshellv6_p.h
@@ -61,8 +61,8 @@ QT_BEGIN_NAMESPACE
struct Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPositionerV6Data {
QSize size;
QRect anchorRect;
- Qt::Edges anchorEdges = 0;
- Qt::Edges gravityEdges = 0;
+ Qt::Edges anchorEdges = {};
+ Qt::Edges gravityEdges = {};
uint constraintAdjustments = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
QPoint offset;
QWaylandXdgPositionerV6Data();
diff --git a/src/compositor/extensions/qwltexturesharingextension.cpp b/src/compositor/extensions/qwltexturesharingextension.cpp
index 6f801e956..bbd18e1a5 100644
--- a/src/compositor/extensions/qwltexturesharingextension.cpp
+++ b/src/compositor/extensions/qwltexturesharingextension.cpp
@@ -301,13 +301,13 @@ QString QWaylandTextureSharingExtension::getExistingFilePath(const QString &key)
if (key.contains(QLatin1String("../")))
return QString();
- for (auto dir : m_image_dirs) {
+ for (auto dir : qAsConst(m_image_dirs)) {
QString path = dir + key;
if (QFileInfo::exists(path))
return path;
}
- for (auto dir : m_image_dirs) {
+ for (auto dir : qAsConst(m_image_dirs)) {
for (auto ext : m_image_suffixes) {
QString fp = dir + key + ext;
//qDebug() << "trying" << fp;
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp
index 3a34d2561..0dc389bb8 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp
@@ -143,7 +143,7 @@ bool QWaylandEglClientBufferIntegration::supportsWindowDecoration() const
QWaylandWindow *QWaylandEglClientBufferIntegration::createEglWindow(QWindow *window)
{
- return new QWaylandEglWindow(window);
+ return new QWaylandEglWindow(window, m_display);
}
QPlatformOpenGLContext *QWaylandEglClientBufferIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
index 030422c56..e8d43fad4 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
@@ -54,8 +54,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandEglWindow::QWaylandEglWindow(QWindow *window)
- : QWaylandWindow(window)
+QWaylandEglWindow::QWaylandEglWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
, m_clientBufferIntegration(static_cast<QWaylandEglClientBufferIntegration *>(mDisplay->clientBufferIntegration()))
{
QSurfaceFormat fmt = window->requestedFormat();
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
index 9e6cb876c..878532afc 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
@@ -56,7 +56,7 @@ class QWaylandEglWindow : public QWaylandWindow
{
Q_OBJECT
public:
- QWaylandEglWindow(QWindow *window);
+ QWaylandEglWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandEglWindow();
WindowType windowType() const override;
void ensureSize() override;
diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp
index 57a7ba7b6..a7377830f 100644
--- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp
+++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
QWaylandXCompositeEGLWindow::QWaylandXCompositeEGLWindow(QWindow *window, QWaylandXCompositeEGLClientBufferIntegration *glxIntegration)
- : QWaylandWindow(window)
+ : QWaylandWindow(window, glxIntegration->waylandDisplay())
, m_glxIntegration(glxIntegration)
, m_config(q_configFromGLFormat(glxIntegration->eglDisplay(), window->format(), true, EGL_WINDOW_BIT | EGL_PIXMAP_BIT))
{
diff --git a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxwindow.cpp b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxwindow.cpp
index 2b491e24d..b0c78b631 100644
--- a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxwindow.cpp
+++ b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxwindow.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
QWaylandXCompositeGLXWindow::QWaylandXCompositeGLXWindow(QWindow *window, QWaylandXCompositeGLXIntegration *glxIntegration)
- : QWaylandWindow(window)
+ : QWaylandWindow(window, glxIntegration->waylandDisplay())
, m_glxIntegration(glxIntegration)
, m_config(qglx_findConfig(glxIntegration->xDisplay(), glxIntegration->screen(), window->format(), GLX_WINDOW_BIT | GLX_PIXMAP_BIT))
{
diff --git a/src/plugins/hardwareintegration/compositor/brcm-egl/brcm-egl.pro b/src/plugins/hardwareintegration/compositor/brcm-egl/brcm-egl.pro
index 53f7af8aa..c89ecec00 100644
--- a/src/plugins/hardwareintegration/compositor/brcm-egl/brcm-egl.pro
+++ b/src/plugins/hardwareintegration/compositor/brcm-egl/brcm-egl.pro
@@ -5,6 +5,8 @@ OTHER_FILES += brcm-egl.json
SOURCES += \
main.cpp
+TARGET = qt-wayland-compositor-brcm-egl
+
include(../../../../hardwareintegration/compositor/brcm-egl/brcm-egl.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
diff --git a/src/plugins/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pro b/src/plugins/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pro
index 1601a384c..d96e58135 100644
--- a/src/plugins/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pro
+++ b/src/plugins/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pro
@@ -5,7 +5,9 @@ OTHER_FILES += dmabuf-server.json
SOURCES += \
main.cpp
-include($PWD/../../../../../hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri)
+TARGET = qt-wayland-compositor-dmabuf-server-buffer
+
+include(../../../../hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
PLUGIN_CLASS_NAME = DmaBufServerBufferIntegrationPlugin
diff --git a/src/plugins/hardwareintegration/compositor/drm-egl-server/drm-egl-server.pro b/src/plugins/hardwareintegration/compositor/drm-egl-server/drm-egl-server.pro
index 040031122..2ba17c388 100644
--- a/src/plugins/hardwareintegration/compositor/drm-egl-server/drm-egl-server.pro
+++ b/src/plugins/hardwareintegration/compositor/drm-egl-server/drm-egl-server.pro
@@ -5,7 +5,9 @@ OTHER_FILES += drm-egl-server.json
SOURCES += \
main.cpp
-include($PWD/../../../../../hardwareintegration/compositor/drm-egl-server/drm-egl-server.pri)
+TARGET = qt-wayland-compositor-drm-egl-server-buffer
+
+include(../../../../hardwareintegration/compositor/drm-egl-server/drm-egl-server.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
PLUGIN_CLASS_NAME = DrmEglServerBufferIntegrationPlugin
diff --git a/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro
index ff16b20bf..c18884a96 100644
--- a/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro
+++ b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro
@@ -7,7 +7,9 @@ OTHER_FILES += vsp2.json
SOURCES += \
main.cpp
-include($PWD/../../../../../../hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pri)
+TARGET = qt-wayland-compositor-vsp2
+
+include(../../../../../hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pri)
PLUGIN_TYPE = wayland-hardware-layer-integration
PLUGIN_CLASS_NAME = Vsp2HardwareLayerIntegrationPlugin
diff --git a/src/plugins/hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pro b/src/plugins/hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pro
index 9e28c7e8c..c9c3a0daf 100644
--- a/src/plugins/hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pro
+++ b/src/plugins/hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pro
@@ -5,7 +5,9 @@ OTHER_FILES += libhybris-egl-server.json
SOURCES += \
main.cpp
-include($PWD/../../../../../hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pri)
+TARGET = qt-wayland-compositor-libybris-egl-server.json
+
+include(../../../../hardwareintegration/compositor/libhybris-egl-server/libhybris-egl-server.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
PLUGIN_CLASS_NAME = LibHybrisEglServerBufferIntegrationPlugin
diff --git a/src/plugins/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pro b/src/plugins/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pro
index bc4311423..1f76f9f00 100644
--- a/src/plugins/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pro
+++ b/src/plugins/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pro
@@ -5,6 +5,8 @@ OTHER_FILES += linux-dmabuf.json
SOURCES += \
main.cpp \
+TARGET = qt-wayland-compositor-linux-dmabuf-unstable-v1
+
include(../../../../hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
diff --git a/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro b/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro
index 56a1bac21..865af1a7d 100644
--- a/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro
+++ b/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro
@@ -5,7 +5,9 @@ OTHER_FILES += shm-emulation-server.json
SOURCES += \
main.cpp
-include($PWD/../../../../../hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri)
+TARGET = qt-wayland-compositor-shm-emulation-server
+
+include(../../../../hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
PLUGIN_CLASS_NAME = ShmServerBufferIntegrationPlugin
diff --git a/src/plugins/hardwareintegration/compositor/vulkan-server/vulkan-server.pro b/src/plugins/hardwareintegration/compositor/vulkan-server/vulkan-server.pro
index 053654218..dc82c3f26 100644
--- a/src/plugins/hardwareintegration/compositor/vulkan-server/vulkan-server.pro
+++ b/src/plugins/hardwareintegration/compositor/vulkan-server/vulkan-server.pro
@@ -5,7 +5,9 @@ OTHER_FILES += vulkan-server.json
SOURCES += \
main.cpp
-include($PWD/../../../../../hardwareintegration/compositor/vulkan-server/vulkan-server.pri)
+TARGET = qt-wayland-compositor-vulkan-server
+
+include(../../../../hardwareintegration/compositor/vulkan-server/vulkan-server.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
PLUGIN_CLASS_NAME = VulkanServerBufferIntegrationPlugin
diff --git a/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro b/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro
index 6aecefffd..d452220c5 100644
--- a/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro
+++ b/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro
@@ -5,7 +5,7 @@ OTHER_FILES += wayland-egl.json
SOURCES += \
main.cpp
-TARGET = qt-plugin-wayland-egl
+TARGET = qt-wayland-compositor-wayland-egl
include(../../../../hardwareintegration/compositor/wayland-egl/wayland-egl.pri)
diff --git a/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro
index f1ca7183a..6d259a687 100644
--- a/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro
+++ b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro
@@ -5,6 +5,8 @@ OTHER_FILES += wayland-eglstream-controller.json
SOURCES += \
main.cpp \
+TARGET = qt-wayland-compositor-wayland-eglstream-controller
+
include(../../../../hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
diff --git a/src/plugins/hardwareintegration/compositor/xcomposite-egl/xcomposite-egl.pro b/src/plugins/hardwareintegration/compositor/xcomposite-egl/xcomposite-egl.pro
index 7c391bd1c..298ed2fc6 100644
--- a/src/plugins/hardwareintegration/compositor/xcomposite-egl/xcomposite-egl.pro
+++ b/src/plugins/hardwareintegration/compositor/xcomposite-egl/xcomposite-egl.pro
@@ -5,6 +5,8 @@ OTHER_FILES += xcomposite-egl.json
SOURCES += \
main.cpp
+TARGET = qt-wayland-compositor-xcomposite-egl
+
include(../../../../hardwareintegration/compositor/xcomposite-egl/xcomposite-egl.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
diff --git a/src/plugins/hardwareintegration/compositor/xcomposite-glx/xcomposite-glx.pro b/src/plugins/hardwareintegration/compositor/xcomposite-glx/xcomposite-glx.pro
index 0f49471da..41e5c2ec5 100644
--- a/src/plugins/hardwareintegration/compositor/xcomposite-glx/xcomposite-glx.pro
+++ b/src/plugins/hardwareintegration/compositor/xcomposite-glx/xcomposite-glx.pro
@@ -5,6 +5,8 @@ OTHER_FILES += xcomposite-glx.json
SOURCES += \
main.cpp
+TARGET = qt-wayland-compositor-xcomposite-glx
+
include(../../../../hardwareintegration/compositor/xcomposite-glx/xcomposite-glx.pri)
PLUGIN_TYPE = wayland-graphics-integration-server
diff --git a/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp b/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp
index 26f598895..636ef0807 100644
--- a/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp
+++ b/src/plugins/shellintegration/fullscreen-shell-v1/qwaylandfullscreenshellv1surface.cpp
@@ -50,10 +50,11 @@ QWaylandFullScreenShellV1Surface::QWaylandFullScreenShellV1Surface(QtWayland::zw
, m_shell(shell)
, m_window(window)
{
- auto screen = static_cast<QWaylandScreen *>(m_window->screen());
+ auto *screen = m_window->waylandScreen();
+ auto *output = screen ? screen->output() : nullptr;
m_shell->present_surface(m_window->wlSurface(),
QtWayland::zwp_fullscreen_shell_v1::present_method_default,
- screen->output());
+ output);
}
} // namespace QtWaylandClient
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index 9691b857f..05f00beee 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -92,7 +92,7 @@ private:
};
bool isServerSide();
- bool parseOption(const char *str);
+ bool parseOption(const QByteArray &str);
QByteArray byteArrayValue(const QXmlStreamReader &xml, const char *name);
int intValue(const QXmlStreamReader &xml, const char *name, int defaultValue = 0);
@@ -123,29 +123,55 @@ private:
QByteArray m_scannerName;
QByteArray m_headerPath;
QByteArray m_prefix;
+ QVector <QByteArray> m_includes;
QXmlStreamReader *m_xml = nullptr;
};
bool Scanner::parseArguments(int argc, char **argv)
{
- m_scannerName = argv[0];
+ QVector<QByteArray> args;
+ args.reserve(argc);
+ for (int i = 0; i < argc; ++i)
+ args << QByteArray(argv[i]);
- if (argc <= 2 || !parseOption(argv[1]))
+ m_scannerName = args[0];
+
+ if (argc <= 2 || !parseOption(args[1]))
return false;
- m_protocolFilePath = QByteArray(argv[2]);
+ m_protocolFilePath = args[2];
- if (argc >= 4)
- m_headerPath = QByteArray(argv[3]);
- if (argc == 5)
- m_prefix = QByteArray(argv[4]);
+ if (argc > 3 && !args[3].startsWith('-')) {
+ // legacy positional arguments
+ m_headerPath = args[3];
+ if (argc == 5)
+ m_prefix = args[4];
+ } else {
+ // --header-path=<path> (14 characters)
+ // --prefix=<prefix> (9 characters)
+ // --add-include=<include> (14 characters)
+ for (int pos = 3; pos < argc; pos++) {
+ const QByteArray &option = args[pos];
+ if (option.startsWith("--header-path=")) {
+ m_headerPath = option.mid(14);
+ } else if (option.startsWith("--prefix=")) {
+ m_prefix = option.mid(10);
+ } else if (option.startsWith("--add-include=")) {
+ auto include = option.mid(14);
+ if (!include.isEmpty())
+ m_includes << include;
+ } else {
+ return false;
+ }
+ }
+ }
return true;
}
void Scanner::printUsage()
{
- fprintf(stderr, "Usage: %s [client-header|server-header|client-code|server-code] specfile [header-path] [prefix]\n", m_scannerName.constData());
+ fprintf(stderr, "Usage: %s [client-header|server-header|client-code|server-code] specfile [--header-path=<path>] [--prefix=<prefix>] [--add-include=<include>]\n", m_scannerName.constData());
}
bool Scanner::isServerSide()
@@ -153,15 +179,15 @@ bool Scanner::isServerSide()
return m_option == ServerHeader || m_option == ServerCode;
}
-bool Scanner::parseOption(const char *str)
+bool Scanner::parseOption(const QByteArray &str)
{
- if (str == QLatin1String("client-header"))
+ if (str == "client-header")
m_option = ClientHeader;
- else if (str == QLatin1String("server-header"))
+ else if (str == "server-header")
m_option = ServerHeader;
- else if (str == QLatin1String("client-code"))
+ else if (str == "client-code")
m_option = ClientCode;
- else if (str == QLatin1String("server-code"))
+ else if (str == "server-code")
m_option = ServerCode;
else
return false;
@@ -441,6 +467,12 @@ bool Scanner::process()
if (m_xml->hasError())
return false;
+ printf("// This file was generated by qtwaylandscanner\n");
+ printf("// source file is %s\n\n", qPrintable(m_protocolFilePath));
+
+ for (auto b : qAsConst(m_includes))
+ printf("#include %s\n", b.constData());
+
if (m_option == ServerHeader) {
QByteArray inclusionGuard = QByteArray("QT_WAYLAND_SERVER_") + preProcessorProtocolName.constData();
printf("#ifndef %s\n", inclusionGuard.constData());