G12: honor Enable Touch Workspace preference

Switch to the Touch built-in workspace when the preference is on and a touch
screen is present; restore the prior workspace when it is turned off.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
nrq6993-a11y
2026-10-21 23:38:03 +07:00
committed by bflatastic
co-authored by Cursor
parent cc4836abb7
commit 1c7b02a6fe
5 changed files with 84 additions and 1 deletions
+11
View File
@@ -1370,6 +1370,17 @@ fn show_font_names_in_english_preference_is_stored() {
assert!(s.prefs.font_names_in_english);
}
/// Preferences › Devices › Enable Touch Workspace (#394): stored and restored through `prefs.set`.
#[test]
fn touch_workspace_preference_is_stored() {
let mut s = Session::new();
assert!(s.prefs.touch_workspace, "on by default");
set_pref(&mut s, "touchWorkspace", json!(false));
assert!(!s.prefs.touch_workspace);
set_pref(&mut s, "touchWorkspace", json!(true));
assert!(s.prefs.touch_workspace);
}
/// Preferences › Type › Highlight Alternate Glyphs (#394): off by default so OpenType
/// substitutions are not pink on every canvas until the user turns the preference on.
#[test]
+3
View File
@@ -514,6 +514,8 @@ pub struct VectorcraftApp {
pub(crate) ime_discard: bool,
/// Preferences were confirmed (see [`Self::take_prefs_changed`]).
pub(crate) prefs_changed: bool,
/// Whether the last frame's input reported a touch screen (Preferences › Devices › Touch Workspace).
pub touch_screen: bool,
/// A numeric field is being scrubbed: the document's edits meanwhile are one undo step
/// ([`scrub::begin_frame`]).
scrub_group: bool,
@@ -623,6 +625,7 @@ impl VectorcraftApp {
ime_marked: None,
ime_discard: false,
prefs_changed: false,
touch_screen: false,
scrub_group: false,
scrub_scope: None,
automation_roots: None,
+9
View File
@@ -39,7 +39,11 @@ pub fn open(app: &mut VectorcraftApp, category: Option<&str>) {
pub fn confirm(app: &mut VectorcraftApp) -> Result<Value, String> {
let Some(d) = app.ui.dialog.clone() else { return Err("no dialog open".into()) };
let values: Map<String, Value> = d.fields.iter().filter(|(k, _)| !k.starts_with("__")).map(|(k, v)| (k.clone(), v.clone())).collect();
let touch_ws = values.get("touchWorkspace").and_then(Value::as_bool);
app.run("prefs.set", json!({ "values": values }))?;
if touch_ws.is_some() {
crate::workspaces::sync_touch_workspace(app, app.touch_screen);
}
app.ui.view.smart_guides = d.fields.get("__smartGuides").and_then(Value::as_bool).unwrap_or(app.ui.view.smart_guides);
app.ui.view.snap_to_grid = d.fields.get("__snapToGrid").and_then(Value::as_bool).unwrap_or(app.ui.view.snap_to_grid);
app.ui.task_bar = d.fields.get("__taskBar").and_then(Value::as_bool).unwrap_or(app.ui.task_bar);
@@ -149,6 +153,11 @@ pub fn apply_runtime(app: &mut VectorcraftApp, ctx: &egui::Context) {
if (ctx.zoom_factor() - z).abs() > 1e-3 {
ctx.set_zoom_factor(z);
}
let touch = ctx.input(|i| i.has_touch_screen());
if touch != app.touch_screen {
app.touch_screen = touch;
crate::workspaces::sync_touch_workspace(app, touch);
}
}
pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
+4
View File
@@ -422,6 +422,9 @@ pub struct UiState {
/// Current workspace (Window → Workspace).
#[serde(default = "default_workspace")]
pub workspace: String,
/// Workspace before Preferences › Devices › Enable Touch Workspace switched to Touch (#394).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub touch_workspace_restore: Option<String>,
/// User-saved workspaces (New Workspace…).
#[serde(default)]
pub custom_workspaces: Vec<crate::workspaces::Workspace>,
@@ -824,6 +827,7 @@ impl Default for UiState {
shortcut_overrides: Default::default(),
shortcut_set: default_shortcut_set(),
workspace: default_workspace(),
touch_workspace_restore: None,
custom_workspaces: vec![],
recent_files: vec![],
recent_fonts: vec![],
+57 -1
View File
@@ -54,6 +54,8 @@ impl Default for Workspace {
}
pub const ESSENTIALS: &str = "Essentials";
/// Touch workspace (Window → Workspace → Touch; Preferences › Devices › Enable Touch Workspace).
pub const TOUCH: &str = "Touch";
/// Built-in workspaces, in Illustrator's menu order (Essentials first).
pub fn builtins() -> Vec<Workspace> {
@@ -115,9 +117,45 @@ pub fn builtins() -> Vec<Workspace> {
x.toolbar_advanced = true;
x.open_panel = Some("symbols".into());
}),
w(TOUCH, &|x| {
x.control_bar = true;
x.toolbar = true;
x.toolbar_advanced = true;
x.task_bar = true;
x.open_panel = Some("align".into());
}),
]
}
/// Preferences › Devices › Enable Touch Workspace (#394): on, a touch screen switches to the Touch
/// workspace; off, or when no touch screen is reported, the workspace before that switch is
/// restored if Touch was entered automatically.
pub fn sync_touch_workspace(app: &mut VectorcraftApp, touch_screen: bool) {
let auto = app.session.prefs.touch_workspace && touch_screen;
if auto {
if app.ui.workspace != TOUCH {
if app.ui.touch_workspace_restore.is_none() {
app.ui.touch_workspace_restore = Some(app.ui.workspace.clone());
}
if let Some(w) = find(&app.ui, TOUCH) {
apply(&mut app.ui, &w);
}
}
} else if app.ui.touch_workspace_restore.is_some() && app.ui.workspace == TOUCH {
let back = app
.ui
.touch_workspace_restore
.take()
.filter(|n| find(&app.ui, n).is_some())
.unwrap_or_else(|| ESSENTIALS.to_string());
if let Some(w) = find(&app.ui, &back) {
apply(&mut app.ui, &w);
}
} else if !auto {
app.ui.touch_workspace_restore = None;
}
}
pub fn is_builtin(name: &str) -> bool {
builtins().iter().any(|w| w.name == name)
}
@@ -493,11 +531,29 @@ mod tests {
#[test]
fn all_requested_workspaces_exist() {
let ui = UiState::default();
for n in ["Essentials", "Essentials Classic", "Painting", "Typography", "Layout", "Tracing", "Web", "Automation"] {
for n in ["Essentials", "Essentials Classic", "Painting", "Typography", "Layout", "Tracing", "Web", "Automation", TOUCH] {
assert!(find(&ui, n).is_some(), "{n}");
}
}
#[test]
fn touch_workspace_preference_switches_and_restores() {
use crate::{Services, VectorcraftApp};
use vectorcraft_engine::Session;
let mut app = VectorcraftApp::new(Session::new(), Services::default());
app.ui.workspace = "Typography".into();
app.session.prefs.touch_workspace = true;
sync_touch_workspace(&mut app, true);
assert_eq!(app.ui.workspace, TOUCH);
assert_eq!(app.ui.touch_workspace_restore.as_deref(), Some("Typography"));
assert!(app.ui.control_bar && app.ui.open_panel.as_deref() == Some("align"));
app.session.prefs.touch_workspace = false;
sync_touch_workspace(&mut app, true);
assert_eq!(app.ui.workspace, "Typography");
assert!(app.ui.touch_workspace_restore.is_none());
}
#[test]
fn saved_workspaces_restore_dock_width() {
let mut ui = UiState { dock_width: Some(420.0), ..Default::default() };