diff --git a/src-tauri/src/scan_keyboard.rs b/src-tauri/src/scan_keyboard.rs index 42bab72c..c7099815 100644 --- a/src-tauri/src/scan_keyboard.rs +++ b/src-tauri/src/scan_keyboard.rs @@ -229,7 +229,8 @@ fn rows_for(page: Page, mac: bool, layout: crate::point_scan::KeyboardLayout) -> middle.push(N("Enter")); let mut bottom = vec![Key::Modifier(0)]; bottom.extend(letters("zxcvbnm")); - bottom.push(C(' ', ' ')); + // A full stop that stays one with Shift or Caps on. + bottom.extend([C('.', '.'), C(' ', ' ')]); return vec![ top, middle, @@ -2107,7 +2108,7 @@ mod tests { middle.push(Key::Named("Enter")); let mut bottom = vec![Key::Modifier(0)]; bottom.extend(line("zxcvbnm")); - bottom.push(Key::Character(' ', ' ')); + bottom.extend([Key::Character('.', '.'), Key::Character(' ', ' ')]); assert_eq!(&letters[..3], &[top, middle, bottom]); assert_eq!(letters.len(), 4); assert!(letters[3].contains(&Key::Layout)); @@ -2166,6 +2167,45 @@ mod tests { assert_eq!(keyboard.rows.len(), 5); } #[test] + fn simple_qwerty_letters_full_stop_stays_a_full_stop_and_starts_a_sentence() { + use crate::point_scan::KeyboardLayout; + let full_stop = Key::Character('.', '.'); + let mut keyboard = Keyboard::new(false).with_layout(KeyboardLayout::SimpleQwerty); + assert!(keyboard.rows.iter().flatten().any(|key| *key == full_stop)); + let expect_full_stop = |keyboard: &mut Keyboard| { + assert_eq!(keyboard.label(full_stop), "."); + assert!(matches!( + keyboard.choose_with_context(full_stop, context(1)), + Some(Output::Punctuation(p)) if p.mark == '.' + )); + keyboard.succeeded_with_context(context(1)); + }; + // Plain, then at a sentence start with the automatic Shift on. + expect_full_stop(&mut keyboard); + assert!(keyboard.capitalize_next); + assert_eq!(keyboard.modifiers[0], Modifier::Once); + expect_full_stop(&mut keyboard); + assert!(matches!( + keyboard.choose_with_context(Key::Character('a', 'A'), context(1)), + Some(Output::Stroke(stroke)) if stroke.character() == Some('A') + )); + keyboard.succeeded_with_context(context(1)); + assert!(!keyboard.capitalize_next); + // With a Shift the user chose. + keyboard.choose_with_context(Key::Modifier(0), context(1)); + expect_full_stop(&mut keyboard); + assert!(matches!( + keyboard.choose_with_context(Key::Character('b', 'B'), context(1)), + Some(Output::Stroke(stroke)) if stroke.character() == Some('B') + )); + keyboard.succeeded_with_context(context(1)); + // With Caps on. + keyboard.reset_context(); + keyboard.choose_with_context(Key::Caps, context(1)); + expect_full_stop(&mut keyboard); + assert!(keyboard.capitalize_next); + } + #[test] fn simple_qwerty_prose_punctuation_on_numbers_keeps_decimal_literal() { use crate::point_scan::KeyboardLayout; let mut keyboard = Keyboard::new(false).with_layout(KeyboardLayout::SimpleQwerty); diff --git a/src/settings/ScannerPreferences.tsx b/src/settings/ScannerPreferences.tsx index 6310c29a..0e3df5f5 100644 --- a/src/settings/ScannerPreferences.tsx +++ b/src/settings/ScannerPreferences.tsx @@ -158,7 +158,7 @@ export function ScannerPreferences({ controller, settings: appSettings, onSettin } {area === 'keyboard' && <> - + legend="Keyboard layout" disabled={disabled || !!pending} @@ -177,7 +177,7 @@ export function ScannerPreferences({ controller, settings: appSettings, onSettin />

Simple QWERTY keeps the letter order with fewer keys on its Letters page. Common letters first puts frequent English letters and Space early in row scanning. The keyboard footer cycles through all three layouts; the choice is saved.

-

The scanning keyboard spaces prose punctuation for you. In Simple QWERTY, those marks are on Numbers; the separate numeric period stays a decimal point. Period, question mark, and exclamation mark capitalize the next letter.

+

The scanning keyboard spaces prose punctuation for you. In Simple QWERTY, the full stop is also on Letters and the other marks are on Numbers; the separate numeric period stays a decimal point. Period, question mark, and exclamation mark capitalize the next letter.

} {(area === 'keyboard' || area === 'mouse' || area === 'menu') && update('panelAvoidsPointer', value)} /> diff --git a/src/settings/ScanningSection.tsx b/src/settings/ScanningSection.tsx index 138e7a77..c6f75f44 100644 --- a/src/settings/ScanningSection.tsx +++ b/src/settings/ScanningSection.tsx @@ -45,7 +45,7 @@ export function ScanningSection({ controller, settings, onSettingsChange }: { co

Choose Mouse from Home or the Point action menu, or assign Open mouse to a switch. Mouse has an Actions tile for editing, windows, browser, media and other commands, so you can stay in Mouse. Modified clicks use the current pointer position. Choose Switch to Point in the Mouse panel or assign Open point to a switch. Stop scanning or Escape ends the session without changing the mode Select continues in next time.

In Mouse, select a direction to move with the saved pointer speed and Remote repeat settings. {mouseRepeatStopInstruction(config)} repeating and scan the panel again. If repeat is off, each selection moves one step.

Assign switch actions in the Switches page. Actions run on release; holding a switch pauses the scan highlight. During repeating Mouse movement, scrolling or keys, {config.mouseRepeatStopEdge === "press" ? "the first switch press stops the action" : "the stop switch keeps the action going until release"}; the stop gesture ignores assigned actions. Manual scanning needs Select, Next and Previous. After clicking or reaching the pass limit, use Select to start again.

-

The scanning keyboard offers QWERTY, Simple QWERTY, and Common letters first. Simple QWERTY keeps three letter rows with punctuation on Numbers. Choose a saved layout in Keyboard settings or cycle layouts from the keyboard footer while typing.

+

The scanning keyboard offers QWERTY, Simple QWERTY, and Common letters first. Simple QWERTY keeps three letter rows with a full stop beside M and other punctuation on Numbers. Choose a saved layout in Keyboard settings or cycle layouts from the keyboard footer while typing.

Assigned keys stay reserved while Switchify runs. Escape resets the scan. Mobile connections pause local scanning until they end.

On Windows, assigned keys remain switches with Shift, Ctrl, Alt or Windows held, even in the background. Other keys and Switchify-generated shortcuts still work normally.