Merge remote-tracking branch 'upstream/master' into yoda-dock-magnification

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	cosmic-app-list/src/app.rs
#	cosmic-applet-audio/src/lib.rs
#	cosmic-applet-input-sources/Cargo.toml
#	cosmic-applet-input-sources/src/lib.rs
#	cosmic-applet-status-area/src/components/app.rs
#	cosmic-panel-button/src/lib.rs
This commit is contained in:
Lionel DARNIS 2026-08-19 22:04:42 +02:00
commit 673547dc52
119 changed files with 2247 additions and 1190 deletions

View file

@ -1,6 +1,6 @@
cosmic-app-list = دُرج التطبيقات
pin = ثبِّت في درج التطبيقات
quit = أنهِ
quit = إنهِ
quit-all = أنهِ الكل
new-window = نافذة جديدة
run = شغِّل

View file

@ -1,5 +1,5 @@
cosmic-app-list = Panel aplikací
pin = Připnout do panelu aplikací
cosmic-app-list = Oblast aplikací
pin = Připnout do oblasti aplikací
quit = Ukončit
quit-all = Ukončit vše
new-window = Nové okno

View file

@ -0,0 +1,8 @@
run = Kør
run-on = Kør på { $gpu }
run-on-default = (Standard)
cosmic-app-list = Programbakke
new-window = Nyt Vindue
quit = Afslut
quit-all = Forlad Alle
pin = Fastgør til app-skuffe

View file

@ -1,5 +1,5 @@
new-window = Νέο παράθυρο
quit = Έξοδος
quit = Τερματισμός
cosmic-app-list = Περιοχή εφαρμογών
run = Εκτέλεση
run-on = Εκτέλεση με { $gpu }

View file

@ -0,0 +1,8 @@
cosmic-app-list = App Tray
new-window = New Window
quit = Quit
run = Run
run-on = Run on { $gpu }
quit-all = Quit All
run-on-default = (Default)
pin = Pin to app tray

View file

@ -1,8 +1,8 @@
cosmic-app-list = سینی برنامه‌ها
pin = سنجاق کردن به سینی برنامه‌ها
quit = بستن
quit-all = بستن همه
cosmic-app-list = نوار برنامه‌ها
pin = افزودن به نوار برنامه‌ها
quit = خروج
quit-all = خروج از همه
new-window = پنجره جدید
run = اجرا
run-on = اجرا روی {$gpu}
run-on-default = (پیش‌فرض)
run-on = اجرا با { $gpu }
run-on-default = (پیش‌فرض)

View file

@ -0,0 +1,8 @@
quit = Pechar
run = Executar
cosmic-app-list = Bandexa de aplicacións
pin = Fixar na bandexa de aplicacións
quit-all = Quitar todo
new-window = Nova Xanela
run-on = Executar en { $gpu }
run-on-default = (Por defecto)

View file

@ -1,8 +1,8 @@
cosmic-app-list = ऐप ट्रे
pin = ऐप ट्रे में पिन करें
quit = बंद करें
quit = बाहर जाएँ
quit-all = सभी बंद करें
new-window = नई विंडो
run = चलाएँ
run-on = {$gpu} पर चलाएँ
run-on = { $gpu } पर चलाएँ
run-on-default = (डिफ़ॉल्ट)

View file

@ -1,8 +1,8 @@
cosmic-app-list = Barra applicazioni
cosmic-app-list = Area applicazioni
pin = Fissa nella barra delle applicazioni
quit = Esci
quit-all = Chiudi tutto
new-window = Nuova finestra
run = Esegui
run-on = Esegui usando la GPU: { $gpu }
run-on-default = (default)
run-on = Esegui su { $gpu }
run-on-default = (Predefinito)

View file

@ -1,5 +1,5 @@
new-window = Naujas Langas
quit = Išeiti
quit = Išjungti
run = Paleisti
run-on = Paleisti naudojantis { $gpu }
run-on-default = (Numatytas)

View file

@ -0,0 +1 @@
cosmic-app-list = Cinta d’aplicacions

View file

@ -1,4 +1,4 @@
quit = ਬਾਹਰ
quit = ਸਮਾਪਤ
cosmic-app-list = ਐਪ ਟਰੇ
pin = ਐਪ ਟਰੇ ਵਿੱਚ ਟੰਗੋ
quit-all = ਸਭ ਵਿੱਚੋਂ ਬਾਹਰ

View file

@ -1,6 +1,6 @@
cosmic-app-list = Zasobnik aplikacji
pin = Przypnij do zasobnika aplikacji
quit = Zamknij
quit = Zakończ
quit-all = Zamknij wszystkie
new-window = Nowe okno
run = Uruchom

View file

@ -1,6 +1,6 @@
cosmic-app-list = Bandeja de aplicativos
pin = Fixar na bandeja de aplicativos
quit = Sair
quit = Encerrar
quit-all = Sair de Todos
new-window = Nova Janela
run = Executar

View file

