Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package plasma6-keyboard for 
openSUSE:Factory checked in at 2026-06-25 10:51:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/plasma6-keyboard (Old)
 and      /work/SRC/openSUSE:Factory/.plasma6-keyboard.new.2088 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "plasma6-keyboard"

Thu Jun 25 10:51:10 2026 rev:8 rq:1361422 version:6.7.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/plasma6-keyboard/plasma6-keyboard.changes        
2026-06-18 21:38:13.738105799 +0200
+++ 
/work/SRC/openSUSE:Factory/.plasma6-keyboard.new.2088/plasma6-keyboard.changes  
    2026-06-25 10:55:12.793247520 +0200
@@ -1,0 +2,12 @@
+Tue Jun 23 11:00:26 UTC 2026 - Fabian Vogt <[email protected]>
+
+- Update to 6.7.1:
+  * New bugfix release
+  * For more details see https://kde.org/announcements/plasma/6/6.7.1
+- Changes since 6.7.0:
+  * Update version for new release 6.7.1
+  * fix: Don't try to close diacritics overlay twice
+  * fix: Don't disable key repeat when diacritics overlay is enabled
+  * fix: improve reliability of dead key and compose key handling w/ overlay 
(kde#518141,kde#519339,kde#520410,kde#520344)
+
+-------------------------------------------------------------------

Old:
----
  plasma-keyboard-6.7.0.tar.xz
  plasma-keyboard-6.7.0.tar.xz.sig

New:
----
  plasma-keyboard-6.7.1.tar.xz
  plasma-keyboard-6.7.1.tar.xz.sig

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

Other differences:
------------------
++++++ plasma6-keyboard.spec ++++++
--- /var/tmp/diff_new_pack.jSb6lv/_old  2026-06-25 10:55:13.857284333 +0200
+++ /var/tmp/diff_new_pack.jSb6lv/_new  2026-06-25 10:55:13.869284748 +0200
@@ -30,14 +30,14 @@
 %{!?_plasma6_version: %define _plasma6_version %(echo %{_plasma6_bugfix} | awk 
-F. '{print $1"."$2}')}
 %bcond_without released
 Name:           plasma6-keyboard
-Version:        6.7.0
+Version:        6.7.1
 Release:        0
 Summary:        Virtual Keyboard for Qt based desktops
 License:        GPL-2.0-or-later AND GPL-3.0-only
 URL:            https://invent.kde.org/plasma/plasma-keyboard
-Source:         %{rname}-%{version}.tar.xz
+Source:         
https://download.kde.org/stable/plasma/%{version}/%{rname}-%{version}.tar.xz
 %if %{with released}
-Source1:        %{rname}-%{version}.tar.xz.sig
+Source1:        
https://download.kde.org/stable/plasma/%{version}/%{rname}-%{version}.tar.xz.sig
 Source2:        plasma.keyring
 %endif
 

++++++ plasma-keyboard-6.7.0.tar.xz -> plasma-keyboard-6.7.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/CMakeLists.txt 
new/plasma-keyboard-6.7.1/CMakeLists.txt
--- old/plasma-keyboard-6.7.0/CMakeLists.txt    2026-06-11 11:36:13.000000000 
+0200
+++ new/plasma-keyboard-6.7.1/CMakeLists.txt    2026-06-23 10:15:21.000000000 
+0200
@@ -3,7 +3,7 @@
 
 cmake_minimum_required(VERSION 3.16)
 
-set(PROJECT_VERSION "6.7.0")
+set(PROJECT_VERSION "6.7.1")
 
 project(plasma-keyboard VERSION ${PROJECT_VERSION})
 
@@ -63,6 +63,9 @@
 
 ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX PLASMA_KEYBOARD 
VERSION_HEADER plasma_keyboard_version.h)
 
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(XKBCommon REQUIRED IMPORTED_TARGET xkbcommon)
+
 find_package(Wayland 1.2 REQUIRED COMPONENTS Client)
 find_package(QtWaylandScanner REQUIRED ${QT_MIN_VERSION})
 find_package(WaylandProtocols 1.19 REQUIRED)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/autotests/CMakeLists.txt 
new/plasma-keyboard-6.7.1/autotests/CMakeLists.txt
--- old/plasma-keyboard-6.7.0/autotests/CMakeLists.txt  2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/autotests/CMakeLists.txt  2026-06-23 
10:15:21.000000000 +0200
@@ -9,7 +9,16 @@
     CONTENT "#pragma once\n#define PLASMA_KEYBOARD_BINARY_PATH 
\"$<TARGET_FILE:plasma-keyboard>\"\n"
 )
 
-ecm_add_test(mockinputmethodcompositor.cpp LINK_LIBRARIES KF6::ConfigCore 
Qt::Core Qt::Gui Qt::GuiPrivate Qt::Test Qt::WaylandCompositor Wayland::Server)
+ecm_add_test(mockinputmethodcompositor.cpp LINK_LIBRARIES
+    KF6::ConfigCore
+    PkgConfig::XKBCommon
+    Qt::Core
+    Qt::Gui
+    Qt::GuiPrivate
+    Qt::Test
+    Qt::WaylandCompositor
+    Wayland::Server
+)
 
 qt6_generate_wayland_protocol_server_sources(mockinputmethodcompositor
     FILES
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/plasma-keyboard-6.7.0/autotests/mockinputmethodcompositor.cpp 
new/plasma-keyboard-6.7.1/autotests/mockinputmethodcompositor.cpp
--- old/plasma-keyboard-6.7.0/autotests/mockinputmethodcompositor.cpp   
2026-06-11 11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/autotests/mockinputmethodcompositor.cpp   
2026-06-23 10:15:21.000000000 +0200
@@ -34,7 +34,7 @@
 #include <linux/input-event-codes.h>
 #include <sys/mman.h>
 #include <unistd.h>
-#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-compose.h>
 
 #define PLASMA_KEYBOARD_UNDER_GDB 0
 
@@ -73,7 +73,7 @@
     InputMethodKeyboard(wl_client *client, uint32_t id, int version)
         : QtWaylandServer::wl_keyboard(client, id, version)
     {
-        sendKeymap();
+        initializeKeymap();
         m_timer.start();
     }
 
@@ -96,11 +96,15 @@
         return m_keymapped;
     }
 
