aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
Diffstat (limited to 'src/window')
-rw-r--r--src/window/mapped.rs159
-rw-r--r--src/window/mod.rs3
2 files changed, 162 insertions, 0 deletions
diff --git a/src/window/mapped.rs b/src/window/mapped.rs
new file mode 100644
index 00000000..4476dede
--- /dev/null
+++ b/src/window/mapped.rs
@@ -0,0 +1,159 @@
+use smithay::backend::renderer::element::{AsRenderElements as _, Id};
+use smithay::desktop::space::SpaceElement as _;
+use smithay::desktop::Window;
+use smithay::output::Output;
+use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1;
+use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
+use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
+use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
+use smithay::wayland::compositor::{send_surface_state, with_states};
+use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
+
+use super::ResolvedWindowRules;
+use crate::layout::{LayoutElement, LayoutElementRenderElement};
+use crate::niri::WindowOffscreenId;
+use crate::render_helpers::renderer::NiriRenderer;
+
+#[derive(Debug)]
+pub struct Mapped {
+ pub window: Window,
+
+ /// Up-to-date rules.
+ pub rules: ResolvedWindowRules,
+}
+
+impl Mapped {
+ pub fn new(window: Window, rules: ResolvedWindowRules) -> Self {
+ Self { window, rules }
+ }
+
+ pub fn toplevel(&self) -> &ToplevelSurface {
+ self.window.toplevel().expect("no X11 support")
+ }
+}
+
+impl LayoutElement for Mapped {
+ type Id = Window;
+
+ fn id(&self) -> &Self::Id {
+ &self.window
+ }
+
+ fn size(&self) -> Size<i32, Logical> {
+ self.window.geometry().size
+ }
+
+ fn buf_loc(&self) -> Point<i32, Logical> {
+ Point::from((0, 0)) - self.window.geometry().loc
+ }
+
+ fn is_in_input_region(&self, point: Point<f64, Logical>) -> bool {
+ let surface_local = point + self.window.geometry().loc.to_f64();
+ self.window.is_in_input_region(&surface_local)
+ }
+
+ fn render<R: NiriRenderer>(
+ &self,
+ renderer: &mut R,
+ location: Point<i32, Logical>,
+ scale: Scale<f64>,
+ ) -> Vec<LayoutElementRenderElement<R>> {
+ let buf_pos = location - self.window.geometry().loc;
+ self.window.render_elements(
+ renderer,
+ buf_pos.to_physical_precise_round(scale),
+ scale,
+ 1.,
+ )
+ }
+
+ fn request_size(&self, size: Size<i32, Logical>) {
+ self.toplevel().with_pending_state(|state| {
+ state.size = Some(size);
+ state.states.unset(xdg_toplevel::State::Fullscreen);
+ });
+ }
+
+ fn request_fullscreen(&self, size: Size<i32, Logical>) {
+ self.toplevel().with_pending_state(|state| {
+ state.size = Some(size);
+ state.states.set(xdg_toplevel::State::Fullscreen);
+ });
+ }
+
+ fn min_size(&self) -> Size<i32, Logical> {
+ with_states(self.toplevel().wl_surface(), |state| {
+ let curr = state.cached_state.current::<SurfaceCachedState>();
+ curr.min_size
+ })
+ }
+
+ fn max_size(&self) -> Size<i32, Logical> {
+ with_states(self.toplevel().wl_surface(), |state| {
+ let curr = state.cached_state.current::<SurfaceCachedState>();
+ curr.max_size
+ })
+ }
+
+ fn is_wl_surface(&self, wl_surface: &WlSurface) -> bool {
+ self.toplevel().wl_surface() == wl_surface
+ }
+
+ fn set_preferred_scale_transform(&self, scale: i32, transform: Transform) {
+ self.window.with_surfaces(|surface, data| {
+ send_surface_state(surface, data, scale, transform);
+ });
+ }
+
+ fn has_ssd(&self) -> bool {
+ self.toplevel().current_state().decoration_mode
+ == Some(zxdg_toplevel_decoration_v1::Mode::ServerSide)
+ }
+
+ fn output_enter(&self, output: &Output) {
+ let overlap = Rectangle::from_loc_and_size((0, 0), (i32::MAX, i32::MAX));
+ self.window.output_enter(output, overlap)
+ }
+
+ fn output_leave(&self, output: &Output) {
+ self.window.output_leave(output)
+ }
+
+ fn set_offscreen_element_id(&self, id: Option<Id>) {
+ let data = self
+ .window
+ .user_data()
+ .get_or_insert(WindowOffscreenId::default);
+ data.0.replace(id);
+ }
+
+ fn set_activated(&self, active: bool) {
+ self.window.set_activated(active);
+ }
+
+ fn set_bounds(&self, bounds: Size<i32, Logical>) {
+ self.toplevel().with_pending_state(|state| {
+ state.bounds = Some(bounds);
+ });
+ }
+
+ fn send_pending_configure(&self) {
+ self.toplevel().send_pending_configure();
+ }
+
+ fn is_fullscreen(&self) -> bool {
+ self.toplevel()
+ .current_state()
+ .states
+ .contains(xdg_toplevel::State::Fullscreen)
+ }
+
+ fn is_pending_fullscreen(&self) -> bool {
+ self.toplevel()
+ .with_pending_state(|state| state.states.contains(xdg_toplevel::State::Fullscreen))
+ }
+
+ fn refresh(&self) {
+ self.window.refresh();
+ }
+}
diff --git a/src/window/mod.rs b/src/window/mod.rs
index fd494b42..124a62f3 100644
--- a/src/window/mod.rs
+++ b/src/window/mod.rs
@@ -1,5 +1,8 @@
use crate::layout::workspace::ColumnWidth;
+pub mod mapped;
+pub use mapped::Mapped;
+
pub mod unmapped;
pub use unmapped::{InitialConfigureState, Unmapped};