Start cthulhu in laptop layout with -l.
This commit is contained in:
1 parent
7723bd7e09
commit
d8b59aa05b
10 files changed
+259
-5
No files matched your search
@@ -14,6 +14,17 @@ Cthulhu is a Linux screen reader written in Go.
|
|||||||
|
|
||||||
AI-assisted contributions are welcome. Contributors remain responsible for human review and testing before submission; see the [full policy](CONTRIBUTING.md#ai-assisted-contributions).
|
AI-assisted contributions are welcome. Contributors remain responsible for human review and testing before submission; see the [full policy](CONTRIBUTING.md#ai-assisted-contributions).
|
||||||
|
|
||||||
|
## Start with the laptop keyboard layout
|
||||||
|
|
||||||
|
Run `cthulhu -l` to use the laptop layout with Caps Lock as the Cthulhu
|
||||||
|
modifier for this session. No number pad is needed. The selection stays
|
||||||
|
active when switching applications and does not change the saved profile.
|
||||||
|
Starting without `-l` uses the saved keyboard settings again.
|
||||||
|
|
||||||
|
Press Caps Lock+Space to open Preferences. Applying preferences replaces the
|
||||||
|
temporary selection; save the laptop layout there to make it permanent.
|
||||||
|
Use `cthulhu -l -s` to open Preferences at startup.
|
||||||
|
|
||||||
## Login greeter settings
|
## Login greeter settings
|
||||||
|
|
||||||
Copy your saved active profile into the LightDM account's default Cthulhu
|
Copy your saved active profile into the LightDM account's default Cthulhu
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ func run(ctx context.Context, arguments []string, stdout, stderr io.Writer) (res
|
|||||||
greeter := options.String("greeter", "", "copy the saved active profile to a greeter account and exit (supported: lightdm)")
|
greeter := options.String("greeter", "", "copy the saved active profile to a greeter account and exit (supported: lightdm)")
|
||||||
shortSettings := options.Bool("s", false, "open the preferences window at startup")
|
shortSettings := options.Bool("s", false, "open the preferences window at startup")
|
||||||
settingsFlag := options.Bool("settings", false, "open the preferences window at startup")
|
settingsFlag := options.Bool("settings", false, "open the preferences window at startup")
|
||||||
|
laptopLayout := options.Bool("l", false, "start with laptop layout and Caps Lock as the Cthulhu key for this session")
|
||||||
preferencesUI := options.Bool("preferences-ui", false, "run the internal preferences helper (private pipe protocol)")
|
preferencesUI := options.Bool("preferences-ui", false, "run the internal preferences helper (private pipe protocol)")
|
||||||
notificationListUI := options.Bool("notification-list-ui", false, "run the internal notification list helper (private pipe protocol)")
|
notificationListUI := options.Bool("notification-list-ui", false, "run the internal notification list helper (private pipe protocol)")
|
||||||
speechHistoryUI := options.Bool("speech-history-ui", false, "run the internal speech history helper (private pipe protocol)")
|
speechHistoryUI := options.Bool("speech-history-ui", false, "run the internal speech history helper (private pipe protocol)")
|
||||||
@@ -248,6 +249,7 @@ func run(ctx context.Context, arguments []string, stdout, stderr io.Writer) (res
|
|||||||
TentacleCgroupParent: *tentacleParent,
|
TentacleCgroupParent: *tentacleParent,
|
||||||
EnableRemote: true,
|
EnableRemote: true,
|
||||||
OpenPreferences: *shortSettings || *settingsFlag,
|
OpenPreferences: *shortSettings || *settingsFlag,
|
||||||
|
LaptopLayout: *laptopLayout,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
SpeechSocket: *speechSocket,
|
SpeechSocket: *speechSocket,
|
||||||
Settings: &settings,
|
Settings: &settings,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||||
|
"git.stormux.org/storm/cthulhu/internal/config"
|
||||||
"git.stormux.org/storm/cthulhu/internal/version"
|
"git.stormux.org/storm/cthulhu/internal/version"
|
||||||
"git.stormux.org/storm/cthulhu/internal/wine"
|
"git.stormux.org/storm/cthulhu/internal/wine"
|
||||||
)
|
)
|
||||||
@@ -62,12 +63,66 @@ func TestHelp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if !strings.HasPrefix(help, versionOutput.String()+"\nUsage: cthulhu [options]\n\nOptions:\n") ||
|
if !strings.HasPrefix(help, versionOutput.String()+"\nUsage: cthulhu [options]\n\nOptions:\n") ||
|
||||||
!strings.Contains(help, "-s") || !strings.Contains(help, "-settings") ||
|
!strings.Contains(help, "-s") || !strings.Contains(help, "-settings") ||
|
||||||
|
!strings.Contains(help, "-l\t") || !strings.Contains(help, "laptop layout") ||
|
||||||
!strings.Contains(help, "-r") || !strings.Contains(help, "-replace") {
|
!strings.Contains(help, "-r") || !strings.Contains(help, "-replace") {
|
||||||
t.Fatalf("help output does not contain expected version, usage, and flags: %q", help)
|
t.Fatalf("help output does not contain expected version, usage, and flags: %q", help)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLaptopStartupDoesNotSaveKeyboard(t *testing.T) {
|
||||||
|
directory := t.TempDir()
|
||||||
|
path := filepath.Join(directory, "settings.toml")
|
||||||
|
store, err := config.NewStore(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
settings := config.DefaultSettings()
|
||||||
|
settings.EnableSound = false
|
||||||
|
if err := store.Save(settings); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
original, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, laptop := range []bool{true, false} {
|
||||||
|
logPath := filepath.Join(directory, "startup.log")
|
||||||
|
arguments := []string{"--config", path, "--debug-file", logPath,
|
||||||
|
"--speech-socket", filepath.Join(directory, "absent.sock")}
|
||||||
|
if laptop {
|
||||||
|
arguments = append(arguments, "-l")
|
||||||
|
}
|
||||||
|
var output bytes.Buffer
|
||||||
|
err := run(t.Context(), arguments, &output, &output)
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "connect to Speech Dispatcher") {
|
||||||
|
t.Fatalf("expected isolated startup failure, got %v", err)
|
||||||
|
}
|
||||||
|
data, err := os.ReadFile(logPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if strings.Contains(string(data), `"message":"using temporary laptop keyboard layout"`) != laptop {
|
||||||
|
t.Fatalf("startup laptop override = %t: %s", laptop, data)
|
||||||
|
}
|
||||||
|
current, err := os.ReadFile(path)
|
||||||
|
if err != nil || !bytes.Equal(current, original) {
|
||||||
|
t.Fatalf("startup changed saved profile: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLaptopCheckConfigDoesNotCreateProfile(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), "absent.toml")
|
||||||
|
var output bytes.Buffer
|
||||||
|
if err := run(t.Context(), []string{"-l", "--check-config", "--config", path}, &output, &output); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||||
|
t.Fatalf("checking built-in defaults created a profile: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCheckConfig(t *testing.T) {
|
func TestCheckConfig(t *testing.T) {
|
||||||
path := filepath.Join(t.TempDir(), "user-settings.toml")
|
path := filepath.Join(t.TempDir(), "user-settings.toml")
|
||||||
contents := []byte("[general]\nstartingProfile = [\"Default\", \"default\"]\n[profiles.default]\nspeakDescription = false\n")
|
contents := []byte("[general]\nstartingProfile = [\"Default\", \"default\"]\n[profiles.default]\nspeakDescription = false\n")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
pkgbase=cthulhu-git
|
pkgbase=cthulhu-git
|
||||||
pkgname=cthulhu-git
|
pkgname=cthulhu-git
|
||||||
_pkgname=cthulhu
|
_pkgname=cthulhu
|
||||||
pkgver=2026.10.25.r566.g7ae2801
|
pkgver=2026.10.26.r569.g7723bd7
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Desktop-agnostic screen reader with speech, Braille, and Tentacle support"
|
pkgdesc="Desktop-agnostic screen reader with speech, Braille, and Tentacle support"
|
||||||
url="https://git.stormux.org/storm/cthulhu"
|
url="https://git.stormux.org/storm/cthulhu"
|
||||||
|
|||||||
+10
-1
@@ -110,6 +110,7 @@ type Options struct {
|
|||||||
TentacleCgroupParent string
|
TentacleCgroupParent string
|
||||||
EnableRemote bool
|
EnableRemote bool
|
||||||
OpenPreferences bool
|
OpenPreferences bool
|
||||||
|
LaptopLayout bool
|
||||||
newCommands func() commandListener
|
newCommands func() commandListener
|
||||||
onPreferences func()
|
onPreferences func()
|
||||||
newSound func() soundService
|
newSound func() soundService
|
||||||
@@ -169,6 +170,12 @@ func Run(ctx context.Context, options Options) error {
|
|||||||
if options.Settings != nil {
|
if options.Settings != nil {
|
||||||
settings = *options.Settings
|
settings = *options.Settings
|
||||||
}
|
}
|
||||||
|
savedSettings := settings
|
||||||
|
if options.LaptopLayout {
|
||||||
|
settings = laptopSettings(settings)
|
||||||
|
logger.Info("using temporary laptop keyboard layout", "keyboard_layout", settings.KeyboardLayout,
|
||||||
|
"cthulhu_modifier_keys", settings.CthulhuModifierKeys)
|
||||||
|
}
|
||||||
if options.newAdapter == nil {
|
if options.newAdapter == nil {
|
||||||
options.newAdapter = func() Adapter {
|
options.newAdapter = func() Adapter {
|
||||||
adapter := atspi.New()
|
adapter := atspi.New()
|
||||||
@@ -282,7 +289,9 @@ func Run(ctx context.Context, options Options) error {
|
|||||||
focusGate.tentacleOutput = tentacles.output
|
focusGate.tentacleOutput = tentacles.output
|
||||||
services = append(services, lifecycle.Service{Name: "tentacles", Start: tentacles.Start, Stop: tentacles.Stop})
|
services = append(services, lifecycle.Service{Name: "tentacles", Start: tentacles.Start, Stop: tentacles.Stop})
|
||||||
}
|
}
|
||||||
preferences := newPreferencesWorker(logger, settings, settingsUpdater)
|
preferences := newPreferencesWorker(logger, savedSettings, settingsUpdater)
|
||||||
|
preferences.laptopLayout = options.LaptopLayout
|
||||||
|
preferences.settings = settings
|
||||||
preferences.tentacles = tentacles
|
preferences.tentacles = tentacles
|
||||||
if tentacles != nil {
|
if tentacles != nil {
|
||||||
tentacles.readerSettings = preferences
|
tentacles.readerSettings = preferences
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
// Copyright (c) 2026 Storm Dragon
|
||||||
|
// Authors: Storm Dragon, Angus Kola
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.stormux.org/storm/cthulhu/internal/config"
|
||||||
|
"git.stormux.org/storm/cthulhu/internal/input"
|
||||||
|
"git.stormux.org/storm/cthulhu/internal/preferences"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLaptopLayoutSessionAndExplicitPreferences(t *testing.T) {
|
||||||
|
global := config.DefaultSettings()
|
||||||
|
global.Path = filepath.Join(t.TempDir(), "settings.toml")
|
||||||
|
store, err := config.NewStore(global.Path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := store.Save(global); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
app := global
|
||||||
|
app.CthulhuModifierKeys = []string{"Insert"}
|
||||||
|
app.TimeFormat = "24-hour"
|
||||||
|
for _, name := range []string{"Cached Application", "New Application"} {
|
||||||
|
if err := store.SaveForApplication(name, app); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
original, err := os.ReadFile(global.Path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
worker := newPreferencesWorker(slog.New(slog.DiscardHandler), global, acceptingRemoteSpeechSettings{})
|
||||||
|
worker.laptopLayout = true
|
||||||
|
worker.settings = worker.sessionKeyboard(global)
|
||||||
|
worker.live = &liveSettings{}
|
||||||
|
worker.live.Store(worker.settings)
|
||||||
|
recorder := &keyboardRecorder{}
|
||||||
|
worker.bindings = recorder
|
||||||
|
checkLaptop := func(settings config.Settings) {
|
||||||
|
t.Helper()
|
||||||
|
if settings.KeyboardLayout != int(input.LaptopKeyboardLayout) ||
|
||||||
|
!reflect.DeepEqual(settings.CthulhuModifierKeys, []string{"Caps_Lock"}) {
|
||||||
|
t.Fatalf("laptop keyboard lost: layout=%d keys=%v", settings.KeyboardLayout, settings.CthulhuModifierKeys)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkLaptop(worker.settings)
|
||||||
|
worker.cycle_progress_output()
|
||||||
|
if worker.globalSettings.KeyboardLayout != global.KeyboardLayout || !reflect.DeepEqual(worker.globalSettings.CthulhuModifierKeys, global.CthulhuModifierKeys) {
|
||||||
|
t.Fatal("progress shortcut cached the startup keyboard in global settings")
|
||||||
|
}
|
||||||
|
for _, name := range []string{"Cached Application", "Other Application", "Cached Application", "New Application"} {
|
||||||
|
worker.switchApplication(t.Context(), name)
|
||||||
|
if worker.activeApp != name {
|
||||||
|
t.Fatal("application switch failed")
|
||||||
|
}
|
||||||
|
checkLaptop(worker.settings)
|
||||||
|
checkLaptop(worker.live.Load())
|
||||||
|
if name != "Other Application" && worker.settings.TimeFormat != "24-hour" {
|
||||||
|
t.Fatal("startup keyboard override discarded application preferences")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current, err := os.ReadFile(global.Path)
|
||||||
|
if err != nil || !bytes.Equal(current, original) {
|
||||||
|
t.Fatalf("switching applications saved the override: %v", err)
|
||||||
|
}
|
||||||
|
// A remote session change and the speech-save shortcut must not promote
|
||||||
|
// the startup keyboard override into global or cached profile settings.
|
||||||
|
next := worker.settings
|
||||||
|
next.EnableKeyEcho = true
|
||||||
|
if response := worker.applyNext(t.Context(), next, false, false); !response.Accepted {
|
||||||
|
t.Fatal(response.Message)
|
||||||
|
}
|
||||||
|
worker.cycle_progress_output()
|
||||||
|
cached := worker.appSettings[worker.activeApp]
|
||||||
|
if cached.KeyboardLayout != app.KeyboardLayout || !reflect.DeepEqual(cached.CthulhuModifierKeys, app.CthulhuModifierKeys) {
|
||||||
|
t.Fatal("session changes cached the startup keyboard in application settings")
|
||||||
|
}
|
||||||
|
worker.handleSpeechCommand(t.Context(), input.IncreaseSpeechSetting)
|
||||||
|
worker.handleSpeechCommand(t.Context(), input.SaveSpeechSettings)
|
||||||
|
loaded, err := store.Load()
|
||||||
|
if err != nil || loaded.KeyboardLayout != global.KeyboardLayout || !reflect.DeepEqual(loaded.CthulhuModifierKeys, global.CthulhuModifierKeys) {
|
||||||
|
t.Fatalf("speech save changed the saved keyboard: %v", err)
|
||||||
|
}
|
||||||
|
worker.switchApplication(t.Context(), "Other Application")
|
||||||
|
worker.switchApplication(t.Context(), "New Application")
|
||||||
|
checkLaptop(worker.settings)
|
||||||
|
if !worker.settings.EnableKeyEcho {
|
||||||
|
t.Fatal("remote application change was lost")
|
||||||
|
}
|
||||||
|
if !worker.beginEdit(t.Context(), "") {
|
||||||
|
t.Fatal("could not open global preferences")
|
||||||
|
}
|
||||||
|
checkLaptop(worker.editing)
|
||||||
|
values := preferences.FromSettings(worker.editing)
|
||||||
|
values.KeyboardLayout = global.KeyboardLayout
|
||||||
|
values.CthulhuModifierKeys = global.CthulhuModifierKeys
|
||||||
|
recorder.err = errors.New("grab conflict")
|
||||||
|
if response := worker.apply(t.Context(), preferences.Request{Values: values}); response.Accepted || !worker.laptopLayout {
|
||||||
|
t.Fatal("failed preferences apply discarded the startup override")
|
||||||
|
}
|
||||||
|
checkLaptop(worker.settings)
|
||||||
|
// Saving the displayed laptop choice explicitly makes it permanent.
|
||||||
|
recorder.err = nil
|
||||||
|
values = preferences.FromSettings(worker.editing)
|
||||||
|
if response := worker.apply(t.Context(), preferences.Request{Values: values, Save: true}); !response.Accepted || worker.laptopLayout {
|
||||||
|
t.Fatalf("explicit save did not replace the startup override: %+v", response)
|
||||||
|
}
|
||||||
|
loaded, err = store.Load()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
checkLaptop(loaded)
|
||||||
|
worker.editingActive = false
|
||||||
|
if !worker.beginEdit(t.Context(), "") {
|
||||||
|
t.Fatal("could not reopen preferences")
|
||||||
|
}
|
||||||
|
values = preferences.FromSettings(worker.editing)
|
||||||
|
values.KeyboardLayout = global.KeyboardLayout
|
||||||
|
values.CthulhuModifierKeys = global.CthulhuModifierKeys
|
||||||
|
if response := worker.apply(t.Context(), preferences.Request{Values: values}); !response.Accepted {
|
||||||
|
t.Fatal(response.Message)
|
||||||
|
}
|
||||||
|
worker.editingActive = false
|
||||||
|
worker.switchApplication(t.Context(), "Another Application")
|
||||||
|
if worker.settings.KeyboardLayout != global.KeyboardLayout || !reflect.DeepEqual(worker.settings.CthulhuModifierKeys, global.CthulhuModifierKeys) {
|
||||||
|
t.Fatal("preferences could not replace the laptop keyboard for the session")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ type preferencesWorker struct {
|
|||||||
globalSettings config.Settings
|
globalSettings config.Settings
|
||||||
appSettings map[string]config.Settings
|
appSettings map[string]config.Settings
|
||||||
quickSpeech quickSpeechSettings
|
quickSpeech quickSpeechSettings
|
||||||
|
laptopLayout bool
|
||||||
activeApp string
|
activeApp string
|
||||||
editApp string
|
editApp string
|
||||||
editing config.Settings
|
editing config.Settings
|
||||||
|
|||||||
@@ -9,8 +9,38 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.stormux.org/storm/cthulhu/internal/config"
|
"git.stormux.org/storm/cthulhu/internal/config"
|
||||||
|
"git.stormux.org/storm/cthulhu/internal/input"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func laptopSettings(settings config.Settings) config.Settings {
|
||||||
|
settings.KeyboardLayout = int(input.LaptopKeyboardLayout)
|
||||||
|
settings.CthulhuModifierKeys = []string{"Caps_Lock"}
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the startup keyboard choice out of profile settings and speech saves.
|
||||||
|
// Explicit preferences Apply replaces it; otherwise it lasts until exit.
|
||||||
|
func (worker *preferencesWorker) sessionKeyboard(settings config.Settings) config.Settings {
|
||||||
|
if worker.laptopLayout {
|
||||||
|
return laptopSettings(settings)
|
||||||
|
}
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortcut and remote changes start from runtime settings. Keep the profile's
|
||||||
|
// keyboard choice beneath the startup override when caching those changes.
|
||||||
|
func (worker *preferencesWorker) retainProfileKeyboard(settings config.Settings, application string) config.Settings {
|
||||||
|
if worker.laptopLayout {
|
||||||
|
base := worker.globalSettings
|
||||||
|
if cached, ok := worker.appSettings[application]; ok {
|
||||||
|
base = cached
|
||||||
|
}
|
||||||
|
settings.KeyboardLayout = base.KeyboardLayout
|
||||||
|
settings.CthulhuModifierKeys = append([]string(nil), base.CthulhuModifierKeys...)
|
||||||
|
}
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
func (worker *preferencesWorker) applicationSettings(application string) (config.Settings, error) {
|
func (worker *preferencesWorker) applicationSettings(application string) (config.Settings, error) {
|
||||||
if settings, ok := worker.appSettings[application]; ok {
|
if settings, ok := worker.appSettings[application]; ok {
|
||||||
return worker.quickSpeech.apply(settings), nil
|
return worker.quickSpeech.apply(settings), nil
|
||||||
@@ -42,6 +72,7 @@ func (worker *preferencesWorker) switchApplication(ctx context.Context, applicat
|
|||||||
}
|
}
|
||||||
settings, err := worker.applicationSettings(application)
|
settings, err := worker.applicationSettings(application)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
settings = worker.sessionKeyboard(settings)
|
||||||
err = worker.applyRuntime(ctx, settings)
|
err = worker.applyRuntime(ctx, settings)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,5 +114,6 @@ func (worker *preferencesWorker) beginEdit(ctx context.Context, application stri
|
|||||||
}
|
}
|
||||||
worker.editing = settings
|
worker.editing = settings
|
||||||
}
|
}
|
||||||
|
worker.editing = worker.sessionKeyboard(worker.editing)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,10 @@ func (worker *preferencesWorker) applyNext(ctx context.Context, next config.Sett
|
|||||||
if err := worker.applyRuntime(ctx, next); err != nil {
|
if err := worker.applyRuntime(ctx, next); err != nil {
|
||||||
return worker.response(err.Error(), false)
|
return worker.response(err.Error(), false)
|
||||||
}
|
}
|
||||||
|
if worker.editingActive {
|
||||||
|
worker.laptopLayout = false
|
||||||
|
}
|
||||||
|
next = worker.retainProfileKeyboard(next, scopeApp)
|
||||||
// An explicit preferences Apply replaces the session's quick speech choices.
|
// An explicit preferences Apply replaces the session's quick speech choices.
|
||||||
if worker.editingActive {
|
if worker.editingActive {
|
||||||
worker.quickSpeech = quickSpeechSettings{}
|
worker.quickSpeech = quickSpeechSettings{}
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ func (worker *preferencesWorker) cycle_progress_output() {
|
|||||||
default:
|
default:
|
||||||
next.ProgressBar.OutputMode, message = "both", "Beep and speak progress bar updates"
|
next.ProgressBar.OutputMode, message = "both", "Beep and speak progress bar updates"
|
||||||
}
|
}
|
||||||
|
profileNext := worker.retainProfileKeyboard(next, worker.activeApp)
|
||||||
if worker.activeApp != "" {
|
if worker.activeApp != "" {
|
||||||
worker.appSettings[worker.activeApp] = next
|
worker.appSettings[worker.activeApp] = profileNext
|
||||||
} else {
|
} else {
|
||||||
for application, settings := range worker.appSettings {
|
for application, settings := range worker.appSettings {
|
||||||
worker.appSettings[application] = config.RebaseApplicationSettings(worker.globalSettings, next, settings)
|
worker.appSettings[application] = config.RebaseApplicationSettings(worker.globalSettings, profileNext, settings)
|
||||||
}
|
}
|
||||||
worker.globalSettings = next
|
worker.globalSettings = profileNext
|
||||||
}
|
}
|
||||||
worker.commit_settings(next)
|
worker.commit_settings(next)
|
||||||
worker.announceSpeechSetting(message)
|
worker.announceSpeechSetting(message)
|
||||||
|
|||||||
Reference in new issue
Block a user