Hello community,

here is the log from the commit of package kguiaddons for openSUSE:Factory 
checked in at 2020-12-15 12:27:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kguiaddons (Old)
 and      /work/SRC/openSUSE:Factory/.kguiaddons.new.2328 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kguiaddons"

Tue Dec 15 12:27:48 2020 rev:85 rq:855363 version:5.77.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kguiaddons/kguiaddons.changes    2020-11-23 
10:32:18.381480716 +0100
+++ /work/SRC/openSUSE:Factory/.kguiaddons.new.2328/kguiaddons.changes  
2020-12-15 12:27:58.923884166 +0100
@@ -1,0 +2,20 @@
+Sat Dec 12 13:35:03 UTC 2020 - Wolfgang Bauer <[email protected]>
+
+- Explicitly BuildRequire pkgconfig(wayland-client) that's needed
+  now and don't rely on other packages pulling it in
+
+-------------------------------------------------------------------
+Sat Dec  5 18:56:34 UTC 2020 - Christophe Giboudeaux <[email protected]>
+
+- Update to 5.77.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/kde-frameworks-5.77.0
+- Changes since 5.76.0:
+  * Remove redundant setLayout() call (parent is passed to Q*Layout ctor)
+  * Make shortcut inhibition work from the get-go (kde#407395)
+  * Fix potential crash in wayland inhibitor teardown (kde#429267)
+  * CMake: Find Qt5::GuiPrivate when Wayland support is enabled
+  * Add KeySequenceRecorder as base for KKeySequenceWidget and KeySequenceItem
+
+-------------------------------------------------------------------

Old:
----
  kguiaddons-5.76.0.tar.xz
  kguiaddons-5.76.0.tar.xz.sig

New:
----
  kguiaddons-5.77.0.tar.xz
  kguiaddons-5.77.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kguiaddons.spec ++++++
--- /var/tmp/diff_new_pack.1859sN/_old  2020-12-15 12:27:59.559884678 +0100
+++ /var/tmp/diff_new_pack.1859sN/_new  2020-12-15 12:27:59.563884681 +0100
@@ -17,7 +17,7 @@
 
 
 %define lname   libKF5GuiAddons5
-%define _tar_path 5.76
+%define _tar_path 5.77
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
@@ -25,7 +25,7 @@
 # Only needed for the package signature condition
 %bcond_without lang
 Name:           kguiaddons
-Version:        5.76.0
+Version:        5.77.0
 Release:        0
 Summary:        Utilities for graphical user interfaces
 License:        LGPL-2.1-or-later
@@ -40,12 +40,14 @@
 BuildRequires:  extra-cmake-modules >= %{_kf5_bugfix_version}
 BuildRequires:  fdupes
 BuildRequires:  kf5-filesystem
+BuildRequires:  libQt5Gui-private-headers-devel
 BuildRequires:  pkgconfig
-BuildRequires:  cmake(Qt5Gui) >= 5.12.0
-# Tests
-BuildRequires:  cmake(Qt5Test) >= 5.12.0
-BuildRequires:  cmake(Qt5Widgets) >= 5.12.0
-BuildRequires:  cmake(Qt5X11Extras) >= 5.12.0
+BuildRequires:  cmake(Qt5Gui) >= 5.13.0
+BuildRequires:  cmake(Qt5Test) >= 5.13.0
+BuildRequires:  cmake(Qt5WaylandClient) >= 5.13.0
+BuildRequires:  cmake(Qt5Widgets) >= 5.13.0
+BuildRequires:  cmake(Qt5X11Extras) >= 5.13.0
+BuildRequires:  pkgconfig(wayland-client)
 BuildRequires:  pkgconfig(x11)
 BuildRequires:  pkgconfig(xcb)
 
@@ -67,7 +69,7 @@
 Group:          Development/Libraries/KDE
 Requires:       %{lname} = %{version}
 Requires:       extra-cmake-modules
-Requires:       cmake(Qt5Gui) >= 5.12.0
+Requires:       cmake(Qt5Gui) >= 5.13.0
 
 %description devel
 The KDE GUI addons provide utilities for graphical user interfaces in the areas


++++++ kguiaddons-5.76.0.tar.xz -> kguiaddons-5.77.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/CMakeLists.txt 
new/kguiaddons-5.77.0/CMakeLists.txt
--- old/kguiaddons-5.76.0/CMakeLists.txt        2020-11-07 12:37:58.000000000 
+0100
+++ new/kguiaddons-5.77.0/CMakeLists.txt        2020-12-05 11:07:55.000000000 
+0100
@@ -1,27 +1,48 @@
 cmake_minimum_required(VERSION 3.5)
 
-set(KF5_VERSION "5.76.0") # handled by release scripts
+set(KF5_VERSION "5.77.0") # handled by release scripts
 project(KGuiAddons VERSION ${KF5_VERSION})
 
 include(FeatureSummary)
-find_package(ECM 5.76.0  NO_MODULE)
+find_package(ECM 5.77.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL "https://commits.kde.org/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
 
+
+option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt 
Assistant, Qt Creator & KDevelop)" OFF)
+add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. 
Qt Assistant, Qt Creator & KDevelop)")
+
+if (UNIX AND NOT ANDROID)
+    option(WITH_WAYLAND "Build with support for KeySequenceEditor inhibiting 
shortcuts on Wayland" ON)
+    add_feature_info(WAYLAND ${WITH_WAYLAND} "KeySequenceEditor inhibiting 
shortcuts on Wayland")
+else()
+    set(WITH_WAYLAND OFF)
+endif()
+
 set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
 
 include(KDEInstallDirs)
 include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
 include(KDECMakeSettings)
-set(REQUIRED_QT_VERSION 5.12.0)
-find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
+
+set(REQUIRED_QT_VERSION 5.13.0)
+if (WITH_WAYLAND)
+    set(_qtgui_find_components COMPONENTS Private)
+endif()
+# QtGui must be found becore Qt5WaylandClient
+find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE 
${_qtgui_find_components})
 
 if (NOT APPLE AND NOT WIN32)
     find_package(X11 MODULE)
     find_package(XCB MODULE COMPONENTS XCB)
 endif()
 
+if (WITH_WAYLAND)
+    find_package(Qt5WaylandClient ${REQUIRED_QT_VERSION} NO_MODULE)
+    find_package(QtWaylandScanner REQUIRED)
+    find_package(Wayland 1.9 REQUIRED Client)
+endif()
 
 include(GenerateExportHeader)
 include(ECMSetupVersion)
@@ -34,8 +55,7 @@
                         PACKAGE_VERSION_FILE 
"${CMAKE_CURRENT_BINARY_DIR}/KF5GuiAddonsConfigVersion.cmake"
                         SOVERSION 5)
 
-option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt 
Assistant, Qt Creator & KDevelop)" OFF)
-add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. 
Qt Assistant, Qt Creator & KDevelop)")
+
 add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050d00)
 add_definitions(-DQT_NO_FOREACH)
 add_subdirectory(src)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/autotests/CMakeLists.txt 
