<NME> xdg.rs
<BEF> //! XDG Output advertising capabilities
//!
//! This protocol is meant for describing outputs in a way
//! which is more in line with the concept of an output on desktop oriented systems.

use std::sync::{Arc, Mutex};

use slog::{o, trace};
use wayland_protocols::xdg::xdg_output::zv1::server::zxdg_output_v1::ZxdgOutputV1;
use wayland_server::{protocol::wl_output::WlOutput, Resource};

use crate::utils::{Logical, Physical, Point, Size};

use super::{Mode, Scale};

#[derive(Debug)]
pub(crate) struct Inner {
    name: String,
    description: String,
    pub(super) logical_position: Point<i32, Logical>,

    pub(super) physical_size: Option<Size<i32, Physical>>,
    pub(super) scale: Scale,

    pub instances: Vec<ZxdgOutputV1>,
    _log: ::slog::Logger,
}

#[derive(Debug, Clone)]
pub(crate) struct XdgOutput {
    pub(crate) inner: Arc<Mutex<Inner>>,
}

impl XdgOutput {
    pub(super) fn new(output: &super::Inner, log: ::slog::Logger) -> Self {
        let log = log.new(o!("smithay_module" => "xdg_output_handler"));

        trace!(log, "Creating new xdg_output"; "name" => &output.name);

        let physical_size = output.current_mode.map(|mode| mode.size);

        Self {
            inner: Arc::new(Mutex::new(Inner {
                name: output.name.clone(),
                description: output.description.clone(),
                logical_position: output.location,

                physical_size,
                scale: output.scale,

                instances: Vec::new(),
                _log: log,
            })),
        }
    }

    pub(super) fn add_instance(&self, xdg_output: &ZxdgOutputV1, wl_output: &WlOutput) {
        let mut inner = self.inner.lock().unwrap();

        xdg_output.logical_position(inner.logical_position.x, inner.logical_position.y);

        if let Some(size) = inner.physical_size {
            let logical_size = size
                .to_f64()
                .to_logical(inner.scale.fractional_scale())
                .to_i32_round();
            xdg_output.logical_size(logical_size.w, logical_size.h);
        }

        if xdg_output.version() >= 2 {
            xdg_output.name(inner.name.clone());
            xdg_output.description(inner.description.clone());
        }

        // xdg_output.done() is deprecated since version 3
        if xdg_output.version() < 3 {
            xdg_output.done();
        }

        wl_output.done();

        inner.instances.push(xdg_output.clone());
    }

    pub(super) fn change_current_state(
        &self,
        new_mode: Option<Mode>,
        new_scale: Option<Scale>,
        new_location: Option<Point<i32, Logical>>,
    ) {
        let mut output = self.inner.lock().unwrap();

        if let Some(new_mode) = new_mode {
            output.physical_size = Some(new_mode.size);
        }
        if let Some(new_scale) = new_scale {
            output.scale = new_scale;
        }
        if let Some(new_location) = new_location {
            output.logical_position = new_location;
        }

        for instance in output.instances.iter() {
            if new_mode.is_some() | new_scale.is_some() {
                if let Some(size) = output.physical_size {
                    let logical_size = size
                        .to_f64()
                        .to_logical(output.scale.fractional_scale())
                        .to_i32_round();
                    instance.logical_size(logical_size.w, logical_size.h);
                }
            }

            if new_location.is_some() {
                instance.logical_position(output.logical_position.x, output.logical_position.y);
            }

            // xdg_output.done() is deprecated since version 3
            if instance.version() < 3 {
                instance.done();
            }

            // No need for wl_output.done() here, it will be called by caller (super::Output::change_current_state)
        }
    }
}
                    output: wl_output,
                } => {
                    let output = Output::from_resource(&wl_output).unwrap();
                    let mut inner = output.inner.lock().unwrap();

                    if inner.xdg_output.is_none() {
                        inner.xdg_output = Some(XdgOutput::new(&inner, log.clone()));

<MSG> output: Add userdata to wayland output object

Anvil's output map has a wrapper type `Output`, that largely stores
information of the wayland `Output` type, that is just not accessible.
Lets change that and make it possible to associate userdata with the
output to remove the need to use another wrapper type.

<DFF> @@ -159,7 +159,7 @@ where
                     output: wl_output,
                 } => {
                     let output = Output::from_resource(&wl_output).unwrap();
-                    let mut inner = output.inner.lock().unwrap();
+                    let mut inner = output.inner.0.lock().unwrap();
 
                     if inner.xdg_output.is_none() {
                         inner.xdg_output = Some(XdgOutput::new(&inner, log.clone()));

output: Add userdata to wayland output object