feat: rebase libcosmic onto iced 0.14

This commit is contained in:
Ashley Wulber 2026-03-18 12:21:57 -04:00 committed by GitHub
parent adb938420e
commit f62abcea4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 1432 additions and 1418 deletions

2613
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ version = "1.0.8"
authors = ["Jeremy Soller <jeremy@system76.com>"]
edition = "2024"
license = "GPL-3.0-only"
rust-version = "1.85"
rust-version = "1.90"
[dependencies]
alacritty_terminal = "0.25.1"

View file

@ -949,7 +949,7 @@ impl App {
sections.push(
widget::row::with_children(vec![
widget::horizontal_space().into(),
widget::space::horizontal().into(),
widget::button::standard(fl!("import"))
.on_press(Message::ColorSchemeImport(color_scheme_kind))
.into(),
@ -1003,7 +1003,7 @@ impl App {
let mut groups = Vec::new();
//TODO: fix text input focus going outside bounds
groups.push(widget::horizontal_space().into());
groups.push(widget::space::horizontal().into());
groups.push(
widget::text_input::search_input(fl!("type-to-search"), &self.shortcut_search_value)
.id(self.shortcut_search_id.clone())
@ -1269,7 +1269,7 @@ impl App {
])
.spacing(space_xxxs)
.into(),
widget::horizontal_space().into(),
widget::space::horizontal().into(),
widget::toggler(profile.drain_on_exit)
.on_toggle(move |t| Message::ProfileHold(profile_id, t))
.into(),
@ -1292,7 +1292,7 @@ impl App {
}
let add_profile = widget::row::with_children(vec![
widget::horizontal_space().into(),
widget::space::horizontal().into(),
widget::button::standard(fl!("add-profile"))
.on_press(Message::ProfileNew)
.into(),
@ -3362,7 +3362,7 @@ impl Application for App {
widget::tooltip::Position::Top,
)
.into(),
widget::horizontal_space().into(),
widget::space::horizontal().into(),
button::custom(icon_cache_get("window-close-symbolic", 16))
.on_press(Message::Find(false))
.padding(space_xxs)
@ -3428,9 +3428,10 @@ impl Application for App {
}
_ => None,
}),
Subscription::run_with_id(
TypeId::of::<TerminalEventSubscription>(),
stream::channel(100, |mut output| async move {
Subscription::run_with(TypeId::of::<TerminalEventSubscription>(), |_| {
stream::channel(
100,
|mut output: iced::futures::channel::mpsc::Sender<Message>| async move {
let (event_tx, mut event_rx) = mpsc::unbounded_channel();
output.send(Message::TermEventTx(event_tx)).await.unwrap();
@ -3442,8 +3443,9 @@ impl Application for App {
}
panic!("terminal event channel closed");
},
)
}),
),
cosmic_config::config_subscription(
TypeId::of::<ConfigSubscription>(),
Self::APP_ID.into(),

View file

@ -1,15 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::iced::Point;
use cosmic::widget::Column;
use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::widget::menu::{Item as MenuItem, menu_button};
use cosmic::widget::{Column, space};
use cosmic::{
Element,
app::Core,
iced::{
Background, Length, advanced::widget::text::Style as TextStyle, widget::horizontal_space,
},
iced::{Background, Length, advanced::widget::text::Style as TextStyle},
iced_core::Border,
theme,
widget::{
@ -57,7 +55,7 @@ pub fn context_menu<'a>(
let key = find_key(&action);
menu_button(vec![
widget::text(label).into(),
horizontal_space().into(),
space::horizontal().into(),
widget::text(key)
.class(theme::Text::Custom(key_style))
.into(),
@ -68,7 +66,7 @@ pub fn context_menu<'a>(
let menu_checkbox = |label, value, action| {
menu_button(vec![
widget::text(label).into(),
widget::horizontal_space().into(),
widget::space::horizontal().into(),
widget::toggler(value)
.on_toggle(move |_| Message::TabContextAction(entity, action))
.size(16.0)

View file

@ -386,7 +386,7 @@ impl PasswordManager {
sections.push(passwords_section.into());
let add_password = widget::row::with_children(vec![
widget::horizontal_space().into(),
widget::space::horizontal().into(),
widget::button::standard(fl!("add-password"))
.on_press(Message::PasswordManager(PasswordManagerMessage::New))
.into(),

View file

@ -7,7 +7,6 @@ use alacritty_terminal::{
term::{TermMode, cell::Flags},
vte::ansi::{CursorShape, NamedColor},
};
use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::{
Renderer,
cosmic_theme::palette::{WithAlpha, blend::Compose},
@ -34,6 +33,7 @@ use cosmic::{
},
theme::Theme,
};
use cosmic::{iced_core::SmolStr, widget::menu::key_bind::KeyBind};
use cosmic_text::LayoutGlyph;
use indexmap::IndexSet;
use std::{
@ -263,7 +263,7 @@ where
}
fn layout(
&self,
&mut self,
_tree: &mut widget::Tree,
_renderer: &Renderer,
limits: &layout::Limits,
@ -297,15 +297,15 @@ where
}
fn operate(
&self,
&mut self,
tree: &mut widget::Tree,
_layout: Layout<'_>,
layout: Layout<'_>,
_renderer: &Renderer,
operation: &mut dyn Operation,
) {
let state = tree.state.downcast_mut::<State>();
operation.focusable(state, self.id.as_ref());
operation.focusable(self.id.as_ref(), layout.bounds(), state);
}
fn mouse_interaction(
@ -316,6 +316,9 @@ where
_viewport: &Rectangle,
_renderer: &Renderer,
) -> mouse::Interaction {
if self.disabled {
return mouse::Interaction::default();
}
let state = tree.state.downcast_ref::<State>();
if let Some(Dragging::Scrollbar { .. }) = &state.dragging {
@ -348,7 +351,7 @@ where
}
}
mouse::Interaction::Idle
mouse::Interaction::default()
}
fn draw(
@ -377,10 +380,10 @@ where
let view_position = layout.position() + [self.padding.left, self.padding.top].into();
let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32)
- self.padding.horizontal() as i32
- self.padding.x() as i32
- scrollbar_w as i32;
let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32)
- self.padding.vertical() as i32;
- self.padding.y() as i32;
if view_w <= 0 || view_h <= 0 {
// Zero sized image
@ -417,7 +420,7 @@ where
},
..Default::default()
},
Color::new(
Color::from_rgba(
f32::from(background_color.r()) / 255.0,
f32::from(background_color.g()) / 255.0,
f32::from(background_color.b()) / 255.0,
@ -468,7 +471,7 @@ where
is_focused: bool,
) {
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
Color::new(
Color::from_rgba(
f32::from(color.r()) / 255.0,
f32::from(color.g()) / 255.0,
f32::from(color.b()) / 255.0,
@ -645,7 +648,7 @@ where
renderer.fill_raw(Raw {
buffer: terminal.buffer_weak(),
position: view_position,
color: Color::new(1.0, 1.0, 1.0, 1.0), // TODO
color: Color::from_rgba(1.0, 1.0, 1.0, 1.0), // TODO
clip_bounds: Rectangle::new(view_position, Size::new(view_w as f32, view_h as f32)),
});
@ -799,19 +802,19 @@ where
log::trace!("redraw {}, {}: {:?}", view_w, view_h, duration);
}
fn on_event(
fn update(
&mut self,
tree: &mut widget::Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor_position: mouse::Cursor,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
_viewport: &Rectangle<f32>,
) -> Status {
) {
if self.disabled {
return Status::Ignored;
return;
}
let state = tree.state.downcast_mut::<State>();
let scrollbar_rect = state.scrollbar_rect.get();
@ -820,7 +823,6 @@ where
let is_app_cursor = terminal.term.lock().mode().contains(TermMode::APP_CURSOR);
let is_mouse_mode = terminal.term.lock().mode().intersects(TermMode::MOUSE_MODE);
let mut status = Status::Ignored;
match event {
Event::Window(event) => match event {
cosmic::iced::window::Event::Focused => {
@ -842,11 +844,11 @@ where
self.padding,
multiplier,
) {
status = Status::Captured;
shell.capture_event();
}
}
if state.autoscroll.is_active() {
shell.request_redraw(RedrawRequest::NextFrame);
shell.request_redraw();
}
}
}
@ -867,8 +869,9 @@ where
..
}) if state.is_focused && named == modified_named => {
for key_bind in self.key_binds.keys() {
if key_bind.matches(modifiers, &Key::Named(named)) {
return Status::Captured;
if key_bind.matches(*modifiers, &Key::Named(*named)) {
shell.capture_event();
return;
}
}
@ -956,7 +959,9 @@ where
};
if let Some(escape_code) = escape_code {
terminal.input_scroll(escape_code);
return Status::Captured;
shell.capture_event();
return;
}
//Special handle Enter, Escape, Backspace and Tab as described in
@ -967,11 +972,11 @@ where
Named::Backspace => {
let code = if modifiers.control() { "\x08" } else { "\x7f" };
terminal.input_scroll(format!("{alt_prefix}{code}").into_bytes());
status = Status::Captured;
shell.capture_event();
}
Named::Enter => {
terminal.input_scroll(format!("{}{}", alt_prefix, "\x0D").into_bytes());
status = Status::Captured;
shell.capture_event();
}
Named::Escape => {
//Escape with any modifier will cancel selection
@ -984,31 +989,19 @@ where
} else {
terminal.input_scroll(format!("{}{}", alt_prefix, "\x1B").into_bytes());
}
status = Status::Captured;
shell.capture_event();
}
Named::Space => {
// Keep this instead of hardcoding the space to allow for dead keys
let character = text.and_then(|c| c.chars().next()).unwrap_or_default();
if modifiers.control() {
// Send NUL character (\x00) for Ctrl + Space
terminal.input_scroll(b"\x00".to_vec());
} else {
terminal
.input_scroll(format!("{}{}", alt_prefix, character).into_bytes());
}
status = Status::Captured;
}
Named::Tab => {
let code = if modifiers.shift() { "\x1b[Z" } else { "\x09" };
terminal.input_scroll(format!("{alt_prefix}{code}").into_bytes());
status = Status::Captured;
shell.capture_event();
}
_ => {}
}
}
Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
state.modifiers = modifiers;
state.modifiers = *modifiers;
if modifiers.contains(Modifiers::CTRL)
|| terminal.active_regex_match.is_some()
@ -1032,6 +1025,31 @@ where
update_active_regex_match(&mut terminal, location, Some(&state.modifiers));
}
}
Event::Keyboard(KeyEvent::KeyPressed {
text,
modifiers,
key,
..
}) if *key == Key::Character(SmolStr::new(" ")) => {
//Special handle Enter, Escape, Backspace and Tab as described in
//https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-key-event-encoding
//Also special handle Ctrl-_ to behave like xterm
let alt_prefix = if modifiers.alt() { "\x1B" } else { "" };
// Keep this instead of hardcoding the space to allow for dead keys
let character = text
.as_ref()
.and_then(|c| c.chars().next())
.unwrap_or_default();
if modifiers.control() {
// Send NUL character (\x00) for Ctrl + Space
terminal.input_scroll(b"\x00".to_vec());
} else {
terminal.input_scroll(format!("{}{}", alt_prefix, character).into_bytes());
}
shell.capture_event();
}
Event::Keyboard(KeyEvent::KeyPressed {
text,
modifiers,
@ -1039,11 +1057,16 @@ where
..
}) if state.is_focused => {
for key_bind in self.key_binds.keys() {
if key_bind.matches(modifiers, &key) {
return Status::Captured;
if key_bind.matches(*modifiers, key) {
shell.capture_event();
return;
}
}
let character = text.and_then(|c| c.chars().next()).unwrap_or_default();
let character = text
.as_ref()
.and_then(|c| c.chars().next())
.unwrap_or_default();
match (
modifiers.logo(),
modifiers.control(),
@ -1064,7 +1087,7 @@ where
str.len() + 1
};
terminal.input_scroll(buf[..len].to_vec());
status = Status::Captured;
shell.capture_event();
}
}
(false, true, _, false) => {
@ -1073,7 +1096,7 @@ where
let mut buf = [0, 0, 0, 0];
let str = character.encode_utf8(&mut buf);
terminal.input_scroll(str.as_bytes().to_vec());
status = Status::Captured;
shell.capture_event();
}
}
(false, true, _, true) => {
@ -1081,9 +1104,9 @@ where
//is taken by zoom, we send that code for
//Ctrl+Underline instead, like xterm and
//gnome-terminal
if key == Key::Character("_".into()) {
if *key == Key::Character("_".into()) {
terminal.input_scroll(b"\x1F".as_slice());
status = Status::Captured;
shell.capture_event();
}
}
(false, false, true, _) => {
@ -1095,7 +1118,7 @@ where
str.len() + 1
};
terminal.input_scroll(buf[..len].to_vec());
status = Status::Captured;
shell.capture_event();
}
}
(false, false, false, _) => {
@ -1104,7 +1127,7 @@ where
let mut buf = [0, 0, 0, 0];
let str = character.encode_utf8(&mut buf);
terminal.input_scroll(str.as_bytes().to_vec());
status = Status::Captured;
shell.capture_event();
}
}
}
@ -1119,7 +1142,12 @@ where
if is_mouse_mode {
state.autoscroll.stop();
terminal.report_mouse(event, &state.modifiers, col as u32, row as u32);
terminal.report_mouse(
event.clone(),
&state.modifiers,
col as u32,
row as u32,
);
} else {
state.is_focused = true;
@ -1214,7 +1242,7 @@ where
}
}
}
} else if button == Button::Middle {
} else if *button == Button::Middle {
if let Some(on_middle_click) = &self.on_middle_click {
shell.publish(on_middle_click());
}
@ -1226,7 +1254,7 @@ where
shell.publish(on_context_menu(None));
}
None => {
if button == Button::Right {
if *button == Button::Right {
let x = p.x - self.padding.left;
let y = p.y - self.padding.top;
//TODO: better calculation of position
@ -1251,7 +1279,7 @@ where
}
}
}
status = Status::Captured;
shell.capture_event();
}
}
}
@ -1286,18 +1314,23 @@ where
if let Some(on_open_hyperlink) = &self.on_open_hyperlink {
if let Some(hyperlink) = get_hyperlink(&terminal, location) {
shell.publish(on_open_hyperlink(hyperlink));
status = Status::Captured;
shell.capture_event();
}
}
}
if is_mouse_mode {
terminal.report_mouse(event, &state.modifiers, col as u32, row as u32);
terminal.report_mouse(
event.clone(),
&state.modifiers,
col as u32,
row as u32,
);
} else {
status = Status::Captured;
shell.capture_event();
}
} else {
status = Status::Captured;
shell.capture_event();
}
}
Event::Mouse(MouseEvent::ButtonReleased(_button)) => {
@ -1309,7 +1342,12 @@ where
let col = x / terminal.size().cell_width;
let row = y / terminal.size().cell_height;
if is_mouse_mode {
terminal.report_mouse(event, &state.modifiers, col as u32, row as u32);
terminal.report_mouse(
event.clone(),
&state.modifiers,
col as u32,
row as u32,
);
}
}
}
@ -1351,7 +1389,12 @@ where
if is_mouse_mode {
if let Some((col, row)) = col_row_opt {
terminal.report_mouse(event, &state.modifiers, col as u32, row as u32);
terminal.report_mouse(
event.clone(),
&state.modifiers,
col as u32,
row as u32,
);
}
} else {
let handled_buffer_drag = update_buffer_drag(
@ -1364,7 +1407,7 @@ where
0.0,
);
if handled_buffer_drag {
status = Status::Captured;
shell.capture_event();
} else if let Some(Dragging::Scrollbar {
start_y,
start_scroll,
@ -1377,7 +1420,7 @@ where
(y - start_y) / buffer.size().1.unwrap_or(1.0)
});
terminal.scroll_to(start_scroll.0 + scroll_offset);
status = Status::Captured;
shell.capture_event();
}
if matches!(state.dragging, Some(Dragging::Buffer { .. })) {
@ -1389,7 +1432,7 @@ where
} else {
state.autoscroll.start(p_global);
}
shell.request_redraw(RedrawRequest::NextFrame);
shell.request_redraw();
}
} else {
state.autoscroll.stop();
@ -1405,15 +1448,15 @@ where
//TODO: better calculation of position
let col = x / terminal.size().cell_width;
let row = y / terminal.size().cell_height;
terminal.scroll_mouse(delta, &state.modifiers, col as u32, row as u32);
terminal.scroll_mouse(*delta, &state.modifiers, col as u32, row as u32);
} else if terminal.term.lock().mode().contains(TermMode::ALT_SCREEN) {
MouseReporter::report_mouse_wheel_as_arrows(
&terminal,
terminal.size().cell_width,
terminal.size().cell_height,
delta,
*delta,
);
status = Status::Captured;
shell.capture_event();
} else {
match delta {
ScrollDelta::Lines { x: _, y } => {
@ -1423,7 +1466,7 @@ where
if lines != 0 {
terminal.scroll(TerminalScroll::Delta(-lines));
}
status = Status::Captured;
shell.capture_event();
}
ScrollDelta::Pixels { x: _, y } => {
//TODO: this adjustment is just a guess!
@ -1441,7 +1484,7 @@ where
if lines != 0 {
terminal.scroll(TerminalScroll::Delta(-lines));
}
status = Status::Captured;
shell.capture_event();
}
}
}
@ -1466,8 +1509,6 @@ where
}
_ => (),
}
status
}
}