-Q_SIGNALS:
-    void keymapDone();
-
-private:
-    void sendKeymap()
+    /**
+     * Sets an updated XKB keymap built from the given layout and variant.
+     * Use this to simulate a compositor keymap change (e.g. switching to 
us/intl
+     * so that dead keys produce the correct keysyms in the child process).
+     *
+     * @param layout XKB layout name (e.g. "us")
+     * @param variant XKB variant name (e.g. "intl"), or nullptr for none
+     */
+    void setKeymap(const char *layout, const char *variant = nullptr)
     {
         QXkbCommon::ScopedXKBContext 
context(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
         if (!context) {
@@ -110,11 +114,13 @@
 
         xkb_rule_names names = {};
         names.rules = "evdev";
-        names.layout = "us";
+        names.layout = layout;
+        names.variant = variant ? variant : "";
+        names.options = "compose:menu";
 
         QXkbCommon::ScopedXKBKeymap 
keymap(xkb_keymap_new_from_names(context.get(), &names, 
XKB_KEYMAP_COMPILE_NO_FLAGS));
         if (!keymap) {
-            qWarning() << "Failed to create xkb keymap";
+            qWarning() << "Failed to create xkb keymap for layout" << layout 
<< variant;
             return;
         }
 
@@ -143,10 +149,23 @@
             qWarning() << "Failed to write keymap terminator";
             return;
         }
-        lseek(fd, 0, SEEK_SET);
+        if (lseek(fd, 0, SEEK_SET) < 0) {
+            close(fd);
+            qWarning() << "Failed to seek keymap file";
+            return;
+        }
 
         send_keymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, mapData.size() + 1);
         close(fd);
+    }
+
+Q_SIGNALS:
+    void keymapDone();
+
+private:
+    void initializeKeymap()
+    {
+        setKeymap("us");
         m_keymapped = true;
         Q_EMIT keymapDone();
     }
@@ -176,6 +195,7 @@
 Q_SIGNALS:
     void keyboardGrabbed();
     void commitStringChanged(const QString &commitString);
+    void keysymReceived(uint32_t sym, uint32_t state);
 
 protected:
     void zwp_input_method_context_v1_destroy(Resource *resource) override
@@ -206,6 +226,7 @@
     {
         Q_UNUSED(resource);
         qInfo() << "keysym" << serial << time << sym << state << modifiers;
+        Q_EMIT keysymReceived(sym, state);
     }
 
     void zwp_input_method_context_v1_grab_keyboard(Resource *resource, 
uint32_t keyboard) override
@@ -545,6 +566,21 @@
         wl_display_flush_clients(m_compositor->display());
     }
 
+    /**
+     * Sets an updated keymap and waits for it to be processed.
+     *
+     * @param layout XKB layout name (e.g. "us")
+     * @param variant XKB variant name (e.g. "intl"), or nullptr for none
+     */
+    void setKeymap(const char *layout, const char *variant = nullptr)
+    {
+        auto *keyboard = m_inputMethod->context()->keyboard();
+        Q_ASSERT(keyboard);
+        keyboard->setKeymap(layout, variant);
+        wl_display_flush_clients(m_compositor->display());
+        QTest::qWait(200);
+    }
+
     void testLongPressShowsOverlayPanel()
     {
         QSignalSpy overlaySpy(m_inputPanel.get(), 
&InputPanelV1::overlayPanelRequested);
@@ -559,6 +595,91 @@
         QCOMPARE(commitStringSpy.first().first().toString(), 
QStringLiteral("à"));
     }
 