@ -1,6 +1,6 @@
cosmic-app-list = Область приложений
pin = Закрепить на панели приложений
quit = Выйти
quit = Завершить
quit-all = Завершить все
new-window = Новое окно
run = Выполнить

View file

@ -0,0 +1,2 @@
run-on = { $gpu } ᱨᱮ ᱫᱟᱹᱲ ᱟᱭ
run-on-default = (ᱢᱩᱞ)

View file

@ -1,6 +1,6 @@
cosmic-app-list = Панель застосунків
pin = Закріпити
quit = Вийти
quit = Завершити
quit-all = Закрити всі
new-window = Нове вікно
run = Виконати

View file

@ -1,8 +1,8 @@
cosmic-app-list = 應用程式匣盤
pin = 釘選至應用程式匣盤
quit = 退出
cosmic-app-list = 應用程式托盤
pin = 釘選至應用程式托盤
quit = 結束
quit-all = 全部退出
new-window = 新建視窗
new-window = 新增視窗
run = 執行
run-on = 在 { $gpu } 上執行
run-on-default = (預設)

View file

@ -28,25 +28,28 @@ use cosmic::{
},
cosmic_config::{Config, CosmicConfigEntry},
desktop::IconSourceExt,
iced::runtime::{core::event, dnd::peek_dnd},
iced::{
self, Alignment, Background, Border, Length, Limits, Padding, Subscription,
advanced::text::{Ellipsize, EllipsizeHeightLimit},
clipboard::mime::{AllowedMimeTypes, AsMimeTypes},
event::listen_with,
platform_specific::shell::commands::popup::{destroy_popup, get_popup},
runtime::{core::event, dnd::peek_dnd, platform_specific::wayland::CornerRadius},
widget::{
Column, Row, column, mouse_area, row, rule::vertical as vertical_rule,
space::horizontal as horizontal_space, space::vertical as vertical_space, stack,
Column, Row, column, mouse_area, row,
rule::vertical as vertical_rule,
space::{horizontal as horizontal_space, vertical as vertical_space},
stack,
},
window,
},
surface,
surface::{self, action::LiveSettings},
theme::{self, Button, Container},
widget::{
DndDestination, Image, button, container, divider, dnd_source, grid,
icon::{self, from_name},
image::Handle,
menu,
rectangle_tracker::{RectangleTracker, RectangleUpdate, rectangle_tracker_subscription},
scrollable, svg, text, text_input,
},
@ -1249,44 +1252,54 @@ impl cosmic::Application for CosmicAppList {
.iter()
.chain(self.pinned_list.iter())
.find(|t| t.id == id)
.cloned()
{
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()) else {
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()).copied()
else {
tracing::error!("No rectangle found for toplevel group");
return Task::none();
};
let corners = self.core.system_theme().cosmic().corner_radii.radius_s;
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
move |_| LiveSettings::default(),
move |app: &mut Self| {
let new_id = window::Id::unique();
app.popup = Some(Popup {
parent: parent_window_id,
id: new_id,
dock_item: toplevel_group.clone(),
popup_type: PopupType::RightClickMenu,
});
let new_id = window::Id::unique();
self.popup = Some(Popup {
parent: parent_window_id,
id: new_id,
dock_item: toplevel_group.clone(),
popup_type: PopupType::RightClickMenu,
});
let mut popup_settings = self.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = *rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let mut popup_settings = app.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
popup_settings
},
None,
));
let gpu_update = Task::perform(try_get_gpus(), |gpus| {
cosmic::Action::App(Message::GpuRequest(gpus))
});
return Task::batch([gpu_update, get_popup(popup_settings)]);
return Task::batch([gpu_update, popup_task]);
}
}
Message::ToplevelListPopup(id, parent_window_id) => {
@ -1317,10 +1330,10 @@ impl cosmic::Application for CosmicAppList {
}
}
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()) else {
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()).copied()
else {
return Task::none();
};
let new_id = window::Id::unique();
self.popup = Some(Popup {
parent: parent_window_id,
@ -1328,48 +1341,56 @@ impl cosmic::Application for CosmicAppList {
dock_item: toplevel_group.clone(),
popup_type: PopupType::ToplevelList,
});
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let mut popup_settings = app.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let max_windows = 7.0;
let window_spacing = 8.0;
popup_settings.positioner.size_limits = match app.core.applet.anchor
{
PanelAnchor::Right | PanelAnchor::Left => Limits::NONE
.min_width(100.0)
.min_height(30.0)
.max_width(window_spacing * 2.0 + TOPLEVEL_BUTTON_WIDTH)
.max_height(
TOPLEVEL_BUTTON_HEIGHT * max_windows
+ window_spacing * (max_windows + 1.0),
),
PanelAnchor::Bottom | PanelAnchor::Top => Limits::NONE
.min_width(30.0)
.min_height(100.0)
.max_width(
TOPLEVEL_BUTTON_WIDTH * max_windows
+ window_spacing * (max_windows + 1.0),
)
.max_height(window_spacing * 2.0 + TOPLEVEL_BUTTON_HEIGHT),
};
popup_settings
},
None,
));
let mut popup_settings = self.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = *rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let max_windows = 7.0;
let window_spacing = 8.0;
popup_settings.positioner.size_limits = match self.core.applet.anchor {
PanelAnchor::Right | PanelAnchor::Left => Limits::NONE
.min_width(100.0)
.min_height(30.0)
.max_width(window_spacing * 2.0 + TOPLEVEL_BUTTON_WIDTH)
.max_height(
TOPLEVEL_BUTTON_HEIGHT * max_windows
+ window_spacing * (max_windows + 1.0),
),
PanelAnchor::Bottom | PanelAnchor::Top => Limits::NONE
.min_width(30.0)
.min_height(100.0)
.max_width(
TOPLEVEL_BUTTON_WIDTH * max_windows
+ window_spacing * (max_windows + 1.0),
)
.max_height(window_spacing * 2.0 + TOPLEVEL_BUTTON_HEIGHT),
};
return get_popup(popup_settings);
return popup_task;
}
}
Message::ToplevelHoverChanged(handle, entering) => {
@ -2148,52 +2169,63 @@ impl cosmic::Application for CosmicAppList {
if create_new {
let new_id = window::Id::unique();
self.overflow_active_popup = Some(new_id);
let rectangle = self.rectangles.get(&DockItemId::ActiveOverflow);
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
if let Some(iced::Rectangle {
let Some(iced::Rectangle {
x,
y,
width,
height,
}) = rectangle
{
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: *x as i32,
y: *y as i32,
width: *width as i32,
height: *height as i32,
};
}
let applet_suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false).0;
let (_favorite_popup_cutoff, active_popup_cutoff) =
self.panel_overflow_lengths();
let popup_applet_count =
self.active_list.len().saturating_sub(
(active_popup_cutoff.unwrap_or_default()).saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32 * popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
}) = self.rectangles.get(&DockItemId::ActiveOverflow).copied()
else {
return Task::none();
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
cmds.push(get_popup(popup_settings));
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let applet_suggested_size = app.core.applet.suggested_size(false).0
+ 2 * app.core.applet.suggested_padding(false).0;
let (_favorite_popup_cutoff, active_popup_cutoff) =
app.panel_overflow_lengths();
let popup_applet_count = app.active_list.len().saturating_sub(
(active_popup_cutoff.unwrap_or_default()).saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32
* popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match app.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
popup_settings
},
None,
));
cmds.push(popup_task);
}
return Task::batch(cmds);
}
@ -2205,52 +2237,63 @@ impl cosmic::Application for CosmicAppList {
if create_new {
let new_id = window::Id::unique();
self.overflow_favorites_popup = Some(new_id);
let rectangle = self.rectangles.get(&DockItemId::FavoritesOverflow);
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
if let Some(iced::Rectangle {
let Some(iced::Rectangle {
x,
y,
width,
height,
}) = rectangle
{
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: *x as i32,
y: *y as i32,
width: *width as i32,
height: *height as i32,
};
}
let applet_suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false).0;
let (favorite_popup_cutoff, _active_popup_cutoff) =
self.panel_overflow_lengths();
let popup_applet_count =
self.pinned_list.len().saturating_sub(
favorite_popup_cutoff.unwrap_or_default().saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32 * popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
}) = self.rectangles.get(&DockItemId::FavoritesOverflow).copied()
else {
return Task::none();
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
cmds.push(get_popup(popup_settings));
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let applet_suggested_size = app.core.applet.suggested_size(false).0
+ 2 * app.core.applet.suggested_padding(false).0;
let (favorite_popup_cutoff, _active_popup_cutoff) =
app.panel_overflow_lengths();
let popup_applet_count = app.pinned_list.len().saturating_sub(
favorite_popup_cutoff.unwrap_or_default().saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32
* popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match app.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
popup_settings
},
None,
));
cmds.push(popup_task);
}
return Task::batch(cmds);
}
@ -2660,7 +2703,8 @@ impl cosmic::Application for CosmicAppList {
.width(Length::Fill)
}
let mut content = column![].align_x(Alignment::Center);
let mut content =
menu::menu_column::MenuColumn::with_capacity(4).align_x(Alignment::Center);
if let Some(exec) = desktop_info.exec() {
if !toplevels.is_empty() {
@ -2784,22 +2828,6 @@ impl cosmic::Application for CosmicAppList {
.popup_container(
container(content)
.padding(1)
//TODO: move style to libcosmic
.class(theme::Container::custom(|theme| {
let cosmic = theme.cosmic();
let component = &cosmic.background(false).component;
container::Style {
icon_color: Some(component.on.into()),
text_color: Some(component.on.into()),
background: Some(Background::Color(component.base.into())),
border: Border {
radius: cosmic.radius_s().into(),
width: 1.0,
color: component.divider.into(),
},
..Default::default()
}
}))
.height(Length::Shrink)
.width(Length::Fill),
)