Add DWMWA_SYSTEMBACKDROP_TYPE support on Windows (#3257)

This commit is contained in:
Dubzer 2024-01-25 20:59:10 +03:00 committed by GitHub
parent d0a1917603
commit 98d3391f2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 76 additions and 5 deletions

View file

@ -33,7 +33,7 @@ Unreleased` header.
- Add the `OwnedDisplayHandle` type for allowing safe display handle usage outside of trivial cases.
- **Breaking:** Rename `TouchpadMagnify` to `PinchGesture`, `SmartMagnify` to `DoubleTapGesture` and `TouchpadRotate` to `RotationGesture` to represent the action rather than the intent.
- on iOS, add detection support for `PinchGesture`, `DoubleTapGesture` and `RotationGesture`.
- on Windows: add `with_border_color`, `with_title_background_color`, `with_title_text_color` and `with_corner_preference`
- on Windows: add `with_system_backdrop`, `with_border_color`, `with_title_background_color`, `with_title_text_color` and `with_corner_preference`
- On Windows, Remove `WS_CAPTION`, `WS_BORDER` and `WS_EX_WINDOWEDGE` styles for child windows without decorations.
- On Windows, fixed a race condition when sending an event through the loop proxy.

View file

@ -126,6 +126,7 @@ If your PR makes notable changes to Winit's features, please update this section
* Setting a menu bar
* `WS_EX_NOREDIRECTIONBITMAP` support
* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme
* Changing a system-drawn backdrop
* Setting the window border color
* Setting the title bar background color
* Setting the title color

View file

@ -15,6 +15,38 @@ pub type HMENU = isize;
/// Monitor Handle type used by Win32 API
pub type HMONITOR = isize;
/// Describes a system-drawn backdrop material of a window.
///
/// For a detailed explanation, see [`DWM_SYSTEMBACKDROP_TYPE docs`].
///
/// [`DWM_SYSTEMBACKDROP_TYPE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_systembackdrop_type
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BackdropType {
/// Corresponds to `DWMSBT_AUTO`.
///
/// Usually draws a default backdrop effect on the title bar.
#[default]
Auto = 0,
/// Corresponds to `DWMSBT_NONE`.
None = 1,
/// Corresponds to `DWMSBT_MAINWINDOW`.
///
/// Draws the Mica backdrop material.
MainWindow = 2,
/// Corresponds to `DWMSBT_TRANSIENTWINDOW`.
///
/// Draws the Background Acrylic backdrop material.
TransientWindow = 3,
/// Corresponds to `DWMSBT_TABBEDWINDOW`.
///
/// Draws the Alt Mica backdrop material.
TabbedWindow = 4,
}
/// Describes a color used by Windows
#[repr(transparent)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@ -188,6 +220,11 @@ pub trait WindowExtWindows {
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
fn set_undecorated_shadow(&self, shadow: bool);
/// Sets system-drawn backdrop type.
///
/// Requires Windows 11 build 22523+.
fn set_system_backdrop(&self, backdrop_type: BackdropType);
/// Sets the color of the window border.
///
/// Supported starting with Windows 11 Build 22000.
@ -230,6 +267,11 @@ impl WindowExtWindows for Window {
self.window.set_undecorated_shadow(shadow)
}
#[inline]
fn set_system_backdrop(&self, backdrop_type: BackdropType) {
self.window.set_system_backdrop(backdrop_type)
}
#[inline]
fn set_border_color(&self, color: Option<Color>) {
self.window.set_border_color(color.unwrap_or(Color::NONE))
@ -315,6 +357,11 @@ pub trait WindowBuilderExtWindows {
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
fn with_undecorated_shadow(self, shadow: bool) -> Self;
/// Sets system-drawn backdrop type.
///
/// Requires Windows 11 build 22523+.
fn with_system_backdrop(self, backdrop_type: BackdropType) -> Self;
/// This sets or removes `WS_CLIPCHILDREN` style.
fn with_clip_children(self, flag: bool) -> Self;
@ -388,6 +435,12 @@ impl WindowBuilderExtWindows for WindowBuilder {
self
}
#[inline]
fn with_system_backdrop(mut self, backdrop_type: BackdropType) -> Self {
self.window.platform_specific.backdrop_type = backdrop_type;
self
}
#[inline]
fn with_clip_children(mut self, flag: bool) -> Self {
self.window.platform_specific.clip_children = flag;

View file

@ -25,7 +25,7 @@ use crate::platform_impl::Fullscreen;
use crate::event::DeviceId as RootDeviceId;
use crate::icon::Icon;
use crate::keyboard::Key;
use crate::platform::windows::{Color, CornerPreference};
use crate::platform::windows::{BackdropType, Color, CornerPreference};
#[derive(Clone, Debug)]
pub struct PlatformSpecificWindowBuilderAttributes {
@ -37,6 +37,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub skip_taskbar: bool,
pub class_name: String,
pub decoration_shadow: bool,
pub backdrop_type: BackdropType,
pub clip_children: bool,
pub border_color: Option<Color>,
pub title_background_color: Option<Color>,
@ -55,6 +56,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
skip_taskbar: false,
class_name: "Window Class".to_string(),
decoration_shadow: false,
backdrop_type: BackdropType::default(),
clip_children: true,
border_color: None,
title_background_color: None,

View file

@ -16,8 +16,9 @@ use windows_sys::Win32::{
Graphics::{
Dwm::{
DwmEnableBlurBehindWindow, DwmSetWindowAttribute, DWMWA_BORDER_COLOR,
DWMWA_CAPTION_COLOR, DWMWA_TEXT_COLOR, DWMWA_WINDOW_CORNER_PREFERENCE,
DWM_BB_BLURREGION, DWM_BB_ENABLE, DWM_BLURBEHIND, DWM_WINDOW_CORNER_PREFERENCE,
DWMWA_CAPTION_COLOR, DWMWA_SYSTEMBACKDROP_TYPE, DWMWA_TEXT_COLOR,
DWMWA_WINDOW_CORNER_PREFERENCE, DWM_BB_BLURREGION, DWM_BB_ENABLE, DWM_BLURBEHIND,
DWM_SYSTEMBACKDROP_TYPE, DWM_WINDOW_CORNER_PREFERENCE,
},
Gdi::{
ChangeDisplaySettingsExW, ClientToScreen, CreateRectRgn, DeleteObject, InvalidateRgn,
@ -60,12 +61,12 @@ use windows_sys::Win32::{
use log::warn;
use crate::platform::windows::{Color, CornerPreference};
use crate::{
cursor::Cursor,
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError as RootOsError},
icon::Icon,
platform::windows::{BackdropType, Color, CornerPreference},
platform_impl::platform::{
dark_mode::try_theme,
definitions::{
@ -1019,6 +1020,18 @@ impl Window {
});
}
#[inline]
pub fn set_system_backdrop(&self, backdrop_type: BackdropType) {
unsafe {
DwmSetWindowAttribute(
self.hwnd(),
DWMWA_SYSTEMBACKDROP_TYPE,
&(backdrop_type as i32) as *const _ as _,
mem::size_of::<DWM_SYSTEMBACKDROP_TYPE>() as _,
);
}
}
#[inline]
pub fn focus_window(&self) {
let window_flags = self.window_state_lock().window_flags();
@ -1308,6 +1321,8 @@ impl<'a> InitData<'a> {
win.set_outer_position(position);
}
win.set_system_backdrop(self.attributes.platform_specific.backdrop_type);
if let Some(color) = self.attributes.platform_specific.border_color {
win.set_border_color(color);
}