Skip to main content

i_slint_backend_winit/
drag_resize_window.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4// cSpell: ignore xdir ydir
5use winit::window::{CursorIcon, ResizeDirection};
6
7pub fn handle_cursor_move_for_resize(
8    window: &winit::window::Window,
9    position: winit::dpi::PhysicalPosition<f64>,
10    current_direction: Option<ResizeDirection>,
11    border_size: f64,
12) -> Option<ResizeDirection> {
13    if !window.is_decorated() && window.is_resizable() {
14        let location = get_resize_direction(window.inner_size(), position, border_size);
15
16        if current_direction != location {
17            window.set_cursor(resize_direction_cursor_icon(location));
18        }
19
20        return location;
21    }
22
23    None
24}
25
26pub fn handle_resize(window: &winit::window::Window, direction: Option<ResizeDirection>) {
27    if let Some(dir) = direction {
28        let _ = window.drag_resize_window(dir);
29    }
30}
31
32/// Get the cursor icon that corresponds to the resize direction.
33fn resize_direction_cursor_icon(resize_direction: Option<ResizeDirection>) -> CursorIcon {
34    match resize_direction {
35        Some(resize_direction) => match resize_direction {
36            ResizeDirection::East => CursorIcon::EResize,
37            ResizeDirection::North => CursorIcon::NResize,
38            ResizeDirection::NorthEast => CursorIcon::NeResize,
39            ResizeDirection::NorthWest => CursorIcon::NwResize,
40            ResizeDirection::South => CursorIcon::SResize,
41            ResizeDirection::SouthEast => CursorIcon::SeResize,
42            ResizeDirection::SouthWest => CursorIcon::SwResize,
43            ResizeDirection::West => CursorIcon::WResize,
44        },
45        None => CursorIcon::Default,
46    }
47}
48
49fn get_resize_direction(
50    win_size: winit::dpi::PhysicalSize<u32>,
51    position: winit::dpi::PhysicalPosition<f64>,
52    border_size: f64,
53) -> Option<ResizeDirection> {
54    enum X {
55        West,
56        East,
57        Default,
58    }
59
60    enum Y {
61        North,
62        South,
63        Default,
64    }
65
66    let xdir = if position.x < border_size {
67        X::West
68    } else if position.x > (win_size.width as f64 - border_size) {
69        X::East
70    } else {
71        X::Default
72    };
73
74    let ydir = if position.y < border_size {
75        Y::North
76    } else if position.y > (win_size.height as f64 - border_size) {
77        Y::South
78    } else {
79        Y::Default
80    };
81
82    Some(match (xdir, ydir) {
83        (X::West, Y::North) => ResizeDirection::NorthWest,
84        (X::West, Y::South) => ResizeDirection::SouthWest,
85        (X::West, Y::Default) => ResizeDirection::West,
86
87        (X::East, Y::North) => ResizeDirection::NorthEast,
88        (X::East, Y::South) => ResizeDirection::SouthEast,
89        (X::East, Y::Default) => ResizeDirection::East,
90
91        (X::Default, Y::North) => ResizeDirection::North,
92        (X::Default, Y::South) => ResizeDirection::South,
93        (X::Default, Y::Default) => return None,
94    })
95}