new/kguiaddons-5.77.0/autotests/CMakeLists.txt
--- old/kguiaddons-5.76.0/autotests/CMakeLists.txt      2020-11-07 
12:37:58.000000000 +0100
+++ new/kguiaddons-5.77.0/autotests/CMakeLists.txt      2020-12-05 
11:07:55.000000000 +0100
@@ -9,5 +9,6 @@
   kcolorutilstest.cpp
   kiconutilstest.cpp
   kcursorsavertest.cpp
+  keysequencerecordertest.cpp
   LINK_LIBRARIES KF5::GuiAddons Qt5::Test
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-5.76.0/autotests/keysequencerecordertest.cpp 
new/kguiaddons-5.77.0/autotests/keysequencerecordertest.cpp
--- old/kguiaddons-5.76.0/autotests/keysequencerecordertest.cpp 1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/autotests/keysequencerecordertest.cpp 2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,168 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#include "keysequencerecordertest.h"
+
+#include <KeySequenceRecorder>
+
+#include <QtTest>
+#include <QWindow>
+
+QTEST_MAIN(KeySequenceRecorderTest)
+
+void KeySequenceRecorderTest::initTestCase()
+{
+    m_window = new QWindow;
+}
+
+void KeySequenceRecorderTest::cleanupTestCase()
+{
+    delete m_window;
+}
+
+void KeySequenceRecorderTest::testValidWindow()
+{
+    KeySequenceRecorder recorder(nullptr);
+    QSignalSpy recordingSpy(&recorder,  
&KeySequenceRecorder::recordingChanged);
+
+    recorder.startRecording();
+    QCOMPARE(recordingSpy.count(), 0);
+    QVERIFY(!recorder.isRecording());
+
+    recorder.setWindow(m_window);
+    recorder.startRecording();
+    QCOMPARE(recordingSpy.count(), 1);
+    QVERIFY(recorder.isRecording());
+}
+
+void KeySequenceRecorderTest::testRecording()
+{
+    KeySequenceRecorder recorder(m_window);
+    QSignalSpy recordingSpy(&recorder,  
&KeySequenceRecorder::recordingChanged);
+    QSignalSpy sequenceSpy(&recorder,  
&KeySequenceRecorder::currentKeySequenceChanged);
+    QSignalSpy resultSpy(&recorder,  &KeySequenceRecorder::gotKeySequence);
+
+    recorder.startRecording();
+    QVERIFY(recorder.isRecording());
+    QCOMPARE(recordingSpy.count(), 1);
+    QCOMPARE(sequenceSpy.count(), 1);
+
+    QTest::keyClick(m_window, Qt::Key_A, Qt::ControlModifier);
+    QVERIFY(recorder.isRecording());
+    QCOMPARE(recordingSpy.count(), 1);
+    QCOMPARE(sequenceSpy.count(), 4); // two key events + modifier release
+    QCOMPARE(resultSpy.count(), 0);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A + 
Qt::ControlModifier));
+
+    QTest::qWait(800);
+    QCOMPARE(sequenceSpy.count(), 4);
+    QCOMPARE(recordingSpy.count(), 2);
+    QVERIFY(!recorder.isRecording());
+    QCOMPARE(resultSpy.count(), 1);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A + 
Qt::ControlModifier));
+    QCOMPARE(resultSpy.takeFirst().at(0).value<QKeySequence>(), 
QKeySequence(Qt::Key_A + Qt::ControlModifier));
+}
+
+void KeySequenceRecorderTest::testModifiers()
+{
+    KeySequenceRecorder recorder(m_window);
+    QSignalSpy recordingSpy(&recorder,  
&KeySequenceRecorder::recordingChanged);
+    QSignalSpy sequenceSpy(&recorder,  
&KeySequenceRecorder::currentKeySequenceChanged);
+    QSignalSpy resultSpy(&recorder,  &KeySequenceRecorder::gotKeySequence);
+
+    recorder.startRecording();
+    QCOMPARE(sequenceSpy.count(), 1);
+    QCOMPARE(recordingSpy.count(), 1);
+    QVERIFY(recorder.isRecording());
+
+    QTest::keyPress(m_window, Qt::Key_Control);
+    QCOMPARE(sequenceSpy.count(), 2);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::ControlModifier));
+
+    // Releasing a different key because when releasing Key_Meta, QTest sends 
a KeyRelease event
+    // with MetaModifier even though modifieres should be empty
+    QTest::keyRelease(m_window, Qt::Key_A, Qt::NoModifier);
+    QCOMPARE(sequenceSpy.count(), 3);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence());
+    QCOMPARE(recordingSpy.count(), 1);
+    QVERIFY(recorder.isRecording());
+
+    QTest::qWait(800);
+    QVERIFY(recorder.isRecording());
+
+    QTest::keyPress(m_window, Qt::Key_Control);
+    QCOMPARE(sequenceSpy.count(), 4);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::ControlModifier));
+
+    QTest::keyPress(m_window, Qt::Key_Alt, Qt::ControlModifier);
+    QCOMPARE(sequenceSpy.count(), 6); // QTest sends two key events, one for 
each modifier
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::AltModifier + 
Qt::ControlModifier));
+
+    QCOMPARE(resultSpy.count(), 0); //modifierless not allowed
+}
+
+void KeySequenceRecorderTest::testModifierless()
+{
+    KeySequenceRecorder recorder(m_window);
+    QSignalSpy resultSpy(&recorder,  &KeySequenceRecorder::gotKeySequence);
+    QSignalSpy sequenceSpy(&recorder,  
&KeySequenceRecorder::currentKeySequenceChanged);
+
+    recorder.startRecording();
+    QVERIFY(recorder.isRecording());
+    QCOMPARE(sequenceSpy.count(), 1);
+
+    recorder.setModifierlessAllowed(false);
+    QTest::keyPress(m_window, Qt::Key_A);
+    QTest::qWait(800);
+    QVERIFY(recorder.isRecording());
+    QCOMPARE(sequenceSpy.count(), 1);
+    QCOMPARE(resultSpy.count(), 0);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence());
+
+    recorder.setModifierlessAllowed(true);
+    QTest::keyPress(m_window, Qt::Key_A);
+    QTest::qWait(800);
+    QVERIFY(!recorder.isRecording());
+    QCOMPARE(sequenceSpy.count(), 2);
+    QCOMPARE(resultSpy.count(), 1);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A));
+}
+
+void KeySequenceRecorderTest::testMultiKeyAllowed()
+{
+    KeySequenceRecorder recorder(m_window);
+    QSignalSpy recordingSpy(&recorder,  
&KeySequenceRecorder::recordingChanged);
+    QSignalSpy resultSpy(&recorder,  &KeySequenceRecorder::gotKeySequence);
+
+    recorder.startRecording();
+
+    recorder.setMultiKeyShortcutsAllowed(true);
+    int keys[4] = {0};
+    for (int i = 0; i < 4; ++i) {
+        QVERIFY(recorder.isRecording());
+        QCOMPARE(recordingSpy.count(), 1);
+        QCOMPARE(resultSpy.count(), 0);
+        keys[i] = Qt::Key_A + Qt::ControlModifier;
+        QKeySequence result(keys[0], keys[1], keys[2], keys[3]);
+        QTest::keyPress(m_window, Qt::Key_A, Qt::ControlModifier);
+        QTest::keyRelease(m_window, Qt::Key_A, Qt::ControlModifier);
+        QCOMPARE(recorder.currentKeySequence(), QKeySequence(keys[0], keys[1], 
keys[2], keys[3]));
+    }
+    QVERIFY(!recorder.isRecording());
+    QCOMPARE(recordingSpy.count(), 2);
+    QCOMPARE(resultSpy.count(), 1);
+    QCOMPARE(resultSpy.takeFirst().at(0).value<QKeySequence>(), 
QKeySequence(keys[0], keys[1], keys[2], keys[3]));
+
+    recorder.setMultiKeyShortcutsAllowed(false);
+    recorder.startRecording();
+    QVERIFY(recorder.isRecording());
+    QCOMPARE(recordingSpy.count(), 3);
+    QTest::keyPress(m_window, Qt::Key_A, Qt::ControlModifier);
+    QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A + 
Qt::ControlModifier));
+    QVERIFY(!recorder.isRecording());
+    QCOMPARE(recordingSpy.count(), 4);
+    QCOMPARE(resultSpy.count(), 1);
+    QCOMPARE(resultSpy.takeAt(0).at(0).value<QKeySequence>(), 
QKeySequence(Qt::Key_A + Qt::ControlModifier));
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-5.76.0/autotests/keysequencerecordertest.h 
new/kguiaddons-5.77.0/autotests/keysequencerecordertest.h
--- old/kguiaddons-5.76.0/autotests/keysequencerecordertest.h   1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/autotests/keysequencerecordertest.h   2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,27 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#ifndef KEYSEQUENCERECORDERTEST_H
+#define KEYSEQUENCERECORDERTEST_H
+
+#include <QObject>
+
+class QWindow;
+
+class KeySequenceRecorderTest : public QObject {
+    Q_OBJECT
+private Q_SLOTS:
+    void initTestCase();
+    void cleanupTestCase();
+    void testValidWindow();
+    void testRecording();
+    void testModifiers();
+    void testModifierless();
+    void testMultiKeyAllowed();
+private:
+    QWindow *m_window;
+};
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/src/CMakeLists.txt 
new/kguiaddons-5.77.0/src/CMakeLists.txt
--- old/kguiaddons-5.76.0/src/CMakeLists.txt    2020-11-07 12:37:58.000000000 
+0100
+++ new/kguiaddons-5.77.0/src/CMakeLists.txt    2020-12-05 11:07:55.000000000 
+0100
@@ -13,8 +13,11 @@
  util/kmodifierkeyinfoprovider.cpp
  util/urlhandler.cpp
  util/kcursorsaver.cpp
