mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-08 06:28:27 -04:00
feat(settings): add keyboard configuration tab for Niri (#2937)
* feat(settings): add dedicated keyboard configuration tab * chore(settings): configure default keyboard settings and clean up embedded niri config * settings/keyboard: emit niri keyboard config only when set, dedup setup banner, index tab --------- Co-authored-by: bbedward <bbedward@gmail.com>
This commit is contained in:
@@ -203,6 +203,16 @@ Singleton {
|
||||
property bool touchpadTapAndDrag: true
|
||||
property bool touchpadTapToClick: true
|
||||
|
||||
property string keyboardLayouts: ""
|
||||
property string keyboardVariants: ""
|
||||
property string keyboardModel: ""
|
||||
property string keyboardOptions: ""
|
||||
property string keyboardKeymapFile: ""
|
||||
property string keyboardTrackLayout: ""
|
||||
property int keyboardRepeatDelay: 0
|
||||
property int keyboardRepeatRate: 0
|
||||
property bool keyboardNumlock: false
|
||||
|
||||
property int firstDayOfWeek: -1
|
||||
property bool showWeekNumber: false
|
||||
property string calendarBackend: "auto"
|
||||
|
||||
@@ -57,6 +57,16 @@ var SPEC = {
|
||||
touchpadTapAndDrag: { def: true, onChange: "updateCompositorInput" },
|
||||
touchpadTapToClick: { def: true, onChange: "updateCompositorInput" },
|
||||
|
||||
keyboardLayouts: { def: "", onChange: "updateCompositorInput" },
|
||||
keyboardVariants: { def: "", onChange: "updateCompositorInput" },
|
||||
keyboardModel: { def: "", onChange: "updateCompositorInput" },
|
||||
keyboardOptions: { def: "", onChange: "updateCompositorInput" },
|
||||
keyboardKeymapFile: { def: "", onChange: "updateCompositorInput" },
|
||||
keyboardTrackLayout: { def: "", onChange: "updateCompositorInput" },
|
||||
keyboardRepeatDelay: { def: 0, onChange: "updateCompositorInput" },
|
||||
keyboardRepeatRate: { def: 0, onChange: "updateCompositorInput" },
|
||||
keyboardNumlock: { def: false, onChange: "updateCompositorInput" },
|
||||
|
||||
firstDayOfWeek: { def: -1 },
|
||||
showWeekNumber: { def: false },
|
||||
calendarBackend: { def: "auto" },
|
||||
|
||||
@@ -733,5 +733,20 @@ FocusScope {
|
||||
Qt.callLater(() => item.forceActiveFocus());
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: keyboardLoader
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 45
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
sourceComponent: KeyboardTab {}
|
||||
|
||||
onActiveChanged: {
|
||||
if (active && item)
|
||||
Qt.callLater(() => item.forceActiveFocus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +326,13 @@ Rectangle {
|
||||
"tabIndex": 44,
|
||||
"niriOnly": true
|
||||
},
|
||||
{
|
||||
"id": "keyboard",
|
||||
"text": I18n.tr("Keyboard"),
|
||||
"icon": "keyboard",
|
||||
"tabIndex": 45,
|
||||
"niriOnly": true
|
||||
},
|
||||
{
|
||||
"id": "locale",
|
||||
"text": I18n.tr("Locale"),
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Settings.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
LayoutMirroring.enabled: I18n.isRtl
|
||||
LayoutMirroring.childrenInherit: true
|
||||
|
||||
DankFlickable {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
contentHeight: settingsColumn.height + Theme.spacingXL
|
||||
contentWidth: width
|
||||
|
||||
Column {
|
||||
id: settingsColumn
|
||||
|
||||
topPadding: 4
|
||||
width: Math.min(550, parent.width - Theme.spacingL * 2)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
NiriInputSetupBanner {
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
SettingsCard {
|
||||
width: parent.width
|
||||
tags: ["keyboard", "layout", "language", "input", "xkb"]
|
||||
title: I18n.tr("Keyboard Layouts")
|
||||
settingKey: "keyboardLayoutsSettings"
|
||||
iconName: "keyboard"
|
||||
|
||||
Column {
|
||||
width: parent?.width ?? 0
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Keyboard Layouts")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Comma-separated list of layout names. Leave empty to use the system keyboard settings.")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
text: SettingsData.keyboardLayouts
|
||||
placeholderText: "us,de"
|
||||
onTextEdited: SettingsData.set("keyboardLayouts", text)
|
||||
}
|
||||
}
|
||||
|
||||
SettingsDropdownRow {
|
||||
tags: ["keyboard", "layout", "switch", "shortcut", "xkb"]
|
||||
settingKey: "keyboardOptions"
|
||||
text: I18n.tr("Switch Layout Shortcut")
|
||||
description: I18n.tr("Choose a shortcut key to cycle between keyboard layouts")
|
||||
options: [I18n.tr("Alt + Shift"), I18n.tr("Ctrl + Shift"), I18n.tr("Caps Lock"), I18n.tr("Super + Space"), I18n.tr("Custom / None")]
|
||||
currentValue: {
|
||||
const opt = SettingsData.keyboardOptions;
|
||||
if (opt.includes("grp:alt_shift_toggle"))
|
||||
return options[0];
|
||||
if (opt.includes("grp:ctrl_shift_toggle"))
|
||||
return options[1];
|
||||
if (opt.includes("grp:caps_toggle"))
|
||||
return options[2];
|
||||
if (opt.includes("grp:win_space_toggle"))
|
||||
return options[3];
|
||||
return options[4];
|
||||
}
|
||||
onValueChanged: value => {
|
||||
const idx = options.indexOf(value);
|
||||
let opt = SettingsData.keyboardOptions.split(",").filter(o => !o.startsWith("grp:")).join(",");
|
||||
|
||||
let newGrp = "";
|
||||
switch (idx) {
|
||||
case 0:
|
||||
newGrp = "grp:alt_shift_toggle";
|
||||
break;
|
||||
case 1:
|
||||
newGrp = "grp:ctrl_shift_toggle";
|
||||
break;
|
||||
case 2:
|
||||
newGrp = "grp:caps_toggle";
|
||||
break;
|
||||
case 3:
|
||||
newGrp = "grp:win_space_toggle";
|
||||
break;
|
||||
}
|
||||
|
||||
if (newGrp)
|
||||
opt = opt ? opt + "," + newGrp : newGrp;
|
||||
SettingsData.set("keyboardOptions", opt);
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent?.width ?? 0
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("XKB Options")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Advanced comma-separated libxkbcommon options.")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
text: SettingsData.keyboardOptions
|
||||
placeholderText: "compose:ralt,ctrl:nocaps"
|
||||
onTextEdited: SettingsData.set("keyboardOptions", text)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent?.width ?? 0
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Keyboard Variant")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
text: SettingsData.keyboardVariants
|
||||
placeholderText: "colemak"
|
||||
onTextEdited: SettingsData.set("keyboardVariants", text)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent?.width ?? 0
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Keyboard Model")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
text: SettingsData.keyboardModel
|
||||
placeholderText: "pc104"
|
||||
onTextEdited: SettingsData.set("keyboardModel", text)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent?.width ?? 0
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Keymap File Path")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: I18n.tr("Direct path to a .xkb keymap file. Overrides layouts/variants above.")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
text: SettingsData.keyboardKeymapFile
|
||||
placeholderText: "~/.config/keymap.xkb"
|
||||
onTextEdited: SettingsData.set("keyboardKeymapFile", text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SettingsCard {
|
||||
width: parent.width
|
||||
tags: ["keyboard", "repeat", "delay", "rate", "numlock", "behavior"]
|
||||
title: I18n.tr("Keyboard Behavior")
|
||||
settingKey: "keyboardBehaviorSettings"
|
||||
iconName: "settings"
|
||||
|
||||
SettingsButtonGroupRow {
|
||||
tags: ["keyboard", "track", "layout"]
|
||||
settingKey: "keyboardTrackLayout"
|
||||
text: I18n.tr("Remember Layout")
|
||||
description: I18n.tr("How layout changes are remembered across apps")
|
||||
model: [I18n.tr("Globally"), I18n.tr("Per Window")]
|
||||
currentIndex: SettingsData.keyboardTrackLayout === "window" ? 1 : 0
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected)
|
||||
return;
|
||||
SettingsData.set("keyboardTrackLayout", index === 1 ? "window" : "global");
|
||||
}
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
tags: ["keyboard", "numlock", "startup"]
|
||||
settingKey: "keyboardNumlock"
|
||||
text: I18n.tr("Enable Num Lock")
|
||||
description: I18n.tr("Automatically turn on Num Lock at startup")
|
||||
checked: SettingsData.keyboardNumlock
|
||||
onToggled: checked => SettingsData.set("keyboardNumlock", checked)
|
||||
}
|
||||
|
||||
SettingsSliderRow {
|
||||
tags: ["keyboard", "repeat", "delay", "speed"]
|
||||
settingKey: "keyboardRepeatDelay"
|
||||
text: I18n.tr("Repeat Delay")
|
||||
description: I18n.tr("Delay before characters start repeating")
|
||||
value: SettingsData.keyboardRepeatDelay || 600
|
||||
minimum: 100
|
||||
maximum: 2000
|
||||
step: 50
|
||||
defaultValue: 600
|
||||
unit: "ms"
|
||||
onSliderValueChanged: newValue => SettingsData.set("keyboardRepeatDelay", newValue)
|
||||
}
|
||||
|
||||
SettingsSliderRow {
|
||||
tags: ["keyboard", "repeat", "rate", "speed"]
|
||||
settingKey: "keyboardRepeatRate"
|
||||
text: I18n.tr("Repeat Rate")
|
||||
description: I18n.tr("Characters per second while holding down key")
|
||||
value: SettingsData.keyboardRepeatRate || 25
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
step: 1
|
||||
defaultValue: 25
|
||||
unit: ""
|
||||
onSliderValueChanged: newValue => SettingsData.set("keyboardRepeatRate", newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Settings.Widgets
|
||||
import "../../Common/ConfigIncludeResolve.js" as ConfigIncludeResolve
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -12,93 +10,6 @@ Item {
|
||||
LayoutMirroring.enabled: I18n.isRtl
|
||||
LayoutMirroring.childrenInherit: true
|
||||
|
||||
property var inputIncludeStatus: ({
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
})
|
||||
property bool checkingInclude: false
|
||||
property bool fixingInclude: false
|
||||
|
||||
function getInputConfigPaths() {
|
||||
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
||||
if (CompositorService.compositor !== "niri")
|
||||
return null;
|
||||
return {
|
||||
"configFile": configDir + "/niri/config.kdl",
|
||||
"layoutFile": configDir + "/niri/dms/input.kdl",
|
||||
"grepPattern": 'include.*"dms/input.kdl"',
|
||||
"includeLine": 'include "dms/input.kdl"'
|
||||
};
|
||||
}
|
||||
|
||||
function checkInputIncludeStatus() {
|
||||
if (CompositorService.compositor !== "niri") {
|
||||
inputIncludeStatus = {
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
checkingInclude = true;
|
||||
Proc.runCommand("check-input-include", [Proc.dmsBin, "config", "resolve-include", "niri", "input.kdl"], (output, exitCode) => {
|
||||
checkingInclude = false;
|
||||
if (exitCode !== 0) {
|
||||
inputIncludeStatus = {
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
};
|
||||
return;
|
||||
}
|
||||
try {
|
||||
inputIncludeStatus = JSON.parse(output.trim());
|
||||
} catch (e) {
|
||||
inputIncludeStatus = {
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fixInputInclude() {
|
||||
const paths = getInputConfigPaths();
|
||||
if (!paths)
|
||||
return;
|
||||
|
||||
fixingInclude = true;
|
||||
const unixTime = Math.floor(Date.now() / 1000);
|
||||
const backupFile = paths.configFile + ".backup" + unixTime;
|
||||
const script = ConfigIncludeResolve.buildRepairScript({
|
||||
configFile: paths.configFile,
|
||||
backupFile: backupFile,
|
||||
fragmentFile: paths.layoutFile,
|
||||
grepPattern: paths.grepPattern,
|
||||
includeLine: paths.includeLine
|
||||
});
|
||||
Proc.runCommand("fix-input-include", ["sh", "-c", script], (output, exitCode) => {
|
||||
fixingInclude = false;
|
||||
if (exitCode !== 0)
|
||||
return;
|
||||
checkInputIncludeStatus();
|
||||
SettingsData.updateCompositorInput();
|
||||
});
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (CompositorService.isNiri) {
|
||||
checkInputIncludeStatus();
|
||||
}
|
||||
}
|
||||
|
||||
DankFlickable {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
@@ -113,67 +24,8 @@ Item {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
StyledRect {
|
||||
id: warningBox
|
||||
NiriInputSetupBanner {
|
||||
width: parent.width
|
||||
height: warningContent.implicitHeight + Theme.spacingL * 2
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
readonly property bool showSetup: !root.inputIncludeStatus.included
|
||||
|
||||
color: showSetup ? Theme.withAlpha(Theme.primary, 0.15) : Theme.withAlpha(Theme.primary, 0)
|
||||
border.color: showSetup ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.primary, 0)
|
||||
border.width: 1
|
||||
visible: showSetup && !root.checkingInclude && CompositorService.isNiri
|
||||
|
||||
Row {
|
||||
id: warningContent
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "warning"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - (fixButton.visible ? fixButton.width + Theme.spacingM : 0) - Theme.spacingM
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("First Time Setup")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.primary
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Click 'Setup' to create %1 and add include to your compositor config.").arg("dms/input")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
}
|
||||
}
|
||||
|
||||
DankButton {
|
||||
id: fixButton
|
||||
visible: warningBox.showSetup
|
||||
text: root.fixingInclude ? I18n.tr("Setting up...") : I18n.tr("Setup")
|
||||
backgroundColor: Theme.primary
|
||||
textColor: Theme.primaryText
|
||||
enabled: !root.fixingInclude
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: root.fixInputInclude()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SettingsCard {
|
||||
@@ -212,12 +64,15 @@ Item {
|
||||
description: I18n.tr("Flat uses constant speed; Adaptive scales with movement speed")
|
||||
model: [I18n.tr("Default"), I18n.tr("Flat"), I18n.tr("Adaptive")]
|
||||
currentIndex: {
|
||||
if (SettingsData.mouseAccelProfile === "flat") return 1;
|
||||
if (SettingsData.mouseAccelProfile === "adaptive") return 2;
|
||||
if (SettingsData.mouseAccelProfile === "flat")
|
||||
return 1;
|
||||
if (SettingsData.mouseAccelProfile === "adaptive")
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected) return;
|
||||
if (!selected)
|
||||
return;
|
||||
const profiles = ["default", "flat", "adaptive"];
|
||||
SettingsData.set("mouseAccelProfile", profiles[index]);
|
||||
}
|
||||
@@ -252,12 +107,15 @@ Item {
|
||||
description: I18n.tr("Choose when to generate scrolling events")
|
||||
model: [I18n.tr("Default"), I18n.tr("No Scroll"), I18n.tr("On Button Down")]
|
||||
currentIndex: {
|
||||
if (SettingsData.mouseScrollMethod === "no-scroll") return 1;
|
||||
if (SettingsData.mouseScrollMethod === "on-button-down") return 2;
|
||||
if (SettingsData.mouseScrollMethod === "no-scroll")
|
||||
return 1;
|
||||
if (SettingsData.mouseScrollMethod === "on-button-down")
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected) return;
|
||||
if (!selected)
|
||||
return;
|
||||
const methods = ["default", "no-scroll", "on-button-down"];
|
||||
SettingsData.set("mouseScrollMethod", methods[index]);
|
||||
}
|
||||
@@ -327,12 +185,15 @@ Item {
|
||||
description: I18n.tr("Flat uses constant speed; Adaptive scales with movement speed")
|
||||
model: [I18n.tr("Default"), I18n.tr("Flat"), I18n.tr("Adaptive")]
|
||||
currentIndex: {
|
||||
if (SettingsData.touchpadAccelProfile === "flat") return 1;
|
||||
if (SettingsData.touchpadAccelProfile === "adaptive") return 2;
|
||||
if (SettingsData.touchpadAccelProfile === "flat")
|
||||
return 1;
|
||||
if (SettingsData.touchpadAccelProfile === "adaptive")
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected) return;
|
||||
if (!selected)
|
||||
return;
|
||||
const profiles = ["default", "flat", "adaptive"];
|
||||
SettingsData.set("touchpadAccelProfile", profiles[index]);
|
||||
}
|
||||
@@ -367,14 +228,19 @@ Item {
|
||||
description: I18n.tr("Choose when to generate scrolling events")
|
||||
model: [I18n.tr("Default"), I18n.tr("Two Finger"), I18n.tr("Edge"), I18n.tr("No Scroll"), I18n.tr("On Button Down")]
|
||||
currentIndex: {
|
||||
if (SettingsData.touchpadScrollMethod === "two-finger") return 1;
|
||||
if (SettingsData.touchpadScrollMethod === "edge") return 2;
|
||||
if (SettingsData.touchpadScrollMethod === "no-scroll") return 3;
|
||||
if (SettingsData.touchpadScrollMethod === "on-button-down") return 4;
|
||||
if (SettingsData.touchpadScrollMethod === "two-finger")
|
||||
return 1;
|
||||
if (SettingsData.touchpadScrollMethod === "edge")
|
||||
return 2;
|
||||
if (SettingsData.touchpadScrollMethod === "no-scroll")
|
||||
return 3;
|
||||
if (SettingsData.touchpadScrollMethod === "on-button-down")
|
||||
return 4;
|
||||
return 0;
|
||||
}
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected) return;
|
||||
if (!selected)
|
||||
return;
|
||||
const methods = ["default", "two-finger", "edge", "no-scroll", "on-button-down"];
|
||||
SettingsData.set("touchpadScrollMethod", methods[index]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import "../../../Common/ConfigIncludeResolve.js" as ConfigIncludeResolve
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
|
||||
property var includeStatus: ({
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
})
|
||||
property bool checking: false
|
||||
property bool fixing: false
|
||||
|
||||
readonly property bool showSetup: !includeStatus.included
|
||||
|
||||
function getInputConfigPaths() {
|
||||
if (CompositorService.compositor !== "niri")
|
||||
return null;
|
||||
|
||||
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
||||
return {
|
||||
"configFile": configDir + "/niri/config.kdl",
|
||||
"layoutFile": configDir + "/niri/dms/input.kdl",
|
||||
"grepPattern": 'include.*"dms/input.kdl"',
|
||||
"includeLine": 'include "dms/input.kdl"'
|
||||
};
|
||||
}
|
||||
|
||||
function checkIncludeStatus() {
|
||||
if (CompositorService.compositor !== "niri") {
|
||||
includeStatus = {
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
checking = true;
|
||||
Proc.runCommand("check-input-include", [Proc.dmsBin, "config", "resolve-include", "niri", "input.kdl"], (output, exitCode) => {
|
||||
checking = false;
|
||||
if (exitCode !== 0) {
|
||||
includeStatus = {
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
};
|
||||
return;
|
||||
}
|
||||
try {
|
||||
includeStatus = JSON.parse(output.trim());
|
||||
} catch (e) {
|
||||
includeStatus = {
|
||||
"exists": false,
|
||||
"included": false,
|
||||
"configFormat": "",
|
||||
"readOnly": false
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fixInclude() {
|
||||
const paths = getInputConfigPaths();
|
||||
if (!paths)
|
||||
return;
|
||||
|
||||
fixing = true;
|
||||
const unixTime = Math.floor(Date.now() / 1000);
|
||||
const backupFile = paths.configFile + ".backup" + unixTime;
|
||||
const script = ConfigIncludeResolve.buildRepairScript({
|
||||
configFile: paths.configFile,
|
||||
backupFile: backupFile,
|
||||
fragmentFile: paths.layoutFile,
|
||||
grepPattern: paths.grepPattern,
|
||||
includeLine: paths.includeLine
|
||||
});
|
||||
Proc.runCommand("fix-input-include", ["sh", "-c", script], (output, exitCode) => {
|
||||
fixing = false;
|
||||
if (exitCode !== 0)
|
||||
return;
|
||||
checkIncludeStatus();
|
||||
SettingsData.updateCompositorInput();
|
||||
});
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (CompositorService.isNiri) {
|
||||
checkIncludeStatus();
|
||||
}
|
||||
}
|
||||
|
||||
height: warningContent.implicitHeight + Theme.spacingL * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: showSetup ? Theme.withAlpha(Theme.primary, 0.15) : Theme.withAlpha(Theme.primary, 0)
|
||||
border.color: showSetup ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.primary, 0)
|
||||
border.width: 1
|
||||
visible: showSetup && !checking && CompositorService.isNiri
|
||||
|
||||
Row {
|
||||
id: warningContent
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "warning"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - (fixButton.visible ? fixButton.width + Theme.spacingM : 0) - Theme.spacingM
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("First Time Setup")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.primary
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Click 'Setup' to create %1 and add include to your compositor config.").arg("dms/input")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
}
|
||||
}
|
||||
|
||||
DankButton {
|
||||
id: fixButton
|
||||
visible: root.showSetup
|
||||
text: root.fixing ? I18n.tr("Setting up...") : I18n.tr("Setup")
|
||||
backgroundColor: Theme.primary
|
||||
textColor: Theme.primaryText
|
||||
enabled: !root.fixing
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: root.fixInclude()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1674,6 +1674,16 @@ window-rule {
|
||||
const touchpadTap = typeof SettingsData !== "undefined" ? SettingsData.touchpadTapToClick : defaultTouchpadTap;
|
||||
const touchpadTapAndDrag = typeof SettingsData !== "undefined" ? SettingsData.touchpadTapAndDrag : defaultTouchpadTapAndDrag;
|
||||
|
||||
const keyboardLayouts = typeof SettingsData !== "undefined" ? SettingsData.keyboardLayouts : "";
|
||||
const keyboardVariants = typeof SettingsData !== "undefined" ? SettingsData.keyboardVariants : "";
|
||||
const keyboardModel = typeof SettingsData !== "undefined" ? SettingsData.keyboardModel : "";
|
||||
const keyboardOptions = typeof SettingsData !== "undefined" ? SettingsData.keyboardOptions : "";
|
||||
const keyboardKeymapFile = typeof SettingsData !== "undefined" ? SettingsData.keyboardKeymapFile : "";
|
||||
const keyboardTrackLayout = typeof SettingsData !== "undefined" ? SettingsData.keyboardTrackLayout : "";
|
||||
const keyboardRepeatDelay = typeof SettingsData !== "undefined" ? SettingsData.keyboardRepeatDelay : 0;
|
||||
const keyboardRepeatRate = typeof SettingsData !== "undefined" ? SettingsData.keyboardRepeatRate : 0;
|
||||
const keyboardNumlock = typeof SettingsData !== "undefined" ? SettingsData.keyboardNumlock : false;
|
||||
|
||||
const dmsWarning = `// ! DO NOT EDIT !
|
||||
// ! AUTO-GENERATED BY DMS !
|
||||
// ! CHANGES WILL BE OVERWRITTEN !
|
||||
@@ -1741,6 +1751,47 @@ window-rule {
|
||||
}
|
||||
inputContent += " }\n";
|
||||
|
||||
// Keyboard block — emitted only when configured so untouched settings keep
|
||||
// niri's locale1 fallback and any keyboard block in the user's own config.
|
||||
const kdlString = value => `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
||||
const keyboardConfigured = keyboardKeymapFile || keyboardLayouts || keyboardVariants || keyboardModel || keyboardOptions || keyboardTrackLayout || keyboardRepeatDelay > 0 || keyboardRepeatRate > 0 || keyboardNumlock;
|
||||
if (keyboardConfigured) {
|
||||
inputContent += " keyboard {\n";
|
||||
if (keyboardKeymapFile) {
|
||||
inputContent += " xkb {\n";
|
||||
inputContent += ` file ${kdlString(keyboardKeymapFile)}\n`;
|
||||
inputContent += " }\n";
|
||||
} else if (keyboardLayouts || keyboardVariants || keyboardModel || keyboardOptions) {
|
||||
inputContent += " xkb {\n";
|
||||
if (keyboardLayouts) {
|
||||
inputContent += ` layout ${kdlString(keyboardLayouts)}\n`;
|
||||
}
|
||||
if (keyboardVariants) {
|
||||
inputContent += ` variant ${kdlString(keyboardVariants)}\n`;
|
||||
}
|
||||
if (keyboardModel) {
|
||||
inputContent += ` model ${kdlString(keyboardModel)}\n`;
|
||||
}
|
||||
if (keyboardOptions) {
|
||||
inputContent += ` options ${kdlString(keyboardOptions)}\n`;
|
||||
}
|
||||
inputContent += " }\n";
|
||||
}
|
||||
if (keyboardTrackLayout) {
|
||||
inputContent += ` track-layout "${keyboardTrackLayout}"\n`;
|
||||
}
|
||||
if (keyboardRepeatDelay > 0) {
|
||||
inputContent += ` repeat-delay ${keyboardRepeatDelay}\n`;
|
||||
}
|
||||
if (keyboardRepeatRate > 0) {
|
||||
inputContent += ` repeat-rate ${keyboardRepeatRate}\n`;
|
||||
}
|
||||
if (keyboardNumlock) {
|
||||
inputContent += " numlock\n";
|
||||
}
|
||||
inputContent += " }\n";
|
||||
}
|
||||
|
||||
inputContent += "}\n";
|
||||
|
||||
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
||||
|
||||
@@ -135,10 +135,14 @@ TAB_INDEX_MAP = {
|
||||
"UsersTab.qml": 35,
|
||||
"AutoStartTab.qml": 36,
|
||||
"BatteryTab.qml": 42,
|
||||
"MouseTouchpadTab.qml": 44,
|
||||
"KeyboardTab.qml": 45,
|
||||
}
|
||||
|
||||
FILE_CONDITION_MAP = {
|
||||
"GreeterTab.qml": "greeterAvailable",
|
||||
"MouseTouchpadTab.qml": "isNiri",
|
||||
"KeyboardTab.qml": "isNiri",
|
||||
}
|
||||
|
||||
TAB_CATEGORY_MAP = {
|
||||
@@ -185,6 +189,8 @@ TAB_CATEGORY_MAP = {
|
||||
41: "Network",
|
||||
42: "Power & Security",
|
||||
43: "Dank Dash",
|
||||
44: "System",
|
||||
45: "System",
|
||||
}
|
||||
|
||||
SEARCHABLE_COMPONENTS = [
|
||||
|
||||
@@ -10921,17 +10921,609 @@
|
||||
],
|
||||
"icon": "dashboard"
|
||||
},
|
||||
{
|
||||
"section": "mouseAccelProfile",
|
||||
"label": "Acceleration Profile",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"acceleration",
|
||||
"adaptive",
|
||||
"constant",
|
||||
"flat",
|
||||
"linux",
|
||||
"mouse",
|
||||
"movement",
|
||||
"os",
|
||||
"profile",
|
||||
"scales",
|
||||
"speed",
|
||||
"system",
|
||||
"uses"
|
||||
],
|
||||
"description": "Flat uses constant speed; Adaptive scales with movement speed",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadAccelProfile",
|
||||
"label": "Acceleration Profile",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"acceleration",
|
||||
"adaptive",
|
||||
"constant",
|
||||
"flat",
|
||||
"linux",
|
||||
"movement",
|
||||
"os",
|
||||
"profile",
|
||||
"scales",
|
||||
"speed",
|
||||
"system",
|
||||
"touchpad",
|
||||
"uses"
|
||||
],
|
||||
"description": "Flat uses constant speed; Adaptive scales with movement speed",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadDisableWhileTyping",
|
||||
"label": "Disable While Typing",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"accidental",
|
||||
"cursor",
|
||||
"disable",
|
||||
"dwt",
|
||||
"jumps",
|
||||
"linux",
|
||||
"os",
|
||||
"prevent",
|
||||
"system",
|
||||
"touchpad",
|
||||
"typing",
|
||||
"while"
|
||||
],
|
||||
"description": "Prevent accidental cursor jumps while typing",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadDisableOnExternalMouse",
|
||||
"label": "Disable on External Mouse",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"connected",
|
||||
"disable",
|
||||
"external",
|
||||
"linux",
|
||||
"mouse",
|
||||
"os",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Disable touchpad when an external mouse is connected",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadDragLock",
|
||||
"label": "Drag Lock",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"briefly",
|
||||
"drag",
|
||||
"dragging",
|
||||
"finger",
|
||||
"keep",
|
||||
"lifted",
|
||||
"linux",
|
||||
"lock",
|
||||
"os",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Keep dragging when finger is briefly lifted",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseLeftHanded",
|
||||
"label": "Left-Handed Mode",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"button",
|
||||
"buttons",
|
||||
"handed",
|
||||
"left",
|
||||
"linux",
|
||||
"mode",
|
||||
"mouse",
|
||||
"os",
|
||||
"primary",
|
||||
"secondary",
|
||||
"swap",
|
||||
"system"
|
||||
],
|
||||
"description": "Swap primary and secondary mouse buttons",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseMiddleEmulation",
|
||||
"label": "Middle Click Emulation",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"buttons",
|
||||
"click",
|
||||
"emulate",
|
||||
"emulation",
|
||||
"left",
|
||||
"linux",
|
||||
"middle",
|
||||
"mouse",
|
||||
"os",
|
||||
"pressing",
|
||||
"right",
|
||||
"system"
|
||||
],
|
||||
"description": "Emulate middle click by pressing left and right buttons",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadMiddleEmulation",
|
||||
"label": "Middle Click Emulation",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"buttons",
|
||||
"click",
|
||||
"emulate",
|
||||
"emulation",
|
||||
"left",
|
||||
"linux",
|
||||
"middle",
|
||||
"os",
|
||||
"pressing",
|
||||
"right",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Emulate middle click by pressing left and right buttons",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "_tab_44",
|
||||
"label": "Mouse & Touchpad",
|
||||
"tabIndex": 44,
|
||||
"category": "Settings",
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"linux",
|
||||
"mouse",
|
||||
"settings",
|
||||
"os",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"icon": "mouse",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseSettings",
|
||||
"label": "Mouse Settings",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"acceleration",
|
||||
"buttons",
|
||||
"input",
|
||||
"linux",
|
||||
"mouse",
|
||||
"os",
|
||||
"pointer",
|
||||
"primary",
|
||||
"secondary",
|
||||
"sensitivity",
|
||||
"settings",
|
||||
"swap",
|
||||
"system"
|
||||
],
|
||||
"icon": "mouse",
|
||||
"description": "Swap primary and secondary mouse buttons",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseNaturalScroll",
|
||||
"label": "Natural Scrolling",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"direction",
|
||||
"linux",
|
||||
"mouse",
|
||||
"natural",
|
||||
"os",
|
||||
"reverse",
|
||||
"scroll",
|
||||
"scrolling",
|
||||
"system",
|
||||
"wheel"
|
||||
],
|
||||
"description": "Reverse mouse wheel scrolling direction",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadNaturalScroll",
|
||||
"label": "Natural Scrolling",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"direction",
|
||||
"finger",
|
||||
"linux",
|
||||
"natural",
|
||||
"os",
|
||||
"reverse",
|
||||
"scroll",
|
||||
"scrolling",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Reverse two-finger scrolling direction",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseAccelSpeed",
|
||||
"label": "Pointer Speed",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"accel",
|
||||
"adjust",
|
||||
"linux",
|
||||
"mouse",
|
||||
"os",
|
||||
"pointer",
|
||||
"sensitivity",
|
||||
"speed",
|
||||
"system"
|
||||
],
|
||||
"description": "Adjust pointer sensitivity speed",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseScrollMethod",
|
||||
"label": "Scroll Method",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"choose",
|
||||
"events",
|
||||
"generate",
|
||||
"linux",
|
||||
"method",
|
||||
"mouse",
|
||||
"os",
|
||||
"scroll",
|
||||
"scrolling",
|
||||
"system"
|
||||
],
|
||||
"description": "Choose when to generate scrolling events",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadScrollMethod",
|
||||
"label": "Scroll Method",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"choose",
|
||||
"events",
|
||||
"generate",
|
||||
"linux",
|
||||
"method",
|
||||
"os",
|
||||
"scroll",
|
||||
"scrolling",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Choose when to generate scrolling events",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "mouseScrollFactor",
|
||||
"label": "Scrolling Speed",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"adjust",
|
||||
"factor",
|
||||
"linux",
|
||||
"mouse",
|
||||
"multiplier",
|
||||
"os",
|
||||
"scroll",
|
||||
"scrolling",
|
||||
"sensitivity",
|
||||
"speed",
|
||||
"system"
|
||||
],
|
||||
"description": "Adjust scrolling sensitivity multiplier",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadScrollFactor",
|
||||
"label": "Scrolling Speed",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"adjust",
|
||||
"factor",
|
||||
"linux",
|
||||
"multiplier",
|
||||
"os",
|
||||
"scroll",
|
||||
"scrolling",
|
||||
"sensitivity",
|
||||
"speed",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Adjust scrolling sensitivity multiplier",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadTapAndDrag",
|
||||
"label": "Tap and Drag",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"drag",
|
||||
"items",
|
||||
"linux",
|
||||
"move",
|
||||
"os",
|
||||
"system",
|
||||
"tap",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Tap and drag on the touchpad to move items",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadTapToClick",
|
||||
"label": "Tap to Click",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"click",
|
||||
"clicks",
|
||||
"left",
|
||||
"linux",
|
||||
"os",
|
||||
"surface",
|
||||
"system",
|
||||
"tap",
|
||||
"touchpad",
|
||||
"trigger"
|
||||
],
|
||||
"description": "Tap the touchpad surface to trigger left click clicks",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadSettings",
|
||||
"label": "Touchpad Settings",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"click",
|
||||
"clicks",
|
||||
"input",
|
||||
"left",
|
||||
"linux",
|
||||
"natural",
|
||||
"os",
|
||||
"sensitivity",
|
||||
"settings",
|
||||
"surface",
|
||||
"system",
|
||||
"tap",
|
||||
"touchpad",
|
||||
"trigger"
|
||||
],
|
||||
"icon": "trackpad_input_2",
|
||||
"description": "Tap the touchpad surface to trigger left click clicks",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "touchpadAccelSpeed",
|
||||
"label": "Touchpad Speed",
|
||||
"tabIndex": 44,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"accel",
|
||||
"adjust",
|
||||
"linux",
|
||||
"os",
|
||||
"pointer",
|
||||
"sensitivity",
|
||||
"speed",
|
||||
"system",
|
||||
"touchpad"
|
||||
],
|
||||
"description": "Adjust touchpad pointer speed",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardNumlock",
|
||||
"label": "Enable Num Lock",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"automatically",
|
||||
"enable",
|
||||
"keyboard",
|
||||
"linux",
|
||||
"lock",
|
||||
"num",
|
||||
"numlock",
|
||||
"os",
|
||||
"startup",
|
||||
"system",
|
||||
"turn"
|
||||
],
|
||||
"description": "Automatically turn on Num Lock at startup",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "_tab_45",
|
||||
"label": "Keyboard",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"keyboard",
|
||||
"linux",
|
||||
"os",
|
||||
"system"
|
||||
],
|
||||
"icon": "keyboard",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardBehaviorSettings",
|
||||
"label": "Keyboard Behavior",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"across",
|
||||
"apps",
|
||||
"behavior",
|
||||
"changes",
|
||||
"delay",
|
||||
"keyboard",
|
||||
"layout",
|
||||
"linux",
|
||||
"numlock",
|
||||
"os",
|
||||
"rate",
|
||||
"remembered",
|
||||
"repeat",
|
||||
"system"
|
||||
],
|
||||
"icon": "settings",
|
||||
"description": "How layout changes are remembered across apps",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardLayoutsSettings",
|
||||
"label": "Keyboard Layouts",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"between",
|
||||
"choose",
|
||||
"cycle",
|
||||
"input",
|
||||
"keyboard",
|
||||
"language",
|
||||
"layout",
|
||||
"layouts",
|
||||
"linux",
|
||||
"os",
|
||||
"shortcut",
|
||||
"system",
|
||||
"xkb"
|
||||
],
|
||||
"icon": "keyboard",
|
||||
"description": "Choose a shortcut key to cycle between keyboard layouts",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardTrackLayout",
|
||||
"label": "Remember Layout",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"across",
|
||||
"apps",
|
||||
"changes",
|
||||
"keyboard",
|
||||
"layout",
|
||||
"linux",
|
||||
"os",
|
||||
"remember",
|
||||
"remembered",
|
||||
"system",
|
||||
"track"
|
||||
],
|
||||
"description": "How layout changes are remembered across apps",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardRepeatDelay",
|
||||
"label": "Repeat Delay",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"before",
|
||||
"characters",
|
||||
"delay",
|
||||
"keyboard",
|
||||
"linux",
|
||||
"os",
|
||||
"repeat",
|
||||
"repeating",
|
||||
"speed",
|
||||
"start",
|
||||
"system"
|
||||
],
|
||||
"description": "Delay before characters start repeating",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardRepeatRate",
|
||||
"label": "Repeat Rate",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"characters",
|
||||
"down",
|
||||
"holding",
|
||||
"keyboard",
|
||||
"linux",
|
||||
"os",
|
||||
"rate",
|
||||
"repeat",
|
||||
"second",
|
||||
"speed",
|
||||
"system",
|
||||
"while"
|
||||
],
|
||||
"description": "Characters per second while holding down key",
|
||||
"conditionKey": "isNiri"
|
||||
},
|
||||
{
|
||||
"section": "keyboardOptions",
|
||||
"label": "Switch Layout Shortcut",
|
||||
"tabIndex": 45,
|
||||
"category": "System",
|
||||
"keywords": [
|
||||
"between",
|
||||
"choose",
|
||||
"cycle",
|
||||
"keyboard",
|
||||
"layout",
|
||||
"layouts",
|
||||
"linux",
|
||||
"os",
|
||||
"shortcut",
|
||||
"switch",
|
||||
"system",
|
||||
"xkb"
|
||||
],
|
||||
"description": "Choose a shortcut key to cycle between keyboard layouts",
|
||||
"conditionKey": "isNiri"
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user