+    /**
+     * Test that a Multi_key compose sequence (Multi_key + t + m → ™) is 
handled
+     * locally by the XKB compose state machine in OverlayController. The
+     * intermediate keys must be consumed and not forwarded to the compositor;
+     * only the composed result should arrive via commit_string.
+     */
+    void testComposeSequence()
+    {
+        // Skip if no XKB compose table is available for the current locale.
+        // Without one, OverlayController::m_xkbComposeState is null and the
+        // compose sequence would not be processed locally.
+        {
+            QXkbCommon::ScopedXKBContext 
xkbContext(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
+            if (!xkbContext) {
+                QSKIP("Could not create XKB context");
+            }
+            const char *locale = setlocale(LC_CTYPE, nullptr);
+            if (!locale || locale[0] == '\0') {
+                locale = "C";
+            }
+            xkb_compose_table *composeTable = 
xkb_compose_table_new_from_locale(xkbContext.get(), locale, 
XKB_COMPOSE_COMPILE_NO_FLAGS);
+            if (!composeTable) {
+                QSKIP("No XKB compose table available for the current locale");
+            }
+            xkb_compose_table_unref(composeTable);
+        }
+
+        QSignalSpy overlaySpy(m_inputPanel.get(), 
&InputPanelV1::overlayPanelRequested);
+        QSignalSpy commitStringSpy(m_inputMethod->context(), 
&InputMethodContext::commitStringChanged);
+        QSignalSpy keysymSpy(m_inputMethod->context(), 
&InputMethodContext::keysymReceived);
+
+        // Send the compose sequence: Multi_key → t → m → ™
+        // KEY_COMPOSE (127) maps to Multi_key via the compose:menu keymap 
option.
+        sendKey(KEY_COMPOSE, 10);
+        sendKey(KEY_T, 10);
+        sendKey(KEY_M, 10);
+
+        // Exactly one commit_string with the composed character should arrive.
+        QTRY_COMPARE(commitStringSpy.count(), 1);
+        QCOMPARE(commitStringSpy.first().first().toString(), 
QStringLiteral("™"));
+
+        // The intermediate keys (t, m) must not have been forwarded via 
keysym.
+        // XKB_KEY_t = 0x74, XKB_KEY_m = 0x6d
+        for (const QList<QVariant> &args : keysymSpy) {
+            const uint32_t sym = args.at(0).toUInt();
+            QVERIFY2(sym != 0x74 && sym != 0x6d, "A compose sequence key (t or 
m) was incorrectly forwarded via keysym");
+        }
+
+        // No overlay should have appeared during the compose sequence.
+        QTest::qWait(200);
+        QVERIFY(overlaySpy.isEmpty());
+    }
+
+    /**
+     * Test that pressing a dead key (e.g. the grave key `) followed by a 
character key (e.g. a) results
+     * in the correct composed character (e.g. à) being committed, without the 
dead key
+     * being forwarded as a separate keysym or commit_string.
+     */
+    void testDeadKeySequence()
+    {
+        // Switch to the US intl with dead keys layout for the test.
+        setKeymap("us", "intl");
+
+        QSignalSpy commitStringSpy(m_inputMethod->context(), 
&InputMethodContext::commitStringChanged);
+        QSignalSpy keysymSpy(m_inputMethod->context(), 
&InputMethodContext::keysymReceived);
+
+        // Send the dead key sequence: ` → a = à
+        sendKey(KEY_GRAVE, 10);
+        sendKey(KEY_A, 10);
+
+        // Exactly one commit_string with the composed character should arrive.
+        QTRY_COMPARE(commitStringSpy.count(), 1);
+        QCOMPARE(commitStringSpy.first().first().toString(), 
QStringLiteral("à"));
+
+        // The dead key (`) must not have been forwarded via keysym.
+        // XKB_KEY_grave = 0x60
+        for (const QList<QVariant> &args : keysymSpy) {
+            const uint32_t sym = args.at(0).toUInt();
+            QVERIFY2(sym != 0x60, "The dead key (`) was incorrectly forwarded 
via keysym");
+        }
+
+        // Set the keymap back to the default to avoid affecting other tests.
+        setKeymap("us", nullptr);
+    }
+
     void cleanupTestCase()
     {
         if (m_child) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/po/hu/kcm_plasmakeyboard.po 
new/plasma-keyboard-6.7.1/po/hu/kcm_plasmakeyboard.po
--- old/plasma-keyboard-6.7.0/po/hu/kcm_plasmakeyboard.po       1970-01-01 
01:00:00.000000000 +0100
+++ new/plasma-keyboard-6.7.1/po/hu/kcm_plasmakeyboard.po       2026-06-23 
10:15:21.000000000 +0200
@@ -0,0 +1,121 @@
+# Copyright (C) 2026 This file is copyright:
+# This file is distributed under the same license as the plasma-keyboard 
package.
+#
+# SPDX-FileCopyrightText: 2026 Kristof Kiszel <[email protected]>
+msgid ""
+msgstr ""
+"Project-Id-Version: plasma-keyboard\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n";
+"POT-Creation-Date: 2026-03-14 00:46+0000\n"
+"PO-Revision-Date: 2026-06-19 22:06+0200\n"
+"Last-Translator: Kristof Kiszel <[email protected]>\n"
+"Language-Team: Hungarian <[email protected]>\n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 26.04.2\n"
+
+#: ui/LocaleSelectorListView.qml:68
+msgid "Filter languages…"
+msgstr "Nyelvek szűrése…"
+
+#: ui/LocaleSelectorListView.qml:69
+msgid "Filter languages"
+msgstr "Nyelvek szűrése"
+
+#: ui/LocaleSelectorListView.qml:82
+msgid ""
+"No languages selected. The default keyboard layout for the system will be "
+"used."
+msgstr ""
+"Nincs kiválasztva nyelv. A rendszer alapértelmezett billentyűzetkiosztása "
+"lesz használva."
+
+#: ui/LocaleSelectorSidebar.qml:25 ui/main_handset.qml:70
+#: ui/main_mediacenter.qml:40
+msgid "Languages"
+msgstr "Nyelvek"
+
+#: ui/main.qml:33
+msgid "Key press feedback:"
+msgstr "Gomblenyomás visszajelzése:"
+
+#: ui/main.qml:34 ui/main_handset.qml:40
+msgid "Sound"
+msgstr "Hang"
+
+#: ui/main.qml:45 ui/main_handset.qml:54
+msgid "Vibration"
+msgstr "Rezgés"
+
+#: ui/main.qml:56
+msgid "General:"
+msgstr "Általános:"
+
+#: ui/main.qml:57 ui/main_handset.qml:90
+msgid "Keyboard navigation"
+msgstr "Billentyűzetnavigáció"
+
+#: ui/main.qml:68 ui/main_handset.qml:104 ui/main_mediacenter.qml:91
+msgid "Auto-capitalization"
+msgstr "Automatikus nagybetű"
+
+#: ui/main.qml:79
+msgid "Alternate characters:"
+msgstr "Alternatív karakterek:"
+
+#: ui/main.qml:80
+msgid "Show popup when holding a key"
+msgstr "Felugró megjelenítése gomb nyomva tartásakor"
+
+#: ui/main.qml:91
+msgid "Hold delay:"
+msgstr "Késleltetés:"
+
+#: ui/main.qml:101
+msgid "milliseconds"
+msgstr "ezredmásodperc"
+
+#: ui/main_handset.qml:29
+msgid "Test the virtual keyboard…"
+msgstr "Virtuális billentyűzet kipróbálása…"
+
+#: ui/main_handset.qml:34
+msgctxt "@title:group"
+msgid "Feedback"
+msgstr "Visszajelzés"
+
+#: ui/main_handset.qml:41
+msgid "Whether to emit a sound on key press"
+msgstr "Adjon-e ki hangot billentyűlenyomáskor"
+
+#: ui/main_handset.qml:55
+msgid "Whether to vibrate on key press"
+msgstr "Rezegjen-e billentyűlenyomáskor"
+
+#: ui/main_handset.qml:76
+msgid "Keyboard Languages"
+msgstr "Billentyűzet nyelvei"
+
+#: ui/main_handset.qml:84
+msgctxt "@title:group"
+msgid "General"
+msgstr "Általános"
+
+#: ui/main_handset.qml:91
+msgid "Whether to use the arrow keys to navigate the keyboard"
+msgstr "Használja-e a nyílgombokat a billentyűzeten navigáláshoz"
+
+#: ui/main_handset.qml:105
+msgid "Automatically capitalize the first letter of sentences"
+msgstr "A mondatok első betűjét automatikusan nagybetűvé alakítja"
+
+#: ui/main_mediacenter.qml:47
+msgid "Key press feedback"
+msgstr "Gomblenyomás visszajelzése"
+
+#: ui/main_mediacenter.qml:82
+msgid "General"
+msgstr "Általános"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/po/ja/kcm_plasmakeyboard.po 
new/plasma-keyboard-6.7.1/po/ja/kcm_plasmakeyboard.po
--- old/plasma-keyboard-6.7.0/po/ja/kcm_plasmakeyboard.po       1970-01-01 
01:00:00.000000000 +0100
+++ new/plasma-keyboard-6.7.1/po/ja/kcm_plasmakeyboard.po       2026-06-23 
10:15:21.000000000 +0200
@@ -0,0 +1,120 @@
+# SPDX-FileCopyrightText: 2026 Mint <[email protected]>
+msgid ""
+msgstr ""
+"Project-Id-Version: plasma-keyboard\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n";
+"POT-Creation-Date: 2026-03-14 00:46+0000\n"
+"PO-Revision-Date: 2026-06-14 15:44+0900\n"
+"Last-Translator: Mint <[email protected]>\n"
+"Language-Team: Japanese <[email protected]>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+"X-Generator: Lokalize 26.04.2\n"
+
+#: ui/LocaleSelectorListView.qml:68
+msgid "Filter languages…"
+msgstr "言語を検索…"
+
+#: ui/LocaleSelectorListView.qml:69
+msgid "Filter languages"
+msgstr "言語の検索"
+
+#: ui/LocaleSelectorListView.qml:82
+msgid ""
+"No languages selected. The default keyboard layout for the system will be "
+"used."
+msgstr ""
+"言語が選択されていません。このシステム標準のキーボードレイアウトが使用されま"
+"す。"
+
+#: ui/LocaleSelectorSidebar.qml:25 ui/main_handset.qml:70
+#: ui/main_mediacenter.qml:40
+msgid "Languages"
+msgstr "言語"
+
+#: ui/main.qml:33
+msgid "Key press feedback:"
+msgstr "キー押下時の反応:"
+
+#: ui/main.qml:34 ui/main_handset.qml:40
+msgid "Sound"
+msgstr "サウンド"
+
+#: ui/main.qml:45 ui/main_handset.qml:54
+msgid "Vibration"
+msgstr "バイブレーション"
+
+#: ui/main.qml:56
+msgid "General:"
+msgstr "全般:"
+
+#: ui/main.qml:57 ui/main_handset.qml:90
+msgid "Keyboard navigation"
+msgstr "物理キーボードで操作"
+
+#: ui/main.qml:68 ui/main_handset.qml:104 ui/main_mediacenter.qml:91
+msgid "Auto-capitalization"
+msgstr "自動大文字変換"
+
+#: ui/main.qml:79
+msgid "Alternate characters:"
+msgstr "代替文字:"
+
+#: ui/main.qml:80
+msgid "Show popup when holding a key"
+msgstr "長押しでポップアップ表示"
+
+#: ui/main.qml:91
+msgid "Hold delay:"
+msgstr "長押しに必要な時間:"
+
+#: ui/main.qml:101
+msgid "milliseconds"
+msgstr "ミリ秒"
+
+#: ui/main_handset.qml:29
+msgid "Test the virtual keyboard…"
+msgstr "仮想キーボードのテスト…"
+
+#: ui/main_handset.qml:34
+msgctxt "@title:group"
+msgid "Feedback"
+msgstr "フィードバック"
+
+#: ui/main_handset.qml:41
+msgid "Whether to emit a sound on key press"
+msgstr "キー押下時にサウンドを再生するかどうか"
+
+#: ui/main_handset.qml:55
+msgid "Whether to vibrate on key press"
+msgstr "キー押下時にバイブレーションするかどうか"
+
+#: ui/main_handset.qml:76
+msgid "Keyboard Languages"
+msgstr "キーボードの言語"
+
+#: ui/main_handset.qml:84
+msgctxt "@title:group"
+msgid "General"
+msgstr "全般"
+
+#: ui/main_handset.qml:91
+msgid "Whether to use the arrow keys to navigate the keyboard"
+msgstr "キーボード内の操作に矢印キーを使用するかどうか"
+
+#: ui/main_handset.qml:105
+msgid "Automatically capitalize the first letter of sentences"
+msgstr "文章の最初の文字を自動で大文字にします"
+
+#: ui/main_mediacenter.qml:47
+msgid "Key press feedback"
+msgstr "キー押下時の反応"
+
+#: ui/main_mediacenter.qml:82
+msgid "General"
+msgstr "全般"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/src/CMakeLists.txt 
new/plasma-keyboard-6.7.1/src/CMakeLists.txt
--- old/plasma-keyboard-6.7.0/src/CMakeLists.txt        2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/CMakeLists.txt        2026-06-23 
10:15:21.000000000 +0200
@@ -106,6 +106,7 @@
     KF6::ConfigCore
     KF6::ConfigGui
     KF6::Crash
+    PkgConfig::XKBCommon
     Plasma::PlasmaQuick
     Qt::DBus
     Qt::Gui
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/plasma-keyboard-6.7.0/src/org.kde.plasma.keyboard.metainfo.xml 
new/plasma-keyboard-6.7.1/src/org.kde.plasma.keyboard.metainfo.xml
--- old/plasma-keyboard-6.7.0/src/org.kde.plasma.keyboard.metainfo.xml  
2026-06-11 11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/org.kde.plasma.keyboard.metainfo.xml  
2026-06-23 10:15:21.000000000 +0200
@@ -91,6 +91,7 @@
     <p xml:lang="fi">Plasma-näppäimistö tarjoaa virtuaalisen 
näyttönäppäimistön kosketusnäytöille, tableteille, muunnettaville laitteille, 
puhelimille ja näppäimistöttömille perinteisille tietokoneille.</p>
     <p xml:lang="fr">Plasma Keyboard fournit un clavier virtuel à l'écran pour 
les écrans tactiles, les tablettes, les ordinateurs convertibles, les 
téléphones et les ordinateurs traditionnels sans clavier physique.</p>
     <p xml:lang="he">מקלדת פלזמה מספקת מקלדת וירטואלית על גבי המסך למסכי מגע, 
מחשבי לוח, מכשירים גמישים, טלפונים ומחשבים מסורתיים בלי מקלדת פיזית.</p>
+    <p xml:lang="hu">A Plasma Billentyűzet egy virtuális képernyő-billentyűzet 
érintőképernyőkhöz, tabletekhez, hibrid eszközökhöz, telefonokhoz és fizikai 
billentyűzet nélküli, hagyományos számítógépekhez.</p>
     <p xml:lang="ia">Claviero de Plasma (Plasma Keyboard) forni un claviero 
virtual, sur chermo, per schermos tactile, tablettas, dispositivos 
convertibile, telephonos, e computatores traditional sin claviero physic.</p>
     <p xml:lang="is">Plasma-lyklaborðið birtir sýndarlyklaborð á skjanum fyrir 
snertiskjái, spjaldtölvur, umbreytanleg tæki, snjallsíma og venjulegar tölvur 
sem ekki eru með alvöru lyklaborð.</p>
     <p xml:lang="it">Plasma Keyboard fornisce una tastiera virtuale su schermo 
per touchscreen, tablet, dispositivi convertibili, telefoni e computer 
tradizionali privi di tastiera fisica.</p>
@@ -125,6 +126,7 @@
       <li xml:lang="fi">Saumaton eheytys Plasma-työtilan ja -sovellusten 
kanssa</li>
       <li xml:lang="fr">Intégration transparente avec l'espace de travail et 
les applications de Plasma</li>
       <li xml:lang="he">שילוב חלק בסביבת העבודה והיישומים של פלזמה</li>
+      <li xml:lang="hu">Zökkenőmentes integráció a Plasma munkaterülettel és 
az alkalmazásokkal</li>
       <li xml:lang="ia">Integration sin solution de continuitate con le spatio 
de labor e applicationes de Plasma</li>
       <li xml:lang="is">Hnökralaus samþætting við vinnusvæði og forrit í 
Plasma</li>
       <li xml:lang="it">Integrazione perfetta con l'area di lavoro e le 
applicazioni Plasma</li>
@@ -158,6 +160,7 @@
       <li xml:lang="fi">Automaattinen näyttäminen tekstisyötettä 
tarvittaessa</li>
       <li xml:lang="fr">Apparence automatique lorsque la saisie de texte est 
nécessaire</li>
       <li xml:lang="he">הופעה אוטומטית כשצריך להקליד טקסט</li>
+      <li xml:lang="hu">Automatikus megjelenés, amikor szövegbevitelre van 
szükség</li>
       <li xml:lang="ia">Apparentia automatic quando le ingresso de testo es 
necessari</li>
       <li xml:lang="is">Sjálfvirk birting þegar þörf er á að setja inn 
texta</li>
       <li xml:lang="it">Aspetto automatico quando è necessario l'inserimento 
di testo</li>
@@ -191,6 +194,7 @@
       <li xml:lang="fi">Useiden asettelujen ja kielten tuki</li>
       <li xml:lang="fr">Prise en charge de plusieurs dispositions et 
langues</li>
       <li xml:lang="he">תמיכה במגוון פריסות ושפות</li>
+      <li xml:lang="hu">Többféle kiosztás és nyelv támogatása</li>
       <li xml:lang="ia">Supporto per linguages e dispositiones multiple</li>
       <li xml:lang="is">Stuðningur við mörg tungumál og framsetningar</li>
       <li xml:lang="it">Supporto per più mappature e lingue</li>
@@ -224,6 +228,7 @@
       <li xml:lang="fi">Mukautettava koko ja toiminta eri alustoilla</li>
       <li xml:lang="fr">Taille et comportement configurables pour différents 
facteurs de forme</li>
       <li xml:lang="he">גודל והתנהגות מתכוונים למגוון גודלי תצוגה</li>
+      <li xml:lang="hu">Konfigurálható méret és működés különböző 
eszköztípusokhoz</li>
       <li xml:lang="ia">Grandor configurabile e comportamento per factores de 
forma differente</li>
       <li xml:lang="is">Stillanleg stærð og hegðun fyrir mismunandi 
skjástærðir</li>
       <li xml:lang="it">Dimensioni e comportamento configurabili per diversi 
fattori di forma</li>
@@ -263,6 +268,7 @@
     <binary>plasma-keyboard</binary>
   </provides>
   <releases>
+    <release version="6.7.1" date="2026-06-23"/>
     <release version="6.7.0" date="2026-06-16"/>
   </releases>
 </component>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/plasma-keyboard-6.7.0/src/overlay/longpresstrigger.cpp 
new/plasma-keyboard-6.7.1/src/overlay/longpresstrigger.cpp
--- old/plasma-keyboard-6.7.0/src/overlay/longpresstrigger.cpp  2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/overlay/longpresstrigger.cpp  2026-06-23 
10:15:21.000000000 +0200
@@ -60,17 +60,36 @@
             return result;
         }
 
-        // Request timer start for long-press detection.
-        // Consume the raw key event to prevent it from being forwarded via
-        // wl_keyboard, which would trigger client-side auto-repeat. Instead,
-        // the controller commits the base character immediately via
-        // commit_string (no repeat) and retracts it if the overlay opens.
-        m_timerStarted = true;
-        result.action = OverlayAction::StartTimer;
-        result.consumeEvent = true;
-        result.pendingText = keyEvent->text();
-        result.pendingNativeScanCode = keyEvent->nativeScanCode();
-        result.timerDurationMs = m_holdThresholdMs;
+        // Characters with diacritic candidates enter the long-press hold timer
+        // (consumed, blocking native auto-repeat). Printable characters 
without
+        // diacritics are consumed and committed via commit_string too, but 
skip
+        // the pending state so the controller's repeat-suppression check does
+        // not catch them.
+        const QChar baseChar = keyEvent->text().at(0).toLower();
+        if (m_diacriticsMap.contains(baseChar)) {
+            if (keyEvent->isAutoRepeat()) {
+                // Diacritic auto-repeat: let the controller's pending-key 
check
+                // suppress it; don't consume here, so the event falls through.
+                return result;
+            }
+            m_timerStarted = true;
+            result.action = OverlayAction::StartTimer;
+            result.consumeEvent = true;
+            result.pendingText = keyEvent->text();
+            result.pendingNativeScanCode = keyEvent->nativeScanCode();
+            result.timerDurationMs = m_holdThresholdMs;
+        } else {
+            // Printable character without diacritics: consume and commit via
+            // commit_string for ordering consistency. Since we are accepting 
the key
+            // event, ask the controller to synthesise repeats with its own 
internal
+            // timer to retain native key repeat behavior.
+            result.action = OverlayAction::ConsumeEvent;
+            result.consumeEvent = true;
+            result.commitText = keyEvent->text();
+            result.enableRepeat = true;
+            result.repeatScanCode = keyEvent->nativeScanCode();
+            result.pendingNativeScanCode = keyEvent->nativeScanCode();
+        }
 
         // qCDebug(PlasmaKeyboard) << "LongPressTrigger: Requesting timer for" 
<< text << "duration" << m_holdThresholdMs << "ms";
         break;
@@ -160,10 +179,6 @@
         return false;
     }
 
-    if (event->isAutoRepeat()) {
-        return false;
-    }
-
     // Only handle simple textual keys without control/meta modifiers
     const Qt::KeyboardModifiers mods = event->modifiers();
     const bool modifierAllowed = mods == Qt::NoModifier || mods == 
Qt::ShiftModifier;
@@ -171,7 +186,11 @@
         return false;
     }
 
