From a6f4b5ac0ab1c3d72f50326933af1b0022f35d75 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 14 May 2025 23:27:12 +0200 Subject: [PATCH] android changes taken from ibaryshnikov --- core/src/text/editor.rs | 4 ++++ core/src/theme.rs | 19 ------------------ graphics/src/text.rs | 33 ++++++++++++++++++++++--------- graphics/src/text/editor.rs | 2 ++ widget/src/text/rich.rs | 39 +++++++++++++++++++++++++++++++++++++ widget/src/text_editor.rs | 37 +++++++++++++++++++++++++++++++++++ winit/src/conversion.rs | 27 ++++++++++++++++++++++--- 7 files changed, 130 insertions(+), 31 deletions(-) diff --git a/core/src/text/editor.rs b/core/src/text/editor.rs index 6921c61c..946b1505 100644 --- a/core/src/text/editor.rs +++ b/core/src/text/editor.rs @@ -88,6 +88,10 @@ pub enum Action { /// The amount of lines to scroll. lines: i32, }, + /// Editor gained focus + Focus, + /// Editor lost focus + Blur, } impl Action { diff --git a/core/src/theme.rs b/core/src/theme.rs index a0ec538b..32976929 100644 --- a/core/src/theme.rs +++ b/core/src/theme.rs @@ -164,25 +164,6 @@ impl Theme { impl Default for Theme { fn default() -> Self { - #[cfg(feature = "auto-detect-theme")] - { - use std::sync::LazyLock; - - static DEFAULT: LazyLock = LazyLock::new(|| { - match dark_light::detect() - .unwrap_or(dark_light::Mode::Unspecified) - { - dark_light::Mode::Dark => Theme::Dark, - dark_light::Mode::Light | dark_light::Mode::Unspecified => { - Theme::Light - } - } - }); - - DEFAULT.clone() - } - - #[cfg(not(feature = "auto-detect-theme"))] Theme::Light } } diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 507ef178..7ccb2317 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -159,16 +159,31 @@ pub fn font_system() -> &'static RwLock { static FONT_SYSTEM: OnceLock> = OnceLock::new(); FONT_SYSTEM.get_or_init(|| { + #[allow(unused_mut)] + let mut raw = cosmic_text::FontSystem::new_with_fonts([ + cosmic_text::fontdb::Source::Binary(Arc::new( + include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), + )), + #[cfg(all(target_arch = "wasm32", feature = "fira-sans"))] + cosmic_text::fontdb::Source::Binary(Arc::new( + include_bytes!("../fonts/FiraSans-Regular.ttf").as_slice(), + )), + ]); + + // Load system fonts for Android + // https://github.com/pop-os/cosmic-text/issues/243#issue-2189977938 + #[cfg(target_os = "android")] + { + raw.db_mut().load_fonts_dir("/system/fonts"); + raw.db_mut().set_sans_serif_family("Roboto"); + raw.db_mut().set_serif_family("Noto Serif"); + raw.db_mut().set_monospace_family("Droid Sans Mono"); // Cutive Mono looks more printer-like + raw.db_mut().set_cursive_family("Dancing Script"); + raw.db_mut().set_fantasy_family("Dancing Script"); + } + RwLock::new(FontSystem { - raw: cosmic_text::FontSystem::new_with_fonts([ - cosmic_text::fontdb::Source::Binary(Arc::new( - include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), - )), - #[cfg(feature = "fira-sans")] - cosmic_text::fontdb::Source::Binary(Arc::new( - include_bytes!("../fonts/FiraSans-Regular.ttf").as_slice(), - )), - ]), + raw, loaded_fonts: HashSet::new(), version: Version::default(), }) diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs index aaf46a6a..a9335eee 100644 --- a/graphics/src/text/editor.rs +++ b/graphics/src/text/editor.rs @@ -438,6 +438,8 @@ impl editor::Editor for Editor { cosmic_text::Action::Scroll { lines }, ); } + // Do nothing, these are for user convenience only + Action::Focus | Action::Blur => {} } self.0 = Some(Arc::new(internal)); diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs index f1b2c75e..1b53eed9 100644 --- a/widget/src/text/rich.rs +++ b/widget/src/text/rich.rs @@ -421,6 +421,45 @@ where shell.capture_event(); } } + // Event::Touch(touch::Event::FingerPressed { position, .. }) => { + // if layout.bounds().contains(*position) { + // println!("Hey"); + // let state = tree + // .state + // .downcast_mut::>(); + // + // self.hovered_link = + // state.paragraph.hit_span(*position).and_then(|span| { + // if self + // .spans + // .as_ref() + // .as_ref() + // .get(span)? + // .link + // .is_some() + // { + // Some(span) + // } else { + // None + // } + // }); + // state.span_pressed = self.hovered_link; + // shell.capture_event(); + // if let Some(span) = self.hovered_link { + // if let Some(link) = self + // .spans + // .as_ref() + // .as_ref() + // .get(span) + // .and_then(|span| span.link.clone()) + // { + // shell.publish(on_link_clicked(link)); + // } + // } + // + // state.span_pressed = None; + // } + // } Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => { let state = tree .state diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 4c2b101f..9aadd467 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -43,6 +43,7 @@ use crate::core::text::editor::{Cursor, Editor as _}; use crate::core::text::highlighter::{self, Highlighter}; use crate::core::text::{self, LineHeight, Text, Wrapping}; use crate::core::time::{Duration, Instant}; +use crate::core::touch; use crate::core::widget::operation; use crate::core::widget::{self, Widget}; use crate::core::window; @@ -719,6 +720,10 @@ where mouse::click::Kind::Triple => Action::SelectLine, }; + if !state.is_focused() { + shell.publish(on_edit(Action::Focus)); + } + state.focus = Some(Focus::now()); state.last_click = Some(click); state.drag_click = Some(click.kind()); @@ -789,6 +794,7 @@ where Binding::Unfocus => { state.focus = None; state.drag_click = None; + shell.publish(on_edit(Action::Blur)); } Binding::Copy => { if let Some(selection) = content.selection() { @@ -1295,6 +1301,37 @@ impl Update { } _ => None, }, + Event::Touch(event) => match event { + touch::Event::FingerPressed { .. } => { + if let Some(cursor_position) = cursor.position_in(bounds) { + let cursor_position = cursor_position + - Vector::new(padding.top, padding.left); + + let click = mouse::Click::new( + cursor_position, + mouse::Button::Left, + state.last_click, + ); + + Some(Update::Click(click)) + } else if state.focus.is_some() { + binding(Binding::Unfocus) + } else { + None + } + } + touch::Event::FingerLifted { .. } + | touch::Event::FingerLost { .. } => Some(Update::Release), + touch::Event::FingerMoved { .. } => match state.drag_click { + Some(mouse::click::Kind::Single) => { + let cursor_position = cursor.position_in(bounds)? + - Vector::new(padding.top, padding.left); + + Some(Update::Drag(cursor_position)) + } + _ => None, + }, + }, Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index ab84afff..0fcdd8c1 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -203,13 +203,19 @@ pub fn window_event( WindowEvent::KeyboardInput { is_synthetic, .. } if is_synthetic => None, WindowEvent::KeyboardInput { event, .. } => Some(Event::Keyboard({ let key = { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(any( + target_arch = "wasm32", + target_os = "android", + )))] { use winit::platform::modifier_supplement::KeyEventExtModifierSupplement; event.key_without_modifiers() } - #[cfg(target_arch = "wasm32")] + #[cfg(any( + target_arch = "wasm32", + target_os = "android", + ))] { // TODO: Fix inconsistent API on Wasm event.logical_key.clone() @@ -217,7 +223,10 @@ pub fn window_event( }; let text = { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(any( + target_arch = "wasm32", + target_os = "android", + )))] { use crate::core::SmolStr; use winit::platform::modifier_supplement::KeyEventExtModifierSupplement; @@ -225,6 +234,18 @@ pub fn window_event( event.text_with_all_modifiers().map(SmolStr::new) } + #[cfg(target_os = "android")] + { + if event.text.is_some() { + event.text + } else { + match &key { + winit::keyboard::Key::Character(c) => Some(c.clone()), + _ => None, + } + } + } + #[cfg(target_arch = "wasm32")] { // TODO: Fix inconsistent API on Wasm