mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-07 22:18:30 -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 touchpadTapAndDrag: true
|
||||||
property bool touchpadTapToClick: 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 int firstDayOfWeek: -1
|
||||||
property bool showWeekNumber: false
|
property bool showWeekNumber: false
|
||||||
property string calendarBackend: "auto"
|
property string calendarBackend: "auto"
|
||||||
|
|||||||
@@ -57,6 +57,16 @@ var SPEC = {
|
|||||||
touchpadTapAndDrag: { def: true, onChange: "updateCompositorInput" },
|
touchpadTapAndDrag: { def: true, onChange: "updateCompositorInput" },
|
||||||
touchpadTapToClick: { 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 },
|
firstDayOfWeek: { def: -1 },
|
||||||
showWeekNumber: { def: false },
|
showWeekNumber: { def: false },
|
||||||
calendarBackend: { def: "auto" },
|
calendarBackend: { def: "auto" },
|
||||||
|
|||||||
@@ -733,5 +733,20 @@ FocusScope {
|
|||||||
Qt.callLater(() => item.forceActiveFocus());
|
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,
|
"tabIndex": 44,
|
||||||
"niriOnly": true
|
"niriOnly": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "keyboard",
|
||||||
|
"text": I18n.tr("Keyboard"),
|
||||||
|
"icon": "keyboard",
|
||||||
|
"tabIndex": 45,
|
||||||
|
"niriOnly": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "locale",
|
"id": "locale",
|
||||||
"text": I18n.tr("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 QtQuick
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Modules.Settings.Widgets
|
import qs.Modules.Settings.Widgets
|
||||||
import "../../Common/ConfigIncludeResolve.js" as ConfigIncludeResolve
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -12,93 +10,6 @@ Item {
|
|||||||
LayoutMirroring.enabled: I18n.isRtl
|
LayoutMirroring.enabled: I18n.isRtl
|
||||||
LayoutMirroring.childrenInherit: true
|
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 {
|
DankFlickable {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
clip: true
|
clip: true
|
||||||
@@ -113,67 +24,8 @@ Item {
|
|||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
spacing: Theme.spacingXL
|
spacing: Theme.spacingXL
|
||||||
|
|
||||||
StyledRect {
|
NiriInputSetupBanner {
|
||||||
id: warningBox
|
|
||||||
width: parent.width
|
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 {
|
SettingsCard {
|
||||||
@@ -212,12 +64,15 @@ Item {
|
|||||||
description: I18n.tr("Flat uses constant speed; Adaptive scales with movement speed")
|
description: I18n.tr("Flat uses constant speed; Adaptive scales with movement speed")
|
||||||
model: [I18n.tr("Default"), I18n.tr("Flat"), I18n.tr("Adaptive")]
|
model: [I18n.tr("Default"), I18n.tr("Flat"), I18n.tr("Adaptive")]
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
if (SettingsData.mouseAccelProfile === "flat") return 1;
|
if (SettingsData.mouseAccelProfile === "flat")
|
||||||
if (SettingsData.mouseAccelProfile === "adaptive") return 2;
|
return 1;
|
||||||
|
if (SettingsData.mouseAccelProfile === "adaptive")
|
||||||
|
return 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
onSelectionChanged: (index, selected) => {
|
onSelectionChanged: (index, selected) => {
|
||||||
if (!selected) return;
|
if (!selected)
|
||||||
|
return;
|
||||||
const profiles = ["default", "flat", "adaptive"];
|
const profiles = ["default", "flat", "adaptive"];
|
||||||
SettingsData.set("mouseAccelProfile", profiles[index]);
|
SettingsData.set("mouseAccelProfile", profiles[index]);
|
||||||
}
|
}
|
||||||
@@ -252,12 +107,15 @@ Item {
|
|||||||
description: I18n.tr("Choose when to generate scrolling events")
|
description: I18n.tr("Choose when to generate scrolling events")
|
||||||
model: [I18n.tr("Default"), I18n.tr("No Scroll"), I18n.tr("On Button Down")]
|
model: [I18n.tr("Default"), I18n.tr("No Scroll"), I18n.tr("On Button Down")]
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
if (SettingsData.mouseScrollMethod === "no-scroll") return 1;
|
if (SettingsData.mouseScrollMethod === "no-scroll")
|
||||||
if (SettingsData.mouseScrollMethod === "on-button-down") return 2;
|
return 1;
|
||||||
|
if (SettingsData.mouseScrollMethod === "on-button-down")
|
||||||
|
return 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
onSelectionChanged: (index, selected) => {
|
onSelectionChanged: (index, selected) => {
|
||||||
if (!selected) return;
|
if (!selected)
|
||||||
|
return;
|
||||||
const methods = ["default", "no-scroll", "on-button-down"];
|
const methods = ["default", "no-scroll", "on-button-down"];
|
||||||
SettingsData.set("mouseScrollMethod", methods[index]);
|
SettingsData.set("mouseScrollMethod", methods[index]);
|
||||||
}
|
}
|
||||||
@@ -327,12 +185,15 @@ Item {
|
|||||||
description: I18n.tr("Flat uses constant speed; Adaptive scales with movement speed")
|
description: I18n.tr("Flat uses constant speed; Adaptive scales with movement speed")
|
||||||
model: [I18n.tr("Default"), I18n.tr("Flat"), I18n.tr("Adaptive")]
|
model: [I18n.tr("Default"), I18n.tr("Flat"), I18n.tr("Adaptive")]
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
if (SettingsData.touchpadAccelProfile === "flat") return 1;
|
if (SettingsData.touchpadAccelProfile === "flat")
|
||||||
if (SettingsData.touchpadAccelProfile === "adaptive") return 2;
|
return 1;
|
||||||
|
if (SettingsData.touchpadAccelProfile === "adaptive")
|
||||||
|
return 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
onSelectionChanged: (index, selected) => {
|
onSelectionChanged: (index, selected) => {
|
||||||
if (!selected) return;
|
if (!selected)
|
||||||
|
return;
|
||||||
const profiles = ["default", "flat", "adaptive"];
|
const profiles = ["default", "flat", "adaptive"];
|
||||||
SettingsData.set("touchpadAccelProfile", profiles[index]);
|
SettingsData.set("touchpadAccelProfile", profiles[index]);
|
||||||
}
|
}
|
||||||
@@ -367,14 +228,19 @@ Item {
|
|||||||
description: I18n.tr("Choose when to generate scrolling events")
|
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")]
|
model: [I18n.tr("Default"), I18n.tr("Two Finger"), I18n.tr("Edge"), I18n.tr("No Scroll"), I18n.tr("On Button Down")]
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
if (SettingsData.touchpadScrollMethod === "two-finger") return 1;
|
if (SettingsData.touchpadScrollMethod === "two-finger")
|
||||||
if (SettingsData.touchpadScrollMethod === "edge") return 2;
|
return 1;
|
||||||
if (SettingsData.touchpadScrollMethod === "no-scroll") return 3;
|
if (SettingsData.touchpadScrollMethod === "edge")
|
||||||
if (SettingsData.touchpadScrollMethod === "on-button-down") return 4;
|
return 2;
|
||||||
|
if (SettingsData.touchpadScrollMethod === "no-scroll")
|
||||||
|
return 3;
|
||||||
|
if (SettingsData.touchpadScrollMethod === "on-button-down")
|
||||||
|
return 4;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
onSelectionChanged: (index, selected) => {
|
onSelectionChanged: (index, selected) => {
|
||||||
if (!selected) return;
|
if (!selected)
|
||||||
|
return;
|
||||||
const methods = ["default", "two-finger", "edge", "no-scroll", "on-button-down"];
|
const methods = ["default", "two-finger", "edge", "no-scroll", "on-button-down"];
|
||||||
SettingsData.set("touchpadScrollMethod", methods[index]);
|
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 touchpadTap = typeof SettingsData !== "undefined" ? SettingsData.touchpadTapToClick : defaultTouchpadTap;
|
||||||
const touchpadTapAndDrag = typeof SettingsData !== "undefined" ? SettingsData.touchpadTapAndDrag : defaultTouchpadTapAndDrag;
|
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 !
|
const dmsWarning = `// ! DO NOT EDIT !
|
||||||
// ! AUTO-GENERATED BY DMS !
|
// ! AUTO-GENERATED BY DMS !
|
||||||
// ! CHANGES WILL BE OVERWRITTEN !
|
// ! CHANGES WILL BE OVERWRITTEN !
|
||||||
@@ -1741,6 +1751,47 @@ window-rule {
|
|||||||
}
|
}
|
||||||
inputContent += " }\n";
|
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";
|
inputContent += "}\n";
|
||||||
|
|
||||||
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
||||||
|
|||||||
@@ -135,10 +135,14 @@ TAB_INDEX_MAP = {
|
|||||||
"UsersTab.qml": 35,
|
"UsersTab.qml": 35,
|
||||||
"AutoStartTab.qml": 36,
|
"AutoStartTab.qml": 36,
|
||||||
"BatteryTab.qml": 42,
|
"BatteryTab.qml": 42,
|
||||||
|
"MouseTouchpadTab.qml": 44,
|
||||||
|
"KeyboardTab.qml": 45,
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_CONDITION_MAP = {
|
FILE_CONDITION_MAP = {
|
||||||
"GreeterTab.qml": "greeterAvailable",
|
"GreeterTab.qml": "greeterAvailable",
|
||||||
|
"MouseTouchpadTab.qml": "isNiri",
|
||||||
|
"KeyboardTab.qml": "isNiri",
|
||||||
}
|
}
|
||||||
|
|
||||||
TAB_CATEGORY_MAP = {
|
TAB_CATEGORY_MAP = {
|
||||||
@@ -185,6 +189,8 @@ TAB_CATEGORY_MAP = {
|
|||||||
41: "Network",
|
41: "Network",
|
||||||
42: "Power & Security",
|
42: "Power & Security",
|
||||||
43: "Dank Dash",
|
43: "Dank Dash",
|
||||||
|
44: "System",
|
||||||
|
45: "System",
|
||||||
}
|
}
|
||||||
|
|
||||||
SEARCHABLE_COMPONENTS = [
|
SEARCHABLE_COMPONENTS = [
|
||||||
|
|||||||
@@ -10921,17 +10921,609 @@
|
|||||||
],
|
],
|
||||||
"icon": "dashboard"
|
"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",
|
"section": "_tab_44",
|
||||||
"label": "Mouse & Touchpad",
|
"label": "Mouse & Touchpad",
|
||||||
"tabIndex": 44,
|
"tabIndex": 44,
|
||||||
"category": "Settings",
|
"category": "System",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
"linux",
|
||||||
"mouse",
|
"mouse",
|
||||||
"settings",
|
"os",
|
||||||
|
"system",
|
||||||
"touchpad"
|
"touchpad"
|
||||||
],
|
],
|
||||||
"icon": "mouse",
|
"icon": "mouse",
|
||||||
"conditionKey": "isNiri"
|
"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