mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-02 23:00:05 -04:00
On Windows, expose DWM attributes (#3409)
This commit is contained in:
@@ -33,6 +33,7 @@ Unreleased` header.
|
|||||||
- Add the `OwnedDisplayHandle` type for allowing safe display handle usage outside of trivial cases.
|
- 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.
|
- **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 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`
|
||||||
|
|
||||||
# 0.29.10
|
# 0.29.10
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,10 @@ If your PR makes notable changes to Winit's features, please update this section
|
|||||||
* Setting a menu bar
|
* Setting a menu bar
|
||||||
* `WS_EX_NOREDIRECTIONBITMAP` support
|
* `WS_EX_NOREDIRECTIONBITMAP` support
|
||||||
* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme
|
* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme
|
||||||
|
* Setting the window border color
|
||||||
|
* Setting the title bar background color
|
||||||
|
* Setting the title color
|
||||||
|
* Setting the corner rounding preference
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
* Window activation policy
|
* Window activation policy
|
||||||
|
|||||||
@@ -15,6 +15,60 @@ pub type HMENU = isize;
|
|||||||
/// Monitor Handle type used by Win32 API
|
/// Monitor Handle type used by Win32 API
|
||||||
pub type HMONITOR = isize;
|
pub type HMONITOR = isize;
|
||||||
|
|
||||||
|
/// Describes a color used by Windows
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Color(u32);
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
/// Use the system's default color
|
||||||
|
pub const SYSTEM_DEFAULT: Color = Color(0xFFFFFFFF);
|
||||||
|
|
||||||
|
//Special constant only valid for the window border and therefore modeled using Option<Color> for user facing code
|
||||||
|
const NONE: Color = Color(0xFFFFFFFE);
|
||||||
|
|
||||||
|
/// Create a new color from the given RGB values
|
||||||
|
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
|
||||||
|
Self((r as u32) | ((g as u32) << 8) | ((b as u32) << 16))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Color {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::SYSTEM_DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Describes how the corners of a window should look like.
|
||||||
|
///
|
||||||
|
/// For a detailed explanation, see [`DWM_WINDOW_CORNER_PREFERENCE docs`].
|
||||||
|
///
|
||||||
|
/// [`DWM_WINDOW_CORNER_PREFERENCE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_window_corner_preference
|
||||||
|
#[repr(i32)]
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum CornerPreference {
|
||||||
|
/// Corresponds to `DWMWCP_DEFAULT`.
|
||||||
|
///
|
||||||
|
/// Let the system decide when to round window corners.
|
||||||
|
#[default]
|
||||||
|
Default = 0,
|
||||||
|
|
||||||
|
/// Corresponds to `DWMWCP_DONOTROUND`.
|
||||||
|
///
|
||||||
|
/// Never round window corners.
|
||||||
|
DoNotRound = 1,
|
||||||
|
|
||||||
|
/// Corresponds to `DWMWCP_ROUND`.
|
||||||
|
///
|
||||||
|
/// Round the corners, if appropriate.
|
||||||
|
Round = 2,
|
||||||
|
|
||||||
|
/// Corresponds to `DWMWCP_ROUNDSMALL`.
|
||||||
|
///
|
||||||
|
/// Round the corners if appropriate, with a small radius.
|
||||||
|
RoundSmall = 3,
|
||||||
|
}
|
||||||
|
|
||||||
/// Additional methods on `EventLoop` that are specific to Windows.
|
/// Additional methods on `EventLoop` that are specific to Windows.
|
||||||
pub trait EventLoopBuilderExtWindows {
|
pub trait EventLoopBuilderExtWindows {
|
||||||
/// Whether to allow the event loop to be created off of the main thread.
|
/// Whether to allow the event loop to be created off of the main thread.
|
||||||
@@ -133,6 +187,26 @@ pub trait WindowExtWindows {
|
|||||||
///
|
///
|
||||||
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
|
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
|
||||||
fn set_undecorated_shadow(&self, shadow: bool);
|
fn set_undecorated_shadow(&self, shadow: bool);
|
||||||
|
|
||||||
|
/// Sets the color of the window border.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn set_border_color(&self, color: Option<Color>);
|
||||||
|
|
||||||
|
/// Sets the background color of the title bar.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn set_title_background_color(&self, color: Option<Color>);
|
||||||
|
|
||||||
|
/// Sets the color of the window title.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn set_title_text_color(&self, color: Color);
|
||||||
|
|
||||||
|
/// Sets the preferred style of the window corners.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn set_corner_preference(&self, preference: CornerPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowExtWindows for Window {
|
impl WindowExtWindows for Window {
|
||||||
@@ -155,6 +229,29 @@ impl WindowExtWindows for Window {
|
|||||||
fn set_undecorated_shadow(&self, shadow: bool) {
|
fn set_undecorated_shadow(&self, shadow: bool) {
|
||||||
self.window.set_undecorated_shadow(shadow)
|
self.window.set_undecorated_shadow(shadow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_border_color(&self, color: Option<Color>) {
|
||||||
|
self.window.set_border_color(color.unwrap_or(Color::NONE))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_title_background_color(&self, color: Option<Color>) {
|
||||||
|
// The windows docs don't mention NONE as a valid options but it works in practice and is useful
|
||||||
|
// to circumvent the Windows option "Show accent color on title bars and window borders"
|
||||||
|
self.window
|
||||||
|
.set_title_background_color(color.unwrap_or(Color::NONE))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_title_text_color(&self, color: Color) {
|
||||||
|
self.window.set_title_text_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_corner_preference(&self, preference: CornerPreference) {
|
||||||
|
self.window.set_corner_preference(preference)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods on `WindowBuilder` that are specific to Windows.
|
/// Additional methods on `WindowBuilder` that are specific to Windows.
|
||||||
@@ -217,6 +314,26 @@ pub trait WindowBuilderExtWindows {
|
|||||||
/// The shadow is hidden by default.
|
/// The shadow is hidden by default.
|
||||||
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
|
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
|
||||||
fn with_undecorated_shadow(self, shadow: bool) -> Self;
|
fn with_undecorated_shadow(self, shadow: bool) -> Self;
|
||||||
|
|
||||||
|
/// Sets the color of the window border.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn with_border_color(self, color: Option<Color>) -> Self;
|
||||||
|
|
||||||
|
/// Sets the background color of the title bar.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn with_title_background_color(self, color: Option<Color>) -> Self;
|
||||||
|
|
||||||
|
/// Sets the color of the window title.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn with_title_text_color(self, color: Color) -> Self;
|
||||||
|
|
||||||
|
/// Sets the preferred style of the window corners.
|
||||||
|
///
|
||||||
|
/// Supported starting with Windows 11 Build 22000.
|
||||||
|
fn with_corner_preference(self, corners: CornerPreference) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowBuilderExtWindows for WindowBuilder {
|
impl WindowBuilderExtWindows for WindowBuilder {
|
||||||
@@ -267,6 +384,30 @@ impl WindowBuilderExtWindows for WindowBuilder {
|
|||||||
self.window.platform_specific.decoration_shadow = shadow;
|
self.window.platform_specific.decoration_shadow = shadow;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_border_color(mut self, color: Option<Color>) -> Self {
|
||||||
|
self.window.platform_specific.border_color = Some(color.unwrap_or(Color::NONE));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_title_background_color(mut self, color: Option<Color>) -> Self {
|
||||||
|
self.window.platform_specific.title_background_color = Some(color.unwrap_or(Color::NONE));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_title_text_color(mut self, color: Color) -> Self {
|
||||||
|
self.window.platform_specific.title_text_color = Some(color);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_corner_preference(mut self, corners: CornerPreference) -> Self {
|
||||||
|
self.window.platform_specific.corner_preference = Some(corners);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods on `MonitorHandle` that are specific to Windows.
|
/// Additional methods on `MonitorHandle` that are specific to Windows.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use crate::platform_impl::Fullscreen;
|
|||||||
use crate::event::DeviceId as RootDeviceId;
|
use crate::event::DeviceId as RootDeviceId;
|
||||||
use crate::icon::Icon;
|
use crate::icon::Icon;
|
||||||
use crate::keyboard::Key;
|
use crate::keyboard::Key;
|
||||||
|
use crate::platform::windows::{Color, CornerPreference};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes {
|
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
@@ -36,6 +37,10 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
|||||||
pub skip_taskbar: bool,
|
pub skip_taskbar: bool,
|
||||||
pub class_name: String,
|
pub class_name: String,
|
||||||
pub decoration_shadow: bool,
|
pub decoration_shadow: bool,
|
||||||
|
pub border_color: Option<Color>,
|
||||||
|
pub title_background_color: Option<Color>,
|
||||||
|
pub title_text_color: Option<Color>,
|
||||||
|
pub corner_preference: Option<CornerPreference>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
@@ -49,6 +54,10 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
|
|||||||
skip_taskbar: false,
|
skip_taskbar: false,
|
||||||
class_name: "Window Class".to_string(),
|
class_name: "Window Class".to_string(),
|
||||||
decoration_shadow: false,
|
decoration_shadow: false,
|
||||||
|
border_color: None,
|
||||||
|
title_background_color: None,
|
||||||
|
title_text_color: None,
|
||||||
|
corner_preference: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ use windows_sys::Win32::{
|
|||||||
HWND, LPARAM, OLE_E_WRONGCOMPOBJ, POINT, POINTS, RECT, RPC_E_CHANGED_MODE, S_OK, WPARAM,
|
HWND, LPARAM, OLE_E_WRONGCOMPOBJ, POINT, POINTS, RECT, RPC_E_CHANGED_MODE, S_OK, WPARAM,
|
||||||
},
|
},
|
||||||
Graphics::{
|
Graphics::{
|
||||||
Dwm::{DwmEnableBlurBehindWindow, DWM_BB_BLURREGION, DWM_BB_ENABLE, DWM_BLURBEHIND},
|
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,
|
||||||
|
},
|
||||||
Gdi::{
|
Gdi::{
|
||||||
ChangeDisplaySettingsExW, ClientToScreen, CreateRectRgn, DeleteObject, InvalidateRgn,
|
ChangeDisplaySettingsExW, ClientToScreen, CreateRectRgn, DeleteObject, InvalidateRgn,
|
||||||
RedrawWindow, CDS_FULLSCREEN, DISP_CHANGE_BADFLAGS, DISP_CHANGE_BADMODE,
|
RedrawWindow, CDS_FULLSCREEN, DISP_CHANGE_BADFLAGS, DISP_CHANGE_BADMODE,
|
||||||
@@ -56,6 +60,7 @@ use windows_sys::Win32::{
|
|||||||
|
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
|
||||||
|
use crate::platform::windows::{Color, CornerPreference};
|
||||||
use crate::{
|
use crate::{
|
||||||
cursor::Cursor,
|
cursor::Cursor,
|
||||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
@@ -1060,6 +1065,54 @@ impl Window {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_border_color(&self, color: Color) {
|
||||||
|
unsafe {
|
||||||
|
DwmSetWindowAttribute(
|
||||||
|
self.hwnd(),
|
||||||
|
DWMWA_BORDER_COLOR,
|
||||||
|
&color as *const _ as _,
|
||||||
|
mem::size_of::<Color>() as _,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_title_background_color(&self, color: Color) {
|
||||||
|
unsafe {
|
||||||
|
DwmSetWindowAttribute(
|
||||||
|
self.hwnd(),
|
||||||
|
DWMWA_CAPTION_COLOR,
|
||||||
|
&color as *const _ as _,
|
||||||
|
mem::size_of::<Color>() as _,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_title_text_color(&self, color: Color) {
|
||||||
|
unsafe {
|
||||||
|
DwmSetWindowAttribute(
|
||||||
|
self.hwnd(),
|
||||||
|
DWMWA_TEXT_COLOR,
|
||||||
|
&color as *const _ as _,
|
||||||
|
mem::size_of::<Color>() as _,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_corner_preference(&self, preference: CornerPreference) {
|
||||||
|
unsafe {
|
||||||
|
DwmSetWindowAttribute(
|
||||||
|
self.hwnd(),
|
||||||
|
DWMWA_WINDOW_CORNER_PREFERENCE,
|
||||||
|
&(preference as DWM_WINDOW_CORNER_PREFERENCE) as *const _ as _,
|
||||||
|
mem::size_of::<DWM_WINDOW_CORNER_PREFERENCE>() as _,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Window {
|
impl Drop for Window {
|
||||||
@@ -1265,6 +1318,19 @@ impl<'a> InitData<'a> {
|
|||||||
if let Some(position) = attributes.position {
|
if let Some(position) = attributes.position {
|
||||||
win.set_outer_position(position);
|
win.set_outer_position(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(color) = self.attributes.platform_specific.border_color {
|
||||||
|
win.set_border_color(color);
|
||||||
|
}
|
||||||
|
if let Some(color) = self.attributes.platform_specific.title_background_color {
|
||||||
|
win.set_title_background_color(color);
|
||||||
|
}
|
||||||
|
if let Some(color) = self.attributes.platform_specific.title_text_color {
|
||||||
|
win.set_title_text_color(color);
|
||||||
|
}
|
||||||
|
if let Some(corner) = self.attributes.platform_specific.corner_preference {
|
||||||
|
win.set_corner_preference(corner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe fn init(
|
unsafe fn init(
|
||||||
|
|||||||
Reference in New Issue
Block a user