Compare commits
6 commits
libcosmic-
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa2a870c35 | ||
|
|
8f10a3bd34 | ||
|
|
64b97077b7 | ||
|
|
13b8d3eab6 | ||
|
|
1bf1e33317 | ||
|
|
d2b2715835 |
12 changed files with 568 additions and 331 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 std::fmt::Debug;
|
||||||
|
|
||||||
use iced_core::window::Id;
|
use iced_core::{Rectangle, window::Id};
|
||||||
|
|
||||||
/// activation Actions
|
/// activation Actions
|
||||||
pub mod activation;
|
pub mod activation;
|
||||||
|
|
@ -35,6 +35,8 @@ pub enum Action {
|
||||||
InhibitShortcuts(bool),
|
InhibitShortcuts(bool),
|
||||||
/// Rounded corners in logical space
|
/// Rounded corners in logical space
|
||||||
RoundedCorners(iced_core::window::Id, Option<CornerRadius>),
|
RoundedCorners(iced_core::window::Id, Option<CornerRadius>),
|
||||||
|
/// Blur effect for a surface
|
||||||
|
BlurSurface(Id, Option<Vec<Rectangle>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
|
|
@ -70,6 +72,11 @@ impl Debug for Action {
|
||||||
Action::RoundedCorners(id, v) => {
|
Action::RoundedCorners(id, v) => {
|
||||||
f.debug_tuple("RoundedCorners").field(id).field(v).finish()
|
f.debug_tuple("RoundedCorners").field(id).field(v).finish()
|
||||||
}
|
}
|
||||||
|
Action::BlurSurface(id, rectangles) => f
|
||||||
|
.debug_tuple("BlurSurface")
|
||||||
|
.field(id)
|
||||||
|
.field(rectangles)
|
||||||
|
.finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ cctk = [
|
||||||
"xkeysym",
|
"xkeysym",
|
||||||
"dep:cctk",
|
"dep:cctk",
|
||||||
]
|
]
|
||||||
|
# Prevents multiple separate process instances.
|
||||||
|
single-instance = []
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ pub fn window_attributes(
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
#[cfg(all(feature = "cctk", target_os = "linux"))]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
use winit::platform::wayland::WindowAttributesWayland;
|
use winit::platform::wayland::WindowAttributesWayland;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@ use crate::platform_specific::SurfaceIdWrapper;
|
||||||
use crate::{
|
use crate::{
|
||||||
Control,
|
Control,
|
||||||
futures::futures::channel::mpsc,
|
futures::futures::channel::mpsc,
|
||||||
handlers::{overlap::OverlapNotifyV1, text_input::TextInputManager},
|
handlers::{
|
||||||
|
ext_background_effect, overlap::OverlapNotifyV1,
|
||||||
|
text_input::TextInputManager,
|
||||||
|
},
|
||||||
platform_specific::wayland::{
|
platform_specific::wayland::{
|
||||||
handlers::{
|
handlers::{
|
||||||
wp_fractional_scaling::FractionalScalingManager,
|
wp_fractional_scaling::FractionalScalingManager,
|
||||||
|
|
@ -346,26 +349,26 @@ impl SctkEventLoop {
|
||||||
&qh,
|
&qh,
|
||||||
),
|
),
|
||||||
corner_radius_manager: registry_state.bind_one::<CosmicCornerRadiusManagerV1, _, _>(
|
corner_radius_manager: registry_state.bind_one::<CosmicCornerRadiusManagerV1, _, _>(
|
||||||
&qh,
|
&qh,
|
||||||
1..=1,
|
1..=1,
|
||||||
(),
|
(),
|
||||||
).ok(),
|
).ok(),
|
||||||
toplevel_manager: ToplevelManagerState::try_new(
|
toplevel_manager: ToplevelManagerState::try_new(
|
||||||
®istry_state,
|
®istry_state,
|
||||||
&qh,
|
&qh,
|
||||||
),
|
),
|
||||||
inhibitor_manager: registry_state.bind_one::<zwp_keyboard_shortcuts_inhibit_manager_v1::ZwpKeyboardShortcutsInhibitManagerV1, _, _>(
|
inhibitor_manager: registry_state.bind_one::<zwp_keyboard_shortcuts_inhibit_manager_v1::ZwpKeyboardShortcutsInhibitManagerV1, _, _>(
|
||||||
&qh,
|
&qh,
|
||||||
1..=1,
|
1..=1,
|
||||||
(),
|
(),
|
||||||
).ok(),
|
).ok(),
|
||||||
text_input_manager: TextInputManager::try_new(®istry_state, &qh),
|
text_input_manager: TextInputManager::try_new(®istry_state, &qh),
|
||||||
|
ext_background_effect_manager: ext_background_effect::ExtBackgroundEffectManager::new(&globals, &qh).ok(),
|
||||||
registry_state,
|
registry_state,
|
||||||
|
|
||||||
queue_handle: qh,
|
queue_handle: qh,
|
||||||
loop_handle,
|
loop_handle,
|
||||||
|
|
||||||
|
|
||||||
inhibitor: None,
|
inhibitor: None,
|
||||||
inhibited: false,
|
inhibited: false,
|
||||||
_cursor_surface: None,
|
_cursor_surface: None,
|
||||||
|
|
@ -373,6 +376,7 @@ impl SctkEventLoop {
|
||||||
outputs: Vec::new(),
|
outputs: Vec::new(),
|
||||||
seats: Vec::new(),
|
seats: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
|
blur_surfaces: HashMap::new(),
|
||||||
layer_surfaces: Vec::new(),
|
layer_surfaces: Vec::new(),
|
||||||
popups: Vec::new(),
|
popups: Vec::new(),
|
||||||
lock_surfaces: Vec::new(),
|
lock_surfaces: Vec::new(),
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use crate::{
|
||||||
Control,
|
Control,
|
||||||
handlers::{
|
handlers::{
|
||||||
activation::IcedRequestData,
|
activation::IcedRequestData,
|
||||||
|
ext_background_effect,
|
||||||
overlap::{OverlapNotificationV1, OverlapNotifyV1},
|
overlap::{OverlapNotificationV1, OverlapNotifyV1},
|
||||||
text_input::{Preedit, TextInputManager},
|
text_input::{Preedit, TextInputManager},
|
||||||
},
|
},
|
||||||
|
|
@ -25,7 +26,7 @@ use iced_futures::{
|
||||||
};
|
};
|
||||||
use raw_window_handle::HasWindowHandle;
|
use raw_window_handle::HasWindowHandle;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet, hash_map::Entry},
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
sync::{Arc, Mutex, atomic::AtomicU32},
|
sync::{Arc, Mutex, atomic::AtomicU32},
|
||||||
|
|
@ -108,6 +109,7 @@ use iced_runtime::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use wayland_protocols::{
|
use wayland_protocols::{
|
||||||
|
ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1,
|
||||||
wp::{
|
wp::{
|
||||||
fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1,
|
fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1,
|
||||||
keyboard_shortcuts_inhibit::zv1::client::{
|
keyboard_shortcuts_inhibit::zv1::client::{
|
||||||
|
|
@ -443,6 +445,7 @@ pub struct SctkState {
|
||||||
pub(crate) popups: Vec<SctkPopup>,
|
pub(crate) popups: Vec<SctkPopup>,
|
||||||
pub(crate) subsurfaces: Vec<SctkSubsurface>,
|
pub(crate) subsurfaces: Vec<SctkSubsurface>,
|
||||||
pub(crate) lock_surfaces: Vec<SctkLockSurface>,
|
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)>,
|
pub(crate) touch_points: HashMap<touch::Finger, (WlSurface, Point)>,
|
||||||
|
|
||||||
/// Window updates, which are coming from SCTK or the compositor, which require
|
/// Window updates, which are coming from SCTK or the compositor, which require
|
||||||
|
|
@ -485,6 +488,7 @@ pub struct SctkState {
|
||||||
pub(crate) toplevel_info: Option<ToplevelInfoState>,
|
pub(crate) toplevel_info: Option<ToplevelInfoState>,
|
||||||
pub(crate) toplevel_manager: Option<ToplevelManagerState>,
|
pub(crate) toplevel_manager: Option<ToplevelManagerState>,
|
||||||
pub(crate) subsurface_state: Option<SubsurfaceState>,
|
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) activation_token_ctr: u32,
|
||||||
pub(crate) token_senders: HashMap<u32, oneshot::Sender<Option<String>>>,
|
pub(crate) token_senders: HashMap<u32, oneshot::Sender<Option<String>>>,
|
||||||
|
|
@ -666,9 +670,7 @@ impl SctkState {
|
||||||
|
|
||||||
// TODO winit sets cursor size after handling the change for the window, so maybe that should be done as well.
|
// 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(
|
pub fn get_popup(
|
||||||
&mut self,
|
&mut self,
|
||||||
settings: SctkPopupSettings,
|
settings: SctkPopupSettings,
|
||||||
|
|
@ -1091,6 +1093,12 @@ impl SctkState {
|
||||||
if let Some(i) = self.layer_surfaces.iter().position(|l| l.id == id) {
|
if let Some(i) = self.layer_surfaces.iter().position(|l| l.id == id) {
|
||||||
let l = self.layer_surfaces.remove(i);
|
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
|
let (removed, remaining): (Vec<_>, Vec<_>) = self
|
||||||
.subsurfaces
|
.subsurfaces
|
||||||
.drain(..)
|
.drain(..)
|
||||||
|
|
@ -1344,6 +1352,12 @@ impl SctkState {
|
||||||
_ = self.destroyed.insert(id);
|
_ = 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
|
let (removed, remaining): (Vec<_>, Vec<_>) = self
|
||||||
.subsurfaces
|
.subsurfaces
|
||||||
.drain(..)
|
.drain(..)
|
||||||
|
|
@ -1455,6 +1469,7 @@ impl SctkState {
|
||||||
// TODO how to handle this when there's no lock?
|
// TODO how to handle this when there's no lock?
|
||||||
if let Some((surface, _)) = self.get_lock_surface(id, &output) {
|
if let Some((surface, _)) = self.get_lock_surface(id, &output) {
|
||||||
let wl_surface = surface.wl_surface();
|
let wl_surface = surface.wl_surface();
|
||||||
|
|
||||||
receive_frame(&mut self.frame_status, &wl_surface);
|
receive_frame(&mut self.frame_status, &wl_surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1465,6 +1480,11 @@ impl SctkState {
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let surface = self.lock_surfaces.remove(i);
|
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
|
let (removed, remaining): (Vec<_>, Vec<_>) = self
|
||||||
.subsurfaces
|
.subsurfaces
|
||||||
.drain(..)
|
.drain(..)
|
||||||
|
|
@ -1536,7 +1556,7 @@ impl SctkState {
|
||||||
let mut destroyed = vec![];
|
let mut destroyed = vec![];
|
||||||
if let Some(subsurface) = self.subsurfaces.iter().position(|s| s.id == id) {
|
if let Some(subsurface) = self.subsurfaces.iter().position(|s| s.id == id) {
|
||||||
let subsurface = self.subsurfaces.remove(subsurface);
|
let subsurface = self.subsurfaces.remove(subsurface);
|
||||||
destroyed.push((subsurface.instance.wl_surface.clone(), subsurface.instance.parent.clone()));
|
destroyed.push((subsurface.instance.wl_surface.clone(), subsurface.instance.parent.clone(), subsurface.id));
|
||||||
|
|
||||||
subsurface.instance.wl_surface.attach(None, 0, 0);
|
subsurface.instance.wl_surface.attach(None, 0, 0);
|
||||||
subsurface.instance.wl_surface.commit();
|
subsurface.instance.wl_surface.commit();
|
||||||
|
|
@ -1544,7 +1564,12 @@ impl SctkState {
|
||||||
SctkEvent::SubsurfaceEvent( crate::sctk_event::SubsurfaceEventVariant::Destroyed(subsurface.instance) )
|
SctkEvent::SubsurfaceEvent( crate::sctk_event::SubsurfaceEventVariant::Destroyed(subsurface.instance) )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (destroyed, parent) in destroyed {
|
for (destroyed, parent, id) in destroyed {
|
||||||
|
if let Some(blurred) = self.blur_surfaces.remove(&id) {
|
||||||
|
for s in blurred {
|
||||||
|
s.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some((wl_surface, f)) = self.seats.iter_mut().find(|f| {
|
if let Some((wl_surface, f)) = self.seats.iter_mut().find(|f| {
|
||||||
f.kbd_focus.as_ref().is_some_and(|f| *f == destroyed)
|
f.kbd_focus.as_ref().is_some_and(|f| *f == destroyed)
|
||||||
}).and_then(|f| Some((parent, &mut f.kbd_focus))) {
|
}).and_then(|f| Some((parent, &mut f.kbd_focus))) {
|
||||||
|
|
@ -1574,7 +1599,7 @@ impl SctkState {
|
||||||
if let Some(manager) = self.corner_radius_manager.as_ref() {
|
if let Some(manager) = self.corner_radius_manager.as_ref() {
|
||||||
if let Some(w) = self.windows.iter_mut().find(|w| w.id == id) {
|
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 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 {
|
if let Some(radii) = v {
|
||||||
let adjusted_radii = CornerRadius {
|
let adjusted_radii = CornerRadius {
|
||||||
|
|
@ -1621,6 +1646,97 @@ 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
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,6 +1,7 @@
|
||||||
// handlers
|
// handlers
|
||||||
pub mod activation;
|
pub mod activation;
|
||||||
pub mod compositor;
|
pub mod compositor;
|
||||||
|
pub mod ext_background_effect;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
pub mod overlap;
|
pub mod overlap;
|
||||||
pub mod seat;
|
pub mod seat;
|
||||||
|
|
@ -12,14 +13,14 @@ pub mod toplevel;
|
||||||
pub mod wp_fractional_scaling;
|
pub mod wp_fractional_scaling;
|
||||||
pub mod wp_viewporter;
|
pub mod wp_viewporter;
|
||||||
|
|
||||||
use cctk::{sctk::{
|
use cctk::sctk::{
|
||||||
delegate_registry, delegate_shm,
|
delegate_registry, delegate_shm,
|
||||||
output::OutputState,
|
output::OutputState,
|
||||||
registry::{ProvidesRegistryState, RegistryState},
|
registry::{ProvidesRegistryState, RegistryState},
|
||||||
registry_handlers,
|
registry_handlers,
|
||||||
seat::SeatState,
|
seat::SeatState,
|
||||||
shm::{Shm, ShmHandler},
|
shm::{Shm, ShmHandler},
|
||||||
}};
|
};
|
||||||
|
|
||||||
use crate::platform_specific::wayland::event_loop::state::SctkState;
|
use crate::platform_specific::wayland::event_loop::state::SctkState;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,10 @@ impl Dispatch<ZwpTextInputV3, (), SctkState> for TextInputManager {
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qhandle: &QueueHandle<SctkState>,
|
_qhandle: &QueueHandle<SctkState>,
|
||||||
) {
|
) {
|
||||||
|
if cfg!(not(feature = "single-instance")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let kbd_focus =
|
let kbd_focus =
|
||||||
match state.seats.iter_mut().find_map(|s| s.kbd_focus.clone()) {
|
match state.seats.iter_mut().find_map(|s| s.kbd_focus.clone()) {
|
||||||
Some(surface) => surface,
|
Some(surface) => surface,
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,12 @@ impl SctkEvent {
|
||||||
(variant.position.0, variant.position.1).into(),
|
(variant.position.0, variant.position.1).into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
events.push((
|
||||||
|
id.clone(),
|
||||||
|
iced_runtime::core::Event::Mouse(
|
||||||
|
mouse::Event::CursorEntered,
|
||||||
|
),
|
||||||
|
));
|
||||||
events.push((
|
events.push((
|
||||||
id,
|
id,
|
||||||
iced_runtime::core::Event::Mouse(
|
iced_runtime::core::Event::Mouse(
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ use crate::core::{
|
||||||
widget::{self, Widget},
|
widget::{self, Widget},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::BorrowMut,
|
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,21 @@ impl winit::window::Window for SctkWinitWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_blur(&self, blur: bool) {
|
fn set_blur(&self, blur: bool) {
|
||||||
// TODO
|
_ = 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
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_visible(&self, visible: bool) {}
|
fn set_visible(&self, visible: bool) {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue