148 lines
4.2 KiB
Go
148 lines
4.2 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package preferences
|
|
|
|
/*
|
|
#include <stdlib.h>
|
|
#include "native.h"
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/input"
|
|
)
|
|
|
|
var modifierKeys = []string{"Insert", "KP_Insert", "Caps_Lock"}
|
|
|
|
func (session *uiSession) setKeyBindings(values Values) {
|
|
session.bindingDraft = input.CloneBindingOverrides(values.KeyBindings)
|
|
setCheck("generalDesktopButton", values.KeyboardLayout != 2)
|
|
setCheck("generalLaptopButton", values.KeyboardLayout == 2)
|
|
setModifierKeys(values.CthulhuModifierKeys)
|
|
session.bindingLayout = values.KeyboardLayout
|
|
if session.bindingLayout != 2 {
|
|
session.bindingLayout = 1
|
|
}
|
|
setCheck("keyBindingDesktopButton", session.bindingLayout == 1)
|
|
setCheck("keyBindingLaptopButton", session.bindingLayout == 2)
|
|
session.populateKeyBindings(0)
|
|
}
|
|
|
|
func (session *uiSession) refreshKeyBindingLayout() {
|
|
layout := 1
|
|
if getCheck("keyBindingLaptopButton") {
|
|
layout = 2
|
|
}
|
|
if layout != session.bindingLayout && (layout == 1 || layout == 2) {
|
|
session.bindingLayout = layout
|
|
session.populateKeyBindings(0)
|
|
}
|
|
}
|
|
|
|
func (session *uiSession) populateKeyBindings(selected int) {
|
|
session.bindingRows = input.BindingRows(input.KeyboardLayout(session.bindingLayout), session.bindingDraft)
|
|
C.prefs_bindings_clear()
|
|
for _, row := range session.bindingRows {
|
|
scope := "Global"
|
|
if row.Scope == "browse" {
|
|
scope = "Browse mode"
|
|
}
|
|
keys := row.Keys
|
|
if keys == "" {
|
|
keys = "Unbound"
|
|
}
|
|
label, scopeText, shortcuts, defaults := C.CString(row.Label), C.CString(scope), C.CString(keys), C.CString(row.DefaultKeys)
|
|
C.prefs_binding_append(label, scopeText, shortcuts, defaults)
|
|
C.free(unsafe.Pointer(label))
|
|
C.free(unsafe.Pointer(scopeText))
|
|
C.free(unsafe.Pointer(shortcuts))
|
|
C.free(unsafe.Pointer(defaults))
|
|
}
|
|
C.prefs_binding_select(C.int(selected))
|
|
// Keep the editor empty when the selected command has been disabled.
|
|
if selected >= 0 && selected < len(session.bindingRows) {
|
|
id, text := C.CString("keyBindingEntry"), C.CString(session.bindingRows[selected].Keys)
|
|
C.prefs_entry_set(id, text)
|
|
C.free(unsafe.Pointer(id))
|
|
C.free(unsafe.Pointer(text))
|
|
}
|
|
}
|
|
|
|
func (session *uiSession) editKeyBinding(action int) {
|
|
selected := int(C.prefs_binding_selected())
|
|
if action != 7 && (selected < 0 || selected >= len(session.bindingRows)) {
|
|
return
|
|
}
|
|
draft := input.CloneBindingOverrides(session.bindingDraft)
|
|
var row input.BindingRow
|
|
if selected >= 0 && selected < len(session.bindingRows) {
|
|
row = session.bindingRows[selected]
|
|
}
|
|
kept := draft[:0]
|
|
for _, override := range draft {
|
|
matches := override.Layout == input.KeyboardLayout(session.bindingLayout) && (action == 7 || (override.Scope == row.Scope && override.Command == row.Command))
|
|
if !matches {
|
|
kept = append(kept, override)
|
|
}
|
|
}
|
|
draft = kept
|
|
if action == 4 || action == 5 {
|
|
keys := []string{}
|
|
if action == 4 {
|
|
id := C.CString("keyBindingEntry")
|
|
text := C.GoString(C.prefs_entry_get(id))
|
|
C.free(unsafe.Pointer(id))
|
|
if strings.TrimSpace(text) != "" {
|
|
for _, key := range strings.Split(text, ";") {
|
|
chord, err := input.ParseCommandChord(key)
|
|
if err != nil {
|
|
status(err.Error(), true)
|
|
return
|
|
}
|
|
keys = append(keys, input.FormatCommandChord(chord))
|
|
}
|
|
}
|
|
}
|
|
draft = append(draft, input.BindingOverride{Layout: input.KeyboardLayout(session.bindingLayout), Scope: row.Scope, Command: row.Command, Keys: keys})
|
|
}
|
|
if err := input.ValidateBindingOverrides(draft); err != nil {
|
|
status(err.Error(), true)
|
|
return
|
|
}
|
|
session.bindingDraft = draft
|
|
session.populateKeyBindings(selected)
|
|
status("Binding updated. Apply or OK commits these changes.", true)
|
|
}
|
|
|
|
func setModifierKeys(keys []string) {
|
|
for _, key := range modifierKeys {
|
|
enabled := false
|
|
for _, configured := range keys {
|
|
if configured == key {
|
|
enabled = true
|
|
break
|
|
}
|
|
}
|
|
id := C.CString(key)
|
|
C.prefs_modifier_set(id, boolean(enabled))
|
|
C.free(unsafe.Pointer(id))
|
|
}
|
|
}
|
|
|
|
func getModifierKeys() []string {
|
|
keys := []string{}
|
|
for _, key := range modifierKeys {
|
|
id := C.CString(key)
|
|
if C.prefs_modifier_get(id) != 0 {
|
|
keys = append(keys, key)
|
|
}
|
|
C.free(unsafe.Pointer(id))
|
|
}
|
|
return keys
|
|
}
|