1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Copyright 2020-2022 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

//! Add native shadows to your windows.
//!
//! ## Platform-specific
//!
//! - **Windows**: On Windows 11, the window will also have rounded corners.
//! - **macOS**: Shadows are always disabled for transparent windows.
//! - **Linux**: Unsupported, Shadows are controlled by the compositor installed on the end-user system.
//!
//! # Example
//!
//! ```no_run
//! use window_shadows::set_shadow;
//!
//! # let window: &dyn raw_window_handle::HasRawWindowHandle = unsafe { std::mem::zeroed() };
//! #[cfg(any(windows, target_os = "macos"))]
//! set_shadow(&window, true).unwrap();
//! ```

/// Enables or disables the shadows for a window.
///
/// ## Platform-specific
///
/// - **Windows**: On Windows 11, the window will also have rounded corners.
/// - **macOS**: Shadows are always disabled for transparent windows.
/// - **Linux**: Unsupported, Shadows are controlled by the compositor installed on the end-user system.
pub fn set_shadow(
    window: impl raw_window_handle::HasRawWindowHandle,
    enable: bool,
) -> Result<(), Error> {
    match window.raw_window_handle() {
        #[cfg(target_os = "macos")]
        raw_window_handle::RawWindowHandle::AppKit(handle) => {
            use cocoa::{appkit::NSWindow, base::id};
            use objc::runtime::{NO, YES};

            unsafe {
                (handle.ns_window as id).setHasShadow_(if enable { YES } else { NO });
            }

            Ok(())
        }
        #[cfg(target_os = "windows")]
        raw_window_handle::RawWindowHandle::Win32(handle) => {
            use windows_sys::Win32::{
                Graphics::Dwm::DwmExtendFrameIntoClientArea, UI::Controls::MARGINS,
            };

            let m = if enable { 1 } else { 0 };
            let margins = MARGINS {
                cxLeftWidth: m,
                cxRightWidth: m,
                cyTopHeight: m,
                cyBottomHeight: m,
            };
            unsafe {
                DwmExtendFrameIntoClientArea(handle.hwnd as _, &margins);
            };
            Ok(())
        }
        _ => Err(Error::UnsupportedPlatform),
    }
}

#[derive(Debug)]
pub enum Error {
    UnsupportedPlatform,
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "\"set_shadow()\" is only supported on Windows and macOS")
    }
}