-    // Check if we have diacritics for this character
+    // Intercept all printable characters so they are consistently committed 
via
+    // commit_string, avoiding ordering issues between commit and key event 
paths
+    // (e.g. when a password manager injects key events, if they arrive via 
multiple
+    // pathways the ordering could be inconsistent). See:
+    // https://invent.kde.org/plasma/plasma-keyboard/-/merge_requests/131
     const QChar baseChar = event->text().at(0).toLower();
     return baseChar.isPrint();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/plasma-keyboard-6.7.0/src/overlay/overlaycontroller.cpp 
new/plasma-keyboard-6.7.1/src/overlay/overlaycontroller.cpp
--- old/plasma-keyboard-6.7.0/src/overlay/overlaycontroller.cpp 2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/overlay/overlaycontroller.cpp 2026-06-23 
10:15:21.000000000 +0200
@@ -10,18 +10,6 @@
 #include "logging.h"
 #include "overlaytrigger.h"
 
-/**
- * Returns true if @p key is in the XKB dead-key range
- * (Qt::Key_Dead_Grave through Qt::Key_Dead_Longsolidusoverlay).
- *
- * Dead keys do not produce text themselves; they modify the next key press
- * to produce a combined character (e.g. dead_acute + e → é).
- */
-static bool isDeadKey(int key)
-{
-    return key >= Qt::Key_Dead_Grave && key <= Qt::Key_Dead_Longsolidusoverlay;
-}
-
 OverlayController::OverlayController(InputPlugin *inputPlugin, QObject *parent)
     : QObject(parent)
     , m_inputPlugin(inputPlugin)
