Desktop: Add fullscreen window mode (#3625)

This commit is contained in:
Timon
2026-01-19 17:32:03 +01:00
committed by GitHub
parent fd0addf61c
commit 07fbcd489c
20 changed files with 195 additions and 153 deletions

View File

@@ -352,6 +352,11 @@ impl App {
window.toggle_maximize();
}
}
DesktopFrontendMessage::WindowFullscreen => {
if let Some(window) = &mut self.window {
window.toggle_fullscreen();
}
}
DesktopFrontendMessage::WindowDrag => {
if let Some(window) = &self.window {
window.start_drag();

View File

@@ -1,13 +1,13 @@
use crate::consts::APP_NAME;
use crate::event::AppEventScheduler;
use crate::wrapper::messages::MenuItem;
use std::collections::HashMap;
use std::sync::Arc;
use winit::cursor::{CursorIcon, CustomCursor, CustomCursorSource};
use winit::event_loop::ActiveEventLoop;
use winit::monitor::Fullscreen;
use winit::window::{Window as WinitWindow, WindowAttributes};
use crate::consts::APP_NAME;
use crate::event::AppEventScheduler;
use crate::wrapper::messages::MenuItem;
pub(crate) trait NativeWindow {
fn init() {}
fn configure(attributes: WindowAttributes, event_loop: &dyn ActiveEventLoop) -> WindowAttributes;
@@ -111,6 +111,9 @@ impl Window {
}
pub(crate) fn toggle_maximize(&self) {
if self.is_fullscreen() {
return;
}
self.winit_window.set_maximized(!self.winit_window.is_maximized());
}
@@ -118,11 +121,22 @@ impl Window {
self.winit_window.is_maximized()
}
pub(crate) fn toggle_fullscreen(&mut self) {
if self.is_fullscreen() {
self.winit_window.set_fullscreen(None);
} else {
self.winit_window.set_fullscreen(Some(Fullscreen::Borderless(None)));
}
}
pub(crate) fn is_fullscreen(&self) -> bool {
self.winit_window.fullscreen().is_some()
}
pub(crate) fn start_drag(&self) {
if self.is_fullscreen() {
return;
}
let _ = self.winit_window.drag_window();
}

View File

@@ -210,10 +210,10 @@ unsafe fn ensure_helper_class() {
// Main window message handler, called on the UI thread for every message the main window receives.
unsafe extern "system" fn main_window_handle_message(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
if msg == WM_NCCALCSIZE && wparam.0 != 0 {
// When maximized, shrink to visible frame so content doesn't extend beyond it.
if unsafe { IsZoomed(hwnd).as_bool() } {
let params = unsafe { &mut *(lparam.0 as *mut NCCALCSIZE_PARAMS) };
let params = unsafe { &mut *(lparam.0 as *mut NCCALCSIZE_PARAMS) };
// When maximized, shrink to visible frame so content doesn't extend beyond it.
if unsafe { IsZoomed(hwnd).as_bool() } && !is_effectively_fullscreen(params.rgrc[0]) {
let dpi = unsafe { GetDpiForWindow(hwnd) };
let size = unsafe { GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) };
let pad = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) };
@@ -366,3 +366,27 @@ unsafe fn calculate_resize_direction(helper: HWND, lparam: LPARAM) -> Option<u32
_ => None,
}
}
// Check if the rect is effectively fullscreen, meaning it would cover the entire monitor.
// We need to use this heuristic because Windows doesn't provide a way to check for fullscreen state.
fn is_effectively_fullscreen(rect: RECT) -> bool {
let hmon = unsafe { MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST) };
if hmon.is_invalid() {
return false;
}
let mut monitor_info = MONITORINFO {
cbSize: std::mem::size_of::<MONITORINFO>() as u32,
..Default::default()
};
if !unsafe { GetMonitorInfoW(hmon, &mut monitor_info) }.as_bool() {
return false;
}
// Allow a tiny tolerance for DPI / rounding issues
const EPS: i32 = 1;
(rect.left - monitor_info.rcMonitor.left).abs() <= EPS
&& (rect.top - monitor_info.rcMonitor.top).abs() <= EPS
&& (rect.right - monitor_info.rcMonitor.right).abs() <= EPS
&& (rect.bottom - monitor_info.rcMonitor.bottom).abs() <= EPS
}

View File

@@ -148,6 +148,9 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
FrontendMessage::WindowMaximize => {
dispatcher.respond(DesktopFrontendMessage::WindowMaximize);
}
FrontendMessage::WindowFullscreen => {
dispatcher.respond(DesktopFrontendMessage::WindowFullscreen);
}
FrontendMessage::WindowDrag => {
dispatcher.respond(DesktopFrontendMessage::WindowDrag);
}

View File

@@ -69,6 +69,7 @@ pub enum DesktopFrontendMessage {
WindowClose,
WindowMinimize,
WindowMaximize,
WindowFullscreen,
WindowDrag,
WindowHide,
WindowHideOthers,