summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/CMakeLists.txt169
-rw-r--r--src/client/Qt6WaylandClientMacros.cmake119
-rw-r--r--src/client/client.pro154
-rw-r--r--src/client/configure.cmake56
-rw-r--r--src/client/configure.json300
-rw-r--r--src/client/doc/qtwaylandclient.qdocconf31
-rw-r--r--src/client/doc/src/cmake/qt_generate_wayland_protocol_client_sources.qdoc51
-rw-r--r--src/client/doc/src/qtwaylandclient-overview.qdoc36
-rw-r--r--src/client/global/qwaylandclientextension.cpp104
-rw-r--r--src/client/global/qwaylandclientextension.h74
-rw-r--r--src/client/global/qwaylandclientextension_p.h52
-rw-r--r--src/client/hardwareintegration/qwaylandclientbufferintegration.cpp40
-rw-r--r--src/client/hardwareintegration/qwaylandclientbufferintegration_p.h44
-rw-r--r--src/client/hardwareintegration/qwaylandclientbufferintegrationfactory.cpp82
-rw-r--r--src/client/hardwareintegration/qwaylandclientbufferintegrationfactory_p.h47
-rw-r--r--src/client/hardwareintegration/qwaylandclientbufferintegrationplugin.cpp42
-rw-r--r--src/client/hardwareintegration/qwaylandclientbufferintegrationplugin_p.h43
-rw-r--r--src/client/hardwareintegration/qwaylandhardwareintegration.cpp40
-rw-r--r--src/client/hardwareintegration/qwaylandhardwareintegration_p.h43
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegration.cpp40
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegration_p.h45
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegrationfactory.cpp82
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegrationfactory_p.h47
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegrationplugin.cpp42
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegrationplugin_p.h43
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h44
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp82
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h47
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp42
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h43
-rw-r--r--src/client/qt_cmdline.cmake0
-rw-r--r--src/client/qtwaylandclientglobal.h60
-rw-r--r--src/client/qtwaylandclientglobal_p.h42
-rw-r--r--src/client/qwaylandabstractdecoration.cpp54
-rw-r--r--src/client/qwaylandabstractdecoration_p.h57
-rw-r--r--src/client/qwaylandbuffer.cpp49
-rw-r--r--src/client/qwaylandbuffer_p.h48
-rw-r--r--src/client/qwaylandclipboard.cpp67
-rw-r--r--src/client/qwaylandclipboard_p.h44
-rw-r--r--src/client/qwaylandcursor.cpp160
-rw-r--r--src/client/qwaylandcursor_p.h73
-rw-r--r--src/client/qwaylanddatadevice.cpp199
-rw-r--r--src/client/qwaylanddatadevice_p.h54
-rw-r--r--src/client/qwaylanddatadevicemanager.cpp44
-rw-r--r--src/client/qwaylanddatadevicemanager_p.h44
-rw-r--r--src/client/qwaylanddataoffer.cpp200
-rw-r--r--src/client/qwaylanddataoffer_p.h51
-rw-r--r--src/client/qwaylanddatasource.cpp87
-rw-r--r--src/client/qwaylanddatasource_p.h55
-rw-r--r--src/client/qwaylanddecorationfactory.cpp83
-rw-r--r--src/client/qwaylanddecorationfactory_p.h47
-rw-r--r--src/client/qwaylanddecorationplugin.cpp42
-rw-r--r--src/client/qwaylanddecorationplugin_p.h43
-rw-r--r--src/client/qwaylanddisplay.cpp933
-rw-r--r--src/client/qwaylanddisplay_p.h270
-rw-r--r--src/client/qwaylanddnd.cpp80
-rw-r--r--src/client/qwaylanddnd_p.h50
-rw-r--r--src/client/qwaylandextendedsurface.cpp128
-rw-r--r--src/client/qwaylandextendedsurface_p.h93
-rw-r--r--src/client/qwaylandfractionalscale.cpp31
-rw-r--r--src/client/qwaylandfractionalscale_p.h52
-rw-r--r--src/client/qwaylandinputcontext.cpp546
-rw-r--r--src/client/qwaylandinputcontext_p.h128
-rw-r--r--src/client/qwaylandinputdevice.cpp561
-rw-r--r--src/client/qwaylandinputdevice_p.h229
-rw-r--r--src/client/qwaylandinputmethodcontext.cpp401
-rw-r--r--src/client/qwaylandinputmethodcontext_p.h118
-rw-r--r--src/client/qwaylandintegration.cpp230
-rw-r--r--src/client/qwaylandintegration_p.h71
-rw-r--r--src/client/qwaylandnativeinterface.cpp172
-rw-r--r--src/client/qwaylandnativeinterface_p.h73
-rw-r--r--src/client/qwaylandplatformservices.cpp50
-rw-r--r--src/client/qwaylandplatformservices_p.h48
-rw-r--r--src/client/qwaylandpointergestures.cpp211
-rw-r--r--src/client/qwaylandpointergestures_p.h115
-rw-r--r--src/client/qwaylandprimaryselectionv1.cpp55
-rw-r--r--src/client/qwaylandprimaryselectionv1_p.h46
-rw-r--r--src/client/qwaylandqtkey.cpp45
-rw-r--r--src/client/qwaylandqtkey_p.h44
-rw-r--r--src/client/qwaylandscreen.cpp210
-rw-r--r--src/client/qwaylandscreen_p.h85
-rw-r--r--src/client/qwaylandshellsurface.cpp102
-rw-r--r--src/client/qwaylandshellsurface_p.h88
-rw-r--r--src/client/qwaylandshm.cpp42
-rw-r--r--src/client/qwaylandshm_p.h47
-rw-r--r--src/client/qwaylandshmbackingstore.cpp167
-rw-r--r--src/client/qwaylandshmbackingstore_p.h57
-rw-r--r--src/client/qwaylandshmwindow.cpp46
-rw-r--r--src/client/qwaylandshmwindow_p.h44
-rw-r--r--src/client/qwaylandsubsurface.cpp40
-rw-r--r--src/client/qwaylandsubsurface_p.h44
-rw-r--r--src/client/qwaylandsurface.cpp76
-rw-r--r--src/client/qwaylandsurface_p.h55
-rw-r--r--src/client/qwaylandtabletv2.cpp314
-rw-r--r--src/client/qwaylandtabletv2_p.h161
-rw-r--r--src/client/qwaylandtextinputinterface.cpp8
-rw-r--r--src/client/qwaylandtextinputinterface_p.h61
-rw-r--r--src/client/qwaylandtextinputv1.cpp362
-rw-r--r--src/client/qwaylandtextinputv1_p.h112
-rw-r--r--src/client/qwaylandtextinputv2.cpp375
-rw-r--r--src/client/qwaylandtextinputv2_p.h110
-rw-r--r--src/client/qwaylandtextinputv3.cpp372
-rw-r--r--src/client/qwaylandtextinputv3_p.h102
-rw-r--r--src/client/qwaylandtouch.cpp89
-rw-r--r--src/client/qwaylandtouch_p.h46
-rw-r--r--src/client/qwaylandviewport.cpp35
-rw-r--r--src/client/qwaylandviewport_p.h42
-rw-r--r--src/client/qwaylandvulkaninstance.cpp70
-rw-r--r--src/client/qwaylandvulkaninstance_p.h57
-rw-r--r--src/client/qwaylandvulkanwindow.cpp63
-rw-r--r--src/client/qwaylandvulkanwindow_p.h56
-rw-r--r--src/client/qwaylandwindow.cpp1309
-rw-r--r--src/client/qwaylandwindow_p.h223
-rw-r--r--src/client/qwaylandwindowmanagerintegration.cpp102
-rw-r--r--src/client/qwaylandwindowmanagerintegration_p.h64
-rw-r--r--src/client/shellintegration/qwaylandclientshellapi_p.h34
-rw-r--r--src/client/shellintegration/qwaylandshellintegration.cpp18
-rw-r--r--src/client/shellintegration/qwaylandshellintegration_p.h105
-rw-r--r--src/client/shellintegration/qwaylandshellintegrationfactory.cpp85
-rw-r--r--src/client/shellintegration/qwaylandshellintegrationfactory_p.h46
-rw-r--r--src/client/shellintegration/qwaylandshellintegrationplugin.cpp42
-rw-r--r--src/client/shellintegration/qwaylandshellintegrationplugin_p.h43
122 files changed, 8038 insertions, 6038 deletions
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
new file mode 100644
index 000000000..4d0a106f6
--- /dev/null
+++ b/src/client/CMakeLists.txt
@@ -0,0 +1,169 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Generated from client.pro.
+
+#####################################################################
+## WaylandClient Module:
+#####################################################################
+
+qt_internal_add_module(WaylandClient
+ PLUGIN_TYPES wayland-graphics-integration-client wayland-inputdevice-integration wayland-decoration-client wayland-shell-integration
+ SOURCES
+ ../shared/qwaylandinputmethodeventbuilder.cpp ../shared/qwaylandinputmethodeventbuilder_p.h
+ ../shared/qwaylandmimehelper.cpp ../shared/qwaylandmimehelper_p.h
+ ../shared/qwaylandsharedmemoryformathelper_p.h
+ global/qwaylandclientextension.cpp global/qwaylandclientextension.h global/qwaylandclientextension_p.h
+ hardwareintegration/qwaylandclientbufferintegration.cpp hardwareintegration/qwaylandclientbufferintegration_p.h
+ hardwareintegration/qwaylandclientbufferintegrationfactory.cpp hardwareintegration/qwaylandclientbufferintegrationfactory_p.h
+ hardwareintegration/qwaylandclientbufferintegrationplugin.cpp hardwareintegration/qwaylandclientbufferintegrationplugin_p.h
+ hardwareintegration/qwaylandhardwareintegration.cpp hardwareintegration/qwaylandhardwareintegration_p.h
+ hardwareintegration/qwaylandserverbufferintegration.cpp hardwareintegration/qwaylandserverbufferintegration_p.h
+ hardwareintegration/qwaylandserverbufferintegrationfactory.cpp hardwareintegration/qwaylandserverbufferintegrationfactory_p.h
+ hardwareintegration/qwaylandserverbufferintegrationplugin.cpp hardwareintegration/qwaylandserverbufferintegrationplugin_p.h
+ inputdeviceintegration/qwaylandinputdeviceintegration_p.h
+ inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h
+ inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h
+ qtwaylandclientglobal.h qtwaylandclientglobal_p.h
+ qwaylandabstractdecoration.cpp qwaylandabstractdecoration_p.h
+ qwaylandbuffer.cpp qwaylandbuffer_p.h
+ qwaylanddecorationfactory.cpp qwaylanddecorationfactory_p.h
+ qwaylanddecorationplugin.cpp qwaylanddecorationplugin_p.h
+ qwaylanddisplay.cpp qwaylanddisplay_p.h
+ qwaylandfractionalscale.cpp qwaylandfractionalscale_p.h
+ qwaylandinputcontext.cpp qwaylandinputcontext_p.h
+ qwaylandtextinputv1.cpp qwaylandtextinputv1_p.h
+ qwaylandtextinputv2.cpp qwaylandtextinputv2_p.h
+ qwaylandtextinputv3.cpp qwaylandtextinputv3_p.h
+ qwaylandtextinputinterface.cpp qwaylandtextinputinterface_p.h
+ qwaylandinputdevice.cpp qwaylandinputdevice_p.h
+ qwaylandinputmethodcontext.cpp qwaylandinputmethodcontext_p.h
+ qwaylandintegration.cpp qwaylandintegration_p.h
+ qwaylandnativeinterface.cpp qwaylandnativeinterface_p.h
+ qwaylandplatformservices.cpp qwaylandplatformservices_p.h
+ qwaylandpointergestures.cpp qwaylandpointergestures_p.h
+ qwaylandqtkey.cpp qwaylandqtkey_p.h
+ qwaylandscreen.cpp qwaylandscreen_p.h
+ qwaylandshellsurface.cpp qwaylandshellsurface_p.h
+ qwaylandshm.cpp qwaylandshm_p.h
+ qwaylandshmbackingstore.cpp qwaylandshmbackingstore_p.h
+ qwaylandshmwindow.cpp qwaylandshmwindow_p.h
+ qwaylandsubsurface.cpp qwaylandsubsurface_p.h
+ qwaylandsurface.cpp qwaylandsurface_p.h
+ qwaylandtouch.cpp qwaylandtouch_p.h
+ qwaylandviewport.cpp qwaylandviewport_p.h
+ qwaylandwindow.cpp qwaylandwindow_p.h
+ qwaylandwindowmanagerintegration.cpp qwaylandwindowmanagerintegration_p.h
+ shellintegration/qwaylandclientshellapi_p.h
+ shellintegration/qwaylandshellintegration_p.h shellintegration/qwaylandshellintegration.cpp
+ shellintegration/qwaylandshellintegrationfactory.cpp shellintegration/qwaylandshellintegrationfactory_p.h
+ shellintegration/qwaylandshellintegrationplugin.cpp shellintegration/qwaylandshellintegrationplugin_p.h
+ INCLUDE_DIRECTORIES
+ ../shared
+ global
+ hardwareintegration
+ inputdeviceintegration
+ shellintegration
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::GuiPrivate
+ Qt::WaylandGlobalPrivate
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Wayland::Client
+ PRIVATE_MODULE_INTERFACE
+ Qt::CorePrivate
+ Qt::GuiPrivate
+ Qt::WaylandGlobalPrivate
+ PRIVATE_HEADER_FILTERS
+ "^qwayland-.*\.h|^wayland-.*-protocol\.h"
+)
+
+qt6_generate_wayland_protocol_client_sources(WaylandClient
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/cursor-shape-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/pointer-gestures-unstable-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/tablet-unstable-v2.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/text-input-unstable-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/text-input-unstable-v2.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/text-input-unstable-v3.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/wayland.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/wp-primary-selection-unstable-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-output-unstable-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/fractional-scale-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/viewporter.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-shell.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-toplevel-drag-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-key-unstable-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-text-input-method-unstable-v1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-windowmanager.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/touch-extension.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardwareintegration/../../extensions/hardware-integration.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardwareintegration/../../extensions/server-buffer-extension.xml
+)
+
+#### Keys ignored in scope 1:.:.:client.pro:<TRUE>:
+# MODULE = "waylandclient"
+# QMAKE_CXXFLAGS_WARN_ON = "--Wcast-qual"
+
+## Scopes:
+#####################################################################
+
+# special case begin
+#
+# Do not explicitly add XKB::XKB. This is already done by Qt::GuiPrivate.
+#
+# qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_xkbcommon
+# PUBLIC_LIBRARIES
+# XKB::XKB
+# )
+# special case end
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_tabletevent
+ SOURCES
+ qwaylandtabletv2.cpp qwaylandtabletv2_p.h
+)
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_clipboard
+ SOURCES
+ qwaylandclipboard.cpp qwaylandclipboard_p.h
+)
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_vulkan
+ SOURCES
+ qwaylandvulkaninstance.cpp qwaylandvulkaninstance_p.h
+ qwaylandvulkanwindow.cpp qwaylandvulkanwindow_p.h
+)
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_cursor
+ SOURCES
+ qwaylandcursor.cpp qwaylandcursor_p.h
+ PUBLIC_LIBRARIES
+ Wayland::Cursor
+)
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_wayland_datadevice
+ SOURCES
+ qwaylanddatadevice.cpp qwaylanddatadevice_p.h
+ qwaylanddatadevicemanager.cpp qwaylanddatadevicemanager_p.h
+ qwaylanddataoffer.cpp qwaylanddataoffer_p.h
+ qwaylanddatasource.cpp qwaylanddatasource_p.h
+)
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_wayland_client_primary_selection
+ SOURCES
+ qwaylandprimaryselectionv1.cpp qwaylandprimaryselectionv1_p.h
+)
+
+qt_internal_extend_target(WaylandClient CONDITION QT_FEATURE_draganddrop
+ SOURCES
+ qwaylanddnd.cpp qwaylanddnd_p.h
+)
+
+qt_internal_add_docs(WaylandClient
+ doc/qtwaylandclient.qdocconf
+)
+
+qt_record_extra_qt_main_tools_package_dependency(WaylandClient WaylandScannerTools "${PROJECT_VERSION}")
+qt_record_extra_qt_package_dependency(WaylandClient WaylandGlobalPrivate "${PROJECT_VERSION}")
diff --git a/src/client/Qt6WaylandClientMacros.cmake b/src/client/Qt6WaylandClientMacros.cmake
new file mode 100644
index 000000000..b4266c558
--- /dev/null
+++ b/src/client/Qt6WaylandClientMacros.cmake
@@ -0,0 +1,119 @@
+
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+function(qt6_generate_wayland_protocol_client_sources target)
+ cmake_parse_arguments(arg
+ "NO_INCLUDE_CORE_ONLY;PRIVATE_CODE;PUBLIC_CODE"
+ "__QT_INTERNAL_WAYLAND_INCLUDE_DIR"
+ "FILES"
+ ${ARGN})
+
+ if(DEFINED arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments were passed to qt6_generate_wayland_protocol_client_sources: (${arg_UNPARSED_ARGUMENTS}).")
+ endif()
+
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+
+ if(NOT TARGET Wayland::Scanner)
+ message(FATAL_ERROR "Wayland::Scanner target not found. You might be missing the WaylandScanner CMake package.")
+ endif()
+
+ if(NOT TARGET Qt6::qtwaylandscanner)
+ message(FATAL_ERROR "qtwaylandscanner executable not found. Most likely there is an issue with your Qt installation.")
+ endif()
+
+ string(TOUPPER "${target}" module_define_infix)
+ string(REPLACE "-" "_" module_define_infix "${module_define_infix}")
+ string(REPLACE "." "_" module_define_infix "${module_define_infix}")
+ set(build_macro "QT_BUILD_${module_define_infix}_LIB")
+
+ foreach(protocol_file IN LISTS arg_FILES)
+ get_filename_component(protocol_name "${protocol_file}" NAME_WLE)
+
+ set(waylandscanner_header_output "${target_binary_dir}/wayland-${protocol_name}-client-protocol.h")
+ set(waylandscanner_code_output "${target_binary_dir}/wayland-${protocol_name}-protocol.c")
+ # TODO: Maybe add "client" prefix or suffix to these in Qt6?
+ set(qtwaylandscanner_header_output "${target_binary_dir}/qwayland-${protocol_name}.h")
+ set(qtwaylandscanner_code_output "${target_binary_dir}/qwayland-${protocol_name}.cpp")
+
+ if (NOT arg_NO_INCLUDE_CORE_ONLY)
+ set(waylandscanner_extra_args "--include-core-only")
+ endif()
+
+
+ if (arg_PRIVATE_CODE)
+ set(wayland_scanner_code_option "private-code")
+ else()
+ set(wayland_scanner_code_option "public-code")
+ endif()
+
+ add_custom_command(
+ OUTPUT "${waylandscanner_header_output}"
+ #TODO: Maybe put the files in ${CMAKE_CURRENT_BINARY_DIR/wayland_generated instead?
+ COMMAND Wayland::Scanner ${waylandscanner_extra_args} client-header < "${protocol_file}" > "${waylandscanner_header_output}"
+ DEPENDS ${protocol_file} Wayland::Scanner
+ )
+
+ add_custom_command(
+ OUTPUT "${waylandscanner_code_output}"
+ COMMAND Wayland::Scanner ${waylandscanner_extra_args} ${wayland_scanner_code_option} < "${protocol_file}" > "${waylandscanner_code_output}"
+ DEPENDS ${protocol_file} Wayland::Scanner
+ )
+
+ set(wayland_include_dir "")
+ if(arg___QT_INTERNAL_WAYLAND_INCLUDE_DIR)
+ set(wayland_include_dir "${arg___QT_INTERNAL_WAYLAND_INCLUDE_DIR}")
+ else()
+ get_target_property(qt_module ${target} _qt_module_interface_name)
+ get_target_property(is_for_module "${target}" _qt_module_has_headers)
+ if (qt_module)
+ set(wayland_include_dir "Qt${qt_module}/private")
+ elseif (is_for_module)
+ set(wayland_include_dir "QtWaylandClient/private")
+ endif()
+ endif()
+
+ add_custom_command(
+ OUTPUT "${qtwaylandscanner_header_output}"
+ COMMAND Qt6::qtwaylandscanner client-header
+ "${protocol_file}"
+ --build-macro=${build_macro}
+ --header-path="${wayland_include_dir}"
+ > "${qtwaylandscanner_header_output}"
+ DEPENDS ${protocol_file} Qt6::qtwaylandscanner
+ )
+
+ set(qtwaylandscanner_code_include "")
+ if (is_for_module)
+ set(qtwaylandscanner_code_include "<QtWaylandClient/private/wayland-wayland-client-protocol.h>")
+ endif()
+
+ add_custom_command(
+ OUTPUT "${qtwaylandscanner_code_output}"
+ COMMAND Qt6::qtwaylandscanner client-code
+ "${protocol_file}"
+ --build-macro=${build_macro}
+ --header-path='${wayland_include_dir}'
+ --add-include='${qtwaylandscanner_code_include}'
+ > "${qtwaylandscanner_code_output}"
+ DEPENDS ${protocol_file} Qt6::qtwaylandscanner
+ )
+
+ set(sources "${waylandscanner_header_output}"
+ "${waylandscanner_code_output}"
+ "${qtwaylandscanner_header_output}"
+ "${qtwaylandscanner_code_output}")
+
+ target_sources(${target} PRIVATE ${sources})
+
+ set_source_files_properties(${sources} PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
+ endforeach()
+ target_include_directories(${target} PRIVATE ${target_binary_dir})
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_generate_wayland_protocol_client_sources)
+ qt6_generate_wayland_protocol_client_sources(${ARGV})
+ endfunction()
+endif()
diff --git a/src/client/client.pro b/src/client/client.pro
deleted file mode 100644
index 458e49360..000000000
--- a/src/client/client.pro
+++ /dev/null
@@ -1,154 +0,0 @@
-TARGET = QtWaylandClient
-MODULE = waylandclient
-
-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
-
-# Prevent gold linker from crashing.
-# This started happening when QtPlatformSupport was modularized.
-use_gold_linker: CONFIG += no_linker_version_script
-
-CONFIG -= precompile_header
-CONFIG += link_pkgconfig wayland-scanner
-
-qtConfig(xkbcommon) {
- QT_FOR_PRIVATE += xkbcommon_support-private
-}
-
-qtHaveModule(linuxaccessibility_support_private): \
- QT_PRIVATE += linuxaccessibility_support_private
-
-QMAKE_USE += wayland-client
-
-INCLUDEPATH += $$PWD/../shared
-
-WAYLANDCLIENTSOURCES += \
- ../extensions/surface-extension.xml \
- ../extensions/touch-extension.xml \
- ../extensions/qt-key-unstable-v1.xml \
- ../extensions/qt-windowmanager.xml \
- ../3rdparty/protocol/wp-primary-selection-unstable-v1.xml \
- ../3rdparty/protocol/text-input-unstable-v2.xml \
- ../3rdparty/protocol/xdg-output-unstable-v1.xml \
- ../3rdparty/protocol/wayland.xml
-
-SOURCES += qwaylandintegration.cpp \
- qwaylandnativeinterface.cpp \
- qwaylandshmbackingstore.cpp \
- qwaylandinputdevice.cpp \
- qwaylanddisplay.cpp \
- qwaylandwindow.cpp \
- qwaylandscreen.cpp \
- qwaylandshmwindow.cpp \
- qwaylandshellsurface.cpp \
- qwaylandextendedsurface.cpp \
- qwaylandsubsurface.cpp \
- qwaylandsurface.cpp \
- qwaylandtouch.cpp \
- qwaylandqtkey.cpp \
- ../shared/qwaylandmimehelper.cpp \
- ../shared/qwaylandinputmethodeventbuilder.cpp \
- qwaylandabstractdecoration.cpp \
- qwaylanddecorationfactory.cpp \
- qwaylanddecorationplugin.cpp \
- qwaylandwindowmanagerintegration.cpp \
- qwaylandinputcontext.cpp \
- qwaylandshm.cpp \
- qwaylandbuffer.cpp \
-
-HEADERS += qwaylandintegration_p.h \
- qwaylandnativeinterface_p.h \
- qwaylanddisplay_p.h \
- qwaylandwindow_p.h \
- qwaylandscreen_p.h \
- qwaylandshmbackingstore_p.h \
- qwaylandinputdevice_p.h \
- qwaylandbuffer_p.h \
- qwaylandshmwindow_p.h \
- qwaylandshellsurface_p.h \
- qwaylandextendedsurface_p.h \
- qwaylandsubsurface_p.h \
- qwaylandsurface_p.h \
- qwaylandtouch_p.h \
- qwaylandqtkey_p.h \
- qwaylandabstractdecoration_p.h \
- qwaylanddecorationfactory_p.h \
- qwaylanddecorationplugin_p.h \
- qwaylandwindowmanagerintegration_p.h \
- qwaylandinputcontext_p.h \
- qwaylandshm_p.h \
- qtwaylandclientglobal.h \
- qtwaylandclientglobal_p.h \
- ../shared/qwaylandinputmethodeventbuilder_p.h \
- ../shared/qwaylandmimehelper_p.h \
- ../shared/qwaylandsharedmemoryformathelper_p.h \
-
-qtConfig(clipboard) {
- HEADERS += qwaylandclipboard_p.h
- SOURCES += qwaylandclipboard.cpp
-}
-
-include(hardwareintegration/hardwareintegration.pri)
-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
-
- HEADERS += \
- qwaylandcursor_p.h
- SOURCES += \
- qwaylandcursor.cpp
-}
-
-qtConfig(wayland-datadevice) {
- HEADERS += \
- qwaylanddatadevice_p.h \
- qwaylanddatadevicemanager_p.h \
- qwaylanddataoffer_p.h \
- qwaylanddatasource_p.h
- SOURCES += \
- qwaylanddatadevice.cpp \
- qwaylanddatadevicemanager.cpp \
- qwaylanddataoffer.cpp \
- qwaylanddatasource.cpp
-}
-
-qtConfig(wayland-client-primary-selection) {
- HEADERS += qwaylandprimaryselectionv1_p.h
- SOURCES += qwaylandprimaryselectionv1.cpp
-}
-
-qtConfig(draganddrop) {
- HEADERS += \
- qwaylanddnd_p.h
- SOURCES += \
- qwaylanddnd.cpp
-}
-
-CONFIG += generated_privates
-MODULE_PLUGIN_TYPES = \
- wayland-graphics-integration-client \
- wayland-inputdevice-integration \
- wayland-decoration-client \
- wayland-shell-integration
-load(qt_module)
diff --git a/src/client/configure.cmake b/src/client/configure.cmake
new file mode 100644
index 000000000..5ed7995ef
--- /dev/null
+++ b/src/client/configure.cmake
@@ -0,0 +1,56 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#### Inputs
+
+
+
+#### Libraries
+
+
+# Even if libdrm is already found by qtbase we still need to list it as dependency for some of our
+# plugins
+if(TARGET Libdrm::Libdrm)
+ qt_internal_disable_find_package_global_promotion(Libdrm::Libdrm)
+endif()
+qt_find_package(Libdrm PROVIDED_TARGETS Libdrm::Libdrm MODULE_NAME gui QMAKE_LIB drm MARK_OPTIONAL)
+
+#### Tests
+
+
+#### Features
+
+qt_feature("wayland-client-primary-selection" PRIVATE
+ LABEL "primary-selection clipboard"
+ CONDITION QT_FEATURE_clipboard
+)
+qt_feature("wayland-client-fullscreen-shell-v1" PRIVATE
+ LABEL "fullscreen-shell-v1"
+ CONDITION QT_FEATURE_wayland_client
+)
+qt_feature("wayland-client-ivi-shell" PRIVATE
+ LABEL "ivi-shell"
+ CONDITION QT_FEATURE_wayland_client
+)
+qt_feature("wayland-client-wl-shell" PRIVATE
+ LABEL "wl-shell (deprecated)"
+ CONDITION QT_FEATURE_wayland_client
+)
+qt_feature("wayland-client-xdg-shell" PRIVATE
+ LABEL "xdg-shell"
+ CONDITION QT_FEATURE_wayland_client
+)
+qt_feature("wayland-client-qt-shell" PRIVATE
+ LABEL "qt-shell"
+ CONDITION QT_FEATURE_wayland_client
+)
+qt_feature("egl-extension-platform-wayland" PRIVATE
+ LABEL "EGL wayland platform extension"
+ CONDITION QT_FEATURE_wayland_client AND QT_FEATURE_opengl AND QT_FEATURE_egl AND TEST_egl_1_5_wayland
+)
+qt_configure_add_summary_section(NAME "Qt Wayland Client Shell Integrations")
+qt_configure_add_summary_entry(ARGS "wayland-client-xdg-shell")
+qt_configure_add_summary_entry(ARGS "wayland-client-ivi-shell")
+qt_configure_add_summary_entry(ARGS "wayland-client-wl-shell")
+qt_configure_add_summary_entry(ARGS "wayland-client-qt-shell")
+qt_configure_end_summary_section() # end of "Qt Wayland Client Shell Integrations" section
diff --git a/src/client/configure.json b/src/client/configure.json
deleted file mode 100644
index f49beaf70..000000000
--- a/src/client/configure.json
+++ /dev/null
@@ -1,300 +0,0 @@
-{
- "module": "waylandclient",
- "condition": "module.gui",
- "depends": [
- "gui-private"
- ],
- "testDir": "../../config.tests",
-
- "libraries": {
- "wayland-client": {
- "label": "Wayland client library",
- "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"
- ]
- },
- "wayland-cursor": {
- "label": "Wayland cursor library",
- "headers": "wayland-cursor.h",
- "test": {
- "main": "struct wl_cursor_image *image = 0;"
- },
- "use": "wayland-client",
- "sources": [
- { "type": "pkgConfig", "args": "wayland-cursor" },
- "-lwayland-cursor"
- ]
- },
- "wayland-egl": {
- "label": "Wayland EGL library",
- "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",
- "-lEGL"
- ]
- },
- "xcomposite": {
- "label": "XComposite",
- "headers": "X11/extensions/Xcomposite.h",
- "test": {
- "main": "XCompositeRedirectWindow((Display *)0,(Window) 0, CompositeRedirectManual);"
-
- },
- "sources": [
- { "type": "pkgConfig", "args": "xcomposite" },
- "-lxcomposite"
- ]
- },
- "glx": {
- "label": "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"
- ]
- }
- },
-
- "tests": {
- "wayland-scanner": {
- "label": "wayland-scanner",
- "type": "compile",
- "test": "wayland_scanner",
- "use": "wayland-client"
- },
- "drm-egl-server": {
- "label": "DRM EGL Server",
- "type": "compile",
- "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": {
- "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": {
- "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"
- },
- "vulkan-server-buffer": {
- "label": "Vulkan Buffer Sharing",
- "type": "compile",
- "test": {
- "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;"
- ]
- }
- }
- },
-
- "features": {
- "wayland-client": {
- "label": "Qt Wayland Client",
- "condition": "!config.win32 && libs.wayland-client && libs.wayland-cursor && tests.wayland-scanner",
- "output": [ "privateFeature" ]
- },
- "wayland-datadevice": {
- "condition": "features.draganddrop || features.clipboard",
- "output": [ "privateFeature" ]
- },
- "wayland-client-primary-selection": {
- "label": "primary-selection clipboard",
- "condition": "features.clipboard",
- "output": [ "privateFeature" ]
- },
- "wayland-client-fullscreen-shell-v1": {
- "label": "fullscreen-shell-v1",
- "condition": "features.wayland-client",
- "output": [ "privateFeature" ]
- },
- "wayland-client-ivi-shell": {
- "label": "ivi-shell",
- "condition": "features.wayland-client",
- "output": [ "privateFeature" ]
- },
- "wayland-client-wl-shell": {
- "label": "wl-shell (deprecated)",
- "condition": "features.wayland-client",
- "output": [ "privateFeature" ]
- },
- "wayland-client-xdg-shell": {
- "label": "xdg-shell",
- "condition": "features.wayland-client",
- "output": [ "privateFeature" ]
- },
- "wayland-client-xdg-shell-v5": {
- "label": "xdg-shell unstable v5 (deprecated)",
- "condition": "features.wayland-client",
- "output": [ "privateFeature" ]
- },
- "wayland-client-xdg-shell-v6": {
- "label": "xdg-shell unstable v6",
- "condition": "features.wayland-client",
- "output": [ "privateFeature" ]
- },
- "wayland-egl": {
- "label": "EGL",
- "condition": "features.wayland-client && features.opengl && features.egl && libs.wayland-egl",
- "output": [ "privateFeature" ]
- },
- "wayland-brcm": {
- "label": "Raspberry Pi",
- "condition": "features.wayland-client && features.eglfs_brcm",
- "output": [ "privateFeature" ]
- },
- "xcomposite-egl": {
- "label": "XComposite EGL",
- "condition": "features.wayland-client && features.opengl && features.egl && features.xlib && libs.xcomposite && features.egl_x11",
- "output": [ "privateFeature" ]
- },
- "xcomposite-glx": {
- "label": "XComposite GLX",
- "condition": "features.wayland-client && features.opengl && !features.opengles2 && features.xlib && libs.xcomposite && libs.glx",
- "output": [ "privateFeature" ]
- },
- "wayland-drm-egl-server-buffer": {
- "label": "DRM EGL",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.drm-egl-server",
- "output": [ "privateFeature" ]
- },
- "wayland-libhybris-egl-server-buffer": {
- "label": "libhybris EGL",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.libhybris-egl-server",
- "output": [ "privateFeature" ]
- },
- "wayland-dmabuf-server-buffer": {
- "label": "Linux dma-buf server buffer integration",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.dmabuf-server-buffer",
- "output": [ "privateFeature" ]
- },
- "wayland-vulkan-server-buffer": {
- "label": "Vulkan-based server buffer integration",
- "condition": "features.wayland-client && features.opengl && features.egl && tests.vulkan-server-buffer",
- "output": [ "privateFeature" ]
- },
- "wayland-shm-emulation-server-buffer": {
- "label": "Shm emulation server buffer integration",
- "condition": "features.wayland-client && features.opengl",
- "output": [ "privateFeature" ]
- }
- },
-
- "report": [
- {
- "type": "note",
- "condition": "!libs.wayland-egl",
- "message": "No wayland-egl support detected. Cross-toolkit compatibility disabled."
- }
- ],
-
- "summary": [
- {
- "section": "Qt Wayland Drivers",
- "condition": "features.wayland-client",
- "entries": [
- "wayland-egl",
- "wayland-brcm",
- "xcomposite-egl",
- "xcomposite-glx",
- "wayland-drm-egl-server-buffer",
- "wayland-libhybris-egl-server-buffer",
- "wayland-dmabuf-server-buffer",
- "wayland-vulkan-server-buffer",
- "wayland-shm-emulation-server-buffer"
- ]
- },
- {
- "section": "Qt Wayland Client Shell Integrations",
- "condition": "features.wayland-client",
- "entries": [
- "wayland-client-xdg-shell",
- "wayland-client-xdg-shell-v5",
- "wayland-client-xdg-shell-v6",
- "wayland-client-ivi-shell",
- "wayland-client-wl-shell"
- ]
- },
- "wayland-client"
- ]
-}
diff --git a/src/client/doc/qtwaylandclient.qdocconf b/src/client/doc/qtwaylandclient.qdocconf
new file mode 100644
index 000000000..20ceaef02
--- /dev/null
+++ b/src/client/doc/qtwaylandclient.qdocconf
@@ -0,0 +1,31 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include($QT_INSTALL_DOCS/config/exampleurl-qtwayland.qdocconf)
+
+project = QtWaylandClient
+description = Qt Wayland Client Reference Documentation
+version = $QT_VERSION
+
+qhp.projects = QtWaylandClient
+
+qhp.QtWaylandClient.file = qtwaylandclient.qhp
+qhp.QtWaylandClient.namespace = org.qt-project.QtWaylandClient.$QT_VERSION_TAG
+qhp.QtWaylandClient.virtualFolder = QtWaylandClient
+qhp.QtWaylandClient.indexTitle = Qt Wayland Client
+qhp.QtWaylandClient.indexRoot =
+
+depends += qtcore \
+ qtqml \
+ qtquick \
+ qtdoc \
+ qtcmake \
+ qtwaylandcompositor
+
+headerdirs += \
+ ../
+sourcedirs += \
+ ../
+
+navigation.landingpage = "Qt Wayland Client"
+
+# Enforce zero documentation warnings
+warninglimit = 0
diff --git a/src/client/doc/src/cmake/qt_generate_wayland_protocol_client_sources.qdoc b/src/client/doc/src/cmake/qt_generate_wayland_protocol_client_sources.qdoc
new file mode 100644
index 000000000..0abd14d4e
--- /dev/null
+++ b/src/client/doc/src/cmake/qt_generate_wayland_protocol_client_sources.qdoc
@@ -0,0 +1,51 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-generate-wayland-protocol-client-sources.html
+\ingroup cmake-commands-qtwaylandclient
+
+\title qt_generate_wayland_protocol_client_sources
+\keyword qt6_generate_wayland_protocol_client_sources
+
+\summary {Generates client-side C++ bindings for a Wayland protocol .XML file}
+
+\cmakecommandsince 6.0
+
+The command is defined in the \c WaylandClient component of the \c Qt6 package, which
+can be loaded like so:
+
+\badcode
+find_package(Qt6 REQUIRED COMPONENTS WaylandClient)
+\endcode
+
+\section1 Synopsis
+
+\badcode
+qt_generate_wayland_protocol_client_sources(target
+ [PUBLIC_CODE | PRIVATE_CODE]
+ FILES file1.xml [file2.xml ...])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_generate_wayland_protocol_client_sources()
+
+\section1 Description
+
+qt_generate_wayland_protocol_client_sources() creates the build steps to run \c{wayland-scanner} and
+\c{qtwaylandscanner} on one or more Wayland protocol files. The tools will in turn generate binding
+code in C and C++ for implementing the protocols, and the resulting files will be built as part
+of the \c target.
+
+The options \c{PUBLIC_CODE} and \c{PRIVATE_CODE} correspond to the \c{public-code} and
+\c{private-code} options of \c{wayland-scanner}. \c{PUBLIC_CODE} will cause the symbols in the
+code that is generated by \c{wayland-scanner} to be exported. For backwards compatibility \c{PUBLIC_CODE} is the
+default but generally \c{PRIVATE_CODE} is strongly recommended.
+
+qt_generate_wayland_protocol_client_sources() will trigger generation of the files needed to
+implement the client side of the protocol. \l{qt_generate_wayland_protocol_server_sources}{qt_generate_wayland_protocol_server_sources()}
+is the equivalent function for the compositor.
+
+See the \l{Custom Shell} or \l{Custom Extension} examples for a demonstration of how to use these
+functions.
+*/
+
diff --git a/src/client/doc/src/qtwaylandclient-overview.qdoc b/src/client/doc/src/qtwaylandclient-overview.qdoc
new file mode 100644
index 000000000..a6f5ce56a
--- /dev/null
+++ b/src/client/doc/src/qtwaylandclient-overview.qdoc
@@ -0,0 +1,36 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page qtwaylandclient-index.html
+ \title Qt Wayland Client
+ \brief Library to enable connecting to a Wayland compositor as a client
+
+ The Qt Wayland Client library provides the necessary functions for an application to act
+ as a \l {https://wayland.freedesktop.org/}{Wayland} client and connect to a Wayland compositor.
+ For most use cases, the library is used automatically through the Wayland QPA plugin, and there is
+ no need for the application itself to use any functions from the library.
+
+ However, when paired with \l{Qt Wayland Compositor}, the cmake function
+ \l{qt_generate_wayland_protocol_client_sources}{qt_generate_wayland_protocol_client_sources()}
+ can be used to create custom protocol extensions.
+
+ \section1 Licenses and Attributions
+
+ Qt Wayland Compositor and the Qt Wayland integration plugin
+ are available under commercial licenses from \l{The Qt Company}.
+
+ In addition, Qt Wayland Compositor is available under the
+ \l{GNU General Public License, version 3}, while
+ the Qt Wayland integration plugin is available under the
+ \l{GNU Lesser General Public License, version 3} or the
+ \l{GNU General Public License, version 2}.
+
+ See \l{Qt Licensing} for further details.
+
+ Qt Wayland Compositor and the Qt Wayland integration plugin
+ use protocol definitions under following permissive licenses:
+
+ \generatelist{groupsbymodule attributions-qtwaylandcompositor}
+
+*/
diff --git a/src/client/global/qwaylandclientextension.cpp b/src/client/global/qwaylandclientextension.cpp
index 125b1e19d..b2783088b 100644
--- a/src/client/global/qwaylandclientextension.cpp
+++ b/src/client/global/qwaylandclientextension.cpp
@@ -1,80 +1,61 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Erik Larsson.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Erik Larsson.
+// Copyright (C) 2021 David Redondo <qt@david-redondo.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandclientextension.h"
#include "qwaylandclientextension_p.h"
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QtWaylandClient/private/qwaylandintegration_p.h>
-#include <QtGui/QGuiApplication>
-#include <QtGui/qpa/qplatformnativeinterface.h>
-#include <QtGui/private/qguiapplication_p.h>
-#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
+using RegistryGlobal = QtWaylandClient::QWaylandDisplay::RegistryGlobal;
+
QWaylandClientExtensionPrivate::QWaylandClientExtensionPrivate()
{
// Keep the possibility to use a custom waylandIntegration as a plugin,
// but also add the possibility to run it as a QML component.
- waylandIntegration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ waylandIntegration = QtWaylandClient::QWaylandIntegration::instance();
if (!waylandIntegration)
waylandIntegration = new QtWaylandClient::QWaylandIntegration();
+}
- if (!waylandIntegration->nativeInterface()->nativeResourceForIntegration("wl_display"))
- qWarning() << "This application requires a Wayland platform plugin";
+void QWaylandClientExtensionPrivate::globalAdded(const RegistryGlobal &global)
+{
+ Q_Q(QWaylandClientExtension);
+ if (!active && global.interface == QLatin1String(q->extensionInterface()->name)) {
+ q->bind(global.registry, global.id, global.version);
+ active = true;
+ emit q->activeChanged();
+ }
}
-void QWaylandClientExtensionPrivate::handleRegistryGlobal(void *data, ::wl_registry *registry, uint32_t id,
- const QString &interface, uint32_t version)
+void QWaylandClientExtensionPrivate::globalRemoved(const RegistryGlobal &global)
{
- QWaylandClientExtension *extension = static_cast<QWaylandClientExtension *>(data);
- if (interface == QLatin1String(extension->extensionInterface()->name) && !extension->d_func()->active) {
- extension->bind(registry, id, version);
- extension->d_func()->active = true;
- emit extension->activeChanged();
+ Q_Q(QWaylandClientExtension);
+ if (active && global.interface == QLatin1String(q->extensionInterface()->name)) {
+ active = false;
+ emit q->activeChanged();
}
}
-void QWaylandClientExtension::addRegistryListener()
+void QWaylandClientExtension::initialize()
{
Q_D(QWaylandClientExtension);
- d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
+ if (d->active) {
+ return;
+ }
+ const QtWaylandClient::QWaylandDisplay *display = d->waylandIntegration->display();
+ const auto globals = display->globals();
+ auto global =
+ std::find_if(globals.cbegin(), globals.cend(), [this](const RegistryGlobal &global) {
+ return global.interface == QLatin1String(extensionInterface()->name);
+ });
+ if (global != globals.cend()) {
+ bind(global->registry, global->id, global->version);
+ d->active = true;
+ emit activeChanged();
+ }
}
QWaylandClientExtension::QWaylandClientExtension(const int ver)
@@ -82,10 +63,17 @@ QWaylandClientExtension::QWaylandClientExtension(const int ver)
{
Q_D(QWaylandClientExtension);
d->version = ver;
+ auto display = d->waylandIntegration->display();
+ QObjectPrivate::connect(display, &QtWaylandClient::QWaylandDisplay::globalAdded, d,
+ &QWaylandClientExtensionPrivate::globalAdded);
+ QObjectPrivate::connect(display, &QtWaylandClient::QWaylandDisplay::globalRemoved, d,
+ &QWaylandClientExtensionPrivate::globalRemoved);
+ // This function uses virtual functions and we don't want it to be called from the constructor.
+ QMetaObject::invokeMethod(this, "initialize", Qt::QueuedConnection);
+}
- // The registry listener uses virtual functions and we don't want it to be called from
- // the constructor.
- QMetaObject::invokeMethod(this, "addRegistryListener", Qt::QueuedConnection);
+QWaylandClientExtension::~QWaylandClientExtension()
+{
}
QtWaylandClient::QWaylandIntegration *QWaylandClientExtension::integration() const
@@ -116,3 +104,5 @@ bool QWaylandClientExtension::isActive() const
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandclientextension.cpp"
diff --git a/src/client/global/qwaylandclientextension.h b/src/client/global/qwaylandclientextension.h
index 98272e571..c57549c34 100644
--- a/src/client/global/qwaylandclientextension.h
+++ b/src/client/global/qwaylandclientextension.h
@@ -1,46 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Erik Larsson.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Erik Larsson.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTEXTENSION_H
#define QWAYLANDCLIENTEXTENSION_H
-#include <QObject>
+#include <QtCore/QObject>
#include <QtWaylandClient/qtwaylandclientglobal.h>
struct wl_interface;
@@ -55,7 +19,7 @@ class QWaylandIntegration;
class QWaylandClientExtensionPrivate;
class QWaylandClientExtensionTemplatePrivate;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtension : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientExtension : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QWaylandClientExtension)
@@ -63,6 +27,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtension : public QObject
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
public:
QWaylandClientExtension(const int version);
+ ~QWaylandClientExtension();
QtWaylandClient::QWaylandIntegration *integration() const;
int version() const;
@@ -76,18 +41,35 @@ Q_SIGNALS:
void versionChanged();
void activeChanged();
-private Q_SLOTS:
- void addRegistryListener();
+protected Q_SLOTS:
+ void initialize();
};
-template <typename T>
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplate : public QWaylandClientExtension
+
+template<typename T, auto destruct = nullptr>
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientExtensionTemplate : public QWaylandClientExtension
{
Q_DECLARE_PRIVATE(QWaylandClientExtensionTemplate)
+
public:
- QWaylandClientExtensionTemplate(const int ver) :
- QWaylandClientExtension(ver)
+ QWaylandClientExtensionTemplate(const int ver) : QWaylandClientExtension(ver)
{
+ if constexpr (destruct != nullptr) {
+ connect(this, &QWaylandClientExtensionTemplate::activeChanged, this, [this] {
+ if (!isActive()) {
+ std::invoke(destruct, static_cast<T *>(this));
+ }
+ });
+ }
+ }
+
+ ~QWaylandClientExtensionTemplate()
+ {
+ if constexpr (destruct != nullptr) {
+ if (isActive()) {
+ std::invoke(destruct, static_cast<T *>(this));
+ }
+ }
}
const struct wl_interface *extensionInterface() const override
diff --git a/src/client/global/qwaylandclientextension_p.h b/src/client/global/qwaylandclientextension_p.h
index 69cc46a0a..b3ef87a5d 100644
--- a/src/client/global/qwaylandclientextension_p.h
+++ b/src/client/global/qwaylandclientextension_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Erik Larsson.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Erik Larsson.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTEXTENSION_P_H
#define QWAYLANDCLIENTEXTENSION_P_H
@@ -53,24 +17,26 @@
#include <QtCore/private/qobject_p.h>
#include <QtWaylandClient/QWaylandClientExtension>
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QtWaylandClient/private/qwaylandintegration_p.h>
QT_BEGIN_NAMESPACE
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionPrivate : public QObjectPrivate
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientExtensionPrivate : public QObjectPrivate
{
- Q_DECLARE_PUBLIC(QWaylandClientExtension)
public:
+ Q_DECLARE_PUBLIC(QWaylandClientExtension)
QWaylandClientExtensionPrivate();
- static void handleRegistryGlobal(void *data, ::wl_registry *registry, uint32_t id,
- const QString &interface, uint32_t version);
+
+ void globalAdded(const QtWaylandClient::QWaylandDisplay::RegistryGlobal &global);
+ void globalRemoved(const QtWaylandClient::QWaylandDisplay::RegistryGlobal &global);
QtWaylandClient::QWaylandIntegration *waylandIntegration = nullptr;
int version = -1;
bool active = false;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
{
public:
QWaylandClientExtensionTemplatePrivate()
diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegration.cpp b/src/client/hardwareintegration/qwaylandclientbufferintegration.cpp
index 61a2c1cdb..b521521b8 100644
--- a/src/client/hardwareintegration/qwaylandclientbufferintegration.cpp
+++ b/src/client/hardwareintegration/qwaylandclientbufferintegration.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandclientbufferintegration_p.h"
diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h b/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h
index 7776c6158..e8b78c52b 100644
--- a/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h
+++ b/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTBUFFERINTEGRATION_H
#define QWAYLANDCLIENTBUFFERINTEGRATION_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +29,7 @@ namespace QtWaylandClient {
class QWaylandWindow;
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientBufferIntegration
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientBufferIntegration
{
public:
QWaylandClientBufferIntegration();
diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory.cpp b/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory.cpp
index 02bed461a..65c7a450d 100644
--- a/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory.cpp
+++ b/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandclientbufferintegrationfactory_p.h"
#include "qwaylandclientbufferintegrationplugin_p.h"
@@ -48,49 +12,17 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qwcbifLoader,
(QWaylandClientBufferIntegrationFactoryInterface_iid, QLatin1String("/wayland-graphics-integration-client"), Qt::CaseInsensitive))
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QWaylandClientBufferIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
-QStringList QWaylandClientBufferIntegrationFactory::keys(const QString &pluginPath)
+QStringList QWaylandClientBufferIntegrationFactory::keys()
{
-#if QT_CONFIG(library)
- QStringList list;
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- list = directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QStringLiteral(" (from ")
- + QDir::toNativeSeparators(pluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
- list.append(loader()->keyMap().values());
- return list;
-#else
- return QStringList();
-#endif
+ return qwcbifLoader->keyMap().values();
}
-QWaylandClientBufferIntegration *QWaylandClientBufferIntegrationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath)
+QWaylandClientBufferIntegration *QWaylandClientBufferIntegrationFactory::create(const QString &name, const QStringList &args)
{
-#if QT_CONFIG(library)
- // Try loading the plugin from platformPluginPath first:
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- if (QWaylandClientBufferIntegration *ret = qLoadPlugin<QWaylandClientBufferIntegration, QWaylandClientBufferIntegrationPlugin>(directLoader(), name, args))
- return ret;
- }
- if (QWaylandClientBufferIntegration *ret = qLoadPlugin<QWaylandClientBufferIntegration, QWaylandClientBufferIntegrationPlugin>(loader(), name, args))
- return ret;
-#endif
- return nullptr;
+ return qLoadPlugin<QWaylandClientBufferIntegration, QWaylandClientBufferIntegrationPlugin>(qwcbifLoader(), name, args);
}
}
diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory_p.h b/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory_p.h
index 7eaeed16c..2344df59c 100644
--- a/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory_p.h
+++ b/src/client/hardwareintegration/qwaylandclientbufferintegrationfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTBUFFERINTEGRATIONFACTORY_H
#define QWAYLANDCLIENTBUFFERINTEGRATIONFACTORY_H
@@ -53,6 +17,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtCore/QStringList>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -60,11 +25,11 @@ namespace QtWaylandClient {
class QWaylandClientBufferIntegration;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientBufferIntegrationFactory
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientBufferIntegrationFactory
{
public:
- static QStringList keys(const QString &pluginPath = QString());
- static QWaylandClientBufferIntegration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString());
+ static QStringList keys();
+ static QWaylandClientBufferIntegration *create(const QString &name, const QStringList &args);
};
}
diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin.cpp b/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin.cpp
index 7aae1d0c4..0335a9219 100644
--- a/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin.cpp
+++ b/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandclientbufferintegrationplugin_p.h"
@@ -55,3 +19,5 @@ QWaylandClientBufferIntegrationPlugin::~QWaylandClientBufferIntegrationPlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandclientbufferintegrationplugin_p.cpp"
diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin_p.h b/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin_p.h
index e66021916..0cedabff3 100644
--- a/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin_p.h
+++ b/src/client/hardwareintegration/qwaylandclientbufferintegrationplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTBUFFERINTEGRATIONPLUGIN_H
#define QWAYLANDCLIENTBUFFERINTEGRATIONPLUGIN_H
@@ -56,6 +20,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/QObject>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,7 @@ class QWaylandClientBufferIntegration;
#define QWaylandClientBufferIntegrationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandClientBufferIntegrationFactoryInterface.5.3"
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClientBufferIntegrationPlugin : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandClientBufferIntegrationPlugin : public QObject
{
Q_OBJECT
public:
diff --git a/src/client/hardwareintegration/qwaylandhardwareintegration.cpp b/src/client/hardwareintegration/qwaylandhardwareintegration.cpp
index 04340da14..a8f59a7a5 100644
--- a/src/client/hardwareintegration/qwaylandhardwareintegration.cpp
+++ b/src/client/hardwareintegration/qwaylandhardwareintegration.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandhardwareintegration_p.h"
diff --git a/src/client/hardwareintegration/qwaylandhardwareintegration_p.h b/src/client/hardwareintegration/qwaylandhardwareintegration_p.h
index 31b4209dc..d82253f92 100644
--- a/src/client/hardwareintegration/qwaylandhardwareintegration_p.h
+++ b/src/client/hardwareintegration/qwaylandhardwareintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDHARDWAREINTEGRATION_H
#define QWAYLANDHARDWAREINTEGRATION_H
@@ -53,6 +17,7 @@
#include <QtWaylandClient/private/qwayland-hardware-integration.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +25,7 @@ namespace QtWaylandClient {
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandHardwareIntegration : public QtWayland::qt_hardware_integration
+class Q_WAYLANDCLIENT_EXPORT QWaylandHardwareIntegration : public QtWayland::qt_hardware_integration
{
public:
QWaylandHardwareIntegration(struct ::wl_registry *registry, int id);
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegration.cpp b/src/client/hardwareintegration/qwaylandserverbufferintegration.cpp
index d966a1919..64fd7686b 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegration.cpp
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegration.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandserverbufferintegration_p.h"
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h b/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h
index 6833efd0c..92236a7ff 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSERVERBUFFERINTEGRATION_H
#define QWAYLANDSERVERBUFFERINTEGRATION_H
@@ -56,6 +20,7 @@
#include <QtWaylandClient/private/qwayland-server-buffer-extension.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,7 @@ namespace QtWaylandClient {
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandServerBuffer
+class Q_WAYLANDCLIENT_EXPORT QWaylandServerBuffer
{
public:
enum Format {
@@ -93,7 +58,7 @@ private:
void *m_user_data = nullptr;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandServerBufferIntegration
+class Q_WAYLANDCLIENT_EXPORT QWaylandServerBufferIntegration
{
public:
QWaylandServerBufferIntegration();
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory.cpp b/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory.cpp
index 39d65f88d..e30bb4dc0 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory.cpp
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandserverbufferintegrationfactory_p.h"
#include "qwaylandserverbufferintegrationplugin_p.h"
@@ -48,49 +12,17 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qwsbifLoader,
(QWaylandServerBufferIntegrationFactoryInterface_iid, QLatin1String("/wayland-graphics-integration-client"), Qt::CaseInsensitive))
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QWaylandServerBufferIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
-QStringList QWaylandServerBufferIntegrationFactory::keys(const QString &pluginPath)
+QStringList QWaylandServerBufferIntegrationFactory::keys()
{
-#if QT_CONFIG(library)
- QStringList list;
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- list = directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QStringLiteral(" (from ")
- + QDir::toNativeSeparators(pluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
- list.append(loader()->keyMap().values());
- return list;
-#else
- return QStringList();
-#endif
+ return qwsbifLoader->keyMap().values();
}
-QWaylandServerBufferIntegration *QWaylandServerBufferIntegrationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath)
+QWaylandServerBufferIntegration *QWaylandServerBufferIntegrationFactory::create(const QString &name, const QStringList &args)
{
-#if QT_CONFIG(library)
- // Try loading the plugin from platformPluginPath first:
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- if (QWaylandServerBufferIntegration *ret = qLoadPlugin<QWaylandServerBufferIntegration, QWaylandServerBufferIntegrationPlugin>(directLoader(), name, args))
- return ret;
- }
- if (QWaylandServerBufferIntegration *ret = qLoadPlugin<QWaylandServerBufferIntegration, QWaylandServerBufferIntegrationPlugin>(loader(), name, args))
- return ret;
-#endif
- return nullptr;
+ return qLoadPlugin<QWaylandServerBufferIntegration, QWaylandServerBufferIntegrationPlugin>(qwsbifLoader(), name, args);
}
}
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory_p.h b/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory_p.h
index 600c24c9b..bce4c45d0 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory_p.h
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegrationfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSERVERBUFFERINTEGRATIONFACTORY_H
#define QWAYLANDSERVERBUFFERINTEGRATIONFACTORY_H
@@ -53,6 +17,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtCore/QStringList>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -60,11 +25,11 @@ namespace QtWaylandClient {
class QWaylandServerBufferIntegration;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandServerBufferIntegrationFactory
+class Q_WAYLANDCLIENT_EXPORT QWaylandServerBufferIntegrationFactory
{
public:
- static QStringList keys(const QString &pluginPath = QString());
- static QWaylandServerBufferIntegration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString());
+ static QStringList keys();
+ static QWaylandServerBufferIntegration *create(const QString &name, const QStringList &args);
};
}
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin.cpp b/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin.cpp
index cff72e7a3..1a01ca04d 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin.cpp
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandserverbufferintegrationplugin_p.h"
@@ -54,3 +18,5 @@ QWaylandServerBufferIntegrationPlugin::~QWaylandServerBufferIntegrationPlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandserverbufferintegrationplugin_p.cpp"
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin_p.h b/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin_p.h
index b5e7ede47..6be8ca8bf 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin_p.h
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegrationplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSERVERBUFFERINTEGRATIONPLUGIN_H
#define QWAYLANDSERVERBUFFERINTEGRATIONPLUGIN_H
@@ -56,6 +20,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/QObject>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,7 @@ class QWaylandServerBufferIntegration;
#define QWaylandServerBufferIntegrationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandServerBufferIntegrationFactoryInterface.5.3"
-class Q_WAYLAND_CLIENT_EXPORT QWaylandServerBufferIntegrationPlugin : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandServerBufferIntegrationPlugin : public QObject
{
Q_OBJECT
public:
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h
index 1fa0fd6de..9a6c8df0b 100644
--- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDINPUTDEVICEINTEGRATION_H
#define QWAYLANDINPUTDEVICEINTEGRATION_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <stdint.h>
@@ -63,7 +27,7 @@ namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandInputDevice;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDeviceIntegration
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDeviceIntegration
{
public:
QWaylandInputDeviceIntegration() {}
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp
index 8f573064e..1c8eb213d 100644
--- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandinputdeviceintegrationfactory_p.h"
#include "qwaylandinputdeviceintegrationplugin_p.h"
@@ -48,49 +12,17 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qwidfiLoader,
(QWaylandInputDeviceIntegrationFactoryInterface_iid, QLatin1String("/wayland-inputdevice-integration"), Qt::CaseInsensitive))
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QWaylandInputDeviceIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
-QStringList QWaylandInputDeviceIntegrationFactory::keys(const QString &pluginPath)
+QStringList QWaylandInputDeviceIntegrationFactory::keys()
{
-#if QT_CONFIG(library)
- QStringList list;
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- list = directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QStringLiteral(" (from ")
- + QDir::toNativeSeparators(pluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
- list.append(loader()->keyMap().values());
- return list;
-#else
- return QStringList();
-#endif
+ return qwidfiLoader->keyMap().values();
}
-QWaylandInputDeviceIntegration *QWaylandInputDeviceIntegrationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath)
+QWaylandInputDeviceIntegration *QWaylandInputDeviceIntegrationFactory::create(const QString &name, const QStringList &args)
{
-#if QT_CONFIG(library)
- // Try loading the plugin from platformPluginPath first:
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- if (QWaylandInputDeviceIntegration *ret = qLoadPlugin<QWaylandInputDeviceIntegration, QWaylandInputDeviceIntegrationPlugin>(directLoader(), name, args))
- return ret;
- }
- if (QWaylandInputDeviceIntegration *ret = qLoadPlugin<QWaylandInputDeviceIntegration, QWaylandInputDeviceIntegrationPlugin>(loader(), name, args))
- return ret;
-#endif
- return nullptr;
+ return qLoadPlugin<QWaylandInputDeviceIntegration, QWaylandInputDeviceIntegrationPlugin>(qwidfiLoader(), name, args);
}
}
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h
index 80096e790..087c963e1 100644
--- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDINPUTDEVICEINTEGRATIONFACTORY_H
#define QWAYLANDINPUTDEVICEINTEGRATIONFACTORY_H
@@ -53,6 +17,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtCore/QStringList>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -60,11 +25,11 @@ namespace QtWaylandClient {
class QWaylandInputDeviceIntegration;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDeviceIntegrationFactory
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDeviceIntegrationFactory
{
public:
- static QStringList keys(const QString &pluginPath = QString());
- static QWaylandInputDeviceIntegration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString());
+ static QStringList keys();
+ static QWaylandInputDeviceIntegration *create(const QString &name, const QStringList &args);
};
}
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp
index 579095767..424b44d3f 100644
--- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandinputdeviceintegrationplugin_p.h"
@@ -55,3 +19,5 @@ QWaylandInputDeviceIntegrationPlugin::~QWaylandInputDeviceIntegrationPlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandinputdeviceintegrationplugin_p.cpp"
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h
index bae6e2166..e43ce1bd1 100644
--- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDINPUTDEVICEINTEGRATIONPLUGIN_H
#define QWAYLANDINPUTDEVICEINTEGRATIONPLUGIN_H
@@ -56,6 +20,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/QObject>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,7 @@ class QWaylandInputDeviceIntegration;
#define QWaylandInputDeviceIntegrationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandInputDeviceIntegrationFactoryInterface.5.3"
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDeviceIntegrationPlugin : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDeviceIntegrationPlugin : public QObject
{
Q_OBJECT
public:
diff --git a/src/client/qt_cmdline.cmake b/src/client/qt_cmdline.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/client/qt_cmdline.cmake
diff --git a/src/client/qtwaylandclientglobal.h b/src/client/qtwaylandclientglobal.h
index 5f474f378..0e5475294 100644
--- a/src/client/qtwaylandclientglobal.h
+++ b/src/client/qtwaylandclientglobal.h
@@ -1,69 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTGLOBAL_H
#define QWAYLANDCLIENTGLOBAL_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
#include <QtGui/qtguiglobal.h>
#include <QtWaylandClient/qtwaylandclient-config.h>
+#include <QtWaylandClient/qtwaylandclientexports.h>
QT_BEGIN_NAMESPACE
-#if !defined(Q_WAYLAND_CLIENT_EXPORT)
-# if defined(QT_SHARED)
-# define Q_WAYLAND_CLIENT_EXPORT Q_DECL_EXPORT
-# else
-# define Q_WAYLAND_CLIENT_EXPORT
-# endif
-#endif
-
QT_END_NAMESPACE
#endif //QWAYLANDCLIENTGLOBAL_H
diff --git a/src/client/qtwaylandclientglobal_p.h b/src/client/qtwaylandclientglobal_p.h
index f2106d0b8..f98d143d2 100644
--- a/src/client/qtwaylandclientglobal_p.h
+++ b/src/client/qtwaylandclientglobal_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIENTGLOBAL_P_H
#define QWAYLANDCLIENTGLOBAL_P_H
@@ -51,9 +15,9 @@
// We mean it.
//
+#include <QtWaylandGlobal/private/qtwaylandglobal-config_p.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtGui/private/qtguiglobal_p.h>
#include <QtWaylandClient/private/qtwaylandclient-config_p.h>
#endif //QWAYLANDCLIENTGLOBAL_P_H
-
diff --git a/src/client/qwaylandabstractdecoration.cpp b/src/client/qwaylandabstractdecoration.cpp
index 87dd6cea0..699618f68 100644
--- a/src/client/qwaylandabstractdecoration.cpp
+++ b/src/client/qwaylandabstractdecoration.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandabstractdecoration_p.h"
@@ -108,11 +72,11 @@ void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window)
static QRegion marginsRegion(const QSize &size, const QMargins &margins)
{
QRegion r;
- const int widthWithMargins = margins.left() + size.width() + margins.right();
- r += QRect(0, 0, widthWithMargins, margins.top()); // top
- r += QRect(0, size.height()+margins.top(), widthWithMargins, margins.bottom()); //bottom
+
+ r += QRect(0, 0, size.width(), margins.top()); // top
+ r += QRect(0, size.height()-margins.bottom(), size.width(), margins.bottom()); //bottom
r += QRect(0, margins.top(), margins.left(), size.height()); //left
- r += QRect(size.width()+margins.left(), margins.top(), margins.right(), size.height()); // right
+ r += QRect(size.width()-margins.left(), margins.top(), margins.right(), size.height()-margins.top()); // right
return r;
}
@@ -122,7 +86,7 @@ const QImage &QWaylandAbstractDecoration::contentImage()
if (d->m_isDirty) {
// Update the decoration backingstore
- const int bufferScale = waylandWindow()->scale();
+ const qreal bufferScale = waylandWindow()->scale();
const QSize imageSize = waylandWindow()->surfaceSize() * bufferScale;
d->m_decorationContentImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
// Only scale by buffer scale, not QT_SCALE_FACTOR etc.
@@ -216,3 +180,5 @@ QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandabstractdecoration_p.cpp"
diff --git a/src/client/qwaylandabstractdecoration_p.h b/src/client/qwaylandabstractdecoration_p.h
index 81c8e1771..3334e00c1 100644
--- a/src/client/qwaylandabstractdecoration_p.h
+++ b/src/client/qwaylandabstractdecoration_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Robin Burchell <robin.burchell@viroteck.net>
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDABSTRACTDECORATION_H
#define QWAYLANDABSTRACTDECORATION_H
@@ -59,9 +23,11 @@
#include <QtGui/QColor>
#include <QtGui/QStaticText>
#include <QtGui/QImage>
+#include <QtGui/QEventPoint>
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtCore/QDebug>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -77,11 +43,17 @@ class QWaylandWindow;
class QWaylandInputDevice;
class QWaylandAbstractDecorationPrivate;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandAbstractDecoration : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QWaylandAbstractDecoration)
public:
+ enum MarginsType {
+ Full,
+ ShadowsExcluded,
+ ShadowsOnly
+ };
+
QWaylandAbstractDecoration();
~QWaylandAbstractDecoration() override;
@@ -91,12 +63,13 @@ public:
void update();
bool isDirty() const;
- virtual QMargins margins() const = 0;
+ virtual QMargins margins(MarginsType marginsType = Full) const = 0;
+
QWindow *window() const;
const QImage &contentImage();
virtual bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods) = 0;
- virtual bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) = 0;
+ virtual bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods) = 0;
protected:
virtual void paint(QPaintDevice *device) = 0;
diff --git a/src/client/qwaylandbuffer.cpp b/src/client/qwaylandbuffer.cpp
index 12df9cc4f..dd99b702b 100644
--- a/src/client/qwaylandbuffer.cpp
+++ b/src/client/qwaylandbuffer.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2017 Giulio Camuffo.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2017 Giulio Camuffo.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandbuffer_p.h"
@@ -67,6 +31,13 @@ void QWaylandBuffer::release(void *data, wl_buffer *)
QWaylandBuffer *self = static_cast<QWaylandBuffer *>(data);
self->mBusy = false;
self->mCommitted = false;
+ if (self->mDeleteOnRelease)
+ delete self;
+}
+
+void QWaylandBuffer::setDeleteOnRelease(bool deleteOnRelease)
+{
+ mDeleteOnRelease = deleteOnRelease;
}
const wl_buffer_listener QWaylandBuffer::listener = {
diff --git a/src/client/qwaylandbuffer_p.h b/src/client/qwaylandbuffer_p.h
index 945f1279a..c96f213b9 100644
--- a/src/client/qwaylandbuffer_p.h
+++ b/src/client/qwaylandbuffer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDBUFFER_H
#define QWAYLANDBUFFER_H
@@ -57,12 +21,13 @@
#include <QtCore/QRect>
#include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-class Q_WAYLAND_CLIENT_EXPORT QWaylandBuffer {
+class Q_WAYLANDCLIENT_EXPORT QWaylandBuffer {
public:
QWaylandBuffer();
virtual ~QWaylandBuffer();
@@ -72,18 +37,21 @@ public:
virtual QSize size() const = 0;
virtual int scale() const { return 1; }
- void setBusy() { mBusy = true; }
+ void setBusy(bool busy) { mBusy = busy; }
bool busy() const { return mBusy; }
void setCommitted() { mCommitted = true; }
bool committed() const { return mCommitted; }
+ void setDeleteOnRelease(bool deleteOnRelease);
+
protected:
struct wl_buffer *mBuffer = nullptr;
private:
bool mBusy = false;
bool mCommitted = false;
+ bool mDeleteOnRelease = false;
static void release(void *data, wl_buffer *);
static const wl_buffer_listener listener;
diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp
index 81f48e05e..df6cf5d2b 100644
--- a/src/client/qwaylandclipboard.cpp
+++ b/src/client/qwaylandclipboard.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandclipboard_p.h"
#include "qwaylanddisplay_p.h"
@@ -54,10 +18,15 @@ namespace QtWaylandClient {
QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display)
: mDisplay(display)
{
+ m_clientClipboard[QClipboard::Clipboard] = nullptr;
+ m_clientClipboard[QClipboard::Selection] = nullptr;
}
QWaylandClipboard::~QWaylandClipboard()
{
+ if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection])
+ delete m_clientClipboard[QClipboard::Clipboard];
+ delete m_clientClipboard[QClipboard::Selection];
}
QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
@@ -69,8 +38,8 @@ QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
switch (mode) {
case QClipboard::Clipboard:
if (auto *dataDevice = seat->dataDevice()) {
- if (auto *source = dataDevice->selectionSource())
- return source->mimeData();
+ if (dataDevice->selectionSource())
+ return m_clientClipboard[QClipboard::Clipboard];
if (auto *offer = dataDevice->selectionOffer())
return offer->mimeData();
}
@@ -78,8 +47,8 @@ QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
case QClipboard::Selection:
#if QT_CONFIG(wayland_client_primary_selection)
if (auto *selectionDevice = seat->primarySelectionDevice()) {
- if (auto *source = selectionDevice->selectionSource())
- return source->mimeData();
+ if (selectionDevice->selectionSource())
+ return m_clientClipboard[QClipboard::Selection];
if (auto *offer = selectionDevice->selectionOffer())
return offer->mimeData();
}
@@ -104,17 +73,27 @@ void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
if (data && data->hasFormat(plain) && !data->hasFormat(utf8))
data->setData(utf8, data->data(plain));
+ if (m_clientClipboard[mode]) {
+ if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection])
+ delete m_clientClipboard[mode];
+ m_clientClipboard[mode] = nullptr;
+ }
+
+ m_clientClipboard[mode] = data;
+
switch (mode) {
case QClipboard::Clipboard:
if (auto *dataDevice = seat->dataDevice()) {
- dataDevice->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : nullptr);
+ dataDevice->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(),
+ m_clientClipboard[QClipboard::Clipboard]) : nullptr);
emitChanged(mode);
}
break;
case QClipboard::Selection:
#if QT_CONFIG(wayland_client_primary_selection)
if (auto *selectionDevice = seat->primarySelectionDevice()) {
- selectionDevice->setSelectionSource(data ? new QWaylandPrimarySelectionSourceV1(mDisplay->primarySelectionManager(), data) : nullptr);
+ selectionDevice->setSelectionSource(data ? new QWaylandPrimarySelectionSourceV1(mDisplay->primarySelectionManager(),
+ m_clientClipboard[QClipboard::Selection]) : nullptr);
emitChanged(mode);
}
#endif
diff --git a/src/client/qwaylandclipboard_p.h b/src/client/qwaylandclipboard_p.h
index ce14e1240..414e3dc71 100644
--- a/src/client/qwaylandclipboard_p.h
+++ b/src/client/qwaylandclipboard_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCLIPBOARD_H
#define QWAYLANDCLIPBOARD_H
@@ -56,6 +20,7 @@
#include <QtCore/QMimeData>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_REQUIRE_CONFIG(clipboard);
@@ -65,7 +30,7 @@ namespace QtWaylandClient {
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandClipboard : public QPlatformClipboard
+class Q_WAYLANDCLIENT_EXPORT QWaylandClipboard : public QPlatformClipboard
{
public:
QWaylandClipboard(QWaylandDisplay *display);
@@ -80,6 +45,7 @@ public:
private:
QWaylandDisplay *mDisplay = nullptr;
QMimeData m_emptyData;
+ QMimeData *m_clientClipboard[2];
};
}
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
index 4356b23a0..98d51a842 100644
--- a/src/client/qwaylandcursor.cpp
+++ b/src/client/qwaylandcursor.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandcursor_p.h"
@@ -43,6 +8,9 @@
#include "qwaylandinputdevice_p.h"
#include "qwaylandshmbackingstore_p.h"
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
+
#include <QtGui/QImageReader>
#include <QDebug>
@@ -54,7 +22,7 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandCursorTheme *QWaylandCursorTheme::create(QWaylandShm *shm, int size, const QString &themeName)
+std::unique_ptr<QWaylandCursorTheme> QWaylandCursorTheme::create(QWaylandShm *shm, int size, const QString &themeName)
{
QByteArray nameBytes = themeName.toLocal8Bit();
struct ::wl_cursor_theme *theme = wl_cursor_theme_load(nameBytes.constData(), size, shm->object());
@@ -64,7 +32,7 @@ QWaylandCursorTheme *QWaylandCursorTheme::create(QWaylandShm *shm, int size, con
return nullptr;
}
- return new QWaylandCursorTheme(theme);
+ return std::unique_ptr<QWaylandCursorTheme>{new QWaylandCursorTheme(theme)};
}
QWaylandCursorTheme::~QWaylandCursorTheme()
@@ -74,7 +42,7 @@ QWaylandCursorTheme::~QWaylandCursorTheme()
wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
{
- if (struct wl_cursor *cursor = m_cursors.value(shape, nullptr))
+ if (struct wl_cursor *cursor = m_cursors[shape])
return cursor;
static Q_CONSTEXPR struct ShapeAndName {
@@ -120,6 +88,8 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
{SizeAllCursor, "size_all"},
+ {BlankCursor, "blank"},
+
{SplitVCursor, "split_v"},
{SplitVCursor, "row-resize"},
{SplitVCursor, "sb_v_double_arrow"},
@@ -206,7 +176,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
ShapeAndName{shape, ""}, byShape);
for (auto it = p.first; it != p.second; ++it) {
if (wl_cursor *cursor = wl_cursor_theme_get_cursor(m_theme, it->name)) {
- m_cursors.insert(shape, cursor);
+ m_cursors[shape] = cursor;
return cursor;
}
}
@@ -219,7 +189,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
-::wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation)
+::wl_cursor *QWaylandCursorTheme::cursor(Qt::CursorShape shape)
{
struct wl_cursor *waylandCursor = nullptr;
@@ -237,15 +207,78 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
- int frame = wl_cursor_frame(waylandCursor, millisecondsIntoAnimation);
- ::wl_cursor_image *image = waylandCursor->images[frame];
- ::wl_buffer *buffer = wl_cursor_image_get_buffer(image);
- if (!buffer) {
- qCWarning(lcQpaWayland) << "Could not find buffer for cursor";
- return nullptr;
+ return waylandCursor;
+}
+
+QWaylandCursorShape::QWaylandCursorShape(::wp_cursor_shape_device_v1 *object)
+ : QtWayland::wp_cursor_shape_device_v1(object)
+{}
+
+QWaylandCursorShape::~QWaylandCursorShape()
+{
+ destroy();
+}
+
+static QtWayland::wp_cursor_shape_device_v1::shape qtCursorShapeToWaylandShape(Qt::CursorShape cursorShape)
+{
+ using QtWayland::wp_cursor_shape_device_v1;
+
+ switch (cursorShape) {
+ case Qt::BlankCursor:
+ case Qt::CustomCursor:
+ case Qt::BitmapCursor:
+ // these should have been handled separately before using the shape protocol
+ Q_ASSERT(false);
+ break;
+ case Qt::ArrowCursor:
+ return wp_cursor_shape_device_v1::shape_default;
+ case Qt::SizeVerCursor:
+ return wp_cursor_shape_device_v1::shape_ns_resize;
+ case Qt::UpArrowCursor:
+ return wp_cursor_shape_device_v1::shape_n_resize;
+ case Qt::SizeHorCursor:
+ return wp_cursor_shape_device_v1::shape_ew_resize;
+ case Qt::CrossCursor:
+ return wp_cursor_shape_device_v1::shape_crosshair;
+ case Qt::SizeBDiagCursor:
+ return wp_cursor_shape_device_v1::shape_nesw_resize;
+ case Qt::IBeamCursor:
+ return wp_cursor_shape_device_v1::shape_text;
+ case Qt::SizeFDiagCursor:
+ return wp_cursor_shape_device_v1::shape_nwse_resize;
+ case Qt::WaitCursor:
+ return wp_cursor_shape_device_v1::shape_wait;
+ case Qt::SizeAllCursor:
+ return wp_cursor_shape_device_v1::shape_all_scroll;
+ case Qt::BusyCursor:
+ return wp_cursor_shape_device_v1::shape_progress;
+ case Qt::SplitVCursor:
+ return wp_cursor_shape_device_v1::shape_row_resize;
+ case Qt::ForbiddenCursor:
+ return wp_cursor_shape_device_v1::shape_not_allowed;
+ case Qt::SplitHCursor:
+ return wp_cursor_shape_device_v1::shape_col_resize;
+ case Qt::PointingHandCursor:
+ return wp_cursor_shape_device_v1::shape_pointer;
+ case Qt::OpenHandCursor:
+ return wp_cursor_shape_device_v1::shape_grab;
+ case Qt::WhatsThisCursor:
+ return wp_cursor_shape_device_v1::shape_help;
+ case Qt::ClosedHandCursor:
+ return wp_cursor_shape_device_v1::shape_grabbing;
+ case Qt::DragMoveCursor:
+ return wp_cursor_shape_device_v1::shape_move;
+ case Qt::DragCopyCursor:
+ return wp_cursor_shape_device_v1::shape_copy;
+ case Qt::DragLinkCursor:
+ return wp_cursor_shape_device_v1::shape_alias;
}
+ return wp_cursor_shape_device_v1::shape_default;
+}
- return image;
+void QWaylandCursorShape::setShape(uint32_t serial, Qt::CursorShape shape)
+{
+ set_shape(serial, qtCursorShapeToWaylandShape(shape));
}
QWaylandCursor::QWaylandCursor(QWaylandDisplay *display)
@@ -256,10 +289,24 @@ QWaylandCursor::QWaylandCursor(QWaylandDisplay *display)
QSharedPointer<QWaylandBuffer> QWaylandCursor::cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor)
{
Q_ASSERT(cursor->shape() == Qt::BitmapCursor);
- const QImage &img = cursor->pixmap().toImage();
+ QImage img = !cursor->pixmap().isNull() ? cursor->pixmap().toImage() : cursor->bitmap().toImage();
+
+ // convert to supported format if necessary
+ if (!display->shm()->formatSupported(img.format())) {
+ if (cursor->mask().isNull()) {
+ img.convertTo(QImage::Format_RGB32);
+ } else {
+ // preserve mask
+ img.convertTo(QImage::Format_ARGB32);
+ QPixmap pixmap = QPixmap::fromImage(img);
+ pixmap.setMask(cursor->mask());
+ img = pixmap.toImage();
+ }
+ }
+
QSharedPointer<QWaylandShmBuffer> buffer(new QWaylandShmBuffer(display, img.size(), img.format()));
memcpy(buffer->image()->bits(), img.bits(), size_t(img.sizeInBytes()));
- return std::move(buffer);
+ return buffer;
}
void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window)
@@ -278,7 +325,7 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window)
void QWaylandCursor::pointerEvent(const QMouseEvent &event)
{
- mLastPos = event.globalPos();
+ mLastPos = event.globalPosition().toPoint();
}
QPoint QWaylandCursor::pos() const
@@ -292,6 +339,13 @@ void QWaylandCursor::setPos(const QPoint &pos)
qCWarning(lcQpaWayland) << "Setting cursor position is not possible on wayland";
}
+QSize QWaylandCursor::size() const
+{
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ return theme->themeHint(QPlatformTheme::MouseCursorSize).toSize();
+ return QSize(24, 24);
+}
+
} // namespace QtWaylandClient
QT_END_NAMESPACE
diff --git a/src/client/qwaylandcursor_p.h b/src/client/qwaylandcursor_p.h
index a4605f3d2..1f6d5109e 100644
--- a/src/client/qwaylandcursor_p.h
+++ b/src/client/qwaylandcursor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDCURSOR_H
#define QWAYLANDCURSOR_H
@@ -54,9 +18,13 @@
#include <qpa/qplatformcursor.h>
#include <QtCore/QMap>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtWaylandClient/private/qwayland-cursor-shape-v1.h>
+#include <QtCore/private/qglobal_p.h>
#if QT_CONFIG(cursor)
+#include <memory>
+
struct wl_cursor;
struct wl_cursor_image;
struct wl_cursor_theme;
@@ -70,14 +38,14 @@ class QWaylandDisplay;
class QWaylandScreen;
class QWaylandShm;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme
+class Q_WAYLANDCLIENT_EXPORT QWaylandCursorTheme
{
public:
- static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName);
+ static std::unique_ptr<QWaylandCursorTheme> create(QWaylandShm *shm, int size, const QString &themeName);
~QWaylandCursorTheme();
- ::wl_cursor_image *cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation = 0);
+ ::wl_cursor *cursor(Qt::CursorShape shape);
-private:
+protected:
enum WaylandCursor {
ArrowCursor = Qt::ArrowCursor,
UpArrowCursor,
@@ -109,16 +77,26 @@ private:
ResizeNorthWestCursor,
ResizeSouthEastCursor,
ResizeNorthEastCursor,
- ResizeSouthWestCursor
+ ResizeSouthWestCursor,
+
+ NumWaylandCursors
};
explicit QWaylandCursorTheme(struct ::wl_cursor_theme *theme) : m_theme(theme) {}
struct ::wl_cursor *requestCursor(WaylandCursor shape);
struct ::wl_cursor_theme *m_theme = nullptr;
- QMap<WaylandCursor, wl_cursor *> m_cursors;
+ wl_cursor *m_cursors[NumWaylandCursors] = {};
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandCursor : public QPlatformCursor
+class Q_WAYLANDCLIENT_EXPORT QWaylandCursorShape : public QtWayland::wp_cursor_shape_device_v1
+{
+public:
+ QWaylandCursorShape(struct ::wp_cursor_shape_device_v1 *object);
+ ~QWaylandCursorShape();
+ void setShape(uint32_t serial, Qt::CursorShape shape);
+};
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandCursor : public QPlatformCursor
{
public:
explicit QWaylandCursor(QWaylandDisplay *display);
@@ -128,10 +106,11 @@ public:
QPoint pos() const override;
void setPos(const QPoint &pos) override;
+ QSize size() const override;
+
static QSharedPointer<QWaylandBuffer> cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor);
- struct wl_cursor_image *cursorImage(Qt::CursorShape shape);
-private:
+protected:
QWaylandDisplay *mDisplay = nullptr;
QPoint mLastPos;
};
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index f7d135e49..30bfb86c5 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandClient module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddatadevice_p.h"
@@ -49,6 +13,8 @@
#include "qwaylandabstractdecoration_p.h"
#include "qwaylandsurface_p.h"
+#include <QtWaylandClient/private/qwayland-xdg-toplevel-drag-v1.h>
+
#include <QtCore/QMimeData>
#include <QtGui/QGuiApplication>
#include <QtGui/private/qguiapplication_p.h>
@@ -63,8 +29,11 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+using namespace Qt::StringLiterals;
+
QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
- : QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
+ : QObject(inputDevice)
+ , QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
, m_display(manager->display())
, m_inputDevice(inputDevice)
{
@@ -72,6 +41,10 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl
QWaylandDataDevice::~QWaylandDataDevice()
{
+ if (version() >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
+ release();
+ else
+ wl_data_device_destroy(object());
}
QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
@@ -110,7 +83,7 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
return m_dragOffer.data();
}
-bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
+bool QWaylandDataDevice::startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon)
{
auto *seat = m_display->currentInputDevice();
auto *origin = seat->pointerFocus();
@@ -122,8 +95,71 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
return false;
}
+ // dragging data without mimetypes is a legal operation in Qt terms
+ // but Wayland uses a mimetype to determine if a drag is accepted or not
+ // In this rare case, insert a placeholder
+ if (mimeData->formats().isEmpty())
+ mimeData->setData("application/x-qt-avoid-empty-placeholder"_L1, QByteArray("1"));
+
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
+
+ if (version() >= 3)
+ m_dragSource->set_actions(dropActionsToWl(supportedActions));
+
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
+ connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) {
+ auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
+ if (!drag->currentDrag()) {
+ return;
+ }
+ // in old versions drop action is not set, so we guess
+ if (m_dragSource->version() < 3) {
+ drag->setResponse(accepted);
+ } else {
+ QPlatformDropQtResponse response(accepted, action);
+ drag->setResponse(response);
+ }
+ });
+ connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this,
+ [this](bool accepted, Qt::DropAction action) {
+ QPlatformDropQtResponse response(accepted, action);
+ if (m_toplevelDrag) {
+ // If the widget was dropped but the drag not accepted it
+ // should be its own window in the future. To distinguish
+ // from canceling mid-drag the drag is accepted here as the
+ // we know if the widget is over a zone where it can be
+ // incorporated or not
+ response = { accepted, Qt::MoveAction };
+ }
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())
+ ->setDropResponse(response);
+ });
+ connect(m_dragSource.data(), &QWaylandDataSource::finished, this, [this]() {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
+ if (m_toplevelDrag) {
+ m_toplevelDrag->destroy();
+ m_toplevelDrag = nullptr;
+ }
+ });
+
+ if (mimeData->hasFormat("application/x-qt-mainwindowdrag-window"_L1)
+ && m_display->xdgToplevelDragManager()) {
+ qintptr dockWindowPtr;
+ QPoint offset;
+ QDataStream windowStream(mimeData->data("application/x-qt-mainwindowdrag-window"_L1));
+ windowStream >> dockWindowPtr;
+ QWindow *dockWindow = reinterpret_cast<QWindow *>(dockWindowPtr);
+ QDataStream offsetStream(mimeData->data("application/x-qt-mainwindowdrag-position"_L1));
+ offsetStream >> offset;
+ if (auto waylandWindow = static_cast<QWaylandWindow *>(dockWindow->handle())) {
+ if (auto toplevel = waylandWindow->surfaceRole<xdg_toplevel>()) {
+ m_toplevelDrag = new QtWayland::xdg_toplevel_drag_v1(
+ m_display->xdgToplevelDragManager()->get_xdg_toplevel_drag(
+ m_dragSource->object()));
+ m_toplevelDrag->attach(toplevel, offset.x(), offset.y());
+ }
+ }
+ }
start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
return true;
@@ -152,21 +188,26 @@ void QWaylandDataDevice::data_device_drop()
supportedActions = drag->supportedActions();
} else if (m_dragOffer) {
dragData = m_dragOffer->mimeData();
- supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ supportedActions = m_dragOffer->supportedActions();
} else {
return;
}
- QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions);
-
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ m_inputDevice->modifiers());
if (drag) {
- static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
+ auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
+ drag->setDropResponse(response);
+ drag->finishDrag();
+ } else if (m_dragOffer) {
+ m_dragOffer->finish();
}
}
void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, wl_fixed_t x, wl_fixed_t y, wl_data_offer *id)
{
- auto *dragWaylandWindow = QWaylandWindow::fromWlSurface(surface);
+ auto *dragWaylandWindow = surface ? QWaylandWindow::fromWlSurface(surface) : nullptr;
if (!dragWaylandWindow)
return; // Ignore foreign surfaces
@@ -184,26 +225,25 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
supportedActions = drag->supportedActions();
} else if (m_dragOffer) {
dragData = m_dragOffer->mimeData();
- supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ supportedActions = m_dragOffer->supportedActions();
}
- const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
-
+ const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(
+ m_dragWindow, dragData, m_dragPoint, supportedActions, QGuiApplication::mouseButtons(),
+ m_inputDevice->modifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
}
- if (response.isAccepted()) {
- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
- } else {
- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
- }
+ sendResponse(supportedActions, response);
}
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(),
+ m_inputDevice->modifiers());
QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
if (!drag) {
@@ -229,20 +269,18 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
supportedActions = drag->supportedActions();
} else {
dragData = m_dragOffer->mimeData();
- supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ supportedActions = m_dragOffer->supportedActions();
}
- QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+ const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
+ QGuiApplication::mouseButtons(),
+ m_inputDevice->modifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
}
- if (response.isAccepted()) {
- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
- } else {
- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
- }
+ sendResponse(supportedActions, response);
}
#endif // QT_CONFIG(draganddrop)
@@ -269,12 +307,12 @@ void QWaylandDataDevice::selectionSourceCancelled()
#if QT_CONFIG(draganddrop)
void QWaylandDataDevice::dragSourceCancelled()
{
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
m_dragSource.reset();
-}
-
-void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType)
-{
- static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType);
+ if (m_toplevelDrag) {
+ m_toplevelDrag->destroy();
+ m_toplevelDrag = nullptr;
+ }
}
QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const
@@ -289,8 +327,37 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con
}
return pnt;
}
+
+void QWaylandDataDevice::sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response)
+{
+ if (response.isAccepted()) {
+ if (version() >= 3)
+ m_dragOffer->set_actions(dropActionsToWl(supportedActions), dropActionsToWl(response.acceptedAction()));
+
+ m_dragOffer->accept(m_enterSerial, m_dragOffer->firstFormat());
+ } else {
+ m_dragOffer->accept(m_enterSerial, QString());
+ }
+}
+
+int QWaylandDataDevice::dropActionsToWl(Qt::DropActions actions)
+{
+
+ int wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+ if (actions & Qt::CopyAction)
+ wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+ if (actions & (Qt::MoveAction | Qt::TargetMoveAction))
+ wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+
+ // wayland does not support LinkAction at the time of writing
+ return wlActions;
+}
+
+
#endif // QT_CONFIG(draganddrop)
}
QT_END_NAMESPACE
+
+#include "moc_qwaylanddatadevice_p.cpp"
diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h
index 16c3ad28e..3dc4fcaf6 100644
--- a/src/client/qwaylanddatadevice_p.h
+++ b/src/client/qwaylanddatadevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandClient module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDATADEVICE_H
@@ -64,8 +28,13 @@ QT_REQUIRE_CONFIG(wayland_datadevice);
QT_BEGIN_NAMESPACE
class QMimeData;
+class QPlatformDragQtResponse;
class QWindow;
+namespace QtWayland {
+class xdg_toplevel_drag_v1;
+}
+
namespace QtWaylandClient {
class QWaylandDisplay;
@@ -89,7 +58,7 @@ public:
#if QT_CONFIG(draganddrop)
QWaylandDataOffer *dragOffer() const;
- bool startDrag(QMimeData *mimeData, QWaylandWindow *icon);
+ bool startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon);
void cancelDrag();
#endif
@@ -109,13 +78,16 @@ private Q_SLOTS:
#if QT_CONFIG(draganddrop)
void dragSourceCancelled();
- void dragSourceTargetChanged(const QString &mimeType);
#endif
private:
#if QT_CONFIG(draganddrop)
QPoint calculateDragPosition(int x, int y, QWindow *wnd) const;
#endif
+ void sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response);
+
+ static int dropActionsToWl(Qt::DropActions dropActions);
+
QWaylandDisplay *m_display = nullptr;
QWaylandInputDevice *m_inputDevice = nullptr;
@@ -125,8 +97,8 @@ private:
QScopedPointer<QWaylandDataOffer> m_dragOffer;
QScopedPointer<QWaylandDataOffer> m_selectionOffer;
QScopedPointer<QWaylandDataSource> m_selectionSource;
-
QScopedPointer<QWaylandDataSource> m_dragSource;
+ QtWayland::xdg_toplevel_drag_v1 *m_toplevelDrag = nullptr;
};
}
diff --git a/src/client/qwaylanddatadevicemanager.cpp b/src/client/qwaylanddatadevicemanager.cpp
index 35d67307f..961d055ea 100644
--- a/src/client/qwaylanddatadevicemanager.cpp
+++ b/src/client/qwaylanddatadevicemanager.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddatadevicemanager_p.h"
@@ -50,8 +14,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
- : wl_data_device_manager(display->wl_registry(), id, 1)
+QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id)
+ : wl_data_device_manager(display->wl_registry(), id, qMin(version, 3))
, m_display(display)
{
// Create transfer devices for all input devices.
diff --git a/src/client/qwaylanddatadevicemanager_p.h b/src/client/qwaylanddatadevicemanager_p.h
index bd05c0fbb..7e1cb1e45 100644
--- a/src/client/qwaylanddatadevicemanager_p.h
+++ b/src/client/qwaylanddatadevicemanager_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDATADEVICEMANAGER_H
#define QWAYLANDDATADEVICEMANAGER_H
@@ -65,10 +29,10 @@ class QWaylandDataDevice;
class QWaylandDataSource;
class QWaylandInputDevice;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
+class Q_WAYLANDCLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
{
public:
- QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id);
+ QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id);
~QWaylandDataDeviceManager() override;
QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice);
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
index 4c06277fe..8110ce35f 100644
--- a/src/client/qwaylanddataoffer.cpp
+++ b/src/client/qwaylanddataoffer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddataoffer_p.h"
#include "qwaylanddatadevicemanager_p.h"
@@ -47,6 +11,8 @@
#include <QtCore/QDebug>
+using namespace std::chrono;
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -56,6 +22,65 @@ static QString utf8Text()
return QStringLiteral("text/plain;charset=utf-8");
}
+static QString uriList()
+{
+ return QStringLiteral("text/uri-list");
+}
+
+static QString mozUrl()
+{
+ return QStringLiteral("text/x-moz-url");
+}
+
+static QString portalFileTransfer()
+{
+ return QStringLiteral("application/vnd.portal.filetransfer");
+}
+
+static QByteArray convertData(const QString &originalMime, const QString &newMime, const QByteArray &data)
+{
+ if (originalMime == newMime)
+ return data;
+
+ // Convert text/x-moz-url, which is an UTF-16 string of
+ // URL and page title pairs, all separated by line breaks, to text/uri-list.
+ // see also qtbase/src/plugins/platforms/xcb/qxcbmime.cpp
+ if (originalMime == uriList() && newMime == mozUrl()) {
+ if (data.size() > 1) {
+ const quint8 byte0 = data.at(0);
+ const quint8 byte1 = data.at(1);
+
+ if ((byte0 == 0xff && byte1 == 0xfe) || (byte0 == 0xfe && byte1 == 0xff)
+ || (byte0 != 0 && byte1 == 0) || (byte0 == 0 && byte1 != 0)) {
+ QByteArray converted;
+ const QString str = QString::fromUtf16(
+ reinterpret_cast<const char16_t *>(data.constData()), data.size() / 2);
+ if (!str.isNull()) {
+ const auto urls = QStringView{str}.split(u'\n');
+ // Only the URL is interesting, skip the page title.
+ for (int i = 0; i < urls.size(); i += 2) {
+ const QUrl url(urls.at(i).trimmed().toString());
+ if (url.isValid()) {
+ converted += url.toEncoded();
+ converted += "\r\n";
+ }
+ }
+ }
+ return converted;
+ // 8 byte encoding, remove a possible 0 at the end.
+ } else {
+ QByteArray converted = data;
+ if (converted.endsWith('\0'))
+ converted.chop(1);
+ converted += "\r\n";
+ return converted;
+ }
+ }
+ }
+
+ return data;
+}
+
QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
: QtWayland::wl_data_offer(offer)
, m_display(display)
@@ -82,6 +107,15 @@ QMimeData *QWaylandDataOffer::mimeData()
return m_mimeData.data();
}
+Qt::DropActions QWaylandDataOffer::supportedActions() const
+{
+ if (version() < 3) {
+ return Qt::MoveAction | Qt::CopyAction;
+ }
+
+ return m_supportedActions;
+}
+
void QWaylandDataOffer::startReceiving(const QString &mimeType, int fd)
{
receive(mimeType, fd);
@@ -93,6 +127,22 @@ void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
m_mimeData->appendFormat(mime_type);
}
+void QWaylandDataOffer::data_offer_action(uint32_t dnd_action)
+{
+ Q_UNUSED(dnd_action);
+ // This is the compositor telling the drag target what action it should perform
+ // It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action?
+}
+
+void QWaylandDataOffer::data_offer_source_actions(uint32_t source_actions)
+{
+ m_supportedActions = Qt::DropActions();
+ if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+ m_supportedActions |= Qt::MoveAction;
+ if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+ m_supportedActions |= Qt::CopyAction;
+}
+
QWaylandMimeData::QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
: m_dataOffer(dataOffer)
{
@@ -104,8 +154,11 @@ QWaylandMimeData::~QWaylandMimeData()
void QWaylandMimeData::appendFormat(const QString &mimeType)
{
- m_types << mimeType;
- m_data.remove(mimeType); // Clear previous contents
+ // "DELETE" is a potential leftover from XdndActionMode sent by e.g. Firefox, ignore it.
+ if (mimeType != QLatin1String("DELETE")) {
+ m_types << mimeType;
+ m_data.remove(mimeType); // Clear previous contents
+ }
}
bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
@@ -116,6 +169,9 @@ bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
if (mimeType == QStringLiteral("text/plain") && m_types.contains(utf8Text()))
return true;
+ if (mimeType == uriList() && m_types.contains(mozUrl()))
+ return true;
+
return false;
}
@@ -124,18 +180,21 @@ QStringList QWaylandMimeData::formats_sys() const
return m_types;
}
-QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QMetaType type) const
{
Q_UNUSED(type);
- if (m_data.contains(mimeType))
- return m_data.value(mimeType);
+ auto it = m_data.constFind(mimeType);
+ if (it != m_data.constEnd())
+ return *it;
QString mime = mimeType;
if (!m_types.contains(mimeType)) {
if (mimeType == QStringLiteral("text/plain") && m_types.contains(utf8Text()))
mime = utf8Text();
+ else if (mimeType == uriList() && m_types.contains(mozUrl()))
+ mime = mozUrl();
else
return QVariant();
}
@@ -157,37 +216,42 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
}
close(pipefd[0]);
- m_data.insert(mimeType, content);
+
+ content = convertData(mimeType, mime, content);
+
+ if (mimeType != portalFileTransfer())
+ m_data.insert(mimeType, content);
+
return content;
}
int QWaylandMimeData::readData(int fd, QByteArray &data) const
{
- fd_set readset;
- FD_ZERO(&readset);
- FD_SET(fd, &readset);
- struct timeval timeout;
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-
- int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout);
- if (ready < 0) {
- qWarning() << "QWaylandDataOffer: select() failed";
- return -1;
- } else if (ready == 0) {
- qWarning("QWaylandDataOffer: timeout reading from pipe");
- return -1;
- } else {
- char buf[4096];
- int n = QT_READ(fd, buf, sizeof buf);
-
- if (n > 0) {
- data.append(buf, n);
- n = readData(fd, data);
- } else if (n < 0) {
- qWarning("QWaylandDataOffer: read() failed");
+ struct pollfd readset;
+ readset.fd = fd;
+ readset.events = POLLIN;
+
+ Q_FOREVER {
+ int ready = qt_safe_poll(&readset, 1, QDeadlineTimer(1s));
+ if (ready < 0) {
+ qWarning() << "QWaylandDataOffer: qt_safe_poll() failed";
+ return -1;
+ } else if (ready == 0) {
+ qWarning("QWaylandDataOffer: timeout reading from pipe");
+ return -1;
+ } else {
+ char buf[4096];
+ int n = QT_READ(fd, buf, sizeof buf);
+
+ if (n < 0) {
+ qWarning("QWaylandDataOffer: read() failed");
+ return -1;
+ } else if (n == 0) {
+ return 0;
+ } else if (n > 0) {
+ data.append(buf, n);
+ }
}
- return n;
}
}
diff --git a/src/client/qwaylanddataoffer_p.h b/src/client/qwaylanddataoffer_p.h
index 9cf1483ca..1c99147d2 100644
--- a/src/client/qwaylanddataoffer_p.h
+++ b/src/client/qwaylanddataoffer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDATAOFFER_H
#define QWAYLANDDATAOFFER_H
@@ -51,6 +15,9 @@
// We mean it.
//
+#include <QtCore/qhash.h>
+#include <QtCore/qstring.h>
+
#include <QtGui/private/qinternalmimedata_p.h>
#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
@@ -74,7 +41,7 @@ public:
virtual ~QWaylandAbstractDataOffer() = default;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDataOffer
+class Q_WAYLANDCLIENT_EXPORT QWaylandDataOffer
: public QtWayland::wl_data_offer // needs to be the first because we do static casts from the user pointer to the wrapper
, public QWaylandAbstractDataOffer
{
@@ -82,6 +49,7 @@ public:
explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
~QWaylandDataOffer() override;
QMimeData *mimeData() override;
+ Qt::DropActions supportedActions() const;
QString firstFormat() const;
@@ -89,10 +57,13 @@ public:
protected:
void data_offer_offer(const QString &mime_type) override;
+ void data_offer_source_actions(uint32_t source_actions) override;
+ void data_offer_action(uint32_t dnd_action) override;
private:
QWaylandDisplay *m_display = nullptr;
QScopedPointer<QWaylandMimeData> m_mimeData;
+ Qt::DropActions m_supportedActions;
};
@@ -106,7 +77,7 @@ public:
protected:
bool hasFormat_sys(const QString &mimeType) const override;
QStringList formats_sys() const override;
- QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const override;
+ QVariant retrieveData_sys(const QString &mimeType, QMetaType type) const override;
private:
int readData(int fd, QByteArray &data) const;
diff --git a/src/client/qwaylanddatasource.cpp b/src/client/qwaylanddatasource.cpp
index ea76943a7..966d5ef7f 100644
--- a/src/client/qwaylanddatasource.cpp
+++ b/src/client/qwaylanddatasource.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddatasource_p.h"
#include "qwaylanddataoffer_p.h"
@@ -49,6 +13,7 @@
#include <unistd.h>
#include <signal.h>
+#include <fcntl.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +25,7 @@ QWaylandDataSource::QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceMana
{
if (!mimeData)
return;
- const auto formats = mimeData->formats();
+ const auto formats = QInternalMimeData::formatsHelper(mimeData);
for (const QString &format : formats) {
offer(format);
}
@@ -71,11 +36,6 @@ QWaylandDataSource::~QWaylandDataSource()
destroy();
}
-QMimeData * QWaylandDataSource::mimeData() const
-{
- return m_mime_data;
-}
-
void QWaylandDataSource::data_source_cancelled()
{
Q_EMIT cancelled();
@@ -93,7 +53,15 @@ void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
action.sa_flags = 0;
sigaction(SIGPIPE, &action, &oldAction);
- write(fd, content.constData(), content.size());
+ // Some compositors (e.g., mutter) make fd with O_NONBLOCK.
+ // Since wl_data_source.send describes that fd is closed here,
+ // it should be done in a loop and don't have any advantage.
+ // Blocking operation will be used.
+ // According to fcntl(2), FSETFL ignores O_WRONLY. So this
+ // call will just remove O_NONBLOCK.
+ fcntl(fd, F_SETFL, O_WRONLY);
+ ssize_t unused = write(fd, content.constData(), content.size());
+ Q_UNUSED(unused);
sigaction(SIGPIPE, &oldAction, nullptr);
}
close(fd);
@@ -101,9 +69,36 @@ void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
void QWaylandDataSource::data_source_target(const QString &mime_type)
{
- Q_EMIT targetChanged(mime_type);
+ m_accepted = !mime_type.isEmpty();
+ Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
+}
+
+void QWaylandDataSource::data_source_action(uint32_t action)
+{
+ Qt::DropAction qtAction = Qt::IgnoreAction;
+
+ if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+ qtAction = Qt::MoveAction;
+ else if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+ qtAction = Qt::CopyAction;
+
+ m_dropAction = qtAction;
+ Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
+}
+
+void QWaylandDataSource::data_source_dnd_finished()
+{
+ Q_EMIT finished();
+}
+
+void QWaylandDataSource::data_source_dnd_drop_performed()
+{
+
+ Q_EMIT dndDropped(m_accepted, m_dropAction);
}
}
QT_END_NAMESPACE
+
+#include "moc_qwaylanddatasource_p.cpp"
diff --git a/src/client/qwaylanddatasource_p.h b/src/client/qwaylanddatasource_p.h
index 25afff79c..a4b317c26 100644
--- a/src/client/qwaylanddatasource_p.h
+++ b/src/client/qwaylanddatasource_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDATASOURCE_H
#define QWAYLANDDATASOURCE_H
@@ -67,27 +31,32 @@ namespace QtWaylandClient {
class QWaylandDataDeviceManager;
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDataSource : public QObject, public QtWayland::wl_data_source
+class Q_WAYLANDCLIENT_EXPORT QWaylandDataSource : public QObject, public QtWayland::wl_data_source
{
Q_OBJECT
public:
QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData);
~QWaylandDataSource() override;
- QMimeData *mimeData() const;
-
Q_SIGNALS:
- void targetChanged(const QString &mime_type);
void cancelled();
+ void finished();
+
+ void dndResponseUpdated(bool accepted, Qt::DropAction action);
+ void dndDropped(bool accepted, Qt::DropAction action);
protected:
void data_source_cancelled() override;
void data_source_send(const QString &mime_type, int32_t fd) override;
void data_source_target(const QString &mime_type) override;
+ void data_source_dnd_drop_performed() override;
+ void data_source_dnd_finished() override;
+ void data_source_action(uint32_t action) override;
private:
- QWaylandDisplay *m_display = nullptr;
QMimeData *m_mime_data = nullptr;
+ bool m_accepted = false;
+ Qt::DropAction m_dropAction = Qt::IgnoreAction;
};
}
diff --git a/src/client/qwaylanddecorationfactory.cpp b/src/client/qwaylanddecorationfactory.cpp
index 32db96e58..b716a4aee 100644
--- a/src/client/qwaylanddecorationfactory.cpp
+++ b/src/client/qwaylanddecorationfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddecorationfactory_p.h"
#include "qwaylanddecorationplugin_p.h"
@@ -48,50 +12,17 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qwdfiLoader,
(QWaylandDecorationFactoryInterface_iid, QLatin1String("/wayland-decoration-client"), Qt::CaseInsensitive))
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QWaylandDecorationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
-QStringList QWaylandDecorationFactory::keys(const QString &pluginPath)
+QStringList QWaylandDecorationFactory::keys()
{
-#if QT_CONFIG(library)
- QStringList list;
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- list = directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QStringLiteral(" (from ")
- + QDir::toNativeSeparators(pluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
- list.append(loader()->keyMap().values());
- return list;
-#else
- return QStringList();
-#endif
+ return qwdfiLoader->keyMap().values();
}
-QWaylandAbstractDecoration *QWaylandDecorationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath)
+QWaylandAbstractDecoration *QWaylandDecorationFactory::create(const QString &name, const QStringList &args)
{
-#if QT_CONFIG(library)
- // Try loading the plugin from platformPluginPath first:
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- if (QWaylandAbstractDecoration *ret = qLoadPlugin<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(directLoader(), name, args))
- return ret;
- }
- if (QWaylandAbstractDecoration *ret = qLoadPlugin<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(loader(), name, args))
- return ret;
-#endif
-
- return nullptr;
+ return qLoadPlugin<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(qwdfiLoader(), name, args);
}
}
diff --git a/src/client/qwaylanddecorationfactory_p.h b/src/client/qwaylanddecorationfactory_p.h
index 606d9b89c..bd0998631 100644
--- a/src/client/qwaylanddecorationfactory_p.h
+++ b/src/client/qwaylanddecorationfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDECORATIONFACTORY_H
#define QWAYLANDDECORATIONFACTORY_H
@@ -53,6 +17,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtCore/QStringList>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -60,11 +25,11 @@ namespace QtWaylandClient {
class QWaylandAbstractDecoration;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDecorationFactory
+class Q_WAYLANDCLIENT_EXPORT QWaylandDecorationFactory
{
public:
- static QStringList keys(const QString &pluginPath = QString());
- static QWaylandAbstractDecoration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString());
+ static QStringList keys();
+ static QWaylandAbstractDecoration *create(const QString &name, const QStringList &args);
};
}
diff --git a/src/client/qwaylanddecorationplugin.cpp b/src/client/qwaylanddecorationplugin.cpp
index 15d907de9..f64211996 100644
--- a/src/client/qwaylanddecorationplugin.cpp
+++ b/src/client/qwaylanddecorationplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddecorationplugin_p.h"
@@ -54,3 +18,5 @@ QWaylandDecorationPlugin::~QWaylandDecorationPlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylanddecorationplugin_p.cpp"
diff --git a/src/client/qwaylanddecorationplugin_p.h b/src/client/qwaylanddecorationplugin_p.h
index 41daaea05..e09d99702 100644
--- a/src/client/qwaylanddecorationplugin_p.h
+++ b/src/client/qwaylanddecorationplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDECORATIONPLUGIN_H
#define QWAYLANDDECORATIONPLUGIN_H
@@ -56,6 +20,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/QObject>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,7 @@ class QWaylandAbstractDecoration;
#define QWaylandDecorationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandDecorationFactoryInterface.5.4"
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDecorationPlugin : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandDecorationPlugin : public QObject
{
Q_OBJECT
public:
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index a17e8917a..f78bf2dd2 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddisplay_p.h"
@@ -60,19 +24,33 @@
#include <wayland-cursor.h>
#endif
#include "qwaylandhardwareintegration_p.h"
+#include "qwaylandtextinputv1_p.h"
+#include "qwaylandtextinputv2_p.h"
+#include "qwaylandtextinputv3_p.h"
#include "qwaylandinputcontext_p.h"
+#include "qwaylandinputmethodcontext_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandshellintegration_p.h"
#include "qwaylandclientbufferintegration_p.h"
-#include "qwaylandextendedsurface_p.h"
+#include "qwaylandpointergestures_p.h"
#include "qwaylandsubsurface_p.h"
#include "qwaylandtouch_p.h"
+#if QT_CONFIG(tabletevent)
+#include "qwaylandtabletv2_p.h"
+#endif
#include "qwaylandqtkey_p.h"
+#include <QtWaylandClient/private/qwayland-text-input-unstable-v1.h>
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
+#include <QtWaylandClient/private/qwayland-text-input-unstable-v3.h>
#include <QtWaylandClient/private/qwayland-wp-primary-selection-unstable-v1.h>
+#include <QtWaylandClient/private/qwayland-qt-text-input-method-unstable-v1.h>
+#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h>
+#include <QtWaylandClient/private/qwayland-viewporter.h>
+#include <QtWaylandClient/private/qwayland-cursor-shape-v1.h>
+#include <QtWaylandClient/private/qwayland-xdg-toplevel-drag-v1.h>
#include <QtCore/private/qcore_unix_p.h>
@@ -84,22 +62,211 @@
#include <errno.h>
+#include <tuple> // for std::tie
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+class EventThread : public QThread
+{
+ Q_OBJECT
+public:
+ enum OperatingMode {
+ EmitToDispatch, // Emit the signal, allow dispatching in a differnt thread.
+ SelfDispatch, // Dispatch the events inside this thread.
+ };
+
+ EventThread(struct wl_display * wl, struct wl_event_queue * ev_queue,
+ OperatingMode mode)
+ : m_fd(wl_display_get_fd(wl))
+ , m_pipefd{ -1, -1 }
+ , m_wldisplay(wl)
+ , m_wlevqueue(ev_queue)
+ , m_mode(mode)
+ , m_reading(true)
+ , m_quitting(false)
+ {
+ setObjectName(QStringLiteral("WaylandEventThread"));
+ }
+
+ void readAndDispatchEvents()
+ {
+ /*
+ * Dispatch pending events and flush the requests at least once. If the event thread
+ * is not reading, try to call _prepare_read() to allow the event thread to poll().
+ * If that fails, re-try dispatch & flush again until _prepare_read() is successful.
+ *
+ * This allow any call to readAndDispatchEvents() to start event thread's polling,
+ * not only the one issued from event thread's waitForReading(), which means functions
+ * called from dispatch_pending() can safely spin an event loop.
+ */
+ if (m_quitting)
+ return;
+
+ for (;;) {
+ if (dispatchQueuePending() < 0) {
+ Q_EMIT waylandError();
+ m_quitting = true;
+ return;
+ }
+
+ wl_display_flush(m_wldisplay);
+
+ // We have to check if event thread is reading every time we dispatch
+ // something, as that may recursively call this function.
+ if (m_reading.loadAcquire())
+ break;
+
+ if (prepareReadQueue() == 0) {
+ QMutexLocker l(&m_mutex);
+ m_reading.storeRelease(true);
+ m_cond.wakeOne();
+ break;
+ }
+ }
+ }
+
+ void stop()
+ {
+ // We have to both write to the pipe and set the flag, as the thread may be
+ // either in the poll() or waiting for _prepare_read().
+ if (m_pipefd[1] != -1 && write(m_pipefd[1], "\0", 1) == -1)
+ qWarning("Failed to write to the pipe: %s.", strerror(errno));
+
+ {
+ QMutexLocker l(&m_mutex);
+ m_quitting = true;
+ m_cond.wakeOne();
+ }
+
+ wait();
+ }
+
+Q_SIGNALS:
+ void needReadAndDispatch();
+ void waylandError();
+
+protected:
+ void run() override
+ {
+ // we use this pipe to make the loop exit otherwise if we simply used a flag on the loop condition, if stop() gets
+ // called while poll() is blocking the thread will never quit since there are no wayland messages coming anymore.
+ struct Pipe
+ {
+ Pipe(int *fds)
+ : fds(fds)
+ {
+ if (qt_safe_pipe(fds) != 0)
+ qWarning("Pipe creation failed. Quitting may hang.");
+ }
+ ~Pipe()
+ {
+ if (fds[0] != -1) {
+ close(fds[0]);
+ close(fds[1]);
+ }
+ }
+
+ int *fds;
+ } pipe(m_pipefd);
+
+ // Make the main thread call wl_prepare_read(), dispatch the pending messages and flush the
+ // outbound ones. Wait until it's done before proceeding, unless we're told to quit.
+ while (waitForReading()) {
+ if (!m_reading.loadRelaxed())
+ break;
+
+ pollfd fds[2] = { { m_fd, POLLIN, 0 }, { m_pipefd[0], POLLIN, 0 } };
+ poll(fds, 2, -1);
+
+ if (fds[1].revents & POLLIN) {
+ // we don't really care to read the byte that was written here since we're closing down
+ wl_display_cancel_read(m_wldisplay);
+ break;
+ }
+
+ if (fds[0].revents & POLLIN)
+ wl_display_read_events(m_wldisplay);
+ // The polll was succesfull and the event thread did the wl_display_read_events(). On the next iteration of the loop
+ // the event sent to the main thread will cause it to dispatch the messages just read, unless the loop exits in which
+ // case we don't care anymore about them.
+ else
+ wl_display_cancel_read(m_wldisplay);
+ }
+ }
+
+private:
+ bool waitForReading()
+ {
+ Q_ASSERT(QThread::currentThread() == this);
+
+ m_reading.storeRelease(false);
+
+ if (m_mode == SelfDispatch) {
+ readAndDispatchEvents();
+ } else {
+ Q_EMIT needReadAndDispatch();
+
+ QMutexLocker lock(&m_mutex);
+ // m_reading might be set from our emit or some other invocation of
+ // readAndDispatchEvents().
+ while (!m_reading.loadRelaxed() && !m_quitting)
+ m_cond.wait(&m_mutex);
+ }
+
+ return !m_quitting;
+ }
+
+ int dispatchQueuePending()
+ {
+ if (m_wlevqueue)
+ return wl_display_dispatch_queue_pending(m_wldisplay, m_wlevqueue);
+ else
+ return wl_display_dispatch_pending(m_wldisplay);
+ }
+
+ int prepareReadQueue()
+ {
+ if (m_wlevqueue)
+ return wl_display_prepare_read_queue(m_wldisplay, m_wlevqueue);
+ else
+ return wl_display_prepare_read(m_wldisplay);
+ }
+
+ int m_fd;
+ int m_pipefd[2];
+ wl_display *m_wldisplay;
+ wl_event_queue *m_wlevqueue;
+ OperatingMode m_mode;
+
+ /* Concurrency note when operating in EmitToDispatch mode:
+ * m_reading is set to false inside event thread's waitForReading(), and is
+ * set to true inside main thread's readAndDispatchEvents().
+ * The lock is not taken when setting m_reading to false, as the main thread
+ * is not actively waiting for it to turn false. However, the lock is taken
+ * inside readAndDispatchEvents() before setting m_reading to true,
+ * as the event thread is actively waiting for it under the wait condition.
+ */
+
+ QAtomicInteger<bool> m_reading;
+ bool m_quitting;
+ QMutex m_mutex;
+ QWaitCondition m_cond;
+};
+
Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorized) Wayland platform logging
struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
- struct wl_surface *surface = mCompositor.create_surface();
+ struct wl_surface *surface = mGlobals.compositor->create_surface();
wl_surface_set_user_data(surface, handle);
return surface;
}
struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
{
- struct ::wl_region *region = mCompositor.create_region();
+ struct ::wl_region *region = mGlobals.compositor->create_region();
for (const QRect &rect : qregion)
wl_region_add(region, rect.x(), rect.y(), rect.width(), rect.height());
@@ -109,12 +276,27 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
::wl_subsurface *QWaylandDisplay::createSubSurface(QWaylandWindow *window, QWaylandWindow *parent)
{
- if (!mSubCompositor) {
+ if (!mGlobals.subCompositor) {
qCWarning(lcQpaWayland) << "Can't create subsurface, not supported by the compositor.";
return nullptr;
}
- return mSubCompositor->get_subsurface(window->wlSurface(), parent->wlSurface());
+ // Make sure we don't pass NULL surfaces to libwayland (crashes)
+ Q_ASSERT(parent->wlSurface());
+ Q_ASSERT(window->wlSurface());
+
+ return mGlobals.subCompositor->get_subsurface(window->wlSurface(), parent->wlSurface());
+}
+
+::wp_viewport *QWaylandDisplay::createViewport(QWaylandWindow *window)
+{
+ if (!mGlobals.viewporter) {
+ qCWarning(lcQpaWayland) << "Can't create wp_viewport, not supported by the compositor.";
+ return nullptr;
+ }
+
+ Q_ASSERT(window->wlSurface());
+ return mGlobals.viewporter->get_viewport(window->wlSurface());
}
QWaylandShellIntegration *QWaylandDisplay::shellIntegration() const
@@ -129,7 +311,7 @@ QWaylandClientBufferIntegration * QWaylandDisplay::clientBufferIntegration() con
QWaylandWindowManagerIntegration *QWaylandDisplay::windowManagerIntegration() const
{
- return mWindowManagerIntegration.data();
+ return mGlobals.windowManagerIntegration.get();
}
QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
@@ -138,119 +320,274 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
qRegisterMetaType<uint32_t>("uint32_t");
mDisplay = wl_display_connect(nullptr);
- if (!mDisplay) {
+ if (mDisplay) {
+ setupConnection();
+ } else {
qErrnoWarning(errno, "Failed to create wl_display");
- return;
}
+ mWaylandTryReconnect = qEnvironmentVariableIsSet("QT_WAYLAND_RECONNECT");
+}
+
+void QWaylandDisplay::setupConnection()
+{
struct ::wl_registry *registry = wl_display_get_registry(mDisplay);
init(registry);
- mWindowManagerIntegration.reset(new QWaylandWindowManagerIntegration(this));
-
#if QT_CONFIG(xkbcommon)
mXkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
if (!mXkbContext)
qCWarning(lcQpaWayland, "failed to create xkb context");
#endif
-
- forceRoundTrip();
-
- if (!mWaitingScreens.isEmpty()) {
- // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
- forceRoundTrip();
- }
+ if (mWaylandInputContextRequested)
+ checkTextInputProtocol();
}
QWaylandDisplay::~QWaylandDisplay(void)
{
+ if (m_eventThread)
+ m_eventThread->stop();
+
+ if (m_frameEventQueueThread)
+ m_frameEventQueueThread->stop();
+
if (mSyncCallback)
wl_callback_destroy(mSyncCallback);
- qDeleteAll(qExchange(mInputDevices, {}));
+ qDeleteAll(std::exchange(mInputDevices, {}));
- for (QWaylandScreen *screen : qExchange(mScreens, {})) {
+ for (QWaylandScreen *screen : std::exchange(mScreens, {})) {
QWindowSystemInterface::handleScreenRemoved(screen);
}
qDeleteAll(mWaitingScreens);
-#if QT_CONFIG(wayland_datadevice)
- delete mDndSelectionHandler.take();
-#endif
#if QT_CONFIG(cursor)
- qDeleteAll(mCursorThemes);
+ mCursorThemes.clear();
#endif
+
+ if (m_frameEventQueue)
+ wl_event_queue_destroy(m_frameEventQueue);
+
+ // Reset the globals manually since they need to be destroyed before the wl_display
+ mGlobals = {};
+
+ if (object())
+ wl_registry_destroy(object());
+
if (mDisplay)
wl_display_disconnect(mDisplay);
}
-void QWaylandDisplay::checkError() const
+// Steps which is called just after constructor. This separates registry_global() out of the constructor
+// so that factory functions in integration can be overridden.
+bool QWaylandDisplay::initialize()
{
- int ecode = wl_display_get_error(mDisplay);
- if ((ecode == EPIPE || ecode == ECONNRESET)) {
- // special case this to provide a nicer error
- qFatal("The Wayland connection broke. Did the Wayland compositor die?");
- } else {
- qFatal("The Wayland connection experienced a fatal error: %s", strerror(ecode));
+ if (!isInitialized())
+ return false;
+
+ forceRoundTrip();
+
+ emit connected();
+
+ if (!mWaitingScreens.isEmpty()) {
+ // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
+ forceRoundTrip();
}
+ if (mWaylandInputContextRequested)
+ mTextInputManagerIndex = INT_MAX;
+
+ return qEnvironmentVariableIntValue("QT_WAYLAND_DONT_CHECK_SHELL_INTEGRATION") || shellIntegration();
}
-void QWaylandDisplay::flushRequests()
+void QWaylandDisplay::ensureScreen()
{
- if (wl_display_prepare_read(mDisplay) == 0) {
- wl_display_read_events(mDisplay);
- }
+ if (!mScreens.empty() || mPlaceholderScreen)
+ return; // There are real screens or we already have a fake one
- if (wl_display_dispatch_pending(mDisplay) < 0)
- checkError();
+ qCInfo(lcQpaWayland) << "Creating a fake screen in order for Qt not to crash";
- wl_display_flush(mDisplay);
+ mPlaceholderScreen = new QPlatformPlaceholderScreen();
+ QWindowSystemInterface::handleScreenAdded(mPlaceholderScreen);
+ Q_ASSERT(!QGuiApplication::screens().empty());
}
-void QWaylandDisplay::blockingReadEvents()
+void QWaylandDisplay::reconnect()
{
- if (wl_display_dispatch(mDisplay) < 0)
- checkError();
+ qCWarning(lcQpaWayland) << "Attempting wayland reconnect";
+ m_eventThread->stop();
+ m_frameEventQueueThread->stop();
+ m_eventThread->wait();
+ m_frameEventQueueThread->wait();
+
+ qDeleteAll(mWaitingScreens);
+ mWaitingScreens.clear();
+
+ while (!mScreens.isEmpty()) {
+ auto screen = mScreens.takeLast();
+ ensureScreen();
+ QWindowSystemInterface::handleScreenRemoved(screen);
+ }
+
+ mCursorThemes.clear();
+ mCursor.reset();
+
+ mGlobals = GlobalHolder();
+
+ mWaylandIntegration->reset();
+
+ qDeleteAll(std::exchange(mInputDevices, {}));
+ mLastInputDevice = nullptr;
+
+ for (const RegistryGlobal &global : mRegistryGlobals) {
+ emit globalRemoved(global);
+ }
+ mRegistryGlobals.clear();
+
+ mLastInputSerial = 0;
+ mLastInputWindow.clear();
+ mLastKeyboardFocus.clear();
+ mActiveWindows.clear();
+
+ const auto windows = QGuiApplication::allWindows();
+ for (auto window : windows) {
+ if (auto waylandWindow = static_cast<QWaylandWindow *>(window->handle()))
+ waylandWindow->closeChildPopups();
+ }
+ // Remove windows that do not need to be recreated and now closed popups
+ QList<QWaylandWindow *> recreateWindows;
+ for (auto window : std::as_const(windows)) {
+ auto waylandWindow = static_cast<QWaylandWindow*>(window->handle());
+ if (waylandWindow && waylandWindow->wlSurface()) {
+ waylandWindow->reset();
+ recreateWindows.push_back(waylandWindow);
+ }
+ }
+
+ if (mSyncCallback) {
+ wl_callback_destroy(mSyncCallback);
+ mSyncCallback = nullptr;
+ }
+
+ if (object())
+ wl_registry_destroy(object());
+ mDisplay = wl_display_connect(nullptr);
+ if (!mDisplay)
+ _exit(1);
+
+ setupConnection();
+ initialize();
+
+ if (m_frameEventQueue)
+ wl_event_queue_destroy(m_frameEventQueue);
+ initEventThread();
+
+ auto needsRecreate = [](QPlatformWindow *window) {
+ return window && !static_cast<QWaylandWindow *>(window)->wlSurface();
+ };
+ auto window = recreateWindows.begin();
+ while (!recreateWindows.isEmpty()) {
+ if (!needsRecreate((*window)->QPlatformWindow::parent()) && !needsRecreate((*window)->transientParent())) {
+ (*window)->reinit();
+ window = recreateWindows.erase(window);
+ } else {
+ ++window;
+ }
+ if (window == recreateWindows.end())
+ window = recreateWindows.begin();
+ }
+
+ mWaylandIntegration->reconfigureInputContext();
}
-wl_event_queue *QWaylandDisplay::createEventQueue()
+void QWaylandDisplay::flushRequests()
{
- return wl_display_create_queue(mDisplay);
+ m_eventThread->readAndDispatchEvents();
}
-void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bool ()> condition, int timeout)
+// We have to wait until we have an eventDispatcher before creating the eventThread,
+// otherwise forceRoundTrip() may block inside _events_read() because eventThread is
+// polling.
+void QWaylandDisplay::initEventThread()
{
- if (!condition())
- return;
-
- QElapsedTimer timer;
- timer.start();
- struct pollfd pFd = qt_make_pollfd(wl_display_get_fd(mDisplay), POLLIN);
- while (timeout == -1 || timer.elapsed() < timeout) {
- while (wl_display_prepare_read_queue(mDisplay, queue) != 0)
- wl_display_dispatch_queue_pending(mDisplay, queue);
+ m_eventThread.reset(
+ new EventThread(mDisplay, /* default queue */ nullptr, EventThread::EmitToDispatch));
+ connect(m_eventThread.get(), &EventThread::needReadAndDispatch, this,
+ &QWaylandDisplay::flushRequests, Qt::QueuedConnection);
+ connect(m_eventThread.get(), &EventThread::waylandError, this,
+ &QWaylandDisplay::checkWaylandError, Qt::QueuedConnection);
+ m_eventThread->start();
+
+ // wl_display_disconnect() free this.
+ m_frameEventQueue = wl_display_create_queue(mDisplay);
+ m_frameEventQueueThread.reset(
+ new EventThread(mDisplay, m_frameEventQueue, EventThread::SelfDispatch));
+ m_frameEventQueueThread->start();
+}
- wl_display_flush(mDisplay);
+void QWaylandDisplay::checkWaylandError()
+{
+ int ecode = wl_display_get_error(mDisplay);
+ if ((ecode == EPIPE || ecode == ECONNRESET)) {
+ qWarning("The Wayland connection broke. Did the Wayland compositor die?");
+ if (mWaylandTryReconnect) {
+ reconnect();
+ return;
+ }
+ } else {
+ qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode));
+ }
+ _exit(-1);
+}
- const int remaining = qMax(timeout - timer.elapsed(), 0ll);
- const int pollTimeout = timeout == -1 ? -1 : remaining;
- if (qt_poll_msecs(&pFd, 1, pollTimeout) > 0)
- wl_display_read_events(mDisplay);
+void QWaylandDisplay::blockingReadEvents()
+{
+ if (wl_display_dispatch(mDisplay) < 0) {
+ int ecode = wl_display_get_error(mDisplay);
+ if ((ecode == EPIPE || ecode == ECONNRESET))
+ qWarning("The Wayland connection broke during blocking read event. Did the Wayland compositor die?");
else
- wl_display_cancel_read(mDisplay);
-
- if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0)
- checkError();
+ qWarning("The Wayland connection experienced a fatal error during blocking read event: %s", strerror(ecode));
+ _exit(-1);
+ }
+}
- if (!condition())
- break;
+void QWaylandDisplay::checkTextInputProtocol()
+{
+ QStringList tips, timps; // for text input protocols and text input manager protocols
+ // zwp_text_input_v2 is preferred over zwp_text_input_v3 because:
+ // - Currently, v3 is not as feature rich as v2.
+ // - While v2 is not upstreamed, it is well supported by KWin since Plasma 5 and Plasma
+ // Mobile uses some v2 only.
+ tips << QLatin1String(QtWayland::qt_text_input_method_v1::interface()->name)
+ << QLatin1String(QtWayland::zwp_text_input_v2::interface()->name)
+ << QLatin1String(QtWayland::zwp_text_input_v3::interface()->name)
+ << QLatin1String(QtWayland::zwp_text_input_v1::interface()->name);
+ timps << QLatin1String(QtWayland::qt_text_input_method_manager_v1::interface()->name)
+ << QLatin1String(QtWayland::zwp_text_input_manager_v2::interface()->name)
+ << QLatin1String(QtWayland::zwp_text_input_manager_v3::interface()->name)
+ << QLatin1String(QtWayland::zwp_text_input_manager_v1::interface()->name);
+
+ QString tiProtocols = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_TEXT_INPUT_PROTOCOL"));
+ qCDebug(lcQpaWayland) << "QT_WAYLAND_TEXT_INPUT_PROTOCOL=" << tiProtocols;
+ QStringList keys;
+ if (!tiProtocols.isEmpty()) {
+ keys = tiProtocols.split(QLatin1Char(';'));
+ QList<QString>::iterator it = keys.begin();
+ while (it != keys.end()) {
+ if (tips.contains(*it))
+ mTextInputManagerList.append(timps.at(tips.indexOf(*it)));
+ else
+ qCDebug(lcQpaWayland) << "text input: unknown protocol - " << *it;
+ ++it;
+ }
}
+ if (mTextInputManagerList.isEmpty()) // fallback
+ mTextInputManagerList = timps;
}
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 : std::as_const(mScreens)) {
if (screen->output() == output)
return screen;
}
@@ -263,78 +600,186 @@ 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()
+template <typename T, auto f>
+struct WithDestructor : public T
{
- flushRequests();
-
- while (true) {
- bool screensReady = !mScreens.isEmpty();
-
- for (int ii = 0; screensReady && ii < mScreens.count(); ++ii) {
- if (mScreens.at(ii)->geometry() == QRect(0, 0, 0, 0))
- screensReady = false;
- }
-
- if (!screensReady)
- blockingReadEvents();
- else
- return;
+ using T::T;
+ ~WithDestructor()
+ {
+ f(this->object());
}
-}
+};
void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uint32_t version)
{
struct ::wl_registry *registry = object();
- if (interface == QStringLiteral("wl_output")) {
- mWaitingScreens << new QWaylandScreen(this, version, id);
- } else if (interface == QStringLiteral("wl_compositor")) {
- mCompositorVersion = qMin((int)version, 3);
- mCompositor.init(registry, id, mCompositorVersion);
- } else if (interface == QStringLiteral("wl_shm")) {
- mShm.reset(new QWaylandShm(this, version, id));
- } else if (interface == QStringLiteral("wl_seat")) {
+ static QStringList interfaceBlacklist = qEnvironmentVariable("QT_WAYLAND_DISABLED_INTERFACES").split(u',');
+ if (interfaceBlacklist.contains(interface)) {
+ return;
+ }
+
+ if (interface == QLatin1String(QtWayland::wl_output::interface()->name)) {
+ mWaitingScreens << mWaylandIntegration->createPlatformScreen(this, version, id);
+ } else if (interface == QLatin1String(QtWayland::wl_compositor::interface()->name)) {
+ mGlobals.compositor.reset(
+ new WithDestructor<QtWayland::wl_compositor, wl_compositor_destroy>(
+ registry, id, qMin((int)version, 6)));
+ } else if (interface == QLatin1String(QWaylandShm::interface()->name)) {
+ mGlobals.shm.reset(new QWaylandShm(this, version, id));
+ } else if (interface == QLatin1String(QWaylandInputDevice::interface()->name)) {
QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, version, id);
mInputDevices.append(inputDevice);
#if QT_CONFIG(wayland_datadevice)
- } else if (interface == QStringLiteral("wl_data_device_manager")) {
- mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
+ } else if (interface == QLatin1String(QWaylandDataDeviceManager::interface()->name)) {
+ mGlobals.dndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id));
+#endif
+ } else if (interface == QLatin1String(QtWayland::wl_subcompositor::interface()->name)) {
+ mGlobals.subCompositor.reset(
+ new WithDestructor<QtWayland::wl_subcompositor, wl_subcompositor_destroy>(registry,
+ id, 1));
+ } else if (interface == QLatin1String(QWaylandTouchExtension::interface()->name)) {
+ mGlobals.touchExtension.reset(new QWaylandTouchExtension(this, id));
+ } else if (interface == QLatin1String(QWaylandQtKeyExtension::interface()->name)) {
+ mGlobals.qtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
+#if QT_CONFIG(tabletevent)
+ } else if (interface == QLatin1String(QWaylandTabletManagerV2::interface()->name)) {
+ mGlobals.tabletManager.reset(new QWaylandTabletManagerV2(this, id, qMin(1, int(version))));
#endif
- } else if (interface == QStringLiteral("qt_surface_extension")) {
- mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
- } else if (interface == QStringLiteral("wl_subcompositor")) {
- mSubCompositor.reset(new QtWayland::wl_subcompositor(registry, id, 1));
- } else if (interface == QStringLiteral("qt_touch_extension")) {
- mTouchExtension.reset(new QWaylandTouchExtension(this, id));
- } else if (interface == QStringLiteral("zqt_key_v1")) {
- mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
+ } else if (interface == QLatin1String(QWaylandPointerGestures::interface()->name)) {
+ mGlobals.pointerGestures.reset(new QWaylandPointerGestures(this, id, 1));
#if QT_CONFIG(wayland_client_primary_selection)
- } else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
- mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
+ } else if (interface == QLatin1String(QWaylandPrimarySelectionDeviceManagerV1::interface()->name)) {
+ mGlobals.primarySelectionManager.reset(
+ new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setPrimarySelectionDevice(
+ mGlobals.primarySelectionManager->createDevice(inputDevice));
#endif
- } else if (interface == QStringLiteral("zwp_text_input_manager_v2") && !mClientSideInputContextRequested) {
- mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
- for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
- inputDevice->setTextInput(new QWaylandTextInput(this, mTextInputManager->get_text_input(inputDevice->wl_seat())));
+ } else if (interface == QLatin1String(QtWayland::qt_text_input_method_manager_v1::interface()->name)
+ && (mTextInputManagerList.contains(interface) && mTextInputManagerList.indexOf(interface) < mTextInputManagerIndex)) {
+ qCDebug(lcQpaWayland) << "text input: register qt_text_input_method_manager_v1";
+ if (mTextInputManagerIndex < INT_MAX) {
+ mGlobals.textInputManagerv1.reset();
+ mGlobals.textInputManagerv2.reset();
+ mGlobals.textInputManagerv3.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInput(nullptr);
+ }
+
+ mGlobals.textInputMethodManager.reset(
+ new WithDestructor<QtWayland::qt_text_input_method_manager_v1,
+ qt_text_input_method_manager_v1_destroy>(registry, id, 1));
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInputMethod(new QWaylandTextInputMethod(
+ this,
+ mGlobals.textInputMethodManager->get_text_input_method(
+ inputDevice->wl_seat())));
+ mWaylandIntegration->reconfigureInputContext();
+ mTextInputManagerIndex = mTextInputManagerList.indexOf(interface);
+ } else if (interface == QLatin1String(QtWayland::zwp_text_input_manager_v1::interface()->name)
+ && (mTextInputManagerList.contains(interface) && mTextInputManagerList.indexOf(interface) < mTextInputManagerIndex)) {
+ qCDebug(lcQpaWayland) << "text input: register zwp_text_input_v1";
+ if (mTextInputManagerIndex < INT_MAX) {
+ mGlobals.textInputMethodManager.reset();
+ mGlobals.textInputManagerv2.reset();
+ mGlobals.textInputManagerv3.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInputMethod(nullptr);
+ }
+
+ mGlobals.textInputManagerv1.reset(
+ new WithDestructor<QtWayland::zwp_text_input_manager_v1,
+ zwp_text_input_manager_v1_destroy>(registry, id, 1));
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices)) {
+ auto textInput =
+ new QWaylandTextInputv1(this, mGlobals.textInputManagerv1->create_text_input());
+ textInput->setSeat(inputDevice->wl_seat());
+ inputDevice->setTextInput(textInput);
+ }
+
+ mWaylandIntegration->reconfigureInputContext();
+ mTextInputManagerIndex = mTextInputManagerList.indexOf(interface);
+ } else if (interface == QLatin1String(QtWayland::zwp_text_input_manager_v2::interface()->name)
+ && (mTextInputManagerList.contains(interface) && mTextInputManagerList.indexOf(interface) < mTextInputManagerIndex)) {
+ qCDebug(lcQpaWayland) << "text input: register zwp_text_input_v2";
+ if (mTextInputManagerIndex < INT_MAX) {
+ mGlobals.textInputMethodManager.reset();
+ mGlobals.textInputManagerv1.reset();
+ mGlobals.textInputManagerv3.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInputMethod(nullptr);
+ }
+
+ mGlobals.textInputManagerv2.reset(
+ new WithDestructor<QtWayland::zwp_text_input_manager_v2,
+ zwp_text_input_manager_v2_destroy>(registry, id, 1));
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInput(new QWaylandTextInputv2(
+ this, mGlobals.textInputManagerv2->get_text_input(inputDevice->wl_seat())));
+ mWaylandIntegration->reconfigureInputContext();
+ mTextInputManagerIndex = mTextInputManagerList.indexOf(interface);
+ } else if (interface == QLatin1String(QtWayland::zwp_text_input_manager_v3::interface()->name)
+ && (mTextInputManagerList.contains(interface) && mTextInputManagerList.indexOf(interface) < mTextInputManagerIndex)) {
+ qCDebug(lcQpaWayland) << "text input: register zwp_text_input_v3";
+ if (mTextInputManagerIndex < INT_MAX) {
+ mGlobals.textInputMethodManager.reset();
+ mGlobals.textInputManagerv2.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInputMethod(nullptr);
+ }
+ mGlobals.textInputManagerv3.reset(
+ new WithDestructor<QtWayland::zwp_text_input_manager_v3,
+ zwp_text_input_manager_v3_destroy>(registry, id, 1));
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInput(new QWaylandTextInputv3(
+ this, mGlobals.textInputManagerv3->get_text_input(inputDevice->wl_seat())));
+
mWaylandIntegration->reconfigureInputContext();
- } else if (interface == QStringLiteral("qt_hardware_integration")) {
+ mTextInputManagerIndex = mTextInputManagerList.indexOf(interface);
+ }else if (interface == QLatin1String(QWaylandHardwareIntegration::interface()->name)) {
bool disableHardwareIntegration = qEnvironmentVariableIntValue("QT_WAYLAND_DISABLE_HW_INTEGRATION");
if (!disableHardwareIntegration) {
- mHardwareIntegration.reset(new QWaylandHardwareIntegration(registry, id));
+ mGlobals.hardwareIntegration.reset(new QWaylandHardwareIntegration(registry, id));
// make a roundtrip here since we need to receive the events sent by
// qt_hardware_integration before creating windows
forceRoundTrip();
}
- } else if (interface == QLatin1String("zxdg_output_manager_v1")) {
- mXdgOutputManager.reset(new QtWayland::zxdg_output_manager_v1(registry, id, qMin(2, int(version))));
- for (auto *screen : qAsConst(mWaitingScreens))
+ } else if (interface == QLatin1String(QWaylandXdgOutputManagerV1::interface()->name)) {
+ mGlobals.xdgOutputManager.reset(new QWaylandXdgOutputManagerV1(this, id, version));
+ for (auto *screen : std::as_const(mWaitingScreens))
screen->initXdgOutput(xdgOutputManager());
- forceRoundTrip();
+ } else if (interface == QLatin1String(QtWayland::wp_fractional_scale_manager_v1::interface()->name)) {
+ mGlobals.fractionalScaleManager.reset(
+ new WithDestructor<QtWayland::wp_fractional_scale_manager_v1,
+ wp_fractional_scale_manager_v1_destroy>(registry, id, 1));
+ } else if (interface == QLatin1String("wp_viewporter")) {
+ mGlobals.viewporter.reset(
+ new WithDestructor<QtWayland::wp_viewporter, wp_viewporter_destroy>(
+ registry, id, qMin(1u, version)));
+ } else if (interface == QLatin1String(QtWayland::wp_cursor_shape_manager_v1::interface()->name)) {
+ mGlobals.cursorShapeManager.reset(new WithDestructor<QtWayland::wp_cursor_shape_manager_v1,
+ wp_cursor_shape_manager_v1_destroy>(
+ registry, id, std::min(1u, version)));
+ } else if (
+ interface == QLatin1String(QtWayland::xdg_toplevel_drag_manager_v1::interface()->name)) {
+ mGlobals.xdgToplevelDragManager.reset(
+ new WithDestructor<QtWayland::xdg_toplevel_drag_manager_v1,
+ xdg_toplevel_drag_manager_v1_destroy>(registry, id, 1));
+ } else if (interface == QLatin1String(QtWayland::qt_windowmanager::interface()->name)) {
+ mGlobals.windowManagerIntegration.reset(
+ new QWaylandWindowManagerIntegration(this, id, version));
}
- mGlobals.append(RegistryGlobal(id, interface, version, registry));
+ mRegistryGlobals.append(RegistryGlobal(id, interface, version, registry));
+ emit globalAdded(mRegistryGlobals.back());
const auto copy = mRegistryListeners; // be prepared for listeners unregistering on notification
for (Listener l : copy)
@@ -343,10 +788,10 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
void QWaylandDisplay::registry_global_remove(uint32_t id)
{
- for (int i = 0, ie = mGlobals.count(); i != ie; ++i) {
- RegistryGlobal &global = mGlobals[i];
+ for (int i = 0, ie = mRegistryGlobals.size(); i != ie; ++i) {
+ RegistryGlobal &global = mRegistryGlobals[i];
if (global.id == id) {
- if (global.interface == QStringLiteral("wl_output")) {
+ if (global.interface == QLatin1String(QtWayland::wl_output::interface()->name)) {
for (auto *screen : mWaitingScreens) {
if (screen->outputId() == id) {
mWaitingScreens.removeOne(screen);
@@ -355,21 +800,48 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
}
}
- for (QWaylandScreen *screen : qAsConst(mScreens)) {
+ for (QWaylandScreen *screen : std::as_const(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;
}
}
}
- if (global.interface == QStringLiteral("zwp_text_input_manager_v2")) {
- mTextInputManager.reset();
- for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
+ if (global.interface == QLatin1String(QtWayland::zwp_text_input_manager_v1::interface()->name)) {
+ mGlobals.textInputManagerv1.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInput(nullptr);
+ mWaylandIntegration->reconfigureInputContext();
+ }
+ if (global.interface == QLatin1String(QtWayland::zwp_text_input_manager_v2::interface()->name)) {
+ mGlobals.textInputManagerv2.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInput(nullptr);
+ mWaylandIntegration->reconfigureInputContext();
+ }
+ if (global.interface == QLatin1String(QtWayland::zwp_text_input_manager_v3::interface()->name)) {
+ mGlobals.textInputManagerv3.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
inputDevice->setTextInput(nullptr);
mWaylandIntegration->reconfigureInputContext();
}
- mGlobals.removeAt(i);
+ if (global.interface == QLatin1String(QtWayland::qt_text_input_method_manager_v1::interface()->name)) {
+ mGlobals.textInputMethodManager.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setTextInputMethod(nullptr);
+ mWaylandIntegration->reconfigureInputContext();
+ }
+#if QT_CONFIG(wayland_client_primary_selection)
+ if (global.interface == QLatin1String(QtWayland::zwp_primary_selection_device_manager_v1::interface()->name)) {
+ mGlobals.primarySelectionManager.reset();
+ for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
+ inputDevice->setPrimarySelectionDevice(nullptr);
+ }
+#endif
+ emit globalRemoved(mRegistryGlobals.takeAt(i));
break;
}
}
@@ -377,7 +849,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
bool QWaylandDisplay::hasRegistryGlobal(QStringView interfaceName) const
{
- for (const RegistryGlobal &global : mGlobals)
+ for (const RegistryGlobal &global : mRegistryGlobals)
if (global.interface == interfaceName)
return true;
@@ -388,71 +860,22 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
{
Listener l = { listener, data };
mRegistryListeners.append(l);
- for (int i = 0, ie = mGlobals.count(); i != ie; ++i)
- (*l.listener)(l.data, mGlobals[i].registry, mGlobals[i].id, mGlobals[i].interface, mGlobals[i].version);
+ for (int i = 0, ie = mRegistryGlobals.size(); i != ie; ++i)
+ (*l.listener)(l.data, mRegistryGlobals[i].registry, mRegistryGlobals[i].id,
+ mRegistryGlobals[i].interface, mRegistryGlobals[i].version);
}
void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
{
- std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
+ auto iter = std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
return (l.listener == listener && l.data == data);
});
+ mRegistryListeners.erase(iter, mRegistryListeners.end());
}
-uint32_t QWaylandDisplay::currentTimeMillisec()
-{
- //### we throw away the time information
- struct timeval tv;
- int ret = gettimeofday(&tv, nullptr);
- if (ret == 0)
- return tv.tv_sec*1000 + tv.tv_usec/1000;
- return 0;
-}
-
-static void
-sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
-{
- Q_UNUSED(serial)
- bool *done = static_cast<bool *>(data);
-
- *done = true;
-
- // If the wl_callback done event is received after the condition check in the while loop in
- // forceRoundTrip(), but before the call to processEvents, the call to processEvents may block
- // forever if no more events are posted (eventhough the callback is handled in response to the
- // aboutToBlock signal). Hence, we wake up the event dispatcher so forceRoundTrip may return.
- // (QTBUG-64696)
- if (auto *dispatcher = QThread::currentThread()->eventDispatcher())
- dispatcher->wakeUp();
-
- wl_callback_destroy(callback);
-}
-
-static const struct wl_callback_listener sync_listener = {
- sync_callback
-};
-
void QWaylandDisplay::forceRoundTrip()
{
- // wl_display_roundtrip() works on the main queue only,
- // but we use a separate one, so basically reimplement it here
- int ret = 0;
- bool done = false;
- wl_callback *callback = wl_display_sync(mDisplay);
- wl_callback_add_listener(callback, &sync_listener, &done);
- flushRequests();
- if (QThread::currentThread()->eventDispatcher()) {
- while (!done && ret >= 0) {
- QThread::currentThread()->eventDispatcher()->processEvents(QEventLoop::WaitForMoreEvents);
- ret = wl_display_dispatch_pending(mDisplay);
- }
- } else {
- while (!done && ret >= 0)
- ret = wl_display_dispatch(mDisplay);
- }
-
- if (ret == -1 && !done)
- wl_callback_destroy(callback);
+ wl_display_roundtrip(mDisplay);
}
bool QWaylandDisplay::supportsWindowDecoration() const
@@ -463,7 +886,12 @@ bool QWaylandDisplay::supportsWindowDecoration() const
if (disabled)
return false;
- static bool integrationSupport = clientBufferIntegration() && clientBufferIntegration()->supportsWindowDecoration();
+ // Don't initialize client buffer integration just to check whether it can have a decoration.
+ if (!mWaylandIntegration->mClientBufferIntegrationInitialized)
+ return true;
+
+ // We can do software-rendered decorations, only disable them if the integration explicitly says it can't.
+ static bool integrationSupport = !clientBufferIntegration() || clientBufferIntegration()->supportsWindowDecoration();
return integrationSupport;
}
@@ -505,6 +933,9 @@ void QWaylandDisplay::handleWindowDeactivated(QWaylandWindow *window)
mActiveWindows.removeOne(window);
+ if (QCoreApplication::closingDown())
+ return;
+
if (auto *decoration = window->decoration())
decoration->update();
}
@@ -516,14 +947,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
if (mLastKeyboardFocus == keyboardFocus)
return;
- if (mWaylandIntegration->mShellIntegration) {
- mWaylandIntegration->mShellIntegration->handleKeyboardFocusChanged(keyboardFocus, mLastKeyboardFocus);
- } else {
- if (keyboardFocus)
- handleWindowActivated(keyboardFocus);
- if (mLastKeyboardFocus)
- handleWindowDeactivated(mLastKeyboardFocus);
- }
+ if (keyboardFocus)
+ handleWindowActivated(keyboardFocus);
+ if (mLastKeyboardFocus)
+ handleWindowDeactivated(mLastKeyboardFocus);
mLastKeyboardFocus = keyboardFocus;
}
@@ -541,7 +968,20 @@ void QWaylandDisplay::handleWaylandSync()
// handleWindowActivated() calls immediately.
QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
if (activeWindow != QGuiApplication::focusWindow())
- QWindowSystemInterface::handleWindowActivated(activeWindow);
+ QWindowSystemInterface::handleFocusWindowChanged(activeWindow);
+
+ if (!activeWindow) {
+ if (lastInputDevice()) {
+#if QT_CONFIG(clipboard)
+ if (auto *dataDevice = lastInputDevice()->dataDevice())
+ dataDevice->invalidateSelectionOffer();
+#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+ if (auto *device = lastInputDevice()->primarySelectionDevice())
+ device->invalidateSelectionOffer();
+#endif
+ }
+ }
}
const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
@@ -565,7 +1005,18 @@ void QWaylandDisplay::requestWaylandSync()
QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
{
- return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
+ return mInputDevices.isEmpty() ? nullptr : mInputDevices.first();
+}
+
+bool QWaylandDisplay::isKeyboardAvailable() const
+{
+ return std::any_of(
+ mInputDevices.constBegin(), mInputDevices.constEnd(),
+ [](const QWaylandInputDevice *device) { return device->keyboard() != nullptr; });
+}
+
+bool QWaylandDisplay::isWaylandInputContextRequested() const {
+ return mWaylandInputContextRequested;
}
#if QT_CONFIG(cursor)
@@ -573,19 +1024,34 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
QWaylandCursor *QWaylandDisplay::waylandCursor()
{
if (!mCursor)
- mCursor.reset(new QWaylandCursor(this));
+ mCursor.reset(mWaylandIntegration->createPlatformCursor(this));
return mCursor.data();
}
+auto QWaylandDisplay::findExistingCursorTheme(const QString &name, int pixelSize) const noexcept
+ -> FindExistingCursorThemeResult
+{
+ const auto byNameAndSize = [](const WaylandCursorTheme &lhs, const WaylandCursorTheme &rhs) {
+ return std::tie(lhs.pixelSize, lhs.name) < std::tie(rhs.pixelSize, rhs.name);
+ };
+
+ const WaylandCursorTheme prototype = {name, pixelSize, nullptr};
+
+ const auto it = std::lower_bound(mCursorThemes.cbegin(), mCursorThemes.cend(), prototype, byNameAndSize);
+ if (it != mCursorThemes.cend() && it->name == name && it->pixelSize == pixelSize)
+ return {it, true};
+ else
+ return {it, false};
+}
+
QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int pixelSize)
{
- if (auto *theme = mCursorThemes.value({name, pixelSize}, nullptr))
- return theme;
+ const auto result = findExistingCursorTheme(name, pixelSize);
+ if (result.found)
+ return result.theme();
- if (auto *theme = QWaylandCursorTheme::create(shm(), pixelSize, name)) {
- mCursorThemes[{name, pixelSize}] = theme;
- return theme;
- }
+ if (auto theme = QWaylandCursorTheme::create(shm(), pixelSize, name))
+ return mCursorThemes.insert(result.position, {name, pixelSize, std::move(theme)})->theme.get();
return nullptr;
}
@@ -595,3 +1061,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
} // namespace QtWaylandClient
QT_END_NAMESPACE
+
+#include "qwaylanddisplay.moc"
+#include "moc_qwaylanddisplay_p.cpp"
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 14bb77198..b93a2ecc0 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDISPLAY_H
#define QWAYLANDDISPLAY_H
@@ -51,10 +15,12 @@
// We mean it.
//
+#include <QtCore/QList>
#include <QtCore/QObject>
-#include <QtCore/QRect>
#include <QtCore/QPointer>
-#include <QtCore/QVector>
+#include <QtCore/QRect>
+#include <QtCore/QMutex>
+#include <QtCore/QReadWriteLock>
#include <QtCore/QWaitCondition>
#include <QtCore/QLoggingCategory>
@@ -66,36 +32,50 @@
#include <qpa/qplatforminputcontextfactory_p.h>
#if QT_CONFIG(xkbcommon)
-#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
+#include <QtGui/private/qxkbcommon_p.h>
#endif
struct wl_cursor_image;
+struct wp_viewport;
QT_BEGIN_NAMESPACE
+#define WAYLAND_IM_KEY "wayland"
+
class QAbstractEventDispatcher;
class QSocketNotifier;
class QPlatformScreen;
+class QPlatformPlaceholderScreen;
namespace QtWayland {
- class qt_surface_extension;
+ class zwp_text_input_manager_v1;
class zwp_text_input_manager_v2;
- class zxdg_output_manager_v1;
+ class zwp_text_input_manager_v3;
+ class qt_text_input_method_manager_v1;
+ class wp_cursor_shape_manager_v1;
+ class wp_fractional_scale_manager_v1;
+ class wp_viewporter;
+ class xdg_toplevel_drag_manager_v1;
}
namespace QtWaylandClient {
-Q_WAYLAND_CLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland);
+Q_WAYLANDCLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland);
class QWaylandInputDevice;
class QWaylandBuffer;
class QWaylandScreen;
+class QWaylandXdgOutputManagerV1;
class QWaylandClientBufferIntegration;
class QWaylandWindowManagerIntegration;
class QWaylandDataDeviceManager;
#if QT_CONFIG(wayland_client_primary_selection)
class QWaylandPrimarySelectionDeviceManagerV1;
#endif
+#if QT_CONFIG(tabletevent)
+class QWaylandTabletManagerV2;
+#endif
+class QWaylandPointerGestures;
class QWaylandTouchExtension;
class QWaylandQtKeyExtension;
class QWaylandWindow;
@@ -105,6 +85,7 @@ class QWaylandSurface;
class QWaylandShellIntegration;
class QWaylandCursor;
class QWaylandCursorTheme;
+class EventThread;
typedef void (*RegistryListener)(void *data,
struct wl_registry *registry,
@@ -112,18 +93,22 @@ typedef void (*RegistryListener)(void *data,
const QString &interface,
uint32_t version);
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
+class Q_WAYLANDCLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
Q_OBJECT
public:
QWaylandDisplay(QWaylandIntegration *waylandIntegration);
~QWaylandDisplay(void) override;
+ bool initialize();
+
#if QT_CONFIG(xkbcommon)
struct xkb_context *xkbContext() const { return mXkbContext.get(); }
#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);
@@ -131,6 +116,7 @@ public:
struct wl_surface *createSurface(void *handle);
struct ::wl_region *createRegion(const QRegion &qregion);
struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
+ struct ::wp_viewport *createViewport(QWaylandWindow *window);
QWaylandShellIntegration *shellIntegration() const;
QWaylandClientBufferIntegration *clientBufferIntegration() const;
@@ -140,29 +126,87 @@ public:
QWaylandCursor *waylandCursor();
QWaylandCursorTheme *loadCursorTheme(const QString &name, int pixelSize);
#endif
- struct wl_display *wl_display() const { return mDisplay; }
+ struct wl_display *wl_display() const
+ {
+ return mDisplay;
+ }
struct ::wl_registry *wl_registry() { return object(); }
- const struct wl_compositor *wl_compositor() const { return mCompositor.object(); }
- QtWayland::wl_compositor *compositor() { return &mCompositor; }
- int compositorVersion() const { return mCompositorVersion; }
+ QtWayland::wl_compositor *compositor()
+ {
+ return mGlobals.compositor.get();
+ }
QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
QWaylandInputDevice *defaultInputDevice() const;
QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
#if QT_CONFIG(wayland_datadevice)
- QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); }
+ QWaylandDataDeviceManager *dndSelectionHandler() const
+ {
+ return mGlobals.dndSelectionHandler.get();
+ }
#endif
#if QT_CONFIG(wayland_client_primary_selection)
- QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
+ QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const
+ {
+ return mGlobals.primarySelectionManager.get();
+ }
#endif
- QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
- QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
- QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
- QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
- QtWayland::zxdg_output_manager_v1 *xdgOutputManager() const { return mXdgOutputManager.data(); }
+#if QT_CONFIG(tabletevent)
+ QWaylandTabletManagerV2 *tabletManager() const
+ {
+ return mGlobals.tabletManager.get();
+ }
+#endif
+ QWaylandPointerGestures *pointerGestures() const
+ {
+ return mGlobals.pointerGestures.get();
+ }
+ QWaylandTouchExtension *touchExtension() const
+ {
+ return mGlobals.touchExtension.get();
+ }
+ QtWayland::qt_text_input_method_manager_v1 *textInputMethodManager() const
+ {
+ return mGlobals.textInputMethodManager.get();
+ }
+ QtWayland::zwp_text_input_manager_v1 *textInputManagerv1() const
+ {
+ return mGlobals.textInputManagerv1.get();
+ }
+ QtWayland::zwp_text_input_manager_v2 *textInputManagerv2() const
+ {
+ return mGlobals.textInputManagerv2.get();
+ }
+ QtWayland::zwp_text_input_manager_v3 *textInputManagerv3() const
+ {
+ return mGlobals.textInputManagerv3.get();
+ }
+ QWaylandHardwareIntegration *hardwareIntegration() const
+ {
+ return mGlobals.hardwareIntegration.get();
+ }
+ QWaylandXdgOutputManagerV1 *xdgOutputManager() const
+ {
+ return mGlobals.xdgOutputManager.get();
+ }
+ QtWayland::wp_fractional_scale_manager_v1 *fractionalScaleManager() const
+ {
+ return mGlobals.fractionalScaleManager.get();
+ }
+ QtWayland::wp_viewporter *viewporter() const
+ {
+ return mGlobals.viewporter.get();
+ }
+ QtWayland::wp_cursor_shape_manager_v1 *cursorShapeManager() const
+ {
+ return mGlobals.cursorShapeManager.get();
+ }
+ QtWayland::xdg_toplevel_drag_manager_v1 *xdgToplevelDragManager() const
+ {
+ return mGlobals.xdgToplevelDragManager.get();
+ }
- bool usingInputContextFromCompositor() const { return mUsingInputContextFromCompositor; }
struct RegistryGlobal {
uint32_t id;
@@ -172,7 +216,10 @@ public:
RegistryGlobal(uint32_t id_, const QString &interface_, uint32_t version_, struct ::wl_registry *registry_)
: id(id_), interface(interface_), version(version_), registry(registry_) { }
};
- QList<RegistryGlobal> globals() const { return mGlobals; }
+ QList<RegistryGlobal> globals() const
+ {
+ return mRegistryGlobals;
+ }
bool hasRegistryGlobal(QStringView interfaceName) const;
/* wl_registry_add_listener does not add but rather sets a listener, so this function is used
@@ -180,9 +227,10 @@ public:
void addRegistryListener(RegistryListener listener, void *data);
void removeListener(RegistryListener listener, void *data);
- QWaylandShm *shm() const { return mShm.data(); }
-
- static uint32_t currentTimeMillisec();
+ QWaylandShm *shm() const
+ {
+ return mGlobals.shm.get();
+ }
void forceRoundTrip();
@@ -199,20 +247,31 @@ public:
void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
void handleWindowDestroyed(QWaylandWindow *window);
- wl_event_queue *createEventQueue();
- void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
+ wl_event_queue *frameEventQueue() { return m_frameEventQueue; };
+
+ bool isKeyboardAvailable() const;
+ bool isWaylandInputContextRequested() const;
-public slots:
+ void initEventThread();
+
+public Q_SLOTS:
void blockingReadEvents();
void flushRequests();
-private:
- void waitForScreens();
- void checkError() const;
+Q_SIGNALS:
+ void connected();
+ void globalAdded(const RegistryGlobal &global);
+ void globalRemoved(const RegistryGlobal &global);
+private:
+ void checkWaylandError();
+ void reconnect();
+ void setupConnection();
void handleWaylandSync();
void requestWaylandSync();
+ void checkTextInputProtocol();
+
struct Listener {
Listener() = default;
Listener(RegistryListener incomingListener,
@@ -222,48 +281,83 @@ private:
RegistryListener listener = nullptr;
void *data = nullptr;
};
-
struct wl_display *mDisplay = nullptr;
- QtWayland::wl_compositor mCompositor;
- QScopedPointer<QWaylandShm> mShm;
+ std::unique_ptr<EventThread> m_eventThread;
+ wl_event_queue *m_frameEventQueue = nullptr;
+ QScopedPointer<EventThread> m_frameEventQueueThread;
QList<QWaylandScreen *> mWaitingScreens;
QList<QWaylandScreen *> mScreens;
+ QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
QList<QWaylandInputDevice *> mInputDevices;
QList<Listener> mRegistryListeners;
QWaylandIntegration *mWaylandIntegration = nullptr;
#if QT_CONFIG(cursor)
- QMap<std::pair<QString, int>, QWaylandCursorTheme *> mCursorThemes; // theme name and size
+ struct WaylandCursorTheme {
+ QString name;
+ int pixelSize;
+ std::unique_ptr<QWaylandCursorTheme> theme;
+ };
+ std::vector<WaylandCursorTheme> mCursorThemes;
+
+ struct FindExistingCursorThemeResult {
+ std::vector<WaylandCursorTheme>::const_iterator position;
+ bool found;
+
+ QWaylandCursorTheme *theme() const noexcept
+ { return found ? position->theme.get() : nullptr; }
+ };
+ FindExistingCursorThemeResult findExistingCursorTheme(const QString &name,
+ int pixelSize) const noexcept;
QScopedPointer<QWaylandCursor> mCursor;
#endif
+
+ struct GlobalHolder
+ {
+ std::unique_ptr<QtWayland::wl_compositor> compositor;
+ std::unique_ptr<QWaylandShm> shm;
#if QT_CONFIG(wayland_datadevice)
- QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler;
+ std::unique_ptr<QWaylandDataDeviceManager> dndSelectionHandler;
#endif
- QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension;
- QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor;
- QScopedPointer<QWaylandTouchExtension> mTouchExtension;
- QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
- QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
+ std::unique_ptr<QtWayland::wl_subcompositor> subCompositor;
+ std::unique_ptr<QWaylandTouchExtension> touchExtension;
+ std::unique_ptr<QWaylandQtKeyExtension> qtKeyExtension;
+#if QT_CONFIG(tabletevent)
+ std::unique_ptr<QWaylandTabletManagerV2> tabletManager;
+#endif
+ std::unique_ptr<QWaylandPointerGestures> pointerGestures;
#if QT_CONFIG(wayland_client_primary_selection)
- QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
+ std::unique_ptr<QWaylandPrimarySelectionDeviceManagerV1> primarySelectionManager;
#endif
- QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManager;
- QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
- QScopedPointer<QtWayland::zxdg_output_manager_v1> mXdgOutputManager;
- QSocketNotifier *mReadNotifier = nullptr;
+ std::unique_ptr<QtWayland::qt_text_input_method_manager_v1> textInputMethodManager;
+ std::unique_ptr<QtWayland::zwp_text_input_manager_v1> textInputManagerv1;
+ std::unique_ptr<QtWayland::zwp_text_input_manager_v2> textInputManagerv2;
+ std::unique_ptr<QtWayland::zwp_text_input_manager_v3> textInputManagerv3;
+ std::unique_ptr<QWaylandHardwareIntegration> hardwareIntegration;
+ std::unique_ptr<QWaylandXdgOutputManagerV1> xdgOutputManager;
+ std::unique_ptr<QtWayland::wp_viewporter> viewporter;
+ std::unique_ptr<QtWayland::wp_fractional_scale_manager_v1> fractionalScaleManager;
+ std::unique_ptr<QtWayland::wp_cursor_shape_manager_v1> cursorShapeManager;
+ std::unique_ptr<QtWayland::xdg_toplevel_drag_manager_v1> xdgToplevelDragManager;
+ std::unique_ptr<QWaylandWindowManagerIntegration> windowManagerIntegration;
+ } mGlobals;
int mFd = -1;
int mWritableNotificationFd = -1;
- QList<RegistryGlobal> mGlobals;
- int mCompositorVersion = -1;
+ QList<RegistryGlobal> mRegistryGlobals;
uint32_t mLastInputSerial = 0;
QWaylandInputDevice *mLastInputDevice = nullptr;
QPointer<QWaylandWindow> mLastInputWindow;
QPointer<QWaylandWindow> mLastKeyboardFocus;
- QVector<QWaylandWindow *> mActiveWindows;
+ QList<QWaylandWindow *> mActiveWindows;
struct wl_callback *mSyncCallback = nullptr;
static const wl_callback_listener syncCallbackListener;
-
- bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
- bool mUsingInputContextFromCompositor = false;
+ bool mWaylandTryReconnect = false;
+
+ bool mWaylandInputContextRequested = [] () {
+ const auto requested = QPlatformInputContextFactory::requested();
+ return requested.isEmpty() || requested.contains(QLatin1String(WAYLAND_IM_KEY));
+ }();
+ QStringList mTextInputManagerList;
+ int mTextInputManagerIndex = INT_MAX;
void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
void registry_global_remove(uint32_t id) override;
diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp
index 6535aa16b..5ea1e0d33 100644
--- a/src/client/qwaylanddnd.cpp
+++ b/src/client/qwaylanddnd.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylanddnd_p.h"
@@ -66,7 +30,7 @@ void QWaylandDrag::startDrag()
{
QBasicDrag::startDrag();
QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
- if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) {
+ if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), drag()->supportedActions(), icon)) {
icon->addAttachOffset(-drag()->hotSpot());
} else {
// Cancelling immediately does not work, since the event loop for QDrag::exec is started
@@ -80,6 +44,9 @@ void QWaylandDrag::cancel()
QBasicDrag::cancel();
m_display->currentInputDevice()->dataDevice()->cancelDrag();
+
+ if (drag())
+ drag()->deleteLater();
}
void QWaylandDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
@@ -92,10 +59,7 @@ void QWaylandDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::Keyboar
void QWaylandDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
- Q_UNUSED(globalPos);
- Q_UNUSED(b);
- Q_UNUSED(mods);
- // Do nothing
+ QBasicDrag::drop(globalPos, b, mods);
}
void QWaylandDrag::endDrag()
@@ -103,33 +67,41 @@ void QWaylandDrag::endDrag()
m_display->currentInputDevice()->handleEndDrag();
}
-void QWaylandDrag::updateTarget(const QString &mimeType)
+void QWaylandDrag::setResponse(bool accepted)
{
- setCanDrop(!mimeType.isEmpty());
-
- if (canDrop()) {
- updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
- } else {
- updateCursor(Qt::IgnoreAction);
- }
+ // This method is used for old DataDevices where the drag action is not communicated
+ Qt::DropAction action = defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers());
+ setResponse(QPlatformDropQtResponse(accepted, action));
}
-void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response)
+void QWaylandDrag::setResponse(const QPlatformDropQtResponse &response)
{
setCanDrop(response.isAccepted());
if (canDrop()) {
- updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
+ updateCursor(response.acceptedAction());
} else {
updateCursor(Qt::IgnoreAction);
}
}
-void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response)
+void QWaylandDrag::setDropResponse(const QPlatformDropQtResponse &response)
{
setExecutedDropAction(response.acceptedAction());
+}
+
+void QWaylandDrag::finishDrag()
+{
QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
eventFilter(shapedPixmapWindow(), &event);
+
+ if (drag())
+ drag()->deleteLater();
+}
+
+bool QWaylandDrag::ownsDragObject() const
+{
+ return true;
}
}
diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h
index 474fe2ab1..4952c6d3d 100644
--- a/src/client/qwaylanddnd_p.h
+++ b/src/client/qwaylanddnd_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDDND_H
#define QWAYLANDDND_H
@@ -65,15 +29,16 @@ namespace QtWaylandClient {
class QWaylandDisplay;
#if QT_CONFIG(draganddrop)
-class Q_WAYLAND_CLIENT_EXPORT QWaylandDrag : public QBasicDrag
+class Q_WAYLANDCLIENT_EXPORT QWaylandDrag : public QBasicDrag
{
public:
QWaylandDrag(QWaylandDisplay *display);
~QWaylandDrag() override;
- void updateTarget(const QString &mimeType);
- void setResponse(const QPlatformDragQtResponse &response);
- void finishDrag(const QPlatformDropQtResponse &response);
+ void setResponse(bool accepted);
+ void setResponse(const QPlatformDropQtResponse &response);
+ void setDropResponse(const QPlatformDropQtResponse &response);
+ void finishDrag();
protected:
void startDrag() override;
@@ -82,6 +47,7 @@ protected:
void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
void endDrag() override;
+ bool ownsDragObject() const override;
private:
QWaylandDisplay *m_display = nullptr;
diff --git a/src/client/qwaylandextendedsurface.cpp b/src/client/qwaylandextendedsurface.cpp
deleted file mode 100644
index a7836e292..000000000
--- a/src/client/qwaylandextendedsurface.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 "qwaylandextendedsurface_p.h"
-
-#include "qwaylandwindow_p.h"
-
-#include "qwaylanddisplay_p.h"
-
-#include "qwaylandnativeinterface_p.h"
-
-#include <QtGui/QGuiApplication>
-#include <qpa/qplatformnativeinterface.h>
-#include <qpa/qwindowsysteminterface.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWaylandClient {
-
-QWaylandExtendedSurface::QWaylandExtendedSurface(QWaylandWindow *window)
- : QtWayland::qt_extended_surface(window->display()->windowExtension()->get_extended_surface(window->wlSurface()))
- , m_window(window)
-{
-}
-
-QWaylandExtendedSurface::~QWaylandExtendedSurface()
-{
- qt_extended_surface_destroy(object());
-}
-
-void QWaylandExtendedSurface::updateGenericProperty(const QString &name, const QVariant &value)
-{
- QByteArray byteValue;
- QDataStream ds(&byteValue, QIODevice::WriteOnly);
- ds << value;
-
- update_generic_property(name, byteValue);
-}
-
-void QWaylandExtendedSurface::setContentOrientationMask(Qt::ScreenOrientations mask)
-{
- int32_t wlmask = 0;
- if (mask & Qt::PrimaryOrientation)
- wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION;
- if (mask & Qt::PortraitOrientation)
- wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION;
- if (mask & Qt::LandscapeOrientation)
- wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION;
- if (mask & Qt::InvertedPortraitOrientation)
- wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION;
- if (mask & Qt::InvertedLandscapeOrientation)
- wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION;
- set_content_orientation_mask(wlmask);
-}
-
-void QWaylandExtendedSurface::extended_surface_onscreen_visibility(int32_t visibility)
-{
- m_window->window()->setVisibility(static_cast<QWindow::Visibility>(visibility));
-}
-
-void QWaylandExtendedSurface::extended_surface_set_generic_property(const QString &name, wl_array *value)
-{
- QByteArray data = QByteArray::fromRawData(static_cast<char *>(value->data), value->size);
-
- QVariant variantValue;
- QDataStream ds(data);
- ds >> variantValue;
-
- m_window->setProperty(name, variantValue);
-}
-
-void QWaylandExtendedSurface::extended_surface_close()
-{
- QWindowSystemInterface::handleCloseEvent(m_window->window());
-}
-
-Qt::WindowFlags QWaylandExtendedSurface::setWindowFlags(Qt::WindowFlags flags)
-{
- uint wlFlags = 0;
-
- if (flags & Qt::WindowStaysOnTopHint) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP;
- if (flags & Qt::WindowOverridesSystemGestures) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES;
- if (flags & Qt::BypassWindowManagerHint) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER;
-
- set_window_flags(wlFlags);
-
- return flags & (Qt::WindowStaysOnTopHint | Qt::WindowOverridesSystemGestures | Qt::BypassWindowManagerHint);
-}
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/client/qwaylandextendedsurface_p.h b/src/client/qwaylandextendedsurface_p.h
deleted file mode 100644
index d71ac6be9..000000000
--- a/src/client/qwaylandextendedsurface_p.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 QWAYLANDEXTENDEDSURFACE_H
-#define QWAYLANDEXTENDEDSURFACE_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/QString>
-#include <QtCore/QVariant>
-
-#include <QtWaylandClient/qtwaylandclientglobal.h>
-
-#include <QtWaylandClient/private/qwayland-surface-extension.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWaylandClient {
-
-class QWaylandDisplay;
-class QWaylandWindow;
-
-class Q_WAYLAND_CLIENT_EXPORT QWaylandExtendedSurface : public QtWayland::qt_extended_surface
-{
-public:
- QWaylandExtendedSurface(QWaylandWindow *window);
- ~QWaylandExtendedSurface() override;
-
- void setContentOrientationMask(Qt::ScreenOrientations mask);
-
- void updateGenericProperty(const QString &name, const QVariant &value);
-
- Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
-
-private:
- void extended_surface_onscreen_visibility(int32_t visibility) override;
- void extended_surface_set_generic_property(const QString &name, wl_array *value) override;
- void extended_surface_close() override;
-
- QWaylandWindow *m_window = nullptr;
- QVariantMap m_properties;
-};
-
-}
-
-QT_END_NAMESPACE
-
-#endif // QWAYLANDEXTENDEDSURFACE_H
diff --git a/src/client/qwaylandfractionalscale.cpp b/src/client/qwaylandfractionalscale.cpp
new file mode 100644
index 000000000..6cd933f47
--- /dev/null
+++ b/src/client/qwaylandfractionalscale.cpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandfractionalscale_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandFractionalScale::QWaylandFractionalScale(struct ::wp_fractional_scale_v1 *object)
+ : QtWayland::wp_fractional_scale_v1(object)
+{}
+
+
+QWaylandFractionalScale::~QWaylandFractionalScale()
+{
+ destroy();
+}
+
+void QWaylandFractionalScale::wp_fractional_scale_v1_preferred_scale(uint scale)
+{
+ qreal preferredScale = scale / 120.0; // hardcoded denominator determined in the spec
+ if (preferredScale != mPreferredScale) {
+ mPreferredScale = preferredScale;
+ Q_EMIT preferredScaleChanged();
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandfractionalscale_p.h b/src/client/qwaylandfractionalscale_p.h
new file mode 100644
index 000000000..48e1fb487
--- /dev/null
+++ b/src/client/qwaylandfractionalscale_p.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDFRACTIONALSCALE_P_H
+#define QWAYLANDFRACTIONALSCALE_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-fractional-scale-v1.h>
+#include <QtWaylandClient/qtwaylandclientglobal.h>
+
+#include <QObject>
+
+#include <optional>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandFractionalScale : public QObject, public QtWayland::wp_fractional_scale_v1
+{
+ Q_OBJECT
+public:
+ explicit QWaylandFractionalScale(struct ::wp_fractional_scale_v1 *object);
+ ~QWaylandFractionalScale();
+
+ std::optional<qreal> preferredScale() const { return mPreferredScale; }
+
+Q_SIGNALS:
+ void preferredScaleChanged();
+
+protected:
+ void wp_fractional_scale_v1_preferred_scale(uint scale) override;
+
+private:
+ std::optional<qreal> mPreferredScale;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
index e9afe05ed..a38bb9a0a 100644
--- a/src/client/qwaylandinputcontext.cpp
+++ b/src/client/qwaylandinputcontext.cpp
@@ -1,393 +1,28 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandClient module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandinputcontext_p.h"
+#include <QLoggingCategory>
#include <QtGui/QGuiApplication>
#include <QtGui/QTextCharFormat>
#include <QtGui/QWindow>
-#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/qpa/qplatformintegration.h>
+#include <QtCore/QVarLengthArray>
#include "qwaylanddisplay_p.h"
#include "qwaylandinputdevice_p.h"
-#include "qwaylandinputmethodeventbuilder_p.h"
#include "qwaylandwindow_p.h"
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(qLcQpaInputMethods, "qt.qpa.input.methods")
-
-namespace QtWaylandClient {
-
-namespace {
-const Qt::InputMethodQueries supportedQueries = Qt::ImEnabled |
- Qt::ImSurroundingText |
- Qt::ImCursorPosition |
- Qt::ImAnchorPosition |
- Qt::ImHints |
- Qt::ImCursorRectangle |
- Qt::ImPreferredLanguage;
-}
-
-QWaylandTextInput::QWaylandTextInput(QWaylandDisplay *display, struct ::zwp_text_input_v2 *text_input)
- : QtWayland::zwp_text_input_v2(text_input)
- , m_display(display)
-{
-}
-
-QWaylandTextInput::~QWaylandTextInput()
-{
- if (m_resetCallback)
- wl_callback_destroy(m_resetCallback);
-}
-
-void QWaylandTextInput::reset()
-{
- m_builder.reset();
- m_preeditCommit = QString();
- updateState(Qt::ImQueryAll, update_state_reset);
-}
-
-void QWaylandTextInput::commit()
-{
- if (QObject *o = QGuiApplication::focusObject()) {
- QInputMethodEvent event;
- event.setCommitString(m_preeditCommit);
- QCoreApplication::sendEvent(o, &event);
- }
-
- reset();
-}
-
-const wl_callback_listener QWaylandTextInput::callbackListener = {
- QWaylandTextInput::resetCallback
-};
-
-void QWaylandTextInput::resetCallback(void *data, wl_callback *, uint32_t)
-{
- QWaylandTextInput *self = static_cast<QWaylandTextInput*>(data);
-
- if (self->m_resetCallback) {
- wl_callback_destroy(self->m_resetCallback);
- self->m_resetCallback = nullptr;
- }
-}
-
-void QWaylandTextInput::updateState(Qt::InputMethodQueries queries, uint32_t flags)
-{
- if (!QGuiApplication::focusObject())
- return;
-
- if (!QGuiApplication::focusWindow() || !QGuiApplication::focusWindow()->handle())
- return;
-
- auto *window = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle());
- auto *surface = window->wlSurface();
- if (!surface || (surface != m_surface))
- return;
-
- queries &= supportedQueries;
-
- // Surrounding text, cursor and anchor positions are transferred together
- if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition))
- queries |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
-
- QInputMethodQueryEvent event(queries);
- QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
-
- if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition)) {
- QString text = event.value(Qt::ImSurroundingText).toString();
- int cursor = event.value(Qt::ImCursorPosition).toInt();
- int anchor = event.value(Qt::ImAnchorPosition).toInt();
-
- // Make sure text is not too big
- if (text.toUtf8().size() > 2048) {
- int c = qAbs(cursor - anchor) <= 512 ? qMin(cursor, anchor) + qAbs(cursor - anchor) / 2: cursor;
-
- const int offset = c - qBound(0, c, 512 - qMin(text.size() - c, 256));
- text = text.mid(offset + c - 256, 512);
- cursor -= offset;
- anchor -= offset;
- }
-
- set_surrounding_text(text, QWaylandInputMethodEventBuilder::indexToWayland(text, cursor), QWaylandInputMethodEventBuilder::indexToWayland(text, anchor));
- }
-
- if (queries & Qt::ImHints) {
- QWaylandInputMethodContentType contentType = QWaylandInputMethodContentType::convert(static_cast<Qt::InputMethodHints>(event.value(Qt::ImHints).toInt()));
- set_content_type(contentType.hint, contentType.purpose);
- }
-
- if (queries & Qt::ImCursorRectangle) {
- const QRect &cRect = event.value(Qt::ImCursorRectangle).toRect();
- const QRect &windowRect = QGuiApplication::inputMethod()->inputItemTransform().mapRect(cRect);
- const QMargins margins = window->frameMargins();
- const QRect &surfaceRect = windowRect.translated(margins.left(), margins.top());
- set_cursor_rectangle(surfaceRect.x(), surfaceRect.y(), surfaceRect.width(), surfaceRect.height());
- }
-
- if (queries & Qt::ImPreferredLanguage) {
- const QString &language = event.value(Qt::ImPreferredLanguage).toString();
- set_preferred_language(language);
- }
-
- update_state(m_serial, flags);
- if (flags != update_state_change) {
- if (m_resetCallback)
- wl_callback_destroy(m_resetCallback);
- m_resetCallback = wl_display_sync(m_display->wl_display());
- wl_callback_add_listener(m_resetCallback, &QWaylandTextInput::callbackListener, this);
- }
-}
-
-void QWaylandTextInput::setCursorInsidePreedit(int)
-{
- // Not supported yet
-}
-
-bool QWaylandTextInput::isInputPanelVisible() const
-{
- return m_inputPanelVisible;
-}
-
-QRectF QWaylandTextInput::keyboardRect() const
-{
- return m_keyboardRectangle;
-}
-
-QLocale QWaylandTextInput::locale() const
-{
- return m_locale;
-}
-
-Qt::LayoutDirection QWaylandTextInput::inputDirection() const
-{
- return m_inputDirection;
-}
-
-void QWaylandTextInput::zwp_text_input_v2_enter(uint32_t serial, ::wl_surface *surface)
-{
- m_serial = serial;
- m_surface = surface;
-
- updateState(Qt::ImQueryAll, update_state_enter);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_leave(uint32_t serial, ::wl_surface *surface)
-{
- m_serial = serial;
-
- if (m_surface != surface) {
- qCDebug(qLcQpaInputMethods()) << Q_FUNC_INFO << "Got leave event for surface" << surface << "focused surface" << m_surface;
- }
-
- m_surface = nullptr;
-}
-
-void QWaylandTextInput::zwp_text_input_v2_modifiers_map(wl_array *map)
-{
- const QList<QByteArray> modifiersMap = QByteArray::fromRawData(static_cast<const char*>(map->data), map->size).split('\0');
-
- m_modifiersMap.clear();
-
- for (const QByteArray &modifier : modifiersMap) {
- if (modifier == "Shift")
- m_modifiersMap.append(Qt::ShiftModifier);
- else if (modifier == "Control")
- m_modifiersMap.append(Qt::ControlModifier);
- else if (modifier == "Alt")
- m_modifiersMap.append(Qt::AltModifier);
- else if (modifier == "Mod1")
- m_modifiersMap.append(Qt::AltModifier);
- else if (modifier == "Mod4")
- m_modifiersMap.append(Qt::MetaModifier);
- else
- m_modifiersMap.append(Qt::NoModifier);
- }
-}
-
-void QWaylandTextInput::zwp_text_input_v2_input_panel_state(uint32_t visible, int32_t x, int32_t y, int32_t width, int32_t height)
-{
- const bool inputPanelVisible = (visible == input_panel_visibility_visible);
- if (m_inputPanelVisible != inputPanelVisible) {
- m_inputPanelVisible = inputPanelVisible;
- QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
- }
- const QRectF keyboardRectangle(x, y, width, height);
- if (m_keyboardRectangle != keyboardRectangle) {
- m_keyboardRectangle = keyboardRectangle;
- QGuiApplicationPrivate::platformIntegration()->inputContext()->emitKeyboardRectChanged();
- }
-}
-
-void QWaylandTextInput::zwp_text_input_v2_preedit_string(const QString &text, const QString &commit)
-{
- if (m_resetCallback) {
- qCDebug(qLcQpaInputMethods()) << "discard preedit_string: reset not confirmed";
- m_builder.reset();
- return;
- }
-
- if (!QGuiApplication::focusObject())
- return;
-
- QInputMethodEvent event = m_builder.buildPreedit(text);
-
- m_builder.reset();
- m_preeditCommit = commit;
-
- QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_preedit_styling(uint32_t index, uint32_t length, uint32_t style)
-{
- m_builder.addPreeditStyling(index, length, style);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_preedit_cursor(int32_t index)
-{
- m_builder.setPreeditCursor(index);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_commit_string(const QString &text)
-{
- if (m_resetCallback) {
- qCDebug(qLcQpaInputMethods()) << "discard commit_string: reset not confirmed";
- m_builder.reset();
- return;
- }
-
- if (!QGuiApplication::focusObject())
- return;
-
- QInputMethodEvent event = m_builder.buildCommit(text);
-
- m_builder.reset();
-
- QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor)
-{
- m_builder.setCursorPosition(index, anchor);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length)
-{
- m_builder.setDeleteSurroundingText(before_length, after_length);
-}
-
-void QWaylandTextInput::zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
-{
#if QT_CONFIG(xkbcommon)
- if (m_resetCallback) {
- qCDebug(qLcQpaInputMethods()) << "discard keysym: reset not confirmed";
- return;
- }
-
- if (!QGuiApplication::focusWindow())
- return;
-
- Qt::KeyboardModifiers qtModifiers = modifiersToQtModifiers(modifiers);
-
- QEvent::Type type = state == WL_KEYBOARD_KEY_STATE_PRESSED ? QEvent::KeyPress : QEvent::KeyRelease;
- QString text = QXkbCommon::lookupStringNoKeysymTransformations(sym);
- int qtkey = QXkbCommon::keysymToQtKey(sym, qtModifiers);
-
- QWindowSystemInterface::handleKeyEvent(QGuiApplication::focusWindow(),
- time, type, qtkey, qtModifiers, text);
-#else
- Q_UNUSED(time);
- Q_UNUSED(sym);
- Q_UNUSED(state);
- Q_UNUSED(modifiers);
+#include <locale.h>
#endif
-}
-
-void QWaylandTextInput::zwp_text_input_v2_language(const QString &language)
-{
- if (m_resetCallback) {
- qCDebug(qLcQpaInputMethods()) << "discard language: reset not confirmed";
- return;
- }
-
- const QLocale locale(language);
- if (m_locale != locale) {
- m_locale = locale;
- QGuiApplicationPrivate::platformIntegration()->inputContext()->emitLocaleChanged();
- }
-}
-
-void QWaylandTextInput::zwp_text_input_v2_text_direction(uint32_t direction)
-{
- if (m_resetCallback) {
- qCDebug(qLcQpaInputMethods()) << "discard text_direction: reset not confirmed";
- return;
- }
-
- const Qt::LayoutDirection inputDirection = (direction == text_direction_auto) ? Qt::LayoutDirectionAuto :
- (direction == text_direction_ltr) ? Qt::LeftToRight :
- (direction == text_direction_rtl) ? Qt::RightToLeft : Qt::LayoutDirectionAuto;
- if (m_inputDirection != inputDirection) {
- m_inputDirection = inputDirection;
- QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputDirectionChanged(m_inputDirection);
- }
-}
-void QWaylandTextInput::zwp_text_input_v2_input_method_changed(uint32_t serial, uint32_t flags)
-{
- Q_UNUSED(flags);
+QT_BEGIN_NAMESPACE
- m_serial = serial;
- updateState(Qt::ImQueryAll, update_state_full);
-}
+Q_LOGGING_CATEGORY(qLcQpaInputMethods, "qt.qpa.input.methods")
-Qt::KeyboardModifiers QWaylandTextInput::modifiersToQtModifiers(uint32_t modifiers)
-{
- Qt::KeyboardModifiers ret = Qt::NoModifier;
- for (int i = 0; modifiers >>= 1; ++i) {
- ret |= m_modifiersMap[i];
- }
- return ret;
-}
+namespace QtWaylandClient {
QWaylandInputContext::QWaylandInputContext(QWaylandDisplay *display)
: mDisplay(display)
@@ -400,29 +35,35 @@ QWaylandInputContext::~QWaylandInputContext()
bool QWaylandInputContext::isValid() const
{
- return mDisplay->textInputManager() != nullptr;
+ return mDisplay->textInputManagerv2() != nullptr || mDisplay->textInputManagerv1() != nullptr || mDisplay->textInputManagerv3() != nullptr;
}
void QWaylandInputContext::reset()
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
+#if QT_CONFIG(xkbcommon)
+ if (m_composeState)
+ xkb_compose_state_reset(m_composeState);
+#endif
QPlatformInputContext::reset();
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return;
- textInput()->reset();
+ inputInterface->reset();
}
void QWaylandInputContext::commit()
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return;
- textInput()->commit();
+ inputInterface->commit();
}
static ::wl_surface *surfaceForWindow(QWindow *window)
@@ -438,99 +79,113 @@ void QWaylandInputContext::update(Qt::InputMethodQueries queries)
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries;
- if (!QGuiApplication::focusObject() || !textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!QGuiApplication::focusObject() || !inputInterface)
return;
auto *currentSurface = surfaceForWindow(mCurrentWindow);
if (currentSurface && !inputMethodAccepted()) {
- textInput()->disable(currentSurface);
+ inputInterface->disableSurface(currentSurface);
mCurrentWindow.clear();
} else if (!currentSurface && inputMethodAccepted()) {
QWindow *window = QGuiApplication::focusWindow();
if (auto *focusSurface = surfaceForWindow(window)) {
- textInput()->enable(focusSurface);
+ inputInterface->enableSurface(focusSurface);
mCurrentWindow = window;
}
}
- textInput()->updateState(queries, QtWayland::zwp_text_input_v2::update_state_change);
+ inputInterface->updateState(queries, QWaylandTextInputInterface::update_state_change);
}
void QWaylandInputContext::invokeAction(QInputMethod::Action action, int cursorPostion)
{
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return;
if (action == QInputMethod::Click)
- textInput()->setCursorInsidePreedit(cursorPostion);
+ inputInterface->setCursorInsidePreedit(cursorPostion);
}
void QWaylandInputContext::showInputPanel()
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return;
- textInput()->show_input_panel();
+ inputInterface->showInputPanel();
}
void QWaylandInputContext::hideInputPanel()
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return;
- textInput()->hide_input_panel();
+ inputInterface->hideInputPanel();
}
bool QWaylandInputContext::isInputPanelVisible() const
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return QPlatformInputContext::isInputPanelVisible();
- return textInput()->isInputPanelVisible();
+ return inputInterface->isInputPanelVisible();
}
QRectF QWaylandInputContext::keyboardRect() const
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return QPlatformInputContext::keyboardRect();
- return textInput()->keyboardRect();
+ return inputInterface->keyboardRect();
}
QLocale QWaylandInputContext::locale() const
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return QPlatformInputContext::locale();
- return textInput()->locale();
+ return inputInterface->locale();
}
Qt::LayoutDirection QWaylandInputContext::inputDirection() const
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return QPlatformInputContext::inputDirection();
- return textInput()->inputDirection();
+ return inputInterface->inputDirection();
}
-void QWaylandInputContext::setFocusObject(QObject *)
+void QWaylandInputContext::setFocusObject(QObject *object)
{
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
+#if QT_CONFIG(xkbcommon)
+ m_focusObject = object;
+#else
+ Q_UNUSED(object);
+#endif
- if (!textInput())
+ QWaylandTextInputInterface *inputInterface = textInput();
+ if (!inputInterface)
return;
QWindow *window = QGuiApplication::focusWindow();
@@ -539,7 +194,7 @@ void QWaylandInputContext::setFocusObject(QObject *)
if (mCurrentWindow.data() != window || !inputMethodAccepted()) {
auto *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->wlSurface();
if (surface)
- textInput()->disable(surface);
+ inputInterface->disableSurface(surface);
mCurrentWindow.clear();
}
}
@@ -548,19 +203,104 @@ void QWaylandInputContext::setFocusObject(QObject *)
if (mCurrentWindow.data() != window) {
auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
if (surface) {
- textInput()->enable(surface);
+ inputInterface->enableSurface(surface);
mCurrentWindow = window;
}
}
- textInput()->updateState(Qt::ImQueryAll, QtWayland::zwp_text_input_v2::update_state_enter);
+ inputInterface->updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_enter);
+ }
+}
+
+QWaylandTextInputInterface *QWaylandInputContext::textInput() const
+{
+ return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
+}
+
+#if QT_CONFIG(xkbcommon)
+
+void QWaylandInputContext::ensureInitialized()
+{
+ if (m_initialized)
+ return;
+
+ if (!m_XkbContext) {
+ qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
+ return;
+ }
+
+ m_initialized = true;
+ const char *const locale = setlocale(LC_CTYPE, nullptr);
+ qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
+
+ m_composeTable = xkb_compose_table_new_from_locale(m_XkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
+ if (m_composeTable)
+ m_composeState = xkb_compose_state_new(m_composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
+
+ if (!m_composeTable) {
+ qCWarning(qLcQpaInputMethods, "failed to create compose table");
+ return;
+ }
+ if (!m_composeState) {
+ qCWarning(qLcQpaInputMethods, "failed to create compose state");
+ return;
}
}
-QWaylandTextInput *QWaylandInputContext::textInput() const
+bool QWaylandInputContext::filterEvent(const QEvent *event)
{
- return mDisplay->defaultInputDevice()->textInput();
+ auto keyEvent = static_cast<const QKeyEvent *>(event);
+ if (keyEvent->type() != QEvent::KeyPress)
+ return false;
+
+ if (!inputMethodAccepted())
+ return false;
+
+ // lazy initialization - we don't want to do this on an app startup
+ ensureInitialized();
+
+ if (!m_composeTable || !m_composeState)
+ return false;
+
+ xkb_compose_state_feed(m_composeState, keyEvent->nativeVirtualKey());
+
+ switch (xkb_compose_state_get_status(m_composeState)) {
+ case XKB_COMPOSE_COMPOSING:
+ return true;
+ case XKB_COMPOSE_CANCELLED:
+ reset();
+ return false;
+ case XKB_COMPOSE_COMPOSED:
+ {
+ const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
+ QVarLengthArray<char, 32> buffer(size + 1);
+ xkb_compose_state_get_utf8(m_composeState, buffer.data(), buffer.size());
+ QString composedText = QString::fromUtf8(buffer.constData());
+
+ QInputMethodEvent event;
+ event.setCommitString(composedText);
+
+ if (!m_focusObject && qApp)
+ m_focusObject = qApp->focusObject();
+
+ if (m_focusObject)
+ QCoreApplication::sendEvent(m_focusObject, &event);
+ else
+ qCWarning(qLcQpaInputMethods, "no focus object");
+
+ reset();
+ return true;
+ }
+ case XKB_COMPOSE_NOTHING:
+ return false;
+ default:
+ Q_UNREACHABLE_RETURN(false);
+ }
}
+#endif
+
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandinputcontext_p.cpp"
diff --git a/src/client/qwaylandinputcontext_p.h b/src/client/qwaylandinputcontext_p.h
index 10132dfe1..e6ce21d34 100644
--- a/src/client/qwaylandinputcontext_p.h
+++ b/src/client/qwaylandinputcontext_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandClient module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDINPUTCONTEXT_H
@@ -54,82 +18,23 @@
#include <qpa/qplatforminputcontext.h>
-#include <QLoggingCategory>
#include <QPointer>
-#include <QRectF>
-#include <QVector>
-#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
-#include <qwaylandinputmethodeventbuilder_p.h>
+#include "qwaylandtextinputinterface_p.h"
+#include <qtwaylandclientglobal_p.h>
+#if QT_CONFIG(xkbcommon)
+#include <xkbcommon/xkbcommon-compose.h>
+#endif
struct wl_callback;
struct wl_callback_listener;
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(qLcQpaInputMethods)
-
namespace QtWaylandClient {
class QWaylandDisplay;
-class QWaylandTextInput : public QtWayland::zwp_text_input_v2
-{
-public:
- QWaylandTextInput(QWaylandDisplay *display, struct ::zwp_text_input_v2 *text_input);
- ~QWaylandTextInput() override;
-
- void reset();
- void commit();
- void updateState(Qt::InputMethodQueries queries, uint32_t flags);
-
- void setCursorInsidePreedit(int cursor);
-
- bool isInputPanelVisible() const;
- QRectF keyboardRect() const;
-
- QLocale locale() const;
- Qt::LayoutDirection inputDirection() const;
-
-protected:
- void zwp_text_input_v2_enter(uint32_t serial, struct ::wl_surface *surface) override;
- void zwp_text_input_v2_leave(uint32_t serial, struct ::wl_surface *surface) override;
- void zwp_text_input_v2_modifiers_map(wl_array *map) override;
- void zwp_text_input_v2_input_panel_state(uint32_t state, int32_t x, int32_t y, int32_t width, int32_t height) override;
- void zwp_text_input_v2_preedit_string(const QString &text, const QString &commit) override;
- void zwp_text_input_v2_preedit_styling(uint32_t index, uint32_t length, uint32_t style) override;
- void zwp_text_input_v2_preedit_cursor(int32_t index) override;
- void zwp_text_input_v2_commit_string(const QString &text) override;
- void zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor) override;
- void zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length) override;
- void zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) override;
- void zwp_text_input_v2_language(const QString &language) override;
- void zwp_text_input_v2_text_direction(uint32_t direction) override;
- void zwp_text_input_v2_input_method_changed(uint32_t serial, uint32_t flags) override;
-
-private:
- Qt::KeyboardModifiers modifiersToQtModifiers(uint32_t modifiers);
-
- QWaylandDisplay *m_display = nullptr;
- QWaylandInputMethodEventBuilder m_builder;
-
- QVector<Qt::KeyboardModifier> m_modifiersMap;
-
- uint32_t m_serial = 0;
- struct ::wl_surface *m_surface = nullptr;
-
- QString m_preeditCommit;
-
- bool m_inputPanelVisible = false;
- QRectF m_keyboardRectangle;
- QLocale m_locale;
- Qt::LayoutDirection m_inputDirection = Qt::LayoutDirectionAuto;
-
- struct ::wl_callback *m_resetCallback = nullptr;
- static const wl_callback_listener callbackListener;
- static void resetCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
-};
-
class QWaylandInputContext : public QPlatformInputContext
{
Q_OBJECT
@@ -155,11 +60,28 @@ public:
void setFocusObject(QObject *object) override;
+#if QT_CONFIG(xkbcommon)
+ bool filterEvent(const QEvent *event) override;
+
+ // This invokable is called from QXkbCommon::setXkbContext().
+ Q_INVOKABLE void setXkbContext(struct xkb_context *context) { m_XkbContext = context; }
+#endif
+
private:
- QWaylandTextInput *textInput() const;
+ QWaylandTextInputInterface *textInput() const;
QWaylandDisplay *mDisplay = nullptr;
QPointer<QWindow> mCurrentWindow;
+
+#if QT_CONFIG(xkbcommon)
+ void ensureInitialized();
+
+ bool m_initialized = false;
+ QObject *m_focusObject = nullptr;
+ xkb_compose_table *m_composeTable = nullptr;
+ xkb_compose_state *m_composeState = nullptr;
+ struct xkb_context *m_XkbContext = nullptr;
+#endif
};
}
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index a9da452dc..ce04971ba 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandinputdevice_p.h"
#include "qwaylandintegration_p.h"
+#include "qwaylandtextinputv3_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylandsurface_p.h"
#include "qwaylandbuffer_p.h"
@@ -50,17 +15,26 @@
#if QT_CONFIG(wayland_client_primary_selection)
#include "qwaylandprimaryselectionv1_p.h"
#endif
+#if QT_CONFIG(tabletevent)
+#include "qwaylandtabletv2_p.h"
+#endif
+#include "qwaylandpointergestures_p.h"
#include "qwaylandtouch_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandshmbackingstore_p.h"
+#include "qwaylandtextinputv1_p.h"
+#include "qwaylandtextinputv2_p.h"
+#include "qwaylandtextinputinterface_p.h"
#include "qwaylandinputcontext_p.h"
+#include "qwaylandinputmethodcontext_p.h"
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatforminputcontext.h>
+#include <qpa/qplatformtheme.h>
#include <QDebug>
#include <unistd.h>
@@ -72,6 +46,7 @@
#endif
#include <QtGui/QGuiApplication>
+#include <QtGui/QPointingDevice>
QT_BEGIN_NAMESPACE
@@ -79,21 +54,27 @@ namespace QtWaylandClient {
Q_LOGGING_CATEGORY(lcQpaWaylandInput, "qt.qpa.wayland.input");
+// The maximum number of concurrent touchpoints is not exposed in wayland, so we assume a
+// reasonable number of them. As of 2021 most touchscreen panels support 10 concurrent touchpoints.
+static const int MaxTouchPoints = 10;
+
QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
: mParent(p)
{
- mRepeatTimer.callOnTimeout([&]() {
+ init(p->get_keyboard());
+ mRepeatTimer.callOnTimeout(this, [&]() {
if (!focusWindow()) {
// We destroyed the keyboard focus surface, but the server didn't get the message yet...
// or the server didn't send an enter event first.
return;
}
- mRepeatTimer.setInterval(mRepeatRate);
- handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers,
- mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
+ mRepeatTimer.setInterval(1000 / mRepeatRate);
+ Qt::KeyboardModifiers modifiers = this->modifiers();
+ handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, modifiers,
+ mRepeatKey.code, mRepeatKey.nativeVirtualKey, this->mNativeModifiers,
mRepeatKey.text, true);
- handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, mRepeatKey.modifiers,
- mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
+ handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, modifiers,
+ mRepeatKey.code, mRepeatKey.nativeVirtualKey, this->mNativeModifiers,
mRepeatKey.text, true);
});
}
@@ -128,8 +109,8 @@ bool QWaylandInputDevice::Keyboard::createDefaultKeymap()
QWaylandInputDevice::Keyboard::~Keyboard()
{
if (mFocus)
- QWindowSystemInterface::handleWindowActivated(nullptr);
- if (mParent->mVersion >= 3)
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr);
+ if (version() >= 3)
wl_keyboard_release(object());
else
wl_keyboard_destroy(object());
@@ -137,17 +118,28 @@ QWaylandInputDevice::Keyboard::~Keyboard()
QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const
{
- return mFocus ? QWaylandWindow::fromWlSurface(mFocus) : nullptr;
+ return mFocus ? mFocus->waylandWindow() : nullptr;
}
QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
: mParent(seat)
{
+ init(seat->get_pointer());
+#if QT_CONFIG(cursor)
+ if (auto cursorShapeManager = seat->mQDisplay->cursorShapeManager()) {
+ mCursor.shape.reset(new QWaylandCursorShape(cursorShapeManager->get_pointer(object())));
+ }
+
+ mCursor.frameTimer.setSingleShot(true);
+ mCursor.frameTimer.callOnTimeout(this, [&]() {
+ cursorTimerCallback();
+ });
+#endif
}
QWaylandInputDevice::Pointer::~Pointer()
{
- if (mParent->mVersion >= 3)
+ if (version() >= 3)
wl_pointer_release(object());
else
wl_pointer_destroy(object());
@@ -162,23 +154,16 @@ QWaylandWindow *QWaylandInputDevice::Pointer::focusWindow() const
class WlCallback : public QtWayland::wl_callback {
public:
- explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn, bool autoDelete = false)
+ explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn)
: QtWayland::wl_callback(callback)
, m_fn(fn)
- , m_autoDelete(autoDelete)
{}
~WlCallback() override { wl_callback_destroy(object()); }
- bool done() const { return m_done; }
void callback_done(uint32_t callback_data) override {
- m_done = true;
m_fn(callback_data);
- if (m_autoDelete)
- delete this;
}
private:
- bool m_done = false;
std::function<void(uint32_t)> m_fn;
- bool m_autoDelete = false;
};
class CursorSurface : public QWaylandSurface
@@ -188,25 +173,21 @@ public:
: QWaylandSurface(display)
, m_pointer(pointer)
{
- //TODO: When we upgrade to libwayland 1.10, use wl_surface_get_version instead.
- m_version = display->compositorVersion();
connect(this, &QWaylandSurface::screensChanged,
m_pointer, &QWaylandInputDevice::Pointer::updateCursor);
}
- void hide()
+ void reset()
{
- uint serial = m_pointer->mEnterSerial;
- Q_ASSERT(serial);
- m_pointer->set_cursor(serial, nullptr, 0, 0);
m_setSerial = 0;
+ m_hotspot = QPoint();
}
// Size and hotspot are in surface coordinates
void update(wl_buffer *buffer, const QPoint &hotspot, const QSize &size, int bufferScale, bool animated = false)
{
// Calling code needs to ensure buffer scale is supported if != 1
- Q_ASSERT(bufferScale == 1 || m_version >= 3);
+ Q_ASSERT(bufferScale == 1 || version() >= 3);
auto enterSerial = m_pointer->mEnterSerial;
if (m_setSerial < enterSerial || m_hotspot != hotspot) {
@@ -215,7 +196,7 @@ public:
m_hotspot = hotspot;
}
- if (m_version >= 3)
+ if (version() >= 3)
set_buffer_scale(bufferScale);
attach(buffer, 0, 0);
@@ -224,7 +205,7 @@ public:
if (animated) {
m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){
Q_UNUSED(time);
- m_pointer->updateCursor();
+ m_pointer->cursorFrameCallback();
}));
}
commit();
@@ -241,29 +222,15 @@ public:
private:
QScopedPointer<WlCallback> m_frameCallback;
QWaylandInputDevice::Pointer *m_pointer = nullptr;
- uint m_version = 0;
uint m_setSerial = 0;
QPoint m_hotspot;
};
-QString QWaylandInputDevice::Pointer::cursorThemeName() const
-{
- static QString themeName = qEnvironmentVariable("XCURSOR_THEME", QStringLiteral("default"));
- return themeName;
-}
-
-int QWaylandInputDevice::Pointer::cursorSize() const
-{
- constexpr int defaultCursorSize = 32;
- static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
- return xCursorSize > 0 ? xCursorSize : defaultCursorSize;
-}
-
int QWaylandInputDevice::Pointer::idealCursorScale() const
{
- // set_buffer_scale is not supported on earlier versions
- if (seat()->mQDisplay->compositorVersion() < 3)
+ if (seat()->mQDisplay->compositor()->version() < 3) {
return 1;
+ }
if (auto *s = mCursor.surface.data()) {
if (s->outputScale() > 0)
@@ -275,17 +242,30 @@ int QWaylandInputDevice::Pointer::idealCursorScale() const
void QWaylandInputDevice::Pointer::updateCursorTheme()
{
+ QString cursorThemeName;
+ QSize cursorSize;
+
+ if (const QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme()) {
+ cursorThemeName = platformTheme->themeHint(QPlatformTheme::MouseCursorTheme).toString();
+ cursorSize = platformTheme->themeHint(QPlatformTheme::MouseCursorSize).toSize();
+ }
+
+ if (cursorThemeName.isEmpty())
+ cursorThemeName = QStringLiteral("default");
+ if (cursorSize.isEmpty())
+ cursorSize = QSize(24, 24);
+
int scale = idealCursorScale();
- int pixelSize = cursorSize() * scale;
+ int pixelSize = cursorSize.width() * scale;
auto *display = seat()->mQDisplay;
- mCursor.theme = display->loadCursorTheme(cursorThemeName(), pixelSize);
+ mCursor.theme = display->loadCursorTheme(cursorThemeName, pixelSize);
if (!mCursor.theme)
return; // A warning has already been printed in loadCursorTheme
- if (auto *arrow = mCursor.theme->cursorImage(Qt::ArrowCursor)) {
- int arrowPixelSize = qMax(arrow->width, arrow->height); // Not all cursor themes are square
- while (scale > 1 && arrowPixelSize / scale < cursorSize())
+ if (auto *arrow = mCursor.theme->cursor(Qt::ArrowCursor)) {
+ int arrowPixelSize = qMax(arrow->images[0]->width, arrow->images[0]->height); // Not all cursor themes are square
+ while (scale > 1 && arrowPixelSize / scale < cursorSize.width())
--scale;
} else {
qCWarning(lcQpaWayland) << "Cursor theme does not support the arrow cursor";
@@ -302,7 +282,8 @@ void QWaylandInputDevice::Pointer::updateCursor()
if (shape == Qt::BlankCursor) {
if (mCursor.surface)
- mCursor.surface->hide();
+ mCursor.surface->reset();
+ set_cursor(mEnterSerial, nullptr, 0, 0);
return;
}
@@ -318,6 +299,14 @@ void QWaylandInputDevice::Pointer::updateCursor()
return;
}
+ if (mCursor.shape) {
+ if (mCursor.surface) {
+ mCursor.surface->reset();
+ }
+ mCursor.shape->setShape(mEnterSerial, shape);
+ return;
+ }
+
if (!mCursor.theme || idealCursorScale() != mCursor.themeBufferScale)
updateCursorTheme();
@@ -326,12 +315,26 @@ void QWaylandInputDevice::Pointer::updateCursor()
// Set from shape using theme
uint time = seat()->mCursor.animationTimer.elapsed();
- if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) {
+
+ if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
+ uint duration = 0;
+ int frame = wl_cursor_frame_and_duration(waylandCursor, time, &duration);
+ ::wl_cursor_image *image = waylandCursor->images[frame];
+
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer) {
+ qCWarning(lcQpaWayland) << "Could not find buffer for cursor" << shape;
+ return;
+ }
int bufferScale = mCursor.themeBufferScale;
QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
QSize size = QSize(image->width, image->height) / bufferScale;
- bool animated = image->delay > 0;
+ bool animated = duration > 0;
+ if (animated) {
+ mCursor.gotFrameCallback = false;
+ mCursor.gotTimerCallback = false;
+ mCursor.frameTimer.start(duration);
+ }
getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
return;
}
@@ -346,26 +349,42 @@ CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface()
return mCursor.surface.get();
}
+void QWaylandInputDevice::Pointer::cursorTimerCallback()
+{
+ mCursor.gotTimerCallback = true;
+ if (mCursor.gotFrameCallback) {
+ updateCursor();
+ }
+}
+
+void QWaylandInputDevice::Pointer::cursorFrameCallback()
+{
+ mCursor.gotFrameCallback = true;
+ if (mCursor.gotTimerCallback) {
+ updateCursor();
+ }
+}
+
#endif // QT_CONFIG(cursor)
QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p)
: mParent(p)
{
+ init(p->get_touch());
}
QWaylandInputDevice::Touch::~Touch()
{
- if (mParent->mVersion >= 3)
+ if (version() >= 3)
wl_touch_release(object());
else
wl_touch_destroy(object());
}
QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id)
- : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 5))
+ : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 9))
, mQDisplay(display)
, mDisplay(display->wl_display())
- , mVersion(qMin(version, 5))
{
#if QT_CONFIG(wayland_datadevice)
if (mQDisplay->dndSelectionHandler()) {
@@ -379,16 +398,33 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
setPrimarySelectionDevice(psm->createDevice(this));
#endif
- if (mQDisplay->textInputManager())
- mTextInput.reset(new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat())));
+ if (mQDisplay->textInputManagerv1()) {
+ auto textInput = new QWaylandTextInputv1(mQDisplay, mQDisplay->textInputManagerv1()->create_text_input());
+ textInput->setSeat(wl_seat());
+ mTextInput.reset(textInput);
+ }
+
+ if (mQDisplay->textInputManagerv2())
+ mTextInput.reset(new QWaylandTextInputv2(mQDisplay, mQDisplay->textInputManagerv2()->get_text_input(wl_seat())));
+ if (mQDisplay->textInputManagerv3())
+ mTextInput.reset(new QWaylandTextInputv3(mQDisplay, mQDisplay->textInputManagerv3()->get_text_input(wl_seat())));
+
+ if (mQDisplay->textInputMethodManager())
+ mTextInputMethod.reset(new QWaylandTextInputMethod(mQDisplay, mQDisplay->textInputMethodManager()->get_text_input_method(wl_seat())));
+
+#if QT_CONFIG(tabletevent)
+ if (auto *tm = mQDisplay->tabletManager())
+ mTabletSeat.reset(new QWaylandTabletSeatV2(tm, this));
+#endif
}
QWaylandInputDevice::~QWaylandInputDevice()
{
- delete mPointer;
- delete mKeyboard;
- delete mTouch;
+ if (version() >= WL_SEAT_RELEASE_SINCE_VERSION)
+ release();
+ else
+ wl_seat_destroy(object());
}
void QWaylandInputDevice::seat_capabilities(uint32_t caps)
@@ -396,37 +432,54 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps)
mCaps = caps;
if (caps & WL_SEAT_CAPABILITY_KEYBOARD && !mKeyboard) {
- mKeyboard = createKeyboard(this);
- mKeyboard->init(get_keyboard());
+ mKeyboard.reset(createKeyboard(this));
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && mKeyboard) {
- delete mKeyboard;
- mKeyboard = nullptr;
+ mKeyboard.reset();
}
if (caps & WL_SEAT_CAPABILITY_POINTER && !mPointer) {
- mPointer = createPointer(this);
- mPointer->init(get_pointer());
+ mPointer.reset(createPointer(this));
+
+ auto *pointerGestures = mQDisplay->pointerGestures();
+ if (pointerGestures) {
+ // NOTE: The name of the device and its system ID are not exposed on Wayland.
+ mTouchPadDevice = new QPointingDevice(
+ QLatin1String("touchpad"), 0, QInputDevice::DeviceType::TouchPad,
+ QPointingDevice::PointerType::Finger, QInputDevice::Capability::Position,
+ MaxTouchPoints, 0, QString(), QPointingDeviceUniqueId(), this);
+ QWindowSystemInterface::registerInputDevice(mTouchPadDevice);
+ mPointerGesturePinch.reset(pointerGestures->createPointerGesturePinch(this));
+ mPointerGesturePinch->init(pointerGestures->get_pinch_gesture(mPointer->object()));
+ mPointerGestureSwipe.reset(pointerGestures->createPointerGestureSwipe(this));
+ mPointerGestureSwipe->init(pointerGestures->get_swipe_gesture(mPointer->object()));
+ }
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && mPointer) {
- delete mPointer;
- mPointer = nullptr;
+ mPointer.reset();
+ mPointerGesturePinch.reset();
+ mPointerGestureSwipe.reset();
}
if (caps & WL_SEAT_CAPABILITY_TOUCH && !mTouch) {
- mTouch = createTouch(this);
- mTouch->init(get_touch());
+ mTouch.reset(createTouch(this));
if (!mTouchDevice) {
- mTouchDevice = new QTouchDevice;
- mTouchDevice->setType(QTouchDevice::TouchScreen);
- mTouchDevice->setCapabilities(QTouchDevice::Position);
- QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+ // TODO number of touchpoints, actual name and ID
+ mTouchDevice = new QPointingDevice(
+ QLatin1String("some touchscreen"), 0, QInputDevice::DeviceType::TouchScreen,
+ QPointingDevice::PointerType::Finger, QInputDevice::Capability::Position,
+ MaxTouchPoints, 0,QString(), QPointingDeviceUniqueId(), this);
+ QWindowSystemInterface::registerInputDevice(mTouchDevice);
}
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && mTouch) {
- delete mTouch;
- mTouch = nullptr;
+ mTouch.reset();
}
}
+void QWaylandInputDevice::seat_name(const QString &name)
+{
+ mSeatName = name;
+}
+
QWaylandInputDevice::Keyboard *QWaylandInputDevice::createKeyboard(QWaylandInputDevice *device)
{
return new Keyboard(device);
@@ -444,17 +497,27 @@ QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice
QWaylandInputDevice::Keyboard *QWaylandInputDevice::keyboard() const
{
- return mKeyboard;
+ return mKeyboard.data();
}
QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const
{
- return mPointer;
+ return mPointer.data();
+}
+
+QWaylandPointerGestureSwipe *QWaylandInputDevice::pointerGestureSwipe() const
+{
+ return mPointerGestureSwipe.data();
+}
+
+QWaylandPointerGesturePinch *QWaylandInputDevice::pointerGesturePinch() const
+{
+ return mPointerGesturePinch.data();
}
QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const
{
- return mTouch;
+ return mTouch.data();
}
void QWaylandInputDevice::handleEndDrag()
@@ -489,16 +552,26 @@ QWaylandPrimarySelectionDeviceV1 *QWaylandInputDevice::primarySelectionDevice()
}
#endif
-void QWaylandInputDevice::setTextInput(QWaylandTextInput *textInput)
+void QWaylandInputDevice::setTextInput(QWaylandTextInputInterface *textInput)
{
mTextInput.reset(textInput);
}
-QWaylandTextInput *QWaylandInputDevice::textInput() const
+void QWaylandInputDevice::setTextInputMethod(QWaylandTextInputMethod *textInputMethod)
+{
+ mTextInputMethod.reset(textInputMethod);
+}
+
+QWaylandTextInputInterface *QWaylandInputDevice::textInput() const
{
return mTextInput.data();
}
+QWaylandTextInputMethod *QWaylandInputDevice::textInputMethod() const
+{
+ return mTextInputMethod.data();
+}
+
void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
{
if (mPointer)
@@ -594,8 +667,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)
{}
};
@@ -620,7 +693,7 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
connect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
mSurfacePos = QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy));
- mGlobalPos = window->window()->mapToGlobal(mSurfacePos.toPoint());
+ mGlobalPos = window->mapToGlobal(mSurfacePos.toPoint());
mParent->mSerial = serial;
mEnterSerial = serial;
@@ -639,13 +712,18 @@ 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)
{}
};
void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surface *surface)
{
+ invalidateFocus();
+ mButtons = Qt::NoButton;
+
+ mParent->mTime = time;
+
// The event may arrive after destroying the window, indicated by
// a null surface.
if (!surface)
@@ -657,11 +735,6 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
if (!QWaylandWindow::mouseGrab())
setFrameEvent(new LeaveEvent(window, mSurfacePos, mGlobalPos));
-
- invalidateFocus();
- mButtons = Qt::NoButton;
-
- mParent->mTime = time;
}
class MotionEvent : public QWaylandPointerEvent
@@ -669,8 +742,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)
{
}
};
@@ -686,7 +759,7 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
QPointF pos(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
QPointF delta = pos - pos.toPoint();
- QPointF global = window->window()->mapToGlobal(pos.toPoint());
+ QPointF global = window->mapToGlobal(pos.toPoint());
global += delta;
mSurfacePos = pos;
@@ -698,7 +771,7 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
// We can't know the true position since we're getting events for another surface,
// so we just set it outside of the window boundaries.
pos = QPointF(-1, -1);
- global = grab->window()->mapToGlobal(pos.toPoint());
+ global = grab->mapToGlobal(pos.toPoint());
window = grab;
}
setFrameEvent(new MotionEvent(window, time, pos, global, mButtons, mParent->modifiers()));
@@ -708,9 +781,10 @@ class PressEvent : public QWaylandPointerEvent
{
public:
PressEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
- const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : QWaylandPointerEvent(QWaylandPointerEvent::Press, Qt::NoScrollPhase, surface,
- timestamp, localPos, globalPos, buttons, modifiers)
+ const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
+ Qt::KeyboardModifiers modifiers)
+ : QWaylandPointerEvent(QEvent::MouseButtonPress, Qt::NoScrollPhase, surface,
+ timestamp, localPos, globalPos, buttons, button, modifiers)
{
}
};
@@ -719,9 +793,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)
{
}
};
@@ -760,6 +835,8 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
default: return; // invalid button number (as far as Qt is concerned)
}
+ mLastButton = qt_button;
+
if (state)
mButtons |= qt_button;
else
@@ -776,15 +853,15 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
QPointF global = mGlobalPos;
if (grab && grab != focusWindow()) {
pos = QPointF(-1, -1);
- global = grab->window()->mapToGlobal(pos.toPoint());
+ global = grab->mapToGlobal(pos.toPoint());
window = grab;
}
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()
@@ -798,10 +875,13 @@ void QWaylandInputDevice::Pointer::invalidateFocus()
void QWaylandInputDevice::Pointer::releaseButtons()
{
+ if (mButtons == Qt::NoButton)
+ return;
+
mButtons = Qt::NoButton;
if (auto *window = focusWindow()) {
- MotionEvent e(focusWindow(), mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
+ ReleaseEvent e(focusWindow(), mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mLastButton, mParent->modifiers());
window->handleMouse(mParent, e);
}
}
@@ -811,9 +891,11 @@ class WheelEvent : public QWaylandPointerEvent
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,
- local, global, pixelDelta, angleDelta, source, modifiers)
+ Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers, bool inverted)
+ : QWaylandPointerEvent(QEvent::Wheel, phase, surface, timestamp, local, global,
+ modifiers & Qt::AltModifier ? pixelDelta.transposed() : pixelDelta,
+ modifiers & Qt::AltModifier ? angleDelta.transposed() : angleDelta,
+ source, modifiers, inverted)
{
}
};
@@ -844,7 +926,7 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
mParent->mTime = time;
- if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) {
+ if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
flushFrameEvent();
}
@@ -867,6 +949,8 @@ void QWaylandInputDevice::Pointer::pointer_axis_source(uint32_t source)
case axis_source_continuous:
qCDebug(lcQpaWaylandInput) << "Axis source continuous";
break;
+ case axis_source_wheel_tilt:
+ qCDebug(lcQpaWaylandInput) << "Axis source wheel tilt";
}
mFrameData.axisSource = axis_source(source);
}
@@ -905,8 +989,9 @@ void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axi
if (!target)
target = focusWindow();
Qt::KeyboardModifiers mods = mParent->modifiers();
+ const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
WheelEvent wheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
- QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods);
+ QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods, inverted);
target->handleMouse(mParent, wheelEvent);
mScrollBeginSent = false;
mScrollDeltaRemainder = QPointF();
@@ -917,14 +1002,16 @@ void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t
if (!focusWindow())
return;
+ const int32_t delta120 = value * 15 * 8;
+
switch (axis) {
case axis_vertical_scroll:
qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete vertical:" << value;
- mFrameData.discreteDelta.ry() += value;
+ mFrameData.delta120.ry() += delta120;
break;
case axis_horizontal_scroll:
qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete horizontal:" << value;
- mFrameData.discreteDelta.rx() += value;
+ mFrameData.delta120.rx() += delta120;
break;
default:
//TODO: is this really needed?
@@ -933,6 +1020,41 @@ void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t
}
}
+void QWaylandInputDevice::Pointer::pointer_axis_value120(uint32_t axis, int32_t value)
+{
+ if (!focusWindow())
+ return;
+
+ switch (axis) {
+ case axis_vertical_scroll:
+ qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_value120 vertical:" << value;
+ mFrameData.delta120.ry() += value;
+ break;
+ case axis_horizontal_scroll:
+ qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_value120 horizontal:" << value;
+ mFrameData.delta120.rx() += value;
+ break;
+ default:
+ qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_value120: Unknown axis:" << axis;
+ return;
+ }
+}
+
+void QWaylandInputDevice::Pointer::pointer_axis_relative_direction(uint32_t axis, uint32_t direction)
+{
+ const bool inverted = direction == axis_relative_direction_inverted;
+ switch (axis) {
+ case axis_vertical_scroll:
+ mFrameData.verticalAxisInverted = inverted;
+ break;
+ case axis_horizontal_scroll:
+ mFrameData.horizontalAxisInverted = inverted;
+ break;
+ default:
+ qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_relative_direction: Unknown axis:" << axis;
+ }
+}
+
void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
{
qCDebug(lcQpaWaylandInput) << "Setting frame event " << event->type;
@@ -943,7 +1065,7 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
mFrameData.event = event;
- if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) {
+ if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
flushFrameEvent();
}
@@ -951,9 +1073,11 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
void QWaylandInputDevice::Pointer::FrameData::resetScrollData()
{
- discreteDelta = QPoint();
+ delta120 = QPoint();
delta = QPointF();
axisSource = axis_source_wheel;
+ horizontalAxisInverted = false;
+ verticalAxisInverted = false;
}
bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const
@@ -968,6 +1092,8 @@ bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const
case axis_source_finger:
case axis_source_continuous:
return !delta.isNull();
+ default:
+ return false;
}
}
@@ -982,20 +1108,27 @@ QPoint QWaylandInputDevice::Pointer::FrameData::pixelDeltaAndError(QPointF *accu
*accumulatedError += delta - pixelDelta;
Q_ASSERT(qAbs(accumulatedError->x()) < 1.0);
Q_ASSERT(qAbs(accumulatedError->y()) < 1.0);
+
+ // for continuous scroll events things should be
+ // in the same direction
+ // i.e converted so downwards surface co-ordinates (positive axis_value)
+ // goes to downwards in wheel event (negative value)
+ pixelDelta *= -1;
return pixelDelta;
}
QPoint QWaylandInputDevice::Pointer::FrameData::angleDelta() const
{
- if (discreteDelta.isNull()) {
+ if (delta120.isNull()) {
// If we didn't get any discrete events, then we need to fall back to
// the continuous information.
return (delta * -12).toPoint(); //TODO: why multiply by 12?
}
// The angle delta is in eights of degrees, and our docs says most mice have
- // 1 click = 15 degrees. It's also in the opposite direction of surface space.
- return -discreteDelta * 15 * 8;
+ // 1 click = 15 degrees, i.e. 120 is one click. It's also in the opposite
+ // direction of surface space.
+ return -delta120;
}
Qt::MouseEventSource QWaylandInputDevice::Pointer::FrameData::wheelEventSource() const
@@ -1026,7 +1159,7 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
target->handleMouse(mParent, WheelEvent(focusWindow(), Qt::ScrollBegin, mParent->mTime,
mSurfacePos, mGlobalPos, QPoint(), QPoint(),
Qt::MouseEventNotSynthesized,
- mParent->modifiers()));
+ mParent->modifiers(), false));
mScrollBeginSent = true;
mScrollDeltaRemainder = QPointF();
}
@@ -1035,11 +1168,15 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
QPoint pixelDelta = mFrameData.pixelDeltaAndError(&mScrollDeltaRemainder);
Qt::MouseEventSource source = mFrameData.wheelEventSource();
+
+ // The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag
+ // Pragmatically it should't come up
+ const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
+
qCDebug(lcQpaWaylandInput) << "Flushing scroll event" << phase << pixelDelta << angleDelta;
target->handleMouse(mParent, WheelEvent(focusWindow(), phase, mParent->mTime, mSurfacePos, mGlobalPos,
- pixelDelta, angleDelta, source, mParent->modifiers()));
+ pixelDelta, angleDelta, source, mParent->modifiers(), inverted));
}
-
mFrameData.resetScrollData();
}
@@ -1048,11 +1185,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;
@@ -1077,7 +1216,7 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd,
return;
}
- char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0));
+ char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0));
if (map_str == MAP_FAILED) {
close(fd);
return;
@@ -1112,13 +1251,17 @@ void QWaylandInputDevice::Keyboard::keyboard_enter(uint32_t time, struct wl_surf
return;
}
+ QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return;
+
if (mFocus) {
qCWarning(lcQpaWayland()) << "Unexpected wl_keyboard.enter event. Keyboard already has focus";
- disconnect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
+ disconnect(mFocus, &QWaylandSurface::destroyed, this, &Keyboard::handleFocusDestroyed);
}
- mFocus = surface;
- connect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
+ mFocus = window->waylandSurface();
+ connect(mFocus, &QWaylandSurface::destroyed, this, &Keyboard::handleFocusDestroyed);
mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
}
@@ -1132,13 +1275,17 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf
return;
}
- if (surface != mFocus) {
+ QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return;
+
+ if (window->waylandSurface() != mFocus) {
qCWarning(lcQpaWayland) << "Ignoring unexpected wl_keyboard.leave event."
<< "wl_surface argument does not match the current focus"
<< "This is most likely a compositor bug";
return;
}
- disconnect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
+ disconnect(mFocus, &QWaylandSurface::destroyed, this, &Keyboard::handleFocusDestroyed);
handleFocusLost();
}
@@ -1150,7 +1297,7 @@ void QWaylandInputDevice::Keyboard::handleKey(ulong timestamp, QEvent::Type type
QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
bool filtered = false;
- if (inputContext && !mParent->mQDisplay->usingInputContextFromCompositor()) {
+ if (inputContext) {
QKeyEvent event(type, key, modifiers, nativeScanCode, nativeVirtualKey,
nativeModifiers, text, autorepeat, count);
event.setTimestamp(timestamp);
@@ -1202,10 +1349,9 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
auto code = key + 8; // map to wl_keyboard::keymap_format::keymap_format_xkb_v1
xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState.get(), code);
+ Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(mXkbState.get(), sym);
- Qt::KeyboardModifiers modifiers = mParent->modifiers();
-
- int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, mXkbState.get(), code);
+ int qtkey = keysymToQtKey(sym, modifiers, mXkbState.get(), code);
QString text = QXkbCommon::lookupString(mXkbState.get(), code);
QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
@@ -1216,8 +1362,6 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
mRepeatKey.code = code;
mRepeatKey.time = time;
mRepeatKey.text = text;
- mRepeatKey.modifiers = modifiers;
- mRepeatKey.nativeModifiers = mNativeModifiers;
mRepeatKey.nativeVirtualKey = sym;
mRepeatTimer.setInterval(mRepeatDelay);
mRepeatTimer.start();
@@ -1238,25 +1382,12 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
{
- // The signal is emitted by QWaylandWindow, which is not necessarily destroyed along with the
- // surface, so we still need to disconnect the signal
- auto *window = qobject_cast<QWaylandWindow *>(sender());
- disconnect(window, &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
- Q_ASSERT(window->wlSurface() == mFocus);
handleFocusLost();
}
void QWaylandInputDevice::Keyboard::handleFocusLost()
{
mFocus = nullptr;
-#if QT_CONFIG(clipboard)
- if (auto *dataDevice = mParent->dataDevice())
- dataDevice->invalidateSelectionOffer();
-#endif
-#if QT_CONFIG(wayland_client_primary_selection)
- if (auto *device = mParent->primarySelectionDevice())
- device->invalidateSelectionOffer();
-#endif
mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
mRepeatTimer.stop();
}
@@ -1307,14 +1438,14 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
mFocus = window;
mParent->mQDisplay->setLastInputDevice(mParent, serial, mFocus);
QPointF position(wl_fixed_to_double(x), wl_fixed_to_double(y));
- mParent->handleTouchPoint(id, Qt::TouchPointPressed, position);
+ mParent->handleTouchPoint(id, QEventPoint::Pressed, position);
}
void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_t id)
{
Q_UNUSED(serial);
- Q_UNUSED(time);
- mParent->handleTouchPoint(id, Qt::TouchPointReleased);
+ mParent->mTime = time;
+ mParent->handleTouchPoint(id, QEventPoint::Released);
if (allTouchPointsReleased()) {
mFocus = nullptr;
@@ -1332,9 +1463,9 @@ void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_
void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
{
- Q_UNUSED(time);
QPointF position(wl_fixed_to_double(x), wl_fixed_to_double(y));
- mParent->handleTouchPoint(id, Qt::TouchPointMoved, position);
+ mParent->mTime = time;
+ mParent->handleTouchPoint(id, QEventPoint::Updated, position);
}
void QWaylandInputDevice::Touch::touch_cancel()
@@ -1345,21 +1476,30 @@ void QWaylandInputDevice::Touch::touch_cancel()
if (touchExt)
touchExt->touchCanceled();
+ mFocus = nullptr;
QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice);
}
-void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition)
+void QWaylandInputDevice::handleTouchPoint(int id, QEventPoint::State state, const QPointF &surfacePosition)
{
auto end = mTouch->mPendingTouchPoints.end();
- auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](auto tp){ return tp.id == id; });
+ auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](const QWindowSystemInterface::TouchPoint &tp){ return tp.id == id; });
if (it == end) {
it = mTouch->mPendingTouchPoints.insert(end, QWindowSystemInterface::TouchPoint());
it->id = id;
}
+ // If the touch points were up and down in same frame, send out frame right away
+ else if ((it->state == QEventPoint::Pressed && state == QEventPoint::Released)
+ || (it->state == QEventPoint::Released && state == QEventPoint::Pressed)) {
+ mTouch->touch_frame();
+ it = mTouch->mPendingTouchPoints.insert(mTouch->mPendingTouchPoints.end(), QWindowSystemInterface::TouchPoint());
+ it->id = id;
+ }
+
QWindowSystemInterface::TouchPoint &tp = *it;
// Only moved and pressed needs to update/set position
- if (state == Qt::TouchPointMoved || state == Qt::TouchPointPressed) {
+ if (state == QEventPoint::Updated || state == QEventPoint::Pressed) {
// We need a global (screen) position.
QWaylandWindow *win = mTouch->mFocus;
@@ -1372,23 +1512,25 @@ 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();
- QPointF globalPosition = win->window()->mapToGlobal(localPosition.toPoint()) + delta;
+ QPointF globalPosition = win->mapToGlobal(localPosition.toPoint()) + delta;
tp.area.moveCenter(globalPosition);
}
- tp.state = state;
- tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
+ // If the touch point was pressed earlier this frame, we don't want to overwrite its state.
+ if (tp.state != QEventPoint::Pressed)
+ tp.state = QEventPoint::State(state);
+
+ tp.pressure = tp.state == QEventPoint::Released ? 0 : 1;
}
bool QWaylandInputDevice::Touch::allTouchPointsReleased()
{
- for (const auto &tp : qAsConst(mPendingTouchPoints)) {
- if (tp.state != Qt::TouchPointReleased)
+ for (const auto &tp : std::as_const(mPendingTouchPoints)) {
+ if (tp.state != QEventPoint::Released)
return false;
}
return true;
@@ -1400,7 +1542,7 @@ void QWaylandInputDevice::Touch::releasePoints()
return;
for (QWindowSystemInterface::TouchPoint &tp : mPendingTouchPoints)
- tp.state = Qt::TouchPointReleased;
+ tp.state = QEventPoint::Released;
touch_frame();
}
@@ -1412,26 +1554,31 @@ void QWaylandInputDevice::Touch::touch_frame()
QWindow *window = mFocus ? mFocus->window() : nullptr;
if (mFocus) {
- const QWindowSystemInterface::TouchPoint &tp = mPendingTouchPoints.last();
+ // Returns a reference to the last item in the list. The list must not be empty.
+ // If the list can be empty, call isEmpty() before calling this function.
+ // See: https://doc.qt.io/qt-5.15/qlist.html#last
+ if (mPendingTouchPoints.empty())
+ return;
+ const QWindowSystemInterface::TouchPoint &tp = mPendingTouchPoints.constLast();
// When the touch event is received, the global pos is calculated with the margins
// in mind. Now we need to adjust again to get the correct local pos back.
- QMargins margins = window->frameMargins();
+ QMargins margins = mFocus->clientSideMargins();
QPoint p = tp.area.center().toPoint();
- QPointF localPos(window->mapFromGlobal(QPoint(p.x() + margins.left(), p.y() + margins.top())));
+ QPointF localPos(mFocus->mapFromGlobal(p) + QPoint(margins.left(), margins.top()));
if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers()))
return;
}
- QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mPendingTouchPoints);
+ QWindowSystemInterface::handleTouchEvent(window, mParent->mTime, mParent->mTouchDevice, mPendingTouchPoints, mParent->modifiers());
// Prepare state for next frame
const auto prevTouchPoints = mPendingTouchPoints;
mPendingTouchPoints.clear();
for (const auto &prevPoint: prevTouchPoints) {
// All non-released touch points should be part of the next touch event
- if (prevPoint.state != Qt::TouchPointReleased) {
+ if (prevPoint.state != QEventPoint::Released) {
QWindowSystemInterface::TouchPoint tp = prevPoint;
- tp.state = Qt::TouchPointStationary; // ... as stationary (unless proven otherwise)
+ tp.state = QEventPoint::Stationary; // ... as stationary (unless proven otherwise)
mPendingTouchPoints.append(tp);
}
}
@@ -1441,3 +1588,5 @@ void QWaylandInputDevice::Touch::touch_frame()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandinputdevice_p.cpp"
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 60d6f2c17..becd5f9be 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDINPUTDEVICE_H
#define QWAYLANDINPUTDEVICE_H
@@ -63,9 +27,10 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtWaylandClient/private/qwayland-pointer-gestures-unstable-v1.h>
#if QT_CONFIG(xkbcommon)
-#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
+#include <QtGui/private/qxkbcommon_p.h>
#endif
#include <QtCore/QDebug>
@@ -89,13 +54,23 @@ class QWaylandDisplay;
#if QT_CONFIG(wayland_client_primary_selection)
class QWaylandPrimarySelectionDeviceV1;
#endif
-class QWaylandTextInput;
+#if QT_CONFIG(tabletevent)
+class QWaylandTabletSeatV2;
+#endif
+class QWaylandPointerGestures;
+class QWaylandPointerGestureSwipe;
+class QWaylandPointerGesturePinch;
+class QWaylandTextInputInterface;
+class QWaylandTextInputMethod;
#if QT_CONFIG(cursor)
class QWaylandCursorTheme;
+class QWaylandCursorShape;
class CursorSurface;
#endif
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice
+Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput);
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice
: public QObject
, public QtWayland::wl_seat
{
@@ -109,7 +84,9 @@ public:
~QWaylandInputDevice() override;
uint32_t capabilities() const { return mCaps; }
+ QString seatname() const { return mSeatName; }
+ QWaylandDisplay *display() const { return mQDisplay; }
struct ::wl_seat *wl_seat() { return QtWayland::wl_seat::object(); }
#if QT_CONFIG(cursor)
@@ -127,8 +104,16 @@ public:
QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice() const;
#endif
- void setTextInput(QWaylandTextInput *textInput);
- QWaylandTextInput *textInput() const;
+#if QT_CONFIG(tabletevent)
+ void setTabletSeat(QWaylandTabletSeatV2 *tabletSeat);
+ QWaylandTabletSeatV2* tabletSeat() const;
+#endif
+
+ void setTextInput(QWaylandTextInputInterface *textInput);
+ QWaylandTextInputInterface *textInput() const;
+
+ void setTextInputMethod(QWaylandTextInputMethod *textInputMethod);
+ QWaylandTextInputMethod *textInputMethod() const;
void removeMouseButtonFromState(Qt::MouseButton button);
@@ -150,14 +135,16 @@ public:
Keyboard *keyboard() const;
Pointer *pointer() const;
+ QWaylandPointerGestureSwipe *pointerGestureSwipe() const;
+ QWaylandPointerGesturePinch *pointerGesturePinch() const;
Touch *touch() const;
-private:
+protected:
QWaylandDisplay *mQDisplay = nullptr;
struct wl_display *mDisplay = nullptr;
- int mVersion;
uint32_t mCaps = 0;
+ QString mSeatName;
#if QT_CONFIG(cursor)
struct CursorState {
@@ -178,22 +165,33 @@ private:
QScopedPointer<QWaylandPrimarySelectionDeviceV1> mPrimarySelectionDevice;
#endif
- Keyboard *mKeyboard = nullptr;
- Pointer *mPointer = nullptr;
- Touch *mTouch = nullptr;
+ QScopedPointer<Keyboard> mKeyboard;
+ QScopedPointer<Pointer> mPointer;
+ QScopedPointer<QWaylandPointerGestureSwipe> mPointerGestureSwipe;
+ QScopedPointer<QWaylandPointerGesturePinch> mPointerGesturePinch;
+ QScopedPointer<Touch> mTouch;
- QScopedPointer<QWaylandTextInput> mTextInput;
+ QScopedPointer<QWaylandTextInputInterface> mTextInput;
+ QScopedPointer<QWaylandTextInputMethod> mTextInputMethod;
+#if QT_CONFIG(tabletevent)
+ QScopedPointer<QWaylandTabletSeatV2> mTabletSeat;
+#endif
uint32_t mTime = 0;
uint32_t mSerial = 0;
void seat_capabilities(uint32_t caps) override;
- void handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition = QPoint());
+ void seat_name(const QString &name) override;
+ void handleTouchPoint(int id, QEventPoint::State state, const QPointF &surfacePosition = QPoint());
- QTouchDevice *mTouchDevice = nullptr;
+ QPointingDevice *mTouchDevice = nullptr;
+ QPointingDevice *mTouchPadDevice = nullptr;
friend class QWaylandTouchExtension;
friend class QWaylandQtKeyExtension;
+ friend class QWaylandPointerGestureSwipe;
+ friend class QWaylandPointerGesturePinch;
+ friend class QWaylandWindow;
};
inline uint32_t QWaylandInputDevice::serial() const
@@ -202,7 +200,7 @@ inline uint32_t QWaylandInputDevice::serial() const
}
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Keyboard : public QObject, public QtWayland::wl_keyboard
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Keyboard : public QObject, public QtWayland::wl_keyboard
{
Q_OBJECT
@@ -230,18 +228,16 @@ public:
void keyboard_repeat_info(int32_t rate, int32_t delay) override;
QWaylandInputDevice *mParent = nullptr;
- ::wl_surface *mFocus = nullptr;
+ QPointer<QWaylandSurface> mFocus;
uint32_t mNativeModifiers = 0;
struct repeatKey {
- int key;
- uint32_t code;
- uint32_t time;
+ int key = 0;
+ uint32_t code = 0;
+ uint32_t time = 0 ;
QString text;
- Qt::KeyboardModifiers modifiers;
- uint32_t nativeVirtualKey;
- uint32_t nativeModifiers;
+ uint32_t nativeVirtualKey = 0;
} mRepeatKey;
QTimer mRepeatTimer;
@@ -254,7 +250,13 @@ public:
struct ::wl_keyboard *wl_keyboard() { return QtWayland::wl_keyboard::object(); }
-private slots:
+#if QT_CONFIG(xkbcommon)
+ virtual int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers, xkb_state *state, xkb_keycode_t code) {
+ return QXkbCommon::keysymToQtKey(keysym, modifiers, state, code);
+ }
+#endif
+
+private Q_SLOTS:
void handleFocusDestroyed();
void handleFocusLost();
@@ -273,7 +275,7 @@ private:
friend class QWaylandInputDevice;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, public QtWayland::wl_pointer
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, public QtWayland::wl_pointer
{
Q_OBJECT
public:
@@ -281,11 +283,11 @@ public:
~Pointer() override;
QWaylandWindow *focusWindow() const;
#if QT_CONFIG(cursor)
- QString cursorThemeName() const;
- int cursorSize() const; // in surface coordinates
int idealCursorScale() const;
void updateCursorTheme();
void updateCursor();
+ void cursorTimerCallback();
+ void cursorFrameCallback();
CursorSurface *getOrCreateCursorSurface();
#endif
QWaylandInputDevice *seat() const { return mParent; }
@@ -307,8 +309,10 @@ protected:
void pointer_axis_stop(uint32_t time, uint32_t axis) override;
void pointer_axis_discrete(uint32_t axis, int32_t value) override;
void pointer_frame() override;
+ void pointer_axis_value120(uint32_t axis, int32_t value120) override;
+ void pointer_axis_relative_direction(uint32_t axis, uint32_t direction) override;
-private slots:
+private Q_SLOTS:
void handleFocusDestroyed() { invalidateFocus(); }
private:
@@ -322,25 +326,28 @@ public:
uint32_t mEnterSerial = 0;
#if QT_CONFIG(cursor)
struct {
+ QScopedPointer<QWaylandCursorShape> shape;
QWaylandCursorTheme *theme = nullptr;
int themeBufferScale = 0;
QScopedPointer<CursorSurface> surface;
+ QTimer frameTimer;
+ bool gotFrameCallback = false;
+ bool gotTimerCallback = false;
} mCursor;
#endif
QPointF mSurfacePos;
QPointF mGlobalPos;
Qt::MouseButtons mButtons = Qt::NoButton;
-#if QT_CONFIG(cursor)
- wl_buffer *mCursorBuffer = nullptr;
- Qt::CursorShape mCursorShape = Qt::BitmapCursor;
-#endif
+ Qt::MouseButton mLastButton = Qt::NoButton;
struct FrameData {
QWaylandPointerEvent *event = nullptr;
QPointF delta;
- QPoint discreteDelta;
+ QPoint delta120;
axis_source axisSource = axis_source_wheel;
+ bool verticalAxisInverted = false;
+ bool horizontalAxisInverted = false;
void resetScrollData();
bool hasPixelDelta() const;
@@ -360,7 +367,7 @@ private: //TODO: should other methods be private as well?
bool isDefinitelyTerminated(axis_source source) const;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Touch : public QtWayland::wl_touch
+class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Touch : public QtWayland::wl_touch
{
public:
Touch(QWaylandInputDevice *p);
@@ -396,33 +403,25 @@ 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,
- Qt::KeyboardModifiers modifiers)
+ Qt::KeyboardModifiers modifiers, bool inverted)
: type(type)
, phase(phase)
, timestamp(timestamp)
@@ -433,20 +432,80 @@ public:
, angleDelta(angleDelta)
, source(source)
, surface(surface)
+ , inverted(inverted)
{}
- 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;
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
QPointer<QWaylandWindow> surface;
+ bool inverted = false;
+};
+
+#ifndef QT_NO_GESTURES
+class QWaylandPointerGestureSwipeEvent
+{
+ Q_GADGET
+public:
+ inline QWaylandPointerGestureSwipeEvent(QWaylandWindow *surface, Qt::GestureState state,
+ ulong timestamp, const QPointF &local,
+ const QPointF &global, uint fingers, const QPointF& delta)
+ : surface(surface)
+ , state(state)
+ , timestamp(timestamp)
+ , local(local)
+ , global(global)
+ , fingers(fingers)
+ , delta(delta)
+ {}
+
+ QPointer<QWaylandWindow> surface;
+ Qt::GestureState state = Qt::GestureState::NoGesture;
+ ulong timestamp = 0;
+ QPointF local;
+ QPointF global;
+ uint fingers = 0;
+ QPointF delta;
+};
+
+class QWaylandPointerGesturePinchEvent
+{
+ Q_GADGET
+public:
+ inline QWaylandPointerGesturePinchEvent(QWaylandWindow *surface, Qt::GestureState state,
+ ulong timestamp, const QPointF &local,
+ const QPointF &global, uint fingers, const QPointF& delta,
+ qreal scale_delta, qreal rotation_delta)
+ : surface(surface)
+ , state(state)
+ , timestamp(timestamp)
+ , local(local)
+ , global(global)
+ , fingers(fingers)
+ , delta(delta)
+ , scale_delta(scale_delta)
+ , rotation_delta(rotation_delta)
+ {}
+
+ QPointer<QWaylandWindow> surface;
+ Qt::GestureState state = Qt::GestureState::NoGesture;
+ ulong timestamp = 0;
+ QPointF local;
+ QPointF global;
+ uint fingers = 0;
+ QPointF delta;
+ qreal scale_delta = 0;
+ qreal rotation_delta = 0;
};
+#endif // #ifndef QT_NO_GESTURES
}
diff --git a/src/client/qwaylandinputmethodcontext.cpp b/src/client/qwaylandinputmethodcontext.cpp
new file mode 100644
index 000000000..2733e4f3a
--- /dev/null
+++ b/src/client/qwaylandinputmethodcontext.cpp
@@ -0,0 +1,401 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandinputmethodcontext_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandinputdevice_p.h"
+
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qtextformat.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcQpaInputMethods)
+
+namespace QtWaylandClient {
+
+static constexpr int maxStringSize = 1000; // actual max is 4096/3
+
+QWaylandTextInputMethod::QWaylandTextInputMethod(QWaylandDisplay *display, struct ::qt_text_input_method_v1 *textInputMethod)
+ : QtWayland::qt_text_input_method_v1(textInputMethod)
+{
+ Q_UNUSED(display);
+}
+
+QWaylandTextInputMethod::~QWaylandTextInputMethod()
+{
+ qt_text_input_method_v1_destroy(object());
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_visible_changed(int32_t visible)
+{
+ if (m_isVisible != visible) {
+ m_isVisible = visible;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
+ }
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_locale_changed(const QString &localeName)
+{
+ m_locale = QLocale(localeName);
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_input_direction_changed(int32_t inputDirection)
+{
+ m_layoutDirection = Qt::LayoutDirection(inputDirection);
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_keyboard_rectangle_changed(wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height)
+{
+ const QRectF keyboardRectangle(wl_fixed_to_double(x),
+ wl_fixed_to_double(y),
+ wl_fixed_to_double(width),
+ wl_fixed_to_double(height));
+ if (m_keyboardRect != keyboardRectangle) {
+ m_keyboardRect = keyboardRectangle;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitKeyboardRectChanged();
+ }
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_start_input_method_event(uint32_t serial, int32_t surrounding_text_offset)
+{
+ if (m_pendingInputMethodEvents.contains(serial)) {
+ qCWarning(qLcQpaInputMethods) << "Input method event with serial" << serial << "already started";
+ return;
+ }
+
+ m_pendingInputMethodEvents[serial] = QList<QInputMethodEvent::Attribute>{};
+ m_offsetFromCompositor[serial] = surrounding_text_offset;
+}
+
+// We need to keep surrounding text below maxStringSize characters, with cursorPos centered in that substring
+
+static int calculateOffset(const QString &text, int cursorPos)
+{
+ int size = text.size();
+ int halfSize = maxStringSize/2;
+ if (size <= maxStringSize || cursorPos < halfSize)
+ return 0;
+ if (cursorPos > size - halfSize)
+ return size - maxStringSize;
+ return cursorPos - halfSize;
+}
+
+static QString mapSurroundingTextToCompositor(const QString &s, int offset)
+{
+ return s.mid(offset, maxStringSize);
+}
+
+static int mapPositionToCompositor(int pos, int offset)
+{
+ return pos - offset;
+}
+
+static int mapPositionFromCompositor(int pos, int offset)
+{
+ return pos + offset;
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_input_method_event_attribute(uint32_t serial, int32_t type, int32_t start, int32_t length, const QString &value)
+{
+ if (!m_pendingInputMethodEvents.contains(serial)) {
+ qCWarning(qLcQpaInputMethods) << "Input method event with serial" << serial << "does not exist";
+ return;
+ }
+
+ int startMapped = mapPositionFromCompositor(start, m_offsetFromCompositor[serial]);
+ QList<QInputMethodEvent::Attribute> &attributes = m_pendingInputMethodEvents[serial];
+ switch (type) {
+ case QInputMethodEvent::Selection:
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), startMapped, length));
+ break;
+ case QInputMethodEvent::Cursor:
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, QColor::fromString(value)));
+ break;
+ case QInputMethodEvent::TextFormat:
+ {
+ QTextCharFormat textFormat;
+ textFormat.setProperty(QTextFormat::FontUnderline, true);
+ textFormat.setProperty(QTextFormat::TextUnderlineStyle, QTextCharFormat::SingleUnderline);
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, textFormat));
+ break;
+ }
+ case QInputMethodEvent::Language:
+ case QInputMethodEvent::Ruby:
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, value));
+ break;
+ };
+}
+
+void QWaylandTextInputMethod::sendInputState(QInputMethodQueryEvent *event, Qt::InputMethodQueries queries)
+{
+ int cursorPosition = event->value(Qt::ImCursorPosition).toInt();
+ int anchorPosition = event->value(Qt::ImAnchorPosition).toInt();
+ QString surroundingText = event->value(Qt::ImSurroundingText).toString();
+ int offset = calculateOffset(surroundingText, cursorPosition);
+
+ if (queries & Qt::ImCursorPosition)
+ update_cursor_position(mapPositionToCompositor(cursorPosition, offset));
+ if (queries & Qt::ImSurroundingText)
+ update_surrounding_text(mapSurroundingTextToCompositor(surroundingText, offset), offset);
+ if (queries & Qt::ImAnchorPosition)
+ update_anchor_position(mapPositionToCompositor(anchorPosition, offset));
+ if (queries & Qt::ImAbsolutePosition)
+ update_absolute_position(event->value(Qt::ImAbsolutePosition).toInt()); // do not map: this is the position in the whole document
+}
+
+
+void QWaylandTextInputMethod::text_input_method_v1_end_input_method_event(uint32_t serial, const QString &commitString, const QString &preeditString, int32_t replacementStart, int32_t replacementLength)
+{
+ if (!m_pendingInputMethodEvents.contains(serial)) {
+ qCWarning(qLcQpaInputMethods) << "Input method event with serial" << serial << "does not exist";
+ return;
+ }
+
+ QList<QInputMethodEvent::Attribute> attributes = m_pendingInputMethodEvents.take(serial);
+ m_offsetFromCompositor.remove(serial);
+ if (QGuiApplication::focusObject() != nullptr) {
+ QInputMethodEvent event(preeditString, attributes);
+ event.setCommitString(commitString, replacementStart, replacementLength);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+ }
+
+ // Send current state to make sure it matches
+ if (QGuiApplication::focusObject() != nullptr) {
+ QInputMethodQueryEvent event(Qt::ImCursorPosition | Qt::ImSurroundingText | Qt::ImAnchorPosition | Qt::ImAbsolutePosition);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+ sendInputState(&event);
+ }
+
+ acknowledge_input_method();
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_key(int32_t type,
+ int32_t key,
+ int32_t modifiers,
+ int32_t autoRepeat,
+ int32_t count,
+ int32_t nativeScanCode,
+ int32_t nativeVirtualKey,
+ int32_t nativeModifiers,
+ const QString &text)
+{
+ if (QGuiApplication::focusObject() != nullptr) {
+ QKeyEvent event(QKeyEvent::Type(type),
+ key,
+ Qt::KeyboardModifiers(modifiers),
+ nativeScanCode,
+ nativeVirtualKey,
+ nativeModifiers,
+ text,
+ autoRepeat,
+ count);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+ }
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_enter(struct ::wl_surface *surface)
+{
+ m_surface = surface;
+}
+
+void QWaylandTextInputMethod::text_input_method_v1_leave(struct ::wl_surface *surface)
+{
+ if (surface != m_surface) {
+ qCWarning(qLcQpaInputMethods) << "Got leave event for surface without corresponding enter";
+ } else {
+ m_surface = nullptr;
+ }
+}
+
+QWaylandInputMethodContext::QWaylandInputMethodContext(QWaylandDisplay *display)
+ : m_display(display)
+{
+}
+
+QWaylandInputMethodContext::~QWaylandInputMethodContext()
+{
+}
+
+bool QWaylandInputMethodContext::isValid() const
+{
+ return m_display->textInputMethodManager() != nullptr;
+}
+
+void QWaylandInputMethodContext::reset()
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ inputMethod->reset();
+}
+
+void QWaylandInputMethodContext::commit()
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ inputMethod->commit();
+
+ m_display->forceRoundTrip();
+}
+
+void QWaylandInputMethodContext::update(Qt::InputMethodQueries queries)
+{
+ wl_surface *currentSurface = m_currentWindow != nullptr && m_currentWindow->handle() != nullptr
+ ? static_cast<QWaylandWindow *>(m_currentWindow->handle())->wlSurface()
+ : nullptr;
+ if (currentSurface != nullptr && !inputMethodAccepted()) {
+ textInputMethod()->disable(currentSurface);
+ m_currentWindow.clear();
+ } else if (currentSurface == nullptr && inputMethodAccepted()) {
+ QWindow *window = QGuiApplication::focusWindow();
+ currentSurface = window != nullptr && window->handle() != nullptr
+ ? static_cast<QWaylandWindow *>(window->handle())->wlSurface()
+ : nullptr;
+ if (currentSurface != nullptr) {
+ textInputMethod()->disable(currentSurface);
+ m_currentWindow = window;
+ }
+ }
+
+ queries &= (Qt::ImEnabled
+ | Qt::ImHints
+ | Qt::ImCursorRectangle
+ | Qt::ImCursorPosition
+ | Qt::ImSurroundingText
+ | Qt::ImCurrentSelection
+ | Qt::ImAnchorPosition
+ | Qt::ImTextAfterCursor
+ | Qt::ImTextBeforeCursor
+ | Qt::ImPreferredLanguage);
+
+ const Qt::InputMethodQueries queriesNeedingOffset = Qt::ImCursorPosition | Qt::ImSurroundingText | Qt::ImAnchorPosition;
+ if (queries & queriesNeedingOffset)
+ queries |= queriesNeedingOffset;
+
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr && QGuiApplication::focusObject() != nullptr) {
+ QInputMethodQueryEvent event(queries);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+
+ inputMethod->start_update(int(queries));
+
+ if (queries & Qt::ImHints)
+ inputMethod->update_hints(event.value(Qt::ImHints).toInt());
+
+ if (queries & Qt::ImCursorRectangle) {
+ QRect rect = event.value(Qt::ImCursorRectangle).toRect();
+ inputMethod->update_cursor_rectangle(rect.x(), rect.y(), rect.width(), rect.height());
+ }
+
+ inputMethod->sendInputState(&event, queries);
+
+ if (queries & Qt::ImPreferredLanguage)
+ inputMethod->update_preferred_language(event.value(Qt::ImPreferredLanguage).toString());
+
+ inputMethod->end_update();
+
+ // ### Should we do a display sync here and ignore all events until it is received?
+ }
+}
+
+void QWaylandInputMethodContext::invokeAction(QInputMethod::Action action, int cursorPosition)
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ inputMethod->invoke_action(int(action), cursorPosition);
+}
+
+void QWaylandInputMethodContext::showInputPanel()
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ inputMethod->show_input_panel();
+}
+
+void QWaylandInputMethodContext::hideInputPanel()
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ inputMethod->hide_input_panel();
+}
+
+bool QWaylandInputMethodContext::isInputPanelVisible() const
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ return inputMethod->isVisible();
+ else
+ return false;
+}
+
+QRectF QWaylandInputMethodContext::keyboardRect() const
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ return inputMethod->keyboardRect();
+ else
+ return QRectF();
+}
+
+QLocale QWaylandInputMethodContext::locale() const
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ return inputMethod->locale();
+ else
+ return QLocale();
+}
+
+Qt::LayoutDirection QWaylandInputMethodContext::inputDirection() const
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod != nullptr)
+ return inputMethod->inputDirection();
+ else
+ return Qt::LeftToRight;
+}
+
+void QWaylandInputMethodContext::setFocusObject(QObject *)
+{
+ QWaylandTextInputMethod *inputMethod = textInputMethod();
+ if (inputMethod == nullptr)
+ return;
+
+ if (inputMethod->isVisible() && !inputMethodAccepted())
+ inputMethod->hide_input_panel();
+
+ QWindow *window = QGuiApplication::focusWindow();
+
+ if (m_currentWindow != nullptr && m_currentWindow->handle() != nullptr) {
+ if (m_currentWindow.data() != window || !inputMethodAccepted()) {
+ auto *surface = static_cast<QWaylandWindow *>(m_currentWindow->handle())->wlSurface();
+ if (surface)
+ inputMethod->disable(surface);
+ m_currentWindow.clear();
+ }
+ }
+
+ if (window != nullptr && window->handle() != nullptr && inputMethodAccepted()) {
+ if (m_currentWindow.data() != window) {
+ auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
+ if (surface != nullptr) {
+ inputMethod->enable(surface);
+ m_currentWindow = window;
+ }
+ }
+
+ update(Qt::ImQueryAll);
+ }
+}
+
+QWaylandTextInputMethod *QWaylandInputMethodContext::textInputMethod() const
+{
+ return m_display->defaultInputDevice() ? m_display->defaultInputDevice()->textInputMethod() : nullptr;
+}
+
+} // QtWaylandClient
+
+QT_END_NAMESPACE
+
+#include "moc_qwaylandinputmethodcontext_p.cpp"
diff --git a/src/client/qwaylandinputmethodcontext_p.h b/src/client/qwaylandinputmethodcontext_p.h
new file mode 100644
index 000000000..85ef65601
--- /dev/null
+++ b/src/client/qwaylandinputmethodcontext_p.h
@@ -0,0 +1,118 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDINPUTMETHODCONTEXT_P_H
+#define QWAYLANDINPUTMETHODCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qpa/qplatforminputcontext.h>
+#include <QtGui/qevent.h>
+#include <QtCore/qlocale.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qhash.h>
+
+#include <QtWaylandClient/private/qwayland-qt-text-input-method-unstable-v1.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+ class QWaylandDisplay;
+
+class QWaylandTextInputMethod : public QtWayland::qt_text_input_method_v1
+{
+public:
+ QWaylandTextInputMethod(QWaylandDisplay *display, struct ::qt_text_input_method_v1 *textInputMethod);
+ ~QWaylandTextInputMethod() override;
+
+ void text_input_method_v1_visible_changed(int32_t visible) override;
+ void text_input_method_v1_enter(struct ::wl_surface *surface) override;
+ void text_input_method_v1_leave(struct ::wl_surface *surface) override;
+ void text_input_method_v1_locale_changed(const QString &localeName) override;
+ void text_input_method_v1_input_direction_changed(int32_t inputDirection) override;
+ void text_input_method_v1_keyboard_rectangle_changed(wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override;
+ void text_input_method_v1_key(int32_t type, int32_t key, int32_t modifiers, int32_t autoRepeat, int32_t count, int32_t nativeScanCode, int32_t nativeVirtualKey, int32_t nativeModifiers, const QString &text) override;
+ void text_input_method_v1_start_input_method_event(uint32_t serial, int32_t surrounding_text_offset) override;
+ void text_input_method_v1_end_input_method_event(uint32_t serial, const QString &commitString, const QString &preeditString, int32_t replacementStart, int32_t replacementLength) override;
+ void text_input_method_v1_input_method_event_attribute(uint32_t serial, int32_t type, int32_t start, int32_t length, const QString &value) override;
+
+ inline bool isVisible() const
+ {
+ return m_isVisible;
+ }
+
+ inline QRectF keyboardRect() const
+ {
+ return m_keyboardRect;
+ }
+
+ inline QLocale locale() const
+ {
+ return m_locale;
+ }
+
+ inline Qt::LayoutDirection inputDirection() const
+ {
+ return m_layoutDirection;
+ }
+
+ void sendInputState(QInputMethodQueryEvent *state, Qt::InputMethodQueries queries = Qt::ImQueryInput);
+
+private:
+ QHash<int, QList<QInputMethodEvent::Attribute> > m_pendingInputMethodEvents;
+ QHash<int,int> m_offsetFromCompositor;
+
+ struct ::wl_surface *m_surface;
+
+ // Cached state
+ bool m_isVisible = false;
+ QRectF m_keyboardRect;
+ QLocale m_locale;
+ Qt::LayoutDirection m_layoutDirection;
+};
+
+class QWaylandInputMethodContext : public QPlatformInputContext
+{
+ Q_OBJECT
+public:
+ QWaylandInputMethodContext(QWaylandDisplay *display);
+ ~QWaylandInputMethodContext() override;
+
+ bool isValid() const override;
+ void reset() override;
+ void commit() override;
+ void update(Qt::InputMethodQueries) override;
+ void invokeAction(QInputMethod::Action, int cursorPosition) override;
+ void showInputPanel() override;
+ void hideInputPanel() override;
+
+ bool isInputPanelVisible() const override;
+ QRectF keyboardRect() const override;
+ QLocale locale() const override;
+ Qt::LayoutDirection inputDirection() const override;
+
+ void setFocusObject(QObject *object) override;
+
+private:
+ QWaylandTextInputMethod *textInputMethod() const;
+
+ QWaylandDisplay *m_display;
+ QPointer<QWindow> m_currentWindow;
+};
+
+} // QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDINPUTMETHODCONTEXT_P_H
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 9bdd9cc12..c5eb1e96a 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandintegration_p.h"
@@ -43,6 +7,7 @@
#include "qwaylandshmwindow_p.h"
#include "qwaylandinputdevice_p.h"
#include "qwaylandinputcontext_p.h"
+#include "qwaylandinputmethodcontext_p.h"
#include "qwaylandshmbackingstore_p.h"
#include "qwaylandnativeinterface_p.h"
#if QT_CONFIG(clipboard)
@@ -50,23 +15,27 @@
#endif
#include "qwaylanddnd_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
+#include "qwaylandplatformservices_p.h"
#include "qwaylandscreen_p.h"
+#include "qwaylandcursor_p.h"
#if defined(Q_OS_MACOS)
-# include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
-# include <QtFontDatabaseSupport/private/qfontengine_coretext_p.h>
+# include <QtGui/private/qcoretextfontdatabase_p.h>
+# include <QtGui/private/qfontengine_coretext_p.h>
#else
-# include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
+# include <QtGui/private/qgenericunixfontdatabase_p.h>
#endif
-#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
-#include <QtThemeSupport/private/qgenericunixthemes_p.h>
+#include <QtGui/private/qgenericunixeventdispatcher_p.h>
+#include <QtGui/private/qgenericunixthemes_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformcursor.h>
#include <QtGui/QSurfaceFormat>
+#if QT_CONFIG(opengl)
#include <QtGui/QOpenGLContext>
+#endif // QT_CONFIG(opengl)
#include <QSocketNotifier>
#include <qpa/qplatforminputcontextfactory_p.h>
@@ -79,19 +48,21 @@
#include "qwaylandserverbufferintegration_p.h"
#include "qwaylandserverbufferintegrationfactory_p.h"
+#include "qwaylandshellsurface_p.h"
#include "qwaylandshellintegration_p.h"
#include "qwaylandshellintegrationfactory_p.h"
#include "qwaylandinputdeviceintegration_p.h"
#include "qwaylandinputdeviceintegrationfactory_p.h"
+#include "qwaylandwindow_p.h"
#if QT_CONFIG(accessibility_atspi_bridge)
-#include <QtLinuxAccessibilitySupport/private/bridge_p.h>
+#include <QtGui/private/qspiaccessiblebridge_p.h>
#endif
#if QT_CONFIG(xkbcommon)
-#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
+#include <QtGui/private/qxkbcommon_p.h>
#endif
#if QT_CONFIG(vulkan)
@@ -103,32 +74,32 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+QWaylandIntegration *QWaylandIntegration::sInstance = nullptr;
+
QWaylandIntegration::QWaylandIntegration()
#if defined(Q_OS_MACOS)
: mFontDb(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>)
#else
: mFontDb(new QGenericUnixFontDatabase())
#endif
- , mNativeInterface(new QWaylandNativeInterface(this))
{
- initializeInputDeviceIntegration();
mDisplay.reset(new QWaylandDisplay(this));
- if (!mDisplay->isInitialized()) {
- mFailed = true;
- return;
- }
-#if QT_CONFIG(clipboard)
- mClipboard.reset(new QWaylandClipboard(mDisplay.data()));
-#endif
-#if QT_CONFIG(draganddrop)
- mDrag.reset(new QWaylandDrag(mDisplay.data()));
-#endif
+ mPlatformServices.reset(new QWaylandPlatformServices(mDisplay.data()));
- reconfigureInputContext();
+ QWaylandWindow::fixedToplevelPositions =
+ !qEnvironmentVariableIsSet("QT_WAYLAND_DISABLE_FIXED_POSITIONS");
+
+ sInstance = this;
}
QWaylandIntegration::~QWaylandIntegration()
{
+ sInstance = nullptr;
+}
+
+bool QWaylandIntegration::init()
+{
+ return mDisplay->initialize();
}
QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
@@ -153,6 +124,8 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
case WindowActivation:
return false;
+ case ScreenWindowGrabbing: // whether QScreen::grabWindow() is supported
+ return false;
default: return QPlatformIntegration::hasCapability(cap);
}
}
@@ -165,10 +138,10 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) cons
#if QT_CONFIG(vulkan)
if (window->surfaceType() == QSurface::VulkanSurface)
- return new QWaylandVulkanWindow(window);
+ return new QWaylandVulkanWindow(window, mDisplay.data());
#endif // QT_CONFIG(vulkan)
- return new QWaylandShmWindow(window);
+ return new QWaylandShmWindow(window, mDisplay.data());
}
#if QT_CONFIG(opengl)
@@ -182,7 +155,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
@@ -190,20 +163,39 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
return createUnixEventDispatcher();
}
+QPlatformNativeInterface *QWaylandIntegration::createPlatformNativeInterface()
+{
+ return new QWaylandNativeInterface(this);
+}
+
+// Support platform specific initialization
+void QWaylandIntegration::initializePlatform()
+{
+ mDisplay->initEventThread();
+
+ mNativeInterface.reset(createPlatformNativeInterface());
+ initializeInputDeviceIntegration();
+#if QT_CONFIG(clipboard)
+ mClipboard.reset(new QWaylandClipboard(mDisplay.data()));
+#endif
+#if QT_CONFIG(draganddrop)
+ mDrag.reset(new QWaylandDrag(mDisplay.data()));
+#endif
+
+ reconfigureInputContext();
+}
+
void QWaylandIntegration::initialize()
{
+ initializePlatform();
+
+ // Call this after initializing event thread for QWaylandDisplay::flushRequests()
QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests()));
QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests()));
- int fd = wl_display_get_fd(mDisplay->wl_display());
- 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
@@ -235,13 +227,6 @@ QVariant QWaylandIntegration::styleHint(StyleHint hint) const
if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration())
return mDisplay->windowManagerIntegration()->showIsFullScreen();
- switch (hint) {
- case QPlatformIntegration::FontSmoothingGamma:
- return qreal(1.0);
- default:
- break;
- }
-
return QPlatformIntegration::styleHint(hint);
}
@@ -263,7 +248,7 @@ QPlatformAccessibility *QWaylandIntegration::accessibility() const
QPlatformServices *QWaylandIntegration::services() const
{
- return mDisplay->windowManagerIntegration();
+ return mPlatformServices.data();
}
QWaylandDisplay *QWaylandIntegration::display() const
@@ -271,6 +256,14 @@ QWaylandDisplay *QWaylandIntegration::display() const
return mDisplay.data();
}
+Qt::KeyboardModifiers QWaylandIntegration::queryKeyboardModifiers() const
+{
+ if (auto *seat = mDisplay->currentInputDevice(); seat && seat->keyboardFocus()) {
+ return seat->modifiers();
+ }
+ return Qt::NoModifier;
+}
+
QList<int> QWaylandIntegration::possibleKeys(const QKeyEvent *event) const
{
if (auto *seat = mDisplay->currentInputDevice())
@@ -288,6 +281,16 @@ QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) co
return QGenericUnixTheme::createUnixTheme(name);
}
+QWaylandScreen *QWaylandIntegration::createPlatformScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id) const
+{
+ return new QWaylandScreen(waylandDisplay, version, id);
+}
+
+QWaylandCursor *QWaylandIntegration::createPlatformCursor(QWaylandDisplay *display) const
+{
+ return new QWaylandCursor(display);
+}
+
#if QT_CONFIG(vulkan)
QPlatformVulkanInstance *QWaylandIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
{
@@ -405,17 +408,11 @@ void QWaylandIntegration::initializeShellIntegration()
preferredShells = targetKeys.split(QLatin1Char(';'));
} else {
preferredShells << QLatin1String("xdg-shell");
- preferredShells << QLatin1String("xdg-shell-v6");
- QString useXdgShell = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_USE_XDG_SHELL"));
- if (!useXdgShell.isEmpty() && useXdgShell != QLatin1String("0")) {
- qWarning() << "QT_WAYLAND_USE_XDG_SHELL is deprecated, "
- "please specify the shell using QT_WAYLAND_SHELL_INTEGRATION instead";
- preferredShells << QLatin1String("xdg-shell-v5");
- }
preferredShells << QLatin1String("wl-shell") << QLatin1String("ivi-shell");
+ preferredShells << QLatin1String("qt-shell");
}
- for (const QString &preferredShell : qAsConst(preferredShells)) {
+ for (const QString &preferredShell : std::as_const(preferredShells)) {
mShellIntegration.reset(createShellIntegration(preferredShell));
if (mShellIntegration) {
qCDebug(lcQpaWayland, "Using the '%s' shell integration", qPrintable(preferredShell));
@@ -427,9 +424,11 @@ 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)
+QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id) const
{
if (mInputDeviceIntegration) {
return mInputDeviceIntegration->createInputDevice(display, version, id);
@@ -465,30 +464,44 @@ void QWaylandIntegration::reconfigureInputContext()
return;
}
- const QString &requested = QPlatformInputContextFactory::requested();
- if (requested == QLatin1String("qtvirtualkeyboard"))
+ auto requested = QPlatformInputContextFactory::requested();
+ if (requested.contains(QLatin1String("qtvirtualkeyboard")))
qCWarning(lcQpaWayland) << "qtvirtualkeyboard currently is not supported at client-side,"
- " use QT_IM_MODULE=qtvirtualkeyboard at compositor-side.";
+ " use QT_IM_MODULES=qtvirtualkeyboard at compositor-side.";
- if (requested.isNull())
- mInputContext.reset(new QWaylandInputContext(mDisplay.data()));
- else
- mInputContext.reset(QPlatformInputContextFactory::create(requested));
+ if (mDisplay->isWaylandInputContextRequested()
+ && !requested.contains(QLatin1String(WAYLAND_IM_KEY)))
+ requested.append(QLatin1String(WAYLAND_IM_KEY));
const QString defaultInputContext(QStringLiteral("compose"));
- if ((!mInputContext || !mInputContext->isValid()) && requested != defaultInputContext)
- mInputContext.reset(QPlatformInputContextFactory::create(defaultInputContext));
+ if (!requested.contains(defaultInputContext))
+ requested.append(defaultInputContext);
+
+ for (const QString &imKey : requested) {
+ if (imKey == QLatin1String(WAYLAND_IM_KEY)) {
+ Q_ASSERT(mDisplay->isWaylandInputContextRequested());
+ if (mDisplay->textInputMethodManager() != nullptr)
+ mInputContext.reset(new QWaylandInputMethodContext(mDisplay.data()));
+ else if (mDisplay->textInputManagerv1() != nullptr
+ || mDisplay->textInputManagerv2() != nullptr
+ || mDisplay->textInputManagerv3() != nullptr)
+ mInputContext.reset(new QWaylandInputContext(mDisplay.data()));
+ } else {
+ mInputContext.reset(QPlatformInputContextFactory::create(imKey));
+ }
+
+ if (mInputContext && mInputContext->isValid())
+ break;
+ }
#if QT_CONFIG(xkbcommon)
QXkbCommon::setXkbContext(mInputContext.data(), mDisplay->xkbContext());
+ if (QWaylandInputContext* waylandInput = qobject_cast<QWaylandInputContext*>(mInputContext.get())) {
+ waylandInput->setXkbContext(mDisplay->xkbContext());
+ }
#endif
- // Even if compositor-side input context handling has been requested, we fallback to
- // client-side handling if compositor does not provide the text-input extension. This
- // is why we need to check here which input context actually is being used.
- mDisplay->mUsingInputContextFromCompositor = qobject_cast<QWaylandInputContext *>(mInputContext.data());
-
- qCDebug(lcQpaWayland) << "using input method:" << inputContext()->metaObject()->className();
+ qCDebug(lcQpaWayland) << "using input method:" << (inputContext() ? inputContext()->metaObject()->className() : "<none>");
}
QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &integrationName)
@@ -501,6 +514,21 @@ QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QStr
}
}
+void QWaylandIntegration::reset()
+{
+ mServerBufferIntegration.reset();
+ mServerBufferIntegrationInitialized = false;
+
+ mInputDeviceIntegration.reset();
+
+ mClientBufferIntegration.reset();
+ mClientBufferIntegrationInitialized = false;
+}
+
+void QWaylandIntegration::setApplicationBadge(qint64 number)
+{
+ mPlatformServices->setApplicationBadge(number);
+}
}
QT_END_NAMESPACE
diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h
index ff70ae25d..f26cc3d29 100644
--- a/src/client/qwaylandintegration_p.h
+++ b/src/client/qwaylandintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINTEGRATION_WAYLAND_H
#define QPLATFORMINTEGRATION_WAYLAND_H
@@ -55,6 +19,7 @@
#include <qpa/qplatformintegration.h>
#include <QtCore/QScopedPointer>
#include <QtCore/QMutex>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -67,14 +32,19 @@ class QWaylandServerBufferIntegration;
class QWaylandShellIntegration;
class QWaylandInputDeviceIntegration;
class QWaylandInputDevice;
+class QWaylandScreen;
+class QWaylandCursor;
+class QWaylandPlatformServices;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandIntegration : public QPlatformIntegration
+class Q_WAYLANDCLIENT_EXPORT QWaylandIntegration : public QPlatformIntegration
{
public:
QWaylandIntegration();
~QWaylandIntegration() override;
- bool hasFailed() { return mFailed; }
+ static QWaylandIntegration *instance() { return sInstance; }
+
+ bool init();
bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
@@ -107,6 +77,8 @@ public:
QWaylandDisplay *display() const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+
QList<int> possibleKeys(const QKeyEvent *event) const override;
QStringList themeNames() const override;
@@ -117,7 +89,11 @@ public:
QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
#endif
- QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, int version, uint32_t id);
+ void setApplicationBadge(qint64 number) override;
+
+ virtual QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, int version, uint32_t id) const;
+ virtual QWaylandScreen *createPlatformScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id) const;
+ virtual QWaylandCursor *createPlatformCursor(QWaylandDisplay *display) const;
virtual QWaylandClientBufferIntegration *clientBufferIntegration() const;
virtual QWaylandServerBufferIntegration *serverBufferIntegration() const;
@@ -125,19 +101,25 @@ public:
void reconfigureInputContext();
-private:
+protected:
// NOTE: mDisplay *must* be destructed after mDrag and mClientBufferIntegration
// and mShellIntegration.
// Do not move this definition into the private section at the bottom.
QScopedPointer<QWaylandDisplay> mDisplay;
protected:
+ void reset();
+ virtual QPlatformNativeInterface *createPlatformNativeInterface();
+
QScopedPointer<QWaylandClientBufferIntegration> mClientBufferIntegration;
QScopedPointer<QWaylandServerBufferIntegration> mServerBufferIntegration;
QScopedPointer<QWaylandShellIntegration> mShellIntegration;
QScopedPointer<QWaylandInputDeviceIntegration> mInputDeviceIntegration;
+ QScopedPointer<QPlatformInputContext> mInputContext;
+
private:
+ void initializePlatform();
void initializeClientBufferIntegration();
void initializeServerBufferIntegration();
void initializeShellIntegration();
@@ -152,16 +134,17 @@ private:
QScopedPointer<QPlatformDrag> mDrag;
#endif
QScopedPointer<QPlatformNativeInterface> mNativeInterface;
- QScopedPointer<QPlatformInputContext> mInputContext;
#if QT_CONFIG(accessibility)
mutable QScopedPointer<QPlatformAccessibility> mAccessibility;
#endif
- bool mFailed = false;
+ QScopedPointer<QWaylandPlatformServices> mPlatformServices;
QMutex mClientBufferInitLock;
bool mClientBufferIntegrationInitialized = false;
bool mServerBufferIntegrationInitialized = false;
bool mShellIntegrationInitialized = false;
+ static QWaylandIntegration *sInstance;
+
friend class QWaylandDisplay;
};
diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp
index bf54a1a00..e1586d244 100644
--- a/src/client/qwaylandnativeinterface.cpp
+++ b/src/client/qwaylandnativeinterface.cpp
@@ -1,53 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandnativeinterface_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylandshellintegration_p.h"
#include "qwaylandsubsurface_p.h"
-#include "qwaylandextendedsurface_p.h"
#include "qwaylandintegration_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandinputdevice_p.h"
+#include <QtCore/private/qnativeinterface_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QScreen>
#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
@@ -55,8 +19,6 @@
#include <QtWaylandClient/private/qwaylandvulkanwindow_p.h>
#endif
-#include <QtPlatformHeaders/qwaylandwindowfunctions.h>
-
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -72,8 +34,10 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re
if (lowerCaseResource == "display" || lowerCaseResource == "wl_display" || lowerCaseResource == "nativedisplay")
return m_integration->display()->wl_display();
- if (lowerCaseResource == "compositor")
- return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
+ if (lowerCaseResource == "compositor") {
+ if (auto compositor = m_integration->display()->compositor())
+ return compositor->object();
+ }
if (lowerCaseResource == "server_buffer_integration")
return m_integration->serverBufferIntegration();
@@ -100,7 +64,65 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re
return touch->wl_touch();
return nullptr;
}
+ if (lowerCaseResource == "serial")
+ return reinterpret_cast<void *>(quintptr(m_integration->display()->defaultInputDevice()->serial()));
+
+ return nullptr;
+}
+
+wl_display *QtWaylandClient::QWaylandNativeInterface::display() const
+{
+ return m_integration->display()->wl_display();
+}
+
+wl_compositor *QtWaylandClient::QWaylandNativeInterface::compositor() const
+{
+ if (auto compositor = m_integration->display()->compositor())
+ return compositor->object();
+ return nullptr;
+}
+
+wl_seat *QtWaylandClient::QWaylandNativeInterface::seat() const
+{
+ if (auto inputDevice = m_integration->display()->defaultInputDevice()) {
+ return inputDevice->wl_seat();
+ }
+ return nullptr;
+}
+
+wl_keyboard *QtWaylandClient::QWaylandNativeInterface::keyboard() const
+{
+ if (auto inputDevice = m_integration->display()->defaultInputDevice())
+ if (auto keyboard = inputDevice->keyboard())
+ return keyboard->wl_keyboard();
+ return nullptr;
+}
+
+wl_pointer *QtWaylandClient::QWaylandNativeInterface::pointer() const
+{
+ if (auto inputDevice = m_integration->display()->defaultInputDevice())
+ if (auto pointer = inputDevice->pointer())
+ return pointer->wl_pointer();
+ return nullptr;
+}
+
+wl_touch *QtWaylandClient::QWaylandNativeInterface::touch() const
+{
+ if (auto inputDevice = m_integration->display()->defaultInputDevice())
+ if (auto touch = inputDevice->touch())
+ return touch->wl_touch();
+ return nullptr;
+}
+
+uint QtWaylandClient::QWaylandNativeInterface::lastInputSerial() const
+{
+ return m_integration->display()->lastInputSerial();
+}
+wl_seat *QtWaylandClient::QWaylandNativeInterface::lastInputSeat() const
+{
+ if (auto inputDevice = m_integration->display()->lastInputDevice())
+ return inputDevice->wl_seat();
return nullptr;
}
@@ -110,8 +132,10 @@ void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourc
if (lowerCaseResource == "display")
return m_integration->display()->wl_display();
- if (lowerCaseResource == "compositor")
- return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
+ if (lowerCaseResource == "compositor") {
+ if (auto compositor = m_integration->display()->compositor())
+ return compositor->object();
+ }
if (lowerCaseResource == "surface") {
QWaylandWindow *w = static_cast<QWaylandWindow*>(window->handle());
return w ? w->wlSurface() : nullptr;
@@ -124,13 +148,14 @@ void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourc
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();
+ return static_cast<QWaylandVulkanWindow *>(window->handle())->vkSurface();
}
}
#endif
- if (auto shellIntegration = m_integration->shellIntegration())
- return shellIntegration->nativeResourceForWindow(resourceString, window);
+ QWaylandWindow *platformWindow = static_cast<QWaylandWindow *>(window->handle());
+ if (platformWindow && platformWindow->shellIntegration())
+ return platformWindow->shellIntegration()->nativeResourceForWindow(resourceString, window);
return nullptr;
}
@@ -139,7 +164,7 @@ void *QWaylandNativeInterface::nativeResourceForScreen(const QByteArray &resourc
{
QByteArray lowerCaseResource = resourceString.toLower();
- if (lowerCaseResource == "output")
+ if (lowerCaseResource == "output" && !screen->handle()->isPlaceholder())
return ((QWaylandScreen *) screen->handle())->output();
return nullptr;
@@ -165,6 +190,17 @@ void *QWaylandNativeInterface::nativeResourceForContext(const QByteArray &resour
}
#endif // opengl
+QPlatformNativeInterface::NativeResourceForWindowFunction QWaylandNativeInterface::nativeResourceFunctionForWindow(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+
+ if (lowerCaseResource == "setmargins") {
+ return NativeResourceForWindowFunction(reinterpret_cast<void *>(setWindowMargins));
+ }
+
+ return nullptr;
+}
+
QVariantMap QWaylandNativeInterface::windowProperties(QPlatformWindow *window) const
{
QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(window);
@@ -194,42 +230,10 @@ void QWaylandNativeInterface::emitWindowPropertyChanged(QPlatformWindow *window,
emit windowPropertyChanged(window,name);
}
-QFunctionPointer QWaylandNativeInterface::platformFunction(const QByteArray &resource) const
+void QWaylandNativeInterface::setWindowMargins(QWindow *window, const QMargins &margins)
{
- if (resource == QWaylandWindowFunctions::setSyncIdentifier()) {
- return QFunctionPointer(setSync);
- } else if (resource == QWaylandWindowFunctions::setDeSyncIdentifier()) {
- return QFunctionPointer(setDeSync);
- } else if (resource == QWaylandWindowFunctions::isSyncIdentifier()) {
- return QFunctionPointer(isSync);
- }
- return nullptr;
-}
-
-
-void QWaylandNativeInterface::setSync(QWindow *window)
-{
- QWaylandWindow *ww = static_cast<QWaylandWindow*>(window->handle());
- if (ww->subSurfaceWindow()) {
- ww->subSurfaceWindow()->setSync();
- }
-}
-
-void QWaylandNativeInterface::setDeSync(QWindow *window)
-{
- QWaylandWindow *ww = static_cast<QWaylandWindow*>(window->handle());
- if (ww->subSurfaceWindow()) {
- ww->subSurfaceWindow()->setDeSync();
- }
-}
-
-bool QWaylandNativeInterface::isSync(QWindow *window)
-{
- QWaylandWindow *ww = static_cast<QWaylandWindow*>(window->handle());
- if (ww->subSurfaceWindow()) {
- return ww->subSurfaceWindow()->isSync();
- }
- return false;
+ QWaylandWindow *wlWindow = static_cast<QWaylandWindow*>(window->handle());
+ wlWindow->setCustomMargins(margins);
}
}
diff --git a/src/client/qwaylandnativeinterface_p.h b/src/client/qwaylandnativeinterface_p.h
index 3de80eb6a..ce8c6bec3 100644
--- a/src/client/qwaylandnativeinterface_p.h
+++ b/src/client/qwaylandnativeinterface_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 QWAYLANDNATIVEINTERFACE_H
-#define QWAYLANDNATIVEINTERFACE_H
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDNATIVEINTERFACE_P_H
+#define QWAYLANDNATIVEINTERFACE_P_H
//
// W A R N I N G
@@ -55,15 +19,21 @@
#include <qpa/qplatformnativeinterface.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qhash.h>
+#include <QtGui/qguiapplication_platform.h>
QT_BEGIN_NAMESPACE
+class QMargins;
+
namespace QtWaylandClient {
class QWaylandIntegration;
class QWaylandScreen;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandNativeInterface : public QPlatformNativeInterface
+class Q_WAYLANDCLIENT_EXPORT QWaylandNativeInterface : public QPlatformNativeInterface,
+ public QNativeInterface::QWaylandApplication
{
public:
QWaylandNativeInterface(QWaylandIntegration *integration);
@@ -75,6 +45,7 @@ public:
#if QT_CONFIG(opengl)
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override;
#endif
+ NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource) override;
QVariantMap windowProperties(QPlatformWindow *window) const override;
QVariant windowProperty(QPlatformWindow *window, const QString &name) const override;
QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const override;
@@ -82,19 +53,25 @@ public:
void emitWindowPropertyChanged(QPlatformWindow *window, const QString &name);
- QFunctionPointer platformFunction(const QByteArray &resource) const override;
+ // QWaylandApplication interface
+ wl_display *display() const override;
+ wl_compositor *compositor() const override;
+ wl_seat *seat() const override;
+ wl_keyboard *keyboard() const override;
+ wl_pointer *pointer() const override;
+ wl_touch *touch() const override;
+ uint lastInputSerial() const override;
+ wl_seat *lastInputSeat() const override;
private:
+ static void setWindowMargins(QWindow *window, const QMargins &margins);
+
QWaylandIntegration *m_integration = nullptr;
QHash<QPlatformWindow*, QVariantMap> m_windowProperties;
-
- static void setSync(QWindow *window);
- static void setDeSync(QWindow *window);
- static bool isSync(QWindow *window);
};
}
QT_END_NAMESPACE
-#endif // QWAYLANDNATIVEINTERFACE_H
+#endif // QWAYLANDNATIVEINTERFACE_P_H
diff --git a/src/client/qwaylandplatformservices.cpp b/src/client/qwaylandplatformservices.cpp
new file mode 100644
index 000000000..14556d282
--- /dev/null
+++ b/src/client/qwaylandplatformservices.cpp
@@ -0,0 +1,50 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandplatformservices_p.h"
+#include "qwaylandwindow_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandshellsurface_p.h"
+#include "qwaylandwindowmanagerintegration_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandPlatformServices::QWaylandPlatformServices(QWaylandDisplay *display)
+ : m_display(display) { }
+
+bool QWaylandPlatformServices::openUrl(const QUrl &url)
+{
+ if (auto windowManagerIntegration = m_display->windowManagerIntegration()) {
+ windowManagerIntegration->openUrl(url);
+ return true;
+ }
+ return QGenericUnixServices::openUrl(url);
+}
+
+bool QWaylandPlatformServices::openDocument(const QUrl &url)
+{
+ if (auto windowManagerIntegration = m_display->windowManagerIntegration()) {
+ windowManagerIntegration->openUrl(url);
+ return true;
+ }
+ return QGenericUnixServices::openDocument(url);
+}
+
+QString QWaylandPlatformServices::portalWindowIdentifier(QWindow *window)
+{
+ if (window && window->handle()) {
+ auto shellSurface = static_cast<QWaylandWindow *>(window->handle())->shellSurface();
+ if (shellSurface) {
+ const QString handle = shellSurface->externWindowHandle();
+ return QLatin1String("wayland:") + handle;
+ }
+ }
+ return QString();
+}
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#include "moc_qwaylandplatformservices_p.cpp"
diff --git a/src/client/qwaylandplatformservices_p.h b/src/client/qwaylandplatformservices_p.h
new file mode 100644
index 000000000..6106a9018
--- /dev/null
+++ b/src/client/qwaylandplatformservices_p.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDPLATFORMSERVICES_H
+#define QWAYLANDPLATFORMSERVICES_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+
+#include <QtGui/private/qgenericunixservices_p.h>
+
+#include <QtWaylandClient/private/qwayland-qt-windowmanager.h>
+#include <QtWaylandClient/qtwaylandclientglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandPlatformServices : public QGenericUnixServices
+{
+public:
+ explicit QWaylandPlatformServices(QWaylandDisplay *waylandDisplay);
+
+ bool openUrl(const QUrl &url) override;
+ bool openDocument(const QUrl &url) override;
+ QString portalWindowIdentifier(QWindow *window) override;
+
+private:
+ QWaylandDisplay *m_display;
+};
+
+QT_END_NAMESPACE
+
+} // namespace QtWaylandClient
+
+#endif // QWAYLANDPLATFORMSERVICES_H
diff --git a/src/client/qwaylandpointergestures.cpp b/src/client/qwaylandpointergestures.cpp
new file mode 100644
index 000000000..87079d800
--- /dev/null
+++ b/src/client/qwaylandpointergestures.cpp
@@ -0,0 +1,211 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandpointergestures_p.h"
+#include "qwaylanddisplay_p.h"
+#include "qwaylandinputdevice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandPointerGestures::QWaylandPointerGestures(QWaylandDisplay *display, uint id, uint version)
+ : zwp_pointer_gestures_v1(display->wl_registry(), id, qMin(version, uint(1)))
+{
+}
+
+QWaylandPointerGestures::~QWaylandPointerGestures() noexcept
+{
+ if (version() >= ZWP_POINTER_GESTURES_V1_RELEASE_SINCE_VERSION)
+ release();
+ else
+ zwp_pointer_gestures_v1_destroy(object());
+}
+
+QWaylandPointerGestureSwipe *
+ QWaylandPointerGestures::createPointerGestureSwipe(QWaylandInputDevice *device)
+{
+ return new QWaylandPointerGestureSwipe(device);
+}
+
+QWaylandPointerGesturePinch *
+ QWaylandPointerGestures::createPointerGesturePinch(QWaylandInputDevice *device)
+{
+ return new QWaylandPointerGesturePinch(device);
+}
+
+QWaylandPointerGestureSwipe::QWaylandPointerGestureSwipe(QWaylandInputDevice *p)
+ : mParent(p)
+{
+}
+
+QWaylandPointerGestureSwipe::~QWaylandPointerGestureSwipe()
+{
+ destroy();
+}
+
+void QWaylandPointerGestureSwipe::zwp_pointer_gesture_swipe_v1_begin(uint32_t serial, uint32_t time,
+ struct ::wl_surface *surface,
+ uint32_t fingers)
+{
+#ifndef QT_NO_GESTURES
+ mFocus = QWaylandWindow::fromWlSurface(surface);
+ if (!mFocus) {
+ return;
+ }
+ mParent->mSerial = serial;
+ mFingers = fingers;
+
+ const auto* pointer = mParent->pointer();
+
+ qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_begin @ "
+ << pointer->mSurfacePos << "fingers" << fingers;
+
+ auto e = QWaylandPointerGestureSwipeEvent(mFocus, Qt::GestureStarted, time,
+ pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
+ QPointF());
+
+ mFocus->handleSwipeGesture(mParent, e);
+#endif
+}
+
+void QWaylandPointerGestureSwipe::zwp_pointer_gesture_swipe_v1_update(uint32_t time,
+ wl_fixed_t dx, wl_fixed_t dy)
+{
+#ifndef QT_NO_GESTURES
+ if (!mFocus) {
+ return;
+ }
+ const auto* pointer = mParent->pointer();
+
+ const QPointF delta = QPointF(wl_fixed_to_double(dx), wl_fixed_to_double(dy));
+ qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_update @ "
+ << pointer->mSurfacePos << "delta" << delta;
+
+ auto e = QWaylandPointerGestureSwipeEvent(mFocus, Qt::GestureUpdated, time,
+ pointer->mSurfacePos, pointer->mGlobalPos, mFingers, delta);
+
+ mFocus->handleSwipeGesture(mParent, e);
+#endif
+}
+
+void QWaylandPointerGestureSwipe::zwp_pointer_gesture_swipe_v1_end(uint32_t serial, uint32_t time,
+ int32_t cancelled)
+{
+#ifndef QT_NO_GESTURES
+ if (!mFocus) {
+ return;
+ }
+ mParent->mSerial = serial;
+ const auto* pointer = mParent->pointer();
+
+ qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_end @ "
+ << pointer->mSurfacePos << (cancelled ? "CANCELED" : "");
+
+ auto gestureType = cancelled ? Qt::GestureFinished : Qt::GestureCanceled;
+
+ auto e = QWaylandPointerGestureSwipeEvent(mFocus, gestureType, time,
+ pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
+ QPointF());
+
+ mFocus->handleSwipeGesture(mParent, e);
+
+ mFocus.clear();
+ mFingers = 0;
+#endif
+}
+
+QWaylandPointerGesturePinch::QWaylandPointerGesturePinch(QWaylandInputDevice *p)
+ : mParent(p)
+{
+}
+
+QWaylandPointerGesturePinch::~QWaylandPointerGesturePinch()
+{
+ destroy();
+}
+
+void QWaylandPointerGesturePinch::zwp_pointer_gesture_pinch_v1_begin(uint32_t serial, uint32_t time,
+ struct ::wl_surface *surface,
+ uint32_t fingers)
+{
+#ifndef QT_NO_GESTURES
+ mFocus = QWaylandWindow::fromWlSurface(surface);
+ if (!mFocus) {
+ return;
+ }
+ mParent->mSerial = serial;
+ mFingers = fingers;
+ mLastScale = 1;
+ const auto* pointer = mParent->pointer();
+
+ qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_pinch_v1_begin @ "
+ << pointer->mSurfacePos << "fingers" << fingers;
+
+ auto e = QWaylandPointerGesturePinchEvent(mFocus, Qt::GestureStarted, time,
+ pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
+ QPointF(), 0, 0);
+
+ mFocus->handlePinchGesture(mParent, e);
+#endif
+}
+
+void QWaylandPointerGesturePinch::zwp_pointer_gesture_pinch_v1_update(uint32_t time,
+ wl_fixed_t dx, wl_fixed_t dy,
+ wl_fixed_t scale,
+ wl_fixed_t rotation)
+{
+#ifndef QT_NO_GESTURES
+ if (!mFocus) {
+ return;
+ }
+ const auto* pointer = mParent->pointer();
+
+ const qreal rscale = wl_fixed_to_double(scale);
+ const qreal rot = wl_fixed_to_double(rotation);
+ const QPointF delta = QPointF(wl_fixed_to_double(dx), wl_fixed_to_double(dy));
+ qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_pinch_v1_update @ "
+ << pointer->mSurfacePos << "delta" << delta
+ << "scale" << mLastScale << "->" << rscale
+ << "delta" << rscale - mLastScale << "rot" << rot;
+
+ auto e = QWaylandPointerGesturePinchEvent(mFocus, Qt::GestureUpdated, time,
+ pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
+ delta, rscale - mLastScale, rot);
+
+ mFocus->handlePinchGesture(mParent, e);
+
+ mLastScale = rscale;
+#endif
+}
+
+void QWaylandPointerGesturePinch::zwp_pointer_gesture_pinch_v1_end(uint32_t serial, uint32_t time,
+ int32_t cancelled)
+{
+#ifndef QT_NO_GESTURES
+ if (!mFocus) {
+ return;
+ }
+ mParent->mSerial = serial;
+ const auto* pointer = mParent->pointer();
+
+ qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_end @ "
+ << pointer->mSurfacePos << (cancelled ? "CANCELED" : "");
+
+ auto gestureType = cancelled ? Qt::GestureFinished : Qt::GestureCanceled;
+
+ auto e = QWaylandPointerGesturePinchEvent(mFocus, gestureType, time,
+ pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
+ QPointF(), 0, 0);
+
+ mFocus->handlePinchGesture(mParent, e);
+
+ mFocus.clear();
+ mFingers = 0;
+ mLastScale = 1;
+#endif
+}
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandpointergestures_p.h b/src/client/qwaylandpointergestures_p.h
new file mode 100644
index 000000000..06ee4a6ed
--- /dev/null
+++ b/src/client/qwaylandpointergestures_p.h
@@ -0,0 +1,115 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDPOINTERGESTURES_P_H
+#define QWAYLANDPOINTERGESTURES_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-pointer-gestures-unstable-v1.h>
+
+#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+class QWaylandWindow;
+class QWaylandInputDevice;
+class QWaylandPointerGestureSwipe;
+class QWaylandPointerGesturePinch;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandPointerGestures : public QtWayland::zwp_pointer_gestures_v1
+{
+public:
+ explicit QWaylandPointerGestures(QWaylandDisplay *display, uint id, uint version);
+ ~QWaylandPointerGestures();
+
+ QWaylandPointerGestureSwipe *createPointerGestureSwipe(QWaylandInputDevice *device);
+ QWaylandPointerGesturePinch *createPointerGesturePinch(QWaylandInputDevice *device);
+};
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandPointerGestureSwipe :
+ public QtWayland::zwp_pointer_gesture_swipe_v1
+{
+public:
+ QWaylandPointerGestureSwipe(QWaylandInputDevice *p);
+ ~QWaylandPointerGestureSwipe() override;
+
+ void zwp_pointer_gesture_swipe_v1_begin(uint32_t serial,
+ uint32_t time,
+ struct ::wl_surface *surface,
+ uint32_t fingers) override;
+
+ void zwp_pointer_gesture_swipe_v1_update(uint32_t time,
+ wl_fixed_t dx,
+ wl_fixed_t dy) override;
+
+ void zwp_pointer_gesture_swipe_v1_end(uint32_t serial,
+ uint32_t time,
+ int32_t cancelled) override;
+
+ struct ::zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1()
+ {
+ return QtWayland::zwp_pointer_gesture_swipe_v1::object();
+ }
+
+ QWaylandInputDevice *mParent = nullptr;
+ QPointer<QWaylandWindow> mFocus;
+ uint mFingers = 0;
+};
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandPointerGesturePinch :
+ public QtWayland::zwp_pointer_gesture_pinch_v1
+{
+public:
+ QWaylandPointerGesturePinch(QWaylandInputDevice *p);
+ ~QWaylandPointerGesturePinch() override;
+
+ void zwp_pointer_gesture_pinch_v1_begin(uint32_t serial,
+ uint32_t time,
+ struct ::wl_surface *surface,
+ uint32_t fingers) override;
+
+ void zwp_pointer_gesture_pinch_v1_update(uint32_t time,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t scale,
+ wl_fixed_t rotation) override;
+
+ void zwp_pointer_gesture_pinch_v1_end(uint32_t serial,
+ uint32_t time,
+ int32_t cancelled) override;
+
+ struct ::zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1()
+ {
+ return QtWayland::zwp_pointer_gesture_pinch_v1::object();
+ }
+
+ QWaylandInputDevice *mParent = nullptr;
+ QPointer<QWaylandWindow> mFocus;
+ uint mFingers = 0;
+
+ // We need to convert between absolute scale provided by wayland/libinput and zoom deltas
+ // that Qt expects. This stores the scale of the last pinch event or 1.0 if there was none.
+ qreal mLastScale = 1;
+};
+
+} // namespace QtWaylandClient
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDPOINTERGESTURES_P_H
diff --git a/src/client/qwaylandprimaryselectionv1.cpp b/src/client/qwaylandprimaryselectionv1.cpp
index 832f96780..d72b8f749 100644
--- a/src/client/qwaylandprimaryselectionv1.cpp
+++ b/src/client/qwaylandprimaryselectionv1.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandprimaryselectionv1_p.h"
#include "qwaylandinputdevice_p.h"
@@ -54,11 +18,11 @@ QWaylandPrimarySelectionDeviceManagerV1::QWaylandPrimarySelectionDeviceManagerV1
: zwp_primary_selection_device_manager_v1(display->wl_registry(), id, qMin(version, uint(1)))
, m_display(display)
{
- // Create devices for all seats.
- // This only works if we get the global before all devices
- const auto seats = m_display->inputDevices();
- for (auto *seat : seats)
- seat->setPrimarySelectionDevice(createDevice(seat));
+}
+
+QWaylandPrimarySelectionDeviceManagerV1::~QWaylandPrimarySelectionDeviceManagerV1()
+{
+ destroy();
}
QWaylandPrimarySelectionDeviceV1 *QWaylandPrimarySelectionDeviceManagerV1::createDevice(QWaylandInputDevice *seat)
@@ -160,7 +124,8 @@ void QWaylandPrimarySelectionSourceV1::zwp_primary_selection_source_v1_send(cons
action.sa_flags = 0;
sigaction(SIGPIPE, &action, &oldAction);
- write(fd, content.constData(), size_t(content.size()));
+ ssize_t unused = write(fd, content.constData(), size_t(content.size()));
+ Q_UNUSED(unused);
sigaction(SIGPIPE, &oldAction, nullptr);
}
close(fd);
@@ -169,3 +134,5 @@ void QWaylandPrimarySelectionSourceV1::zwp_primary_selection_source_v1_send(cons
} // namespace QtWaylandClient
QT_END_NAMESPACE
+
+#include "moc_qwaylandprimaryselectionv1_p.cpp"
diff --git a/src/client/qwaylandprimaryselectionv1_p.h b/src/client/qwaylandprimaryselectionv1_p.h
index 3f0a42a67..f39aec526 100644
--- a/src/client/qwaylandprimaryselectionv1_p.h
+++ b/src/client/qwaylandprimaryselectionv1_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDPRIMARYSELECTIONV1_P_H
#define QWAYLANDPRIMARYSELECTIONV1_P_H
@@ -73,6 +37,7 @@ class QWaylandPrimarySelectionDeviceManagerV1 : public QtWayland::zwp_primary_se
{
public:
explicit QWaylandPrimarySelectionDeviceManagerV1(QWaylandDisplay *display, uint id, uint version);
+ ~QWaylandPrimarySelectionDeviceManagerV1();
QWaylandPrimarySelectionDeviceV1 *createDevice(QWaylandInputDevice *seat);
QWaylandDisplay *display() const { return m_display; }
@@ -96,7 +61,7 @@ private:
QScopedPointer<QWaylandMimeData> m_mimeData;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandPrimarySelectionSourceV1 : public QObject, public QtWayland::zwp_primary_selection_source_v1
+class Q_WAYLANDCLIENT_EXPORT QWaylandPrimarySelectionSourceV1 : public QObject, public QtWayland::zwp_primary_selection_source_v1
{
Q_OBJECT
public:
@@ -105,7 +70,7 @@ public:
QMimeData *mimeData() const { return m_mimeData; }
-signals:
+Q_SIGNALS:
void cancelled();
protected:
@@ -113,7 +78,6 @@ protected:
void zwp_primary_selection_source_v1_cancelled() override { emit cancelled(); }
private:
- QWaylandDisplay *m_display = nullptr;
QMimeData *m_mimeData = nullptr;
};
diff --git a/src/client/qwaylandqtkey.cpp b/src/client/qwaylandqtkey.cpp
index 192619738..079a03e0d 100644
--- a/src/client/qwaylandqtkey.cpp
+++ b/src/client/qwaylandqtkey.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandqtkey_p.h"
#include "qwaylandinputdevice_p.h"
@@ -51,6 +15,11 @@ QWaylandQtKeyExtension::QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_
{
}
+QWaylandQtKeyExtension::~QWaylandQtKeyExtension()
+{
+ zqt_key_v1_destroy(object());
+}
+
void QWaylandQtKeyExtension::zqt_key_v1_key(struct wl_surface *surface,
uint32_t time,
uint32_t type,
diff --git a/src/client/qwaylandqtkey_p.h b/src/client/qwaylandqtkey_p.h
index 117c44a6d..1544a0166 100644
--- a/src/client/qwaylandqtkey_p.h
+++ b/src/client/qwaylandqtkey_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDQTKEY_H
#define QWAYLANDQTKEY_H
@@ -55,6 +19,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtWaylandClient/private/qwayland-qt-key-unstable-v1.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -62,10 +27,11 @@ namespace QtWaylandClient {
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandQtKeyExtension : public QtWayland::zqt_key_v1
+class Q_WAYLANDCLIENT_EXPORT QWaylandQtKeyExtension : public QtWayland::zqt_key_v1
{
public:
QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_t id);
+ ~QWaylandQtKeyExtension();
private:
QWaylandDisplay *m_display = nullptr;
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index e70796832..d51e8c6a0 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandscreen_p.h"
@@ -53,8 +17,18 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandDisplay* display, uint id, uint version)
+ : QtWayland::zxdg_output_manager_v1(display->wl_registry(), id, qMin(3u, version))
+{
+}
+
+QWaylandXdgOutputManagerV1::~QWaylandXdgOutputManagerV1()
+{
+ destroy();
+}
+
QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id)
- : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2))
+ : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 3))
, m_outputId(id)
, mWaylandDisplay(waylandDisplay)
, mOutputName(QStringLiteral("Screen%1").arg(id))
@@ -66,7 +40,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin
qCWarning(lcQpaWayland) << "wl_output done event not supported by compositor,"
<< "QScreen may not work correctly";
mWaylandDisplay->forceRoundTrip(); // Give the compositor a chance to send geometry etc.
- mOutputDone = true; // Fake the done event
+ mProcessedEvents |= OutputDoneEvent; // Fake the done event
maybeInitialize();
}
}
@@ -75,16 +49,32 @@ QWaylandScreen::~QWaylandScreen()
{
if (zxdg_output_v1::isInitialized())
zxdg_output_v1::destroy();
+ if (wl_output::version() >= WL_OUTPUT_RELEASE_SINCE_VERSION)
+ wl_output::release();
+ else
+ wl_output_destroy(wl_output::object());
+}
+
+uint QWaylandScreen::requiredEvents() const
+{
+ uint ret = OutputDoneEvent;
+
+ if (mWaylandDisplay->xdgOutputManager()) {
+ if (mWaylandDisplay->xdgOutputManager()->version() >= 2)
+ ret |= XdgOutputNameEvent;
+
+ if (mWaylandDisplay->xdgOutputManager()->version() < 3)
+ ret |= XdgOutputDoneEvent;
+ }
+ return ret;
}
void QWaylandScreen::maybeInitialize()
{
Q_ASSERT(!mInitialized);
- if (!mOutputDone)
- return;
-
- if (mWaylandDisplay->xdgOutputManager() && !mXdgOutputDone)
+ const uint requiredEvents = this->requiredEvents();
+ if ((mProcessedEvents & requiredEvents) != requiredEvents)
return;
mInitialized = true;
@@ -95,7 +85,7 @@ void QWaylandScreen::maybeInitialize()
updateXdgOutputProperties();
}
-void QWaylandScreen::initXdgOutput(QtWayland::zxdg_output_manager_v1 *xdgOutputManager)
+void QWaylandScreen::initXdgOutput(QWaylandXdgOutputManagerV1 *xdgOutputManager)
{
Q_ASSERT(xdgOutputManager);
if (zxdg_output_v1::isInitialized())
@@ -165,22 +155,29 @@ QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const
{
QList<QPlatformScreen *> list;
const QList<QWaylandScreen*> screens = mWaylandDisplay->screens();
- list.reserve(screens.count());
- for (QWaylandScreen *screen : qAsConst(screens)) {
+ auto *placeholder = mWaylandDisplay->placeholderScreen();
+
+ list.reserve(screens.size() + (placeholder ? 1 : 0));
+
+ for (QWaylandScreen *screen : std::as_const(screens)) {
if (screen->screen())
list << screen;
}
+
+ if (placeholder)
+ list << placeholder;
+
return list;
}
-void QWaylandScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
+QWindow *QWaylandScreen::topLevelAt(const QPoint & pos) const
{
- const auto allWindows = QGuiApplication::allWindows();
- for (QWindow *window : allWindows) {
- QWaylandWindow *w = static_cast<QWaylandWindow *>(window->handle());
- if (w && w->waylandScreen() == this)
- w->setOrientationMask(mask);
+ if (QWaylandWindow::fixedToplevelPositions) {
+ Q_UNUSED(pos);
+ return nullptr;
}
+
+ return QPlatformScreen::topLevelAt(pos);
}
Qt::ScreenOrientation QWaylandScreen::orientation() const
@@ -210,9 +207,37 @@ QPlatformCursor *QWaylandScreen::cursor() const
}
#endif // QT_CONFIG(cursor)
-QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
+QPlatformScreen::SubpixelAntialiasingType QWaylandScreen::subpixelAntialiasingTypeHint() const
+{
+ QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
+ if (type == QPlatformScreen::Subpixel_None) {
+ switch (mSubpixel) {
+ case wl_output::subpixel_unknown:
+ case wl_output::subpixel_none:
+ type = QPlatformScreen::Subpixel_None;
+ break;
+ case wl_output::subpixel_horizontal_rgb:
+ type = QPlatformScreen::Subpixel_RGB;
+ break;
+ case wl_output::subpixel_horizontal_bgr:
+ type = QPlatformScreen::Subpixel_BGR;
+ break;
+ case wl_output::subpixel_vertical_rgb:
+ type = QPlatformScreen::Subpixel_VRGB;
+ break;
+ case wl_output::subpixel_vertical_bgr:
+ type = QPlatformScreen::Subpixel_VBGR;
+ break;
+ }
+ }
+ return type;
+}
+
+QWaylandScreen *QWaylandScreen::waylandScreenFromWindow(QWindow *window)
{
QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(window);
+ if (platformScreen->isPlaceholder())
+ return nullptr;
return static_cast<QWaylandScreen *>(platformScreen);
}
@@ -223,6 +248,35 @@ QWaylandScreen *QWaylandScreen::fromWlOutput(::wl_output *output)
return nullptr;
}
+Qt::ScreenOrientation QWaylandScreen::toScreenOrientation(int wlTransform,
+ Qt::ScreenOrientation fallback) const
+{
+ auto orientation = fallback;
+ bool isPortrait = mGeometry.height() > mGeometry.width();
+ switch (wlTransform) {
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation;
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation;
+ break;
+ // Ignore these ones, at least for now
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ break;
+ }
+
+ return orientation;
+}
+
void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
{
if (!(flags & WL_OUTPUT_MODE_CURRENT))
@@ -243,11 +297,10 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y,
const QString &model,
int32_t transform)
{
- Q_UNUSED(subpixel);
-
mManufacturer = make;
mModel = model;
+ mSubpixel = subpixel;
mTransform = transform;
mPhysicalSize = QSize(width, height);
@@ -261,39 +314,25 @@ void QWaylandScreen::output_scale(int32_t factor)
void QWaylandScreen::output_done()
{
- mOutputDone = true;
- if (mInitialized)
+ mProcessedEvents |= OutputDoneEvent;
+
+ if (mInitialized) {
updateOutputProperties();
- else
+ if (zxdg_output_v1::isInitialized())
+ updateXdgOutputProperties();
+ } else {
maybeInitialize();
+ }
}
void QWaylandScreen::updateOutputProperties()
{
if (mTransform >= 0) {
- bool isPortrait = mGeometry.height() > mGeometry.width();
- switch (mTransform) {
- case WL_OUTPUT_TRANSFORM_NORMAL:
- m_orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation;
- break;
- case WL_OUTPUT_TRANSFORM_90:
- m_orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation;
- break;
- case WL_OUTPUT_TRANSFORM_180:
- m_orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation;
- break;
- case WL_OUTPUT_TRANSFORM_270:
- m_orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation;
- break;
- // Ignore these ones, at least for now
- case WL_OUTPUT_TRANSFORM_FLIPPED:
- case WL_OUTPUT_TRANSFORM_FLIPPED_90:
- case WL_OUTPUT_TRANSFORM_FLIPPED_180:
- case WL_OUTPUT_TRANSFORM_FLIPPED_270:
- break;
+ auto newOrientation = toScreenOrientation(mTransform, m_orientation);
+ if (m_orientation != newOrientation) {
+ m_orientation = newOrientation;
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
}
-
- QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
mTransform = -1;
}
@@ -316,7 +355,10 @@ void QWaylandScreen::zxdg_output_v1_logical_size(int32_t width, int32_t height)
void QWaylandScreen::zxdg_output_v1_done()
{
- mXdgOutputDone = true;
+ if (Q_UNLIKELY(mWaylandDisplay->xdgOutputManager()->version() >= 3))
+ qWarning(lcQpaWayland) << "zxdg_output_v1.done received on version 3 or newer, this is most likely a bug in the compositor";
+
+ mProcessedEvents |= XdgOutputDoneEvent;
if (mInitialized)
updateXdgOutputProperties();
else
@@ -325,7 +367,11 @@ void QWaylandScreen::zxdg_output_v1_done()
void QWaylandScreen::zxdg_output_v1_name(const QString &name)
{
+ if (Q_UNLIKELY(mInitialized))
+ qWarning(lcQpaWayland) << "zxdg_output_v1.name received after output has been initialized, this is most likely a bug in the compositor";
+
mOutputName = name;
+ mProcessedEvents |= XdgOutputNameEvent;
}
void QWaylandScreen::updateXdgOutputProperties()
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index e9e07d9cd..ce3df3099 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSCREEN_H
#define QWAYLANDSCREEN_H
@@ -52,11 +16,12 @@
//
#include <qpa/qplatformscreen.h>
+#include <QtGui/qscreen_platform.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtWaylandClient/private/qwayland-wayland.h>
#include <QtWaylandClient/private/qwayland-xdg-output-unstable-v1.h>
-
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,16 @@ namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandCursor;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandScreen : public QPlatformScreen, QtWayland::wl_output, QtWayland::zxdg_output_v1
+class Q_WAYLANDCLIENT_EXPORT QWaylandXdgOutputManagerV1 : public QtWayland::zxdg_output_manager_v1 {
+public:
+ QWaylandXdgOutputManagerV1(QWaylandDisplay *display, uint id, uint version);
+ ~QWaylandXdgOutputManagerV1();
+};
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandScreen : public QPlatformScreen,
+ QtWayland::wl_output,
+ QtWayland::zxdg_output_v1,
+ public QNativeInterface::QWaylandScreen
{
public:
QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id);
@@ -73,7 +47,7 @@ public:
void maybeInitialize();
- void initXdgOutput(QtWayland::zxdg_output_manager_v1 *xdgOutputManager);
+ void initXdgOutput(QWaylandXdgOutputManagerV1 *xdgOutputManager);
QWaylandDisplay *display() const;
@@ -89,7 +63,7 @@ public:
QDpi logicalDpi() const override;
QList<QPlatformScreen *> virtualSiblings() const override;
- void setOrientationUpdateMask(Qt::ScreenOrientations mask) override;
+ QWindow *topLevelAt(const QPoint &point) const override;
Qt::ScreenOrientation orientation() const override;
int scale() const;
@@ -102,13 +76,28 @@ public:
QPlatformCursor *cursor() const override;
#endif
+ SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override;
+
uint32_t outputId() const { return m_outputId; }
- ::wl_output *output() { return QtWayland::wl_output::object(); }
+ ::wl_output *output() const override
+ {
+ return const_cast<::wl_output *>(QtWayland::wl_output::object());
+ }
static QWaylandScreen *waylandScreenFromWindow(QWindow *window);
static QWaylandScreen *fromWlOutput(::wl_output *output);
-private:
+ Qt::ScreenOrientation toScreenOrientation(int wlTransform,
+ Qt::ScreenOrientation fallback) const;
+
+protected:
+ enum Event : uint {
+ XdgOutputDoneEvent = 0x1,
+ OutputDoneEvent = 0x2,
+ XdgOutputNameEvent = 0x4,
+ };
+ uint requiredEvents() const;
+
void output_mode(uint32_t flags, int width, int height, int refresh) override;
void output_geometry(int32_t x, int32_t y,
int32_t width, int32_t height,
@@ -136,18 +125,14 @@ private:
int mScale = 1;
int mDepth = 32;
int mRefreshRate = 60000;
+ int mSubpixel = -1;
int mTransform = -1;
QImage::Format mFormat = QImage::Format_ARGB32_Premultiplied;
QSize mPhysicalSize;
QString mOutputName;
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
- bool mOutputDone = false;
- bool mXdgOutputDone = false;
+ uint mProcessedEvents = 0;
bool mInitialized = false;
-
-#if QT_CONFIG(cursor)
- QScopedPointer<QWaylandCursor> mWaylandCursor;
-#endif
};
}
diff --git a/src/client/qwaylandshellsurface.cpp b/src/client/qwaylandshellsurface.cpp
index 91cc2c2c0..fde1e1d3f 100644
--- a/src/client/qwaylandshellsurface.cpp
+++ b/src/client/qwaylandshellsurface.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandshellsurface_p.h"
#include "qwaylandwindow_p.h"
-#include "qwaylandextendedsurface_p.h"
+#include "qwaylandinputdevice_p.h"
QT_BEGIN_NAMESPACE
@@ -57,10 +21,66 @@ void QWaylandShellSurface::setWindowFlags(Qt::WindowFlags flags)
void QWaylandShellSurface::sendProperty(const QString &name, const QVariant &value)
{
- Q_UNUSED(name)
- Q_UNUSED(value)
+ Q_UNUSED(name);
+ Q_UNUSED(value);
}
+QPlatformWindow *QWaylandShellSurface::platformWindow()
+{
+ return m_window;
+}
+
+wl_surface *QWaylandShellSurface::wlSurface()
+{
+ return m_window ? m_window->wlSurface() : nullptr;
+}
+
+void QWaylandShellSurface::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
+{
+ m_window->resizeFromApplyConfigure(sizeWithMargins, offset);
+}
+
+void QWaylandShellSurface::repositionFromApplyConfigure(const QPoint &position)
+{
+ m_window->repositionFromApplyConfigure(position);
+}
+
+void QWaylandShellSurface::setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins)
+{
+ m_window->setGeometryFromApplyConfigure(globalPosition, sizeWithMargins);
+}
+
+void QWaylandShellSurface::applyConfigureWhenPossible()
+{
+ m_window->applyConfigureWhenPossible();
+}
+
+void QWaylandShellSurface::handleActivationChanged(bool activated)
+{
+ if (activated)
+ m_window->display()->handleWindowActivated(m_window);
+ else
+ m_window->display()->handleWindowDeactivated(m_window);
+}
+
+uint32_t QWaylandShellSurface::getSerial(QWaylandInputDevice *inputDevice)
+{
+ return inputDevice->serial();
+}
+
+void QWaylandShellSurface::setXdgActivationToken(const QString &token)
+{
+ Q_UNUSED(token);
+ qCWarning(lcQpaWayland) << "setXdgActivationToken not implemented" << token;
+}
+
+void QWaylandShellSurface::requestXdgActivationToken(quint32 serial)
+{
+ Q_UNUSED(serial);
+ Q_EMIT m_window->xdgActivationTokenCreated({});
+}
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandshellsurface_p.cpp"
diff --git a/src/client/qwaylandshellsurface_p.h b/src/client/qwaylandshellsurface_p.h
index f5f202d08..8632efd04 100644
--- a/src/client/qwaylandshellsurface_p.h
+++ b/src/client/qwaylandshellsurface_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHELLSURFACE_H
#define QWAYLANDSHELLSURFACE_H
@@ -53,28 +17,32 @@
#include <QtCore/QSize>
#include <QObject>
-
-#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QPoint>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtCore/private/qglobal_p.h>
+
+#include <any>
+
+struct wl_surface;
QT_BEGIN_NAMESPACE
class QVariant;
class QWindow;
+class QPlatformWindow;
namespace QtWaylandClient {
class QWaylandWindow;
class QWaylandInputDevice;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShellSurface : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandShellSurface : public QObject
{
Q_OBJECT
public:
explicit QWaylandShellSurface(QWaylandWindow *window);
~QWaylandShellSurface() override {}
- virtual void resize(QWaylandInputDevice * /*inputDevice*/, Qt::Edges /*edges*/) {}
-
+ virtual bool resize(QWaylandInputDevice *, Qt::Edges) { return false; }
virtual bool move(QWaylandInputDevice *) { return false; }
virtual bool showWindowMenu(QWaylandInputDevice *seat) { Q_UNUSED(seat); return false; }
virtual void setTitle(const QString & /*title*/) {}
@@ -87,19 +55,47 @@ public:
virtual void raise() {}
virtual void lower() {}
- virtual void setContentOrientationMask(Qt::ScreenOrientations orientation) { Q_UNUSED(orientation) }
+ virtual void setContentOrientationMask(Qt::ScreenOrientations orientation) { Q_UNUSED(orientation); }
virtual void sendProperty(const QString &name, const QVariant &value);
- inline QWaylandWindow *window() { return m_window; }
-
virtual void applyConfigure() {}
virtual void requestWindowStates(Qt::WindowStates states) {Q_UNUSED(states);}
virtual bool wantsDecorations() const { return false; }
+ virtual QMargins serverSideFrameMargins() const { return QMargins(); }
virtual void propagateSizeHints() {}
virtual void setWindowGeometry(const QRect &rect) { Q_UNUSED(rect); }
+ virtual void setWindowPosition(const QPoint &position) { Q_UNUSED(position); }
+
+ virtual bool requestActivate() { return false; }
+ virtual bool requestActivateOnShow() { return false; }
+ virtual void setXdgActivationToken(const QString &token);
+ virtual void requestXdgActivationToken(quint32 serial);
+
+ virtual void setAlertState(bool enabled) { Q_UNUSED(enabled); }
+ virtual bool isAlertState() const { return false; }
+
+ virtual QString externWindowHandle() { return QString(); }
+
+ inline QWaylandWindow *window() { return m_window; }
+ QPlatformWindow *platformWindow();
+ struct wl_surface *wlSurface();
+
+ virtual std::any surfaceRole() const { return std::any(); };
+
+ virtual void attachPopup(QWaylandShellSurface *popup) { Q_UNUSED(popup); }
+ virtual void detachPopup(QWaylandShellSurface *popup) { Q_UNUSED(popup); }
+
+protected:
+ void resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset = {0, 0});
+ void repositionFromApplyConfigure(const QPoint &position);
+ void setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins);
+ void applyConfigureWhenPossible();
+ void handleActivationChanged(bool activated);
+
+ static uint32_t getSerial(QWaylandInputDevice *inputDevice);
private:
QWaylandWindow *m_window = nullptr;
diff --git a/src/client/qwaylandshm.cpp b/src/client/qwaylandshm.cpp
index e94357bb5..9ee7a96bc 100644
--- a/src/client/qwaylandshm.cpp
+++ b/src/client/qwaylandshm.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics Inc, author: <mikko.levonmaa@lge.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Inc, author: <mikko.levonmaa@lge.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtWaylandClient/private/qwaylandshm_p.h>
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
@@ -52,7 +16,7 @@ QWaylandShm::QWaylandShm(QWaylandDisplay *display, int version, uint32_t id)
QWaylandShm::~QWaylandShm()
{
-
+ wl_shm_destroy(object());
}
void QWaylandShm::shm_format(uint32_t format)
diff --git a/src/client/qwaylandshm_p.h b/src/client/qwaylandshm_p.h
index 639effa16..eb4a90c12 100644
--- a/src/client/qwaylandshm_p.h
+++ b/src/client/qwaylandshm_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 LG Electronics Inc, author: <mikko.levonmaa@lge.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 LG Electronics Inc, author: <mikko.levonmaa@lge.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHM_H
#define QWAYLANDSHM_H
@@ -51,11 +15,12 @@
// We mean it.
//
-#include <QVector>
#include <QImage>
+#include <QList>
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -63,7 +28,7 @@ namespace QtWaylandClient {
class QWaylandDisplay;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShm : public QtWayland::wl_shm
+class Q_WAYLANDCLIENT_EXPORT QWaylandShm : public QtWayland::wl_shm
{
public:
@@ -81,7 +46,7 @@ protected:
void shm_format(uint32_t format) override;
private:
- QVector<uint32_t> m_formats;
+ QList<uint32_t> m_formats;
};
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index 9b5971a21..d77c548a0 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandshmbackingstore_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylandsubsurface_p.h"
@@ -47,10 +11,12 @@
#include <QtCore/qstandardpaths.h>
#include <QtCore/qtemporaryfile.h>
#include <QtGui/QPainter>
+#include <QtGui/QTransform>
#include <QMutexLocker>
#include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
+#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -60,6 +26,19 @@
# ifndef MFD_CLOEXEC
# define MFD_CLOEXEC 0x0001U
# endif
+# ifndef MFD_ALLOW_SEALING
+# define MFD_ALLOW_SEALING 0x0002U
+# endif
+// from bits/fcntl-linux.h
+# ifndef F_ADD_SEALS
+# define F_ADD_SEALS 1033
+# endif
+# ifndef F_SEAL_SEAL
+# define F_SEAL_SEAL 0x0001
+# endif
+# ifndef F_SEAL_SHRINK
+# define F_SEAL_SHRINK 0x0002
+# endif
#endif
QT_BEGIN_NAMESPACE
@@ -67,14 +46,17 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
- const QSize &size, QImage::Format format, int scale)
+ const QSize &size, QImage::Format format, qreal scale)
+ : mDirtyRegion(QRect(QPoint(0, 0), size / scale))
{
int stride = size.width() * 4;
int alloc = stride * size.height();
int fd = -1;
#ifdef SYS_memfd_create
- fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC);
+ fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ if (fd >= 0)
+ fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
#endif
QScopedPointer<QFile> filePointer;
@@ -89,6 +71,7 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
file->open(fd, QIODevice::ReadWrite | QIODevice::Unbuffered, QFile::AutoCloseHandle);
filePointer.reset(file);
}
+ // NOTE beginPaint assumes a new buffer be all zeroes, which QFile::resize does.
if (!filePointer->isOpen() || !filePointer->resize(alloc)) {
qWarning("QWaylandShmBuffer: failed: %s", qUtf8Printable(filePointer->errorString()));
return;
@@ -107,7 +90,7 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
QWaylandShm* shm = display->shm();
wl_shm_format wl_format = shm->formatFrom(format);
mImage = QImage(data, size.width(), size.height(), stride, format);
- mImage.setDevicePixelRatio(qreal(scale));
+ mImage.setDevicePixelRatio(scale);
mShmPool = wl_shm_create_pool(shm->object(), fd, alloc);
init(wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
@@ -125,7 +108,7 @@ QWaylandShmBuffer::~QWaylandShmBuffer(void)
QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &marginsIn)
{
- QMargins margins = marginsIn * int(mImage.devicePixelRatio());
+ QMargins margins = marginsIn * mImage.devicePixelRatio();
if (!margins.isNull() && margins != mMargins) {
if (mMarginsImage) {
@@ -151,11 +134,22 @@ 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)
{
-
+ QObject::connect(mDisplay, &QWaylandDisplay::connected, window, [this]() {
+ auto copy = mBuffers;
+ // clear available buffers so we create new ones
+ // actual deletion is deferred till after resize call so we can copy
+ // contents from the back buffer
+ mBuffers.clear();
+ mFrontBuffer = nullptr;
+ // recreateBackBufferIfNeeded always resets mBackBuffer
+ if (mRequestedSize.isValid() && waylandWindow())
+ recreateBackBufferIfNeeded();
+ qDeleteAll(copy);
+ });
}
QWaylandShmBackingStore::~QWaylandShmBackingStore()
@@ -174,14 +168,29 @@ QPaintDevice *QWaylandShmBackingStore::paintDevice()
return contentSurface();
}
+void QWaylandShmBackingStore::updateDirtyStates(const QRegion &region)
+{
+ // Update dirty state of buffers based on what was painted. The back buffer will
+ // not be dirty since we already painted on it, while other buffers will become dirty.
+ for (QWaylandShmBuffer *b : std::as_const(mBuffers)) {
+ if (b != mBackBuffer)
+ b->dirtyRegion() += region;
+ }
+}
+
void QWaylandShmBackingStore::beginPaint(const QRegion &region)
{
mPainting = true;
- ensureSize();
+ waylandWindow()->setBackingStore(this);
+ const bool bufferWasRecreated = recreateBackBufferIfNeeded();
- waylandWindow()->setCanResize(false);
+ const QMargins margins = windowDecorationMargins();
+ updateDirtyStates(region.translated(margins.left(), margins.top()));
- if (mBackBuffer->image()->hasAlphaChannel()) {
+ // Although undocumented, QBackingStore::beginPaint expects the painted region
+ // to be cleared before use if the window has a surface format with an alpha.
+ // Fresh QWaylandShmBuffer are already cleared, so we don't need to clear those.
+ if (!bufferWasRecreated && mBackBuffer->image()->hasAlphaChannel()) {
QPainter p(paintDevice());
p.setCompositionMode(QPainter::CompositionMode_Source);
const QColor blank = Qt::transparent;
@@ -195,14 +204,6 @@ void QWaylandShmBackingStore::endPaint()
mPainting = false;
if (mPendingFlush)
flush(window(), mPendingRegion, QPoint());
- waylandWindow()->setCanResize(true);
-}
-
-void QWaylandShmBackingStore::ensureSize()
-{
- waylandWindow()->setBackingStore(this);
- waylandWindow()->createDecoration();
- resize(mRequestedSize);
}
void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
@@ -241,8 +242,10 @@ void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
mRequestedSize = size;
}
-QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
+QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size, bool &bufferWasRecreated)
{
+ bufferWasRecreated = false;
+
const auto copy = mBuffers; // remove when ported to vector<unique_ptr> + remove_if
for (QWaylandShmBuffer *b : copy) {
if (!b->busy()) {
@@ -261,40 +264,61 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
if (mBuffers.size() < MAX_BUFFERS) {
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
QWaylandShmBuffer *b = new QWaylandShmBuffer(mDisplay, size, format, waylandWindow()->scale());
+ bufferWasRecreated = true;
mBuffers.push_front(b);
return b;
}
return nullptr;
}
-void QWaylandShmBackingStore::resize(const QSize &size)
+bool QWaylandShmBackingStore::recreateBackBufferIfNeeded()
{
+ bool bufferWasRecreated = false;
QMargins margins = windowDecorationMargins();
- int scale = waylandWindow()->scale();
- QSize sizeWithMargins = (size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom())) * scale;
+ qreal scale = waylandWindow()->scale();
+ const QSize sizeWithMargins = (mRequestedSize + QSize(margins.left() + margins.right(), margins.top() + margins.bottom())) * scale;
// We look for a free buffer to draw into. If the buffer is not the last buffer we used,
- // that is mBackBuffer, and the size is the same we memcpy the old content into the new
+ // that is mBackBuffer, and the size is the same we copy the damaged content into the new
// buffer so that QPainter is happy to find the stuff it had drawn before. If the new
// buffer has a different size it needs to be redrawn completely anyway, and if the buffer
// is the same the stuff is there already.
// You can exercise the different codepaths with weston, switching between the gl and the
// pixman renderer. With the gl renderer release events are sent early so we can effectively
// run single buffered, while with the pixman renderer we have to use two.
- QWaylandShmBuffer *buffer = getBuffer(sizeWithMargins);
+ QWaylandShmBuffer *buffer = getBuffer(sizeWithMargins, bufferWasRecreated);
while (!buffer) {
qCDebug(lcWaylandBackingstore, "QWaylandShmBackingStore: stalling waiting for a buffer to be released from the compositor...");
mDisplay->blockingReadEvents();
- buffer = getBuffer(sizeWithMargins);
+ buffer = getBuffer(sizeWithMargins, bufferWasRecreated);
}
qsizetype oldSizeInBytes = mBackBuffer ? mBackBuffer->image()->sizeInBytes() : 0;
qsizetype newSizeInBytes = buffer->image()->sizeInBytes();
// mBackBuffer may have been deleted here but if so it means its size was different so we wouldn't copy it anyway
- if (mBackBuffer != buffer && oldSizeInBytes == newSizeInBytes)
- memcpy(buffer->image()->bits(), mBackBuffer->image()->constBits(), newSizeInBytes);
+ if (mBackBuffer != buffer && oldSizeInBytes == newSizeInBytes) {
+ Q_ASSERT(mBackBuffer);
+ const QImage *sourceImage = mBackBuffer->image();
+ QImage *targetImage = buffer->image();
+
+ QPainter painter(targetImage);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+
+ // Let painter operate in device pixels, to make it easier to compare coordinates
+ const qreal sourceDevicePixelRatio = sourceImage->devicePixelRatio();
+ const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
+ painter.scale(1.0 / targetDevicePixelRatio, 1.0 / targetDevicePixelRatio);
+
+ for (const QRect &rect : buffer->dirtyRegion()) {
+ QRectF sourceRect(QPointF(rect.topLeft()) * sourceDevicePixelRatio,
+ QSizeF(rect.size()) * sourceDevicePixelRatio);
+ QRectF targetRect(QPointF(rect.topLeft()) * targetDevicePixelRatio,
+ QSizeF(rect.size()) * targetDevicePixelRatio);
+ painter.drawImage(targetRect, *sourceImage, sourceRect);
+ }
+ }
mBackBuffer = buffer;
@@ -307,6 +331,10 @@ void QWaylandShmBackingStore::resize(const QSize &size)
if (windowDecoration() && window()->isVisible() && oldSizeInBytes != newSizeInBytes)
windowDecoration()->update();
+
+ buffer->dirtyRegion() = QRegion();
+
+ return bufferWasRecreated;
}
QImage *QWaylandShmBackingStore::entireSurface() const
@@ -328,9 +356,10 @@ void QWaylandShmBackingStore::updateDecorations()
qreal dp = sourceImage.devicePixelRatio();
int dpWidth = int(sourceImage.width() / dp);
int dpHeight = int(sourceImage.height() / dp);
- QMatrix sourceMatrix;
+ QTransform sourceMatrix;
sourceMatrix.scale(dp, dp);
QRect target; // needs to be in device independent pixels
+ QRegion dirtyRegion;
//Top
target.setX(0);
@@ -338,16 +367,19 @@ void QWaylandShmBackingStore::updateDecorations()
target.setWidth(dpWidth);
target.setHeight(windowDecorationMargins().top());
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
+ dirtyRegion += target;
//Left
target.setWidth(windowDecorationMargins().left());
target.setHeight(dpHeight);
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
+ dirtyRegion += target;
//Right
target.setX(dpWidth - windowDecorationMargins().right());
target.setWidth(windowDecorationMargins().right());
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
+ dirtyRegion += target;
//Bottom
target.setX(0);
@@ -355,6 +387,9 @@ void QWaylandShmBackingStore::updateDecorations()
target.setWidth(dpWidth);
target.setHeight(windowDecorationMargins().bottom());
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
+ dirtyRegion += target;
+
+ updateDirtyStates(dirtyRegion);
}
QWaylandAbstractDecoration *QWaylandShmBackingStore::windowDecoration() const
diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h
index 8a85cd7f3..6d276bf7b 100644
--- a/src/client/qwaylandshmbackingstore_p.h
+++ b/src/client/qwaylandshmbackingstore_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHMBACKINGSTORE_H
#define QWAYLANDSHMBACKINGSTORE_H
@@ -68,33 +32,35 @@ class QWaylandDisplay;
class QWaylandAbstractDecoration;
class QWaylandWindow;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer {
+class Q_WAYLANDCLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer {
public:
QWaylandShmBuffer(QWaylandDisplay *display,
- const QSize &size, QImage::Format format, int scale = 1);
+ const QSize &size, QImage::Format format, qreal scale = 1);
~QWaylandShmBuffer() override;
QSize size() const override { return mImage.size(); }
int scale() const override { return int(mImage.devicePixelRatio()); }
QImage *image() { return &mImage; }
QImage *imageInsideMargins(const QMargins &margins);
+
+ QRegion &dirtyRegion() { return mDirtyRegion; }
private:
QImage mImage;
struct wl_shm_pool *mShmPool = nullptr;
QMargins mMargins;
QImage *mMarginsImage = nullptr;
+ QRegion mDirtyRegion;
};
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingStore
+class Q_WAYLANDCLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingStore
{
public:
- QWaylandShmBackingStore(QWindow *window);
+ QWaylandShmBackingStore(QWindow *window, QWaylandDisplay *display);
~QWaylandShmBackingStore() override;
QPaintDevice *paintDevice() override;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
void resize(const QSize &size, const QRegion &staticContents) override;
- void resize(const QSize &size);
void beginPaint(const QRegion &region) override;
void endPaint() override;
@@ -103,7 +69,7 @@ public:
QMargins windowDecorationMargins() const;
QImage *entireSurface() const;
QImage *contentSurface() const;
- void ensureSize();
+ bool recreateBackBufferIfNeeded();
QWaylandWindow *waylandWindow() const;
void iterateBuffer();
@@ -113,8 +79,9 @@ public:
#endif
private:
+ void updateDirtyStates(const QRegion &region);
void updateDecorations();
- QWaylandShmBuffer *getBuffer(const QSize &size);
+ QWaylandShmBuffer *getBuffer(const QSize &size, bool &bufferWasRecreated);
QWaylandDisplay *mDisplay = nullptr;
std::list<QWaylandShmBuffer *> mBuffers;
diff --git a/src/client/qwaylandshmwindow.cpp b/src/client/qwaylandshmwindow.cpp
index 52833803d..8fecad178 100644
--- a/src/client/qwaylandshmwindow.cpp
+++ b/src/client/qwaylandshmwindow.cpp
@@ -1,56 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandshmwindow_p.h"
#include "qwaylandbuffer_p.h"
-#include <QtCore/QVector>
-
#include <QtCore/QDebug>
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..f11df5e47 100644
--- a/src/client/qwaylandshmwindow_p.h
+++ b/src/client/qwaylandshmwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHMWINDOW_H
#define QWAYLANDSHMWINDOW_H
@@ -58,10 +22,10 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow
+class Q_WAYLANDCLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow
{
public:
- QWaylandShmWindow(QWindow *window);
+ QWaylandShmWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandShmWindow() override;
WindowType windowType() const override;
diff --git a/src/client/qwaylandsubsurface.cpp b/src/client/qwaylandsubsurface.cpp
index 2ff966cbc..a0afd06ed 100644
--- a/src/client/qwaylandsubsurface.cpp
+++ b/src/client/qwaylandsubsurface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandsubsurface_p.h"
diff --git a/src/client/qwaylandsubsurface_p.h b/src/client/qwaylandsubsurface_p.h
index 76da10b24..7600c5807 100644
--- a/src/client/qwaylandsubsurface_p.h
+++ b/src/client/qwaylandsubsurface_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSUBSURFACE_H
#define QWAYLANDSUBSURFACE_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
#include <QtCore/qmutex.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
@@ -64,7 +28,7 @@ namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandWindow;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandSubSurface : public QtWayland::wl_subsurface
+class Q_WAYLANDCLIENT_EXPORT QWaylandSubSurface : public QtWayland::wl_subsurface
{
public:
QWaylandSubSurface(QWaylandWindow *window, QWaylandWindow *parent, ::wl_subsurface *subsurface);
diff --git a/src/client/qwaylandsurface.cpp b/src/client/qwaylandsurface.cpp
index c35f01b56..274fdda82 100644
--- a/src/client/qwaylandsurface.cpp
+++ b/src/client/qwaylandsurface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandsurface_p.h"
#include "qwaylanddisplay_p.h"
@@ -51,6 +15,7 @@ QWaylandSurface::QWaylandSurface(QWaylandDisplay *display)
: wl_surface(display->createSurface(this))
{
connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandSurface::handleScreenRemoved);
+ connect(qApp, &QGuiApplication::screenAdded, this, &QWaylandSurface::screensChanged);
}
QWaylandSurface::~QWaylandSurface()
@@ -60,7 +25,14 @@ QWaylandSurface::~QWaylandSurface()
QWaylandScreen *QWaylandSurface::oldestEnteredScreen()
{
- return m_screens.value(0, nullptr);
+ for (auto *screen : std::as_const(m_screens)) {
+ // only report valid screens
+ // we can have some ouptuts waiting for xdg output information
+ // that are valid QPlatformScreens, but not valid QScreens
+ if (screen->screen())
+ return screen;
+ }
+ return nullptr;
}
QWaylandSurface *QWaylandSurface::fromWlSurface(::wl_surface *surface)
@@ -72,8 +44,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();
}
@@ -117,6 +93,24 @@ void QWaylandSurface::surface_leave(wl_output *output)
emit screensChanged();
}
+void QWaylandSurface::surface_preferred_buffer_scale(int32_t scale)
+{
+ if (m_preferredBufferScale == scale)
+ return;
+ m_preferredBufferScale = scale;
+ Q_EMIT preferredBufferScaleChanged();
+}
+
+void QWaylandSurface::surface_preferred_buffer_transform(uint32_t transform)
+{
+ if (m_preferredBufferTransform == transform)
+ return;
+ m_preferredBufferTransform = static_cast<wl_output_transform>(transform);
+ Q_EMIT preferredBufferTransformChanged();
+}
+
} // namespace QtWaylandClient
QT_END_NAMESPACE
+
+#include "moc_qwaylandsurface_p.cpp"
diff --git a/src/client/qwaylandsurface_p.h b/src/client/qwaylandsurface_p.h
index 541010934..41860297e 100644
--- a/src/client/qwaylandsurface_p.h
+++ b/src/client/qwaylandsurface_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSURFACE_P_H
#define QWAYLANDSURFACE_P_H
@@ -54,6 +18,7 @@
#include <QtGui/QScreen>
#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -71,21 +36,29 @@ public:
~QWaylandSurface() override;
QWaylandScreen *oldestEnteredScreen();
QWaylandWindow *waylandWindow() const { return m_window; }
+ std::optional<int32_t> preferredBufferScale() const { return m_preferredBufferScale; }
+ std::optional<wl_output_transform> preferredBufferTransform() const { return m_preferredBufferTransform; }
static QWaylandSurface *fromWlSurface(::wl_surface *surface);
-signals:
+Q_SIGNALS:
void screensChanged();
+ void preferredBufferScaleChanged();
+ void preferredBufferTransformChanged();
-private slots:
+private Q_SLOTS:
void handleScreenRemoved(QScreen *qScreen);
protected:
void surface_enter(struct ::wl_output *output) override;
void surface_leave(struct ::wl_output *output) override;
+ void surface_preferred_buffer_scale(int32_t scale) override;
+ void surface_preferred_buffer_transform(uint32_t transform) override;
- QVector<QWaylandScreen *> m_screens; //As seen by wl_surface.enter/leave events. Chronological order.
+ QList<QWaylandScreen *> m_screens; //As seen by wl_surface.enter/leave events. Chronological order.
QWaylandWindow *m_window = nullptr;
+ std::optional<int32_t> m_preferredBufferScale;
+ std::optional<wl_output_transform> m_preferredBufferTransform;
friend class QWaylandWindow; // TODO: shouldn't need to be friends
};
diff --git a/src/client/qwaylandtabletv2.cpp b/src/client/qwaylandtabletv2.cpp
new file mode 100644
index 000000000..73524c166
--- /dev/null
+++ b/src/client/qwaylandtabletv2.cpp
@@ -0,0 +1,314 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#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);
+}
+
+QWaylandTabletManagerV2::~QWaylandTabletManagerV2()
+{
+ destroy();
+}
+
+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()))
+ , m_seat(seat)
+{
+}
+
+QWaylandTabletSeatV2::~QWaylandTabletSeatV2()
+{
+ for (auto *tablet : m_tablets)
+ tablet->destroy();
+ for (auto *tool : m_tools)
+ tool->destroy();
+ for (auto *pad : m_pads)
+ pad->destroy();
+ qDeleteAll(m_tablets);
+ qDeleteAll(m_tools);
+ qDeleteAll(m_pads);
+ 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(this, 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(QWaylandTabletSeatV2 *tabletSeat, ::zwp_tablet_tool_v2 *tool)
+ : QtWayland::zwp_tablet_tool_v2(tool)
+ , m_tabletSeat(tabletSeat)
+{
+}
+
+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 = QPointingDevice::PointerType::Pen;
+ break;
+ case type::type_eraser:
+ m_pointerType = QPointingDevice::PointerType::Eraser;
+ break;
+ case type::type_mouse:
+ case type::type_lens:
+ m_pointerType = QPointingDevice::PointerType::Cursor;
+ break;
+ case type::type_finger:
+ m_pointerType = QPointingDevice::PointerType::Unknown;
+ break;
+ }
+ switch (m_toolType) {
+ case type::type_airbrush:
+ m_tabletDevice = QInputDevice::DeviceType::Airbrush;
+ break;
+ case type::type_brush:
+ case type::type_pencil:
+ case type::type_pen:
+ case type::type_eraser:
+ m_tabletDevice = QInputDevice::DeviceType::Stylus;
+ break;
+ case type::type_lens:
+ m_tabletDevice = QInputDevice::DeviceType::Puck;
+ break;
+ case type::type_mouse:
+ case type::type_finger:
+ m_tabletDevice = QInputDevice::DeviceType::Unknown;
+ 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)
+{
+ m_pending.down = true;
+
+ if (m_pending.proximitySurface) {
+ if (QWaylandWindow *window = m_pending.proximitySurface->waylandWindow()) {
+ QWaylandInputDevice *seat = m_tabletSeat->seat();
+ seat->display()->setLastInputDevice(seat, serial, window);
+ }
+ }
+}
+
+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(int(m_tabletDevice), int(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,
+ int(m_tabletDevice), int(m_pointerType), buttons, pressure,
+ xTilt, yTilt, tangentialPressure, rotation, z, m_uid);
+ }
+
+ if (!m_pending.proximitySurface && m_applied.enteredSurface) {
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(int(m_tabletDevice), int(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
+
+#include "moc_qwaylandtabletv2_p.cpp"
diff --git a/src/client/qwaylandtabletv2_p.h b/src/client/qwaylandtabletv2_p.h
new file mode 100644
index 000000000..20a8a4f5a
--- /dev/null
+++ b/src/client/qwaylandtabletv2_p.h
@@ -0,0 +1,161 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#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 <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QPointF>
+#include <QtGui/QPointingDevice>
+#include <QtGui/QInputDevice>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+class QWaylandInputDevice;
+class QWaylandSurface;
+
+class QWaylandTabletSeatV2;
+class QWaylandTabletV2;
+class QWaylandTabletToolV2;
+class QWaylandTabletPadV2;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandTabletManagerV2 : public QtWayland::zwp_tablet_manager_v2
+{
+public:
+ explicit QWaylandTabletManagerV2(QWaylandDisplay *display, uint id, uint version);
+ ~QWaylandTabletManagerV2() override;
+ QWaylandTabletSeatV2 *createTabletSeat(QWaylandInputDevice *seat);
+};
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandTabletSeatV2 : public QObject, public QtWayland::zwp_tablet_seat_v2
+{
+ Q_OBJECT
+public:
+ explicit QWaylandTabletSeatV2(QWaylandTabletManagerV2 *manager, QWaylandInputDevice *seat);
+ ~QWaylandTabletSeatV2() override;
+
+ QWaylandInputDevice *seat() const { return m_seat; }
+
+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:
+ QWaylandInputDevice *m_seat;
+ QList<QWaylandTabletV2 *> m_tablets;
+ QList<QWaylandTabletToolV2 *> m_tools;
+ QList<QWaylandTabletPadV2 *> m_pads;
+};
+
+class Q_WAYLANDCLIENT_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_WAYLANDCLIENT_EXPORT QWaylandTabletToolV2 : public QObject, public QtWayland::zwp_tablet_tool_v2
+{
+ Q_OBJECT
+public:
+ QWaylandTabletToolV2(QWaylandTabletSeatV2 *tabletSeat, ::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:
+ QWaylandTabletSeatV2 *m_tabletSeat;
+
+ // Static state (sent before done event)
+ QPointingDevice::PointerType m_pointerType = QPointingDevice::PointerType::Unknown;
+ QInputDevice::DeviceType m_tabletDevice = QInputDevice::DeviceType::Unknown;
+ 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_WAYLANDCLIENT_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/qwaylandtextinputinterface.cpp b/src/client/qwaylandtextinputinterface.cpp
new file mode 100644
index 000000000..794396475
--- /dev/null
+++ b/src/client/qwaylandtextinputinterface.cpp
@@ -0,0 +1,8 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandtextinputinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandtextinputinterface_p.h b/src/client/qwaylandtextinputinterface_p.h
new file mode 100644
index 000000000..6f695575f
--- /dev/null
+++ b/src/client/qwaylandtextinputinterface_p.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDTEXTINPUTINTERFACE_P_H
+#define QWAYLANDTEXTINPUTINTERFACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qlocale.h>
+#include <QtCore/qrect.h>
+#include <QtCore/private/qglobal_p.h>
+
+struct wl_surface;
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandTextInputInterface
+{
+public:
+ virtual ~QWaylandTextInputInterface() {}
+ virtual void reset() = 0;
+ virtual void commit() = 0;
+ virtual void disableSurface(::wl_surface *surface) = 0;
+ virtual void enableSurface(::wl_surface *surface) = 0;
+ virtual void updateState(Qt::InputMethodQueries queries, uint32_t flags) = 0;
+ virtual void showInputPanel() {}
+ virtual void hideInputPanel() {}
+ virtual bool isInputPanelVisible() const = 0;
+ virtual QRectF keyboardRect() const = 0;
+ virtual QLocale locale() const = 0;
+ virtual Qt::LayoutDirection inputDirection() const = 0;
+ virtual void setCursorInsidePreedit(int cursor) = 0;
+
+ // This enum should be compatible with update_state of text-input-unstable-v2.
+ // Higher versions of text-input-* protocol may not use it directly
+ // but QtWaylandClient can determine clients' states based on the values
+ enum TextInputState {
+ update_state_change = 0, // updated state because it changed
+ update_state_full = 1, // full state after enter or input_method_changed event
+ update_state_reset = 2, // full state after reset
+ update_state_enter = 3, // full state after switching focus to a different widget on client side
+ };
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTEXTINPUTINTERFACE_P_H
+
diff --git a/src/client/qwaylandtextinputv1.cpp b/src/client/qwaylandtextinputv1.cpp
new file mode 100644
index 000000000..846ed95c8
--- /dev/null
+++ b/src/client/qwaylandtextinputv1.cpp
@@ -0,0 +1,362 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include <qpa/qplatforminputcontext.h>
+
+#include "qwaylandtextinputv1_p.h"
+
+#include "qwaylandwindow_p.h"
+#include "qwaylandinputmethodeventbuilder_p.h"
+
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qwindow.h>
+#include <QTextCharFormat>
+#include <QList>
+#include <QRectF>
+#include <QLocale>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcQpaInputMethods)
+
+namespace QtWaylandClient {
+
+namespace {
+
+const Qt::InputMethodQueries supportedQueries1 = Qt::ImEnabled |
+ Qt::ImSurroundingText |
+ Qt::ImCursorPosition |
+ Qt::ImAnchorPosition |
+ Qt::ImHints |
+ Qt::ImCursorRectangle |
+ Qt::ImPreferredLanguage;
+}
+
+QWaylandTextInputv1::QWaylandTextInputv1(QWaylandDisplay *display, struct ::zwp_text_input_v1 *text_input)
+ : QtWayland::zwp_text_input_v1(text_input)
+{
+ Q_UNUSED(display);
+}
+
+QWaylandTextInputv1::~QWaylandTextInputv1()
+{
+ if (m_resetCallback)
+ wl_callback_destroy(m_resetCallback);
+ zwp_text_input_v1_destroy(object());
+}
+
+void QWaylandTextInputv1::reset()
+{
+ m_builder.reset();
+ m_preeditCommit = QString();
+ updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_reset);
+}
+
+void QWaylandTextInputv1::commit()
+{
+ if (QObject *o = QGuiApplication::focusObject()) {
+ QInputMethodEvent event;
+ event.setCommitString(m_preeditCommit);
+ QCoreApplication::sendEvent(o, &event);
+ }
+
+ reset();
+}
+
+const wl_callback_listener QWaylandTextInputv1::callbackListener = {
+ QWaylandTextInputv1::resetCallback
+};
+
+void QWaylandTextInputv1::resetCallback(void *data, wl_callback *, uint32_t)
+{
+ QWaylandTextInputv1 *self = static_cast<QWaylandTextInputv1*>(data);
+
+ if (self->m_resetCallback) {
+ wl_callback_destroy(self->m_resetCallback);
+ self->m_resetCallback = nullptr;
+ }
+}
+
+void QWaylandTextInputv1::updateState(Qt::InputMethodQueries queries, uint32_t flags)
+{
+ if (!QGuiApplication::focusObject())
+ return;
+
+ if (!QGuiApplication::focusWindow() || !QGuiApplication::focusWindow()->handle())
+ return;
+
+ auto *window = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle());
+ auto *surface = window->wlSurface();
+ if (!surface || (surface != m_surface))
+ return;
+
+ queries &= supportedQueries1;
+
+ // Surrounding text, cursor and anchor positions are transferred together
+ if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition))
+ queries |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
+
+ QInputMethodQueryEvent event(queries);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+
+ if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition)) {
+ QString text = event.value(Qt::ImSurroundingText).toString();
+ int cursor = event.value(Qt::ImCursorPosition).toInt();
+ int anchor = event.value(Qt::ImAnchorPosition).toInt();
+
+ // Make sure text is not too big
+ if (text.toUtf8().size() > 2048) {
+ int c = qAbs(cursor - anchor) <= 512 ? qMin(cursor, anchor) + qAbs(cursor - anchor) / 2: cursor;
+
+ const int offset = c - qBound(0, c, 512 - qMin(text.size() - c, 256));
+ text = text.mid(offset + c - 256, 512);
+ cursor -= offset;
+ anchor -= offset;
+ }
+
+ set_surrounding_text(text, QWaylandInputMethodEventBuilder::indexToWayland(text, cursor), QWaylandInputMethodEventBuilder::indexToWayland(text, anchor));
+ }
+
+ if (queries & Qt::ImHints) {
+ QWaylandInputMethodContentType contentType = QWaylandInputMethodContentType::convert(static_cast<Qt::InputMethodHints>(event.value(Qt::ImHints).toInt()));
+ set_content_type(contentType.hint, contentType.purpose);
+ }
+
+ if (queries & Qt::ImCursorRectangle) {
+ const QRect &cRect = event.value(Qt::ImCursorRectangle).toRect();
+ const QRect &windowRect = QGuiApplication::inputMethod()->inputItemTransform().mapRect(cRect);
+ const QRect &nativeRect = QHighDpi::toNativePixels(windowRect, QGuiApplication::focusWindow());
+ const QMargins margins = window->clientSideMargins();
+ const QRect &surfaceRect = nativeRect.translated(margins.left(), margins.top());
+ set_cursor_rectangle(surfaceRect.x(), surfaceRect.y(), surfaceRect.width(), surfaceRect.height());
+ }
+
+ if (queries & Qt::ImPreferredLanguage) {
+ const QString &language = event.value(Qt::ImPreferredLanguage).toString();
+ set_preferred_language(language);
+ }
+
+ if (flags == QWaylandTextInputInterface::update_state_reset)
+ QtWayland::zwp_text_input_v1::reset();
+ else
+ commit_state(m_serial);
+}
+
+void QWaylandTextInputv1::setCursorInsidePreedit(int)
+{
+ // Not supported yet
+}
+
+bool QWaylandTextInputv1::isInputPanelVisible() const
+{
+ return m_inputPanelVisible;
+}
+
+QRectF QWaylandTextInputv1::keyboardRect() const
+{
+ return m_keyboardRectangle;
+}
+
+QLocale QWaylandTextInputv1::locale() const
+{
+ return m_locale;
+}
+
+Qt::LayoutDirection QWaylandTextInputv1::inputDirection() const
+{
+ return m_inputDirection;
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_enter(::wl_surface *surface)
+{
+ m_surface = surface;
+
+ updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_reset);
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_leave()
+{
+ m_surface = nullptr;
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_modifiers_map(wl_array *map)
+{
+ const QList<QByteArray> modifiersMap = QByteArray::fromRawData(static_cast<const char*>(map->data), map->size).split('\0');
+
+ m_modifiersMap.clear();
+
+ for (const QByteArray &modifier : modifiersMap) {
+ if (modifier == "Shift")
+ m_modifiersMap.append(Qt::ShiftModifier);
+ else if (modifier == "Control")
+ m_modifiersMap.append(Qt::ControlModifier);
+ else if (modifier == "Alt")
+ m_modifiersMap.append(Qt::AltModifier);
+ else if (modifier == "Mod1")
+ m_modifiersMap.append(Qt::AltModifier);
+ else if (modifier == "Mod4")
+ m_modifiersMap.append(Qt::MetaModifier);
+ else
+ m_modifiersMap.append(Qt::NoModifier);
+ }
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_input_panel_state(uint32_t visible)
+{
+ const bool inputPanelVisible = (visible == 1);
+ if (m_inputPanelVisible != inputPanelVisible) {
+ m_inputPanelVisible = inputPanelVisible;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
+ }
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_preedit_string(uint32_t serial, const QString &text, const QString &commit)
+{
+ m_serial = serial;
+
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard preedit_string: reset not confirmed";
+ m_builder.reset();
+ return;
+ }
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ QInputMethodEvent *event = m_builder.buildPreedit(text);
+
+ m_builder.reset();
+ m_preeditCommit = commit;
+
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), event);
+ delete event;
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_preedit_styling(uint32_t index, uint32_t length, uint32_t style)
+{
+ m_builder.addPreeditStyling(index, length, style);
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_preedit_cursor(int32_t index)
+{
+ m_builder.setPreeditCursor(index);
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_commit_string(uint32_t serial, const QString &text)
+{
+ m_serial = serial;
+
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard commit_string: reset not confirmed";
+ m_builder.reset();
+ return;
+ }
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ // When committing the text, the preeditString needs to be reset, to prevent it to be
+ // send again in the commit() function
+ m_preeditCommit.clear();
+
+ QInputMethodEvent *event = m_builder.buildCommit(text);
+
+ m_builder.reset();
+
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), event);
+ delete event;
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_cursor_position(int32_t index, int32_t anchor)
+{
+ m_builder.setCursorPosition(index, anchor);
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_delete_surrounding_text(int32_t before_length, uint32_t after_length)
+{
+ //before_length is negative, but the builder expects it to be positive
+ m_builder.setDeleteSurroundingText(-before_length, after_length);
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
+{
+ m_serial = serial;
+
+#if QT_CONFIG(xkbcommon)
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard keysym: reset not confirmed";
+ return;
+ }
+
+ if (!QGuiApplication::focusWindow())
+ return;
+
+ Qt::KeyboardModifiers qtModifiers = modifiersToQtModifiers(modifiers);
+
+ QEvent::Type type = state == WL_KEYBOARD_KEY_STATE_PRESSED ? QEvent::KeyPress : QEvent::KeyRelease;
+ QString text = QXkbCommon::lookupStringNoKeysymTransformations(sym);
+ int qtkey = QXkbCommon::keysymToQtKey(sym, qtModifiers);
+
+ QWindowSystemInterface::handleKeyEvent(QGuiApplication::focusWindow(),
+ time, type, qtkey, qtModifiers, text);
+#else
+ Q_UNUSED(time);
+ Q_UNUSED(sym);
+ Q_UNUSED(state);
+ Q_UNUSED(modifiers);
+#endif
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_language(uint32_t serial, const QString &language)
+{
+ m_serial = serial;
+
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard language: reset not confirmed";
+ return;
+ }
+
+ const QLocale locale(language);
+ if (m_locale != locale) {
+ m_locale = locale;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitLocaleChanged();
+ }
+}
+
+void QWaylandTextInputv1::zwp_text_input_v1_text_direction(uint32_t serial, uint32_t direction)
+{
+ m_serial = serial;
+
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard text_direction: reset not confirmed";
+ return;
+ }
+
+ const Qt::LayoutDirection inputDirection = (direction == text_direction_auto) ? Qt::LayoutDirectionAuto :
+ (direction == text_direction_ltr) ? Qt::LeftToRight :
+ (direction == text_direction_rtl) ? Qt::RightToLeft : Qt::LayoutDirectionAuto;
+ if (m_inputDirection != inputDirection) {
+ m_inputDirection = inputDirection;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputDirectionChanged(m_inputDirection);
+ }
+}
+
+Qt::KeyboardModifiers QWaylandTextInputv1::modifiersToQtModifiers(uint32_t modifiers)
+{
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
+ for (int i = 0; i < m_modifiersMap.size(); ++i) {
+ if (modifiers & (1 << i)) {
+ ret |= m_modifiersMap[i];
+ }
+ }
+ return ret;
+}
+
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/client/qwaylandtextinputv1_p.h b/src/client/qwaylandtextinputv1_p.h
new file mode 100644
index 000000000..dc591cdb1
--- /dev/null
+++ b/src/client/qwaylandtextinputv1_p.h
@@ -0,0 +1,112 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+#ifndef QWAYLANDTEXTINPUTV1_H
+#define QWAYLANDTEXTINPUTV1_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 "qwaylandtextinputinterface_p.h"
+#include <QtWaylandClient/private/qwayland-text-input-unstable-v1.h>
+#include <qwaylandinputmethodeventbuilder_p.h>
+
+struct wl_callback;
+struct wl_callback_listener;
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+
+class QWaylandTextInputv1 : public QtWayland::zwp_text_input_v1, public QWaylandTextInputInterface
+{
+public:
+ QWaylandTextInputv1(QWaylandDisplay *display, struct ::zwp_text_input_v1 *text_input);
+ ~QWaylandTextInputv1() override;
+
+ void setSeat(struct ::wl_seat *seat) { m_seat = seat; }
+
+ void reset() override;
+ void commit() override;
+ void updateState(Qt::InputMethodQueries queries, uint32_t flags) override;
+
+ void setCursorInsidePreedit(int cursor) override;
+
+ bool isInputPanelVisible() const override;
+ QRectF keyboardRect() const override;
+
+ QLocale locale() const override;
+ Qt::LayoutDirection inputDirection() const override;
+
+ void showInputPanel() override
+ {
+ show_input_panel();
+ }
+ void hideInputPanel() override
+ {
+ hide_input_panel();
+ }
+ void enableSurface(::wl_surface *surface) override
+ {
+ activate(m_seat, surface);
+ }
+ void disableSurface(::wl_surface *surface) override
+ {
+ Q_UNUSED(surface);
+ deactivate(m_seat);
+ }
+
+protected:
+ void zwp_text_input_v1_enter(struct ::wl_surface *surface) override;
+ void zwp_text_input_v1_leave() override;
+ void zwp_text_input_v1_modifiers_map(wl_array *map) override;
+ void zwp_text_input_v1_input_panel_state(uint32_t state) override;
+ void zwp_text_input_v1_preedit_string(uint32_t serial, const QString &text, const QString &commit) override;
+ void zwp_text_input_v1_preedit_styling(uint32_t index, uint32_t length, uint32_t style) override;
+ void zwp_text_input_v1_preedit_cursor(int32_t index) override;
+ void zwp_text_input_v1_commit_string(uint32_t serial, const QString &text) override;
+ void zwp_text_input_v1_cursor_position(int32_t index, int32_t anchor) override;
+ void zwp_text_input_v1_delete_surrounding_text(int32_t before_length, uint32_t after_length) override;
+ void zwp_text_input_v1_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) override;
+ void zwp_text_input_v1_language(uint32_t serial, const QString &language) override;
+ void zwp_text_input_v1_text_direction(uint32_t serial, uint32_t direction) override;
+
+private:
+ Qt::KeyboardModifiers modifiersToQtModifiers(uint32_t modifiers);
+
+ QWaylandInputMethodEventBuilder m_builder;
+
+ QList<Qt::KeyboardModifier> m_modifiersMap;
+
+ uint32_t m_serial = 0;
+ struct ::wl_surface *m_surface = nullptr;
+ struct ::wl_seat *m_seat = nullptr;
+
+ QString m_preeditCommit;
+
+ bool m_inputPanelVisible = false;
+ QRectF m_keyboardRectangle;
+ QLocale m_locale;
+ Qt::LayoutDirection m_inputDirection = Qt::LayoutDirectionAuto;
+
+ struct ::wl_callback *m_resetCallback = nullptr;
+ static const wl_callback_listener callbackListener;
+ static void resetCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
+};
+
+}
+
+QT_END_NAMESPACE
+#endif // QWAYLANDTEXTINPUTV1_H
+
diff --git a/src/client/qwaylandtextinputv2.cpp b/src/client/qwaylandtextinputv2.cpp
new file mode 100644
index 000000000..9d462f7d6
--- /dev/null
+++ b/src/client/qwaylandtextinputv2.cpp
@@ -0,0 +1,375 @@
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <qpa/qplatforminputcontext.h>
+
+#include "qwaylandtextinputv2_p.h"
+
+#include "qwaylandwindow_p.h"
+#include "qwaylandinputmethodeventbuilder_p.h"
+
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qwindow.h>
+#include <QTextCharFormat>
+#include <QList>
+#include <QRectF>
+#include <QLocale>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcQpaInputMethods)
+
+namespace QtWaylandClient {
+
+namespace {
+
+const Qt::InputMethodQueries supportedQueries2 = Qt::ImEnabled |
+ Qt::ImSurroundingText |
+ Qt::ImCursorPosition |
+ Qt::ImAnchorPosition |
+ Qt::ImHints |
+ Qt::ImCursorRectangle |
+ Qt::ImPreferredLanguage;
+}
+
+QWaylandTextInputv2::QWaylandTextInputv2(QWaylandDisplay *display, struct ::zwp_text_input_v2 *text_input)
+ : QtWayland::zwp_text_input_v2(text_input)
+ , m_display(display)
+{
+}
+
+QWaylandTextInputv2::~QWaylandTextInputv2()
+{
+ if (m_resetCallback)
+ wl_callback_destroy(m_resetCallback);
+ destroy();
+}
+
+void QWaylandTextInputv2::reset()
+{
+ m_builder.reset();
+ m_preeditCommit = QString();
+ updateState(Qt::ImQueryAll, QtWayland::zwp_text_input_v2::update_state_reset);
+}
+
+void QWaylandTextInputv2::commit()
+{
+ if (QObject *o = QGuiApplication::focusObject()) {
+ if (!m_preeditCommit.isEmpty()) {
+
+ QInputMethodEvent event;
+ event.setCommitString(m_preeditCommit);
+ m_preeditCommit = QString();
+
+ QCoreApplication::sendEvent(o, &event);
+ }
+ }
+
+ reset();
+}
+
+const wl_callback_listener QWaylandTextInputv2::callbackListener = {
+ QWaylandTextInputv2::resetCallback
+};
+
+void QWaylandTextInputv2::resetCallback(void *data, wl_callback *, uint32_t)
+{
+ QWaylandTextInputv2 *self = static_cast<QWaylandTextInputv2*>(data);
+
+ if (self->m_resetCallback) {
+ wl_callback_destroy(self->m_resetCallback);
+ self->m_resetCallback = nullptr;
+ }
+}
+
+void QWaylandTextInputv2::updateState(Qt::InputMethodQueries queries, uint32_t flags)
+{
+ if (!QGuiApplication::focusObject())
+ return;
+
+ if (!QGuiApplication::focusWindow() || !QGuiApplication::focusWindow()->handle())
+ return;
+
+ auto *window = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle());
+ auto *surface = window->wlSurface();
+ if (!surface || (surface != m_surface))
+ return;
+
+ queries &= supportedQueries2;
+
+ // Surrounding text, cursor and anchor positions are transferred together
+ if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition))
+ queries |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
+
+ QInputMethodQueryEvent event(queries);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+
+ if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition)) {
+ QString text = event.value(Qt::ImSurroundingText).toString();
+ int cursor = event.value(Qt::ImCursorPosition).toInt();
+ int anchor = event.value(Qt::ImAnchorPosition).toInt();
+
+ // Make sure text is not too big
+ if (text.toUtf8().size() > 2048) {
+ int c = qAbs(cursor - anchor) <= 512 ? qMin(cursor, anchor) + qAbs(cursor - anchor) / 2: cursor;
+
+ const int offset = c - qBound(0, c, 512 - qMin(text.size() - c, 256));
+ text = text.mid(offset + c - 256, 512);
+ cursor -= offset;
+ anchor -= offset;
+ }
+
+ set_surrounding_text(text, QWaylandInputMethodEventBuilder::indexToWayland(text, cursor), QWaylandInputMethodEventBuilder::indexToWayland(text, anchor));
+ }
+
+ if (queries & Qt::ImHints) {
+ QWaylandInputMethodContentType contentType = QWaylandInputMethodContentType::convert(static_cast<Qt::InputMethodHints>(event.value(Qt::ImHints).toInt()));
+ set_content_type(contentType.hint, contentType.purpose);
+ }
+
+ if (queries & Qt::ImCursorRectangle) {
+ const QRect &cRect = event.value(Qt::ImCursorRectangle).toRect();
+ const QRect &windowRect = QGuiApplication::inputMethod()->inputItemTransform().mapRect(cRect);
+ const QRect &nativeRect = QHighDpi::toNativePixels(windowRect, QGuiApplication::focusWindow());
+ const QMargins margins = window->clientSideMargins();
+ const QRect &surfaceRect = nativeRect.translated(margins.left(), margins.top());
+ set_cursor_rectangle(surfaceRect.x(), surfaceRect.y(), surfaceRect.width(), surfaceRect.height());
+ }
+
+ if (queries & Qt::ImPreferredLanguage) {
+ const QString &language = event.value(Qt::ImPreferredLanguage).toString();
+ set_preferred_language(language);
+ }
+
+ update_state(m_serial, flags);
+ if (flags != QtWayland::zwp_text_input_v2::update_state_change) {
+ if (m_resetCallback)
+ wl_callback_destroy(m_resetCallback);
+ m_resetCallback = wl_display_sync(m_display->wl_display());
+ wl_callback_add_listener(m_resetCallback, &QWaylandTextInputv2::callbackListener, this);
+ }
+}
+
+void QWaylandTextInputv2::setCursorInsidePreedit(int)
+{
+ // Not supported yet
+}
+
+bool QWaylandTextInputv2::isInputPanelVisible() const
+{
+ return m_inputPanelVisible;
+}
+
+QRectF QWaylandTextInputv2::keyboardRect() const
+{
+ return m_keyboardRectangle;
+}
+
+QLocale QWaylandTextInputv2::locale() const
+{
+ return m_locale;
+}
+
+Qt::LayoutDirection QWaylandTextInputv2::inputDirection() const
+{
+ return m_inputDirection;
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_enter(uint32_t serial, ::wl_surface *surface)
+{
+ m_serial = serial;
+ m_surface = surface;
+
+ updateState(Qt::ImQueryAll, QtWayland::zwp_text_input_v2::update_state_enter);
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_leave(uint32_t serial, ::wl_surface *surface)
+{
+ m_serial = serial;
+
+ if (m_surface != surface) {
+ qCDebug(qLcQpaInputMethods()) << Q_FUNC_INFO << "Got leave event for surface" << surface << "focused surface" << m_surface;
+ }
+
+ m_surface = nullptr;
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_modifiers_map(wl_array *map)
+{
+ const QList<QByteArray> modifiersMap = QByteArray::fromRawData(static_cast<const char*>(map->data), map->size).split('\0');
+
+ m_modifiersMap.clear();
+
+ for (const QByteArray &modifier : modifiersMap) {
+ if (modifier == "Shift")
+ m_modifiersMap.append(Qt::ShiftModifier);
+ else if (modifier == "Control")
+ m_modifiersMap.append(Qt::ControlModifier);
+ else if (modifier == "Alt")
+ m_modifiersMap.append(Qt::AltModifier);
+ else if (modifier == "Mod1")
+ m_modifiersMap.append(Qt::AltModifier);
+ else if (modifier == "Mod4")
+ m_modifiersMap.append(Qt::MetaModifier);
+ else
+ m_modifiersMap.append(Qt::NoModifier);
+ }
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_input_panel_state(uint32_t visible, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ const bool inputPanelVisible = (visible == input_panel_visibility_visible);
+ if (m_inputPanelVisible != inputPanelVisible) {
+ m_inputPanelVisible = inputPanelVisible;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
+ }
+ const QRectF keyboardRectangle(x, y, width, height);
+ if (m_keyboardRectangle != keyboardRectangle) {
+ m_keyboardRectangle = keyboardRectangle;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitKeyboardRectChanged();
+ }
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_preedit_string(const QString &text, const QString &commit)
+{
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard preedit_string: reset not confirmed";
+ m_builder.reset();
+ return;
+ }
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ QInputMethodEvent *event = m_builder.buildPreedit(text);
+
+ m_builder.reset();
+ m_preeditCommit = commit;
+
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), event);
+ delete event;
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_preedit_styling(uint32_t index, uint32_t length, uint32_t style)
+{
+ m_builder.addPreeditStyling(index, length, style);
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_preedit_cursor(int32_t index)
+{
+ m_builder.setPreeditCursor(index);
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_commit_string(const QString &text)
+{
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard commit_string: reset not confirmed";
+ m_builder.reset();
+ return;
+ }
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ QInputMethodEvent *event = m_builder.buildCommit(text);
+
+ m_builder.reset();
+
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), event);
+ delete event;
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor)
+{
+ m_builder.setCursorPosition(index, anchor);
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length)
+{
+ m_builder.setDeleteSurroundingText(before_length, after_length);
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
+{
+#if QT_CONFIG(xkbcommon)
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard keysym: reset not confirmed";
+ return;
+ }
+
+ if (!QGuiApplication::focusWindow())
+ return;
+
+ Qt::KeyboardModifiers qtModifiers = modifiersToQtModifiers(modifiers);
+
+ QEvent::Type type = state == WL_KEYBOARD_KEY_STATE_PRESSED ? QEvent::KeyPress : QEvent::KeyRelease;
+ QString text = QXkbCommon::lookupStringNoKeysymTransformations(sym);
+ int qtkey = QXkbCommon::keysymToQtKey(sym, qtModifiers);
+
+ QWindowSystemInterface::handleKeyEvent(QGuiApplication::focusWindow(),
+ time, type, qtkey, qtModifiers, text);
+#else
+ Q_UNUSED(time);
+ Q_UNUSED(sym);
+ Q_UNUSED(state);
+ Q_UNUSED(modifiers);
+#endif
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_language(const QString &language)
+{
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard language: reset not confirmed";
+ return;
+ }
+
+ const QLocale locale(language);
+ if (m_locale != locale) {
+ m_locale = locale;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitLocaleChanged();
+ }
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_text_direction(uint32_t direction)
+{
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard text_direction: reset not confirmed";
+ return;
+ }
+
+ const Qt::LayoutDirection inputDirection = (direction == text_direction_auto) ? Qt::LayoutDirectionAuto :
+ (direction == text_direction_ltr) ? Qt::LeftToRight :
+ (direction == text_direction_rtl) ? Qt::RightToLeft : Qt::LayoutDirectionAuto;
+ if (m_inputDirection != inputDirection) {
+ m_inputDirection = inputDirection;
+ QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputDirectionChanged(m_inputDirection);
+ }
+}
+
+void QWaylandTextInputv2::zwp_text_input_v2_input_method_changed(uint32_t serial, uint32_t flags)
+{
+ Q_UNUSED(flags);
+
+ m_serial = serial;
+ updateState(Qt::ImQueryAll, QtWayland::zwp_text_input_v2::update_state_full);
+}
+
+Qt::KeyboardModifiers QWaylandTextInputv2::modifiersToQtModifiers(uint32_t modifiers)
+{
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
+ for (int i = 0; i < m_modifiersMap.size(); ++i) {
+ if (modifiers & (1 << i)) {
+ ret |= m_modifiersMap[i];
+ }
+ }
+ return ret;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandtextinputv2_p.h b/src/client/qwaylandtextinputv2_p.h
new file mode 100644
index 000000000..94b0408a9
--- /dev/null
+++ b/src/client/qwaylandtextinputv2_p.h
@@ -0,0 +1,110 @@
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+#ifndef QWAYLANDINPUTV2_P_H
+#define QWAYLANDINPUTV2_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 "qwaylandtextinputinterface_p.h"
+#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
+#include <qwaylandinputmethodeventbuilder_p.h>
+
+struct wl_callback;
+struct wl_callback_listener;
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+
+class QWaylandTextInputv2 : public QtWayland::zwp_text_input_v2, public QWaylandTextInputInterface
+{
+public:
+ QWaylandTextInputv2(QWaylandDisplay *display, struct ::zwp_text_input_v2 *text_input);
+ ~QWaylandTextInputv2() override;
+
+ void reset() override;
+ void commit() override;
+ void updateState(Qt::InputMethodQueries queries, uint32_t flags) override;
+
+ void setCursorInsidePreedit(int cursor) override;
+
+ bool isInputPanelVisible() const override;
+ QRectF keyboardRect() const override;
+
+ QLocale locale() const override;
+ Qt::LayoutDirection inputDirection() const override;
+
+ void showInputPanel() override
+ {
+ show_input_panel();
+ }
+ void hideInputPanel() override
+ {
+ hide_input_panel();
+ }
+ void enableSurface(::wl_surface *surface) override
+ {
+ enable(surface);
+ }
+ void disableSurface(::wl_surface *surface) override
+ {
+ disable(surface);
+ }
+
+protected:
+ void zwp_text_input_v2_enter(uint32_t serial, struct ::wl_surface *surface) override;
+ void zwp_text_input_v2_leave(uint32_t serial, struct ::wl_surface *surface) override;
+ void zwp_text_input_v2_modifiers_map(wl_array *map) override;
+ void zwp_text_input_v2_input_panel_state(uint32_t state, int32_t x, int32_t y, int32_t width, int32_t height) override;
+ void zwp_text_input_v2_preedit_string(const QString &text, const QString &commit) override;
+ void zwp_text_input_v2_preedit_styling(uint32_t index, uint32_t length, uint32_t style) override;
+ void zwp_text_input_v2_preedit_cursor(int32_t index) override;
+ void zwp_text_input_v2_commit_string(const QString &text) override;
+ void zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor) override;
+ void zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length) override;
+ void zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) override;
+ void zwp_text_input_v2_language(const QString &language) override;
+ void zwp_text_input_v2_text_direction(uint32_t direction) override;
+ void zwp_text_input_v2_input_method_changed(uint32_t serial, uint32_t flags) override;
+
+private:
+ Qt::KeyboardModifiers modifiersToQtModifiers(uint32_t modifiers);
+
+ QWaylandDisplay *m_display = nullptr;
+ QWaylandInputMethodEventBuilder m_builder;
+
+ QList<Qt::KeyboardModifier> m_modifiersMap;
+
+ uint32_t m_serial = 0;
+ struct ::wl_surface *m_surface = nullptr;
+
+ QString m_preeditCommit;
+
+ bool m_inputPanelVisible = false;
+ QRectF m_keyboardRectangle;
+ QLocale m_locale;
+ Qt::LayoutDirection m_inputDirection = Qt::LayoutDirectionAuto;
+
+ struct ::wl_callback *m_resetCallback = nullptr;
+ static const wl_callback_listener callbackListener;
+ static void resetCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTEXTINPUTV2_P_H
diff --git a/src/client/qwaylandtextinputv3.cpp b/src/client/qwaylandtextinputv3.cpp
new file mode 100644
index 000000000..bb449c9d6
--- /dev/null
+++ b/src/client/qwaylandtextinputv3.cpp
@@ -0,0 +1,372 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandtextinputv3_p.h"
+
+#include "qwaylandwindow_p.h"
+#include "qwaylandinputmethodeventbuilder_p.h"
+
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qwindow.h>
+#include <QTextCharFormat>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcQpaWaylandTextInput, "qt.qpa.wayland.textinput")
+
+namespace QtWaylandClient {
+
+QWaylandTextInputv3::QWaylandTextInputv3(QWaylandDisplay *display,
+ struct ::zwp_text_input_v3 *text_input)
+ : QtWayland::zwp_text_input_v3(text_input)
+{
+ Q_UNUSED(display)
+}
+
+QWaylandTextInputv3::~QWaylandTextInputv3()
+{
+ destroy();
+}
+
+namespace {
+const Qt::InputMethodQueries supportedQueries3 = Qt::ImEnabled |
+ Qt::ImSurroundingText |
+ Qt::ImCursorPosition |
+ Qt::ImAnchorPosition |
+ Qt::ImHints |
+ Qt::ImCursorRectangle;
+}
+
+void QWaylandTextInputv3::zwp_text_input_v3_enter(struct ::wl_surface *surface)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << m_surface << surface;
+
+ m_surface = surface;
+
+ m_pendingPreeditString.clear();
+ m_pendingCommitString.clear();
+ m_pendingDeleteBeforeText = 0;
+ m_pendingDeleteAfterText = 0;
+
+ enable();
+ updateState(supportedQueries3, update_state_enter);
+}
+
+void QWaylandTextInputv3::zwp_text_input_v3_leave(struct ::wl_surface *surface)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO;
+
+ if (m_surface != surface) {
+ qCWarning(qLcQpaWaylandTextInput()) << Q_FUNC_INFO << "Got leave event for surface" << surface << "focused surface" << m_surface;
+ return;
+ }
+
+ m_currentPreeditString.clear();
+
+ m_surface = nullptr;
+
+ disable();
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "Done";
+}
+
+void QWaylandTextInputv3::zwp_text_input_v3_preedit_string(const QString &text, int32_t cursorBegin, int32_t cursorEnd)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << text << cursorBegin << cursorEnd;
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ m_pendingPreeditString.text = text;
+ m_pendingPreeditString.cursorBegin = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursorBegin);
+ m_pendingPreeditString.cursorEnd = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursorEnd);
+}
+
+void QWaylandTextInputv3::zwp_text_input_v3_commit_string(const QString &text)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << text;
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ m_pendingCommitString = text;
+}
+
+void QWaylandTextInputv3::zwp_text_input_v3_delete_surrounding_text(uint32_t beforeText, uint32_t afterText)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << beforeText << afterText;
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ m_pendingDeleteBeforeText = beforeText;
+ m_pendingDeleteAfterText = afterText;
+}
+
+void QWaylandTextInputv3::zwp_text_input_v3_done(uint32_t serial)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "with serial" << serial << m_currentSerial;
+
+ // This is a case of double click.
+ // text_input_v3 will ignore this done signal and just keep the selection of the clicked word.
+ if (m_cursorPos != m_anchorPos && (m_pendingDeleteBeforeText != 0 || m_pendingDeleteAfterText != 0)) {
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "Ignore done";
+ m_pendingDeleteBeforeText = 0;
+ m_pendingDeleteAfterText = 0;
+ m_pendingPreeditString.clear();
+ m_pendingCommitString.clear();
+ return;
+ }
+
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return;
+
+ if (!m_surface) {
+ qCWarning(qLcQpaWaylandTextInput) << Q_FUNC_INFO << serial << "Surface is not enabled yet";
+ return;
+ }
+
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "PREEDIT" << m_pendingPreeditString.text << m_pendingPreeditString.cursorBegin;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ {
+ if (m_pendingPreeditString.cursorBegin != -1 ||
+ m_pendingPreeditString.cursorEnd != -1) {
+ // Current supported cursor shape is just line.
+ // It means, cursorEnd and cursorBegin are the same.
+ QInputMethodEvent::Attribute attribute1(QInputMethodEvent::Cursor,
+ m_pendingPreeditString.text.length(),
+ 1);
+ attributes.append(attribute1);
+ }
+
+ // only use single underline style for now
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+ QInputMethodEvent::Attribute attribute2(QInputMethodEvent::TextFormat,
+ 0,
+ m_pendingPreeditString.text.length(), format);
+ attributes.append(attribute2);
+ }
+ QInputMethodEvent event(m_pendingPreeditString.text, attributes);
+
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "DELETE" << m_pendingDeleteBeforeText << m_pendingDeleteAfterText;
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "COMMIT" << m_pendingCommitString;
+
+ int replaceFrom = 0;
+ int replaceLength = 0;
+ if (m_pendingDeleteBeforeText != 0 || m_pendingDeleteAfterText != 0) {
+ // A workaround for reselection
+ // It will disable redundant commit after reselection
+ m_condReselection = true;
+ const QByteArray &utf8 = QStringView{m_surroundingText}.toUtf8();
+ if (m_cursorPos < int(m_pendingDeleteBeforeText)) {
+ replaceFrom = -QString::fromUtf8(QByteArrayView{utf8}.first(m_pendingDeleteBeforeText)).size();
+ replaceLength = QString::fromUtf8(QByteArrayView{utf8}.first(m_pendingDeleteBeforeText + m_pendingDeleteAfterText)).size();
+ } else {
+ replaceFrom = -QString::fromUtf8(QByteArrayView{utf8}.sliced(m_cursorPos - m_pendingDeleteBeforeText, m_pendingDeleteBeforeText)).size();
+ replaceLength = QString::fromUtf8(QByteArrayView{utf8}.sliced(m_cursorPos - m_pendingDeleteBeforeText, m_pendingDeleteBeforeText + m_pendingDeleteAfterText)).size();
+ }
+ }
+
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "DELETE from " << replaceFrom << " length " << replaceLength;
+ event.setCommitString(m_pendingCommitString,
+ replaceFrom,
+ replaceLength);
+ m_currentPreeditString = m_pendingPreeditString;
+ m_pendingPreeditString.clear();
+ m_pendingCommitString.clear();
+ m_pendingDeleteBeforeText = 0;
+ m_pendingDeleteAfterText = 0;
+ QCoreApplication::sendEvent(focusObject, &event);
+
+ if (serial == m_currentSerial)
+ updateState(supportedQueries3, update_state_full);
+}
+
+void QWaylandTextInputv3::reset()
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO;
+
+ m_pendingPreeditString.clear();
+}
+
+void QWaylandTextInputv3::commit()
+{
+ m_currentSerial = (m_currentSerial < UINT_MAX) ? m_currentSerial + 1U: 0U;
+
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "with serial" << m_currentSerial;
+ QtWayland::zwp_text_input_v3::commit();
+}
+
+void QWaylandTextInputv3::updateState(Qt::InputMethodQueries queries, uint32_t flags)
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << queries << flags;
+
+ if (!QGuiApplication::focusObject())
+ return;
+
+ if (!QGuiApplication::focusWindow() || !QGuiApplication::focusWindow()->handle())
+ return;
+
+ auto *window = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle());
+ auto *surface = window->wlSurface();
+ if (!surface || (surface != m_surface))
+ return;
+
+ queries &= supportedQueries3;
+ bool needsCommit = false;
+
+ QInputMethodQueryEvent event(queries);
+ QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
+
+ // For some reason, a query for Qt::ImSurroundingText gives an empty string even though it is not.
+ if (!(queries & Qt::ImSurroundingText) && event.value(Qt::ImSurroundingText).toString().isEmpty()) {
+ return;
+ }
+
+ if (queries & Qt::ImCursorRectangle) {
+ const QRect &cRect = event.value(Qt::ImCursorRectangle).toRect();
+ const QRect &windowRect = QGuiApplication::inputMethod()->inputItemTransform().mapRect(cRect);
+ const QRect &nativeRect = QHighDpi::toNativePixels(windowRect, QGuiApplication::focusWindow());
+ const QMargins margins = window->clientSideMargins();
+ const QRect &surfaceRect = nativeRect.translated(margins.left(), margins.top());
+ if (surfaceRect != m_cursorRect) {
+ set_cursor_rectangle(surfaceRect.x(), surfaceRect.y(), surfaceRect.width(), surfaceRect.height());
+ m_cursorRect = surfaceRect;
+ needsCommit = true;
+ }
+ }
+
+ if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition)) {
+ QString text = event.value(Qt::ImSurroundingText).toString();
+ int cursor = event.value(Qt::ImCursorPosition).toInt();
+ int anchor = event.value(Qt::ImAnchorPosition).toInt();
+
+ qCDebug(qLcQpaWaylandTextInput) << "Original surrounding_text from InputMethodQuery: " << text << cursor << anchor;
+
+ // Make sure text is not too big
+ // surround_text cannot exceed 4000byte in wayland protocol
+ // The worst case will be supposed here.
+ const int MAX_MESSAGE_SIZE = 4000;
+
+ const int textSize = text.toUtf8().size();
+ if (textSize > MAX_MESSAGE_SIZE) {
+ qCDebug(qLcQpaWaylandTextInput) << "SurroundText size is over "
+ << MAX_MESSAGE_SIZE
+ << " byte, some text will be clipped.";
+ const int selectionStart = qMin(cursor, anchor);
+ const int selectionEnd = qMax(cursor, anchor);
+ const int selectionLength = selectionEnd - selectionStart;
+ const int selectionSize = QStringView{text}.sliced(selectionStart, selectionLength).toUtf8().size();
+ // If selection is bigger than 4000 byte, it is fixed to 4000 byte.
+ // anchor will be moved in the 4000 byte boundary.
+ if (selectionSize > MAX_MESSAGE_SIZE) {
+ if (anchor > cursor) {
+ cursor = 0;
+ anchor = MAX_MESSAGE_SIZE;
+ text = text.sliced(selectionStart, selectionLength);
+ } else {
+ anchor = 0;
+ cursor = MAX_MESSAGE_SIZE;
+ text = text.sliced(selectionEnd - selectionLength, selectionLength);
+ }
+ } else {
+ // This is not optimal in some cases.
+ // For examples, if the cursor position and
+ // the selectionEnd are close to the end of the surround text,
+ // the tail of the text might always be clipped.
+ // However all the cases of over 4000 byte are just exceptions.
+ int selEndSize = QStringView{text}.first(selectionEnd).toUtf8().size();
+ cursor = QWaylandInputMethodEventBuilder::indexToWayland(text, cursor);
+ anchor = QWaylandInputMethodEventBuilder::indexToWayland(text, anchor);
+ if (selEndSize < MAX_MESSAGE_SIZE) {
+ text = QString::fromUtf8(QByteArrayView{text.toUtf8()}.first(MAX_MESSAGE_SIZE));
+ } else {
+ const int startOffset = selEndSize - MAX_MESSAGE_SIZE;
+ text = QString::fromUtf8(QByteArrayView{text.toUtf8()}.sliced(startOffset, MAX_MESSAGE_SIZE));
+ cursor -= startOffset;
+ anchor -= startOffset;
+ }
+ }
+ } else {
+ cursor = QWaylandInputMethodEventBuilder::indexToWayland(text, cursor);
+ anchor = QWaylandInputMethodEventBuilder::indexToWayland(text, anchor);
+ }
+ qCDebug(qLcQpaWaylandTextInput) << "Modified surrounding_text: " << text << cursor << anchor;
+
+ if (m_surroundingText != text || m_cursorPos != cursor || m_anchorPos != anchor) {
+ qCDebug(qLcQpaWaylandTextInput) << "Current surrounding_text: " << m_surroundingText << m_cursorPos << m_anchorPos;
+ qCDebug(qLcQpaWaylandTextInput) << "New surrounding_text: " << text << cursor << anchor;
+
+ set_surrounding_text(text, cursor, anchor);
+
+ // A workaround in the case of reselection
+ // It will work when re-clicking a preedit text
+ if (m_condReselection) {
+ qCDebug(qLcQpaWaylandTextInput) << "\"commit\" is disabled when Reselection by changing focus";
+ m_condReselection = false;
+ needsCommit = false;
+
+ }
+
+ m_surroundingText = text;
+ m_cursorPos = cursor;
+ m_anchorPos = anchor;
+ m_cursor = cursor;
+ }
+ }
+
+ if (queries & Qt::ImHints) {
+ QWaylandInputMethodContentType contentType = QWaylandInputMethodContentType::convertV3(static_cast<Qt::InputMethodHints>(event.value(Qt::ImHints).toInt()));
+ qCDebug(qLcQpaWaylandTextInput) << m_contentHint << contentType.hint;
+ qCDebug(qLcQpaWaylandTextInput) << m_contentPurpose << contentType.purpose;
+
+ if (m_contentHint != contentType.hint || m_contentPurpose != contentType.purpose) {
+ qCDebug(qLcQpaWaylandTextInput) << "set_content_type: " << contentType.hint << contentType.purpose;
+ set_content_type(contentType.hint, contentType.purpose);
+
+ m_contentHint = contentType.hint;
+ m_contentPurpose = contentType.purpose;
+ needsCommit = true;
+ }
+ }
+
+ if (needsCommit
+ && (flags == update_state_change || flags == update_state_enter))
+ commit();
+}
+
+void QWaylandTextInputv3::setCursorInsidePreedit(int cursor)
+{
+ Q_UNUSED(cursor);
+}
+
+bool QWaylandTextInputv3::isInputPanelVisible() const
+{
+ return false;
+}
+
+QRectF QWaylandTextInputv3::keyboardRect() const
+{
+ qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO;
+ return m_cursorRect;
+}
+
+QLocale QWaylandTextInputv3::locale() const
+{
+ return QLocale();
+}
+
+Qt::LayoutDirection QWaylandTextInputv3::inputDirection() const
+{
+ return Qt::LeftToRight;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandtextinputv3_p.h b/src/client/qwaylandtextinputv3_p.h
new file mode 100644
index 000000000..8e32e514d
--- /dev/null
+++ b/src/client/qwaylandtextinputv3_p.h
@@ -0,0 +1,102 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDTEXTINPUTV3_P_H
+#define QWAYLANDTEXTINPUTV3_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 "qwaylandtextinputinterface_p.h"
+#include <QtWaylandClient/private/qwayland-text-input-unstable-v3.h>
+#include <QLoggingCategory>
+
+struct wl_callback;
+struct wl_callback_listener;
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcQpaWaylandTextInput)
+
+namespace QtWaylandClient {
+
+class QWaylandDisplay;
+
+class QWaylandTextInputv3 : public QtWayland::zwp_text_input_v3, public QWaylandTextInputInterface
+{
+public:
+ QWaylandTextInputv3(QWaylandDisplay *display, struct ::zwp_text_input_v3 *text_input);
+ ~QWaylandTextInputv3() override;
+
+ void reset() override;
+ void commit() override;
+ void updateState(Qt::InputMethodQueries queries, uint32_t flags) override;
+ // TODO: not supported yet
+ void setCursorInsidePreedit(int cursor) override;
+
+ bool isInputPanelVisible() const override;
+ QRectF keyboardRect() const override;
+
+ QLocale locale() const override;
+ Qt::LayoutDirection inputDirection() const override;
+
+ // doing nothing in zwp_text_input_v3.
+ // enter() and leave() takes the role to enable/disable the surface
+ void enableSurface(::wl_surface *) override {};
+ void disableSurface(::wl_surface *) override {};
+
+protected:
+ void zwp_text_input_v3_enter(struct ::wl_surface *surface) override;
+ void zwp_text_input_v3_leave(struct ::wl_surface *surface) override;
+ void zwp_text_input_v3_preedit_string(const QString &text, int32_t cursor_begin, int32_t cursor_end) override;
+ void zwp_text_input_v3_commit_string(const QString &text) override;
+ void zwp_text_input_v3_delete_surrounding_text(uint32_t before_length, uint32_t after_length) override;
+ void zwp_text_input_v3_done(uint32_t serial) override;
+
+private:
+ ::wl_surface *m_surface = nullptr; // ### Here for debugging purposes
+
+ struct PreeditInfo {
+ QString text;
+ int cursorBegin = 0;
+ int cursorEnd = 0;
+
+ void clear() {
+ text.clear();
+ cursorBegin = 0;
+ cursorEnd = 0;
+ }
+ };
+
+ PreeditInfo m_pendingPreeditString;
+ PreeditInfo m_currentPreeditString;
+ QString m_pendingCommitString;
+ uint m_pendingDeleteBeforeText = 0; // byte length
+ uint m_pendingDeleteAfterText = 0; // byte length
+
+ QString m_surroundingText;
+ int m_cursor; // cursor position in QString
+ int m_cursorPos; // cursor position in wayland index
+ int m_anchorPos; // anchor position in wayland index
+ uint32_t m_contentHint = 0;
+ uint32_t m_contentPurpose = 0;
+ QRect m_cursorRect;
+
+ uint m_currentSerial = 0;
+
+ bool m_condReselection = false;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTEXTINPUTV3_P_H
diff --git a/src/client/qwaylandtouch.cpp b/src/client/qwaylandtouch.cpp
index 0394aef31..dfd04d446 100644
--- a/src/client/qwaylandtouch.cpp
+++ b/src/client/qwaylandtouch.cpp
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandtouch_p.h"
#include "qwaylandinputdevice_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandsurface_p.h"
+#include <QtGui/QPointingDevice>
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -57,12 +23,18 @@ QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_
{
}
+QWaylandTouchExtension::~QWaylandTouchExtension()
+{
+ qt_touch_extension_destroy(object());
+}
+
void QWaylandTouchExtension::registerDevice(int caps)
{
- mTouchDevice = new QTouchDevice;
- mTouchDevice->setType(QTouchDevice::TouchScreen);
- mTouchDevice->setCapabilities(QTouchDevice::Capabilities(caps));
- QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+ // TODO number of touchpoints, actual name and ID
+ mTouchDevice = new QPointingDevice(QLatin1String("some touchscreen"), 0,
+ QInputDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger,
+ QInputDevice::Capabilities(caps), 10, 0);
+ QWindowSystemInterface::registerInputDevice(mTouchDevice);
}
static inline qreal fromFixed(int f)
@@ -98,13 +70,12 @@ void QWaylandTouchExtension::touch_extension_touch(uint32_t time,
QWindowSystemInterface::TouchPoint tp;
tp.id = id;
- tp.state = Qt::TouchPointState(int(state & 0xFFFF));
+ tp.state = QEventPoint::State(int(state & 0xFFFF));
int sentPointCount = state >> 16;
if (!mPointsLeft) {
Q_ASSERT(sentPointCount > 0);
mPointsLeft = sentPointCount;
}
- tp.flags = QTouchEvent::TouchPoint::InfoFlags(int(flags & 0xFFFF));
if (!mTouchDevice)
registerDevice(flags >> 16);
@@ -141,19 +112,19 @@ void QWaylandTouchExtension::touch_extension_touch(uint32_t time,
void QWaylandTouchExtension::sendTouchEvent()
{
// Copy all points, that are in the previous but not in the current list, as stationary.
- for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
+ for (int i = 0; i < mPrevTouchPoints.size(); ++i) {
const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
- if (prevPoint.state == Qt::TouchPointReleased)
+ if (prevPoint.state == QEventPoint::Released)
continue;
bool found = false;
- for (int j = 0; j < mTouchPoints.count(); ++j)
+ for (int j = 0; j < mTouchPoints.size(); ++j)
if (mTouchPoints.at(j).id == prevPoint.id) {
found = true;
break;
}
if (!found) {
QWindowSystemInterface::TouchPoint p = prevPoint;
- p.state = Qt::TouchPointStationary;
+ p.state = QEventPoint::Stationary;
mTouchPoints.append(p);
}
}
@@ -165,22 +136,28 @@ void QWaylandTouchExtension::sendTouchEvent()
QWindowSystemInterface::handleTouchEvent(mTargetWindow, mTimestamp, mTouchDevice, mTouchPoints);
- Qt::TouchPointStates states = 0;
- for (int i = 0; i < mTouchPoints.count(); ++i)
+ QEventPoint::States states = {};
+ for (int i = 0; i < mTouchPoints.size(); ++i)
states |= mTouchPoints.at(i).state;
if (mFlags & QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH) {
- if (states == Qt::TouchPointPressed)
+ const bool firstPress = states == QEventPoint::Pressed;
+ if (firstPress)
mMouseSourceId = mTouchPoints.first().id;
- for (int i = 0; i < mTouchPoints.count(); ++i) {
+ for (int i = 0; i < mTouchPoints.size(); ++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 == QEventPoint::Released;
+ 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;
@@ -191,7 +168,7 @@ void QWaylandTouchExtension::sendTouchEvent()
mPrevTouchPoints = mTouchPoints;
mTouchPoints.clear();
- if (states == Qt::TouchPointReleased)
+ if (states == QEventPoint::Released)
mPrevTouchPoints.clear();
}
@@ -200,7 +177,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/qwaylandtouch_p.h b/src/client/qwaylandtouch_p.h
index 93a829e21..e283f9009 100644
--- a/src/client/qwaylandtouch_p.h
+++ b/src/client/qwaylandtouch_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDTOUCH_H
#define QWAYLANDTOUCH_H
@@ -55,6 +19,7 @@
#include <QtWaylandClient/private/qwayland-touch-extension.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -63,10 +28,11 @@ namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandInputDevice;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandTouchExtension : public QtWayland::qt_touch_extension
+class Q_WAYLANDCLIENT_EXPORT QWaylandTouchExtension : public QtWayland::qt_touch_extension
{
public:
QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id);
+ ~QWaylandTouchExtension() override;
void touchCanceled();
@@ -95,7 +61,7 @@ private:
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
- QTouchDevice *mTouchDevice = nullptr;
+ QPointingDevice *mTouchDevice = nullptr;
uint32_t mTimestamp;
int mPointsLeft;
uint32_t mFlags;
diff --git a/src/client/qwaylandviewport.cpp b/src/client/qwaylandviewport.cpp
new file mode 100644
index 000000000..3252718c0
--- /dev/null
+++ b/src/client/qwaylandviewport.cpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandviewport_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandViewport::QWaylandViewport(::wp_viewport *viewport)
+ : QtWayland::wp_viewport(viewport)
+{
+}
+
+QWaylandViewport::~QWaylandViewport()
+{
+ destroy();
+}
+
+void QWaylandViewport::setSource(const QRectF &source)
+{
+ set_source(wl_fixed_from_double(source.x()),
+ wl_fixed_from_double(source.y()),
+ wl_fixed_from_double(source.width()),
+ wl_fixed_from_double(source.height()));
+}
+
+void QWaylandViewport::setDestination(const QSize &destination)
+{
+ set_destination(destination.width(), destination.height());
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandviewport_p.h b/src/client/qwaylandviewport_p.h
new file mode 100644
index 000000000..e1dfeb3a7
--- /dev/null
+++ b/src/client/qwaylandviewport_p.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDVIEWPORT_P_H
+#define QWAYLANDVIEWPORT_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-viewporter.h>
+#include <QtWaylandClient/qtwaylandclientglobal.h>
+
+#include <QRect>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandViewport : public QtWayland::wp_viewport
+{
+public:
+ explicit QWaylandViewport(::wp_viewport *viewport);
+ ~QWaylandViewport() override;
+
+ void setSource(const QRectF &source);
+ void setDestination(const QSize &destination);
+
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDVIEWPORT_P_H
diff --git a/src/client/qwaylandvulkaninstance.cpp b/src/client/qwaylandvulkaninstance.cpp
index 5edbd4757..be55130a4 100644
--- a/src/client/qwaylandvulkaninstance.cpp
+++ b/src/client/qwaylandvulkaninstance.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandvulkaninstance_p.h"
#include "qwaylandwindow_p.h"
@@ -124,9 +88,39 @@ void QWaylandVulkanInstance::presentAboutToBeQueued(QWindow *window)
qWarning() << "Attempted to call presentAboutToBeQueued() without a valid platform window";
return;
}
+
+ bool ok;
+ int frameCallbackTimeout = qEnvironmentVariableIntValue("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", &ok);
+
+ if (ok)
+ mFrameCallbackTimeout = frameCallbackTimeout;
+
+ if (w->format().swapInterval() > 0)
+ w->waitForFrameSync(mFrameCallbackTimeout);
+
w->handleUpdate();
}
+void QWaylandVulkanInstance::beginFrame(QWindow *window)
+{
+ auto *w = static_cast<QWaylandWindow *>(window->handle());
+ if (!w) {
+ qWarning() << "Attempted to call beginFrame() without a valid platform window";
+ return;
+ }
+ w->beginFrame();
+}
+
+void QWaylandVulkanInstance::endFrame(QWindow *window)
+{
+ auto *w = static_cast<QWaylandWindow *>(window->handle());
+ if (!w) {
+ qWarning() << "Attempted to call endFrame() without a valid platform window";
+ return;
+ }
+ w->endFrame();
+}
+
} // namespace QtWaylandClient
QT_END_NAMESPACE
diff --git a/src/client/qwaylandvulkaninstance_p.h b/src/client/qwaylandvulkaninstance_p.h
index b68293b78..7683ce566 100644
--- a/src/client/qwaylandvulkaninstance_p.h
+++ b/src/client/qwaylandvulkaninstance_p.h
@@ -1,52 +1,27 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDVULKANINSTANCE_P_H
#define QWAYLANDVULKANINSTANCE_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.
+//
+
#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 <QtGui/private/qbasicvulkanplatforminstance_p.h>
#include <QLibrary>
QT_BEGIN_NAMESPACE
@@ -67,10 +42,14 @@ public:
VkSurfaceKHR createSurface(QWaylandWindow *window);
+ void beginFrame(QWindow *window) override;
+ void endFrame(QWindow *window) override;
+
private:
QVulkanInstance *m_instance = nullptr;
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR m_getPhysDevPresSupport = nullptr;
PFN_vkCreateWaylandSurfaceKHR m_createSurface = nullptr;
+ int mFrameCallbackTimeout = 100;
};
} // namespace QtWaylandClient
diff --git a/src/client/qwaylandvulkanwindow.cpp b/src/client/qwaylandvulkanwindow.cpp
index 4c67b6b32..2bc52829d 100644
--- a/src/client/qwaylandvulkanwindow.cpp
+++ b/src/client/qwaylandvulkanwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandvulkanwindow_p.h"
@@ -43,18 +7,14 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandVulkanWindow::QWaylandVulkanWindow(QWindow *window)
- : QWaylandWindow(window)
+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);
- }
+ invalidateSurface();
}
QWaylandWindow::WindowType QWaylandVulkanWindow::windowType() const
@@ -62,7 +22,18 @@ QWaylandWindow::WindowType QWaylandVulkanWindow::windowType() const
return QWaylandWindow::Vulkan;
}
-VkSurfaceKHR *QWaylandVulkanWindow::surface()
+void QWaylandVulkanWindow::invalidateSurface()
+{
+ if (m_surface) {
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (inst)
+ static_cast<QWaylandVulkanInstance *>(inst->handle())->destroySurface(m_surface);
+ }
+ m_surface = VK_NULL_HANDLE;
+ QWaylandWindow::invalidateSurface();
+}
+
+VkSurfaceKHR *QWaylandVulkanWindow::vkSurface()
{
if (m_surface)
return &m_surface;
diff --git a/src/client/qwaylandvulkanwindow_p.h b/src/client/qwaylandvulkanwindow_p.h
index d0b2de75d..c5692bc7f 100644
--- a/src/client/qwaylandvulkanwindow_p.h
+++ b/src/client/qwaylandvulkanwindow_p.h
@@ -1,45 +1,20 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDVULKANWINDOW_P_H
#define QWAYLANDVULKANWINDOW_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 "qwaylandwindow_p.h"
#include "qwaylandvulkaninstance_p.h"
@@ -50,12 +25,13 @@ namespace QtWaylandClient {
class QWaylandVulkanWindow : public QWaylandWindow
{
public:
- explicit QWaylandVulkanWindow(QWindow *window);
+ explicit QWaylandVulkanWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandVulkanWindow() override;
WindowType windowType() const override;
+ void invalidateSurface() override;
- VkSurfaceKHR *surface();
+ VkSurfaceKHR *vkSurface();
private:
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index bffb57015..e311b2eb4 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandwindow_p.h"
@@ -43,15 +7,17 @@
#include "qwaylanddisplay_p.h"
#include "qwaylandsurface_p.h"
#include "qwaylandinputdevice_p.h"
+#include "qwaylandfractionalscale_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandshellsurface_p.h"
#include "qwaylandsubsurface_p.h"
#include "qwaylandabstractdecoration_p.h"
-#include "qwaylandwindowmanagerintegration_p.h"
+#include "qwaylandplatformservices_p.h"
#include "qwaylandnativeinterface_p.h"
#include "qwaylanddecorationfactory_p.h"
#include "qwaylandshmbackingstore_p.h"
#include "qwaylandshellintegration_p.h"
+#include "qwaylandviewport_p.h"
#include <QtCore/QFileInfo>
#include <QtCore/QPointer>
@@ -60,38 +26,56 @@
#include <QGuiApplication>
#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
#include <QtCore/QDebug>
#include <QtCore/QThread>
+#include <QtCore/private/qthread_p.h>
+
+#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace QtWaylandClient {
Q_LOGGING_CATEGORY(lcWaylandBackingstore, "qt.qpa.wayland.backingstore")
QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
+QWaylandWindow *QWaylandWindow::mTopPopup = nullptr;
-QWaylandWindow::QWaylandWindow(QWindow *window)
+QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
: QPlatformWindow(window)
- , mDisplay(waylandScreen()->display())
- , mFrameQueue(mDisplay->createEventQueue())
+ , mDisplay(display)
+ , mSurfaceLock(QReadWriteLock::Recursive)
+ , mShellIntegration(display->shellIntegration())
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
{
+ {
+ bool ok;
+ int frameCallbackTimeout = qEnvironmentVariableIntValue("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", &ok);
+ if (ok)
+ mFrameCallbackTimeout = frameCallbackTimeout;
+ }
+
static WId id = 1;
mWindowId = id++;
initializeWlSurface();
+
+ connect(this, &QWaylandWindow::wlSurfaceCreated, this,
+ &QNativeInterface::Private::QWaylandWindow::surfaceCreated);
+ connect(this, &QWaylandWindow::wlSurfaceDestroyed, this,
+ &QNativeInterface::Private::QWaylandWindow::surfaceDestroyed);
}
QWaylandWindow::~QWaylandWindow()
{
- mDisplay->handleWindowDestroyed(this);
-
delete mWindowDecoration;
if (mSurface)
- reset(false);
+ reset();
const QWindow *parent = window();
const auto tlw = QGuiApplication::topLevelWindows();
@@ -107,8 +91,10 @@ QWaylandWindow::~QWaylandWindow()
void QWaylandWindow::ensureSize()
{
- if (mBackingStore)
- mBackingStore->ensureSize();
+ if (mBackingStore) {
+ setBackingStore(mBackingStore);
+ mBackingStore->recreateBackBufferIfNeeded();
+ }
}
void QWaylandWindow::initWindow()
@@ -118,51 +104,76 @@ void QWaylandWindow::initWindow()
if (!mSurface) {
initializeWlSurface();
- QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
- QGuiApplication::sendEvent(window(), &e);
+ }
+
+ if (mDisplay->fractionalScaleManager() && qApp->highDpiScaleFactorRoundingPolicy() == Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) {
+ mFractionalScale.reset(new QWaylandFractionalScale(mDisplay->fractionalScaleManager()->get_fractional_scale(mSurface->object())));
+
+ connect(mFractionalScale.data(), &QWaylandFractionalScale::preferredScaleChanged,
+ this, &QWaylandWindow::updateScale);
}
if (shouldCreateSubSurface()) {
Q_ASSERT(!mSubSurfaceWindow);
- QWaylandWindow *p = static_cast<QWaylandWindow *>(QPlatformWindow::parent());
- if (::wl_subsurface *ss = mDisplay->createSubSurface(this, p)) {
- mSubSurfaceWindow = new QWaylandSubSurface(this, p, ss);
+ auto *parent = static_cast<QWaylandWindow *>(QPlatformWindow::parent());
+ if (!parent->mSurface)
+ parent->initializeWlSurface();
+ if (parent->wlSurface()) {
+ if (::wl_subsurface *subsurface = mDisplay->createSubSurface(this, parent))
+ mSubSurfaceWindow = new QWaylandSubSurface(this, parent, subsurface);
}
} else if (shouldCreateShellSurface()) {
Q_ASSERT(!mShellSurface);
- Q_ASSERT(mDisplay->shellIntegration());
+ Q_ASSERT(mShellIntegration);
+ mTransientParent = guessTransientParent();
+ if (mTransientParent) {
+ if (window()->type() == Qt::Popup) {
+ if (mTopPopup && mTopPopup != mTransientParent) {
+ qCWarning(lcQpaWayland) << "Creating a popup with a parent," << mTransientParent->window()
+ << "which does not match the current topmost grabbing popup,"
+ << mTopPopup->window() << "With some shell surface protocols, this"
+ << "is not allowed. The wayland QPA plugin is currently handling"
+ << "it by setting the parent to the topmost grabbing popup."
+ << "Note, however, that this may cause positioning errors and"
+ << "popups closing unxpectedly. Please fix the transient parent of the popup.";
+ mTransientParent = mTopPopup;
+ }
+ mTopPopup = this;
+ }
+ }
- mShellSurface = mDisplay->shellIntegration()->createShellSurface(this);
+ mShellSurface = mShellIntegration->createShellSurface(this);
if (mShellSurface) {
+ if (mTransientParent) {
+ if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup)
+ mTransientParent->addChildPopup(this);
+ }
+
// Set initial surface title
setWindowTitle(window()->title());
// The appId is the desktop entry identifier that should follow the
- // reverse DNS convention (see http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html).
- // According to xdg-shell the appId is only the name, without
- // the .desktop suffix.
+ // reverse DNS convention (see
+ // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html). According
+ // to xdg-shell the appId is only the name, without the .desktop suffix.
//
- // If the application specifies the desktop file name use that
- // removing the ".desktop" suffix, otherwise fall back to the
- // executable name and prepend the reversed organization domain
- // when available.
+ // If the application specifies the desktop file name use that,
+ // otherwise fall back to the executable name and prepend the
+ // reversed organization domain when available.
if (!QGuiApplication::desktopFileName().isEmpty()) {
- QString name = QGuiApplication::desktopFileName();
- if (name.endsWith(QLatin1String(".desktop")))
- name.chop(8);
- mShellSurface->setAppId(name);
+ mShellSurface->setAppId(QGuiApplication::desktopFileName());
} else {
- QFileInfo fi = QCoreApplication::instance()->applicationFilePath();
+ QFileInfo fi = QFileInfo(QCoreApplication::instance()->applicationFilePath());
QStringList domainName =
QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'),
- QString::SkipEmptyParts);
+ Qt::SkipEmptyParts);
if (domainName.isEmpty()) {
mShellSurface->setAppId(fi.baseName());
} else {
QString appId;
- for (int i = 0; i < domainName.count(); ++i)
+ for (int i = 0; i < domainName.size(); ++i)
appId.prepend(QLatin1Char('.')).prepend(domainName.at(i));
appId.append(fi.baseName());
mShellSurface->setAppId(appId);
@@ -171,31 +182,43 @@ void QWaylandWindow::initWindow()
// the user may have already set some window properties, so make sure to send them out
for (auto it = m_properties.cbegin(); it != m_properties.cend(); ++it)
mShellSurface->sendProperty(it.key(), it.value());
+
+ emit surfaceRoleCreated();
} else {
qWarning("Could not create a shell surface object.");
}
}
- mScale = waylandScreen()->scale();
+ // The fractional scale manager check is needed to work around Gnome < 36 where viewports don't work
+ // Right now viewports are only necessary when a fractional scale manager is used
+ if (display()->viewporter() && display()->fractionalScaleManager()) {
+ mViewport.reset(new QWaylandViewport(display()->createViewport(this)));
+ }
// 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()
// to inform the compositor that high-resolution buffers will be provided.
- if (mDisplay->compositorVersion() >= 3)
- mSurface->set_buffer_scale(scale());
+ if (mViewport)
+ updateViewport();
+ else if (mSurface->version() >= 3)
+ mSurface->set_buffer_scale(std::ceil(scale()));
- if (QScreen *s = window()->screen())
- setOrientationMask(s->orientationUpdateMask());
setWindowFlags(window()->flags());
- if (window()->geometry().isEmpty())
- setGeometry_helper(QRect(QPoint(), QSize(500,500)));
- else
- setGeometry_helper(window()->geometry());
+ QRect geometry = windowGeometry();
+ QRect defaultGeometry = this->defaultGeometry();
+ if (geometry.width() <= 0)
+ geometry.setWidth(defaultGeometry.width());
+ if (geometry.height() <= 0)
+ geometry.setHeight(defaultGeometry.height());
+
+ setGeometry_helper(geometry);
setMask(window()->mask());
if (mShellSurface)
mShellSurface->requestWindowStates(window()->windowStates());
handleContentOrientationChange(window()->contentOrientation());
mFlags = window()->flags();
+
+ mSurface->commit();
}
void QWaylandWindow::initializeWlSurface()
@@ -206,14 +229,28 @@ void QWaylandWindow::initializeWlSurface()
mSurface.reset(new QWaylandSurface(mDisplay));
connect(mSurface.data(), &QWaylandSurface::screensChanged,
this, &QWaylandWindow::handleScreensChanged);
+ connect(mSurface.data(), &QWaylandSurface::preferredBufferScaleChanged,
+ this, &QWaylandWindow::updateScale);
+ connect(mSurface.data(), &QWaylandSurface::preferredBufferTransformChanged,
+ this, &QWaylandWindow::updateBufferTransform);
mSurface->m_window = this;
}
emit wlSurfaceCreated();
}
+void QWaylandWindow::setShellIntegration(QWaylandShellIntegration *shellIntegration)
+{
+ Q_ASSERT(shellIntegration);
+ if (mShellSurface) {
+ qCWarning(lcQpaWayland) << "Cannot set shell integration while there's already a shell surface created";
+ return;
+ }
+ mShellIntegration = shellIntegration;
+}
+
bool QWaylandWindow::shouldCreateShellSurface() const
{
- if (!mDisplay->shellIntegration())
+ if (!shellIntegration())
return false;
if (shouldCreateSubSurface())
@@ -233,36 +270,76 @@ bool QWaylandWindow::shouldCreateSubSurface() const
return QPlatformWindow::parent() != nullptr;
}
-void QWaylandWindow::reset(bool sendDestroyEvent)
+void QWaylandWindow::beginFrame()
{
- if (mSurface && sendDestroyEvent) {
- QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
- QGuiApplication::sendEvent(window(), &e);
- }
- delete mShellSurface;
- mShellSurface = nullptr;
- delete mSubSurfaceWindow;
- mSubSurfaceWindow = nullptr;
+ mSurfaceLock.lockForRead();
+}
+
+void QWaylandWindow::endFrame()
+{
+ mSurfaceLock.unlock();
+}
+
+void QWaylandWindow::reset()
+{
+ closeChildPopups();
+
+ if (mTopPopup == this)
+ mTopPopup = mTransientParent && (mTransientParent->window()->type() == Qt::Popup) ? mTransientParent : nullptr;
+
if (mSurface) {
+ {
+ QWriteLocker lock(&mSurfaceLock);
+ invalidateSurface();
+ if (mTransientParent)
+ mTransientParent->removeChildPopup(this);
+ delete mShellSurface;
+ mShellSurface = nullptr;
+ emit surfaceRoleDestroyed();
+ delete mSubSurfaceWindow;
+ mSubSurfaceWindow = nullptr;
+ mTransientParent = nullptr;
+ mSurface.reset();
+ mViewport.reset();
+ mFractionalScale.reset();
+ }
emit wlSurfaceDestroyed();
- QWriteLocker lock(&mSurfaceLock);
- mSurface.reset();
}
- if (mFrameCallback) {
- wl_callback_destroy(mFrameCallback);
- mFrameCallback = nullptr;
- }
+ {
+ QMutexLocker lock(&mFrameSyncMutex);
+ if (mFrameCallback) {
+ wl_callback_destroy(mFrameCallback);
+ mFrameCallback = nullptr;
+ }
- int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
- if (timerId != -1) {
- killTimer(timerId);
+ mFrameCallbackElapsedTimer.invalidate();
+ mWaitingForFrameCallback = false;
}
- mWaitingForFrameCallback = false;
+ if (mFrameCallbackCheckIntervalTimerId != -1) {
+ killTimer(mFrameCallbackCheckIntervalTimerId);
+ mFrameCallbackCheckIntervalTimerId = -1;
+ }
+
mFrameCallbackTimedOut = false;
+ mWaitingToApplyConfigure = false;
+ mCanResize = true;
+ mResizeDirty = false;
+ mScale = std::nullopt;
+ mOpaqueArea = QRegion();
mMask = QRegion();
+
+ mInputRegion = QRegion();
+ mTransparentInputRegion = false;
+
+ if (mQueuedBuffer) {
+ mQueuedBuffer->setBusy(false);
+ }
mQueuedBuffer = nullptr;
+ mQueuedBufferDamage = QRegion();
+
+ mDisplay->handleWindowDestroyed(this);
}
QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
@@ -296,27 +373,34 @@ void QWaylandWindow::setParent(const QPlatformWindow *parent)
}
}
+QString QWaylandWindow::windowTitle() const
+{
+ return mWindowTitle;
+}
+
void QWaylandWindow::setWindowTitle(const QString &title)
{
- if (mShellSurface) {
- const QString separator = QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH
- const QString formatted = formatWindowTitle(title, separator);
-
- const int libwaylandMaxBufferSize = 4096;
- // Some parts of the buffer is used for metadata, so subtract 100 to be on the safe side.
- // Also, QString is in utf-16, which means that in the worst case each character will be
- // three bytes when converted to utf-8 (which is what libwayland uses), so divide by three.
- const int maxLength = libwaylandMaxBufferSize / 3 - 100;
-
- auto truncated = QStringRef(&formatted).left(maxLength);
- if (truncated.length() < formatted.length()) {
- qCWarning(lcQpaWayland) << "Window titles longer than" << maxLength << "characters are not supported."
- << "Truncating window title (from" << formatted.length() << "chars)";
- }
- mShellSurface->setTitle(truncated.toString());
+ const QString separator = QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH
+ const QString formatted = formatWindowTitle(title, separator);
+
+ const int libwaylandMaxBufferSize = 4096;
+ // Some parts of the buffer is used for metadata, so subtract 100 to be on the safe side.
+ // Also, QString is in utf-16, which means that in the worst case each character will be
+ // three bytes when converted to utf-8 (which is what libwayland uses), so divide by three.
+ const int maxLength = libwaylandMaxBufferSize / 3 - 100;
+
+ auto truncated = QStringView{formatted}.left(maxLength);
+ if (truncated.size() < formatted.size()) {
+ qCWarning(lcQpaWayland) << "Window titles longer than" << maxLength << "characters are not supported."
+ << "Truncating window title (from" << formatted.size() << "chars)";
}
- if (mWindowDecoration && window()->isVisible())
+ mWindowTitle = truncated.toString();
+
+ if (mShellSurface)
+ mShellSurface->setTitle(mWindowTitle);
+
+ if (mWindowDecorationEnabled && window()->isVisible())
mWindowDecoration->update();
}
@@ -324,51 +408,131 @@ void QWaylandWindow::setWindowIcon(const QIcon &icon)
{
mWindowIcon = icon;
- if (mWindowDecoration && window()->isVisible())
+ if (mWindowDecorationEnabled && window()->isVisible())
mWindowDecoration->update();
}
+QRect QWaylandWindow::defaultGeometry() const
+{
+ return QRect(QPoint(), QSize(500,500));
+}
+
void QWaylandWindow::setGeometry_helper(const QRect &rect)
{
- QPlatformWindow::setGeometry(QRect(rect.x(), rect.y(),
- qBound(window()->minimumWidth(), rect.width(), window()->maximumWidth()),
- qBound(window()->minimumHeight(), rect.height(), window()->maximumHeight())));
+ QPlatformWindow::setGeometry(rect);
+ if (mViewport)
+ updateViewport();
if (mSubSurfaceWindow) {
- QMargins m = QPlatformWindow::parent()->frameMargins();
+ QMargins m = static_cast<QWaylandWindow *>(QPlatformWindow::parent())->clientSideMargins();
mSubSurfaceWindow->set_position(rect.x() + m.left(), rect.y() + m.top());
- mSubSurfaceWindow->parent()->window()->requestUpdate();
+
+ QWaylandWindow *parentWindow = mSubSurfaceWindow->parent();
+ if (parentWindow && parentWindow->isExposed()) {
+ QRect parentExposeGeometry(QPoint(), parentWindow->geometry().size());
+ parentWindow->sendExposeEvent(parentExposeGeometry);
+ }
}
}
-void QWaylandWindow::setGeometry(const QRect &rect)
+void QWaylandWindow::setGeometry(const QRect &r)
{
+ auto rect = r;
+ if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
+ && window()->type() != Qt::ToolTip) {
+ rect.moveTo(screen()->geometry().topLeft());
+ }
setGeometry_helper(rect);
if (window()->isVisible() && rect.isValid()) {
- if (mWindowDecoration)
+ if (mWindowDecorationEnabled)
mWindowDecoration->update();
- if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize)
+ if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize) {
+ QMutexLocker lock(&mResizeLock);
mResizeDirty = true;
- else
+ } else {
QWindowSystemInterface::handleGeometryChange(window(), geometry());
-
+ }
mSentInitialResize = true;
}
QRect exposeGeometry(QPoint(), geometry().size());
if (isExposed() && !mInResizeFromApplyConfigure && exposeGeometry != mLastExposeGeometry)
sendExposeEvent(exposeGeometry);
- if (mShellSurface)
+ if (mShellSurface) {
mShellSurface->setWindowGeometry(windowContentGeometry());
+ if (!qt_window_private(window())->positionAutomatic && !mInResizeFromApplyConfigure)
+ mShellSurface->setWindowPosition(windowGeometry().topLeft());
+ }
+
+ if (isOpaque() && mMask.isEmpty())
+ setOpaqueArea(QRect(QPoint(0, 0), rect.size()));
+}
+
+void QWaylandWindow::updateInputRegion()
+{
+ if (!mSurface)
+ return;
+
+ const bool transparentInputRegion = mFlags.testFlag(Qt::WindowTransparentForInput);
+
+ QRegion inputRegion;
+ if (!transparentInputRegion)
+ inputRegion = mMask;
+
+ if (mInputRegion == inputRegion && mTransparentInputRegion == transparentInputRegion)
+ return;
+
+ mInputRegion = inputRegion;
+ mTransparentInputRegion = transparentInputRegion;
+
+ if (mInputRegion.isEmpty() && !mTransparentInputRegion) {
+ mSurface->set_input_region(nullptr);
+ } else {
+ struct ::wl_region *region = mDisplay->createRegion(mInputRegion);
+ mSurface->set_input_region(region);
+ wl_region_destroy(region);
+ }
+}
+
+void QWaylandWindow::updateViewport()
+{
+ if (!surfaceSize().isEmpty())
+ mViewport->setDestination(surfaceSize());
+}
+
+void QWaylandWindow::setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins)
+{
+ QMargins margins = clientSideMargins();
+
+ QPoint positionWithoutMargins = globalPosition + QPoint(margins.left(), margins.top());
+ int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
+ int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
+
+ QRect geometry(positionWithoutMargins, QSize(widthWithoutMargins, heightWithoutMargins));
+
+ mInResizeFromApplyConfigure = true;
+ setGeometry(geometry);
+ mInResizeFromApplyConfigure = false;
+}
+
+void QWaylandWindow::repositionFromApplyConfigure(const QPoint &globalPosition)
+{
+ QMargins margins = clientSideMargins();
+ QPoint positionWithoutMargins = globalPosition + QPoint(margins.left(), margins.top());
+
+ QRect geometry(positionWithoutMargins, windowGeometry().size());
+ mInResizeFromApplyConfigure = true;
+ setGeometry(geometry);
+ mInResizeFromApplyConfigure = false;
}
void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
{
- QMargins margins = frameMargins();
- int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left()+margins.right()), 1);
- int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top()+margins.bottom()), 1);
+ QMargins margins = clientSideMargins();
+ int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
+ int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
QRect geometry(windowGeometry().topLeft(), QSize(widthWithoutMargins, heightWithoutMargins));
mOffset += offset;
@@ -386,47 +550,35 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
mLastExposeGeometry = rect;
}
-
-static QVector<QPointer<QWaylandWindow>> activePopups;
-
-void QWaylandWindow::closePopups(QWaylandWindow *parent)
-{
- while (!activePopups.isEmpty()) {
- auto popup = activePopups.takeLast();
- if (popup.isNull())
- continue;
- if (popup.data() == parent)
- return;
- popup->reset();
- }
-}
-
-QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
+QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
{
+ QReadLocker lock(&mSurfaceLock);
if (mSurface) {
if (auto *screen = mSurface->oldestEnteredScreen())
return screen;
}
-
- return waylandScreen();
+ return QPlatformWindow::screen();
}
void QWaylandWindow::setVisible(bool visible)
{
+ // Workaround for issue where setVisible may be called with the same value twice
+ if (lastVisible == visible)
+ return;
+ lastVisible = visible;
+
if (visible) {
- if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
- activePopups << this;
initWindow();
- mDisplay->flushRequests();
- setGeometry(window()->geometry());
+ setGeometry(windowGeometry());
// Don't flush the events here, or else the newly visible window may start drawing, but since
// there was no frame before it will be stuck at the waitForFrameSync() in
// QWaylandShmBackingStore::beginPaint().
+
+ if (mShellSurface)
+ mShellSurface->requestActivateOnShow();
} else {
sendExposeEvent(QRect());
- if (window()->type() == Qt::Popup)
- closePopups(this);
reset();
}
}
@@ -447,23 +599,37 @@ void QWaylandWindow::lower()
void QWaylandWindow::setMask(const QRegion &mask)
{
+ QReadLocker locker(&mSurfaceLock);
+ if (!mSurface)
+ return;
+
if (mMask == mask)
return;
mMask = mask;
- if (!mSurface)
- return;
+ updateInputRegion();
- if (mMask.isEmpty()) {
- mSurface->set_input_region(nullptr);
- } else {
- struct ::wl_region *region = mDisplay->createRegion(mMask);
- mSurface->set_input_region(region);
- wl_region_destroy(region);
+ if (isOpaque()) {
+ if (mMask.isEmpty())
+ setOpaqueArea(QRect(QPoint(0, 0), geometry().size()));
+ else
+ setOpaqueArea(mMask);
}
+}
- mSurface->commit();
+void QWaylandWindow::setAlertState(bool enabled)
+{
+ if (mShellSurface)
+ mShellSurface->setAlertState(enabled);
+}
+
+bool QWaylandWindow::isAlertState() const
+{
+ if (mShellSurface)
+ return mShellSurface->isAlertState();
+
+ return false;
}
void QWaylandWindow::applyConfigureWhenPossible()
@@ -480,12 +646,24 @@ void QWaylandWindow::doApplyConfigure()
if (!mWaitingToApplyConfigure)
return;
+ Q_ASSERT_X(QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed(),
+ "QWaylandWindow::doApplyConfigure", "not called from main thread");
+
if (mShellSurface)
mShellSurface->applyConfigure();
mWaitingToApplyConfigure = false;
}
+void QWaylandWindow::doApplyConfigureFromOtherThread()
+{
+ QMutexLocker lock(&mResizeLock);
+ if (!mCanResize || !mWaitingToApplyConfigure)
+ return;
+ doApplyConfigure();
+ sendRecursiveExposeEvent();
+}
+
void QWaylandWindow::setCanResize(bool canResize)
{
QMutexLocker lock(&mResizeLock);
@@ -496,8 +674,13 @@ void QWaylandWindow::setCanResize(bool canResize)
QWindowSystemInterface::handleGeometryChange(window(), geometry());
}
if (mWaitingToApplyConfigure) {
- doApplyConfigure();
- sendExposeEvent(QRect(QPoint(), geometry().size()));
+ bool inGuiThread = QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed();
+ if (inGuiThread) {
+ doApplyConfigure();
+ sendRecursiveExposeEvent();
+ } else {
+ QMetaObject::invokeMethod(this, &QWaylandWindow::doApplyConfigureFromOtherThread, Qt::QueuedConnection);
+ }
} else if (mResizeDirty) {
mResizeDirty = false;
sendExposeEvent(QRect(QPoint(), geometry().size()));
@@ -513,18 +696,39 @@ void QWaylandWindow::applyConfigure()
doApplyConfigure();
lock.unlock();
- sendExposeEvent(QRect(QPoint(), geometry().size()));
+ sendRecursiveExposeEvent();
QWindowSystemInterface::flushWindowSystemEvents();
}
+void QWaylandWindow::sendRecursiveExposeEvent()
+{
+ if (!isExposed())
+ sendExposeEvent(QRect());
+ else
+ sendExposeEvent(QRect(QPoint(), geometry().size()));
+
+ for (QWaylandSubSurface *subSurface : std::as_const(mChildren)) {
+ auto subWindow = subSurface->window();
+ subWindow->sendRecursiveExposeEvent();
+ }
+}
+
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
{
- Q_ASSERT(!buffer->committed());
+ QReadLocker locker(&mSurfaceLock);
+ if (mSurface == nullptr)
+ return;
+
if (buffer) {
+ Q_ASSERT(!buffer->committed());
handleUpdate();
- buffer->setBusy();
-
- mSurface->attach(buffer->buffer(), x, y);
+ buffer->setBusy(true);
+ if (mSurface->version() >= WL_SURFACE_OFFSET_SINCE_VERSION) {
+ mSurface->offset(x, y);
+ mSurface->attach(buffer->buffer(), 0, 0);
+ } else {
+ mSurface->attach(buffer->buffer(), x, y);
+ }
} else {
mSurface->attach(nullptr, 0, 0);
}
@@ -538,7 +742,20 @@ void QWaylandWindow::attachOffset(QWaylandBuffer *buffer)
void QWaylandWindow::damage(const QRect &rect)
{
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+ QReadLocker locker(&mSurfaceLock);
+ if (mSurface == nullptr)
+ return;
+
+ const qreal s = scale();
+ if (mSurface->version() >= 4) {
+ const QRect bufferRect =
+ QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
+ .toAlignedRect();
+ mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
+ bufferRect.height());
+ } else {
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+ }
}
void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
@@ -546,21 +763,15 @@ void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
if (isExposed()) {
commit(buffer, damage);
} else {
+ if (mQueuedBuffer) {
+ mQueuedBuffer->setBusy(false);
+ }
mQueuedBuffer = buffer;
+ mQueuedBuffer->setBusy(true);
mQueuedBufferDamage = damage;
}
}
-void QWaylandWindow::handleExpose(const QRegion &region)
-{
- QWindowSystemInterface::handleExposeEvent(window(), region);
- if (mQueuedBuffer) {
- commit(mQueuedBuffer, mQueuedBufferDamage);
- mQueuedBuffer = nullptr;
- mQueuedBufferDamage = QRegion();
- }
-}
-
void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
{
Q_ASSERT(isExposed());
@@ -568,12 +779,25 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
qCDebug(lcWaylandBackingstore) << "Buffer already committed, ignoring.";
return;
}
+
+ QReadLocker locker(&mSurfaceLock);
if (!mSurface)
return;
attachOffset(buffer);
- for (const QRect &rect: damage)
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+ if (mSurface->version() >= 4) {
+ const qreal s = scale();
+ for (const QRect &rect : damage) {
+ const QRect bufferRect =
+ QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
+ .toAlignedRect();
+ mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
+ bufferRect.height());
+ }
+ } else {
+ for (const QRect &rect: damage)
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+ }
Q_ASSERT(!buffer->committed());
buffer->setCommitted();
mSurface->commit();
@@ -581,55 +805,61 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
void QWaylandWindow::commit()
{
- mSurface->commit();
+ QReadLocker locker(&mSurfaceLock);
+ if (mSurface != nullptr)
+ mSurface->commit();
}
const wl_callback_listener QWaylandWindow::callbackListener = {
[](void *data, wl_callback *callback, uint32_t time) {
- Q_UNUSED(callback);
Q_UNUSED(time);
auto *window = static_cast<QWaylandWindow*>(data);
- window->handleFrameCallback();
+ window->handleFrameCallback(callback);
}
};
-void QWaylandWindow::handleFrameCallback()
+void QWaylandWindow::handleFrameCallback(wl_callback* callback)
{
- // Stop the timer and stop waiting immediately
- int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
+ QMutexLocker locker(&mFrameSyncMutex);
+ if (!mFrameCallback) {
+ // This means the callback is already unset by QWaylandWindow::reset.
+ // The wl_callback object will be destroyed there too.
+ return;
+ }
+ Q_ASSERT(callback == mFrameCallback);
+ wl_callback_destroy(callback);
+ mFrameCallback = nullptr;
+
mWaitingForFrameCallback = false;
+ mFrameCallbackElapsedTimer.invalidate();
// The rest can wait until we can run it on the correct thread
- auto doHandleExpose = [this, timerId]() {
- if (timerId != -1)
- killTimer(timerId);
-
- bool wasExposed = isExposed();
- mFrameCallbackTimedOut = false;
- if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
- sendExposeEvent(QRect(QPoint(), geometry().size()));
- if (wasExposed && hasPendingUpdateRequest())
- deliverUpdateRequest();
- };
-
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this, doHandleExpose);
- } else {
- doHandleExpose();
+ if (mWaitingForUpdateDelivery.testAndSetAcquire(false, true)) {
+ // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync()
+ // in the single-threaded case.
+ QMetaObject::invokeMethod(this, &QWaylandWindow::doHandleFrameCallback, Qt::QueuedConnection);
}
+ mFrameSyncWait.notify_all();
}
-QMutex QWaylandWindow::mFrameSyncMutex;
+void QWaylandWindow::doHandleFrameCallback()
+{
+ mWaitingForUpdateDelivery.storeRelease(false);
+ bool wasExposed = isExposed();
+ mFrameCallbackTimedOut = false;
+ if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
+ sendExposeEvent(QRect(QPoint(), geometry().size()));
+ if (wasExposed && hasPendingUpdateRequest())
+ deliverUpdateRequest();
+
+}
bool QWaylandWindow::waitForFrameSync(int timeout)
{
- if (!mWaitingForFrameCallback)
- return true;
-
QMutexLocker locker(&mFrameSyncMutex);
- wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(mFrameCallback), mFrameQueue);
- mDisplay->dispatchQueueWhile(mFrameQueue, [&]() { return mWaitingForFrameCallback; }, timeout);
+ QDeadlineTimer deadline(timeout);
+ while (mWaitingForFrameCallback && mFrameSyncWait.wait(&mFrameSyncMutex, deadline)) { }
if (mWaitingForFrameCallback) {
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
@@ -638,21 +868,29 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
sendExposeEvent(QRect());
}
- // Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread
- // Ordered semantics is needed to avoid stopping the timer twice and not miss it when it's
- // started by other writes
- int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
- if (fcbId != -1)
- QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
-
return !mWaitingForFrameCallback;
}
QMargins QWaylandWindow::frameMargins() const
{
- if (mWindowDecoration)
+ if (mWindowDecorationEnabled)
return mWindowDecoration->margins();
- return QPlatformWindow::frameMargins();
+ else if (mShellSurface)
+ return mShellSurface->serverSideFrameMargins();
+ else
+ return QPlatformWindow::frameMargins();
+}
+
+QMargins QWaylandWindow::clientSideMargins() const
+{
+ return mWindowDecorationEnabled ? mWindowDecoration->margins() : QMargins{};
+}
+
+void QWaylandWindow::setCustomMargins(const QMargins &margins) {
+ const QMargins oldMargins = mCustomMargins;
+ mCustomMargins = margins;
+ propagateSizeHints();
+ setGeometry(geometry().marginsRemoved(oldMargins).marginsAdded(margins));
}
/*!
@@ -660,7 +898,20 @@ QMargins QWaylandWindow::frameMargins() const
*/
QSize QWaylandWindow::surfaceSize() const
{
- return geometry().marginsAdded(frameMargins()).size();
+ return geometry().marginsAdded(clientSideMargins()).size();
+}
+
+QMargins QWaylandWindow::windowContentMargins() const
+{
+ QMargins shadowMargins;
+
+ if (mWindowDecorationEnabled)
+ shadowMargins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsOnly);
+
+ if (!mCustomMargins.isNull())
+ shadowMargins += mCustomMargins;
+
+ return shadowMargins;
}
/*!
@@ -669,11 +920,26 @@ QSize QWaylandWindow::surfaceSize() const
*/
QRect QWaylandWindow::windowContentGeometry() const
{
- return QRect(QPoint(), surfaceSize());
+ const QMargins margins = windowContentMargins();
+ return QRect(QPoint(margins.left(), margins.top()), surfaceSize().shrunkBy(margins));
+}
+
+/*!
+ * 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 = clientSideMargins();
+ return QPointF(surfacePosition.x() - margins.left(), surfacePosition.y() - margins.top());
}
-wl_surface *QWaylandWindow::wlSurface()
+wl_surface *QWaylandWindow::wlSurface() const
{
+ QReadLocker locker(&mSurfaceLock);
return mSurface ? mSurface->object() : nullptr;
}
@@ -682,6 +948,15 @@ QWaylandShellSurface *QWaylandWindow::shellSurface() const
return mShellSurface;
}
+std::any QWaylandWindow::_surfaceRole() const
+{
+ if (mSubSurfaceWindow)
+ return mSubSurfaceWindow->object();
+ if (mShellSurface)
+ return mShellSurface->surfaceRole();
+ return {};
+}
+
QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
{
return mSubSurfaceWindow;
@@ -689,38 +964,59 @@ 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)
{
- if (mDisplay->compositorVersion() < 2)
+ mLastReportedContentOrientation = orientation;
+ updateBufferTransform();
+}
+
+void QWaylandWindow::updateBufferTransform()
+{
+ QReadLocker locker(&mSurfaceLock);
+ if (mSurface == nullptr || mSurface->version() < 2)
return;
wl_output_transform transform;
- bool isPortrait = window()->screen() && window()->screen()->primaryOrientation() == Qt::PortraitOrientation;
- switch (orientation) {
- case Qt::PrimaryOrientation:
- transform = WL_OUTPUT_TRANSFORM_NORMAL;
- break;
- case Qt::LandscapeOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_270 : WL_OUTPUT_TRANSFORM_NORMAL;
- break;
- case Qt::PortraitOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_90;
- break;
- case Qt::InvertedLandscapeOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_90 : WL_OUTPUT_TRANSFORM_180;
- break;
- case Qt::InvertedPortraitOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
- break;
- default:
- Q_UNREACHABLE();
+ Qt::ScreenOrientation screenOrientation = Qt::PrimaryOrientation;
+
+ if (mSurface->version() >= 6) {
+ const auto transform = mSurface->preferredBufferTransform().value_or(WL_OUTPUT_TRANSFORM_NORMAL);
+ if (auto screen = waylandScreen())
+ screenOrientation = screen->toScreenOrientation(transform, Qt::PrimaryOrientation);
+ } else {
+ if (auto screen = window()->screen())
+ screenOrientation = screen->primaryOrientation();
+ }
+
+ const bool isPortrait = (screenOrientation == Qt::PortraitOrientation);
+
+ switch (mLastReportedContentOrientation) {
+ case Qt::PrimaryOrientation:
+ transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ break;
+ case Qt::LandscapeOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_270 : WL_OUTPUT_TRANSFORM_NORMAL;
+ break;
+ case Qt::PortraitOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_90;
+ break;
+ case Qt::InvertedLandscapeOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_90 : WL_OUTPUT_TRANSFORM_180;
+ break;
+ case Qt::InvertedPortraitOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
+ break;
+ default:
+ Q_UNREACHABLE();
}
mSurface->set_buffer_transform(transform);
- // set_buffer_transform is double buffered, we need to commit.
- mSurface->commit();
}
void QWaylandWindow::setOrientationMask(Qt::ScreenOrientations mask)
@@ -742,10 +1038,18 @@ void QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
mFlags = flags;
createDecoration();
+
+ QReadLocker locker(&mSurfaceLock);
+ updateInputRegion();
}
bool QWaylandWindow::createDecoration()
{
+ Q_ASSERT_X(QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed(),
+ "QWaylandWindow::createDecoration", "not called from main thread");
+ // TODO: client side decorations do not work with Vulkan backend.
+ if (window()->surfaceType() == QSurface::VulkanSurface)
+ return false;
if (!mDisplay->supportsWindowDecoration())
return false;
@@ -768,12 +1072,17 @@ bool QWaylandWindow::createDecoration()
decoration = false;
if (mSubSurfaceWindow)
decoration = false;
- if (mShellSurface && !mShellSurface->wantsDecorations())
+ if (!mShellSurface || !mShellSurface->wantsDecorations())
decoration = false;
- bool hadDecoration = mWindowDecoration;
+ bool hadDecoration = mWindowDecorationEnabled;
if (decoration && !decorationPluginFailed) {
- if (!mWindowDecoration) {
+ if (!mWindowDecorationEnabled) {
+ if (mWindowDecoration) {
+ delete mWindowDecoration;
+ mWindowDecoration = nullptr;
+ }
+
QStringList decorations = QWaylandDecorationFactory::keys();
if (decorations.empty()) {
qWarning() << "No decoration plugins available. Running with no decorations.";
@@ -791,6 +1100,22 @@ bool QWaylandWindow::createDecoration()
}
}
+ if (targetKey.isEmpty()) {
+ auto unixServices = dynamic_cast<QGenericUnixServices *>(
+ QGuiApplicationPrivate::platformIntegration()->services());
+ const QByteArray currentDesktop = unixServices->desktopEnvironment();
+ if (currentDesktop == "GNOME") {
+ if (decorations.contains("adwaita"_L1))
+ targetKey = "adwaita"_L1;
+ else if (decorations.contains("gnome"_L1))
+ targetKey = "gnome"_L1;
+ } else {
+ // Do not use Adwaita/GNOME decorations on other DEs
+ decorations.removeAll("adwaita"_L1);
+ decorations.removeAll("gnome"_L1);
+ }
+ }
+
if (targetKey.isEmpty())
targetKey = decorations.first(); // first come, first served.
@@ -802,19 +1127,29 @@ bool QWaylandWindow::createDecoration()
return false;
}
mWindowDecoration->setWaylandWindow(this);
+ mWindowDecorationEnabled = true;
}
} else {
- delete mWindowDecoration;
- mWindowDecoration = nullptr;
+ mWindowDecorationEnabled = false;
}
- if (hadDecoration != (bool)mWindowDecoration) {
- for (QWaylandSubSurface *subsurf : qAsConst(mChildren)) {
+ if (hadDecoration != mWindowDecorationEnabled) {
+ for (QWaylandSubSurface *subsurf : std::as_const(mChildren)) {
QPoint pos = subsurf->window()->geometry().topLeft();
QMargins m = frameMargins();
subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
}
- sendExposeEvent(QRect(QPoint(), geometry().size()));
+ setGeometry(geometry());
+
+ // creating a decoration changes our margins which in turn change size hints
+ propagateSizeHints();
+
+ // This is a special case where the buffer is recreated, but since
+ // the content rect remains the same, the widgets remain the same
+ // size and are not redrawn, leaving the new buffer empty. As a simple
+ // work-around, we trigger a full extra update whenever the client-side
+ // window decorations are toggled while the window is showing.
+ window()->requestUpdate();
}
return mWindowDecoration;
@@ -822,7 +1157,7 @@ bool QWaylandWindow::createDecoration()
QWaylandAbstractDecoration *QWaylandWindow::decoration() const
{
- return mWindowDecoration;
+ return mWindowDecorationEnabled ? mWindowDecoration : nullptr;
}
static QWaylandWindow *closestShellSurfaceWindow(QWindow *window)
@@ -838,22 +1173,32 @@ static QWaylandWindow *closestShellSurfaceWindow(QWindow *window)
QWaylandWindow *QWaylandWindow::transientParent() const
{
+ return mTransientParent;
+}
+
+QWaylandWindow *QWaylandWindow::guessTransientParent() const
+{
// Take the closest window with a shell surface, since the transient parent may be a
// QWidgetWindow or some other window without a shell surface, which is then not able to
// get mouse events.
if (auto transientParent = closestShellSurfaceWindow(window()->transientParent()))
return transientParent;
- if (QGuiApplication::focusWindow() && (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup))
- return closestShellSurfaceWindow(QGuiApplication::focusWindow());
+ if (window()->type() == Qt::Popup) {
+ if (mTopPopup)
+ return mTopPopup;
+ }
+
+ if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup)
+ return display()->lastInputWindow();
return nullptr;
}
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{
- if (e.type == QWaylandPointerEvent::Leave) {
- if (mWindowDecoration) {
+ if (e.type == QEvent::Leave) {
+ if (mWindowDecorationEnabled) {
if (mMouseEventsInContentArea)
QWindowSystemInterface::handleLeaveEvent(window());
} else {
@@ -865,38 +1210,167 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
return;
}
- if (mWindowDecoration) {
+ if (mWindowDecorationEnabled) {
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);
+ e.phase, e.source, e.inverted);
break;
+ default:
+ Q_UNREACHABLE();
}
}
#if QT_CONFIG(cursor)
- if (e.type == QWaylandPointerEvent::Enter) {
- QRect contentGeometry = windowContentGeometry().marginsRemoved(frameMargins());
+ if (e.type == QEvent::Enter) {
+ QRect contentGeometry = QRect(QPoint(), surfaceSize()).marginsRemoved(clientSideMargins());
if (contentGeometry.contains(e.local.toPoint()))
restoreMouseCursor(inputDevice);
}
#endif
}
-bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods)
+#ifndef QT_NO_GESTURES
+void QWaylandWindow::handleSwipeGesture(QWaylandInputDevice *inputDevice,
+ const QWaylandPointerGestureSwipeEvent &e)
+{
+ switch (e.state) {
+ case Qt::GestureStarted:
+ if (mGestureState != GestureNotActive)
+ qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
+
+ if (mWindowDecorationEnabled && !mMouseEventsInContentArea) {
+ // whole gesture sequence will be ignored
+ mGestureState = GestureActiveInDecoration;
+ return;
+ }
+
+ mGestureState = GestureActiveInContentArea;
+ QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
+ inputDevice->mTouchPadDevice,
+ Qt::BeginNativeGesture,
+ e.local, e.global, e.fingers);
+ break;
+ case Qt::GestureUpdated:
+ if (mGestureState != GestureActiveInContentArea)
+ return;
+
+ if (!e.delta.isNull()) {
+ QWindowSystemInterface::handleGestureEventWithValueAndDelta(
+ window(), e.timestamp, inputDevice->mTouchPadDevice,
+ Qt::PanNativeGesture,
+ 0, e.delta, e.local, e.global, e.fingers);
+ }
+ break;
+ case Qt::GestureFinished:
+ case Qt::GestureCanceled:
+ if (mGestureState == GestureActiveInDecoration) {
+ mGestureState = GestureNotActive;
+ return;
+ }
+
+ if (mGestureState != GestureActiveInContentArea)
+ qCWarning(lcQpaWaylandInput) << "Unexpected" << (e.state == Qt::GestureFinished ? "GestureFinished" : "GestureCanceled");
+
+ mGestureState = GestureNotActive;
+
+ // There's currently no way to expose cancelled gestures to the rest of Qt, so
+ // this part of information is lost.
+ QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
+ inputDevice->mTouchPadDevice,
+ Qt::EndNativeGesture,
+ e.local, e.global, e.fingers);
+ break;
+ default:
+ break;
+ }
+}
+
+void QWaylandWindow::handlePinchGesture(QWaylandInputDevice *inputDevice,
+ const QWaylandPointerGesturePinchEvent &e)
{
- if (!mWindowDecoration)
+ switch (e.state) {
+ case Qt::GestureStarted:
+ if (mGestureState != GestureNotActive)
+ qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
+
+ if (mWindowDecorationEnabled && !mMouseEventsInContentArea) {
+ // whole gesture sequence will be ignored
+ mGestureState = GestureActiveInDecoration;
+ return;
+ }
+
+ mGestureState = GestureActiveInContentArea;
+ QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
+ inputDevice->mTouchPadDevice,
+ Qt::BeginNativeGesture,
+ e.local, e.global, e.fingers);
+ break;
+ case Qt::GestureUpdated:
+ if (mGestureState != GestureActiveInContentArea)
+ return;
+
+ if (!e.delta.isNull()) {
+ QWindowSystemInterface::handleGestureEventWithValueAndDelta(
+ window(), e.timestamp, inputDevice->mTouchPadDevice,
+ Qt::PanNativeGesture,
+ 0, e.delta, e.local, e.global, e.fingers);
+ }
+ if (e.rotation_delta != 0) {
+ QWindowSystemInterface::handleGestureEventWithRealValue(window(), e.timestamp,
+ inputDevice->mTouchPadDevice,
+ Qt::RotateNativeGesture,
+ e.rotation_delta,
+ e.local, e.global, e.fingers);
+ }
+ if (e.scale_delta != 0) {
+ QWindowSystemInterface::handleGestureEventWithRealValue(window(), e.timestamp,
+ inputDevice->mTouchPadDevice,
+ Qt::ZoomNativeGesture,
+ e.scale_delta,
+ e.local, e.global, e.fingers);
+ }
+ break;
+ case Qt::GestureFinished:
+ case Qt::GestureCanceled:
+ if (mGestureState == GestureActiveInDecoration) {
+ mGestureState = GestureNotActive;
+ return;
+ }
+
+ if (mGestureState != GestureActiveInContentArea)
+ qCWarning(lcQpaWaylandInput) << "Unexpected" << (e.state == Qt::GestureFinished ? "GestureFinished" : "GestureCanceled");
+
+ mGestureState = GestureNotActive;
+
+ // There's currently no way to expose cancelled gestures to the rest of Qt, so
+ // this part of information is lost.
+ QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
+ inputDevice->mTouchPadDevice,
+ Qt::EndNativeGesture,
+ e.local, e.global, e.fingers);
+ break;
+ default:
+ break;
+ }
+}
+#endif // #ifndef QT_NO_GESTURES
+
+
+bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods)
+{
+ if (!mWindowDecorationEnabled)
return false;
return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods);
}
@@ -912,16 +1386,14 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
return;
}
- QMargins marg = frameMargins();
+ QMargins marg = clientSideMargins();
QRect windowRect(0 + marg.left(),
0 + marg.top(),
- geometry().size().width() - marg.right(),
- geometry().size().height() - marg.bottom());
+ geometry().size().width(),
+ geometry().size().height());
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 +1404,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);
+ e.phase, e.source, e.inverted);
break;
}
+ default:
+ Q_UNREACHABLE();
}
mMouseEventsInContentArea = true;
@@ -961,20 +1435,65 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
void QWaylandWindow::handleScreensChanged()
{
- QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
+ QPlatformScreen *newScreen = calculateScreenFromSurfaceEvents();
- if (newScreen == mLastReportedScreen)
+ if (newScreen->screen() == window()->screen())
return;
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
- mLastReportedScreen = newScreen;
- int scale = newScreen->scale();
- if (scale != mScale) {
- mScale = scale;
- if (mSurface && mDisplay->compositorVersion() >= 3)
- mSurface->set_buffer_scale(mScale);
- ensureSize();
+ if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
+ && window()->type() != Qt::ToolTip
+ && geometry().topLeft() != newScreen->geometry().topLeft()) {
+ auto geometry = this->geometry();
+ geometry.moveTo(newScreen->geometry().topLeft());
+ setGeometry(geometry);
+ }
+
+ updateScale();
+ updateBufferTransform();
+}
+
+void QWaylandWindow::updateScale()
+{
+ if (mFractionalScale) {
+ auto preferredScale = mFractionalScale->preferredScale().value_or(1.0);
+ preferredScale = std::max(1.0, preferredScale);
+ Q_ASSERT(mViewport);
+ setScale(preferredScale);
+ return;
+ }
+
+ if (mSurface && mSurface->version() >= 6) {
+ auto preferredScale = mSurface->preferredBufferScale().value_or(1);
+ preferredScale = std::max(1, preferredScale);
+ setScale(preferredScale);
+ return;
+ }
+
+ int scale = screen()->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(screen())->scale();
+ setScale(scale);
+}
+
+void QWaylandWindow::setScale(qreal newScale)
+{
+ if (mScale.has_value() && qFuzzyCompare(mScale.value(), newScale))
+ return;
+ mScale = newScale;
+
+ QWindowSystemInterface::handleWindowDevicePixelRatioChanged(window());
+ if (mSurface) {
+ if (mViewport)
+ updateViewport();
+ else if (mSurface->version() >= 3)
+ mSurface->set_buffer_scale(std::ceil(newScale));
+ }
+ ensureSize();
+
+ if (isExposed()) {
+ // redraw at the new DPR
+ window()->requestUpdate();
+ sendExposeEvent(QRect(QPoint(), geometry().size()));
}
}
@@ -987,13 +1506,17 @@ void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &
void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
{
- setMouseCursor(device, window()->cursor());
+ if (const QCursor *overrideCursor = QGuiApplication::overrideCursor())
+ setMouseCursor(device, *overrideCursor);
+ else
+ setMouseCursor(device, window()->cursor());
}
#endif
void QWaylandWindow::requestActivateWindow()
{
- qCWarning(lcQpaWayland) << "Wayland does not support QWindow::requestActivate()";
+ if (mShellSurface)
+ mShellSurface->requestActivate();
}
bool QWaylandWindow::isExposed() const
@@ -1018,14 +1541,14 @@ bool QWaylandWindow::isActive() const
return mDisplay->isWindowActivated(this);
}
-int QWaylandWindow::scale() const
+qreal QWaylandWindow::scale() const
{
- return mScale;
+ return devicePixelRatio();
}
qreal QWaylandWindow::devicePixelRatio() const
{
- return mScale;
+ return mScale.value_or(waylandScreen() ? waylandScreen()->scale() : 1);
}
bool QWaylandWindow::setMouseGrabEnabled(bool grab)
@@ -1039,10 +1562,28 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
return true;
}
+QWaylandWindow::ToplevelWindowTilingStates QWaylandWindow::toplevelWindowTilingStates() const
+{
+ return mLastReportedToplevelWindowTilingStates;
+}
+
+void QWaylandWindow::handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states)
+{
+ mLastReportedToplevelWindowTilingStates = states;
+}
+
+Qt::WindowStates QWaylandWindow::windowStates() const
+{
+ return mLastReportedWindowStates;
+}
+
void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
{
createDecoration();
- QWindowSystemInterface::handleWindowStateChanged(window(), states, mLastReportedWindowStates);
+ Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
+ Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
+ QWindowSystemInterface::handleWindowStateChanged(window(), statesWithoutActive,
+ lastStatesWithoutActive);
mLastReportedWindowStates = states;
}
@@ -1079,15 +1620,36 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa
return m_properties.value(name, defaultValue);
}
+#ifdef QT_PLATFORM_WINDOW_HAS_VIRTUAL_SET_BACKING_STORE
+void QWaylandWindow::setBackingStore(QPlatformBackingStore *store)
+{
+ mBackingStore = dynamic_cast<QWaylandShmBackingStore *>(store);
+}
+#endif
+
void QWaylandWindow::timerEvent(QTimerEvent *event)
{
- if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
- killTimer(event->timerId());
- qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
- mFrameCallbackTimedOut = true;
- mWaitingForUpdate = false;
- sendExposeEvent(QRect());
+ if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
+ return;
+
+ {
+ QMutexLocker lock(&mFrameSyncMutex);
+
+ bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
+ if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
+ killTimer(mFrameCallbackCheckIntervalTimerId);
+ mFrameCallbackCheckIntervalTimerId = -1;
+ }
+ if (!mFrameCallbackElapsedTimer.isValid() || !callbackTimerExpired) {
+ return;
+ }
+ mFrameCallbackElapsedTimer.invalidate();
}
+
+ qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
+ mFrameCallbackTimedOut = true;
+ mWaitingForUpdate = false;
+ sendExposeEvent(QRect());
}
void QWaylandWindow::requestUpdate()
@@ -1096,8 +1658,11 @@ void QWaylandWindow::requestUpdate()
Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
// If we have a frame callback all is good and will be taken care of there
- if (mWaitingForFrameCallback)
- return;
+ {
+ QMutexLocker locker(&mFrameSyncMutex);
+ if (mWaitingForFrameCallback)
+ return;
+ }
// If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
// This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
@@ -1110,7 +1675,12 @@ void QWaylandWindow::requestUpdate()
// so use invokeMethod to delay the delivery a bit.
QMetaObject::invokeMethod(this, [this] {
// Things might have changed in the meantime
- if (hasPendingUpdateRequest() && !mWaitingForFrameCallback)
+ {
+ QMutexLocker locker(&mFrameSyncMutex);
+ if (mWaitingForFrameCallback)
+ return;
+ }
+ if (hasPendingUpdateRequest())
deliverUpdateRequest();
}, Qt::QueuedConnection);
}
@@ -1121,31 +1691,36 @@ void QWaylandWindow::requestUpdate()
void QWaylandWindow::handleUpdate()
{
qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
+
// TODO: Should sync subsurfaces avoid requesting frame callbacks?
QReadLocker lock(&mSurfaceLock);
if (!mSurface)
return;
- if (mFrameCallback) {
- wl_callback_destroy(mFrameCallback);
- mFrameCallback = nullptr;
- }
+ QMutexLocker locker(&mFrameSyncMutex);
+ if (mWaitingForFrameCallback)
+ return;
- mFrameCallback = mSurface->frame();
+ struct ::wl_surface *wrappedSurface = reinterpret_cast<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object()));
+ wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mDisplay->frameEventQueue());
+ mFrameCallback = wl_surface_frame(wrappedSurface);
+ wl_proxy_wrapper_destroy(wrappedSurface);
wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
mWaitingForFrameCallback = true;
mWaitingForUpdate = false;
- // Stop current frame timer if any, can't use killTimer directly, see comment above.
- int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
- if (fcbId != -1)
- QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
-
// Start a timer for handling the case when the compositor stops sending frame callbacks.
- QMetaObject::invokeMethod(this, [this] { // Again; can't do it directly
- if (mWaitingForFrameCallback)
- mFrameCallbackTimerId = startTimer(100);
- }, Qt::QueuedConnection);
+ if (mFrameCallbackTimeout > 0) {
+ QMetaObject::invokeMethod(this, [this] {
+ QMutexLocker locker(&mFrameSyncMutex);
+
+ if (mWaitingForFrameCallback) {
+ if (mFrameCallbackCheckIntervalTimerId < 0)
+ mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
+ mFrameCallbackElapsedTimer.start();
+ }
+ }, Qt::QueuedConnection);
+ }
}
void QWaylandWindow::deliverUpdateRequest()
@@ -1166,14 +1741,98 @@ void QWaylandWindow::propagateSizeHints()
mShellSurface->propagateSizeHints();
}
-bool QtWaylandClient::QWaylandWindow::startSystemMove(const QPoint &pos)
+bool QWaylandWindow::startSystemResize(Qt::Edges edges)
{
- Q_UNUSED(pos);
- if (auto seat = display()->lastInputDevice())
- return mShellSurface && mShellSurface->move(seat);
+ if (auto *seat = display()->lastInputDevice()) {
+ bool rc = mShellSurface && mShellSurface->resize(seat, edges);
+ seat->handleEndDrag();
+ return rc;
+ }
return false;
}
+bool QtWaylandClient::QWaylandWindow::startSystemMove()
+{
+ if (auto seat = display()->lastInputDevice()) {
+ bool rc = mShellSurface && mShellSurface->move(seat);
+ seat->handleEndDrag();
+ return rc;
+ }
+ return false;
+}
+
+bool QWaylandWindow::isOpaque() const
+{
+ return window()->requestedFormat().alphaBufferSize() <= 0;
+}
+
+void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
+{
+ const QRegion translatedOpaqueArea = opaqueArea.translated(clientSideMargins().left(), clientSideMargins().top());
+
+ if (translatedOpaqueArea == mOpaqueArea || !mSurface)
+ return;
+
+ mOpaqueArea = translatedOpaqueArea;
+
+ struct ::wl_region *region = mDisplay->createRegion(translatedOpaqueArea);
+ mSurface->set_opaque_region(region);
+ wl_region_destroy(region);
+}
+
+void QWaylandWindow::requestXdgActivationToken(uint serial)
+{
+ mShellSurface->requestXdgActivationToken(serial);
+}
+
+void QWaylandWindow::setXdgActivationToken(const QString &token)
+{
+ mShellSurface->setXdgActivationToken(token);
+}
+
+void QWaylandWindow::addChildPopup(QWaylandWindow *child)
+{
+ if (mShellSurface)
+ mShellSurface->attachPopup(child->shellSurface());
+ mChildPopups.append(child);
+}
+
+void QWaylandWindow::removeChildPopup(QWaylandWindow *child)
+{
+ if (mShellSurface)
+ mShellSurface->detachPopup(child->shellSurface());
+ mChildPopups.removeAll(child);
+}
+
+void QWaylandWindow::closeChildPopups() {
+ while (!mChildPopups.isEmpty()) {
+ auto popup = mChildPopups.takeLast();
+ popup->reset();
+ }
+}
+
+void QWaylandWindow::reinit()
+{
+ if (window()->isVisible()) {
+ initWindow();
+ if (hasPendingUpdateRequest())
+ deliverUpdateRequest();
+ }
+}
+
+bool QWaylandWindow::windowEvent(QEvent *event)
+{
+ if (event->type() == QEvent::ApplicationPaletteChange
+ || event->type() == QEvent::ApplicationFontChange) {
+ if (mWindowDecorationEnabled && window()->isVisible())
+ mWindowDecoration->update();
+ }
+
+ return QPlatformWindow::windowEvent(event);
+}
+
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandwindow_p.cpp"
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index c488c2e3f..c1b736c1e 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the config.tests of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDWINDOW_H
#define QWAYLANDWINDOW_H
@@ -56,13 +20,22 @@
#include <QtCore/QReadWriteLock>
#include <QtGui/QIcon>
+#include <QtGui/QEventPoint>
#include <QtCore/QVariant>
#include <QtCore/QLoggingCategory>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QList>
+#include <QtCore/QMap> // for QVariantMap
#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformwindow_p.h>
#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
+#include <QtWaylandClient/private/qwaylandshellsurface_p.h>
+
+#include <QtCore/qpointer.h>
struct wl_egl_window;
@@ -79,11 +52,17 @@ class QWaylandSubSurface;
class QWaylandAbstractDecoration;
class QWaylandInputDevice;
class QWaylandScreen;
+class QWaylandShellIntegration;
class QWaylandShmBackingStore;
class QWaylandPointerEvent;
+class QWaylandPointerGestureSwipeEvent;
+class QWaylandPointerGesturePinchEvent;
class QWaylandSurface;
+class QWaylandFractionalScale;
+class QWaylandViewport;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow
+class Q_WAYLANDCLIENT_EXPORT QWaylandWindow : public QNativeInterface::Private::QWaylandWindow,
+ public QPlatformWindow
{
Q_OBJECT
public:
@@ -93,15 +72,28 @@ public:
Vulkan
};
- QWaylandWindow(QWindow *window);
+ enum ToplevelWindowTilingState {
+ WindowNoState = 0,
+ WindowTiledLeft = 1,
+ WindowTiledRight = 2,
+ WindowTiledTop = 4,
+ WindowTiledBottom = 8
+ };
+ Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState)
+
+ QWaylandWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandWindow() override;
+ // Keep Toplevels position on the top left corner of their screen
+ static inline bool fixedToplevelPositions = true;
+
virtual WindowType windowType() const = 0;
virtual void ensureSize();
WId winId() const override;
void setVisible(bool visible) override;
void setParent(const QPlatformWindow *parent) override;
+ QString windowTitle() const;
void setWindowTitle(const QString &title) override;
inline QIcon windowIcon() const;
@@ -109,6 +101,8 @@ public:
void setGeometry(const QRect &rect) override;
void resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset = {0, 0});
+ void repositionFromApplyConfigure(const QPoint &position);
+ void setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins);
void applyConfigureWhenPossible(); //rename to possible?
@@ -119,7 +113,6 @@ public:
void damage(const QRect &rect);
void safeCommit(QWaylandBuffer *buffer, const QRegion &damage);
- void handleExpose(const QRegion &region);
void commit(QWaylandBuffer *buffer, const QRegion &damage);
void commit();
@@ -127,21 +120,35 @@ public:
bool waitForFrameSync(int timeout);
QMargins frameMargins() const override;
+ QMargins clientSideMargins() const;
+ void setCustomMargins(const QMargins &margins) override;
QSize surfaceSize() const;
+ QMargins windowContentMargins() const;
QRect windowContentGeometry() const;
+ QPointF mapFromWlSurface(const QPointF &surfacePosition) const;
QWaylandSurface *waylandSurface() const { return mSurface.data(); }
- ::wl_surface *wlSurface();
+ ::wl_surface *wlSurface() const;
+ ::wl_surface *surface() const override
+ {
+ return wlSurface();
+ }
static QWaylandWindow *fromWlSurface(::wl_surface *surface);
QWaylandDisplay *display() const { return mDisplay; }
QWaylandShellSurface *shellSurface() const;
+ std::any _surfaceRole() const override;
QWaylandSubSurface *subSurfaceWindow() const;
QWaylandScreen *waylandScreen() const;
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
+ void updateBufferTransform();
void setOrientationMask(Qt::ScreenOrientations mask);
+ ToplevelWindowTilingStates toplevelWindowTilingStates() const;
+ void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states);
+
+ Qt::WindowStates windowStates() const;
void setWindowState(Qt::WindowStates states) override;
void setWindowFlags(Qt::WindowFlags flags) override;
void handleWindowStatesChanged(Qt::WindowStates states);
@@ -151,7 +158,10 @@ public:
void setMask(const QRegion &region) override;
- int scale() const;
+ void setAlertState(bool enabled) override;
+ bool isAlertState() const override;
+
+ qreal scale() const;
qreal devicePixelRatio() const override;
void requestActivateWindow() override;
@@ -161,9 +171,15 @@ public:
QWaylandAbstractDecoration *decoration() const;
void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
+#ifndef QT_NO_GESTURES
+ void handleSwipeGesture(QWaylandInputDevice *inputDevice,
+ const QWaylandPointerGestureSwipeEvent &e);
+ void handlePinchGesture(QWaylandInputDevice *inputDevice,
+ const QWaylandPointerGesturePinchEvent &e);
+#endif
bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
- Qt::TouchPointState state, Qt::KeyboardModifiers mods);
+ QEventPoint::State state, Qt::KeyboardModifiers mods);
bool createDecoration();
@@ -174,7 +190,6 @@ public:
QWaylandWindow *transientParent() const;
- QMutex *resizeMutex() { return &mResizeLock; }
void doApplyConfigure();
void setCanResize(bool canResize);
@@ -188,99 +203,179 @@ public:
QVariant property(const QString &name);
QVariant property(const QString &name, const QVariant &defaultValue);
+#ifdef QT_PLATFORM_WINDOW_HAS_VIRTUAL_SET_BACKING_STORE
+ void setBackingStore(QPlatformBackingStore *store) override;
+#else
void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; }
+#endif
QWaylandShmBackingStore *backingStore() const { return mBackingStore; }
+ void setShellIntegration(QWaylandShellIntegration *shellIntegration);
+ QWaylandShellIntegration *shellIntegration() const { return mShellIntegration; }
+
bool setKeyboardGrabEnabled(bool) override { return false; }
void propagateSizeHints() override;
void addAttachOffset(const QPoint point);
- bool startSystemMove(const QPoint &pos) override;
+ bool startSystemResize(Qt::Edges edges) override;
+ bool startSystemMove() override;
void timerEvent(QTimerEvent *event) override;
void requestUpdate() override;
void handleUpdate();
void deliverUpdateRequest() override;
-public slots:
+ void setXdgActivationToken(const QString &token);
+ void requestXdgActivationToken(uint serial) override;
+
+ void beginFrame();
+ void endFrame();
+
+ void closeChildPopups();
+ void sendRecursiveExposeEvent();
+
+ virtual void reinit();
+ void reset();
+
+ bool windowEvent(QEvent *event) override;
+
+public Q_SLOTS:
void applyConfigure();
-signals:
+Q_SIGNALS:
void wlSurfaceCreated();
void wlSurfaceDestroyed();
protected:
+ virtual void doHandleFrameCallback();
+ virtual QRect defaultGeometry() const;
+ void sendExposeEvent(const QRect &rect);
+
QWaylandDisplay *mDisplay = nullptr;
+
+ // mSurface can be written by the main thread. Other threads should claim a read lock for access
+ mutable QReadWriteLock mSurfaceLock;
QScopedPointer<QWaylandSurface> mSurface;
+ QScopedPointer<QWaylandFractionalScale> mFractionalScale;
+ QScopedPointer<QWaylandViewport> mViewport;
+
+ QWaylandShellIntegration *mShellIntegration = nullptr;
QWaylandShellSurface *mShellSurface = nullptr;
QWaylandSubSurface *mSubSurfaceWindow = nullptr;
- QVector<QWaylandSubSurface *> mChildren;
+ QList<QWaylandSubSurface *> mChildren;
QWaylandAbstractDecoration *mWindowDecoration = nullptr;
+ bool mWindowDecorationEnabled = false;
bool mMouseEventsInContentArea = false;
Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
+#ifndef QT_NO_GESTURES
+ enum GestureState {
+ GestureNotActive,
+ GestureActiveInContentArea,
+ GestureActiveInDecoration
+ };
+
+ // We want gestures started in the decoration area to be completely ignored even if the mouse
+ // pointer is later moved to content area. Likewise, gestures started in the content area should
+ // keep sending events even if the mouse pointer is moved over the decoration (consider that
+ // the events for that gesture will be sent to us even if it's moved outside the window).
+ // So we track the gesture state and accept or ignore events based on that. Note that
+ // concurrent gestures of different types are not allowed in the protocol, so single state is
+ // enough
+ GestureState mGestureState = GestureNotActive;
+#endif
+
WId mWindowId;
- bool mWaitingForFrameCallback = false;
bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
- QAtomicInt mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
- struct ::wl_callback *mFrameCallback = nullptr;
- struct ::wl_event_queue *mFrameQueue = nullptr;
+ int mFrameCallbackCheckIntervalTimerId = -1;
+ QAtomicInt mWaitingForUpdateDelivery = false;
+
+ bool mWaitingForFrameCallback = false; // Protected by mFrameSyncMutex
+ QElapsedTimer mFrameCallbackElapsedTimer; // Protected by mFrameSyncMutex
+ struct ::wl_callback *mFrameCallback = nullptr; // Protected by mFrameSyncMutex
+ QMutex mFrameSyncMutex;
QWaitCondition mFrameSyncWait;
// True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
bool mWaitingForUpdate = false;
- QMutex mResizeLock;
+ QRecursiveMutex mResizeLock;
bool mWaitingToApplyConfigure = false;
bool mCanResize = true;
bool mResizeDirty = false;
bool mResizeAfterSwap;
+ int mFrameCallbackTimeout = 100;
QVariantMap m_properties;
bool mSentInitialResize = false;
QPoint mOffset;
- int mScale = 1;
- QWaylandScreen *mLastReportedScreen = nullptr;
+ std::optional<qreal> mScale = std::nullopt;
+ QString mWindowTitle;
QIcon mWindowIcon;
Qt::WindowFlags mFlags;
QRegion mMask;
+
+ // Empty QRegion maps to "infinite" input region, needs a dedicated "deliberately empty" state.
+ QRegion mInputRegion;
+ bool mTransparentInputRegion = false;
+
+ QRegion mOpaqueArea;
Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
+ ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState;
QWaylandShmBackingStore *mBackingStore = nullptr;
QWaylandBuffer *mQueuedBuffer = nullptr;
QRegion mQueuedBufferDamage;
+ QMargins mCustomMargins;
+
+ QPointer<QWaylandWindow> mTransientParent;
+ QList<QPointer<QWaylandWindow>> mChildPopups;
+
+ Qt::ScreenOrientation mLastReportedContentOrientation = Qt::PrimaryOrientation;
+
+private Q_SLOTS:
+ void doApplyConfigureFromOtherThread();
+
private:
void setGeometry_helper(const QRect &rect);
void initWindow();
void initializeWlSurface();
bool shouldCreateShellSurface() const;
bool shouldCreateSubSurface() const;
- void reset(bool sendDestroyEvent = true);
- void sendExposeEvent(const QRect &rect);
- static void closePopups(QWaylandWindow *parent);
- QWaylandScreen *calculateScreenFromSurfaceEvents() const;
+ QPlatformScreen *calculateScreenFromSurfaceEvents() const;
+ void setOpaqueArea(const QRegion &opaqueArea);
+ bool isOpaque() const;
+ void updateInputRegion();
+ void updateViewport();
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
void handleScreensChanged();
+ void updateScale();
+ void setScale(qreal newScale);
+
+ QWaylandWindow *guessTransientParent() const;
+ void addChildPopup(QWaylandWindow *child);
+ void removeChildPopup(QWaylandWindow *child);
bool mInResizeFromApplyConfigure = false;
+ bool lastVisible = false;
QRect mLastExposeGeometry;
static const wl_callback_listener callbackListener;
- void handleFrameCallback();
+ void handleFrameCallback(struct ::wl_callback* callback);
- static QMutex mFrameSyncMutex;
static QWaylandWindow *mMouseGrab;
-
- QReadWriteLock mSurfaceLock;
+ static QWaylandWindow *mTopPopup;
friend class QWaylandSubSurface;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates)
+
inline QIcon QWaylandWindow::windowIcon() const
{
return mWindowIcon;
diff --git a/src/client/qwaylandwindowmanagerintegration.cpp b/src/client/qwaylandwindowmanagerintegration.cpp
index dd1acaf72..9668491d2 100644
--- a/src/client/qwaylandwindowmanagerintegration.cpp
+++ b/src/client/qwaylandwindowmanagerintegration.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylanddisplay_p.h"
+#include "qwaylandshellsurface_p.h"
#include <stdint.h>
#include <QtCore/QEvent>
@@ -57,49 +22,25 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-class QWaylandWindowManagerIntegrationPrivate {
-public:
- QWaylandWindowManagerIntegrationPrivate(QWaylandDisplay *waylandDisplay);
- bool m_blockPropertyUpdates = false;
- QWaylandDisplay *m_waylandDisplay = nullptr;
- QHash<QWindow*, QVariantMap> m_queuedProperties;
- bool m_showIsFullScreen = false;
-};
-
-QWaylandWindowManagerIntegrationPrivate::QWaylandWindowManagerIntegrationPrivate(QWaylandDisplay *waylandDisplay)
- : m_waylandDisplay(waylandDisplay)
-{
-
-}
-
-QWaylandWindowManagerIntegration::QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay)
- : d_ptr(new QWaylandWindowManagerIntegrationPrivate(waylandDisplay))
+QWaylandWindowManagerIntegration::QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay,
+ uint id, uint version)
+ : QtWayland::qt_windowmanager(waylandDisplay->object(), id, version)
{
- waylandDisplay->addRegistryListener(&wlHandleListenerGlobal, this);
}
QWaylandWindowManagerIntegration::~QWaylandWindowManagerIntegration()
{
-
+ qt_windowmanager_destroy(object());
}
bool QWaylandWindowManagerIntegration::showIsFullScreen() const
{
- Q_D(const QWaylandWindowManagerIntegration);
- return d->m_showIsFullScreen;
-}
-
-void QWaylandWindowManagerIntegration::wlHandleListenerGlobal(void *data, wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
-{
- Q_UNUSED(version);
- if (interface == QStringLiteral("qt_windowmanager"))
- static_cast<QWaylandWindowManagerIntegration *>(data)->init(registry, id, 1);
+ return m_showIsFullScreen;
}
void QWaylandWindowManagerIntegration::windowmanager_hints(int32_t showIsFullScreen)
{
- Q_D(QWaylandWindowManagerIntegration);
- d->m_showIsFullScreen = showIsFullScreen;
+ m_showIsFullScreen = showIsFullScreen;
}
void QWaylandWindowManagerIntegration::windowmanager_quit()
@@ -107,11 +48,9 @@ void QWaylandWindowManagerIntegration::windowmanager_quit()
QGuiApplication::quit();
}
-void QWaylandWindowManagerIntegration::openUrl_helper(const QUrl &url)
+void QWaylandWindowManagerIntegration::openUrl(const QUrl &url)
{
- Q_ASSERT(isInitialized());
QString data = url.toString();
-
static const int chunkSize = 128;
while (!data.isEmpty()) {
QString chunk = data.left(chunkSize);
@@ -123,25 +62,8 @@ void QWaylandWindowManagerIntegration::openUrl_helper(const QUrl &url)
open_url(!data.isEmpty(), chunk);
}
}
-
-bool QWaylandWindowManagerIntegration::openUrl(const QUrl &url)
-{
- if (isInitialized()) {
- openUrl_helper(url);
- return true;
- }
- return QGenericUnixServices::openUrl(url);
-}
-
-bool QWaylandWindowManagerIntegration::openDocument(const QUrl &url)
-{
- if (isInitialized()) {
- openUrl_helper(url);
- return true;
- }
- return QGenericUnixServices::openDocument(url);
-}
-
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandwindowmanagerintegration_p.cpp"
diff --git a/src/client/qwaylandwindowmanagerintegration_p.h b/src/client/qwaylandwindowmanagerintegration_p.h
index 31de6ddd3..be06d68ee 100644
--- a/src/client/qwaylandwindowmanagerintegration_p.h
+++ b/src/client/qwaylandwindowmanagerintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDWINDOWMANAGERINTEGRATION_H
#define QWAYLANDWINDOWMANAGERINTEGRATION_H
@@ -52,9 +16,6 @@
//
#include <QtCore/QObject>
-#include <QtCore/QScopedPointer>
-
-#include <QtServiceSupport/private/qgenericunixservices_p.h>
#include <QtWaylandClient/private/qwayland-qt-windowmanager.h>
#include <QtWaylandClient/qtwaylandclientglobal.h>
@@ -63,34 +24,27 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-class QWaylandWindow;
class QWaylandDisplay;
class QWaylandWindowManagerIntegrationPrivate;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowManagerIntegration : public QObject, public QGenericUnixServices, public QtWayland::qt_windowmanager
+class Q_WAYLANDCLIENT_EXPORT QWaylandWindowManagerIntegration : public QtWayland::qt_windowmanager
{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QWaylandWindowManagerIntegration)
+
public:
- explicit QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay);
- ~QWaylandWindowManagerIntegration() override;
+ explicit QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay, uint id,
+ uint version);
+ ~QWaylandWindowManagerIntegration();
- bool openUrl(const QUrl &url) override;
- bool openDocument(const QUrl &url) override;
+ void openUrl(const QUrl &url);
bool showIsFullScreen() const;
private:
- static void wlHandleListenerGlobal(void *data, wl_registry *registry, uint32_t id,
- const QString &interface, uint32_t version);
-
- QScopedPointer<QWaylandWindowManagerIntegrationPrivate> d_ptr;
-
void windowmanager_hints(int32_t showIsFullScreen) override;
void windowmanager_quit() override;
- void openUrl_helper(const QUrl &url);
+ bool m_showIsFullScreen = false;
};
QT_END_NAMESPACE
diff --git a/src/client/shellintegration/qwaylandclientshellapi_p.h b/src/client/shellintegration/qwaylandclientshellapi_p.h
new file mode 100644
index 000000000..984435aa9
--- /dev/null
+++ b/src/client/shellintegration/qwaylandclientshellapi_p.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDCLIENTSHELLAPI_P_H
+#define QWAYLANDCLIENTSHELLAPI_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.
+//
+
+// N O T E
+// -------
+// This file provides a supported API for creating client-side shell
+// extensions. Source compatibility will be preserved, but we may break
+// forward and backward binary compatibility, even in patch releases.
+//
+// The supported API contains these classes:
+//
+// QtWaylandClient::QWaylandShellSurface
+// QtWaylandClient::QWaylandShellIntegration
+// QtWaylandClient::QWaylandShellIntegrationPlugin
+
+#include "QtWaylandClient/private/qwaylandshellsurface_p.h"
+#include "QtWaylandClient/private/qwaylandshellintegration_p.h"
+#include "QtWaylandClient/private/qwaylandshellintegrationplugin_p.h"
+
+#endif // QWAYLANDCLIENTSHELLAPI_P_H
diff --git a/src/client/shellintegration/qwaylandshellintegration.cpp b/src/client/shellintegration/qwaylandshellintegration.cpp
new file mode 100644
index 000000000..3d2f21c77
--- /dev/null
+++ b/src/client/shellintegration/qwaylandshellintegration.cpp
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qwaylandshellintegration_p.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+wl_surface *QWaylandShellIntegration::wlSurfaceForWindow(QWaylandWindow *window)
+{
+ return window->wlSurface();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/shellintegration/qwaylandshellintegration_p.h b/src/client/shellintegration/qwaylandshellintegration_p.h
index ccad00481..791a94043 100644
--- a/src/client/shellintegration/qwaylandshellintegration_p.h
+++ b/src/client/shellintegration/qwaylandshellintegration_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Jolla 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 Jolla Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHELLINTEGRATION_H
#define QWAYLANDSHELLINTEGRATION_H
@@ -52,43 +16,80 @@
//
#include <QtWaylandClient/qtwaylandclientglobal.h>
-#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/qwaylandclientextension.h>
+
+
+
+#include <QDebug>
+#include <private/qglobal_p.h>
+
+struct wl_surface;
+struct wl_registry;
QT_BEGIN_NAMESPACE
+class QWindow;
+
namespace QtWaylandClient {
class QWaylandWindow;
class QWaylandDisplay;
class QWaylandShellSurface;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShellIntegration
+class Q_WAYLANDCLIENT_EXPORT QWaylandShellIntegration
{
public:
QWaylandShellIntegration() {}
virtual ~QWaylandShellIntegration() {}
- virtual bool initialize(QWaylandDisplay *display) {
- m_display = display;
- return true;
- }
+ virtual bool initialize(QWaylandDisplay *display) = 0;
virtual QWaylandShellSurface *createShellSurface(QWaylandWindow *window) = 0;
- virtual void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
- if (newFocus)
- m_display->handleWindowActivated(newFocus);
- if (oldFocus)
- m_display->handleWindowDeactivated(oldFocus);
- }
virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) {
Q_UNUSED(resource);
Q_UNUSED(window);
return nullptr;
}
-protected:
- QWaylandDisplay *m_display = nullptr;
+ static wl_surface *wlSurfaceForWindow(QWaylandWindow *window);
+
+};
+
+template <typename T>
+class Q_WAYLANDCLIENT_EXPORT QWaylandShellIntegrationTemplate : public QWaylandShellIntegration, public QWaylandClientExtension
+{
+public:
+ QWaylandShellIntegrationTemplate(const int ver) :
+ QWaylandClientExtension(ver)
+ {
+ }
+
+ bool initialize(QWaylandDisplay *) override
+ {
+ QWaylandClientExtension::initialize();
+ return isActive();
+ }
+
+ const struct wl_interface *extensionInterface() const override
+ {
+ return T::interface();
+ }
+
+ void bind(struct ::wl_registry *registry, int id, int ver) override
+ {
+ T* instance = static_cast<T *>(this);
+ // Make sure lowest version is used of the supplied version from the
+ // developer and the version specified in the protocol and also the
+ // compositor version.
+ if (this->version() > T::interface()->version) {
+ qWarning("Supplied protocol version to QWaylandClientExtensionTemplate is higher than the version of the protocol, using protocol version instead.");
+ }
+ int minVersion = qMin(ver, qMin(T::interface()->version, this->version()));
+ setVersion(minVersion);
+ instance->init(registry, id, minVersion);
+ }
};
+
}
QT_END_NAMESPACE
diff --git a/src/client/shellintegration/qwaylandshellintegrationfactory.cpp b/src/client/shellintegration/qwaylandshellintegrationfactory.cpp
index 48fda14d4..feedb27c5 100644
--- a/src/client/shellintegration/qwaylandshellintegrationfactory.cpp
+++ b/src/client/shellintegration/qwaylandshellintegrationfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Jolla Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Jolla Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandshellintegrationfactory_p.h"
#include "qwaylandshellintegrationplugin_p.h"
@@ -48,54 +12,23 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qwsifLoader,
(QWaylandShellIntegrationFactoryInterface_iid, QLatin1String("/wayland-shell-integration"), Qt::CaseInsensitive))
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QWaylandShellIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
-QStringList QWaylandShellIntegrationFactory::keys(const QString &pluginPath)
+QStringList QWaylandShellIntegrationFactory::keys()
{
-#if QT_CONFIG(library)
- QStringList list;
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- list = directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QStringLiteral(" (from ")
- + QDir::toNativeSeparators(pluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
- list.append(loader()->keyMap().values());
- return list;
-#else
- return QStringList();
-#endif
+ return qwsifLoader->keyMap().values();
}
-QWaylandShellIntegration *QWaylandShellIntegrationFactory::create(const QString &name, QWaylandDisplay *display, const QStringList &args, const QString &pluginPath)
+QWaylandShellIntegration *QWaylandShellIntegrationFactory::create(const QString &name, QWaylandDisplay *display, const QStringList &args)
{
-#if QT_CONFIG(library)
- QScopedPointer<QWaylandShellIntegration> integration;
-
- // Try loading the plugin from platformPluginPath first:
- if (!pluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(pluginPath);
- integration.reset(qLoadPlugin<QWaylandShellIntegration, QWaylandShellIntegrationPlugin>(directLoader(), name, args));
- }
- if (!integration)
- integration.reset(qLoadPlugin<QWaylandShellIntegration, QWaylandShellIntegrationPlugin>(loader(), name, args));
-#endif
+ std::unique_ptr<QWaylandShellIntegration> integration;
+ integration.reset(qLoadPlugin<QWaylandShellIntegration, QWaylandShellIntegrationPlugin>(qwsifLoader(), name, args));
if (integration && !integration->initialize(display))
return nullptr;
- return integration.take();
+ return integration.release();
}
}
diff --git a/src/client/shellintegration/qwaylandshellintegrationfactory_p.h b/src/client/shellintegration/qwaylandshellintegrationfactory_p.h
index 515a18e1f..edc0e70c7 100644
--- a/src/client/shellintegration/qwaylandshellintegrationfactory_p.h
+++ b/src/client/shellintegration/qwaylandshellintegrationfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Jolla Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Jolla Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHELLINTEGRATIONFACTORY_H
#define QWAYLANDSHELLINTEGRATIONFACTORY_H
@@ -63,11 +27,11 @@ namespace QtWaylandClient {
class QWaylandShellIntegration;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShellIntegrationFactory
+class Q_WAYLANDCLIENT_EXPORT QWaylandShellIntegrationFactory
{
public:
- static QStringList keys(const QString &pluginPath = QString());
- static QWaylandShellIntegration *create(const QString &name, QWaylandDisplay *display, const QStringList &args = QStringList(), const QString &pluginPath = QString());
+ static QStringList keys();
+ static QWaylandShellIntegration *create(const QString &name, QWaylandDisplay *display, const QStringList &args = QStringList());
};
}
diff --git a/src/client/shellintegration/qwaylandshellintegrationplugin.cpp b/src/client/shellintegration/qwaylandshellintegrationplugin.cpp
index d89e61fb1..0e2338282 100644
--- a/src/client/shellintegration/qwaylandshellintegrationplugin.cpp
+++ b/src/client/shellintegration/qwaylandshellintegrationplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Jolla Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Jolla Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaylandshellintegrationplugin_p.h"
@@ -55,3 +19,5 @@ QWaylandShellIntegrationPlugin::~QWaylandShellIntegrationPlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandshellintegrationplugin_p.cpp"
diff --git a/src/client/shellintegration/qwaylandshellintegrationplugin_p.h b/src/client/shellintegration/qwaylandshellintegrationplugin_p.h
index d60675690..85339e1e7 100644
--- a/src/client/shellintegration/qwaylandshellintegrationplugin_p.h
+++ b/src/client/shellintegration/qwaylandshellintegrationplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Jolla Ltd
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Jolla Ltd
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAYLANDSHELLINTEGRATIONPLUGIN_H
#define QWAYLANDSHELLINTEGRATIONPLUGIN_H
@@ -56,6 +20,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/QObject>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,7 @@ class QWaylandShellIntegration;
#define QWaylandShellIntegrationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandShellIntegrationFactoryInterface.5.3"
-class Q_WAYLAND_CLIENT_EXPORT QWaylandShellIntegrationPlugin : public QObject
+class Q_WAYLANDCLIENT_EXPORT QWaylandShellIntegrationPlugin : public QObject
{
Q_OBJECT
public: