Merge pull request #11 from Stremio/fix-full-screen

fix: Retrieve active monitor before going full screen
This commit is contained in:
Владимир Борисов 2025-01-16 09:23:35 +02:00 committed by GitHub
commit c58cbafa69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,147 +1,156 @@
use std::{cmp, mem}; use std::{cmp, mem};
use winapi::shared::windef::HWND; use winapi::shared::windef::HWND;
use winapi::um::winuser::{ use winapi::um::winuser::{
GetForegroundWindow, GetSystemMetrics, GetWindowLongA, GetWindowRect, IsIconic, IsZoomed, GetForegroundWindow, GetMonitorInfoA, GetSystemMetrics, GetWindowLongA, GetWindowRect,
SetForegroundWindow, SetWindowLongA, SetWindowPos, GWL_EXSTYLE, GWL_STYLE, HWND_NOTOPMOST, IsIconic, IsZoomed, MonitorFromWindow, SetForegroundWindow, SetWindowLongA, SetWindowPos,
HWND_TOPMOST, SM_CXSCREEN, SM_CYSCREEN, SWP_FRAMECHANGED, SWP_NOMOVE, SWP_NOSIZE, WS_CAPTION, GWL_EXSTYLE, GWL_STYLE, HWND_NOTOPMOST, HWND_TOPMOST, MONITORINFO, MONITOR_DEFAULTTONEAREST,
WS_EX_CLIENTEDGE, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE, WS_EX_TOPMOST, WS_EX_WINDOWEDGE, SM_CXSCREEN, SM_CYSCREEN, SWP_FRAMECHANGED, SWP_NOMOVE, SWP_NOSIZE, WS_CAPTION,
WS_THICKFRAME, WS_EX_CLIENTEDGE, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE, WS_EX_TOPMOST, WS_EX_WINDOWEDGE,
}; WS_THICKFRAME,
// https://doc.qt.io/qt-5/qt.html#WindowState-enum };
bitflags! { // https://doc.qt.io/qt-5/qt.html#WindowState-enum
struct WindowState: u8 { bitflags! {
const MINIMIZED = 0x01; struct WindowState: u8 {
const MAXIMIZED = 0x02; const MINIMIZED = 0x01;
const FULL_SCREEN = 0x04; const MAXIMIZED = 0x02;
const ACTIVE = 0x08; const FULL_SCREEN = 0x04;
} const ACTIVE = 0x08;
} }
}
#[derive(Default, Clone)]
pub struct WindowStyle { #[derive(Default, Clone)]
pub full_screen: bool, pub struct WindowStyle {
pub pos: (i32, i32), pub full_screen: bool,
pub size: (i32, i32), pub pos: (i32, i32),
pub style: i32, pub size: (i32, i32),
pub ex_style: i32, pub style: i32,
} pub ex_style: i32,
}
impl WindowStyle {
pub fn get_window_state(self, hwnd: HWND) -> u32 { impl WindowStyle {
let mut state: WindowState = WindowState::empty(); pub fn get_window_state(self, hwnd: HWND) -> u32 {
if 0 != unsafe { IsIconic(hwnd) } { let mut state: WindowState = WindowState::empty();
state |= WindowState::MINIMIZED; if 0 != unsafe { IsIconic(hwnd) } {
} state |= WindowState::MINIMIZED;
if 0 != unsafe { IsZoomed(hwnd) } { }
state |= WindowState::MAXIMIZED; if 0 != unsafe { IsZoomed(hwnd) } {
} state |= WindowState::MAXIMIZED;
if hwnd == unsafe { GetForegroundWindow() } { }
state |= WindowState::ACTIVE if hwnd == unsafe { GetForegroundWindow() } {
} state |= WindowState::ACTIVE
if self.full_screen { }
state |= WindowState::FULL_SCREEN; if self.full_screen {
} state |= WindowState::FULL_SCREEN;
state.bits() as u32 }
} state.bits() as u32
pub fn is_window_minimized(&self, hwnd: HWND) -> bool { }
0 != unsafe { IsIconic(hwnd) } pub fn is_window_minimized(&self, hwnd: HWND) -> bool {
} 0 != unsafe { IsIconic(hwnd) }
pub fn show_window_at(&self, hwnd: HWND, pos: HWND) { }
unsafe { pub fn show_window_at(&self, hwnd: HWND, pos: HWND) {
SetWindowPos( unsafe {
hwnd, SetWindowPos(
pos, hwnd,
self.pos.0, pos,
self.pos.1, self.pos.0,
self.size.0, self.pos.1,
self.size.1, self.size.0,
SWP_FRAMECHANGED, self.size.1,
); SWP_FRAMECHANGED,
} );
} }
pub fn center_window(&mut self, hwnd: HWND, min_width: i32, min_height: i32) { }
let monitor_w = unsafe { GetSystemMetrics(SM_CXSCREEN) }; pub fn center_window(&mut self, hwnd: HWND, min_width: i32, min_height: i32) {
let monitor_h = unsafe { GetSystemMetrics(SM_CYSCREEN) }; let monitor_w = unsafe { GetSystemMetrics(SM_CXSCREEN) };
let small_side = cmp::min(monitor_w, monitor_h) * 70 / 100; let monitor_h = unsafe { GetSystemMetrics(SM_CYSCREEN) };
self.size = ( let small_side = cmp::min(monitor_w, monitor_h) * 70 / 100;
cmp::max(small_side * 16 / 9, min_width), self.size = (
cmp::max(small_side, min_height), cmp::max(small_side * 16 / 9, min_width),
); cmp::max(small_side, min_height),
self.pos = ((monitor_w - self.size.0) / 2, (monitor_h - self.size.1) / 2); );
self.show_window_at(hwnd, HWND_NOTOPMOST); self.pos = ((monitor_w - self.size.0) / 2, (monitor_h - self.size.1) / 2);
} self.show_window_at(hwnd, HWND_NOTOPMOST);
pub fn toggle_full_screen(&mut self, hwnd: HWND) { }
if self.full_screen { pub fn toggle_full_screen(&mut self, hwnd: HWND) {
let topmost = if self.ex_style as u32 & WS_EX_TOPMOST == WS_EX_TOPMOST { if self.full_screen {
HWND_TOPMOST let topmost = if self.ex_style as u32 & WS_EX_TOPMOST == WS_EX_TOPMOST {
} else { HWND_TOPMOST
HWND_NOTOPMOST } else {
}; HWND_NOTOPMOST
unsafe { };
SetWindowLongA(hwnd, GWL_STYLE, self.style); unsafe {
SetWindowLongA(hwnd, GWL_EXSTYLE, self.ex_style); SetWindowLongA(hwnd, GWL_STYLE, self.style);
} SetWindowLongA(hwnd, GWL_EXSTYLE, self.ex_style);
self.show_window_at(hwnd, topmost); }
self.full_screen = false; self.show_window_at(hwnd, topmost);
} else { self.full_screen = false;
unsafe { } else {
let mut rect = mem::zeroed(); unsafe {
GetWindowRect(hwnd, &mut rect); let mut rect = mem::zeroed();
self.pos = (rect.left, rect.top); GetWindowRect(hwnd, &mut rect);
self.size = ((rect.right - rect.left), (rect.bottom - rect.top)); self.pos = (rect.left, rect.top);
self.style = GetWindowLongA(hwnd, GWL_STYLE); self.size = ((rect.right - rect.left), (rect.bottom - rect.top));
self.ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); self.style = GetWindowLongA(hwnd, GWL_STYLE);
SetWindowLongA( self.ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
hwnd,
GWL_STYLE, let monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
self.style & !(WS_CAPTION as i32 | WS_THICKFRAME as i32), let mut monitor_info: MONITORINFO = mem::zeroed();
); monitor_info.cbSize = mem::size_of_val(&monitor_info) as u32;
SetWindowLongA( if GetMonitorInfoA(monitor, &mut monitor_info) == 0 {
hwnd, println!("GetMonitorInfoA failed");
GWL_EXSTYLE, return;
self.ex_style }
& !(WS_EX_DLGMODALFRAME as i32 SetWindowLongA(
| WS_EX_WINDOWEDGE as i32 hwnd,
| WS_EX_CLIENTEDGE as i32 GWL_STYLE,
| WS_EX_STATICEDGE as i32), self.style & !(WS_CAPTION as i32 | WS_THICKFRAME as i32),
); );
SetWindowPos( SetWindowLongA(
hwnd, hwnd,
HWND_NOTOPMOST, GWL_EXSTYLE,
0, self.ex_style
0, & !(WS_EX_DLGMODALFRAME as i32
GetSystemMetrics(SM_CXSCREEN), | WS_EX_WINDOWEDGE as i32
GetSystemMetrics(SM_CYSCREEN), | WS_EX_CLIENTEDGE as i32
SWP_FRAMECHANGED, | WS_EX_STATICEDGE as i32),
); );
} SetWindowPos(
self.full_screen = true; hwnd,
} HWND_NOTOPMOST,
} monitor_info.rcMonitor.left,
pub fn toggle_topmost(&mut self, hwnd: HWND) { monitor_info.rcMonitor.top,
let topmost = if unsafe { GetWindowLongA(hwnd, GWL_EXSTYLE) } as u32 & WS_EX_TOPMOST monitor_info.rcMonitor.right - monitor_info.rcMonitor.left,
== WS_EX_TOPMOST monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top,
{ SWP_FRAMECHANGED,
HWND_NOTOPMOST );
} else { }
HWND_TOPMOST self.full_screen = true;
}; }
unsafe { }
SetWindowPos( pub fn toggle_topmost(&mut self, hwnd: HWND) {
hwnd, let topmost = if unsafe { GetWindowLongA(hwnd, GWL_EXSTYLE) } as u32 & WS_EX_TOPMOST
topmost, == WS_EX_TOPMOST
0, {
0, HWND_NOTOPMOST
0, } else {
0, HWND_TOPMOST
SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED, };
); unsafe {
} SetWindowPos(
self.ex_style = unsafe { GetWindowLongA(hwnd, GWL_EXSTYLE) }; hwnd,
} topmost,
pub fn set_active(&mut self, hwnd: HWND) { 0,
unsafe { 0,
SetForegroundWindow(hwnd); 0,
} 0,
} SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED,
} );
}
self.ex_style = unsafe { GetWindowLongA(hwnd, GWL_EXSTYLE) };
}
pub fn set_active(&mut self, hwnd: HWND) {
unsafe {
SetForegroundWindow(hwnd);
}
}
}