+ recorder/keyboardgrabber.cpp
+ recorder/keysequencerecorder.cpp
 )
 
+
 set (kguiaddons_LIB_SRCS ${kguiaddons_LIB_SRCS} 
util/kmodifierkeyinfoprovider.cpp)
 
 ecm_qt_declare_logging_category(kguiaddons_LIB_SRCS
@@ -27,6 +30,16 @@
 
 add_library(KF5GuiAddons ${kguiaddons_LIB_SRCS})
 
+if(WITH_WAYLAND)
+    ecm_add_qtwayland_client_protocol(wayland_SRCS
+        PROTOCOL recorder/keyboard-shortcuts-inhibit-unstable-v1.xml
+        BASENAME keyboard-shortcuts-inhibit-unstable-v1
+    )
+    target_sources(KF5GuiAddons PRIVATE recorder/waylandinhibition.cpp 
${wayland_SRCS})
+    target_compile_definitions(KF5GuiAddons PRIVATE WITH_WAYLAND)
+    target_link_libraries(KF5GuiAddons PRIVATE Qt5::GuiPrivate 
Qt5::WaylandClient Wayland::Client)
+endif()
+
 generate_export_header(KF5GuiAddons BASE_NAME KGuiAddons)
 add_library(KF5::GuiAddons ALIAS KF5GuiAddons)
 
@@ -35,6 +48,7 @@
   ${CMAKE_CURRENT_SOURCE_DIR}/fonts
   ${CMAKE_CURRENT_SOURCE_DIR}/text
   ${CMAKE_CURRENT_SOURCE_DIR}/util
+  ${CMAKE_CURRENT_SOURCE_DIR}/recorder
   )
 target_include_directories(KF5GuiAddons PUBLIC 
"$<BUILD_INTERFACE:${kguiaddons_INCLUDES}>")
 target_include_directories(KF5GuiAddons INTERFACE 
"$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KGuiAddons>" )
@@ -96,6 +110,14 @@
   REQUIRED_HEADERS KGuiAddons_HEADERS
 )
 
+ecm_generate_headers(KGuiAddons_HEADERS
+    HEADER_NAMES
+    KeySequenceRecorder
+
+    RELATIVE recorder
+    REQUIRED_HEADERS KGuiAddons_HEADERS
+)
+
 find_package(PythonModuleGeneration)
 
 if (PythonModuleGeneration_FOUND)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-5.76.0/src/recorder/keyboard-shortcuts-inhibit-unstable-v1.xml 