@@ -30,6 +18,12 @@
     m_holdTimer.setSingleShot(true);
     connect(&m_holdTimer, &QTimer::timeout, this, 
&OverlayController::handleTimerExpired);
 
+    m_repeatTimer.setSingleShot(true);
+    connect(&m_repeatTimer, &QTimer::timeout, this, 
&OverlayController::handleRepeatTimer);
+
+    m_overlayGraceTimer.setSingleShot(true);
+    connect(&m_overlayGraceTimer, &QTimer::timeout, this, 
&OverlayController::handleOverlayGraceTimer);
+
     // The settle timer is a single-shot guard that absorbs extra 
surrounding_text
     // echoes from clients that send more than one event per commit_string.
     // 100 ms is well above any realistic Wayland roundtrip but well below the
@@ -37,10 +31,29 @@
     static constexpr int SURROUNDING_TEXT_SETTLE_DELAY_MS = 100;
     m_surroundingTextSettleTimer.setSingleShot(true);
     m_surroundingTextSettleTimer.setInterval(SURROUNDING_TEXT_SETTLE_DELAY_MS);
+
+    // Initialize XKB compose state machine using the system locale.
+    m_xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+    if (m_xkbContext) {
+        const char *locale = setlocale(LC_CTYPE, nullptr);
+        if (!locale || locale[0] == '\0') {
+            locale = "C";
+        }
+        m_xkbComposeTable = xkb_compose_table_new_from_locale(m_xkbContext, 
locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
+        if (m_xkbComposeTable) {
+            m_xkbComposeState = xkb_compose_state_new(m_xkbComposeTable, 
XKB_COMPOSE_STATE_NO_FLAGS);
+        }
+    }
 }
 
 OverlayController::~OverlayController()
 {
+    if (m_xkbComposeState)
+        xkb_compose_state_unref(m_xkbComposeState);
+    if (m_xkbComposeTable)
+        xkb_compose_table_unref(m_xkbComposeTable);
+    if (m_xkbContext)
+        xkb_context_unref(m_xkbContext);
 }
 
 void OverlayController::registerTrigger(OverlayTrigger *trigger)
