Share native theme components and fix dialog backdrop blur
Centralize native palettes, presets, typography, controls, menus, calendar rendering, and icon assets in ferese-theme. Reuse the shared components across the shell, settings, lock screen, authentication prompt, and screen-sharing chooser. Attach themed dialogs to compositor-owned materials, correct backdrop capture and sampling across output transforms, smooth patterned backgrounds, and prevent clipped picker buttons with the configured shell font.
This commit is contained in:
1 parent
362bf79012
commit
b2363a18b0
85 files changed
+2163
-1591
No files matched your search
@@ -0,0 +1,121 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use ferese_protocols::material::v1::client::{
|
||||
ferese_material_manager_v1::FereseMaterialManagerV1,
|
||||
ferese_surface_material_v1::FereseSurfaceMaterialV1,
|
||||
};
|
||||
use wayland_client::{
|
||||
Connection, Dispatch, Proxy, QueueHandle, delegate_noop,
|
||||
globals::{GlobalListContents, registry_queue_init},
|
||||
protocol::{wl_registry, wl_surface},
|
||||
};
|
||||
|
||||
/// Keeps a compositor-owned dialog material attached for the window lifetime.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ModalMaterial {
|
||||
_binding: Arc<Binding>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Binding {
|
||||
connection: Connection,
|
||||
manager: FereseMaterialManagerV1,
|
||||
material: FereseSurfaceMaterialV1,
|
||||
}
|
||||
|
||||
impl ModalMaterial {
|
||||
/// Attach while Iced owns the native window; keep its background transparent on success.
|
||||
/// Other compositors return an error so the caller can retain its own surface fill.
|
||||
pub fn attach(window: &dyn cosmic::iced::window::Window) -> Result<Self, String> {
|
||||
use cosmic::iced::window::raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
||||
|
||||
let display = window.display_handle().map_err(|error| error.to_string())?;
|
||||
let handle = window.window_handle().map_err(|error| error.to_string())?;
|
||||
let (RawDisplayHandle::Wayland(display), RawWindowHandle::Wayland(handle)) =
|
||||
(display.as_raw(), handle.as_raw())
|
||||
else {
|
||||
return Err("Dialog materials require Wayland".into());
|
||||
};
|
||||
// Iced lends live native handles; this backend borrows its connection.
|
||||
let backend = unsafe {
|
||||
wayland_client::backend::Backend::from_foreign_display(display.display.as_ptr().cast())
|
||||
};
|
||||
let connection = Connection::from_backend(backend);
|
||||
let id = unsafe {
|
||||
wayland_client::backend::ObjectId::from_ptr(
|
||||
wl_surface::WlSurface::interface(),
|
||||
handle.surface.as_ptr().cast(),
|
||||
)
|
||||
}
|
||||
.map_err(|error| error.to_string())?;
|
||||
let surface =
|
||||
wl_surface::WlSurface::from_id(&connection, id).map_err(|error| error.to_string())?;
|
||||
let (globals, mut queue) =
|
||||
registry_queue_init::<MaterialState>(&connection).map_err(|error| error.to_string())?;
|
||||
let qh = queue.handle();
|
||||
let manager = globals
|
||||
.bind::<FereseMaterialManagerV1, _, _>(&qh, 1..=1, ())
|
||||
.map_err(|error| error.to_string())?;
|
||||
let material = manager.get_surface_material(&surface, &qh, ());
|
||||
let binding = Binding {
|
||||
connection,
|
||||
manager,
|
||||
material,
|
||||
};
|
||||
let mut state = MaterialState::default();
|
||||
queue
|
||||
.roundtrip(&mut state)
|
||||
.map_err(|error| error.to_string())?;
|
||||
if !state.ready {
|
||||
return Err("Dialog material attachment was not acknowledged".into());
|
||||
}
|
||||
Ok(Self {
|
||||
_binding: Arc::new(binding),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Binding {
|
||||
fn drop(&mut self) {
|
||||
self.material.destroy();
|
||||
self.manager.destroy();
|
||||
let _ = self.connection.flush();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct MaterialState {
|
||||
ready: bool,
|
||||
}
|
||||
|
||||
impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for MaterialState {
|
||||
fn event(
|
||||
_state: &mut Self,
|
||||
_registry: &wl_registry::WlRegistry,
|
||||
_event: wl_registry::Event,
|
||||
_data: &GlobalListContents,
|
||||
_connection: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<FereseSurfaceMaterialV1, ()> for MaterialState {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_material: &FereseSurfaceMaterialV1,
|
||||
event: ferese_protocols::material::v1::client::ferese_surface_material_v1::Event,
|
||||
_data: &(),
|
||||
_connection: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
) {
|
||||
if matches!(
|
||||
event,
|
||||
ferese_protocols::material::v1::client::ferese_surface_material_v1::Event::Ready
|
||||
) {
|
||||
state.ready = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate_noop!(MaterialState: ignore FereseMaterialManagerV1);
|
||||
Reference in new issue
Block a user