EvanZhu0721 / 公开仓库
SBMS
SBMS complete the calculation rules for the default logical desktop topology relationship and the physical dimensions of the displays in the Windows multi-screen collaboration system.
文件
../ bininputuiconfig.rs81.2 KBcontrol.rs4.1 KBcontroller.rs43.6 KBdiagnostics.rs24.2 KBdisplay.rs29.8 KBgeometry.rs21.4 KBgpu_renderer.rs37.4 KBinput.rs79.7 KBlaunch_broker.rs10.3 KBlib.rs350 Blimits.rs714 Bmain.rs24.4 KBmapping.rs46.5 KBnetwork.rs9.2 KBrenderer.rs20.6 KBsession_gate.rs14.9 KBsunshine.rs12.2 KBui.rs68.5 KBvirtual_display.rs7.2 KBwin32_flyout.rs3.4 KBwin32_tray.rs22.3 KBwindow_migration.rs43.8 KBsrc/win32_flyout.rs3.4 KB
1
use std::mem::size_of;2
3
use raw_window_handle::{HasWindowHandle, RawWindowHandle};4
use slint::{PhysicalPosition, Window};5
use windows::Win32::Foundation::{HWND, POINT, RECT};6
use windows::Win32::Graphics::Gdi::{7
GetMonitorInfoW, MONITOR_DEFAULTTONEAREST, MONITORINFO, MonitorFromPoint,8
};9
use windows::Win32::UI::WindowsAndMessaging::{GetCursorPos, SetForegroundWindow};10
const FLYOUT_GAP: i32 = 8;11
12
pub fn position(window: &Window) {13
let anchor = crate::win32_tray::icon_rect().or_else(cursor_rect);14
let Some(anchor) = anchor else {15
return;16
};17
let center = POINT {18
x: anchor.left + (anchor.right - anchor.left) / 2,19
y: anchor.top + (anchor.bottom - anchor.top) / 2,20
};21
let monitor = unsafe { MonitorFromPoint(center, MONITOR_DEFAULTTONEAREST) };22
let mut info = MONITORINFO {23
cbSize: size_of::<MONITORINFO>() as u32,24
rcMonitor: RECT::default(),25
rcWork: RECT::default(),26
dwFlags: 0,27
};28
if !unsafe { GetMonitorInfoW(monitor, &mut info) }.as_bool() {29
return;30
}31
32
let size = window.size();33
let width = size.width as i32;34
let height = size.height as i32;35
let edge = taskbar_edge(info.rcMonitor, info.rcWork, center);36
let (x, y) = match edge {37
Edge::Bottom => (38
center.x - width / 2,39
info.rcWork.bottom - height - FLYOUT_GAP,40
),41
Edge::Top => (center.x - width / 2, info.rcWork.top + FLYOUT_GAP),42
Edge::Left => (info.rcWork.left + FLYOUT_GAP, center.y - height / 2),43
Edge::Right => (44
info.rcWork.right - width - FLYOUT_GAP,45
center.y - height / 2,46
),47
};48
let max_x = (info.rcWork.right - width).max(info.rcWork.left);49
let max_y = (info.rcWork.bottom - height).max(info.rcWork.top);50
let x = x.clamp(info.rcWork.left, max_x);51
let y = y.clamp(info.rcWork.top, max_y);52
window.set_position(PhysicalPosition::new(x, y));53
}54
55
pub fn activate(window: &Window) -> bool {56
if let Some(hwnd) = hwnd(window) {57
return unsafe { SetForegroundWindow(hwnd) }.as_bool();58
}59
false60
}61
62
fn hwnd(window: &Window) -> Option<HWND> {63
let provider = window.window_handle();64
let handle = provider.window_handle().ok()?;65
match handle.as_raw() {66
RawWindowHandle::Win32(handle) => Some(HWND(handle.hwnd.get() as *mut _)),67
_ => None,68
}69
}70
71
fn cursor_rect() -> Option<RECT> {72
let mut cursor = POINT::default();73
unsafe { GetCursorPos(&mut cursor) }.ok()?;74
Some(RECT {75
left: cursor.x,76
top: cursor.y,77
right: cursor.x + 1,78
bottom: cursor.y + 1,79
})80
}81
82
#[derive(Clone, Copy)]83
enum Edge {84
Bottom,85
Top,86
Left,87
Right,88
}89
90
fn taskbar_edge(monitor: RECT, work: RECT, anchor: POINT) -> Edge {91
if work.bottom < monitor.bottom {92
return Edge::Bottom;93
}94
if work.top > monitor.top {95
return Edge::Top;96
}97
if work.left > monitor.left {98
return Edge::Left;99
}100
if work.right < monitor.right {101
return Edge::Right;102
}103
104
let distances = [105
(anchor.y - monitor.top, Edge::Top),106
(monitor.bottom - anchor.y, Edge::Bottom),107
(anchor.x - monitor.left, Edge::Left),108
(monitor.right - anchor.x, Edge::Right),109
];110
distances111
.into_iter()112
.min_by_key(|(distance, _)| *distance)113
.map(|(_, edge)| edge)114
.unwrap_or(Edge::Bottom)115
}116