diff --git a/src/input.rs b/src/input.rs index 5c32b205864c174a19c729264ad420f13c797e2c..3e1b84ebf95d310d32fa158b3401d89edb4c6a8d 100644 --- a/src/input.rs +++ b/src/input.rs @@ -22,8 +22,8 @@ use wasm_bindgen_futures::JsFuture; use crate::{ get_node_cursor_pos, get_timestamp, get_x_offset_center, get_y_offset_center, save_edit_history, CosmicAttrs, CosmicEditHistory, CosmicEditor, CosmicFontSystem, - CosmicMaxChars, CosmicMaxLines, CosmicText, CosmicTextChanged, CosmicTextPosition, Focus, - PasswordInput, ReadOnly, XOffset, + CosmicMaxChars, CosmicMaxLines, CosmicTextChanged, CosmicTextPosition, Focus, ReadOnly, + XOffset, }; #[derive(Resource)] @@ -49,14 +49,12 @@ pub(crate) fn input_mouse( buttons: Res<Input<MouseButton>>, mut cosmic_edit_query: Query<( &mut CosmicEditor, - &CosmicAttrs, &GlobalTransform, &CosmicTextPosition, Entity, &XOffset, Option<&mut Node>, Option<&mut Sprite>, - Option<&PasswordInput>, )>, mut font_system: ResMut<CosmicFontSystem>, mut scroll_evr: EventReader<MouseWheel>, @@ -88,41 +86,13 @@ pub(crate) fn input_mouse( let primary_window = windows.single(); let scale_factor = primary_window.scale_factor() as f32; let (camera, camera_transform) = camera_q.iter().find(|(c, _)| c.is_active).unwrap(); - for ( - mut editor, - attrs, - node_transform, - text_position, - entity, - x_offset, - node_opt, - sprite_opt, - password_opt, - ) in &mut cosmic_edit_query.iter_mut() + for (mut editor, node_transform, text_position, entity, x_offset, node_opt, sprite_opt) in + &mut cosmic_edit_query.iter_mut() { if active_editor.0 != Some(entity) { continue; } - // hijack buffer contents - let current_text = editor.get_text(); - let current_select_opt = editor.0.select_opt().clone(); - let current_cursor = editor.0.cursor().clone(); - - // intercept text for password inputs - if let Some(password) = password_opt { - if !current_text.is_empty() { - editor.set_text( - CosmicText::OneStyle(format!("{}", password.0).repeat(current_text.len())), - attrs.0.clone(), - &mut font_system.0, - ); - - editor.0.set_select_opt(current_select_opt); - editor.0.set_cursor(current_cursor); - } - } - let (width, height, is_ui_node) = match node_opt { Some(node) => (node.size().x, node.size().y, true), None => { @@ -239,18 +209,6 @@ pub(crate) fn input_mouse( } } } - - // reset intercepted text - if password_opt.is_some() && !current_text.is_empty() { - editor.set_text( - crate::CosmicText::OneStyle(current_text), - attrs.0.clone(), - &mut font_system.0, - ); - - editor.0.set_select_opt(current_select_opt); - editor.0.set_cursor(current_cursor); - } } } diff --git a/src/lib.rs b/src/lib.rs index 0fdbb84aca597e394cf8255675296d57ca996c8f..e356ba627ee31c906d214cf7ef52776d9dafba6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,8 @@ use input::{input_kb, input_mouse, undo_redo, ClickTimer}; use input::{poll_wasm_paste, WasmPaste, WasmPasteAsyncChannel}; use render::{ blink_cursor, cosmic_edit_redraw_buffer, freeze_cursor_blink, hide_inactive_or_readonly_cursor, - on_scale_factor_change, set_initial_scale, CursorBlinkTimer, CursorVisibility, SwashCacheState, + hide_password_text, on_scale_factor_change, restore_password_text, set_initial_scale, + CursorBlinkTimer, CursorVisibility, PasswordStates, SwashCacheState, }; #[cfg(feature = "multicam")] @@ -314,23 +315,33 @@ impl Plugin for CosmicEditPlugin { .add_systems( Update, ( - init_history, - input_kb, - input_mouse, - undo_redo, - blink_cursor, - freeze_cursor_blink, - hide_inactive_or_readonly_cursor, - clear_inactive_selection, - render::update_handle_ui, - render::update_handle_sprite, + ( + init_history, + input_kb, + undo_redo, + blink_cursor, + freeze_cursor_blink, + hide_inactive_or_readonly_cursor, + clear_inactive_selection, + render::update_handle_ui, + render::update_handle_sprite, + ) + .before(hide_password_text), + hide_password_text, + input_mouse.after(hide_password_text), ), ) .add_systems( PostUpdate, - (cosmic_edit_redraw_buffer).after(TransformSystem::TransformPropagate), + ( + restore_password_text, + cosmic_edit_redraw_buffer + .after(TransformSystem::TransformPropagate) + .before(restore_password_text), + ), ) .init_resource::<Focus>() + .init_resource::<PasswordStates>() .insert_resource(CursorBlinkTimer(Timer::from_seconds( 0.53, TimerMode::Repeating, diff --git a/src/render.rs b/src/render.rs index 80b63e021f651b80f9c1dbbb835f8bc5e9d69b54..83d84b5c998f76116616efa51f8d2a93189ec2cb 100644 --- a/src/render.rs +++ b/src/render.rs @@ -4,6 +4,7 @@ use bevy::{ asset::HandleId, prelude::*, render::render_resource::Extent3d, + utils::HashMap, window::{PrimaryWindow, WindowScaleFactorChanged}, }; use cosmic_text::{Affinity, Edit, Metrics, SwashCache}; @@ -44,7 +45,6 @@ pub(crate) fn cosmic_edit_redraw_buffer( &mut XOffset, &CosmicMode, Option<&mut Placeholder>, - Option<&PasswordInput>, )>, mut font_system: ResMut<CosmicFontSystem>, ) { @@ -64,7 +64,6 @@ pub(crate) fn cosmic_edit_redraw_buffer( mut x_offset, mode, mut placeholder_opt, - password_opt, ) in &mut cosmic_edit_query.iter_mut() { if !cosmic_editor.0.buffer().redraw() { @@ -72,22 +71,6 @@ pub(crate) fn cosmic_edit_redraw_buffer( } let current_text = cosmic_editor.get_text(); - let current_select_opt = cosmic_editor.0.select_opt().clone(); - let current_cursor = cosmic_editor.0.cursor().clone(); - - // intercept text for password inputs - if let Some(password) = password_opt { - if !current_text.is_empty() { - cosmic_editor.set_text( - CosmicText::OneStyle(format!("{}", password.0).repeat(current_text.len())), - attrs.0.clone(), - &mut font_system.0, - ); - - cosmic_editor.0.set_select_opt(current_select_opt); - cosmic_editor.0.set_cursor(current_cursor); - } - } // Check for placeholder, replace editor if found and buffer is empty let editor = if current_text.is_empty() && placeholder_opt.is_some() { @@ -283,18 +266,6 @@ pub(crate) fn cosmic_edit_redraw_buffer( } editor.buffer_mut().set_redraw(false); - - // reset intercepted text - if password_opt.is_some() && !current_text.is_empty() { - cosmic_editor.set_text( - crate::CosmicText::OneStyle(current_text), - attrs.0.clone(), - &mut font_system.0, - ); - - cosmic_editor.0.set_select_opt(current_select_opt); - cosmic_editor.0.set_cursor(current_cursor); - } } } @@ -527,3 +498,55 @@ pub(crate) fn update_handle_sprite( *handle = canvas.0.clone_weak(); } } + +#[derive(Resource, Default)] +pub(crate) struct PasswordStates(pub HashMap<Entity, String>); + +pub(crate) fn hide_password_text( + mut editor_q: Query<(Entity, &mut CosmicEditor, &CosmicAttrs, &PasswordInput)>, + mut font_system: ResMut<CosmicFontSystem>, + mut password_input_states: ResMut<PasswordStates>, +) { + for (entity, mut cosmic_editor, attrs, password) in editor_q.iter_mut() { + let text = cosmic_editor.get_text(); + let select_opt = cosmic_editor.0.select_opt(); + let cursor = cosmic_editor.0.cursor(); + + if !text.is_empty() { + cosmic_editor.set_text( + CosmicText::OneStyle(format!("{}", password.0).repeat(text.len())), + attrs.0.clone(), + &mut font_system.0, + ); + + cosmic_editor.0.set_select_opt(select_opt); + cosmic_editor.0.set_cursor(cursor); + } + + password_input_states.0.insert(entity, text); + } +} + +pub(crate) fn restore_password_text( + mut editor_q: Query<(Entity, &mut CosmicEditor, &CosmicAttrs), With<PasswordInput>>, + mut font_system: ResMut<CosmicFontSystem>, + password_input_states: Res<PasswordStates>, +) { + for (entity, mut cosmic_editor, attrs) in editor_q.iter_mut() { + if let Some(text) = password_input_states.0.get(&entity) { + // reset intercepted text + if !text.is_empty() { + let cursor = cosmic_editor.0.cursor(); + let select_opt = cosmic_editor.0.select_opt(); + cosmic_editor.set_text( + crate::CosmicText::OneStyle(text.clone()), + attrs.0.clone(), + &mut font_system.0, + ); + + cosmic_editor.0.set_select_opt(select_opt); + cosmic_editor.0.set_cursor(cursor); + } + } + } +}