mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b93514a82a |
Generated
+2
@@ -2257,6 +2257,7 @@ dependencies = [
|
|||||||
"tracy-client",
|
"tracy-client",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
|
"wayland-protocols-plasma",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
"wayland-server",
|
"wayland-server",
|
||||||
"xcursor",
|
"xcursor",
|
||||||
@@ -4218,6 +4219,7 @@ dependencies = [
|
|||||||
"wayland-client",
|
"wayland-client",
|
||||||
"wayland-protocols",
|
"wayland-protocols",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
|
"wayland-server",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ tracing-subscriber.workspace = true
|
|||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracy-client.workspace = true
|
tracy-client.workspace = true
|
||||||
wayland-backend = "0.3.14"
|
wayland-backend = "0.3.14"
|
||||||
|
wayland-protocols-plasma = { version = "0.3.11", features = ["server"] }
|
||||||
wayland-scanner = "0.31.9"
|
wayland-scanner = "0.31.9"
|
||||||
wayland-server = { version = "0.31.12", features = ["libwayland_1_23"] }
|
wayland-server = { version = "0.31.12", features = ["libwayland_1_23"] }
|
||||||
xcursor = "0.3.10"
|
xcursor = "0.3.10"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
use smithay::delegate_background_effect;
|
use smithay::delegate_background_effect;
|
||||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||||
use smithay::utils::{Logical, Rectangle};
|
use smithay::utils::{Logical, Point, Rectangle, Size};
|
||||||
use smithay::wayland::background_effect::{
|
use smithay::wayland::background_effect::{
|
||||||
self, BackgroundEffectSurfaceCachedState, ExtBackgroundEffectHandler,
|
self, BackgroundEffectSurfaceCachedState, ExtBackgroundEffectHandler,
|
||||||
};
|
};
|
||||||
@@ -10,7 +10,9 @@ use smithay::wayland::compositor::{
|
|||||||
add_post_commit_hook, with_states, RegionAttributes, SurfaceData,
|
add_post_commit_hook, with_states, RegionAttributes, SurfaceData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::delegate_kde_blur;
|
||||||
use crate::niri::State;
|
use crate::niri::State;
|
||||||
|
use crate::protocols::kde_blur::{KdeBlurHandler, KdeBlurRegion, KdeBlurSurfaceCachedState};
|
||||||
use crate::utils::region::region_to_non_overlapping_rects;
|
use crate::utils::region::region_to_non_overlapping_rects;
|
||||||
|
|
||||||
/// Per-surface cache for processed blur region (non-overlapping rects).
|
/// Per-surface cache for processed blur region (non-overlapping rects).
|
||||||
@@ -59,6 +61,7 @@ fn recompute_blur_region(states: &SurfaceData, inner: &mut CachedBlurRegionInner
|
|||||||
};
|
};
|
||||||
let rects = Arc::make_mut(rects);
|
let rects = Arc::make_mut(rects);
|
||||||
|
|
||||||
|
// Prefer ext-background-effect.
|
||||||
if cached.has::<BackgroundEffectSurfaceCachedState>() {
|
if cached.has::<BackgroundEffectSurfaceCachedState>() {
|
||||||
let mut guard = cached.get::<BackgroundEffectSurfaceCachedState>();
|
let mut guard = cached.get::<BackgroundEffectSurfaceCachedState>();
|
||||||
if let Some(region) = &guard.current().blur_region {
|
if let Some(region) = &guard.current().blur_region {
|
||||||
@@ -69,6 +72,29 @@ fn recompute_blur_region(states: &SurfaceData, inner: &mut CachedBlurRegionInner
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cached.has::<KdeBlurSurfaceCachedState>() {
|
||||||
|
let mut guard = cached.get::<KdeBlurSurfaceCachedState>();
|
||||||
|
match &guard.current().blur_region {
|
||||||
|
Some(KdeBlurRegion::WholeSurface) => {
|
||||||
|
// Store a single "infinite" rect that gets naturally clipped.
|
||||||
|
let infinite = Rectangle::new(
|
||||||
|
Point::new(-i32::MAX / 2, -i32::MAX / 2),
|
||||||
|
Size::new(i32::MAX, i32::MAX),
|
||||||
|
);
|
||||||
|
rects.clear();
|
||||||
|
rects.push(infinite);
|
||||||
|
}
|
||||||
|
Some(KdeBlurRegion::Region(region)) => {
|
||||||
|
region_to_non_overlapping_rects(region, rects);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
inner.rects = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neither is present.
|
||||||
inner.rects = None;
|
inner.rects = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,3 +147,14 @@ impl ExtBackgroundEffectHandler for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
delegate_background_effect!(State);
|
delegate_background_effect!(State);
|
||||||
|
|
||||||
|
impl KdeBlurHandler for State {
|
||||||
|
fn set_blur_region(&mut self, wl_surface: WlSurface) {
|
||||||
|
mark_blur_region_pending_dirty(&wl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unset_blur_region(&mut self, wl_surface: WlSurface) {
|
||||||
|
mark_blur_region_pending_dirty(&wl_surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate_kde_blur!(State);
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ use crate::niri_render_elements;
|
|||||||
use crate::protocols::ext_workspace::{self, ExtWorkspaceManagerState};
|
use crate::protocols::ext_workspace::{self, ExtWorkspaceManagerState};
|
||||||
use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState};
|
use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState};
|
||||||
use crate::protocols::gamma_control::GammaControlManagerState;
|
use crate::protocols::gamma_control::GammaControlManagerState;
|
||||||
|
use crate::protocols::kde_blur::KdeBlurState;
|
||||||
use crate::protocols::mutter_x11_interop::MutterX11InteropManagerState;
|
use crate::protocols::mutter_x11_interop::MutterX11InteropManagerState;
|
||||||
use crate::protocols::output_management::OutputManagementManagerState;
|
use crate::protocols::output_management::OutputManagementManagerState;
|
||||||
use crate::protocols::screencopy::{Screencopy, ScreencopyBuffer, ScreencopyManagerState};
|
use crate::protocols::screencopy::{Screencopy, ScreencopyBuffer, ScreencopyManagerState};
|
||||||
@@ -282,6 +283,7 @@ pub struct Niri {
|
|||||||
pub output_management_state: OutputManagementManagerState,
|
pub output_management_state: OutputManagementManagerState,
|
||||||
pub viewporter_state: ViewporterState,
|
pub viewporter_state: ViewporterState,
|
||||||
pub background_effect_state: BackgroundEffectState,
|
pub background_effect_state: BackgroundEffectState,
|
||||||
|
pub kde_blur_state: KdeBlurState,
|
||||||
pub xdg_foreign_state: XdgForeignState,
|
pub xdg_foreign_state: XdgForeignState,
|
||||||
pub shm_state: ShmState,
|
pub shm_state: ShmState,
|
||||||
pub output_manager_state: OutputManagerState,
|
pub output_manager_state: OutputManagerState,
|
||||||
@@ -2332,6 +2334,7 @@ impl Niri {
|
|||||||
ScreencopyManagerState::new::<State, _>(&display_handle, client_is_unrestricted);
|
ScreencopyManagerState::new::<State, _>(&display_handle, client_is_unrestricted);
|
||||||
let viewporter_state = ViewporterState::new::<State>(&display_handle);
|
let viewporter_state = ViewporterState::new::<State>(&display_handle);
|
||||||
let background_effect_state = BackgroundEffectState::new::<State>(&display_handle);
|
let background_effect_state = BackgroundEffectState::new::<State>(&display_handle);
|
||||||
|
let kde_blur_state = KdeBlurState::new::<State>(&display_handle);
|
||||||
let xdg_foreign_state = XdgForeignState::new::<State>(&display_handle);
|
let xdg_foreign_state = XdgForeignState::new::<State>(&display_handle);
|
||||||
|
|
||||||
let is_tty = matches!(backend, Backend::Tty(_));
|
let is_tty = matches!(backend, Backend::Tty(_));
|
||||||
@@ -2516,6 +2519,7 @@ impl Niri {
|
|||||||
screencopy_state,
|
screencopy_state,
|
||||||
viewporter_state,
|
viewporter_state,
|
||||||
background_effect_state,
|
background_effect_state,
|
||||||
|
kde_blur_state,
|
||||||
xdg_foreign_state,
|
xdg_foreign_state,
|
||||||
text_input_state,
|
text_input_state,
|
||||||
input_method_state,
|
input_method_state,
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use smithay::reexports::wayland_server;
|
||||||
|
use smithay::wayland::compositor::{
|
||||||
|
get_region_attributes, with_states, Cacheable, RegionAttributes,
|
||||||
|
};
|
||||||
|
use wayland_protocols_plasma::blur::server::org_kde_kwin_blur::{self, OrgKdeKwinBlur};
|
||||||
|
use wayland_protocols_plasma::blur::server::org_kde_kwin_blur_manager::{
|
||||||
|
self, OrgKdeKwinBlurManager,
|
||||||
|
};
|
||||||
|
use wayland_server::backend::GlobalId;
|
||||||
|
use wayland_server::protocol::wl_surface::WlSurface;
|
||||||
|
use wayland_server::{
|
||||||
|
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait KdeBlurHandler:
|
||||||
|
GlobalDispatch<OrgKdeKwinBlurManager, ()>
|
||||||
|
+ Dispatch<OrgKdeKwinBlurManager, ()>
|
||||||
|
+ Dispatch<OrgKdeKwinBlur, KdeBlurSurfaceUserData>
|
||||||
|
+ 'static
|
||||||
|
{
|
||||||
|
/// Called when a blur region becomes pending on a surface, awaiting a commit.
|
||||||
|
fn set_blur_region(&mut self, wl_surface: WlSurface) {
|
||||||
|
let _ = wl_surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called when a blur region unset becomes pending on a surface, awaiting a commit.
|
||||||
|
fn unset_blur_region(&mut self, wl_surface: WlSurface) {
|
||||||
|
let _ = wl_surface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct KdeBlurSurfaceCachedState {
|
||||||
|
/// Region of the surface that will have its background blurred.
|
||||||
|
///
|
||||||
|
/// `None` means no blurring.
|
||||||
|
pub blur_region: Option<KdeBlurRegion>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub enum KdeBlurRegion {
|
||||||
|
#[default]
|
||||||
|
WholeSurface,
|
||||||
|
Region(RegionAttributes),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cacheable for KdeBlurSurfaceCachedState {
|
||||||
|
fn commit(&mut self, _dh: &DisplayHandle) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_into(self, into: &mut Self, _dh: &DisplayHandle) {
|
||||||
|
*into = self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KdeBlurSurfaceUserData {
|
||||||
|
surface: Weak<WlSurface>,
|
||||||
|
pending_region: Mutex<KdeBlurRegion>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KdeBlurSurfaceUserData {
|
||||||
|
fn new(surface: WlSurface) -> Self {
|
||||||
|
Self {
|
||||||
|
surface: surface.downgrade(),
|
||||||
|
pending_region: Mutex::new(KdeBlurRegion::WholeSurface),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wl_surface(&self) -> Option<WlSurface> {
|
||||||
|
self.surface.upgrade().ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KdeBlurState {
|
||||||
|
global: GlobalId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KdeBlurState {
|
||||||
|
pub fn new<D: KdeBlurHandler>(display: &DisplayHandle) -> KdeBlurState {
|
||||||
|
let global = display.create_global::<D, OrgKdeKwinBlurManager, _>(1, ());
|
||||||
|
KdeBlurState { global }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global(&self) -> GlobalId {
|
||||||
|
self.global.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: KdeBlurHandler> GlobalDispatch<OrgKdeKwinBlurManager, (), D> for KdeBlurState {
|
||||||
|
fn bind(
|
||||||
|
_state: &mut D,
|
||||||
|
_handle: &DisplayHandle,
|
||||||
|
_client: &Client,
|
||||||
|
resource: New<OrgKdeKwinBlurManager>,
|
||||||
|
_global_data: &(),
|
||||||
|
data_init: &mut DataInit<'_, D>,
|
||||||
|
) {
|
||||||
|
let _manager = data_init.init(resource, ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: KdeBlurHandler> Dispatch<OrgKdeKwinBlurManager, (), D> for KdeBlurState {
|
||||||
|
fn request(
|
||||||
|
state: &mut D,
|
||||||
|
_client: &Client,
|
||||||
|
_manager: &OrgKdeKwinBlurManager,
|
||||||
|
request: org_kde_kwin_blur_manager::Request,
|
||||||
|
_data: &(),
|
||||||
|
_dh: &DisplayHandle,
|
||||||
|
data_init: &mut DataInit<'_, D>,
|
||||||
|
) {
|
||||||
|
match request {
|
||||||
|
org_kde_kwin_blur_manager::Request::Create { id, surface } => {
|
||||||
|
data_init.init(id, KdeBlurSurfaceUserData::new(surface));
|
||||||
|
}
|
||||||
|
org_kde_kwin_blur_manager::Request::Unset { surface } => {
|
||||||
|
with_states(&surface, |states| {
|
||||||
|
let mut cached = states.cached_state.get::<KdeBlurSurfaceCachedState>();
|
||||||
|
let pending = cached.pending();
|
||||||
|
pending.blur_region = None;
|
||||||
|
});
|
||||||
|
state.unset_blur_region(surface);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: KdeBlurHandler> Dispatch<OrgKdeKwinBlur, KdeBlurSurfaceUserData, D> for KdeBlurState {
|
||||||
|
fn request(
|
||||||
|
state: &mut D,
|
||||||
|
_client: &Client,
|
||||||
|
_obj: &OrgKdeKwinBlur,
|
||||||
|
request: org_kde_kwin_blur::Request,
|
||||||
|
data: &KdeBlurSurfaceUserData,
|
||||||
|
_dh: &DisplayHandle,
|
||||||
|
_data_init: &mut DataInit<'_, D>,
|
||||||
|
) {
|
||||||
|
match request {
|
||||||
|
org_kde_kwin_blur::Request::SetRegion { region } => {
|
||||||
|
let region = region.as_ref().map(get_region_attributes);
|
||||||
|
|
||||||
|
// In the KDE blur protocol, an empty region means whole surface.
|
||||||
|
let region = match region {
|
||||||
|
Some(region) if !region.rects.is_empty() => KdeBlurRegion::Region(region),
|
||||||
|
_ => KdeBlurRegion::WholeSurface,
|
||||||
|
};
|
||||||
|
|
||||||
|
*data.pending_region.lock().unwrap() = region;
|
||||||
|
}
|
||||||
|
org_kde_kwin_blur::Request::Commit => {
|
||||||
|
let Some(surface) = data.wl_surface() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
with_states(&surface, |states| {
|
||||||
|
let mut cached = states.cached_state.get::<KdeBlurSurfaceCachedState>();
|
||||||
|
let pending = cached.pending();
|
||||||
|
let region = data.pending_region.lock().unwrap().clone();
|
||||||
|
pending.blur_region = Some(region);
|
||||||
|
});
|
||||||
|
state.set_blur_region(surface);
|
||||||
|
}
|
||||||
|
org_kde_kwin_blur::Request::Release => {
|
||||||
|
// No-op.
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn destroyed(
|
||||||
|
_state: &mut D,
|
||||||
|
_client_id: wayland_server::backend::ClientId,
|
||||||
|
_object: &OrgKdeKwinBlur,
|
||||||
|
_data: &KdeBlurSurfaceUserData,
|
||||||
|
) {
|
||||||
|
// No-op: cleanup is handled by double-buffering and surface destruction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! delegate_kde_blur {
|
||||||
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
||||||
|
const _: () = {
|
||||||
|
use smithay::reexports::wayland_server;
|
||||||
|
use wayland_protocols_plasma::blur::server::{
|
||||||
|
org_kde_kwin_blur_manager::OrgKdeKwinBlurManager,
|
||||||
|
org_kde_kwin_blur::OrgKdeKwinBlur,
|
||||||
|
};
|
||||||
|
use wayland_server::{delegate_dispatch, delegate_global_dispatch};
|
||||||
|
use $crate::protocols::kde_blur::{KdeBlurState, KdeBlurSurfaceUserData};
|
||||||
|
|
||||||
|
delegate_global_dispatch!(
|
||||||
|
$(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
|
||||||
|
$ty: [OrgKdeKwinBlurManager: ()] => KdeBlurState
|
||||||
|
);
|
||||||
|
|
||||||
|
delegate_dispatch!(
|
||||||
|
$(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
|
||||||
|
$ty: [OrgKdeKwinBlurManager: ()] => KdeBlurState
|
||||||
|
);
|
||||||
|
|
||||||
|
delegate_dispatch!(
|
||||||
|
$(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
|
||||||
|
$ty: [OrgKdeKwinBlur: KdeBlurSurfaceUserData] => KdeBlurState
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
pub mod ext_workspace;
|
pub mod ext_workspace;
|
||||||
pub mod foreign_toplevel;
|
pub mod foreign_toplevel;
|
||||||
pub mod gamma_control;
|
pub mod gamma_control;
|
||||||
|
pub mod kde_blur;
|
||||||
pub mod mutter_x11_interop;
|
pub mod mutter_x11_interop;
|
||||||
pub mod output_management;
|
pub mod output_management;
|
||||||
pub mod screencopy;
|
pub mod screencopy;
|
||||||
|
|||||||
Reference in New Issue
Block a user