Compare commits
No commits in common. "aa2a870c357284630045b05186fa7a6313c27693" and "78caabba7ef91cd1030da6f70b41d266704ffece" have entirely different histories.
aa2a870c35
...
78caabba7e
12 changed files with 331 additions and 568 deletions
593
Cargo.lock
generated
593
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@ cctk = [
|
|||
"xkeysym",
|
||||
"dep:cctk",
|
||||
]
|
||||
# Prevents multiple separate process instances.
|
||||
single-instance = []
|
||||
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ pub fn window_attributes(
|
|||
),
|
||||
));
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(all(feature = "cctk", target_os = "linux"))]
|
||||
{
|
||||
use winit::platform::wayland::WindowAttributesWayland;
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
®istry_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(®istry_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(),
|
||||
|
|
|
|||
|
|
@ -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(®ion));
|
||||
}
|
||||
},
|
||||
(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(®ion));
|
||||
blur_surface
|
||||
}).collect::<Vec<_>>();
|
||||
_ = vacant_entry.insert(blur_surfaces);
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use crate::core::{
|
|||
widget::{self, Widget},
|
||||
};
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue