Compare commits

..

No commits in common. "aa2a870c357284630045b05186fa7a6313c27693" and "78caabba7ef91cd1030da6f70b41d266704ffece" have entirely different histories.

12 changed files with 331 additions and 568 deletions

593
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
use std::fmt::Debug;
use iced_core::{Rectangle, window::Id};
use iced_core::window::Id;
/// activation Actions
pub mod activation;
@ -35,8 +35,6 @@ pub enum Action {
InhibitShortcuts(bool),
/// Rounded corners in logical space
RoundedCorners(iced_core::window::Id, Option<CornerRadius>),
/// Blur effect for a surface
BlurSurface(Id, Option<Vec<Rectangle>>),
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
@ -72,11 +70,6 @@ impl Debug for Action {
Action::RoundedCorners(id, v) => {
f.debug_tuple("RoundedCorners").field(id).field(v).finish()
}
Action::BlurSurface(id, rectangles) => f
.debug_tuple("BlurSurface")
.field(id)
.field(rectangles)
.finish(),
}
}
}

View file

@ -37,8 +37,6 @@ cctk = [
"xkeysym",
"dep:cctk",
]
# Prevents multiple separate process instances.
single-instance = []
[dependencies]

View file

@ -178,7 +178,7 @@ pub fn window_attributes(
),
));
}
#[cfg(target_os = "linux")]
#[cfg(all(feature = "cctk", target_os = "linux"))]
{
use winit::platform::wayland::WindowAttributesWayland;

View file

@ -7,10 +7,7 @@ use crate::platform_specific::SurfaceIdWrapper;
use crate::{
Control,
futures::futures::channel::mpsc,
handlers::{
ext_background_effect, overlap::OverlapNotifyV1,
text_input::TextInputManager,
},
handlers::{overlap::OverlapNotifyV1, text_input::TextInputManager},
platform_specific::wayland::{
handlers::{
wp_fractional_scaling::FractionalScalingManager,
@ -349,26 +346,26 @@ impl SctkEventLoop {
&qh,
),
corner_radius_manager: registry_state.bind_one::<CosmicCornerRadiusManagerV1, _, _>(
&qh,
1..=1,
(),
).ok(),
&qh,
1..=1,
(),
).ok(),
toplevel_manager: ToplevelManagerState::try_new(
&registry_state,
&qh,
),
inhibitor_manager: registry_state.bind_one::<zwp_keyboard_shortcuts_inhibit_manager_v1::ZwpKeyboardShortcutsInhibitManagerV1, _, _>(
&qh,
1..=1,
(),
).ok(),
inhibitor_manager: registry_state.bind_one::<zwp_keyboard_shortcuts_inhibit_manager_v1::ZwpKeyboardShortcutsInhibitManagerV1, _, _>(
&qh,
1..=1,
(),
).ok(),
text_input_manager: TextInputManager::try_new(&registry_state, &qh),
ext_background_effect_manager: ext_background_effect::ExtBackgroundEffectManager::new(&globals, &qh).ok(),
registry_state,
queue_handle: qh,
loop_handle,
inhibitor: None,
inhibited: false,
_cursor_surface: None,
@ -376,7 +373,6 @@ impl SctkEventLoop {
outputs: Vec::new(),
seats: Vec::new(),
windows: Vec::new(),
blur_surfaces: HashMap::new(),
layer_surfaces: Vec::new(),
popups: Vec::new(),
lock_surfaces: Vec::new(),

View file

@ -2,7 +2,6 @@ use crate::{
Control,
handlers::{
activation::IcedRequestData,
ext_background_effect,
overlap::{OverlapNotificationV1, OverlapNotifyV1},
text_input::{Preedit, TextInputManager},
},
@ -26,7 +25,7 @@ use iced_futures::{
};
use raw_window_handle::HasWindowHandle;
use std::{
collections::{HashMap, HashSet, hash_map::Entry},
collections::{HashMap, HashSet},
convert::Infallible,
fmt::Debug,
sync::{Arc, Mutex, atomic::AtomicU32},
@ -109,7 +108,6 @@ use iced_runtime::{
},
};
use wayland_protocols::{
ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1,
wp::{
fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1,
keyboard_shortcuts_inhibit::zv1::client::{
@ -445,7 +443,6 @@ pub struct SctkState {
pub(crate) popups: Vec<SctkPopup>,
pub(crate) subsurfaces: Vec<SctkSubsurface>,
pub(crate) lock_surfaces: Vec<SctkLockSurface>,
pub(crate) blur_surfaces: HashMap<core::window::Id, Vec<ExtBackgroundEffectSurfaceV1>>,
pub(crate) touch_points: HashMap<touch::Finger, (WlSurface, Point)>,
/// Window updates, which are coming from SCTK or the compositor, which require
@ -488,7 +485,6 @@ pub struct SctkState {
pub(crate) toplevel_info: Option<ToplevelInfoState>,
pub(crate) toplevel_manager: Option<ToplevelManagerState>,
pub(crate) subsurface_state: Option<SubsurfaceState>,
pub(crate) ext_background_effect_manager: Option<ext_background_effect::ExtBackgroundEffectManager>,
pub(crate) activation_token_ctr: u32,
pub(crate) token_senders: HashMap<u32, oneshot::Sender<Option<String>>>,
@ -670,7 +666,9 @@ impl SctkState {
// TODO winit sets cursor size after handling the change for the window, so maybe that should be done as well.
}
}
impl SctkState {
pub fn get_popup(
&mut self,
settings: SctkPopupSettings,
@ -1093,12 +1091,6 @@ impl SctkState {
if let Some(i) = self.layer_surfaces.iter().position(|l| l.id == id) {
let l = self.layer_surfaces.remove(i);
if let Some(blurred) = self.blur_surfaces.remove(&l.id) {
for s in blurred {
s.destroy();
}
}
let (removed, remaining): (Vec<_>, Vec<_>) = self
.subsurfaces
.drain(..)
@ -1352,12 +1344,6 @@ impl SctkState {
_ = self.destroyed.insert(id);
}
if let Some(blurred) = self.blur_surfaces.remove(&id) {
for s in blurred {
s.destroy();
}
}
let (removed, remaining): (Vec<_>, Vec<_>) = self
.subsurfaces
.drain(..)
@ -1469,7 +1455,6 @@ impl SctkState {
// TODO how to handle this when there's no lock?
if let Some((surface, _)) = self.get_lock_surface(id, &output) {
let wl_surface = surface.wl_surface();
receive_frame(&mut self.frame_status, &wl_surface);
}
}
@ -1480,11 +1465,6 @@ impl SctkState {
})
{
let surface = self.lock_surfaces.remove(i);
if let Some(blurred) = self.blur_surfaces.remove(&surface.id) {
for s in blurred {
s.destroy();
}
}
let (removed, remaining): (Vec<_>, Vec<_>) = self
.subsurfaces
.drain(..)
@ -1556,7 +1536,7 @@ impl SctkState {
let mut destroyed = vec![];
if let Some(subsurface) = self.subsurfaces.iter().position(|s| s.id == id) {
let subsurface = self.subsurfaces.remove(subsurface);
destroyed.push((subsurface.instance.wl_surface.clone(), subsurface.instance.parent.clone(), subsurface.id));
destroyed.push((subsurface.instance.wl_surface.clone(), subsurface.instance.parent.clone()));
subsurface.instance.wl_surface.attach(None, 0, 0);
subsurface.instance.wl_surface.commit();
@ -1564,12 +1544,7 @@ impl SctkState {
SctkEvent::SubsurfaceEvent( crate::sctk_event::SubsurfaceEventVariant::Destroyed(subsurface.instance) )
);
}
for (destroyed, parent, id) in destroyed {
if let Some(blurred) = self.blur_surfaces.remove(&id) {
for s in blurred {
s.destroy();
}
}
for (destroyed, parent) in destroyed {
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))) {
@ -1599,7 +1574,7 @@ impl SctkState {
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());
let half_min_dim = (geo_size.width as u32).min(geo_size.height as u32) / 2;
let half_min_dim = ((geo_size.width as u32).min(geo_size.height as u32) / 2);
if let Some(radii) = v {
let adjusted_radii = CornerRadius {
@ -1646,97 +1621,6 @@ impl SctkState {
}
}
}
Action::BlurSurface(id, rectangles) => {
use wayland_protocols::ext::background_effect::v1::client::ext_background_effect_manager_v1;
if let Some(bg_effect_mgr) = self.ext_background_effect_manager.as_mut() && !bg_effect_mgr.capabilities().contains(ext_background_effect_manager_v1::Capability::Blur) {
bg_effect_mgr.enqueue(id, rectangles.clone());
return Ok(());
}
let s = if let Some(s) = self.popups.iter().find(|s| s.data.id == id) {
s.popup.wl_surface()
} else if let Some(s) = self.layer_surfaces.iter().find(|s| s.id == id) {
s.surface.wl_surface()
} else if let Some(s) = self.lock_surfaces.iter().find(|s| s.id == id) {
s.session_lock_surface.wl_surface()
} else if let Some(subsurface) = self.subsurfaces.iter().find(|s| s.id == id) {
&subsurface.instance.wl_surface
} else {
log::error!("Failed to find surface for blur action");
return Ok(());
};
let existing_blur = self.blur_surfaces.entry(id);
match (existing_blur, rectangles) {
(Entry::Occupied(occupied_entry), None) => {
let blur_surfaces = occupied_entry.remove();
for region in blur_surfaces {
region.destroy();
}
},
(Entry::Occupied(mut occupied_entry), Some(rectangles)) => {
let blur_surfaces = occupied_entry.get_mut();
let regions = rectangles.into_iter().map(|rect| {
let region = self
.compositor_state
.wl_compositor()
.create_region(&self.queue_handle, ());
region.add(
rect.x.round() as i32,
rect.y.round() as i32,
rect.width.round() as i32,
rect.height.round() as i32,
);
region
}).collect::<Vec<_>>();
if regions.len() > blur_surfaces.len() {
// add extra blur surfaces if needed
for _ in blur_surfaces.len()..regions.len() {
let Some(extra_region) = self.ext_background_effect_manager.as_mut().map(|mgr| mgr.blur(s, &self.queue_handle)) else {
log::error!("Failed to create blur effect for surface");
return Ok(());
};
blur_surfaces.push(extra_region);
}
} else if regions.len() < blur_surfaces.len() {
for surface in blur_surfaces.iter().skip(regions.len()) {
surface.destroy();
}
}
// update existing blur surfaces
for (blur_surface, region) in blur_surfaces.iter().zip(regions.into_iter()) {
blur_surface.set_blur_region(Some(&region));
}
},
(Entry::Vacant(..), None) => {
// nothing to remove
},
(Entry::Vacant(vacant_entry), Some(rectangles)) => {
if self.ext_background_effect_manager.is_none() {
log::error!("Blur effect is not supported.");
return Ok(());
}
let blur_surfaces = rectangles.into_iter().map(|rect| {
let region = self
.compositor_state
.wl_compositor()
.create_region(&self.queue_handle, ());
region.add(
rect.x.round() as i32,
rect.y.round() as i32,
rect.width.round() as i32,
rect.height.round() as i32,
);
let blur_manager = self.ext_background_effect_manager.as_mut().unwrap();
let blur_surface = blur_manager.blur(s, &self.queue_handle);
blur_surface.set_blur_region(Some(&region));
blur_surface
}).collect::<Vec<_>>();
_ = vacant_entry.insert(blur_surfaces);
},
}
},
};
Ok(())
}

View file

@ -1,107 +0,0 @@
use std::collections::HashMap;
use cctk::sctk;
use iced_runtime::core::Rectangle;
use iced_runtime::platform_specific::wayland::Action;
use sctk::globals::GlobalData;
use sctk::reexports::client::globals::{BindError, GlobalList};
use sctk::reexports::client::protocol::wl_surface::WlSurface;
use sctk::reexports::client::{Connection, Dispatch, Proxy, QueueHandle, delegate_dispatch};
use wayland_protocols::ext::background_effect::v1::client::ext_background_effect_manager_v1::{Capability, Event, ExtBackgroundEffectManagerV1};
use wayland_protocols::ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1;
use crate::event_loop::state::SctkState;
use crate::window;
#[derive(Debug, Clone)]
pub struct ExtBackgroundEffectManager {
manager: ExtBackgroundEffectManagerV1,
capabilities: Capability,
queued_blur_actions: HashMap<window::Id, Option<Vec<Rectangle>>>,
}
impl ExtBackgroundEffectManager {
pub fn new(
globals: &GlobalList,
queue_handle: &QueueHandle<SctkState>,
) -> Result<Self, BindError> {
let manager = globals.bind(queue_handle, 1..=1, GlobalData)?;
Ok(Self {
manager,
capabilities: Capability::empty(),
queued_blur_actions: HashMap::new(),
})
}
pub fn blur(
&mut self,
surface: &WlSurface,
queue_handle: &QueueHandle<SctkState>,
) -> ExtBackgroundEffectSurfaceV1 {
self.manager
.get_background_effect(surface, queue_handle, ())
}
pub fn enqueue(&mut self, id: window::Id, rects: Option<Vec<Rectangle>>) {
_ = self.queued_blur_actions.insert(id, rects);
}
pub fn capabilities(&self) -> Capability {
self.capabilities
}
}
impl Dispatch<ExtBackgroundEffectManagerV1, GlobalData, SctkState>
for ExtBackgroundEffectManager
{
fn event(
state: &mut SctkState,
_: &ExtBackgroundEffectManagerV1,
event: <ExtBackgroundEffectManagerV1 as Proxy>::Event,
_: &GlobalData,
_: &Connection,
_: &QueueHandle<SctkState>,
) {
match event {
Event::Capabilities { flags } => match flags {
wayland_client::WEnum::Value(capability) => {
let mut queued_actions = Vec::new();
if let Some(bg_effect_mgr) =
state.ext_background_effect_manager.as_mut()
{
bg_effect_mgr.capabilities = capability;
queued_actions =
bg_effect_mgr.queued_blur_actions.drain().collect();
}
for (id, rects) in queued_actions {
_ = state.handle_action(Action::BlurSurface(id, rects));
}
}
wayland_client::WEnum::Unknown(u) => {
log::warn!("Unknown value: {u:?}");
}
},
e => {
log::warn!("Ignored event {e:?}");
}
}
}
}
impl Dispatch<ExtBackgroundEffectSurfaceV1, (), SctkState>
for ExtBackgroundEffectManager
{
fn event(
_: &mut SctkState,
_: &ExtBackgroundEffectSurfaceV1,
_: <ExtBackgroundEffectSurfaceV1 as Proxy>::Event,
_: &(),
_: &Connection,
_: &QueueHandle<SctkState>,
) {
// There is no event
}
}
delegate_dispatch!(SctkState: [ExtBackgroundEffectManagerV1: GlobalData] => ExtBackgroundEffectManager);
delegate_dispatch!(SctkState: [ExtBackgroundEffectSurfaceV1: ()] => ExtBackgroundEffectManager);

View file

@ -1,7 +1,6 @@
// handlers
pub mod activation;
pub mod compositor;
pub mod ext_background_effect;
pub mod output;
pub mod overlap;
pub mod seat;
@ -13,14 +12,14 @@ pub mod toplevel;
pub mod wp_fractional_scaling;
pub mod wp_viewporter;
use cctk::sctk::{
use cctk::{sctk::{
delegate_registry, delegate_shm,
output::OutputState,
registry::{ProvidesRegistryState, RegistryState},
registry_handlers,
seat::SeatState,
shm::{Shm, ShmHandler},
};
}};
use crate::platform_specific::wayland::event_loop::state::SctkState;

View file

@ -69,10 +69,6 @@ impl Dispatch<ZwpTextInputV3, (), SctkState> for TextInputManager {
_conn: &Connection,
_qhandle: &QueueHandle<SctkState>,
) {
if cfg!(not(feature = "single-instance")) {
return;
}
let kbd_focus =
match state.seats.iter_mut().find_map(|s| s.kbd_focus.clone()) {
Some(surface) => surface,

View file

@ -380,12 +380,6 @@ impl SctkEvent {
(variant.position.0, variant.position.1).into(),
)
}
events.push((
id.clone(),
iced_runtime::core::Event::Mouse(
mouse::Event::CursorEntered,
),
));
events.push((
id,
iced_runtime::core::Event::Mouse(

View file

@ -7,6 +7,7 @@ use crate::core::{
widget::{self, Widget},
};
use std::{
borrow::BorrowMut,
cell::RefCell,
collections::HashMap,
fmt::Debug,

View file

@ -287,21 +287,7 @@ impl winit::window::Window for SctkWinitWindow {
}
fn set_blur(&self, blur: bool) {
_ = self.tx.send(Action::Action(
iced_runtime::platform_specific::wayland::Action::BlurSurface(
self.id.inner(),
if blur {
Some(vec![iced_runtime::core::Rectangle {
x: 0.,
y: 0.,
width: f32::MAX,
height: f32::MAX,
}])
} else {
None
},
),
));
// TODO
}
fn set_visible(&self, visible: bool) {}