wip: corner radius v2
This commit is contained in:
parent
9f41055861
commit
1bcba7e30c
7 changed files with 137 additions and 65 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -1294,7 +1294,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-client-toolkit"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/pop-os/cosmic-protocols?rev=160b086#160b086abe03cd34a8a375d7fbe47b24308d1f38"
|
||||
source = "git+https://github.com/pop-os/cosmic-protocols?rev=a7d2d7a#a7d2d7a6188425f699eaddf7a025617ce56068ae"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"cosmic-protocols",
|
||||
|
|
@ -1307,7 +1307,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-protocols"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/pop-os/cosmic-protocols?rev=160b086#160b086abe03cd34a8a375d7fbe47b24308d1f38"
|
||||
source = "git+https://github.com/pop-os/cosmic-protocols?rev=a7d2d7a#a7d2d7a6188425f699eaddf7a025617ce56068ae"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"wayland-backend",
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ tiny-skia = { version = "0.11", default-features = false, features = [
|
|||
"std",
|
||||
"simd",
|
||||
] }
|
||||
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "c253ec1" }
|
||||
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "a7d2d7a" }
|
||||
softbuffer = { git = "https://github.com/pop-os/softbuffer", tag = "cosmic-4.0" }
|
||||
syntect = "5.2"
|
||||
tokio = "1.0"
|
||||
|
|
|
|||
|
|
@ -682,7 +682,9 @@ pub use error::Error;
|
|||
pub use event::Event;
|
||||
pub use executor::Executor;
|
||||
pub use font::Font;
|
||||
pub use renderer::{Renderer, graphics::geometry};
|
||||
pub use renderer::Renderer;
|
||||
#[cfg(feature = "canvas")]
|
||||
pub use renderer::graphics::geometry;
|
||||
pub use task::Task;
|
||||
pub use window::Window;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ use cctk::{
|
|||
reexports::{
|
||||
calloop::{self, EventLoop},
|
||||
client::{
|
||||
ConnectError, Connection, Proxy, globals::registry_queue_init,
|
||||
Connection, Proxy, globals::registry_queue_init,
|
||||
},
|
||||
},
|
||||
registry::RegistryState,
|
||||
|
|
@ -46,8 +46,6 @@ use cctk::{
|
|||
};
|
||||
use raw_window_handle::HasDisplayHandle;
|
||||
use state::{FrameStatus, SctkWindow, send_event};
|
||||
#[cfg(feature = "a11y")]
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fmt::Debug,
|
||||
|
|
@ -71,8 +69,8 @@ pub struct SctkEventLoop {
|
|||
pub(crate) state: SctkState,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Connect(ConnectError),
|
||||
Calloop(calloop::Error),
|
||||
Global(GlobalError),
|
||||
NoDisplayHandle,
|
||||
|
|
@ -129,7 +127,7 @@ impl SctkEventLoop {
|
|||
crate::platform_specific::Action::ResizeWindow(id) => {
|
||||
if let Some((_, v)) = state.windows.iter()
|
||||
.find(|w| w.id == id)
|
||||
.map(|w| w.corner_radius.as_ref())
|
||||
.map(|w| state.corner_radii.get(&id))
|
||||
.unwrap_or_default() {
|
||||
_ = state.handle_action(iced_runtime::platform_specific::wayland::Action::RoundedCorners(id, *v));
|
||||
}
|
||||
|
|
@ -138,7 +136,7 @@ impl SctkEventLoop {
|
|||
window,
|
||||
id,
|
||||
) => {
|
||||
state.windows.push(SctkWindow { window, id, corner_radius: Default::default() });
|
||||
state.windows.push(SctkWindow { window, id });
|
||||
if let Some(v) = state.pending_corner_radius.remove(&id) {
|
||||
_ = state.handle_action(iced_runtime::platform_specific::wayland::Action::RoundedCorners(id, Some(v)));
|
||||
}
|
||||
|
|
@ -350,7 +348,7 @@ impl SctkEventLoop {
|
|||
),
|
||||
corner_radius_manager: registry_state.bind_one::<CosmicCornerRadiusManagerV1, _, _>(
|
||||
&qh,
|
||||
1..=1,
|
||||
1..=2,
|
||||
(),
|
||||
).ok(),
|
||||
toplevel_manager: ToplevelManagerState::try_new(
|
||||
|
|
@ -377,6 +375,7 @@ impl SctkEventLoop {
|
|||
seats: Vec::new(),
|
||||
windows: Vec::new(),
|
||||
blur_surfaces: HashMap::new(),
|
||||
corner_radii: HashMap::new(),
|
||||
layer_surfaces: Vec::new(),
|
||||
popups: Vec::new(),
|
||||
lock_surfaces: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
use crate::{
|
||||
Control,
|
||||
handlers::{
|
||||
activation::IcedRequestData,
|
||||
ext_background_effect,
|
||||
overlap::{OverlapNotificationV1, OverlapNotifyV1},
|
||||
text_input::{Preedit, TextInputManager},
|
||||
activation::IcedRequestData, ext_background_effect, overlap::{OverlapNotificationV1, OverlapNotifyV1}, shell::corner_radius::CornerRadiusWrapper, text_input::{Preedit, TextInputManager}
|
||||
},
|
||||
platform_specific::{
|
||||
Event,
|
||||
|
|
@ -65,7 +62,7 @@ use cctk::{
|
|||
wl_surface::{self, WlSurface},
|
||||
wl_touch::WlTouch,
|
||||
},
|
||||
},
|
||||
}, protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||
},
|
||||
registry::RegistryState,
|
||||
seat::{
|
||||
|
|
@ -341,22 +338,13 @@ pub struct SctkPopupData {
|
|||
pub(crate) grab: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MyCosmicCornerRadiusToplevelV1(CosmicCornerRadiusToplevelV1);
|
||||
|
||||
impl Drop for MyCosmicCornerRadiusToplevelV1 {
|
||||
fn drop(&mut self) {
|
||||
self.0.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SctkCornerRadius(Arc<MyCosmicCornerRadiusToplevelV1>);
|
||||
pub struct SctkCornerRadius(Arc<CornerRadiusWrapper>);
|
||||
|
||||
pub struct SctkWindow {
|
||||
pub(crate) window: Arc<dyn winit::window::Window>,
|
||||
pub(crate) id: core::window::Id,
|
||||
pub(crate) corner_radius: Option<(SctkCornerRadius, Option<CornerRadius>)>,
|
||||
}
|
||||
|
||||
impl SctkWindow {
|
||||
|
|
@ -444,6 +432,7 @@ pub struct SctkState {
|
|||
pub(crate) subsurfaces: Vec<SctkSubsurface>,
|
||||
pub(crate) lock_surfaces: Vec<SctkLockSurface>,
|
||||
pub(crate) blur_surfaces: HashMap<core::window::Id, Vec<ExtBackgroundEffectSurfaceV1>>,
|
||||
pub(crate) corner_radii: HashMap<core::window::Id, (SctkCornerRadius, Option<CornerRadius>)>,
|
||||
pub(crate) touch_points: HashMap<touch::Finger, (WlSurface, Point)>,
|
||||
|
||||
/// Window updates, which are coming from SCTK or the compositor, which require
|
||||
|
|
@ -1137,6 +1126,7 @@ impl SctkState {
|
|||
s.destroy();
|
||||
}
|
||||
}
|
||||
_ = self.corner_radii.remove(&id);
|
||||
|
||||
let (removed, remaining): (Vec<_>, Vec<_>) = self
|
||||
.subsurfaces
|
||||
|
|
@ -1396,6 +1386,8 @@ impl SctkState {
|
|||
s.destroy();
|
||||
}
|
||||
}
|
||||
_ = self.corner_radii.remove(&id);
|
||||
|
||||
|
||||
let (removed, remaining): (Vec<_>, Vec<_>) = self
|
||||
.subsurfaces
|
||||
|
|
@ -1524,6 +1516,8 @@ impl SctkState {
|
|||
s.destroy();
|
||||
}
|
||||
}
|
||||
_ = self.corner_radii.remove(&id);
|
||||
|
||||
let (removed, remaining): (Vec<_>, Vec<_>) = self
|
||||
.subsurfaces
|
||||
.drain(..)
|
||||
|
|
@ -1609,6 +1603,8 @@ impl SctkState {
|
|||
s.destroy();
|
||||
}
|
||||
}
|
||||
_ = self.corner_radii.remove(&id);
|
||||
|
||||
if let Some((wl_surface, f)) = self.seats.iter_mut().find(|f| {
|
||||
f.kbd_focus.as_ref().is_some_and(|f| *f == destroyed)
|
||||
}).and_then(|f| Some((parent, &mut f.kbd_focus))) {
|
||||
|
|
@ -1636,8 +1632,25 @@ impl SctkState {
|
|||
}
|
||||
Action::RoundedCorners(id, v) => {
|
||||
if let Some(manager) = self.corner_radius_manager.as_ref() {
|
||||
if let Some(w) = self.windows.iter_mut().find(|w| w.id == id) {
|
||||
let geo_size: LogicalSize<f64> = w.window.surface_size().cast::<f64>().to_logical(w.window.scale_factor());
|
||||
enum Surface {
|
||||
Xdg(XdgSurface, Option<XdgToplevel>),
|
||||
Wlr(ZwlrLayerSurfaceV1),
|
||||
}
|
||||
let s = if let Some(w) = self.windows.iter_mut().find(|w| w.id == id) {
|
||||
Some((Surface::Xdg(w.xdg_surface(&self.connection), Some(w.xdg_toplevel(&self.connection))), w.window.surface_size().cast::<f64>().to_logical(w.window.scale_factor())))
|
||||
} else if let Some(p) = self.popups.iter_mut().find(|w| w.data.id == id) {
|
||||
let guard = p.common.lock().unwrap();
|
||||
Some((Surface::Xdg(p.popup.xdg_surface().clone(), None), guard.size.cast::<f64>()))
|
||||
} else if let Some(l) = self.layer_surfaces.iter_mut().find(|l| l.id == id) {
|
||||
let guard = l.common.lock().unwrap();
|
||||
match l.surface.kind() {
|
||||
SurfaceKind::Wlr(l) => Some((Surface::Wlr(l.clone()), guard.size.cast::<f64>())),
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some((s, geo_size)) = s {
|
||||
let half_min_dim = (geo_size.width as u32).min(geo_size.height as u32) / 2;
|
||||
|
||||
if let Some(radii) = v {
|
||||
|
|
@ -1647,37 +1660,73 @@ impl SctkState {
|
|||
bottom_right: radii.bottom_right.min(half_min_dim),
|
||||
bottom_left: radii.bottom_left.min(half_min_dim),
|
||||
};
|
||||
if let Some((protocol_object, corner_radii)) = w.corner_radius.as_mut() {
|
||||
if let Some((protocol_object, corner_radii)) = self.corner_radii.get_mut(&id) {
|
||||
if *corner_radii != Some(adjusted_radii) {
|
||||
protocol_object.0.0.set_radius(
|
||||
match protocol_object.0.as_ref() {
|
||||
CornerRadiusWrapper::Xdg(protocol_object) => protocol_object.set_radius(
|
||||
adjusted_radii.top_left,
|
||||
adjusted_radii.top_right,
|
||||
adjusted_radii.bottom_right,
|
||||
adjusted_radii.bottom_left,
|
||||
),
|
||||
CornerRadiusWrapper::Wlr(protocol_object) => protocol_object.set_radius(
|
||||
adjusted_radii.top_left,
|
||||
adjusted_radii.top_right,
|
||||
adjusted_radii.bottom_right,
|
||||
adjusted_radii.bottom_left,
|
||||
)
|
||||
};
|
||||
*corner_radii = Some(adjusted_radii.clone());
|
||||
}
|
||||
} else {
|
||||
|
||||
let protocol_object = match s {
|
||||
Surface::Xdg(s, w) => {
|
||||
if manager.version() == 1 {
|
||||
if let Some(w) = w {
|
||||
CornerRadiusWrapper::Xdg(manager.get_corner_radius(&w, &self.queue_handle, ()))
|
||||
} else {
|
||||
log::error!("Corner radius is not supported for popups on xdg shell v1");
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
CornerRadiusWrapper::Xdg(manager.get_corner_radius_surface(&s, &self.queue_handle, ()))}
|
||||
}
|
||||
Surface::Wlr(l) => {
|
||||
if manager.version() == 1 {
|
||||
return Ok(());
|
||||
}
|
||||
CornerRadiusWrapper::Wlr(manager.get_corner_radius_layer(&l, &self.queue_handle, ()))}
|
||||
};
|
||||
match &protocol_object {
|
||||
CornerRadiusWrapper::Xdg(protocol_object) => protocol_object.set_radius(
|
||||
adjusted_radii.top_left,
|
||||
adjusted_radii.top_right,
|
||||
adjusted_radii.bottom_right,
|
||||
adjusted_radii.bottom_left,
|
||||
);
|
||||
*corner_radii = Some(adjusted_radii.clone());
|
||||
}
|
||||
} else {
|
||||
let toplevel = w.xdg_toplevel(&self.connection);
|
||||
|
||||
let protocol_object = manager.get_corner_radius(&toplevel, &self.queue_handle, ());
|
||||
|
||||
protocol_object.set_radius(
|
||||
adjusted_radii.top_left,
|
||||
adjusted_radii.top_right,
|
||||
adjusted_radii.bottom_right,
|
||||
adjusted_radii.bottom_left,
|
||||
);
|
||||
w.corner_radius = Some((SctkCornerRadius(Arc::new(MyCosmicCornerRadiusToplevelV1( protocol_object))), Some(adjusted_radii.clone())));
|
||||
),
|
||||
CornerRadiusWrapper::Wlr(protocol_object) => protocol_object.set_radius(
|
||||
adjusted_radii.top_left,
|
||||
adjusted_radii.top_right,
|
||||
adjusted_radii.bottom_right,
|
||||
adjusted_radii.bottom_left,
|
||||
)
|
||||
};
|
||||
_ = self.corner_radii.insert(id, (SctkCornerRadius(Arc::new(protocol_object)), Some(adjusted_radii.clone())));
|
||||
}
|
||||
} else {
|
||||
if let Some(old) = w.corner_radius.as_mut() {
|
||||
old.0.0.as_ref().0.unset_radius();
|
||||
if let Some(old) = self.corner_radii.get_mut(&id) {
|
||||
match old.0.0.as_ref() {
|
||||
CornerRadiusWrapper::Xdg(protocol_object) => protocol_object.unset_radius(),
|
||||
CornerRadiusWrapper::Wlr(protocol_object) => {
|
||||
protocol_object.unset_radius()
|
||||
}
|
||||
};
|
||||
old.1 = None;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(v) = v{
|
||||
if let Some(v) = v {
|
||||
_ = self.pending_corner_radius.insert(id, v);
|
||||
} else {
|
||||
_ = self.pending_corner_radius.remove(&id);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,29 @@
|
|||
use cctk::{sctk, cosmic_protocols::{
|
||||
corner_radius::v1::client::{
|
||||
use cctk::{
|
||||
cosmic_protocols::corner_radius::v1::client::{
|
||||
cosmic_corner_radius_layer_v1::CosmicCornerRadiusLayerV1,
|
||||
cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1,
|
||||
cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1,
|
||||
},
|
||||
overlap_notify::v1::client::zcosmic_overlap_notification_v1::ZcosmicOverlapNotificationV1,
|
||||
}};
|
||||
use sctk::reexports::{
|
||||
client::{Connection, Dispatch, Proxy},
|
||||
|
||||
sctk,
|
||||
};
|
||||
use sctk::reexports::client::{Connection, Dispatch, Proxy};
|
||||
|
||||
use crate::event_loop::state::SctkState;
|
||||
use crate::platform_specific::wayland::SctkEvent;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CornerRadiusWrapper {
|
||||
Xdg(CosmicCornerRadiusToplevelV1),
|
||||
Wlr(CosmicCornerRadiusLayerV1),
|
||||
}
|
||||
|
||||
impl Drop for CornerRadiusWrapper {
|
||||
fn drop(&mut self) {
|
||||
match self {
|
||||
Self::Xdg(c) => c.destroy(),
|
||||
Self::Wlr(c) => c.destroy(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<CosmicCornerRadiusManagerV1, ()> for SctkState {
|
||||
fn event(
|
||||
|
|
@ -21,15 +33,11 @@ impl Dispatch<CosmicCornerRadiusManagerV1, ()> for SctkState {
|
|||
_data: &(),
|
||||
_conn: &Connection,
|
||||
_qhandle: &sctk::reexports::client::QueueHandle<Self>,
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
Dispatch<
|
||||
CosmicCornerRadiusToplevelV1,
|
||||
(),
|
||||
> for SctkState
|
||||
{
|
||||
impl Dispatch<CosmicCornerRadiusToplevelV1, ()> for SctkState {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_proxy: &CosmicCornerRadiusToplevelV1,
|
||||
|
|
@ -39,7 +47,22 @@ impl
|
|||
_qhandle: &sctk::reexports::client::QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
_ => unimplemented!()
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<CosmicCornerRadiusLayerV1, ()> for SctkState {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_proxy: &CosmicCornerRadiusLayerV1,
|
||||
event: <CosmicCornerRadiusLayerV1 as Proxy>::Event,
|
||||
_data: &(),
|
||||
_conn: &Connection,
|
||||
_qhandle: &sctk::reexports::client::QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@ impl PlatformSpecific {
|
|||
};
|
||||
self.wayland.display_handle = Some(display);
|
||||
self.wayland.proxy = Some(raw);
|
||||
// TODO remove this
|
||||
self.wayland.sender =
|
||||
crate::platform_specific::event_loop::SctkEventLoop::new(
|
||||
self.wayland.winit_event_sender.clone().unwrap(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue