From 4d4f754318998ea3318ffab15fb96d04b3d33e81 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 6 Oct 2025 11:02:11 +0200 Subject: [PATCH 1/3] i18n: translation updates from weblate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aindriú Mac Giolla Eoin Co-authored-by: Aliaksandr Truš Co-authored-by: Fedorov Alexei Co-authored-by: Hosted Weblate Co-authored-by: Priit Jõerüüt Co-authored-by: Yago Raña Gayoso Co-authored-by: mikenu Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/ Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/be/ Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/es/ Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/et/ Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/ga/ Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/ja/ Translate-URL: https://hosted.weblate.org/projects/pop-os/libcosmic/ru/ Translation: Pop OS/libcosmic --- i18n/be/libcosmic.ftl | 8 ++++++++ i18n/es/libcosmic.ftl | 7 +++++++ i18n/et/libcosmic.ftl | 1 + i18n/ja/libcosmic.ftl | 8 ++++++++ i18n/ru/libcosmic.ftl | 8 ++++++++ i18n/sr-Cyrl/libcosmic.ftl | 6 ------ 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/i18n/be/libcosmic.ftl b/i18n/be/libcosmic.ftl index e69de29b..eb3abf33 100644 --- a/i18n/be/libcosmic.ftl +++ b/i18n/be/libcosmic.ftl @@ -0,0 +1,8 @@ +close = Закрыць +license = Ліцэнзія +links = Спасылкі +developers = Распрацоўшчыкі +designers = Дызайнеры +artists = Мастакі +translators = Перакладчыкі +documenters = Дакументалісты diff --git a/i18n/es/libcosmic.ftl b/i18n/es/libcosmic.ftl index e69de29b..6d30b5ad 100644 --- a/i18n/es/libcosmic.ftl +++ b/i18n/es/libcosmic.ftl @@ -0,0 +1,7 @@ +license = Licencia +links = Enlaces +developers = Desarrolladores +designers = Diseñadores +artists = Artistas +translators = Traductores +documenters = Documentadores diff --git a/i18n/et/libcosmic.ftl b/i18n/et/libcosmic.ftl index 1449e0af..38b16698 100644 --- a/i18n/et/libcosmic.ftl +++ b/i18n/et/libcosmic.ftl @@ -5,3 +5,4 @@ developers = Arendajad artists = Kunstnikud translators = Tõlkijad documenters = Dokumenteerijad +designers = Kujundajad diff --git a/i18n/ja/libcosmic.ftl b/i18n/ja/libcosmic.ftl index e69de29b..c6b9ed1a 100644 --- a/i18n/ja/libcosmic.ftl +++ b/i18n/ja/libcosmic.ftl @@ -0,0 +1,8 @@ +close = 閉じる +license = ライセンス +links = リンク +developers = 開発者 +designers = デザイナー +artists = アーティスト +translators = 翻訳者 +documenters = ドキュメント作成者 diff --git a/i18n/ru/libcosmic.ftl b/i18n/ru/libcosmic.ftl index e69de29b..0ef03fb1 100644 --- a/i18n/ru/libcosmic.ftl +++ b/i18n/ru/libcosmic.ftl @@ -0,0 +1,8 @@ +close = Закрыть +license = Лицензия +links = Ссылки +developers = Разработчики +designers = Дизайнеры +artists = Художники +translators = Переводчики +documenters = Авторы документации diff --git a/i18n/sr-Cyrl/libcosmic.ftl b/i18n/sr-Cyrl/libcosmic.ftl index 579392f4..30ed82d3 100644 --- a/i18n/sr-Cyrl/libcosmic.ftl +++ b/i18n/sr-Cyrl/libcosmic.ftl @@ -1,11 +1,5 @@ # Context Drawer close = Затвори - # About license = Лиценца links = Линкови -Developers = Програмери -Designers = Дизајнери -Artists = Уметници -Translators = Преводиоци -Documenters = Документатори From dc4e0edd7311152963c1574ee51540ae5b20e683 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Tue, 7 Oct 2025 13:28:42 -0400 Subject: [PATCH 2/3] fix(input): drag threshold --- src/widget/text_input/input.rs | 176 +++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 74 deletions(-) diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index ab38a718..fb889138 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -211,6 +211,7 @@ pub struct TextInput<'a, Message> { always_active: bool, /// The text input tracks and manages the input value in its state. manage_value: bool, + drag_threshold: f32, } impl<'a, Message> TextInput<'a, Message> @@ -259,6 +260,7 @@ where helper_text: None, always_active: false, manage_value: false, + drag_threshold: 20.0, } } @@ -557,6 +559,12 @@ where layout.children().next().unwrap() } } + + /// Set the drag threshold. + pub fn drag_threshold(mut self, drag_threshold: f32) -> Self { + self.drag_threshold = drag_threshold; + self + } } impl Widget for TextInput<'_, Message> @@ -926,6 +934,7 @@ where line_height, layout, self.manage_value, + self.drag_threshold, ) } @@ -1346,6 +1355,7 @@ pub fn update<'a, Message: Clone + 'static>( line_height: text::LineHeight, layout: Layout<'_>, manage_value: bool, + drag_threshold: f32, ) -> event::Status { let update_cache = |state, value| { replace_paragraph( @@ -1424,84 +1434,39 @@ pub fn update<'a, Message: Clone + 'static>( ) { #[cfg(feature = "wayland")] (None, click::Kind::Single, cursor::State::Selection { start, end }) => { - // if something is already selected, we can start a drag and drop for a - // single click that is on top of the selected text - // is the click on selected text? + let left = start.min(end); + let right = end.max(start); - if on_input.is_some() || manage_value { - let left = start.min(end); - let right = end.max(start); + let (left_position, _left_offset) = measure_cursor_and_scroll_offset( + state.value.raw(), + text_layout.bounds(), + left, + ); - let (left_position, _left_offset) = measure_cursor_and_scroll_offset( - state.value.raw(), - text_layout.bounds(), - left, - ); + let (right_position, _right_offset) = measure_cursor_and_scroll_offset( + state.value.raw(), + text_layout.bounds(), + right, + ); - let (right_position, _right_offset) = measure_cursor_and_scroll_offset( - state.value.raw(), - text_layout.bounds(), - right, - ); + let width = right_position - left_position; + let selection_bounds = Rectangle { + x: text_layout.bounds().x + left_position, + y: text_layout.bounds().y, + width, + height: text_layout.bounds().height, + }; - let width = right_position - left_position; - let selection_bounds = Rectangle { - x: text_layout.bounds().x + left_position, - y: text_layout.bounds().y, - width, - height: text_layout.bounds().height, - }; - - if cursor.is_over(selection_bounds) { - // XXX never start a dnd if the input is secure - if is_secure { - return event::Status::Ignored; - } - let input_text = - state.selected_text(&value.to_string()).unwrap_or_default(); - state.dragging_state = Some(DraggingState::Dnd( - DndAction::empty(), - input_text.clone(), - )); - let mut editor = Editor::new(unsecured_value, &mut state.cursor); - editor.delete(); - - let contents = editor.contents(); - let unsecured_value = Value::new(&contents); - state.tracked_value = unsecured_value.clone(); - if let Some(on_input) = on_input { - let message = (on_input)(contents); - shell.publish(message); - } - if let Some(on_start_dnd) = on_start_dnd_source { - shell.publish(on_start_dnd(state.clone())); - } - let state_clone = state.clone(); - - iced_core::clipboard::start_dnd( - clipboard, - false, - id.map(iced_core::clipboard::DndSource::Widget), - Some(iced_core::clipboard::IconSurface::new( - Element::from( - TextInput::<'static, ()>::new("", input_text.clone()) - .dnd_icon(true), - ), - iced_core::widget::tree::State::new(state_clone), - Vector::ZERO, - )), - Box::new(TextInputString(input_text)), - DndAction::Move, - ); - - update_cache(state, &unsecured_value); - } else { - update_cache(state, value); - state.setting_selection(value, text_layout.bounds(), target); - } - } else { - state.setting_selection(value, text_layout.bounds(), target); + if cursor.is_over(selection_bounds) && (on_input.is_some() || manage_value) + { + state.dragging_state = Some(DraggingState::PrepareDnd(cursor_position)); + return event::Status::Captured; } + // clear selection and place cursor at click position + update_cache(state, value); + state.setting_selection(value, text_layout.bounds(), target); + state.dragging_state = None; + return event::Status::Captured; } (None, click::Kind::Single, _) => { state.setting_selection(value, text_layout.bounds(), target); @@ -1575,6 +1540,15 @@ pub fn update<'a, Message: Clone + 'static>( | Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => { cold(); let state = state(); + #[cfg(feature = "wayland")] + if matches!(state.dragging_state, Some(DraggingState::PrepareDnd(_))) { + // clear selection and place cursor at click position + update_cache(state, value); + if let Some(position) = cursor.position_over(layout.bounds()) { + let target = position.x - text_layout.bounds().x; + state.setting_selection(value, text_layout.bounds(), target); + } + } state.dragging_state = None; return if cursor.is_over(layout.bounds()) { @@ -1598,6 +1572,58 @@ pub fn update<'a, Message: Clone + 'static>( .cursor .select_range(state.cursor.start(value), position); + return event::Status::Captured; + } + #[cfg(feature = "wayland")] + if let Some(DraggingState::PrepareDnd(start_position)) = state.dragging_state { + let distance = ((position.x - start_position.x).powi(2) + + (position.y - start_position.y).powi(2)) + .sqrt(); + + if distance >= drag_threshold { + if is_secure { + return event::Status::Ignored; + } + + let input_text = state.selected_text(&value.to_string()).unwrap_or_default(); + state.dragging_state = + Some(DraggingState::Dnd(DndAction::empty(), input_text.clone())); + let mut editor = Editor::new(unsecured_value, &mut state.cursor); + editor.delete(); + + let contents = editor.contents(); + let unsecured_value = Value::new(&contents); + state.tracked_value = unsecured_value.clone(); + if let Some(on_input) = on_input { + let message = (on_input)(contents); + shell.publish(message); + } + if let Some(on_start_dnd) = on_start_dnd_source { + shell.publish(on_start_dnd(state.clone())); + } + let state_clone = state.clone(); + + iced_core::clipboard::start_dnd( + clipboard, + false, + id.map(iced_core::clipboard::DndSource::Widget), + Some(iced_core::clipboard::IconSurface::new( + Element::from( + TextInput::<'static, ()>::new("", input_text.clone()) + .dnd_icon(true), + ), + iced_core::widget::tree::State::new(state_clone), + Vector::ZERO, + )), + Box::new(TextInputString(input_text)), + DndAction::Move, + ); + + update_cache(state, &unsecured_value); + } else { + state.dragging_state = Some(DraggingState::PrepareDnd(start_position)); + } + return event::Status::Captured; } } @@ -2519,10 +2545,12 @@ impl AsMimeTypes for TextInputString { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub(crate) enum DraggingState { Selection, #[cfg(feature = "wayland")] + PrepareDnd(Point), + #[cfg(feature = "wayland")] Dnd(DndAction, String), } From d40e9fa4e49397b0c5846b1c243b0b297df5fa36 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Tue, 7 Oct 2025 15:55:31 -0400 Subject: [PATCH 3/3] fix: support NotShowIn --- src/desktop.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/desktop.rs b/src/desktop.rs index 687fa6c4..c9b50704 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -61,9 +61,14 @@ pub fn load_applications<'a>( .filter_map(move |p| fde::DesktopEntry::from_path(p, Some(locales)).ok()) .filter(move |de| { (include_no_display || !de.no_display()) - && !only_show_in.zip(de.only_show_in()).is_some_and( + && only_show_in.zip(de.only_show_in()).is_none_or( |(xdg_current_desktop, only_show_in)| { - !only_show_in.contains(&xdg_current_desktop) + only_show_in.contains(&xdg_current_desktop) + }, + ) + && only_show_in.zip(de.not_show_in()).is_none_or( + |(xdg_current_desktop, not_show_in)| { + !not_show_in.contains(&xdg_current_desktop) }, ) }) @@ -94,6 +99,11 @@ pub fn load_applications_for_app_ids<'a>( ) { return false; } + if only_show_in.zip(de.not_show_in()).is_some_and( + |(xdg_current_desktop, not_show_in)| not_show_in.contains(&xdg_current_desktop), + ) { + return false; + } // Search by ID first app_ids