<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)]

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

use super::{Mode, Output};

#[derive(Debug)]
pub(crate) struct Inner {

    pub instances: Vec<ZxdgOutputV1>,
    pub(super) logical_position: Point<i32, Logical>,

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

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

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
        xdg_output.logical_position(inner.logical_position.x, inner.logical_position.y);

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


        // 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;
        }

    pub(super) fn change_current_state(
        &self,
        new_mode: Option<Mode>,
        new_scale: Option<i32>,
        new_location: Option<Point<i32, Logical>>,
    ) {
        let mut output = self.inner.lock().unwrap();
                    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();
        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_logical(output.scale);
                    instance.logical_size(logical_size.w, logical_size.h);
                }
            }

<MSG> output: allow fractional scale values

<DFF> @@ -17,7 +17,7 @@ use wayland_server::{protocol::wl_output::WlOutput, Display, Filter, Global, Mai
 
 use crate::utils::{Logical, Physical, Point, Size};
 
-use super::{Mode, Output};
+use super::{Mode, Output, Scale};
 
 #[derive(Debug)]
 pub(crate) struct Inner {
@@ -26,7 +26,7 @@ pub(crate) struct Inner {
     pub(super) logical_position: Point<i32, Logical>,
 
     pub(super) physical_size: Option<Size<i32, Physical>>,
-    pub(super) scale: i32,
+    pub(super) scale: Scale,
 
     instances: Vec<ZxdgOutputV1>,
     _log: ::slog::Logger,
@@ -64,7 +64,10 @@ impl XdgOutput {
         xdg_output.logical_position(inner.logical_position.x, inner.logical_position.y);
 
         if let Some(size) = inner.physical_size {
-            let logical_size = size.to_logical(inner.scale);
+            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);
         }
 
@@ -100,7 +103,7 @@ impl XdgOutput {
     pub(super) fn change_current_state(
         &self,
         new_mode: Option<Mode>,
-        new_scale: Option<i32>,
+        new_scale: Option<Scale>,
         new_location: Option<Point<i32, Logical>>,
     ) {
         let mut output = self.inner.lock().unwrap();
@@ -118,7 +121,10 @@ impl XdgOutput {
         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_logical(output.scale);
+                    let logical_size = size
+                        .to_f64()
+                        .to_logical(output.scale.fractional_scale())
+                        .to_i32_round();
                     instance.logical_size(logical_size.w, logical_size.h);
                 }
             }

output: allow fractional scale values