feat: blur
This commit is contained in:
parent
953478f801
commit
0b7803077a
5 changed files with 683 additions and 608 deletions
1020
Cargo.lock
generated
1020
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
19
Cargo.toml
19
Cargo.toml
|
|
@ -156,12 +156,17 @@ default-features = false
|
||||||
features = ["advanced-shaping"]
|
features = ["advanced-shaping"]
|
||||||
|
|
||||||
[patch."https://github.com/pop-os/cosmic-protocols"]
|
[patch."https://github.com/pop-os/cosmic-protocols"]
|
||||||
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols//" }
|
cctk = { git = "https://github.com/pop-os/cosmic-protocols//", package = "cosmic-client-toolkit", rev = "32283d7" }
|
||||||
cctk = { git = "https://github.com/pop-os/cosmic-protocols//", package = "cosmic-client-toolkit" }
|
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols//", rev = "32283d7" }
|
||||||
|
|
||||||
# [patch."https://github.com/pop-os/libcosmic"]
|
# [patch."https://github.com/pop-os/libcosmic"]
|
||||||
# iced_core = { git = "https://github.com/pop-os/libcosmic//" }
|
# iced_core = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
|
||||||
# iced_futures = { git = "https://github.com/pop-os/libcosmic//" }
|
# iced_futures = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
|
||||||
# libcosmic = { git = "https://github.com/pop-os/libcosmic//" }
|
# libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
|
||||||
# cosmic-config = { git = "https://github.com/pop-os/libcosmic//" }
|
# cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
|
||||||
# cosmic-theme = { git = "https://github.com/pop-os/libcosmic//" }
|
# cosmic-theme = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
|
||||||
|
# libcosmic = { path = "../libcosmic" }
|
||||||
|
# cosmic-config = { path = "../libcosmic/cosmic-config" }
|
||||||
|
# cosmic-theme = { path = "../libcosmic/cosmic-theme" }
|
||||||
|
# iced_futures = { path = "../libcosmic/iced/futures" }
|
||||||
|
# iced_winit = { path = "../libcosmic/iced/winit" }
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,16 @@ use cosmic::iced::core::SmolStr;
|
||||||
use cosmic::iced::event::wayland::{Event as WaylandEvent, OutputEvent, SessionLockEvent};
|
use cosmic::iced::event::wayland::{Event as WaylandEvent, OutputEvent, SessionLockEvent};
|
||||||
use cosmic::iced::event::{self};
|
use cosmic::iced::event::{self};
|
||||||
use cosmic::iced::keyboard::{Event as KeyEvent, Key, Modifiers};
|
use cosmic::iced::keyboard::{Event as KeyEvent, Key, Modifiers};
|
||||||
|
use cosmic::iced::platform_specific::shell::commands::blur::blur;
|
||||||
use cosmic::iced::runtime::core::window::Id as SurfaceId;
|
use cosmic::iced::runtime::core::window::Id as SurfaceId;
|
||||||
|
use cosmic::iced::runtime::platform_specific::wayland::CornerRadius;
|
||||||
use cosmic::iced::{self, Rectangle, Size, Subscription};
|
use cosmic::iced::{self, Rectangle, Size, Subscription};
|
||||||
use cosmic::widget;
|
use cosmic::surface::corner_radius::rounded_rect_strips;
|
||||||
|
use cosmic::widget::rectangle_tracker::{RectangleUpdate, rectangle_tracker_subscription};
|
||||||
|
use cosmic::widget::{self, RectangleTracker};
|
||||||
use cosmic_config::{ConfigSet, CosmicConfigEntry};
|
use cosmic_config::{ConfigSet, CosmicConfigEntry};
|
||||||
use cosmic_greeter_daemon::{BgSource, CosmicCompConfig, UserData};
|
use cosmic_greeter_daemon::{BgSource, CosmicCompConfig, UserData};
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wayland_client::protocol::wl_output::WlOutput;
|
use wayland_client::protocol::wl_output::WlOutput;
|
||||||
|
|
||||||
|
|
@ -39,8 +43,12 @@ pub struct Common<M> {
|
||||||
pub output_names: HashMap<WlOutput, String>,
|
pub output_names: HashMap<WlOutput, String>,
|
||||||
pub power_info_opt: Option<(widget::Icon, f64)>,
|
pub power_info_opt: Option<(widget::Icon, f64)>,
|
||||||
pub prompt_opt: Option<(String, bool, Option<String>)>,
|
pub prompt_opt: Option<(String, bool, Option<String>)>,
|
||||||
|
pub rectangle_tracker: Option<RectangleTracker<(SurfaceId, bool)>>,
|
||||||
|
pub rectangles: HashMap<(SurfaceId, bool), iced::Rectangle>,
|
||||||
|
pub include_menu: bool,
|
||||||
pub subsurface_rects: HashMap<WlOutput, Rectangle>,
|
pub subsurface_rects: HashMap<WlOutput, Rectangle>,
|
||||||
pub surface_ids: HashMap<WlOutput, SurfaceId>,
|
pub surface_ids: HashMap<WlOutput, SurfaceId>,
|
||||||
|
pub subsurface_outputs: HashMap<SurfaceId, WlOutput>,
|
||||||
pub surface_images: HashMap<SurfaceId, widget::image::Handle>,
|
pub surface_images: HashMap<SurfaceId, widget::image::Handle>,
|
||||||
pub surface_names: HashMap<SurfaceId, String>,
|
pub surface_names: HashMap<SurfaceId, String>,
|
||||||
pub text_input_ids: HashMap<String, widget::Id>,
|
pub text_input_ids: HashMap<String, widget::Id>,
|
||||||
|
|
@ -54,12 +62,14 @@ pub enum Message {
|
||||||
Focus(SurfaceId),
|
Focus(SurfaceId),
|
||||||
Key(Modifiers, Key, Option<SmolStr>),
|
Key(Modifiers, Key, Option<SmolStr>),
|
||||||
NetworkIcon(Option<&'static str>),
|
NetworkIcon(Option<&'static str>),
|
||||||
|
SubsurfaceOpened(SurfaceId),
|
||||||
OutputEvent(OutputEvent, WlOutput),
|
OutputEvent(OutputEvent, WlOutput),
|
||||||
PowerInfo(Option<(f64, bool, bool)>),
|
PowerInfo(Option<(f64, bool, bool)>),
|
||||||
Prompt(String, bool, Option<String>),
|
Prompt(String, bool, Option<String>),
|
||||||
SessionLockEvent(SessionLockEvent),
|
SessionLockEvent(SessionLockEvent),
|
||||||
Tick,
|
Tick,
|
||||||
Tz(jiff::tz::TimeZone),
|
Tz(jiff::tz::TimeZone),
|
||||||
|
Rectangle(RectangleUpdate<(SurfaceId, bool)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: From<Message> + Send + 'static> Common<M> {
|
impl<M: From<Message> + Send + 'static> Common<M> {
|
||||||
|
|
@ -118,6 +128,10 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
||||||
battery_percent: 0.0,
|
battery_percent: 0.0,
|
||||||
on_battery: false,
|
on_battery: false,
|
||||||
charging_limit: None,
|
charging_limit: None,
|
||||||
|
subsurface_outputs: HashMap::new(),
|
||||||
|
rectangle_tracker: None,
|
||||||
|
rectangles: HashMap::new(),
|
||||||
|
include_menu: false,
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
app,
|
app,
|
||||||
|
|
@ -322,13 +336,75 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
||||||
Message::Tz(tz) => {
|
Message::Tz(tz) => {
|
||||||
self.time.set_tz(tz);
|
self.time.set_tz(tz);
|
||||||
}
|
}
|
||||||
|
Message::SubsurfaceOpened(id) => {
|
||||||
|
return self.blur_rects(id);
|
||||||
|
}
|
||||||
|
Message::Rectangle(u) => match u {
|
||||||
|
RectangleUpdate::Rectangle(r) => {
|
||||||
|
self.rectangles.insert(r.0, r.1);
|
||||||
|
|
||||||
|
return self.blur_rects(r.0.0);
|
||||||
|
}
|
||||||
|
RectangleUpdate::Init(tracker) => {
|
||||||
|
self.rectangle_tracker.replace(tracker);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn dropdown_blur_rects(&mut self, enable: bool) -> Task<M> {
|
||||||
|
let mut ids = HashSet::new();
|
||||||
|
for r in self.rectangles.keys() {
|
||||||
|
ids.insert(r.0);
|
||||||
|
}
|
||||||
|
self.include_menu = enable;
|
||||||
|
Task::batch(
|
||||||
|
ids.into_iter()
|
||||||
|
.map(|i| self.blur_rects(i))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blur_rects(&mut self, id: SurfaceId) -> Task<M> {
|
||||||
|
if let Some(output) = self.subsurface_outputs.get(&id) {
|
||||||
|
if let Some(rect) = self.subsurface_rects.get(output) {
|
||||||
|
let x = rect.x;
|
||||||
|
let y = rect.y;
|
||||||
|
if let Some(rect) = self.rectangles.get(&(id, false)) {
|
||||||
|
let mut offset_rect = *rect;
|
||||||
|
offset_rect.x += x;
|
||||||
|
offset_rect.y += y;
|
||||||
|
let rad = CornerRadius {
|
||||||
|
top_left: 16,
|
||||||
|
top_right: 16,
|
||||||
|
bottom_left: 16,
|
||||||
|
bottom_right: 16,
|
||||||
|
};
|
||||||
|
let mut rects = rounded_rect_strips(offset_rect, rad);
|
||||||
|
if let Some(other_rect) = self.rectangles.get(&(id, true))
|
||||||
|
&& self.include_menu
|
||||||
|
{
|
||||||
|
let mut other = *other_rect;
|
||||||
|
other.x += x;
|
||||||
|
other.y += y;
|
||||||
|
|
||||||
|
rects.append(&mut rounded_rect_strips(other, rad));
|
||||||
|
}
|
||||||
|
|
||||||
|
return blur(id, Some(rects)).discard();
|
||||||
|
} else {
|
||||||
|
tracing::error!("no rectangle for surface {id:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subscription(&self) -> Subscription<Message> {
|
pub fn subscription(&self) -> Subscription<Message> {
|
||||||
let mut subscriptions = Vec::with_capacity(3);
|
let mut subscriptions = Vec::with_capacity(3);
|
||||||
|
subscriptions
|
||||||
|
.push(rectangle_tracker_subscription(0).map(|update| Message::Rectangle(update.1)));
|
||||||
subscriptions.push(event::listen_with(|event, status, id| match event {
|
subscriptions.push(event::listen_with(|event, status, id| match event {
|
||||||
iced::Event::Keyboard(KeyEvent::KeyPressed {
|
iced::Event::Keyboard(KeyEvent::KeyPressed {
|
||||||
key,
|
key,
|
||||||
|
|
@ -351,6 +427,9 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
||||||
WaylandEvent::SessionLock(lock_event) => {
|
WaylandEvent::SessionLock(lock_event) => {
|
||||||
Some(Message::SessionLockEvent(lock_event))
|
Some(Message::SessionLockEvent(lock_event))
|
||||||
}
|
}
|
||||||
|
iced::event::wayland::Event::Subsurface(
|
||||||
|
iced::event::wayland::SubsurfaceEvent::Created,
|
||||||
|
) => Some(Message::SubsurfaceOpened(id)),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
iced::Event::Window(iced::window::Event::Focused) => Some(Message::Focus(id)),
|
iced::Event::Window(iced::window::Event::Focused) => Some(Message::Focus(id)),
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ use cosmic::iced::platform_specific::shell::wayland::commands::subsurface::repos
|
||||||
use cosmic::iced::runtime::core::window::Id as SurfaceId;
|
use cosmic::iced::runtime::core::window::Id as SurfaceId;
|
||||||
use cosmic::iced::runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings;
|
use cosmic::iced::runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings;
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
self, Alignment, Background, Border, Length, Point, Size, Subscription, window,
|
self, Alignment, Background, Border, Length, Point, Rectangle, Size, Subscription, window,
|
||||||
};
|
};
|
||||||
use cosmic::widget::{id_container, text};
|
use cosmic::widget::{id_container, text};
|
||||||
use cosmic::{Element, executor, surface, theme, widget};
|
use cosmic::{Element, executor, surface, theme, widget};
|
||||||
|
|
@ -547,12 +547,12 @@ impl App {
|
||||||
Element::from(items)
|
Element::from(items)
|
||||||
};
|
};
|
||||||
|
|
||||||
widget::container(items)
|
let menu = widget::container(items)
|
||||||
.padding(1)
|
.padding(1)
|
||||||
//TODO: move style to libcosmic
|
//TODO: move style to libcosmic
|
||||||
.class(theme::Container::custom(|theme| {
|
.class(theme::Container::custom(|theme| {
|
||||||
let cosmic = theme.cosmic();
|
let cosmic = theme.cosmic();
|
||||||
let component = &cosmic.background.component;
|
let component = &cosmic.background(theme.transparent).component;
|
||||||
widget::container::Style {
|
widget::container::Style {
|
||||||
icon_color: Some(component.on.into()),
|
icon_color: Some(component.on.into()),
|
||||||
text_color: Some(component.on.into()),
|
text_color: Some(component.on.into()),
|
||||||
|
|
@ -565,7 +565,13 @@ impl App {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.width(Length::Fixed(240.0))
|
.width(Length::Fixed(240.0));
|
||||||
|
|
||||||
|
if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||||
|
Element::from(t.container((id, true), menu))
|
||||||
|
} else {
|
||||||
|
menu.into()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut input_button = widget::popover(
|
let mut input_button = widget::popover(
|
||||||
|
|
@ -928,29 +934,37 @@ impl App {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let menu = widget::layer_container(
|
||||||
|
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||||
|
)
|
||||||
|
.layer(cosmic::cosmic_theme::Layer::Background)
|
||||||
|
.padding(16)
|
||||||
|
.class(cosmic::theme::Container::Custom(Box::new(
|
||||||
|
|theme: &cosmic::Theme| {
|
||||||
|
// Use background appearance as the base
|
||||||
|
let mut appearance =
|
||||||
|
widget::container::Catalog::style(theme, &cosmic::theme::Container::Background);
|
||||||
|
appearance.background = Some(iced::Background::Color(
|
||||||
|
// TODO if we can use popups instead of subsurfaces for the greeter and the lockscreen
|
||||||
|
// then we can allow transparency
|
||||||
|
theme.cosmic().background(theme.transparent).base.into(),
|
||||||
|
));
|
||||||
|
appearance.border = iced::Border::default().rounded(16);
|
||||||
|
appearance
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
.width(Length::Fixed(800.0));
|
||||||
|
let menu = if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||||
|
Element::from(t.container((id, false), menu))
|
||||||
|
} else {
|
||||||
|
menu.into()
|
||||||
|
};
|
||||||
let menu = widget::container(widget::column::with_children(vec![
|
let menu = widget::container(widget::column::with_children(vec![
|
||||||
widget::space::vertical()
|
widget::space::vertical()
|
||||||
.height(Length::FillPortion(1))
|
.height(Length::FillPortion(1))
|
||||||
.into(),
|
.into(),
|
||||||
widget::layer_container(
|
menu,
|
||||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
|
||||||
)
|
|
||||||
.layer(cosmic::cosmic_theme::Layer::Background)
|
|
||||||
.padding(16)
|
|
||||||
.class(cosmic::theme::Container::Custom(Box::new(
|
|
||||||
|theme: &cosmic::Theme| {
|
|
||||||
// Use background appearance as the base
|
|
||||||
let mut appearance = widget::container::Catalog::style(
|
|
||||||
theme,
|
|
||||||
&cosmic::theme::Container::Background,
|
|
||||||
);
|
|
||||||
appearance.border = iced::Border::default().rounded(16);
|
|
||||||
appearance
|
|
||||||
},
|
|
||||||
)))
|
|
||||||
.class(cosmic::theme::Container::Background)
|
|
||||||
.width(Length::Fixed(800.0))
|
|
||||||
.into(),
|
|
||||||
widget::space::vertical()
|
widget::space::vertical()
|
||||||
.height(Length::FillPortion(4))
|
.height(Length::FillPortion(4))
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -959,6 +973,7 @@ impl App {
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.align_x(Alignment::Center);
|
.align_x(Alignment::Center);
|
||||||
|
|
||||||
|
// TODO make these opaque?
|
||||||
let popover = widget::popover(menu).modal(true);
|
let popover = widget::popover(menu).modal(true);
|
||||||
match self.dialog_page_opt {
|
match self.dialog_page_opt {
|
||||||
Some(DialogPage::Restart(instant)) => {
|
Some(DialogPage::Restart(instant)) => {
|
||||||
|
|
@ -1090,7 +1105,8 @@ impl cosmic::Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the application, and optionally emits command on initialize.
|
/// Creates the application, and optionally emits command on initialize.
|
||||||
fn init(core: Core, flags: Self::Flags) -> (Self, Task<Message>) {
|
fn init(mut core: Core, flags: Self::Flags) -> (Self, Task<Message>) {
|
||||||
|
core.set_app_type(cosmic::core::AppType::System);
|
||||||
let mut tasks = Vec::new();
|
let mut tasks = Vec::new();
|
||||||
let (mut common, common_task) = Common::init(core);
|
let (mut common, common_task) = Common::init(core);
|
||||||
common.on_output_event = Some(Box::new(|output_event, output| {
|
common.on_output_event = Some(Box::new(|output_event, output| {
|
||||||
|
|
@ -1251,7 +1267,12 @@ impl cosmic::Application for App {
|
||||||
surface_id,
|
surface_id,
|
||||||
Size::new(unwrapped_size.0 as f32, unwrapped_size.1 as f32),
|
Size::new(unwrapped_size.0 as f32, unwrapped_size.1 as f32),
|
||||||
);
|
);
|
||||||
|
self.common
|
||||||
|
.subsurface_rects
|
||||||
|
.insert(output.clone(), Rectangle::new(loc, sub_size));
|
||||||
|
self.common
|
||||||
|
.subsurface_outputs
|
||||||
|
.insert(subsurface_id, output.clone());
|
||||||
let msg = cosmic::surface::action::subsurface(
|
let msg = cosmic::surface::action::subsurface(
|
||||||
move |_: &mut App| SctkSubsurfaceSettings {
|
move |_: &mut App| SctkSubsurfaceSettings {
|
||||||
parent: surface_id,
|
parent: surface_id,
|
||||||
|
|
@ -1330,6 +1351,7 @@ impl cosmic::Application for App {
|
||||||
self.selected_session = selected_session;
|
self.selected_session = selected_session;
|
||||||
if self.dropdown_opt == Some(Dropdown::Session) {
|
if self.dropdown_opt == Some(Dropdown::Session) {
|
||||||
self.dropdown_opt = None;
|
self.dropdown_opt = None;
|
||||||
|
return self.common.dropdown_blur_rects(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::EnterUser(focus_input, username) => {
|
Message::EnterUser(focus_input, username) => {
|
||||||
|
|
@ -1346,7 +1368,10 @@ impl cosmic::Application for App {
|
||||||
username,
|
username,
|
||||||
};
|
};
|
||||||
if focus_input {
|
if focus_input {
|
||||||
return widget::text_input::focus(USERNAME_ID.clone());
|
return Task::batch([
|
||||||
|
self.common.dropdown_blur_rects(false),
|
||||||
|
widget::text_input::focus(USERNAME_ID.clone()),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Username(username) => {
|
Message::Username(username) => {
|
||||||
|
|
@ -1384,9 +1409,12 @@ impl cosmic::Application for App {
|
||||||
self.send_request(Request::CancelSession);
|
self.send_request(Request::CancelSession);
|
||||||
}
|
}
|
||||||
if let Some(randr_list) = self.randr_list.as_ref() {
|
if let Some(randr_list) = self.randr_list.as_ref() {
|
||||||
return self.update(Message::RandrUpdate {
|
return Task::batch([
|
||||||
randr: Arc::new(Ok(randr_list.clone())),
|
self.common.dropdown_blur_rects(false),
|
||||||
});
|
self.update(Message::RandrUpdate {
|
||||||
|
randr: Arc::new(Ok(randr_list.clone())),
|
||||||
|
}),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1529,8 +1557,10 @@ impl cosmic::Application for App {
|
||||||
Message::DropdownToggle(dropdown) => {
|
Message::DropdownToggle(dropdown) => {
|
||||||
if self.dropdown_opt == Some(dropdown) {
|
if self.dropdown_opt == Some(dropdown) {
|
||||||
self.dropdown_opt = None;
|
self.dropdown_opt = None;
|
||||||
|
return self.common.dropdown_blur_rects(false);
|
||||||
} else {
|
} else {
|
||||||
self.dropdown_opt = Some(dropdown);
|
self.dropdown_opt = Some(dropdown);
|
||||||
|
return self.common.dropdown_blur_rects(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::KeyboardLayout(layout_i) => {
|
Message::KeyboardLayout(layout_i) => {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use cosmic::iced::runtime::platform_specific::wayland::subsurface::SctkSubsurfac
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
self, Alignment, Background, Border, Length, Point, Rectangle, Size, Subscription,
|
self, Alignment, Background, Border, Length, Point, Rectangle, Size, Subscription,
|
||||||
};
|
};
|
||||||
|
use cosmic::widget::indeterminate_circular;
|
||||||
use cosmic::{Element, executor, surface, theme, widget};
|
use cosmic::{Element, executor, surface, theme, widget};
|
||||||
use cosmic_config::CosmicConfigEntry;
|
use cosmic_config::CosmicConfigEntry;
|
||||||
use cosmic_greeter_daemon::{TimeAppletConfig, UserData};
|
use cosmic_greeter_daemon::{TimeAppletConfig, UserData};
|
||||||
|
|
@ -382,12 +383,12 @@ impl App {
|
||||||
Element::from(items)
|
Element::from(items)
|
||||||
};
|
};
|
||||||
|
|
||||||
widget::container(items)
|
let menu = widget::container(items)
|
||||||
.padding(1)
|
.padding(1)
|
||||||
//TODO: move style to libcosmic
|
//TODO: move style to libcosmic
|
||||||
.class(theme::Container::custom(|theme| {
|
.class(theme::Container::custom(|theme| {
|
||||||
let cosmic = theme.cosmic();
|
let cosmic = theme.cosmic();
|
||||||
let component = &cosmic.background.component;
|
let component = &cosmic.background(theme.transparent).component;
|
||||||
widget::container::Style {
|
widget::container::Style {
|
||||||
icon_color: Some(component.on.into()),
|
icon_color: Some(component.on.into()),
|
||||||
text_color: Some(component.on.into()),
|
text_color: Some(component.on.into()),
|
||||||
|
|
@ -400,7 +401,13 @@ impl App {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.width(Length::Fixed(240.0))
|
.width(Length::Fixed(240.0));
|
||||||
|
|
||||||
|
if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||||
|
Element::from(t.container((surface_id, true), menu))
|
||||||
|
} else {
|
||||||
|
menu.into()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut input_button = widget::popover(
|
let mut input_button = widget::popover(
|
||||||
|
|
@ -585,30 +592,34 @@ impl App {
|
||||||
.align_x(Alignment::Center)
|
.align_x(Alignment::Center)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
};
|
};
|
||||||
|
let menu = widget::layer_container(
|
||||||
|
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||||
|
)
|
||||||
|
.layer(cosmic::cosmic_theme::Layer::Background)
|
||||||
|
.padding(16)
|
||||||
|
.class(cosmic::theme::Container::Custom(Box::new(
|
||||||
|
|theme: &cosmic::Theme| {
|
||||||
|
// Use background appearance as the base
|
||||||
|
let mut appearance =
|
||||||
|
widget::container::Catalog::style(theme, &cosmic::theme::Container::Background);
|
||||||
|
let c: iced::Color = theme.cosmic().background(theme.transparent).base.into();
|
||||||
|
appearance.background = Some(iced::Background::Color(c));
|
||||||
|
appearance.border = iced::Border::default().rounded(16.0);
|
||||||
|
appearance
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Shrink);
|
||||||
|
let menu = if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||||
|
Element::from(t.container((surface_id, false), menu))
|
||||||
|
} else {
|
||||||
|
menu.into()
|
||||||
|
};
|
||||||
widget::container(widget::column::with_children(vec![
|
widget::container(widget::column::with_children(vec![
|
||||||
widget::space::vertical()
|
widget::space::vertical()
|
||||||
.height(Length::FillPortion(1))
|
.height(Length::FillPortion(1))
|
||||||
.into(),
|
.into(),
|
||||||
widget::layer_container(
|
menu,
|
||||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
|
||||||
)
|
|
||||||
.layer(cosmic::cosmic_theme::Layer::Background)
|
|
||||||
.padding(16)
|
|
||||||
.class(cosmic::theme::Container::Custom(Box::new(
|
|
||||||
|theme: &cosmic::Theme| {
|
|
||||||
// Use background appearance as the base
|
|
||||||
let mut appearance = widget::container::Catalog::style(
|
|
||||||
theme,
|
|
||||||
&cosmic::theme::Container::Background,
|
|
||||||
);
|
|
||||||
appearance.border = iced::Border::default().rounded(16.0);
|
|
||||||
appearance
|
|
||||||
},
|
|
||||||
)))
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Shrink)
|
|
||||||
.into(),
|
|
||||||
widget::space::vertical()
|
widget::space::vertical()
|
||||||
.height(Length::FillPortion(4))
|
.height(Length::FillPortion(4))
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -644,7 +655,8 @@ impl cosmic::Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the application, and optionally emits command on initialize.
|
/// Creates the application, and optionally emits command on initialize.
|
||||||
fn init(core: Core, flags: Self::Flags) -> (Self, Task<Self::Message>) {
|
fn init(mut core: Core, flags: Self::Flags) -> (Self, Task<Self::Message>) {
|
||||||
|
core.set_app_type(cosmic::core::AppType::System);
|
||||||
let (mut common, common_task) = Common::init(core);
|
let (mut common, common_task) = Common::init(core);
|
||||||
common.on_output_event = Some(Box::new(|output_event, output| {
|
common.on_output_event = Some(Box::new(|output_event, output| {
|
||||||
Message::OutputEvent(output_event, output)
|
Message::OutputEvent(output_event, output)
|
||||||
|
|
@ -714,6 +726,10 @@ impl cosmic::Application for App {
|
||||||
return Task::none();
|
return Task::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.common
|
||||||
|
.subsurface_outputs
|
||||||
|
.insert(subsurface_id, output.clone());
|
||||||
|
|
||||||
let size = if let Some((w, h)) =
|
let size = if let Some((w, h)) =
|
||||||
output_info_opt.as_ref().and_then(|info| info.logical_size)
|
output_info_opt.as_ref().and_then(|info| info.logical_size)
|
||||||
{
|
{
|
||||||
|
|
@ -791,11 +807,11 @@ impl cosmic::Application for App {
|
||||||
);
|
);
|
||||||
|
|
||||||
if matches!(self.state, State::Locked { .. }) {
|
if matches!(self.state, State::Locked { .. }) {
|
||||||
return Task::batch([get_lock_surface(surface_id, output).chain({
|
return get_lock_surface(surface_id, output).chain({
|
||||||
cosmic::task::message(cosmic::Action::Cosmic(
|
cosmic::task::message(cosmic::Action::Cosmic(
|
||||||
cosmic::app::Action::Surface(msg),
|
cosmic::app::Action::Surface(msg),
|
||||||
))
|
))
|
||||||
})]);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutputEvent::Removed => {
|
OutputEvent::Removed => {
|
||||||
|
|
@ -945,11 +961,15 @@ impl cosmic::Application for App {
|
||||||
.zip(self.common.output_names.get(output))
|
.zip(self.common.output_names.get(output))
|
||||||
{
|
{
|
||||||
let subsurface_id = SurfaceId::unique();
|
let subsurface_id = SurfaceId::unique();
|
||||||
|
self.common
|
||||||
|
.subsurface_outputs
|
||||||
|
.insert(subsurface_id, output.clone());
|
||||||
let surface_id = *surface_id;
|
let surface_id = *surface_id;
|
||||||
self.common.surface_names.insert(surface_id, name.clone());
|
self.common.surface_names.insert(surface_id, name.clone());
|
||||||
self.common
|
self.common
|
||||||
.surface_names
|
.surface_names
|
||||||
.insert(subsurface_id, name.clone());
|
.insert(subsurface_id, name.clone());
|
||||||
|
|
||||||
let msg = cosmic::surface::action::subsurface(
|
let msg = cosmic::surface::action::subsurface(
|
||||||
move |_: &mut App| SctkSubsurfaceSettings {
|
move |_: &mut App| SctkSubsurfaceSettings {
|
||||||
parent: surface_id,
|
parent: surface_id,
|
||||||
|
|
@ -970,7 +990,7 @@ impl cosmic::Application for App {
|
||||||
cosmic::app::Action::Surface(msg),
|
cosmic::app::Action::Surface(msg),
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
tracing::error!("no rectangle for subsurface...");
|
tracing::error!("no rectangle for subsurface creation...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Task::batch(commands);
|
return Task::batch(commands);
|
||||||
|
|
@ -1009,8 +1029,10 @@ impl cosmic::Application for App {
|
||||||
Message::DropdownToggle(dropdown) => {
|
Message::DropdownToggle(dropdown) => {
|
||||||
if self.dropdown_opt == Some(dropdown) {
|
if self.dropdown_opt == Some(dropdown) {
|
||||||
self.dropdown_opt = None;
|
self.dropdown_opt = None;
|
||||||
|
return self.common.dropdown_blur_rects(false);
|
||||||
} else {
|
} else {
|
||||||
self.dropdown_opt = Some(dropdown);
|
self.dropdown_opt = Some(dropdown);
|
||||||
|
return self.common.dropdown_blur_rects(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Inhibit(inhibit) => match self.state {
|
Message::Inhibit(inhibit) => match self.state {
|
||||||
|
|
@ -1027,7 +1049,8 @@ impl cosmic::Application for App {
|
||||||
self.common.set_xkb_config(&self.flags.user_data);
|
self.common.set_xkb_config(&self.flags.user_data);
|
||||||
}
|
}
|
||||||
if self.dropdown_opt == Some(Dropdown::Keyboard) {
|
if self.dropdown_opt == Some(Dropdown::Keyboard) {
|
||||||
self.dropdown_opt = None
|
self.dropdown_opt = None;
|
||||||
|
return self.common.dropdown_blur_rects(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Submit(value) => {
|
Message::Submit(value) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue