Skip to content

Commit

Permalink
Add DWMWA_SYSTEMBACKDROP_TYPE support on Windows (#3257)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dubzer authored Jan 25, 2024
1 parent d0a1917 commit 98d3391
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
1 change: 1 addition & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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>,
Expand All @@ -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,
Expand Down
21 changes: 18 additions & 3 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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::{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 98d3391

Please sign in to comment.