mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b93514a82a |
Generated
+2
@@ -2257,6 +2257,7 @@ dependencies = [
|
||||
"tracy-client",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols-plasma",
|
||||
"wayland-scanner",
|
||||
"wayland-server",
|
||||
"xcursor",
|
||||
@@ -4218,6 +4219,7 @@ dependencies = [
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wayland-scanner",
|
||||
"wayland-server",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -95,6 +95,7 @@ tracing-subscriber.workspace = true
|
||||
tracing.workspace = true
|
||||
tracy-client.workspace = true
|
||||
wayland-backend = "0.3.14"
|
||||
wayland-protocols-plasma = { version = "0.3.11", features = ["server"] }
|
||||
wayland-scanner = "0.31.9"
|
||||
wayland-server = { version = "0.31.12", features = ["libwayland_1_23"] }
|
||||
xcursor = "0.3.10"
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use smithay::delegate_background_effect;
|
||||
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::{
|
||||
self, BackgroundEffectSurfaceCachedState, ExtBackgroundEffectHandler,
|
||||
};
|
||||
@@ -10,7 +10,9 @@ use smithay::wayland::compositor::{
|
||||
add_post_commit_hook, with_states, RegionAttributes, SurfaceData,
|
||||
};
|
||||
|
||||
use crate::delegate_kde_blur;
|
||||
use crate::niri::State;
|
||||
use crate::protocols::kde_blur::{KdeBlurHandler, KdeBlurRegion, KdeBlurSurfaceCachedState};
|
||||
use crate::utils::region::region_to_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);
|
||||
|
||||
// Prefer ext-background-effect.
|
||||
if cached.has::<BackgroundEffectSurfaceCachedState>() {
|
||||
let mut guard = cached.get::<BackgroundEffectSurfaceCachedState>();
|
||||
if let Some(region) = &guard.current().blur_region {
|
||||
@@ -69,6 +72,29 @@ fn recompute_blur_region(states: &SurfaceData, inner: &mut CachedBlurRegionInner
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -121,3 +147,14 @@ impl ExtBackgroundEffectHandler for 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::foreign_toplevel::{self, ForeignToplevelManagerState};
|
||||
use crate::protocols::gamma_control::GammaControlManagerState;
|
||||
use crate::protocols::kde_blur::KdeBlurState;
|
||||
use crate::protocols::mutter_x11_interop::MutterX11InteropManagerState;
|
||||
use crate::protocols::output_management::OutputManagementManagerState;
|
||||
use crate::protocols::screencopy::{Screencopy, ScreencopyBuffer, ScreencopyManagerState};
|
||||
@@ -282,6 +283,7 @@ pub struct Niri {
|
||||
pub output_management_state: OutputManagementManagerState,
|
||||
pub viewporter_state: ViewporterState,
|
||||
pub background_effect_state: BackgroundEffectState,
|
||||
pub kde_blur_state: KdeBlurState,
|
||||
pub xdg_foreign_state: XdgForeignState,
|
||||
pub shm_state: ShmState,
|
||||
pub output_manager_state: OutputManagerState,
|
||||
@@ -2332,6 +2334,7 @@ impl Niri {
|
||||
ScreencopyManagerState::new::<State, _>(&display_handle, client_is_unrestricted);
|
||||
let viewporter_state = ViewporterState::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 is_tty = matches!(backend, Backend::Tty(_));
|
||||
@@ -2516,6 +2519,7 @@ impl Niri {
|
||||
screencopy_state,
|
||||
viewporter_state,
|
||||
background_effect_state,
|
||||
kde_blur_state,
|
||||
xdg_foreign_state,
|
||||
text_input_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 foreign_toplevel;
|
||||
pub mod gamma_control;
|
||||
pub mod kde_blur;
|
||||
pub mod mutter_x11_interop;
|
||||
pub mod output_management;
|
||||
pub mod screencopy;
|
||||
|
||||
Reference in New Issue
Block a user