Update iced/libcosmic

This commit is contained in:
Ian Douglas Scott 2024-10-18 13:13:53 -07:00 committed by Ian Douglas Scott
parent e0c0f27f67
commit b70828e23f
17 changed files with 2019 additions and 1262 deletions

2796
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ cosmic-comp-config = { git = "https://github.com/pop-os/cosmic-comp" }
env_logger = "0.11.0"
futures-channel = "0.3.25"
gbm = "0.15.0"
libcosmic = { git = "https://github.com/pop-os/libcosmic", default-features = false, features = ["tokio", "wayland", "single-instance"] }
libcosmic = { git = "https://github.com/pop-os/libcosmic", default-features = false, features = ["tokio", "wayland", "single-instance", "multi-window", "winit"] }
cosmic-config = { git = "https://github.com/pop-os/libcosmic" }
freedesktop-desktop-entry = "0.5.0"
freedesktop-icons = "0.2.4"
@ -45,7 +45,3 @@ mock-backend = []
[profile.dev]
# Not usable at opt-level 0, at least with software renderer
opt-level = 1
# [patch."https://github.com/pop-os/libcosmic"]
# libcosmic = { path = "../libcosmic" }
# cosmic-config = { path = "../libcosmic/cosmic-config" }

View file

@ -16,7 +16,7 @@ use cosmic::{
self,
futures::{executor::block_on, FutureExt, SinkExt},
},
iced_sctk::subsurface_widget::{Shmbuf, SubsurfaceBuffer},
iced_winit::platform_specific::wayland::subsurface_widget::{Shmbuf, SubsurfaceBuffer},
};
use futures_channel::mpsc;
@ -61,11 +61,7 @@ fn create_solid_capture_image(r: u8, g: u8, b: u8) -> CaptureImage {
))
.0,
#[cfg(feature = "no-subsurfaces")]
image: cosmic::widget::image::Handle::from_pixels(
512,
512,
[r, g, b, 255].repeat(512 * 512),
),
image: cosmic::widget::image::Handle::from_rgba(512, 512, [r, g, b, 255].repeat(512 * 512)),
}
}
@ -108,7 +104,7 @@ pub struct Workspace {
}
pub fn subscription(conn: Connection) -> iced::Subscription<Event> {
iced::subscription::run_with_id("wayland-mock-sub", async { start(conn) }.flatten_stream())
iced::Subscription::run_with_id("wayland-mock-sub", async { start(conn) }.flatten_stream())
}
struct AppData {

View file

@ -8,7 +8,8 @@
//! backend for testing without any special protocols.
use cosmic::{
cctk::wayland_client::protocol::wl_output, iced_sctk::subsurface_widget::SubsurfaceBuffer,
cctk::wayland_client::protocol::wl_output,
iced_winit::platform_specific::wayland::subsurface_widget::SubsurfaceBuffer,
};
use std::collections::HashSet;

View file

@ -7,7 +7,9 @@ use cctk::{
};
use cosmic::{
cctk,
iced_sctk::subsurface_widget::{BufferSource, Dmabuf, Plane, Shmbuf},
iced_winit::platform_specific::wayland::subsurface_widget::{
BufferSource, Dmabuf, Plane, Shmbuf,
},
};
use std::{
os::fd::AsFd,

View file

@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex};
use super::{AppData, ScreencopySession, SessionData};
#[derive(Clone, Hash, PartialEq, Eq)]
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum CaptureSource {
Toplevel(zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1),
Workspace(

View file

@ -41,7 +41,7 @@ mod workspace;
use super::{CaptureFilter, CaptureImage, Cmd, Event};
pub fn subscription(conn: Connection) -> iced::Subscription<Event> {
iced::subscription::run_with_id("wayland-sub", async { start(conn) }.flatten_stream())
iced::Subscription::run_with_id("wayland-sub", async { start(conn) }.flatten_stream())
}
pub struct AppData {

View file

@ -11,7 +11,9 @@ use cosmic::{
},
wayland_client::{Connection, Proxy, QueueHandle, WEnum},
},
iced_sctk::subsurface_widget::{SubsurfaceBuffer, SubsurfaceBufferRelease},
iced_winit::platform_specific::wayland::subsurface_widget::{
SubsurfaceBuffer, SubsurfaceBufferRelease,
},
};
use std::{
array,
@ -206,7 +208,7 @@ impl ScreencopyHandler for AppData {
width: front.size.0,
height: front.size.1,
#[cfg(feature = "no-subsurfaces")]
image: cosmic::widget::image::Handle::from_pixels(
image: cosmic::widget::image::Handle::from_rgba(
front.size.0,
front.size.1,
front.mmap.to_vec(),

View file

@ -6,10 +6,7 @@
use cctk::{
cosmic_protocols::workspace::v1::client::zcosmic_workspace_handle_v1,
sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer},
wayland_client::{
protocol::{wl_data_device_manager::DndAction, wl_output},
Connection, Proxy, WEnum,
},
wayland_client::{protocol::wl_output, Connection, Proxy, WEnum},
};
use clap::Parser;
use cosmic::{
@ -17,31 +14,29 @@ use cosmic::{
cctk,
iced::{
self,
clipboard::mime::AsMimeTypes,
event::wayland::{Event as WaylandEvent, OutputEvent},
keyboard::key::{Key, Named},
wayland::{
actions::data_device::{DataFromMimeType, DndIcon},
data_device::{accept_mime_type, request_dnd_data, set_actions, start_drag},
},
widget, Command, Size, Subscription, Vector,
Size, Subscription, Task,
},
iced_runtime::{
command::platform_specific::wayland::layer_surface::{
IcedOutput, SctkLayerSurfaceSettings,
},
window::Id as SurfaceId,
iced_core::window::Id as SurfaceId,
iced_runtime::platform_specific::wayland::layer_surface::{
IcedOutput, SctkLayerSurfaceSettings,
},
iced_winit::platform_specific::wayland::commands::layer_surface::{
destroy_layer_surface, get_layer_surface,
},
iced_sctk::commands::layer_surface::{destroy_layer_surface, get_layer_surface},
};
use cosmic_comp_config::CosmicCompConfig;
use cosmic_config::{cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry};
use i18n_embed::DesktopLanguageRequester;
use once_cell::sync::Lazy;
use std::{
borrow::Cow,
collections::{HashMap, HashSet},
mem,
path::PathBuf,
str::{self, FromStr},
str,
};
mod desktop_info;
@ -90,20 +85,41 @@ impl CosmicFlags for Args {
}
}
struct WlDndId {
mime_type: &'static str,
}
// TODO store protocol object id?
#[derive(Clone, Debug)]
struct DragToplevel {}
impl DataFromMimeType for WlDndId {
fn from_mime_type(&self, mime_type: &str) -> Option<Vec<u8>> {
if mime_type == self.mime_type {
Some(Vec::new())
impl AsMimeTypes for DragToplevel {
fn available(&self) -> Cow<'static, [String]> {
vec![TOPLEVEL_MIME.clone()].into()
}
fn as_bytes(&self, mime_type: &str) -> Option<Cow<'static, [u8]>> {
if mime_type == *TOPLEVEL_MIME {
Some(Vec::new().into())
} else {
None
}
}
}
impl cosmic::iced::clipboard::mime::AllowedMimeTypes for DragToplevel {
fn allowed() -> Cow<'static, [String]> {
vec![crate::TOPLEVEL_MIME.clone()].into()
}
}
impl TryFrom<(Vec<u8>, std::string::String)> for DragToplevel {
type Error = ();
fn try_from((bytes, mime_type): (Vec<u8>, String)) -> Result<Self, ()> {
if mime_type == *TOPLEVEL_MIME {
Ok(Self {})
} else {
Err(())
}
}
}
#[derive(Clone, Debug)]
enum Msg {
WaylandEvent(WaylandEvent),
@ -114,23 +130,24 @@ enum Msg {
CloseWorkspace(ZcosmicWorkspaceHandleV1),
ActivateToplevel(ZcosmicToplevelHandleV1),
CloseToplevel(ZcosmicToplevelHandleV1),
StartDrag(Size, Vector, DragSurface),
//StartDrag(Size, Vector, DragSurface),
StartDrag(DragSurface),
DndWorkspaceEnter(
ZcosmicWorkspaceHandleV1,
wl_output::WlOutput,
DndAction,
f64,
f64,
Vec<String>,
(f32, f32),
),
DndWorkspaceLeave(ZcosmicWorkspaceHandleV1, wl_output::WlOutput),
DndWorkspaceDrop,
DndWorkspaceData(String, Vec<u8>),
DndWorkspaceDrop(DragToplevel),
SourceFinished,
#[allow(dead_code)]
NewWorkspace,
CompConfig(Box<CosmicCompConfig>),
Config(CosmicWorkspacesConfig),
BgConfig(cosmic_bg_config::state::State),
Ignore,
}
#[derive(Debug)]
@ -142,7 +159,7 @@ struct Workspace {
is_active: bool,
}
#[derive(Debug)]
#[derive(Clone, Debug)]
struct Toplevel {
handle: ZcosmicToplevelHandleV1,
info: ToplevelInfo,
@ -193,7 +210,7 @@ struct App {
conn: Option<Connection>,
visible: bool,
wayland_cmd_sender: Option<calloop::channel::Sender<backend::Cmd>>,
drag_surface: Option<(SurfaceId, DragSurface, Size)>,
drag_surface: Option<(DragSurface, Size)>,
conf: Conf,
core: cosmic::app::Core,
drop_target: Option<(ZcosmicWorkspaceHandleV1, wl_output::WlOutput)>,
@ -218,10 +235,7 @@ impl App {
self.toplevels.iter_mut().find(|i| &i.handle == handle)
}
fn create_surface(
&mut self,
output: wl_output::WlOutput,
) -> Command<cosmic::app::Message<Msg>> {
fn create_surface(&mut self, output: wl_output::WlOutput) -> Task<cosmic::app::Message<Msg>> {
let id = SurfaceId::unique();
self.layer_surfaces.insert(
id,
@ -241,10 +255,7 @@ impl App {
})
}
fn destroy_surface(
&mut self,
output: &wl_output::WlOutput,
) -> Command<cosmic::app::Message<Msg>> {
fn destroy_surface(&mut self, output: &wl_output::WlOutput) -> Task<cosmic::app::Message<Msg>> {
if let Some((id, _)) = self
.layer_surfaces
.iter()
@ -254,11 +265,11 @@ impl App {
self.layer_surfaces.remove(&id).unwrap();
destroy_layer_surface(id)
} else {
Command::none()
Task::none()
}
}
fn toggle(&mut self) -> Command<cosmic::app::Message<Msg>> {
fn toggle(&mut self) -> Task<cosmic::app::Message<Msg>> {
if self.visible {
self.hide()
} else {
@ -266,11 +277,11 @@ impl App {
}
}
fn show(&mut self) -> Command<cosmic::app::Message<Msg>> {
fn show(&mut self) -> Task<cosmic::app::Message<Msg>> {
if !self.visible {
self.visible = true;
let outputs = self.outputs.clone();
let cmd = Command::batch(
let cmd = Task::batch(
outputs
.into_iter()
.map(|output| self.create_surface(output.handle))
@ -280,16 +291,16 @@ impl App {
cmd
} else {
Command::none()
Task::none()
}
}
// Close all shell surfaces
fn hide(&mut self) -> Command<cosmic::app::Message<Msg>> {
fn hide(&mut self) -> Task<cosmic::app::Message<Msg>> {
self.visible = false;
self.update_capture_filter();
self.drag_surface = None;
Command::batch(
Task::batch(
mem::take(&mut self.layer_surfaces)
.into_keys()
.map(destroy_layer_surface)
@ -325,21 +336,18 @@ impl Application for App {
type Flags = Args;
const APP_ID: &'static str = "com.system76.CosmicWorkspaces";
fn init(
core: cosmic::app::Core,
_flags: Self::Flags,
) -> (Self, iced::Command<Message<Self::Message>>) {
fn init(core: cosmic::app::Core, _flags: Self::Flags) -> (Self, Task<Message<Self::Message>>) {
(
Self {
core,
..Default::default()
},
Command::none(),
Task::none(),
)
}
// TODO: show panel and dock? Drag?
fn update(&mut self, message: Msg) -> Command<cosmic::app::Message<Msg>> {
fn update(&mut self, message: Msg) -> Task<cosmic::app::Message<Msg>> {
match message {
Msg::SourceFinished => {
self.drag_surface = None;
@ -455,13 +463,14 @@ impl Application for App {
}
}
backend::Event::WorkspaceCapture(handle, output_name, image) => {
//println!("Workspace capture");
if let Some(workspace) = self.workspace_for_handle_mut(&handle) {
workspace.img_for_output.insert(output_name, image);
}
}
backend::Event::ToplevelCapture(handle, image) => {
if let Some(toplevel) = self.toplevel_for_handle_mut(&handle) {
//println!("Got toplevel image!");
// println!("Got toplevel image!");
toplevel.img = Some(image);
}
}
@ -495,37 +504,11 @@ impl Application for App {
// TODO confirmation?
self.send_wayland_cmd(backend::Cmd::CloseToplevel(toplevel_handle));
}
Msg::StartDrag(size, offset, drag_surface) => {
let (output, mime_type) = match &drag_surface {
DragSurface::Workspace { handle: _, output } => (output, &*WORKSPACE_MIME),
DragSurface::Toplevel { handle: _, output } => (output, &*TOPLEVEL_MIME),
};
let id = SurfaceId::unique();
if let Some((parent_id, _)) = self
.layer_surfaces
.iter()
.find(|(_, x)| &x.output == output)
{
self.drag_surface = Some((id, drag_surface, size));
return start_drag(
vec![mime_type.to_string()],
DndAction::Move,
*parent_id,
Some((DndIcon::Custom(id), offset * -1.0)),
Box::new(WlDndId { mime_type }),
);
}
Msg::StartDrag(drag_surface) => {
self.drag_surface = Some((drag_surface, Default::default()));
}
Msg::DndWorkspaceEnter(handle, output, _action, mimes, (_x, _y)) => {
Msg::DndWorkspaceEnter(handle, output, _x, _y, _mimes) => {
self.drop_target = Some((handle, output));
// XXX
// if mimes.iter().any(|x| x == WORKSPACE_MIME) && action == DndAction::Move {
if mimes.iter().any(|x| x == &*TOPLEVEL_MIME) {
return Command::batch(vec![
set_actions(DndAction::Move, DndAction::Move),
accept_mime_type(Some(TOPLEVEL_MIME.to_string())),
]);
}
}
Msg::DndWorkspaceLeave(handle, output) => {
// Currently in iced-sctk, a `DndOfferEvent::Motion` may cause a leave event after
@ -533,25 +516,15 @@ impl Application for App {
if self.drop_target == Some((handle, output)) {
self.drop_target = None;
}
return accept_mime_type(None);
}
Msg::DndWorkspaceDrop => {
return request_dnd_data(TOPLEVEL_MIME.to_string());
}
Msg::DndWorkspaceData(mime_type, data) => {
if mime_type == *TOPLEVEL_MIME {
// XXX getting empty data?
let _protocol_id = str::from_utf8(&data)
.ok()
.and_then(|s| u32::from_str(s).ok());
if let Some((_, DragSurface::Toplevel { handle, .. }, _)) = &self.drag_surface {
if let Some(drop_target) = self.drop_target.take() {
self.send_wayland_cmd(backend::Cmd::MoveToplevelToWorkspace(
handle.clone(),
drop_target.0,
drop_target.1,
));
}
Msg::DndWorkspaceDrop(_toplevel) => {
if let Some((DragSurface::Toplevel { handle, .. }, _)) = &self.drag_surface {
if let Some(drop_target) = self.drop_target.take() {
self.send_wayland_cmd(backend::Cmd::MoveToplevelToWorkspace(
handle.clone(),
drop_target.0,
drop_target.1,
));
}
}
}
@ -575,23 +548,24 @@ impl Application for App {
Msg::BgConfig(c) => {
self.conf.bg = c;
}
Msg::Ignore => {}
}
Command::none()
Task::none()
}
fn dbus_activation(
&mut self,
msg: cosmic::app::DbusActivationMessage,
) -> iced::Command<cosmic::app::Message<Self::Message>> {
) -> Task<cosmic::app::Message<Self::Message>> {
if let DbusActivationDetails::Activate = msg.msg {
self.toggle()
} else {
Command::none()
Task::none()
}
}
fn subscription(&self) -> Subscription<Msg> {
let events = iced::event::listen_with(|evt, _| {
let events = iced::event::listen_with(|evt, _, _| {
if let iced::Event::PlatformSpecific(iced::event::PlatformSpecific::Wayland(evt)) = evt
{
Some(Msg::WaylandEvent(evt))
@ -599,6 +573,8 @@ impl Application for App {
key: Key::Named(Named::Escape),
modifiers: _,
location: _,
modified_key: _,
physical_key: _,
}) = evt
{
Some(Msg::Close)
@ -662,13 +638,6 @@ impl Application for App {
if let Some(surface) = self.layer_surfaces.get(&id) {
return view::layer_surface(self, surface);
}
if let Some((drag_id, drag_surface, size)) = &self.drag_surface {
if drag_id == &id {
if let Some(element) = view::drag_surface(self, drag_surface, *size) {
return element;
}
}
}
log::info!("NO VIEW");
text("workspaces").into()
}

View file

@ -8,10 +8,10 @@ use cosmic::{
self,
advanced::layout::flex::Axis,
widget::{column, row},
Border, Size,
Border,
},
iced_core::Shadow,
iced_sctk::subsurface_widget::Subsurface,
iced_winit::platform_specific::wayland::subsurface_widget::Subsurface,
widget,
};
use cosmic_bg_config::Source;
@ -19,7 +19,7 @@ use cosmic_comp_config::workspace::WorkspaceLayout;
use crate::{
backend::{self, CaptureImage},
App, DragSurface, LayerSurface, Msg, Toplevel, Workspace,
App, DragSurface, DragToplevel, LayerSurface, Msg, Toplevel, Workspace,
};
pub(crate) fn layer_surface<'a>(
@ -33,7 +33,7 @@ pub(crate) fn layer_surface<'a>(
}
}
let mut drag_toplevel = None;
if let Some((_, DragSurface::Toplevel { handle, .. }, _)) = &app.drag_surface {
if let Some((DragSurface::Toplevel { handle, .. }, _)) = &app.drag_surface {
drag_toplevel = Some(handle);
}
let layout = app.conf.workspace_config.workspace_layout;
@ -77,41 +77,10 @@ pub(crate) fn layer_surface<'a>(
container.into()
}
pub(crate) fn drag_surface<'a>(
app: &'a App,
drag_surface: &DragSurface,
size: Size,
) -> Option<cosmic::Element<'a, Msg>> {
let item = match drag_surface {
DragSurface::Workspace { handle, output } => {
if let Some(workspace) = app.workspaces.iter().find(|x| &x.handle == handle) {
workspace_item(workspace, output, false)
} else {
return None;
}
}
DragSurface::Toplevel { handle, .. } => {
if let Some(toplevel) = app.toplevels.iter().find(|x| &x.handle == handle) {
toplevel_preview(toplevel, true)
} else {
return None;
}
}
};
// TODO Use `mouse_interaction_wrapper` (need to modify iced_sctk to update view of
// drag surfaces)
Some(
widget::container(item)
.height(iced::Length::Fixed(size.height))
.width(iced::Length::Fixed(size.width))
.into(),
)
}
fn close_button(on_press: Msg) -> cosmic::Element<'static, Msg> {
widget::container(
widget::button(widget::icon::from_name("window-close-symbolic").size(16))
.style(cosmic::theme::Button::Destructive)
widget::button::custom(widget::icon::from_name("window-close-symbolic").size(16))
.class(cosmic::theme::Button::Destructive)
.on_press(on_press),
)
.align_x(iced::alignment::Horizontal::Right)
@ -123,9 +92,9 @@ fn workspace_item_appearance(
theme: &cosmic::Theme,
is_active: bool,
hovered: bool,
) -> cosmic::widget::button::Appearance {
) -> cosmic::widget::button::Style {
let cosmic = theme.cosmic();
let mut appearance = cosmic::widget::button::Appearance::new();
let mut appearance = cosmic::widget::button::Style::new();
appearance.border_radius = cosmic.corner_radii.radius_s.into();
if is_active {
appearance.border_width = 2.0;
@ -146,9 +115,9 @@ fn workspace_item<'a>(
let is_active = workspace.is_active;
column![
// TODO editable name?
widget::button(column![image, widget::text(&workspace.name)])
widget::button::custom(column![image, widget::text(&workspace.name)])
.selected(workspace.is_active)
.style(cosmic::theme::Button::Custom {
.class(cosmic::theme::Button::Custom {
active: Box::new(move |_focused, theme| workspace_item_appearance(
theme,
is_active,
@ -173,6 +142,7 @@ fn workspace_sidebar_entry<'a>(
workspace: &'a Workspace,
output: &'a wl_output::WlOutput,
is_drop_target: bool,
drag_id: u64,
) -> cosmic::Element<'a, Msg> {
/* XXX
let mouse_interaction = if is_drop_target {
@ -198,18 +168,30 @@ fn workspace_sidebar_entry<'a>(
*/
//crate::widgets::mouse_interaction_wrapper(
// mouse_interaction,
iced::widget::dnd_listener(workspace_item(workspace, output, is_drop_target))
.on_enter(|actions, mime, pos| {
Msg::DndWorkspaceEnter(workspace.handle.clone(), output.clone(), actions, mime, pos)
})
.on_exit(Msg::DndWorkspaceLeave(
workspace.handle.clone(),
output.clone(),
))
.on_drop(Msg::DndWorkspaceDrop)
.on_data(Msg::DndWorkspaceData)
//)
.into()
let workspace_handle = workspace.handle.clone();
let workspace_handle2 = workspace_handle.clone();
let output_clone = output.clone();
let output_clone2 = output.clone();
cosmic::widget::dnd_destination::dnd_destination_for_data(
workspace_item(workspace, output, is_drop_target),
|data: Option<DragToplevel>, _action| match data {
Some(toplevel) => Msg::DndWorkspaceDrop(toplevel),
None => Msg::Ignore,
},
)
.drag_id(drag_id)
.on_enter(move |actions, mime, pos| {
Msg::DndWorkspaceEnter(
workspace_handle.clone(),
output_clone.clone(),
actions,
mime,
pos,
)
})
.on_leave(move || Msg::DndWorkspaceLeave(workspace_handle2.clone(), output_clone2.clone()))
//)
.into()
}
fn workspaces_sidebar<'a>(
@ -219,7 +201,8 @@ fn workspaces_sidebar<'a>(
drop_target: Option<&backend::ZcosmicWorkspaceHandleV1>,
) -> cosmic::Element<'a, Msg> {
let sidebar_entries = workspaces
.map(|w| workspace_sidebar_entry(w, output, drop_target == Some(&w.handle)))
.enumerate()
.map(|(i, w)| workspace_sidebar_entry(w, output, drop_target == Some(&w.handle), i as u64))
.collect();
let axis = match layout {
WorkspaceLayout::Vertical => Axis::Vertical,
@ -260,8 +243,8 @@ fn workspaces_sidebar<'a>(
widget::container(sidebar_entries_container)
.width(width)
.height(height)
.style(cosmic::theme::Container::custom(|theme| {
cosmic::iced_style::container::Appearance {
.class(cosmic::theme::Container::custom(|theme| {
cosmic::iced::widget::container::Style {
text_color: Some(theme.cosmic().on_bg_color().into()),
icon_color: Some(theme.cosmic().on_bg_color().into()),
background: Some(iced::Color::from(theme.cosmic().background.base).into()),
@ -280,8 +263,9 @@ fn workspaces_sidebar<'a>(
.into()
}
fn toplevel_preview(toplevel: &Toplevel, is_being_dragged: bool) -> cosmic::Element<Msg> {
let label = widget::text(&toplevel.info.title);
fn toplevel_preview(toplevel: &Toplevel, is_being_dragged: bool) -> cosmic::Element<'static, Msg> {
// Clone so it can be 'static, for use in drag icon
let label = widget::text(toplevel.info.title.clone());
let label = if let Some(icon) = &toplevel.icon {
row![widget::icon(widget::icon::from_path(icon.clone())), label].spacing(4)
} else {
@ -292,17 +276,17 @@ fn toplevel_preview(toplevel: &Toplevel, is_being_dragged: bool) -> cosmic::Elem
crate::widgets::toplevel_item(
vec![
close_button(Msg::CloseToplevel(toplevel.handle.clone())),
widget::button(capture_image(toplevel.img.as_ref(), alpha))
widget::button::custom(capture_image(toplevel.img.as_ref(), alpha))
.selected(
toplevel
.info
.state
.contains(&zcosmic_toplevel_handle_v1::State::Activated),
)
.style(cosmic::theme::Button::Image)
.class(cosmic::theme::Button::Image)
.on_press(Msg::ActivateToplevel(toplevel.handle.clone()))
.into(),
widget::button(label)
widget::button::custom(label)
.on_press(Msg::ActivateToplevel(toplevel.handle.clone()))
.into(),
],
@ -325,19 +309,28 @@ fn toplevel_previews_entry<'a>(
toplevel_preview(toplevel, is_being_dragged),
!is_being_dragged,
);
iced::widget::dnd_source(preview)
.on_drag(|size, offset| {
Msg::StartDrag(
size,
offset,
DragSurface::Toplevel {
handle: toplevel.handle.clone(),
output: output.clone(),
},
let toplevel2 = toplevel.clone();
cosmic::widget::dnd_source::<_, DragToplevel>(preview)
.drag_threshold(5.)
.drag_content(|| DragToplevel {})
// XXX State?
.drag_icon(move |offset| {
(
toplevel_preview(&toplevel2, true).map(|_| ()),
cosmic::iced_core::widget::tree::State::None,
-offset,
)
})
.on_finished(Msg::SourceFinished)
.on_cancelled(Msg::SourceFinished)
.on_start(Some(Msg::StartDrag(
//size,
//offset,
DragSurface::Toplevel {
handle: toplevel.handle.clone(),
output: output.clone(),
},
)))
.on_finish(Some(Msg::SourceFinished))
.on_cancel(Some(Msg::SourceFinished))
.into()
}
@ -382,42 +375,38 @@ fn bg_element<'a>(
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.into(),
Some(Source::Color(color)) => {
widget::layer_container(widget::horizontal_space(iced::Length::Fill))
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.style(cosmic::theme::Container::Custom(Box::new(move |_| {
let color = color.clone();
cosmic::iced_style::container::Appearance {
background: Some(match color {
cosmic_bg_config::Color::Single(c) => iced::Background::Color(
cosmic::iced::Color::new(c[0], c[1], c[2], 1.0),
),
cosmic_bg_config::Color::Gradient(cosmic_bg_config::Gradient {
colors,
radius,
}) => {
let stop_increment = 1.0 / (colors.len() - 1) as f32;
let mut stop = 0.0;
Some(Source::Color(color)) => widget::layer_container(widget::horizontal_space())
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.class(cosmic::theme::Container::Custom(Box::new(move |_| {
let color = color.clone();
cosmic::iced::widget::container::Style {
background: Some(match color {
cosmic_bg_config::Color::Single(c) => {
iced::Background::Color(cosmic::iced::Color::new(c[0], c[1], c[2], 1.0))
}
cosmic_bg_config::Color::Gradient(cosmic_bg_config::Gradient {
colors,
radius,
}) => {
let stop_increment = 1.0 / (colors.len() - 1) as f32;
let mut stop = 0.0;
let mut linear = iced::gradient::Linear::new(iced::Degrees(radius));
let mut linear = iced::gradient::Linear::new(iced::Degrees(radius));
for &[r, g, b] in colors.iter() {
linear = linear
.add_stop(stop, cosmic::iced::Color::from_rgb(r, g, b));
stop += stop_increment;
}
iced::Background::Gradient(cosmic::iced_core::Gradient::Linear(
linear,
))
for &[r, g, b] in colors.iter() {
linear =
linear.add_stop(stop, cosmic::iced::Color::from_rgb(r, g, b));
stop += stop_increment;
}
}),
..Default::default()
}
})))
.into()
}
iced::Background::Gradient(cosmic::iced_core::Gradient::Linear(linear))
}
}),
..Default::default()
}
})))
.into(),
None => {
widget::image::Image::<widget::image::Handle>::new(widget::image::Handle::from_path(
"/usr/share/backgrounds/pop/kate-hazen-COSMIC-desktop-wallpaper.png",
@ -430,7 +419,7 @@ fn bg_element<'a>(
}
}
fn capture_image(image: Option<&CaptureImage>, alpha: f32) -> cosmic::Element<'_, Msg> {
fn capture_image(image: Option<&CaptureImage>, alpha: f32) -> cosmic::Element<'static, Msg> {
if let Some(image) = image {
#[cfg(feature = "no-subsurfaces")]
{
@ -439,11 +428,9 @@ fn capture_image(image: Option<&CaptureImage>, alpha: f32) -> cosmic::Element<'_
}
#[cfg(not(feature = "no-subsurfaces"))]
{
Subsurface::new(image.width, image.height, &image.wl_buffer)
.alpha(alpha)
.into()
Subsurface::new(image.wl_buffer.clone()).alpha(alpha).into()
}
} else {
widget::Image::new(widget::image::Handle::from_pixels(1, 1, vec![0, 0, 0, 255])).into()
widget::Image::new(widget::image::Handle::from_rgba(1, 1, vec![0, 0, 0, 255])).into()
}
}

View file

@ -5,11 +5,11 @@ use cosmic::{
advanced::{
layout::{self},
mouse, overlay, renderer,
widget::{tree, Operation, OperationOutputWrapper, Tree},
widget::{tree, Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
event::{self, Event},
Length, Rectangle, Size,
Length, Rectangle, Size, Vector,
},
iced_core::Renderer,
};
@ -52,7 +52,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for ImageBg<'a, Msg>
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
);
fn mouse_interaction(
&self,
@ -82,6 +82,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for ImageBg<'a, Msg>
tree: &'b mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
translation: Vector,
) -> Option<overlay::Element<'b, Msg, cosmic::Theme, cosmic::Renderer>>;
}
}

View file

@ -1,11 +1,11 @@
use cosmic::iced::{
advanced::{
layout, mouse, overlay, renderer,
widget::{tree, Id, Operation, OperationOutputWrapper, Tree},
widget::{tree, Id, Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
event::{self, Event},
Length, Rectangle, Size,
Length, Rectangle, Size, Vector,
};
use std::marker::PhantomData;
@ -61,7 +61,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for LayoutWrapper<'a,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
);
fn draw(
&self,
@ -102,6 +102,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for LayoutWrapper<'a,
tree: &'b mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
transation: Vector,
) -> Option<overlay::Element<'b, Msg, cosmic::Theme, cosmic::Renderer>>;
fn set_id(&mut self, id: Id);
}

View file

@ -1,11 +1,11 @@
use cosmic::iced::{
advanced::{
layout, mouse, overlay, renderer,
widget::{tree, Id, Operation, OperationOutputWrapper, Tree},
widget::{tree, Id, Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
event::{self, Event},
Length, Rectangle, Size,
Length, Rectangle, Size, Vector,
};
use std::marker::PhantomData;
@ -46,7 +46,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for MouseInteractionW
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
);
fn draw(
&self,
@ -79,6 +79,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for MouseInteractionW
tree: &'b mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
translation: Vector,
) -> Option<overlay::Element<'b, Msg, cosmic::Theme, cosmic::Renderer>>;
fn set_id(&mut self, id: Id);
}

View file

@ -6,7 +6,7 @@ use cosmic::iced::{
advanced::{
layout::{self, flex::Axis},
mouse, renderer,
widget::{Operation, OperationOutputWrapper, Tree},
widget::{Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
event::{self, Event},
@ -120,7 +120,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for ToplevelItem<'a,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
self.children

View file

@ -2,7 +2,7 @@ use cosmic::iced::{
advanced::{
layout::{self, flex::Axis},
mouse, renderer,
widget::{Operation, OperationOutputWrapper, Tree},
widget::{Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
event::{self, Event},
@ -130,7 +130,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for Toplevels<'a, Msg
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
self.children

View file

@ -4,7 +4,7 @@
use cosmic::iced::{
advanced::{
layout, mouse, renderer,
widget::{Operation, OperationOutputWrapper, Tree},
widget::{Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
event::{self, Event},
@ -42,7 +42,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for VisibilityWrapper
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
) {
self.content
.as_widget()

View file

@ -5,9 +5,10 @@ use cosmic::iced::{
advanced::{
layout::{self, flex::Axis},
mouse, renderer,
widget::{Operation, OperationOutputWrapper, Tree},
widget::{Operation, Tree},
Clipboard, Layout, Shell, Widget,
},
core::clipboard::DndDestinationRectangles,
event::{self, Event},
Length, Point, Rectangle, Size,
};
@ -122,7 +123,7 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for WorkspaceBar<'a,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Msg>>,
operation: &mut dyn Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
self.children
@ -219,6 +220,24 @@ impl<'a, Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for WorkspaceBar<'a,
fn diff(&mut self, tree: &mut Tree) {
tree.diff_children(&mut self.children);
}
fn drag_destinations(
&self,
state: &Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
dnd_rectangles: &mut DndDestinationRectangles,
) {
for ((e, layout), state) in self
.children
.iter()
.zip(layout.children())
.zip(state.children.iter())
{
e.as_widget()
.drag_destinations(state, layout, renderer, dnd_rectangles);
}
}
}
impl<'a, Msg: 'static> From<WorkspaceBar<'a, Msg>> for cosmic::Element<'a, Msg> {