Compare commits
4 commits
master
...
fix/waylan
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22d6f353f1 | ||
| 28010fd260 | |||
| a7cd859317 | |||
| 5cb0dbb0c5 |
4 changed files with 282 additions and 44 deletions
|
|
@ -187,6 +187,11 @@ impl DockItem {
|
|||
dot_border_radius: [f32; 4],
|
||||
window_id: window::Id,
|
||||
filter: Option<&dyn Fn(&ToplevelInfo) -> bool>,
|
||||
// Yoda: multiplier on the computed icon size (1.0 = default,
|
||||
// >1.0 = magnified e.g. on hover for the macOS Tahoe effect).
|
||||
// Applied to the icon's rendered width/height only — indicator
|
||||
// dot and surrounding layout stay at base size.
|
||||
icon_scale: f32,
|
||||
) -> Element<'_, Message> {
|
||||
let Self {
|
||||
toplevels,
|
||||
|
|
@ -205,17 +210,35 @@ impl DockItem {
|
|||
};
|
||||
let toplevel_count = filtered_toplevels.len();
|
||||
|
||||
// Cairo-like : pastille plus petite + atténuée quand toutes les fenêtres
|
||||
// de cette app sont minimisées.
|
||||
let all_minimized = toplevel_count > 0
|
||||
&& filtered_toplevels
|
||||
.iter()
|
||||
.all(|(info, _)| info.state.contains(&State::Minimized));
|
||||
|
||||
let app_icon = AppletIconData::new(applet);
|
||||
|
||||
// Yoda: scaled icon size for hover magnification. Clamped so
|
||||
// tiny floats don't round to 0 and huge ones stay within u16.
|
||||
let scaled_icon_size = ((f32::from(app_icon.icon_size) * icon_scale).round() as i32)
|
||||
.clamp(1, u16::MAX as i32) as u16;
|
||||
let cosmic_icon = cosmic::widget::icon(
|
||||
fde::IconSource::from_unknown(desktop_info.icon().unwrap_or_default()).as_cosmic_icon(),
|
||||
)
|
||||
// sets the preferred icon size variant
|
||||
.size(128)
|
||||
.width(app_icon.icon_size.into())
|
||||
.height(app_icon.icon_size.into());
|
||||
.width(scaled_icon_size.into())
|
||||
.height(scaled_icon_size.into());
|
||||
|
||||
let indicator = {
|
||||
// Padding réduit quand minimisée → pastille plus petite.
|
||||
let effective_radius = if all_minimized {
|
||||
(app_icon.dot_radius * 0.55).max(1.0)
|
||||
} else {
|
||||
app_icon.dot_radius
|
||||
};
|
||||
|
||||
let container = if toplevel_count <= 1 {
|
||||
vertical_space().height(Length::Fixed(0.0))
|
||||
} else {
|
||||
|
|
@ -229,22 +252,34 @@ impl DockItem {
|
|||
}
|
||||
}
|
||||
.apply(container)
|
||||
.padding(app_icon.dot_radius);
|
||||
.padding(effective_radius);
|
||||
|
||||
if toplevel_count == 0 {
|
||||
container
|
||||
} else {
|
||||
container.class(theme::Container::custom(move |theme| container::Style {
|
||||
background: if is_focused {
|
||||
Some(Background::Color(theme.cosmic().accent_color().into()))
|
||||
container.class(theme::Container::custom(move |theme| {
|
||||
let cosmic = theme.cosmic();
|
||||
let accent: iced::Color = cosmic.accent_color().into();
|
||||
let on_bg: iced::Color = cosmic.on_bg_color().into();
|
||||
// Teinte neutre atténuée quand toutes les fenêtres sont minimisées.
|
||||
let muted = iced::Color { a: 0.45, ..on_bg };
|
||||
|
||||
let fill = if all_minimized {
|
||||
muted
|
||||
} else if is_focused {
|
||||
accent
|
||||
} else {
|
||||
Some(Background::Color(theme.cosmic().on_bg_color().into()))
|
||||
},
|
||||
border: Border {
|
||||
radius: dot_border_radius.into(),
|
||||
on_bg
|
||||
};
|
||||
|
||||
container::Style {
|
||||
background: Some(Background::Color(fill)),
|
||||
border: Border {
|
||||
radius: dot_border_radius.into(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}))
|
||||
}
|
||||
};
|
||||
|
|
@ -374,6 +409,21 @@ struct CosmicAppList {
|
|||
output_list: FxHashMap<WlOutput, OutputInfo>,
|
||||
locales: Vec<String>,
|
||||
hovered_toplevel: Option<ExtForeignToplevelHandleV1>,
|
||||
/// Yoda: which dock icon the pointer is currently over (for hover
|
||||
/// magnification). None = no dock icon hovered.
|
||||
hovered_dock_item: Option<DockItemId>,
|
||||
/// Yoda: animated "virtual cursor" center used by the fisheye
|
||||
/// formula — lerps toward the real hovered icon's center on each
|
||||
/// AnimTick, so the bell curve slides smoothly from one icon to the
|
||||
/// next instead of snapping.
|
||||
anim_hover_center: Option<(f32, f32)>,
|
||||
/// Yoda: fade-in/out intensity of the magnification effect
|
||||
/// (0.0 = icons flat, 1.0 = full fisheye). Targets 1.0 while the
|
||||
/// pointer is over any dock icon, 0.0 otherwise. Lerped on AnimTick.
|
||||
anim_hover_intensity: f32,
|
||||
/// Yoda: timestamp of the last AnimTick, for dt-based exponential
|
||||
/// smoothing. `None` on first tick.
|
||||
anim_last_tick: Option<std::time::Instant>,
|
||||
overflow_favorites_popup: Option<window::Id>,
|
||||
overflow_active_popup: Option<window::Id>,
|
||||
}
|
||||
|
|
@ -389,6 +439,13 @@ enum Message {
|
|||
Wayland(WaylandUpdate),
|
||||
PinApp(u32),
|
||||
UnpinApp(u32),
|
||||
/// Yoda: pointer entered (Some) or left (None) a dock icon — drives
|
||||
/// the macOS Tahoe-style hover magnification effect.
|
||||
DockItemHover(Option<DockItemId>),
|
||||
/// Yoda: ticked at ~60fps by the animation subscription. Advances
|
||||
/// anim_hover_center + anim_hover_intensity toward their targets so
|
||||
/// the fisheye effect transitions smoothly instead of snapping.
|
||||
AnimTick(std::time::Instant),
|
||||
Popup(u32, window::Id),
|
||||
Pressed(window::Id),
|
||||
ToplevelListPopup(u32, window::Id),
|
||||
|
|
@ -647,6 +704,79 @@ impl CosmicAppList {
|
|||
.collect::<Vec<_>>();
|
||||
}
|
||||
|
||||
/// Yoda: macOS-Tahoe fisheye-style magnification. Returns the
|
||||
/// per-icon size multiplier based on the distance (in pixels) from
|
||||
/// the currently hovered icon's center to this icon's center.
|
||||
///
|
||||
/// Uses a gaussian bell curve so the hovered icon peaks at
|
||||
/// 1.0 + PEAK, immediate neighbors still bulge noticeably, and icons
|
||||
/// further away relax back to 1.0× — that's the smooth neighbour
|
||||
/// deformation people associate with the macOS Dock.
|
||||
///
|
||||
/// Falls back to binary 1.3×/1.0× when the rectangle tracker hasn't
|
||||
/// populated yet (first render, or just after layout changes).
|
||||
///
|
||||
/// Uses the animated hover center (anim_hover_center) and intensity
|
||||
/// (anim_hover_intensity) so inter-icon transitions slide smoothly
|
||||
/// and the whole effect fades in/out at the dock's edges.
|
||||
fn icon_scale_for(&self, id: &DockItemId) -> f32 {
|
||||
const PEAK: f32 = 0.35;
|
||||
// sigma expressed in multiples of the hovered icon's size —
|
||||
// 1.4 means the ±1 neighbors sit ~0.7σ away and still bulge
|
||||
// visibly, while ±3+ has collapsed to ~1.0× (fisheye footprint
|
||||
// close to 5 icons wide, Tahoe-ish).
|
||||
const SIGMA_FACTOR: f32 = 1.4;
|
||||
|
||||
// No intensity at all → skip the rest.
|
||||
if self.anim_hover_intensity < 0.001 {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
// Prefer the animated center (smooth); fall back to the real
|
||||
// hovered icon's center (first render, before tick fires).
|
||||
let hover_center = self.anim_hover_center.or_else(|| {
|
||||
let hovered_id = self.hovered_dock_item.as_ref()?;
|
||||
let r = self.rectangles.get(hovered_id)?;
|
||||
Some((r.x + r.width / 2.0, r.y + r.height / 2.0))
|
||||
});
|
||||
let Some(hover_center) = hover_center else {
|
||||
// No coords yet — visibly peak on the exact hovered id so
|
||||
// the very first frame still responds.
|
||||
return if self.hovered_dock_item.as_ref() == Some(id) {
|
||||
1.0 + PEAK * self.anim_hover_intensity
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
};
|
||||
|
||||
let this_rect = match self.rectangles.get(id) {
|
||||
Some(r) => r,
|
||||
None => return 1.0,
|
||||
};
|
||||
|
||||
let is_horizontal = matches!(
|
||||
self.core.applet.anchor,
|
||||
PanelAnchor::Top | PanelAnchor::Bottom
|
||||
);
|
||||
let this_center = if is_horizontal {
|
||||
this_rect.x + this_rect.width / 2.0
|
||||
} else {
|
||||
this_rect.y + this_rect.height / 2.0
|
||||
};
|
||||
let hover_axis = if is_horizontal { hover_center.0 } else { hover_center.1 };
|
||||
let distance = (this_center - hover_axis).abs();
|
||||
let icon_extent = if is_horizontal {
|
||||
this_rect.width
|
||||
} else {
|
||||
this_rect.height
|
||||
}
|
||||
.max(1.0);
|
||||
let sigma = icon_extent * SIGMA_FACTOR;
|
||||
// exp(-t²) bell curve, t = distance / sigma
|
||||
let t = distance / sigma;
|
||||
1.0 + PEAK * self.anim_hover_intensity * (-t * t).exp()
|
||||
}
|
||||
|
||||
fn is_on_current_monitor_and_workspace(&self, toplevel_info: &ToplevelInfo) -> bool {
|
||||
use cosmic_app_list_config::ToplevelFilter;
|
||||
|
||||
|
|
@ -1582,6 +1712,52 @@ impl cosmic::Application for CosmicAppList {
|
|||
Message::GpuRequest(gpus) => {
|
||||
self.gpus = gpus;
|
||||
}
|
||||
Message::DockItemHover(id) => {
|
||||
self.hovered_dock_item = id;
|
||||
// Seed the animated center on the very first hover so
|
||||
// the bell doesn't "fly in" from (0,0).
|
||||
if self.anim_hover_center.is_none()
|
||||
&& let Some(hovered_id) = self.hovered_dock_item.as_ref()
|
||||
&& let Some(r) = self.rectangles.get(hovered_id)
|
||||
{
|
||||
self.anim_hover_center = Some((
|
||||
r.x + r.width / 2.0,
|
||||
r.y + r.height / 2.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
Message::AnimTick(now) => {
|
||||
// dt-based exponential smoothing: reach ~99% of the
|
||||
// target in ~120ms at 60fps (about 7 ticks).
|
||||
let dt = self
|
||||
.anim_last_tick
|
||||
.map(|prev| now.saturating_duration_since(prev).as_secs_f32())
|
||||
.unwrap_or(0.016)
|
||||
.min(0.1); // clamp so a long pause doesn't snap
|
||||
self.anim_last_tick = Some(now);
|
||||
|
||||
// Intensity: target 1.0 when any icon is hovered, 0.0 else.
|
||||
let intensity_target = if self.hovered_dock_item.is_some() { 1.0 } else { 0.0 };
|
||||
let tau = 0.060_f32; // time-constant (s); smaller = snappier
|
||||
let alpha = 1.0 - (-dt / tau).exp();
|
||||
self.anim_hover_intensity += (intensity_target - self.anim_hover_intensity) * alpha;
|
||||
|
||||
// Hovered-center smoothing: chase the real rect's center.
|
||||
if let Some(hovered_id) = self.hovered_dock_item.as_ref()
|
||||
&& let Some(r) = self.rectangles.get(hovered_id)
|
||||
{
|
||||
let target = (r.x + r.width / 2.0, r.y + r.height / 2.0);
|
||||
let current = self.anim_hover_center.unwrap_or(target);
|
||||
self.anim_hover_center = Some((
|
||||
current.0 + (target.0 - current.0) * alpha,
|
||||
current.1 + (target.1 - current.1) * alpha,
|
||||
));
|
||||
} else if self.anim_hover_intensity < 0.01 {
|
||||
// Nothing hovered + intensity faded out → forget the
|
||||
// animated center so the next hover seeds fresh.
|
||||
self.anim_hover_center = None;
|
||||
}
|
||||
}
|
||||
Message::OpenActive => {
|
||||
let create_new = self.overflow_active_popup.is_none();
|
||||
let mut cmds = vec![self.close_popups()];
|
||||
|
|
@ -1763,7 +1939,9 @@ impl cosmic::Application for CosmicAppList {
|
|||
.filter(|(info, _)| self.is_on_current_monitor_and_workspace(info))
|
||||
.any(|y| focused_item.contains(&y.0.foreign_toplevel));
|
||||
|
||||
self.core
|
||||
let dock_id = dock_item.id;
|
||||
let icon_scale = self.icon_scale_for(&DockItemId::from(dock_id));
|
||||
let tooltip = self.core
|
||||
.applet
|
||||
.applet_tooltip::<Message>(
|
||||
dock_item.as_icon(
|
||||
|
|
@ -1776,6 +1954,7 @@ impl cosmic::Application for CosmicAppList {
|
|||
dot_radius,
|
||||
self.core.main_window_id().unwrap(),
|
||||
Some(&|info| self.is_on_current_monitor_and_workspace(info)),
|
||||
icon_scale,
|
||||
),
|
||||
dock_item
|
||||
.desktop_info
|
||||
|
|
@ -1785,7 +1964,10 @@ impl cosmic::Application for CosmicAppList {
|
|||
self.popup.is_some(),
|
||||
Message::Surface,
|
||||
None,
|
||||
)
|
||||
);
|
||||
cosmic::widget::mouse_area(tooltip)
|
||||
.on_enter(Message::DockItemHover(Some(DockItemId::from(dock_id))))
|
||||
.on_exit(Message::DockItemHover(None))
|
||||
.into()
|
||||
})
|
||||
.collect();
|
||||
|
|
@ -1836,6 +2018,10 @@ impl cosmic::Application for CosmicAppList {
|
|||
dot_radius,
|
||||
self.core.main_window_id().unwrap(),
|
||||
Some(&|info| self.is_on_current_monitor_and_workspace(info)),
|
||||
// Yoda: no magnification on DnD-preview icons — these
|
||||
// float around as the user drags, so static 1.0 is
|
||||
// less visually confusing.
|
||||
1.0,
|
||||
),
|
||||
);
|
||||
} else if self.is_listening_for_dnd && self.pinned_list.is_empty() {
|
||||
|
|
@ -1875,8 +2061,10 @@ impl cosmic::Application for CosmicAppList {
|
|||
.iter()
|
||||
.filter(|(info, _)| self.is_on_current_monitor_and_workspace(info))
|
||||
.any(|y| focused_item.contains(&y.0.foreign_toplevel));
|
||||
let dock_id = dock_item.id;
|
||||
let icon_scale = self.icon_scale_for(&DockItemId::from(dock_id));
|
||||
|
||||
self.core
|
||||
let tooltip = self.core
|
||||
.applet
|
||||
.applet_tooltip(
|
||||
dock_item.as_icon(
|
||||
|
|
@ -1889,6 +2077,7 @@ impl cosmic::Application for CosmicAppList {
|
|||
dot_radius,
|
||||
self.core.main_window_id().unwrap(),
|
||||
Some(&|info| self.is_on_current_monitor_and_workspace(info)),
|
||||
icon_scale,
|
||||
),
|
||||
dock_item
|
||||
.desktop_info
|
||||
|
|
@ -1898,7 +2087,10 @@ impl cosmic::Application for CosmicAppList {
|
|||
self.popup.is_some(),
|
||||
Message::Surface,
|
||||
None,
|
||||
)
|
||||
);
|
||||
cosmic::widget::mouse_area(tooltip)
|
||||
.on_enter(Message::DockItemHover(Some(DockItemId::from(dock_id))))
|
||||
.on_exit(Message::DockItemHover(None))
|
||||
.into()
|
||||
})
|
||||
.collect();
|
||||
|
|
@ -2313,6 +2505,10 @@ impl cosmic::Application for CosmicAppList {
|
|||
dot_radius,
|
||||
id,
|
||||
Some(&|info| self.is_on_current_monitor_and_workspace(info)),
|
||||
// Yoda: icons in the overflow popup are
|
||||
// already smaller-grid — keep them at 1.0
|
||||
// so the popup doesn't reshuffle on hover.
|
||||
1.0,
|
||||
),
|
||||
dock_item
|
||||
.desktop_info
|
||||
|
|
@ -2421,6 +2617,10 @@ impl cosmic::Application for CosmicAppList {
|
|||
dot_radius,
|
||||
id,
|
||||
Some(&|info| self.is_on_current_monitor_and_workspace(info)),
|
||||
// Yoda: popup icons stay at 1.0 (hover
|
||||
// magnification is applied to the main
|
||||
// dock row only).
|
||||
1.0,
|
||||
),
|
||||
dock_item
|
||||
.desktop_info
|
||||
|
|
@ -2479,7 +2679,21 @@ impl cosmic::Application for CosmicAppList {
|
|||
}
|
||||
|
||||
fn subscription(&self) -> Subscription<Message> {
|
||||
// Yoda: ~60fps animation ticks for the fisheye magnification.
|
||||
// Only emitted when an animation is actually in progress (hover
|
||||
// intensity >0 OR still fading out) — keeps the panel idle when
|
||||
// the pointer is nowhere near the dock.
|
||||
let anim_active = self.hovered_dock_item.is_some()
|
||||
|| self.anim_hover_intensity > 0.001;
|
||||
let anim_subscription = if anim_active {
|
||||
cosmic::iced::time::every(std::time::Duration::from_millis(16))
|
||||
.map(Message::AnimTick)
|
||||
} else {
|
||||
Subscription::none()
|
||||
};
|
||||
|
||||
Subscription::batch([
|
||||
anim_subscription,
|
||||
wayland_subscription().map(Message::Wayland),
|
||||
listen_with(|e, _, id| match e {
|
||||
cosmic::iced::core::Event::PlatformSpecific(event::PlatformSpecific::Wayland(
|
||||
|
|
|
|||
|
|
@ -388,7 +388,10 @@ impl CaptureData {
|
|||
},
|
||||
)
|
||||
.unwrap();
|
||||
self.conn.flush().unwrap();
|
||||
if let Err(err) = self.conn.flush() {
|
||||
tracing::error!("Wayland flush failed during screencopy session create: {err}");
|
||||
return None;
|
||||
}
|
||||
|
||||
let formats = session
|
||||
.wait_while(|data| data.formats.is_none())
|
||||
|
|
@ -437,7 +440,10 @@ impl CaptureData {
|
|||
session: capture_session.clone(),
|
||||
},
|
||||
);
|
||||
self.conn.flush().unwrap();
|
||||
if let Err(err) = self.conn.flush() {
|
||||
tracing::error!("Wayland flush failed during screencopy capture: {err}");
|
||||
return None;
|
||||
}
|
||||
|
||||
// TODO: wait for server to release buffer?
|
||||
let res = session
|
||||
|
|
@ -709,7 +715,10 @@ pub(crate) fn wayland_handler(
|
|||
if app_data.exit {
|
||||
break;
|
||||
}
|
||||
event_loop.dispatch(None, &mut app_data).unwrap();
|
||||
if let Err(err) = event_loop.dispatch(None, &mut app_data) {
|
||||
tracing::error!("Wayland event loop terminated: {err}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use cosmic::{
|
|||
Alignment, Length, Subscription,
|
||||
advanced::text::{Ellipsize, EllipsizeHeightLimit},
|
||||
platform_specific::shell::wayland::commands::popup::{destroy_popup, get_popup},
|
||||
widget::{self, column, rich_text, row},
|
||||
widget::{self, column, row},
|
||||
window,
|
||||
},
|
||||
surface, theme,
|
||||
|
|
@ -26,7 +26,7 @@ use cosmic::{
|
|||
use cosmic::iced::futures::executor::block_on;
|
||||
|
||||
use cosmic_notifications_config::NotificationsConfig;
|
||||
use cosmic_notifications_util::{ActionId, Image, Notification, markup};
|
||||
use cosmic_notifications_util::{ActionId, Image, Notification};
|
||||
use std::{borrow::Cow, collections::HashMap, path::PathBuf, sync::LazyLock};
|
||||
use subscriptions::notifications::{self, NotificationsAppletProxy};
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
|
@ -456,11 +456,8 @@ impl cosmic::Application for Notifications {
|
|||
column![
|
||||
text::body(n.summary.lines().next().unwrap_or_default())
|
||||
.width(Length::Fill),
|
||||
Element::from(
|
||||
rich_text(markup::html_to_spans(&n.body))
|
||||
.size(12.0)
|
||||
.width(Length::Fill)
|
||||
)
|
||||
text::caption(n.body.lines().next().unwrap_or_default())
|
||||
.width(Length::Fill)
|
||||
]
|
||||
)
|
||||
.width(Length::Fill),
|
||||
|
|
|
|||
|
|
@ -12,26 +12,44 @@ fn main() -> cosmic::iced::Result {
|
|||
};
|
||||
|
||||
let start = applet.rfind('/').map_or(0, |v| v + 1);
|
||||
let cmd = &applet.as_str()[start..];
|
||||
let cmd = applet.as_str()[start..].to_string();
|
||||
|
||||
tracing::info!("Starting `{cmd}` with version {VERSION}");
|
||||
|
||||
match cmd {
|
||||
"cosmic-app-list" => cosmic_app_list::run(),
|
||||
"cosmic-applet-a11y" => cosmic_applet_a11y::run(),
|
||||
"cosmic-applet-audio" => cosmic_applet_audio::run(),
|
||||
"cosmic-applet-battery" => cosmic_applet_battery::run(),
|
||||
"cosmic-applet-bluetooth" => cosmic_applet_bluetooth::run(),
|
||||
"cosmic-applet-minimize" => cosmic_applet_minimize::run(),
|
||||
"cosmic-applet-network" => cosmic_applet_network::run(),
|
||||
"cosmic-applet-notifications" => cosmic_applet_notifications::run(),
|
||||
"cosmic-applet-power" => cosmic_applet_power::run(),
|
||||
"cosmic-applet-status-area" => cosmic_applet_status_area::run(),
|
||||
"cosmic-applet-tiling" => cosmic_applet_tiling::run(),
|
||||
"cosmic-applet-time" => cosmic_applet_time::run(),
|
||||
"cosmic-applet-workspaces" => cosmic_applet_workspaces::run(),
|
||||
"cosmic-applet-input-sources" => cosmic_applet_input_sources::run(),
|
||||
"cosmic-panel-button" => cosmic_panel_button::run(),
|
||||
_ => Ok(()),
|
||||
let cmd_for_run = cmd.clone();
|
||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || {
|
||||
match cmd_for_run.as_str() {
|
||||
"cosmic-app-list" => cosmic_app_list::run(),
|
||||
"cosmic-applet-a11y" => cosmic_applet_a11y::run(),
|
||||
"cosmic-applet-audio" => cosmic_applet_audio::run(),
|
||||
"cosmic-applet-battery" => cosmic_applet_battery::run(),
|
||||
"cosmic-applet-bluetooth" => cosmic_applet_bluetooth::run(),
|
||||
"cosmic-applet-minimize" => cosmic_applet_minimize::run(),
|
||||
"cosmic-applet-network" => cosmic_applet_network::run(),
|
||||
"cosmic-applet-notifications" => cosmic_applet_notifications::run(),
|
||||
"cosmic-applet-power" => cosmic_applet_power::run(),
|
||||
"cosmic-applet-status-area" => cosmic_applet_status_area::run(),
|
||||
"cosmic-applet-tiling" => cosmic_applet_tiling::run(),
|
||||
"cosmic-applet-time" => cosmic_applet_time::run(),
|
||||
"cosmic-applet-workspaces" => cosmic_applet_workspaces::run(),
|
||||
"cosmic-applet-input-sources" => cosmic_applet_input_sources::run(),
|
||||
"cosmic-panel-button" => cosmic_panel_button::run(),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}));
|
||||
|
||||
match result {
|
||||
Ok(r) => r,
|
||||
Err(payload) => {
|
||||
let msg = payload
|
||||
.downcast_ref::<&str>()
|
||||
.map(|s| s.to_string())
|
||||
.or_else(|| payload.downcast_ref::<String>().cloned())
|
||||
.unwrap_or_else(|| "<non-string panic>".to_string());
|
||||
tracing::error!(
|
||||
"`{cmd}` panicked (likely compositor disconnect), exiting cleanly: {msg}"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue