feat(osd): add keyboard layout OSD (#4034)

port 2.0
This commit is contained in:
Huỳnh Thiện Lộc authored and GitHub committed 2026-10-30 12:50:44 -04:00
1 parent 7060c8eeb7
commit 16fc39cc16
9 files changed
+129 -2

No files matched your search

+1
View File
@@ -1132,6 +1132,7 @@ Singleton {
property bool osdMicMuteEnabled: Spec.SPEC.osdMicMuteEnabled.def
property bool osdMicVolumeEnabled: Spec.SPEC.osdMicVolumeEnabled.def
property bool osdCapsLockEnabled: Spec.SPEC.osdCapsLockEnabled.def
property bool osdKeyboardLayoutEnabled: Spec.SPEC.osdKeyboardLayoutEnabled.def
property bool osdTouchpadEnabled: Spec.SPEC.osdTouchpadEnabled.def
property bool osdPowerProfileEnabled: Spec.SPEC.osdPowerProfileEnabled.def
property bool osdAudioOutputEnabled: Spec.SPEC.osdAudioOutputEnabled.def
@@ -1478,6 +1478,9 @@ var LOCAL_SPEC = {
osdCapsLockEnabled: {
def: true
},
osdKeyboardLayoutEnabled: {
def: false
},
osdTouchpadEnabled: {
def: true
},
+6
View File
@@ -1315,6 +1315,12 @@ Item {
delegate: CapsLockOSD {}
}
Variants {
model: (SettingsData.osdKeyboardLayoutEnabled && KeyboardLayoutService.available) ? SettingsData.getFilteredScreens("osd") : []
delegate: KeyboardLayoutOSD {}
}
Variants {
model: (SettingsData.osdTouchpadEnabled && CompositorService.isNiri) ? root.legacySystemLevelOsdScreens : []
@@ -1,6 +1,8 @@
.pragma library
.import "../../../DCommon/Common/LayoutCodes.js" as LayoutCodes
var VALID_VARIANTS = ["US", "UK", "GB", "AZERTY", "QWERTY", "Dvorak", "Colemak", "Mac", "Intl", "International"];
// Overrides are keyed by whatever string would otherwise be displayed, so the same
// map applies after any compositor-specific shortening (compact vs. vertical mode).
function applyOverride(label, overrides) {
@@ -12,7 +12,7 @@ BasePill {
property bool compactMode: SettingsData.widgetOption("keyboard_layout_name", widgetData, "keyboardLayoutNameCompactMode")
property bool showIcon: SettingsData.widgetOption("keyboard_layout_name", widgetData, "keyboardLayoutNameShowIcon")
readonly property var labelOverrides: SettingsData.widgetOption("keyboard_layout_name", widgetData, "keyboardLayoutNameLabelOverrides") ?? ({})
readonly property var validVariants: ["US", "UK", "GB", "AZERTY", "QWERTY", "Dvorak", "Colemak", "Mac", "Intl", "International"]
readonly property var validVariants: KeyboardLayoutLabels.VALID_VARIANTS
readonly property bool codesOnly: KeyboardLayoutService.namesAreXkbCodes
readonly property string currentLayout: compactMode ? KeyboardLayoutService.compactLayout : KeyboardLayoutService.currentLayout
readonly property var _allLayoutLabels: (compactMode || !codesOnly ? KeyboardLayoutService.layoutNames : []).map(n => displayLabel(n))
@@ -0,0 +1,87 @@
import QtQuick
import QtQuick.Layouts
import qs.Common
import qs.Services
import qs.DCommon.Widgets
import qs.Widgets
DOSD {
id: root
osdKind: "keyboardLayout"
property string lastLayout: ""
property bool layoutInitialized: false
readonly property string currentLayout: KeyboardLayoutService.currentLayout
readonly property string layoutLabel: currentLayout
readonly property real horizontalPadding: Theme.spacingL
readonly property real itemSpacing: Theme.spacingM
readonly property real labelWidth: Math.ceil(labelMetrics.width)
osdWidth: Math.min(screenWidth - Theme.spacingM * 2, Math.max(180, horizontalPadding * 2 + Theme.buttonHeightS + itemSpacing + labelWidth + Theme.spacingM * 2))
osdHeight: Theme.osdHeight
autoHideInterval: 2000
enableMouseInteraction: false
function observeLayout() {
if (!KeyboardLayoutService.layoutKnown) {
layoutInitialized = false;
lastLayout = "";
return;
}
if (!layoutInitialized) {
lastLayout = currentLayout;
layoutInitialized = true;
return;
}
if (lastLayout === currentLayout)
return;
lastLayout = currentLayout;
if (SettingsData.osdKeyboardLayoutEnabled)
show();
}
onCurrentLayoutChanged: observeLayout()
Component.onCompleted: {
KeyboardLayoutService.consumers++;
observeLayout();
}
Component.onDestruction: KeyboardLayoutService.consumers--
StyledTextMetrics {
id: labelMetrics
font.pixelSize: Theme.fontSizeMedium
font.weight: Theme.fontWeightMedium
text: root.layoutLabel
}
content: Item {
anchors.fill: parent
RowLayout {
anchors {
fill: parent
leftMargin: root.horizontalPadding
rightMargin: root.horizontalPadding
}
spacing: root.itemSpacing
OsdIcon {
Layout.alignment: Qt.AlignVCenter
iconName: "keyboard"
}
StyledText {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
text: root.layoutLabel
font.pixelSize: Theme.fontSizeMedium
font.weight: Theme.fontWeightMedium
color: Theme.surfaceText
wrapMode: Text.NoWrap
elide: Text.ElideRight
}
}
}
}
+13
View File
@@ -49,6 +49,11 @@ Item {
"label": I18n.tr("Caps lock"),
"shown": SettingsData.osdCapsLockEnabled
},
{
"value": "keyboardLayout",
"label": I18n.tr("Keyboard layout"),
"shown": SettingsData.osdKeyboardLayoutEnabled && KeyboardLayoutService.available
},
{
"value": "touchpad",
"label": I18n.tr("Touchpad"),
@@ -190,6 +195,14 @@ Item {
onToggled: checked => SettingsData.set("osdCapsLockEnabled", checked)
}
SettingsToggleRow {
settingKey: "osdKeyboardLayoutEnabled"
visible: KeyboardLayoutService.available
text: I18n.tr("Keyboard layout")
checked: SettingsData.osdKeyboardLayoutEnabled
onToggled: checked => SettingsData.set("osdKeyboardLayoutEnabled", checked)
}
SettingsToggleRow {
settingKey: "osdTouchpadEnabled"
visible: CompositorService.isNiri
@@ -5,7 +5,7 @@ import "../../Modules/DBar/Widgets/KeyboardLayoutLabels.js" as KeyboardLayoutLab
TestCase {
name: "KeyboardLayoutLabels"
readonly property var validVariants: ["US", "UK", "GB", "AZERTY", "QWERTY", "Dvorak", "Colemak", "Mac", "Intl", "International"]
readonly property var validVariants: KeyboardLayoutLabels.VALID_VARIANTS
function test_overrideReplacesRawHyprlandCompactLabel() {
compare(KeyboardLayoutLabels.displayLabel("am-phonetic-alt", true, true, validVariants, {
@@ -8907,6 +8907,21 @@
"timeout"
]
},
{
"section": "osdKeyboardLayoutEnabled",
"label": "Keyboard layout",
"tabIndex": 18,
"category": "On-screen displays",
"keywords": [
"displays",
"indicator",
"keyboard",
"layout",
"osd",
"popup",
"screen"
]
},
{
"section": "osdMediaPlaybackEnabled",
"label": "Media playback",