@@ -74,7 +87,10 @@
     // Compare by native scan code (physical key) rather than Qt key code, 
because
     // the Qt key code can change if the modifier is released before the 
repeat fires
     // (e.g. Shift+/ produces Key_Question on press but Key_Slash on repeat).
-    if (event->isAutoRepeat() && event->nativeScanCode() == 
m_pendingNativeScanCode) {
+    //
+    // Suppress auto-repeat key events for the pending key (diacritic 
long-press)
+    // or for a key being repeated by our internal timer (non-diacritic 
ConsumeEvent).
+    if (event->isAutoRepeat() && (event->nativeScanCode() == 
m_pendingNativeScanCode || event->nativeScanCode() == m_repeatNativeScanCode)) {
         // qCDebug(PlasmaKeyboard) << "Suppressing repeat press of pending 
overlay key" << m_pendingText;
         return true;
     }
@@ -115,28 +131,47 @@
         // Fall through to process the new key
     }
 
-    // Handle Compose (Multi_key) to enter compose mode.
-    if (event->key() == Qt::Key_Multi_key) {
-        qCDebug(PlasmaKeyboard) << "Compose key pressed; entering compose 
mode";
-        m_composeActive = true;
-        return false;
-    }
-
-    if (m_composeActive) {
-        qCDebug(PlasmaKeyboard) << "Compose sequence in progress; passing key 
through:" << event->key();
-        return false;
-    }
-
-    // Detect dead key press and enter dead key bypass mode.
-    if (isDeadKey(event->key())) {
-        qCDebug(PlasmaKeyboard) << "Dead key detected; entering dead key 
bypass mode (key =" << event->key() << ")";
-        m_deadKeyActive = true;
-        return false;
-    }
-
-    if (m_deadKeyActive) {
-        qCDebug(PlasmaKeyboard) << "Dead key sequence in progress; passing key 
through. (key =" << event->key() << ")";
-        return false;
+    // XKB compose state machine — handles Multi_key sequences and dead keys.
+    // Keys that are part of a sequence are consumed here; the composed result
+    // is committed via commit_string so it never reaches the trigger pipeline.
+    if (m_xkbComposeState) {
+        const xkb_keysym_t keysym = 
static_cast<xkb_keysym_t>(event->nativeVirtualKey());
+        if (keysym != XKB_KEY_NoSymbol) {
+            const xkb_compose_feed_result feedResult = 
xkb_compose_state_feed(m_xkbComposeState, keysym);
+            if (feedResult == XKB_COMPOSE_FEED_ACCEPTED) {
+                const xkb_compose_status status = 
xkb_compose_state_get_status(m_xkbComposeState);
+                switch (status) {
+                case XKB_COMPOSE_COMPOSING:
+                    // Sequence started or continuing — cancel any pending 
overlay
+                    // (it belongs to a key typed before the sequence began).
+                    if (m_holdTimer.isActive() || m_overlayVisible) {
+                        cancelOverlay();
+                    }
+                    return true; // Consume; do not forward to compositor.
+                case XKB_COMPOSE_COMPOSED: {
+                    if (m_holdTimer.isActive() || m_overlayVisible) {
+                        cancelOverlay();
+                    }
+                    char buf[64] = {};
+                    if (xkb_compose_state_get_utf8(m_xkbComposeState, buf, 
sizeof(buf)) > 0 && m_inputPlugin) {
+                        ++m_pendingSurroundingTextUpdates;
+                        m_surroundingTextSettleTimer.start();
+                        m_inputPlugin->commit(QString::fromUtf8(buf));
+                    }
+                    xkb_compose_state_reset(m_xkbComposeState);
+                    return true; // Consume the completing key.
+                }
+                case XKB_COMPOSE_CANCELLED:
+                    xkb_compose_state_reset(m_xkbComposeState);
+                    break; // Fall through — process cancelling key normally.
+                case XKB_COMPOSE_NOTHING:
+                    break; // Not in a sequence; fall through.
+                }
+            } else {
+                // qCDebug(PlasmaKeyboard) << "XKB compose feed result:" << 
feedResult << "(keysym" << keysym << "not part of a compose sequence)";
+            }
+            // XKB_COMPOSE_FEED_IGNORED or post-cancel: fall through to 
triggers.
+        }
     }
 
     // Dispatch to triggers in order
@@ -161,6 +196,22 @@
         return false;
     }
 