new/kguiaddons-5.77.0/src/recorder/keyboard-shortcuts-inhibit-unstable-v1.xml
--- 
old/kguiaddons-5.76.0/src/recorder/keyboard-shortcuts-inhibit-unstable-v1.xml   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/kguiaddons-5.77.0/src/recorder/keyboard-shortcuts-inhibit-unstable-v1.xml   
    2020-12-05 11:07:55.000000000 +0100
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="keyboard_shortcuts_inhibit_unstable_v1">
+
+  <copyright>
+    Copyright © 2017 Red Hat Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <description summary="Protocol for inhibiting the compositor keyboard 
shortcuts">
+    This protocol specifies a way for a client to request the compositor
+    to ignore its own keyboard shortcuts for a given seat, so that all
+    key events from that seat get forwarded to a surface.
+
+    Warning! The protocol described in this file is experimental and
+    backward incompatible changes may be made. Backward compatible
+    changes may be added together with the corresponding interface
+    version bump.
+    Backward incompatible changes are done by bumping the version
+    number in the protocol and interface names and resetting the
+    interface version. Once the protocol is to be declared stable,
+    the 'z' prefix and the version number in the protocol and
+    interface names are removed and the interface version number is
+    reset.
+  </description>
+
+  <interface name="zwp_keyboard_shortcuts_inhibit_manager_v1" version="1">
+    <description summary="context object for keyboard grab_manager">
+      A global interface used for inhibiting the compositor keyboard shortcuts.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the keyboard shortcuts inhibitor object">
+       Destroy the keyboard shortcuts inhibitor manager.
+      </description>
+    </request>
+
+    <request name="inhibit_shortcuts">
+      <description summary="create a new keyboard shortcuts inhibitor object">
+       Create a new keyboard shortcuts inhibitor object associated with
+       the given surface for the given seat.
+
+       If shortcuts are already inhibited for the specified seat and surface,
+       a protocol error "already_inhibited" is raised by the compositor.
+      </description>
+      <arg name="id" type="new_id" 
interface="zwp_keyboard_shortcuts_inhibitor_v1"/>
+      <arg name="surface" type="object" interface="wl_surface"
+          summary="the surface that inhibits the keyboard shortcuts behavior"/>
+      <arg name="seat" type="object" interface="wl_seat"
+          summary="the wl_seat for which keyboard shortcuts should be 
disabled"/>
+    </request>
+
+    <enum name="error">
+      <entry name="already_inhibited"
+            value="0"
+            summary="the shortcuts are already inhibited for this surface"/>
+    </enum>
+  </interface>
+
+  <interface name="zwp_keyboard_shortcuts_inhibitor_v1" version="1">
+    <description summary="context object for keyboard shortcuts inhibitor">
+      A keyboard shortcuts inhibitor instructs the compositor to ignore
+      its own keyboard shortcuts when the associated surface has keyboard
+      focus. As a result, when the surface has keyboard focus on the given
+      seat, it will receive all key events originating from the specified
+      seat, even those which would normally be caught by the compositor for
+      its own shortcuts.
+
+      The Wayland compositor is however under no obligation to disable
+      all of its shortcuts, and may keep some special key combo for its own
+      use, including but not limited to one allowing the user to forcibly
+      restore normal keyboard events routing in the case of an unwilling
+      client. The compositor may also use the same key combo to reactivate
+      an existing shortcut inhibitor that was previously deactivated on
+      user request.
+
+      When the compositor restores its own keyboard shortcuts, an
+      "inactive" event is emitted to notify the client that the keyboard
+      shortcuts inhibitor is not effectively active for the surface and
+      seat any more, and the client should not expect to receive all
+      keyboard events.
+
+      When the keyboard shortcuts inhibitor is inactive, the client has
+      no way to forcibly reactivate the keyboard shortcuts inhibitor.
+
+      The user can chose to re-enable a previously deactivated keyboard
+      shortcuts inhibitor using any mechanism the compositor may offer,
+      in which case the compositor will send an "active" event to notify
+      the client.
+
+      If the surface is destroyed, unmapped, or loses the seat's keyboard
+      focus, the keyboard shortcuts inhibitor becomes irrelevant and the
+      compositor will restore its own keyboard shortcuts but no "inactive"
+      event is emitted in this case.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the keyboard shortcuts inhibitor object">
+       Remove the keyboard shortcuts inhibitor from the associated wl_surface.
+      </description>
+    </request>
+
+    <event name="active">
+      <description summary="shortcuts are inhibited">
+       This event indicates that the shortcut inhibitor is active.
+
+       The compositor sends this event every time compositor shortcuts
+       are inhibited on behalf of the surface. When active, the client
+       may receive input events normally reserved by the compositor
+       (see zwp_keyboard_shortcuts_inhibitor_v1).
+
+       This occurs typically when the initial request "inhibit_shortcuts"
+       first becomes active or when the user instructs the compositor to
+       re-enable and existing shortcuts inhibitor using any mechanism
+       offered by the compositor.
+      </description>
+    </event>
+
+    <event name="inactive">
+      <description summary="shortcuts are restored">
+       This event indicates that the shortcuts inhibitor is inactive,
+       normal shortcuts processing is restored by the compositor.
+       </description>
+    </event>
+  </interface>
+</protocol>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/src/recorder/keyboardgrabber.cpp 
new/kguiaddons-5.77.0/src/recorder/keyboardgrabber.cpp
--- old/kguiaddons-5.76.0/src/recorder/keyboardgrabber.cpp      1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/keyboardgrabber.cpp      2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,42 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#include "keyboardgrabber_p.h"
+
+#include <QWindow>
+
+KeyboardGrabber::KeyboardGrabber(QWindow *window)
+    : ShortcutInhibition()
+    , m_grabbedWindow(window)
+    , m_grabbingKeyboard(false)
+{
+}
+
+KeyboardGrabber::~KeyboardGrabber()
+{
+    disableInhibition();
+}
+
+void KeyboardGrabber::enableInhibition()
+{
+    if (m_grabbingKeyboard || !m_grabbedWindow) {
+        return;
+    }
+    m_grabbingKeyboard = m_grabbedWindow->setKeyboardGrabEnabled(true);
+}
+
+void KeyboardGrabber::disableInhibition()
+{
+    if (!m_grabbingKeyboard) {
+        return;
+    }
+    m_grabbingKeyboard = !(m_grabbedWindow->setKeyboardGrabEnabled(false));
+}
+
+bool KeyboardGrabber::shortcutsAreInhibited() const
+{
+    return m_grabbingKeyboard;
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/src/recorder/keyboardgrabber_p.h 
new/kguiaddons-5.77.0/src/recorder/keyboardgrabber_p.h
--- old/kguiaddons-5.76.0/src/recorder/keyboardgrabber_p.h      1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/keyboardgrabber_p.h      2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,24 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#ifndef GRABBINGINHIBITION_H
+#define GRABBINGINHIBITION_H
+
+#include "shortcutinhibition_p.h"
+
+class KeyboardGrabber : public ShortcutInhibition
+{
+public:
+    explicit KeyboardGrabber(QWindow *window);
+    ~KeyboardGrabber();
+    void enableInhibition() override;
+    void disableInhibition() override;
+    bool shortcutsAreInhibited() const override;
+private:
+    QWindow *m_grabbedWindow;
+    bool m_grabbingKeyboard;
+};
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-5.76.0/src/recorder/keysequencerecorder.cpp 
new/kguiaddons-5.77.0/src/recorder/keysequencerecorder.cpp
--- old/kguiaddons-5.76.0/src/recorder/keysequencerecorder.cpp  1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/keysequencerecorder.cpp  2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,492 @@
+/*
+    SPDX-FileCopyrightText: 1998 Mark Donohoe <[email protected]>
+    SPDX-FileCopyrightText: 2001 Ellis Whitehead <[email protected]>
+    SPDX-FileCopyrightText: 2007 Andreas Hartmetz <[email protected]>
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "keysequencerecorder.h"
+
+#include "keyboardgrabber_p.h"
+#include "kguiaddons_debug.h"
+#include "shortcutinhibition_p.h"
+#include "waylandinhibition_p.h"
+
+#include <QGuiApplication>
+#include <QKeyEvent>
+#include <QPointer>
+#include <QTimer>
+#include <QWindow>
+
+#include <array>
+#include <memory>
+
+constexpr Qt::KeyboardModifiers modifierMask = Qt::ShiftModifier | 
Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier;
+
+// Copied here from KKeyServer
+static bool isShiftAsModifierAllowed(int keyQt)
+{
+    // remove any modifiers
+    keyQt &= ~Qt::KeyboardModifierMask;
+
+    // Shift only works as a modifier with certain keys. It's not possible
+    // to enter the SHIFT+5 key sequence for me because this is handled as
+    // '%' by qt on my keyboard.
+    // The working keys are all hardcoded here :-(
+    if (keyQt >= Qt::Key_F1 && keyQt <= Qt::Key_F35) {
+        return true;
+    }
+
+    if (QChar(keyQt).isLetter()) {
+        return true;
+    }
+
+    switch (keyQt) {
+    case Qt::Key_Return:
+    case Qt::Key_Space:
+    case Qt::Key_Backspace:
+    case Qt::Key_Tab:
+    case Qt::Key_Backtab:
+    case Qt::Key_Escape:
+    case Qt::Key_Print:
+    case Qt::Key_ScrollLock:
+    case Qt::Key_Pause:
+    case Qt::Key_PageUp:
+    case Qt::Key_PageDown:
+    case Qt::Key_Insert:
+    case Qt::Key_Delete:
+    case Qt::Key_Home:
+    case Qt::Key_End:
+    case Qt::Key_Up:
+    case Qt::Key_Down:
+    case Qt::Key_Left:
+    case Qt::Key_Right:
+    case Qt::Key_Enter:
+    case Qt::Key_SysReq:
+    case Qt::Key_CapsLock:
+    case Qt::Key_NumLock:
+    case Qt::Key_Help:
+    case Qt::Key_Back:
+    case Qt::Key_Forward:
+    case Qt::Key_Stop:
+    case Qt::Key_Refresh:
+    case Qt::Key_Favorites:
+    case Qt::Key_LaunchMedia:
+    case Qt::Key_OpenUrl:
+    case Qt::Key_HomePage:
+    case Qt::Key_Search:
+    case Qt::Key_VolumeDown:
+    case Qt::Key_VolumeMute:
+    case Qt::Key_VolumeUp:
+    case Qt::Key_BassBoost:
+    case Qt::Key_BassUp:
+    case Qt::Key_BassDown:
+    case Qt::Key_TrebleUp:
+    case Qt::Key_TrebleDown:
+    case Qt::Key_MediaPlay:
+    case Qt::Key_MediaStop:
+    case Qt::Key_MediaPrevious:
+    case Qt::Key_MediaNext:
+    case Qt::Key_MediaRecord:
+    case Qt::Key_MediaPause:
+    case Qt::Key_MediaTogglePlayPause:
+    case Qt::Key_LaunchMail:
+    case Qt::Key_Calculator:
+    case Qt::Key_Memo:
+    case Qt::Key_ToDoList:
+    case Qt::Key_Calendar:
+    case Qt::Key_PowerDown:
+    case Qt::Key_ContrastAdjust:
+    case Qt::Key_Standby:
+    case Qt::Key_MonBrightnessUp:
+    case Qt::Key_MonBrightnessDown:
+    case Qt::Key_KeyboardLightOnOff:
+    case Qt::Key_KeyboardBrightnessUp:
+    case Qt::Key_KeyboardBrightnessDown:
+    case Qt::Key_PowerOff:
+    case Qt::Key_WakeUp:
+    case Qt::Key_Eject:
+    case Qt::Key_ScreenSaver:
+    case Qt::Key_WWW:
+    case Qt::Key_Sleep:
+    case Qt::Key_LightBulb:
+    case Qt::Key_Shop:
+    case Qt::Key_History:
+    case Qt::Key_AddFavorite:
+    case Qt::Key_HotLinks:
+    case Qt::Key_BrightnessAdjust:
+    case Qt::Key_Finance:
+    case Qt::Key_Community:
+    case Qt::Key_AudioRewind:
+    case Qt::Key_BackForward:
+    case Qt::Key_ApplicationLeft:
+    case Qt::Key_ApplicationRight:
+    case Qt::Key_Book:
+    case Qt::Key_CD:
+    case Qt::Key_Clear:
+    case Qt::Key_ClearGrab:
+    case Qt::Key_Close:
+    case Qt::Key_Copy:
+    case Qt::Key_Cut:
+    case Qt::Key_Display:
+    case Qt::Key_DOS:
+    case Qt::Key_Documents:
+    case Qt::Key_Excel:
+    case Qt::Key_Explorer:
+    case Qt::Key_Game:
+    case Qt::Key_Go:
+    case Qt::Key_iTouch:
+    case Qt::Key_LogOff:
+    case Qt::Key_Market:
+    case Qt::Key_Meeting:
+    case Qt::Key_MenuKB:
+    case Qt::Key_MenuPB:
+    case Qt::Key_MySites:
+    case Qt::Key_News:
+    case Qt::Key_OfficeHome:
+    case Qt::Key_Option:
+    case Qt::Key_Paste:
+    case Qt::Key_Phone:
+    case Qt::Key_Reply:
+    case Qt::Key_Reload:
+    case Qt::Key_RotateWindows:
+    case Qt::Key_RotationPB:
+    case Qt::Key_RotationKB:
+    case Qt::Key_Save:
+    case Qt::Key_Send:
+    case Qt::Key_Spell:
+    case Qt::Key_SplitScreen:
+    case Qt::Key_Support:
+    case Qt::Key_TaskPane:
+    case Qt::Key_Terminal:
+    case Qt::Key_Tools:
+    case Qt::Key_Travel:
+    case Qt::Key_Video:
+    case Qt::Key_Word:
+    case Qt::Key_Xfer:
+    case Qt::Key_ZoomIn:
+    case Qt::Key_ZoomOut:
+    case Qt::Key_Away:
+    case Qt::Key_Messenger:
+    case Qt::Key_WebCam:
+    case Qt::Key_MailForward:
+    case Qt::Key_Pictures:
+    case Qt::Key_Music:
+    case Qt::Key_Battery:
+    case Qt::Key_Bluetooth:
+    case Qt::Key_WLAN:
+    case Qt::Key_UWB:
+    case Qt::Key_AudioForward:
+    case Qt::Key_AudioRepeat:
+    case Qt::Key_AudioRandomPlay:
+    case Qt::Key_Subtitle:
+    case Qt::Key_AudioCycleTrack:
+    case Qt::Key_Time:
+    case Qt::Key_Select:
+    case Qt::Key_View:
+    case Qt::Key_TopMenu:
+    case Qt::Key_Suspend:
+    case Qt::Key_Hibernate:
+    case Qt::Key_Launch0:
+    case Qt::Key_Launch1:
+    case Qt::Key_Launch2:
+    case Qt::Key_Launch3:
+    case Qt::Key_Launch4:
+    case Qt::Key_Launch5:
+    case Qt::Key_Launch6:
+    case Qt::Key_Launch7:
+    case Qt::Key_Launch8:
+    case Qt::Key_Launch9:
+    case Qt::Key_LaunchA:
+    case Qt::Key_LaunchB:
+    case Qt::Key_LaunchC:
+    case Qt::Key_LaunchD:
+    case Qt::Key_LaunchE:
+    case Qt::Key_LaunchF:
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+
+static bool isOkWhenModifierless(int key)
+{
+    //this whole function is a hack, but especially the first line of code
+    if (QKeySequence(key).toString().length() == 1) {
+        return false;
+    }
+
+    switch (key) {
+    case Qt::Key_Return:
+    case Qt::Key_Space:
+    case Qt::Key_Tab:
+    case Qt::Key_Backtab: //does this ever happen?
+    case Qt::Key_Backspace:
+    case Qt::Key_Delete:
+        return false;
+    default:
+        return true;
+    }
+}
+
+static QKeySequence appendToSequence(const QKeySequence &sequence, int key) {
+    std::array<int, 4> keys{sequence[0], sequence[1], sequence[2], 
sequence[3]};
+    keys[sequence.count()] = key;
+    return QKeySequence(keys[0], keys[1], keys[2], keys[3]);
+}
+
+class KeySequenceRecorderPrivate : public QObject {
+    Q_OBJECT
+public:
+    KeySequenceRecorderPrivate(KeySequenceRecorder *q);
+
+    void controlModifierlessTimeout();
+    bool eventFilter(QObject *watched, QEvent *event) override;
+    void handleKeyPress(QKeyEvent *event);
+    void handleKeyRelease(QKeyEvent *event);
+    void finishRecording();
+
+    KeySequenceRecorder *q;
+    QKeySequence m_currentKeySequence;
+    QPointer<QWindow> m_window;
+    bool m_isRecording;
+    bool m_multiKeyShortcutsAllowed;
+    bool m_modifierlessAllowed;
+
+    Qt::KeyboardModifiers m_currentModifiers;
+    QTimer m_modifierlessTimer;
+    std::unique_ptr<ShortcutInhibition> m_inhibition;
+};
+
+KeySequenceRecorderPrivate::KeySequenceRecorderPrivate(KeySequenceRecorder *q)
+    : QObject(q)
+    , q(q)
+{
+}
+
+void KeySequenceRecorderPrivate::controlModifierlessTimeout()
+{
+    if (m_currentKeySequence != 0 && !m_currentModifiers) {
+        // No modifier key pressed currently. Start the timout
+        m_modifierlessTimer.start(600);
+    } else {
+        // A modifier is pressed. Stop the timeout
+        m_modifierlessTimer.stop();
+    }
+}
+
+bool KeySequenceRecorderPrivate::eventFilter(QObject *watched, QEvent *event)
+{
+    if (!m_isRecording) {
+        return QObject::eventFilter(watched, event);
+    }
+
+    if (event->type() == QEvent::ShortcutOverride || event->type() == 
QEvent::ContextMenu) {
+        event->accept();
+        return true;
+    }
+    if (event->type() == QEvent::KeyRelease) {
+        handleKeyRelease(static_cast<QKeyEvent*>(event));
+        return true;
+    }
+    if (event->type() == QEvent::KeyPress) {
+        handleKeyPress(static_cast<QKeyEvent*>(event));
+        return true;
+    }
+    return QObject::eventFilter(watched, event);
+}
+
+void KeySequenceRecorderPrivate::handleKeyPress(QKeyEvent *event)
+{
+
+    m_currentModifiers = event->modifiers() & modifierMask;
+    int key = event->key();
+    switch (key) {
+    case -1:
+        qCWarning(KGUIADDONS_LOG) << "Got unknown key";
+        // Old behavior was to stop recording here instead of continuing like 
this
+        return;
+    case 0:
+        break;
+    case Qt::Key_AltGr:
+        //or else we get unicode salad
+        break;
+    case Qt::Key_Super_L:
+    case Qt::Key_Super_R:
+        // Qt doesn't properly recognize Super_L/Super_R as MetaModifier
+        m_currentModifiers |= Qt::MetaModifier;
+        Q_FALLTHROUGH();
+    case Qt::Key_Shift:
+    case Qt::Key_Control:
+    case Qt::Key_Alt:
+    case Qt::Key_Meta:
+        controlModifierlessTimeout();
+        Q_EMIT q->currentKeySequenceChanged();
+        break;
+    default:
+        if (m_currentKeySequence.count() == 0 && !(m_currentModifiers & 
~Qt::ShiftModifier)) {
+            // It's the first key and no modifier pressed. Check if this is 
allowed
+            if (!(isOkWhenModifierless(key) || m_modifierlessAllowed)) {
+                // No it's not
+                return;
+            }
+        }
+
+        // We now have a valid key press.
+        if ((key == Qt::Key_Backtab) && (m_currentModifiers & 
Qt::ShiftModifier)) {
+            key = Qt::Key_Tab | m_currentModifiers;
+        } else if (isShiftAsModifierAllowed(key)) {
+            key |= m_currentModifiers;
+        } else {
+            key |= (m_currentModifiers & ~Qt::ShiftModifier);
+        }
+
+        m_currentKeySequence = appendToSequence(m_currentKeySequence, key);
+        Q_EMIT q->currentKeySequenceChanged();
+
+        if ((!m_multiKeyShortcutsAllowed) || (m_currentKeySequence.count() == 
4)) {
+            finishRecording();
+            break;
+        }
+        controlModifierlessTimeout();
+    }
+    event->accept();
+}
+
+void KeySequenceRecorderPrivate::handleKeyRelease(QKeyEvent *event)
+{
+    Qt::KeyboardModifiers modifiers = event->modifiers() & modifierMask;
+    switch (event->key()) {
+    case -1:
+        return;
+    case Qt::Key_Super_L:
+    case Qt::Key_Super_R:
+        // Qt doesn't properly recognize Super_L/Super_R as MetaModifier
+        modifiers &= ~Qt::MetaModifier;
+    }
+    if ((modifiers & m_currentModifiers) < m_currentModifiers) {
+        m_currentModifiers = modifiers;
+        controlModifierlessTimeout();
+        Q_EMIT q->currentKeySequenceChanged();
+    }
+}
+
+void KeySequenceRecorderPrivate::finishRecording()
+{
+    m_modifierlessTimer.stop();
+    m_isRecording = false;
+    m_currentModifiers = Qt::NoModifier;
+    if (m_inhibition) {
+        m_inhibition->disableInhibition();
+    }
+    Q_EMIT q->recordingChanged();
+    Q_EMIT q->gotKeySequence(m_currentKeySequence);
+}
+
+KeySequenceRecorder::KeySequenceRecorder(QWindow *window, QObject *parent)
+    : QObject(parent)
+    , d(new KeySequenceRecorderPrivate(this))
+{
+    d->m_isRecording = false;
+    d->m_modifierlessAllowed = false;
+    d->m_multiKeyShortcutsAllowed = true;
+
+    setWindow(window);
+    connect(&d->m_modifierlessTimer, &QTimer::timeout, d.get(), 
&KeySequenceRecorderPrivate::finishRecording);
+}
+
+KeySequenceRecorder::~KeySequenceRecorder() noexcept
+{
+}
+
+void KeySequenceRecorder::startRecording()
+{
+    if (!d->m_window) {
+        qCWarning(KGUIADDONS_LOG) << "Cannot record without a window";
+        return;
+    }
+    d->m_isRecording = true;
+    d->m_currentKeySequence = QKeySequence();
+    if (d->m_inhibition) {
+        d->m_inhibition->enableInhibition();
+    }
+    Q_EMIT recordingChanged();
+    Q_EMIT currentKeySequenceChanged();
+}
+
+bool KeySequenceRecorder::isRecording() const
+{
+    return d->m_isRecording;
+}
+
+QKeySequence KeySequenceRecorder::currentKeySequence() const
+{
+    return  d->m_isRecording ? appendToSequence(d->m_currentKeySequence, 
d->m_currentModifiers) : d->m_currentKeySequence;
+}
+
+QWindow* KeySequenceRecorder::window() const
+{
+    return d->m_window;
+}
+
+void KeySequenceRecorder::setWindow(QWindow *window)
+{
+    if (window == d->m_window) {
+        return;
+    }
+
+    if (d->m_window) {
+        d->m_window->removeEventFilter(d.get());
+    }
+
+    if (window) {
+        window->installEventFilter(d.get());
+        qCDebug(KGUIADDONS_LOG) << "listening for events in" << window;
+    }
+
+    if (qApp->platformName() == QLatin1String("wayland")) {
+#ifdef WITH_WAYLAND
+        d->m_inhibition.reset(new WaylandInhibition(window));
+#endif
+    } else  {
+        d->m_inhibition.reset(new KeyboardGrabber(window));
+    }
+
+    d->m_window = window;
+
+    Q_EMIT windowChanged();
+}
+
+bool KeySequenceRecorder::multiKeyShortcutsAllowed() const
+{
+    return d->m_multiKeyShortcutsAllowed;
+}
+
+void KeySequenceRecorder::setMultiKeyShortcutsAllowed(bool allowed)
+{
+    if (allowed == d->m_multiKeyShortcutsAllowed) {
+        return;
+    }
+    d->m_multiKeyShortcutsAllowed = allowed;
+    Q_EMIT multiKeyShortcutsAllowedChanged();
+}
+
+bool KeySequenceRecorder::modifierlessAllowed() const
+{
+    return d->m_modifierlessAllowed;
+}
+
+void KeySequenceRecorder::setModifierlessAllowed(bool allowed)
+{
+    if (allowed == d->m_modifierlessAllowed) {
+        return;
+    }
+    d->m_modifierlessAllowed = allowed;
+    Q_EMIT modifierlessAllowedChanged();
+}
+
+#include "keysequencerecorder.moc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/src/recorder/keysequencerecorder.h 
new/kguiaddons-5.77.0/src/recorder/keysequencerecorder.h
--- old/kguiaddons-5.76.0/src/recorder/keysequencerecorder.h    1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/keysequencerecorder.h    2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,132 @@
+/*
+    SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <[email protected]>
+    SPDX-FileCopyrightText: 2007 Andreas Hartmetz <[email protected]>
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+
+#ifndef KSHORTCUTRECORDER_H
+#define KSHORTCUTRECORDER_H
+
+#include <kguiaddons_export.h>
+
+#include <QKeySequence>
+#include <QObject>
+
+#include <memory>
+
+class KeySequenceRecorderPrivate;
+
+class QWindow;
+
+/**
+ * @class KeySequenceRecorder keysequencerecorder.h KeySequenceRecorder
+ *
+ * @short Record a QKeySequence by listening to key events in a window.
+ *
+ * After calling startRecording key events in the set window will be captured 
until a valid
+ * QKeySequence has been recorded and gotKeySequence is emitted. See 
multiKeyShortcutsAllowed and
+ * modifierlessAllowed for what constitutes a valid key sequence.
+ *
+ * During recording any shortcuts are inhibited and cannot be triggered. 
Either by using the
+ * <a 
href="https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml";>
+ * keyboard-shortcuts-inhibit protocol </a> on Wayland or grabbing the 
keyboard.
+ *
+ * For graphical elements that record key sequences and can optionally perform 
conflict checking
+ * against existing shortcuts see KKeySequenceWidget and KeySequenceItem.
+ * @since 5.77
+ * @see KKeySequenceWidget, KeySequenceItem
+ */
+
+class KGUIADDONS_EXPORT KeySequenceRecorder : public QObject 
+{
+    Q_OBJECT
+
+    /**
+     * Whether key events are currently recorded
+     */
+    Q_PROPERTY(bool isRecording READ isRecording NOTIFY recordingChanged)
+    /**
+     * The recorded key sequence.
+     * After construction this is empty.
+     *
+     * During recording it is continiously updated with the newest user input.
+     *
+     * After recording it contains the last recorded QKeySequence
+     */
+    Q_PROPERTY(QKeySequence currentKeySequence READ currentKeySequence NOTIFY 
currentKeySequenceChanged)
+    /**
+     * The window in which the key events are happening that should be recorded
+     */
+    Q_PROPERTY(QWindow* window READ window WRITE setWindow NOTIFY 
windowChanged)
+    /**
+     * If key presses of "plain" keys without a modifier are considered to be 
a valid finished
+     * key combination.
+     * Plain keys  include letter and symbol keys and text editing keys 
(Return, Space, Tab,
+     * Backspace, Delete). Other keys like F1, Cursor keys, Insert, PageDown 
will always work.
+     *
+     * By default this is `false`.
+     */
+    Q_PROPERTY(bool modifierlessAllowed READ modifierlessAllowed WRITE 
setModifierlessAllowed NOTIFY modifierlessAllowedChanged)
+    /** Controls the amount of key combinations that are captured until 
recording stops and gotKeySequence
+     * is emitted.
+     * By default  this is `true` and "Emacs-style" key sequences are 
recorded. Recording does not
+     * stop until four valid key combination have been recorded. Afterwards 
`currentKeySequence().count()`
+     * will be 4.
+     *
+     * Otherwise only one key combination is recorded before gotKeySequence is 
emitted with a
+     * QKeySequence with a `count()` of  1.
+     * @see QKeySequence
+     */
+    Q_PROPERTY(bool multiKeyShortcutsAllowed READ multiKeyShortcutsAllowed 
WRITE setMultiKeyShortcutsAllowed NOTIFY multiKeyShortcutsAllowedChanged)
+public:
+    /**
+     * Constructor.
+     *
+     * @par window The window whose key events will be recorded.
+     * @see window
+     */
+    explicit KeySequenceRecorder(QWindow *window, QObject *parent = nullptr);
+    ~KeySequenceRecorder();
+
+    /**
+     * Start recording.
+     * Calling startRecording when window() is `nullptr` has no effect.
+     */
+    void Q_INVOKABLE startRecording();
+
+    bool isRecording() const;
+
+    QKeySequence currentKeySequence() const;
+
+    QWindow* window() const;
+    void setWindow(QWindow *window);
+
+    bool multiKeyShortcutsAllowed() const;
+    void setMultiKeyShortcutsAllowed(bool allowed);
+
+    void setModifierlessAllowed(bool allowed);
+    bool modifierlessAllowed() const;
+
+Q_SIGNALS:
+    /**
+     * This signal is emitted when a key sequence has been recorded.
+     *
+     * Compared to currentKeySequenceChanged and currentKeySequence this is 
signal is not emmitted
+     * continiously during recording but only after recording has finished.
+     */
+    void gotKeySequence(const QKeySequence &keySequence);
+
+    void recordingChanged();
+    void windowChanged();
+    void currentKeySequenceChanged();
+    void multiKeyShortcutsAllowedChanged();
+    void modifierlessAllowedChanged();
+private:
+    friend class KeySequenceRecorderPrivate;
+    std::unique_ptr<KeySequenceRecorderPrivate> d;
+};
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-5.76.0/src/recorder/shortcutinhibition_p.h 
new/kguiaddons-5.77.0/src/recorder/shortcutinhibition_p.h
--- old/kguiaddons-5.76.0/src/recorder/shortcutinhibition_p.h   1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/shortcutinhibition_p.h   2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,19 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#ifndef SHORTCUTINHIBITION_H
+#define SHORTCUTINHIBITION_H
+
+class QWindow;
+
+class ShortcutInhibition {
+public:
+    virtual ~ShortcutInhibition(){}
+    virtual void enableInhibition() = 0;
+    virtual void disableInhibition() = 0;
+    virtual bool shortcutsAreInhibited() const = 0;
+};
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/src/recorder/waylandinhibition.cpp 
new/kguiaddons-5.77.0/src/recorder/waylandinhibition.cpp
--- old/kguiaddons-5.76.0/src/recorder/waylandinhibition.cpp    1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/waylandinhibition.cpp    2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,104 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#include "waylandinhibition_p.h"
+
+#include <QGuiApplication>
+#include <qpa/qplatformnativeinterface.h>
+#include <QtWaylandClient/QWaylandClientExtensionTemplate>
+
+#include "qwayland-keyboard-shortcuts-inhibit-unstable-v1.h"
+
+class ShortcutsInhibitManager
+    : public QWaylandClientExtensionTemplate<ShortcutsInhibitManager>
+    , public QtWayland::zwp_keyboard_shortcuts_inhibit_manager_v1
+{
+public:
+    ShortcutsInhibitManager()
+        : QWaylandClientExtensionTemplate<ShortcutsInhibitManager>(1)
+    {
+        // QWaylandClientExtensionTemplate invokes this with a 
QueuedConnection but we want shortcuts
+        // to be inhibited immediately.
+        QMetaObject::invokeMethod(this, "addRegistryListener");
+    }
+    ~ShortcutsInhibitManager()
+    {
+        if (isInitialized()) {
+            destroy();
+        }
+    }
+};
+
+class ShortcutsInhibitor : public 
QtWayland::zwp_keyboard_shortcuts_inhibitor_v1
+{
+public:
+    ShortcutsInhibitor(::zwp_keyboard_shortcuts_inhibitor_v1 *id)
+        : QtWayland::zwp_keyboard_shortcuts_inhibitor_v1(id)
+    {
+    }
+
+    ~ShortcutsInhibitor()
+    {
+        destroy();
+    }
+
+    void zwp_keyboard_shortcuts_inhibitor_v1_active() override
+    {
+        m_active = true;
+    }
+
+    void zwp_keyboard_shortcuts_inhibitor_v1_inactive() override
+    {
+        m_active = false;
+    }
+
+    bool isActive() const 
+    {
+        return m_active;
+    }
+
+private:
+    bool m_active = false;
+};
+
+WaylandInhibition::WaylandInhibition(QWindow *window)
+    : ShortcutInhibition()
+    , m_manager(new ShortcutsInhibitManager)
+    , m_window(window)
+{
+}
+
+WaylandInhibition::~WaylandInhibition() = default;
+
+bool WaylandInhibition::shortcutsAreInhibited() const
+{
+    return m_inhibitor && m_inhibitor->isActive();
+}
+
+void WaylandInhibition::enableInhibition()
+{
+    if (m_inhibitor || !m_manager->isActive()) {
+        return;
+    }
+    QPlatformNativeInterface *nativeInterface = 
qApp->platformNativeInterface();
+    if (!nativeInterface) {
+        return;
+    }
+    auto seat = 
static_cast<wl_seat*>(nativeInterface->nativeResourceForIntegration("wl_seat"));
+    auto surface = 
static_cast<wl_surface*>(nativeInterface->nativeResourceForWindow("surface", 
m_window));
+    if (!seat || !surface) {
+        return;
+    }
+    m_inhibitor.reset(new 
ShortcutsInhibitor(m_manager->inhibit_shortcuts(surface, seat)));
+}
+
+void WaylandInhibition::disableInhibition()
+{
+    if (!m_inhibitor) {
+        return;
+    }
+    m_inhibitor.reset();
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/src/recorder/waylandinhibition_p.h 
new/kguiaddons-5.77.0/src/recorder/waylandinhibition_p.h
--- old/kguiaddons-5.76.0/src/recorder/waylandinhibition_p.h    1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-5.77.0/src/recorder/waylandinhibition_p.h    2020-12-05 
11:07:55.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+    SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
+*/
+
+#ifndef WAYLANDSHORTCUTINHIBITOR_H
+#define WAYLANDSHORTCUTINHIBITOR_H
+
+#include "shortcutinhibition_p.h"
+
+#include <memory>
+
+class ShortcutsInhibitManager;
+class ShortcutsInhibitor;
+
+class WaylandInhibition : public ShortcutInhibition
+{
+public:
+    explicit WaylandInhibition(QWindow *window);
+    ~WaylandInhibition() override;
+    bool shortcutsAreInhibited() const override;
+    void enableInhibition() override;
+    void disableInhibition() override;
+private:
+
+    std::unique_ptr<ShortcutsInhibitManager> m_manager;
+    std::unique_ptr<ShortcutsInhibitor> m_inhibitor;
+    QWindow *m_window;
+};
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-5.76.0/tests/kmodifierkeyinfotest.cpp 
new/kguiaddons-5.77.0/tests/kmodifierkeyinfotest.cpp
--- old/kguiaddons-5.76.0/tests/kmodifierkeyinfotest.cpp        2020-11-07 
12:37:58.000000000 +0100
+++ new/kguiaddons-5.77.0/tests/kmodifierkeyinfotest.cpp        2020-12-05 
11:07:55.000000000 +0100
@@ -120,8 +120,6 @@
         layout->addLayout(hlayout);
     }
 
-    setLayout(layout);
-
     connect(&m_lock, &KModifierKeyInfo::keyPressed,
             this, &TestWidget::keyPressed);
     connect(&m_lock, &KModifierKeyInfo::keyLatched,
_______________________________________________
openSUSE Commits mailing list -- [email protected]
To unsubscribe, email [email protected]
List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette
List Archives: 
https://lists.opensuse.org/archives/list/[email protected]

Reply via email to