From b19e95fa1844ca726aa5761f2d331fd780854bc6 Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector@hecrj.dev>
Date: Fri, 10 May 2024 22:16:35 +0200
Subject: Add `SpecificWith` variant to `window::Position`

---
 core/src/window/position.rs |  8 +++++++-
 winit/src/conversion.rs     | 29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/core/src/window/position.rs b/core/src/window/position.rs
index 73391e75..1c8e86b6 100644
--- a/core/src/window/position.rs
+++ b/core/src/window/position.rs
@@ -1,4 +1,4 @@
-use crate::Point;
+use crate::{Point, Size};
 
 /// The position of a window in a given screen.
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -15,6 +15,12 @@ pub enum Position {
     /// at (0, 0) you would have to set the position to
     /// `(PADDING_X, PADDING_Y)`.
     Specific(Point),
+    /// Like [`Specific`], but the window is positioned with the specific coordinates returned by the function.
+    ///
+    /// The function receives the window size and the monitor's resolution as input.
+    ///
+    /// [`Specific`]: Self::Specific
+    SpecificWith(fn(Size, Size) -> Point),
 }
 
 impl Default for Position {
diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs
index d04fc2f1..ea33e610 100644
--- a/winit/src/conversion.rs
+++ b/winit/src/conversion.rs
@@ -323,6 +323,35 @@ pub fn position(
                 y: f64::from(position.y),
             }))
         }
+        window::Position::SpecificWith(to_position) => {
+            if let Some(monitor) = monitor {
+                let start = monitor.position();
+
+                let resolution: winit::dpi::LogicalSize<f32> =
+                    monitor.size().to_logical(monitor.scale_factor());
+
+                let position = to_position(
+                    size,
+                    Size::new(resolution.width, resolution.height),
+                );
+
+                let centered: winit::dpi::PhysicalPosition<i32> =
+                    winit::dpi::LogicalPosition {
+                        x: position.x,
+                        y: position.y,
+                    }
+                    .to_physical(monitor.scale_factor());
+
+                Some(winit::dpi::Position::Physical(
+                    winit::dpi::PhysicalPosition {
+                        x: start.x + centered.x,
+                        y: start.y + centered.y,
+                    },
+                ))
+            } else {
+                None
+            }
+        }
         window::Position::Centered => {
             if let Some(monitor) = monitor {
                 let start = monitor.position();
-- 
cgit