+    // If the overlay grace timer is running and the held key is released,
+    // stop the grace timer — the overlay stays visible waiting for selection
+    // or cancellation via the normal pathways.
+    if (m_overlayGraceTimer.isActive() && event->nativeScanCode() == 
m_pendingNativeScanCode) {
+        m_overlayGraceTimer.stop();
+    }
+
+    // Check for key release that should stop the internal repeat timer.
+    // This must run before the swallow-release and pending-key checks since
+    // it may share the same scan code.
+    if (m_repeatNativeScanCode != 0 && event->nativeScanCode() == 
m_repeatNativeScanCode) {
+        m_repeatTimer.stop();
+        m_repeatText.clear();
+        m_repeatNativeScanCode = 0;
+    }
+
     // Swallow release of a discarded/committed pending key.
     // Compare by native scan code (physical key) so that modifier changes
     // between press and release don't prevent the match.
@@ -369,23 +420,6 @@
         qCDebug(PlasmaKeyboard) << "External cursor move detected while 
overlay active; cancelling overlay";
         cancelOverlay();
     }
-
-    // If a Compose (Multi_key) sequence was in progress, an external 
surrounding-text
-    // update signals that the compositor has processed and committed the 
result of a
-    // compose sequence (or that the user typed normally while compose mode 
was stale).
-    // Either way the compose state is done.
-    if (m_composeActive) {
-        qCDebug(PlasmaKeyboard) << "Compose sequence ended (external 
surrounding-text change); clearing compose state";
-        m_composeActive = false;
-    }
-
-    // If a dead key sequence was in progress, the surrounding-text update 
means the
-    // compositor has committed the composed result (or the original dead key 
character).
-    // Either way, dead key mode is over.
-    if (m_deadKeyActive) {
-        qCDebug(PlasmaKeyboard) << "Dead key sequence ended (surrounding-text 
change)";
-        m_deadKeyActive = false;
-    }
 }
 
 void OverlayController::openOverlay(const QString &triggerId, const QString 
&baseText, const QStringList &candidates)
@@ -409,6 +443,16 @@
     Q_EMIT activeTriggerIdChanged();
     Q_EMIT pendingTextChanged();
     Q_EMIT overlayRequested(triggerId, baseText);
+
+    // Start grace timer for diacritics long-press overlays: if the user keeps
+    // holding the key after the overlay opens, after a grace period the 
overlay
+    // closes and the base character starts auto-repeating.
+    //
+    // Only start if there is a physically held pending key (not for 
emoji/text-
+    // expansion overlays which don't use the hold timer pathway).
+    if (!m_pendingText.isEmpty() && m_pendingTrigger && !m_pendingKeyReleased) 
{
+        m_overlayGraceTimer.start(1000); // 1000 ms grace period after overlay 
opens
+    }
 }
 
 void OverlayController::handleTimerExpired()
@@ -500,18 +544,86 @@
         }
         break;
     case OverlayAction::ConsumeEvent:
-        // Event consumed but no visible action
+        // Commit the base character via commit_string for ordering 
consistency, even
+        // if the key is not a diacritic candidate.
+        if (!result.commitText.isEmpty() && m_inputPlugin) {
+            ++m_pendingSurroundingTextUpdates;
+            m_surroundingTextSettleTimer.start();
+            m_inputPlugin->commit(result.commitText);
+        }
+        // If the trigger requested a pending scan code, mark it for 
swallowing on release.
+        if (result.consumeEvent && result.pendingNativeScanCode != 0) {
+            m_ignoreReleaseNativeScanCode = result.pendingNativeScanCode;
+            m_swallowNextRelease = true;
+        }
+        // Start internal repeat timer for consumed non-diacritic keys so they
+        // retain auto-repeat even though the raw key events are consumed and 
don't reach the client.
+        if (result.enableRepeat && result.repeatScanCode != 0) {
+            m_repeatText = result.commitText;
+            m_repeatNativeScanCode = result.repeatScanCode;
+            // Initial delay before first repeat (matches typical XKB repeat 
delay)
+            m_repeatTimer.start(500);
+        }
         break;
     case OverlayAction::None:
         break;
     }
 }
 
+void OverlayController::handleRepeatTimer()
+{
+    if (m_repeatText.isEmpty() || !m_inputPlugin) {
+        return;
+    }
+
+    // First tick is the initial repeat delay; switch to the shorter rate.
+    if (m_repeatTimer.interval() > 100) {
+        m_repeatTimer.setInterval(33); // ~30 Hz
+    }
+
+    ++m_pendingSurroundingTextUpdates;
+    m_surroundingTextSettleTimer.start();
+    m_inputPlugin->commit(m_repeatText);
+
+    // The timer is single-shot; restart it for the next tick.
+    m_repeatTimer.start();
+}
+
+void OverlayController::handleOverlayGraceTimer()
+{
+    // If the key was already released while the overlay was visible, don't
+    // start repeating — the overlay is still up waiting for selection.
+    if (m_pendingKeyReleased || m_pendingText.isEmpty()) {
+        return;
+    }
+
+    // Close the overlay.
+    if (m_overlayVisible) {
+        m_overlayVisible = false;
+        Q_EMIT overlayVisibleChanged();
+        Q_EMIT overlayClosed();
+    }
+
+    // Start the internal repeat timer with the base character.
+    m_repeatText = m_pendingText;
+    m_repeatNativeScanCode = m_pendingNativeScanCode;
+    m_repeatTimer.start(500);
+
+    // The raw key press was consumed, so the eventual release must be 
swallowed.
+    m_ignoreReleaseNativeScanCode = m_pendingNativeScanCode;
+    m_swallowNextRelease = true;
+}
+
 void OverlayController::resetState()
 {
     if (m_holdTimer.isActive()) {
         m_holdTimer.stop();
     }
+    m_repeatTimer.stop();
+    m_repeatText.clear();
+    m_repeatNativeScanCode = 0;
+    m_overlayGraceTimer.stop();
+    m_overlayGraceTimer.stop();
 
     const bool wasVisible = m_overlayVisible;
     const bool hadPending = !m_pendingText.isEmpty();
@@ -526,8 +638,9 @@
     m_candidateModel->clear();
     m_pendingSurroundingTextUpdates = 0;
     m_surroundingTextSettleTimer.stop();
-    m_composeActive = false;
-    m_deadKeyActive = false;
+    if (m_xkbComposeState) {
+        xkb_compose_state_reset(m_xkbComposeState);
+    }
 
     if (wasVisible) {
         Q_EMIT overlayVisibleChanged();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/plasma-keyboard-6.7.0/src/overlay/overlaycontroller.h 
new/plasma-keyboard-6.7.1/src/overlay/overlaycontroller.h
--- old/plasma-keyboard-6.7.0/src/overlay/overlaycontroller.h   2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/overlay/overlaycontroller.h   2026-06-23 
10:15:21.000000000 +0200
@@ -14,6 +14,8 @@
 #include <QTimer>
 #include <qqmlintegration.h>
 
+#include <xkbcommon/xkbcommon-compose.h>
+
 class InputPlugin;
 
 /**
@@ -187,6 +189,8 @@
 
 private Q_SLOTS:
     void handleTimerExpired();
+    void handleRepeatTimer();
+    void handleOverlayGraceTimer();
 
 private:
     void executeAction(const OverlayTriggerResult &result, OverlayTrigger 
*trigger);
@@ -197,6 +201,8 @@
     CandidateModel *m_candidateModel = nullptr;
 
     QTimer m_holdTimer;
+    QTimer m_repeatTimer;
+    QTimer m_overlayGraceTimer;
     bool m_overlayVisible = false;
     QString m_activeTriggerId;
     QString m_pendingText;
@@ -212,31 +218,19 @@
      */
     bool m_pendingKeyReleased = false;
 
+    /** The trigger that is currently timing (for long-press). */
+    OverlayTrigger *m_pendingTrigger = nullptr;
+
     /**
-     * Set to true when a Compose (Multi_key) key press is detected.
-     *
-     * While true, all key events bypass the overlay trigger pipeline and are 
forwarded
-     * directly to the compositor so it can complete the compose sequence
-     * (e.g. Multi_key + t + m → ™). The flag is cleared once an external 
surrounding-text
-     * change arrives (indicating the composed character was committed) or 
when the context
-     * is reset.
+     * Text being repeated by the internal timer for a consumed key. Empty 
when no repeat
+     * is active.
      */
-    bool m_composeActive = false;
+    QString m_repeatText;
 
     /**
-     * Set to true when a dead key press (Qt::Key_Dead_Grave … 
Qt::Key_Dead_Longsolidusoverlay)
-     * is detected.
-     *
-     * While true, the next non-dead-key press bypasses all overlay triggers 
and is
-     * forwarded directly to the compositor so the XKB compose state can 
combine the
-     * dead key with the follow-up key (e.g. dead_acute + e → é).  The flag is 
cleared
-     * after forwarding that one follow-up key, or when the context is reset 
(e.g. an
-     * external surrounding-text change).
+     * Native scan code of the key currently being repeated. 0 when idle.
      */
-    bool m_deadKeyActive = false;
-
-    /** The trigger that is currently timing (for long-press). */
-    OverlayTrigger *m_pendingTrigger = nullptr;
+    quint32 m_repeatNativeScanCode = 0;
 
     /**
      * Number of compositor surrounding-text echo events the controller is 
still
@@ -275,4 +269,23 @@
      *     the 200 ms long-press threshold)
      */
     QTimer m_surroundingTextSettleTimer;
+
+    /**
+     * XKB compose state machine for handling client-side compose sequences 
(e.g.
+     * Multi_key + t + m → ™). The controller processes compose sequences 
locally so that
+     * the intermediate keys (e.g. Multi_key, t) can be consumed and not 
forwarded to the
+     * client, while only the final composed result (e.g. ™) is sent via 
commit_string.
+     */
+    xkb_context *m_xkbContext = nullptr;
+
+    /**
+     * XKB compose table compiled from the system locale, used to initialize 
the compose state.
+     */
+    xkb_compose_table *m_xkbComposeTable = nullptr;
+
+    /**
+     * XKB compose state initialized from the compose table, used to track the 
current
+     * compose sequence and produce the final composed result.
+     */
+    xkb_compose_state *m_xkbComposeState = nullptr;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/src/overlay/overlaytrigger.h 
new/plasma-keyboard-6.7.1/src/overlay/overlaytrigger.h
--- old/plasma-keyboard-6.7.0/src/overlay/overlaytrigger.h      2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/overlay/overlaytrigger.h      2026-06-23 
10:15:21.000000000 +0200
@@ -78,6 +78,25 @@
 
     /** For StartTimer: the pending text to be committed or shown in overlay. 
*/
     QString pendingText;
+
+    /**
+     * For ConsumeEvent: whether to enable an internal repeat timer for this 
key.
+     *
+     * The compositor does not send auto-repeat events (state=2) to the input
+     * method grab when the initial press is consumed, so keys that go through
+     * the commit_string path lose native repeat. Set this to true for 
printable
+     * characters that should auto-repeat when held.
+     */
+    bool enableRepeat = false;
+
+    /**
+     * For ConsumeEvent: native scan code used to match the key release that
+     * should stop the repeat timer.
+     *
+     * Same as pendingNativeScanCode but for the controller's internal repeat
+     * timer rather than the long-press hold timer.
+     */
+    quint32 repeatScanCode = 0;
 };
 
 /**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plasma-keyboard-6.7.0/src/qml/DiacriticsOverlay.qml 
new/plasma-keyboard-6.7.1/src/qml/DiacriticsOverlay.qml
--- old/plasma-keyboard-6.7.0/src/qml/DiacriticsOverlay.qml     2026-06-11 
11:36:13.000000000 +0200
+++ new/plasma-keyboard-6.7.1/src/qml/DiacriticsOverlay.qml     2026-06-23 
10:15:21.000000000 +0200
@@ -71,7 +71,6 @@
         case Qt.Key_Return:
             if (root.selectedIndex >= 0 && root.selectedIndex < 
root.options.length) {
                 root.characterSelected(root.options[root.selectedIndex]);
-                root.close();
             } else {
                 // If no option is selected, close the overlay without 
selecting a character
                 root.close();
@@ -120,7 +119,6 @@
 
                     onClicked: {
                         root.characterSelected(delegate.modelData)
-                        root.close()
                     }
 
                     contentItem: Column {

Reply via email to