Windows: Add transparency effect (#20400)

Gowtham K and thedeveloper-sharath created

Release Notes:

- Added Transparency effect for Windows #19405 


![image](https://github.com/user-attachments/assets/b0750020-5a89-48c9-b26e-13b30874cf8d)


![image](https://github.com/user-attachments/assets/80609a14-b8c3-4159-b909-1e61f4c3eac3)

---------

Co-authored-by: thedeveloper-sharath <35845141+thedeveloper-sharath@users.noreply.github.com>

Change summary

crates/gpui/src/platform/windows/window.rs | 97 +++++++++++++++++++++++
1 file changed, 94 insertions(+), 3 deletions(-)

Detailed changes

crates/gpui/src/platform/windows/window.rs 🔗

@@ -647,11 +647,47 @@ impl PlatformWindow for WindowsWindow {
     }
 
     fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
-        self.0
-            .state
-            .borrow_mut()
+        let mut window_state = self.0.state.borrow_mut();
+        window_state
             .renderer
             .update_transparency(background_appearance != WindowBackgroundAppearance::Opaque);
+        let mut version = unsafe { std::mem::zeroed() };
+        let status = unsafe { windows::Wdk::System::SystemServices::RtlGetVersion(&mut version) };
+        if status.is_ok() {
+            if background_appearance == WindowBackgroundAppearance::Blurred {
+                if version.dwBuildNumber >= 17763 {
+                    set_window_composition_attribute(window_state.hwnd, Some((0, 0, 0, 10)), 4);
+                }
+            } else {
+                if version.dwBuildNumber >= 17763 {
+                    set_window_composition_attribute(window_state.hwnd, None, 0);
+                }
+            }
+            //Transparent effect might cause some flickering and performance issues due `WS_EX_COMPOSITED` is enabled
+            //if `WS_EX_COMPOSITED` is removed the window instance won't initiate
+            if background_appearance == WindowBackgroundAppearance::Transparent {
+                unsafe {
+                    let current_style = GetWindowLongW(window_state.hwnd, GWL_EXSTYLE);
+                    SetWindowLongW(
+                        window_state.hwnd,
+                        GWL_EXSTYLE,
+                        current_style | WS_EX_LAYERED.0 as i32 | WS_EX_COMPOSITED.0 as i32,
+                    );
+                    SetLayeredWindowAttributes(window_state.hwnd, COLORREF(0), 225, LWA_ALPHA)
+                        .inspect_err(|e| log::error!("Unable to set window to transparent: {e}"))
+                        .ok();
+                };
+            } else {
+                unsafe {
+                    let current_style = GetWindowLongW(window_state.hwnd, GWL_EXSTYLE);
+                    SetWindowLongW(
+                        window_state.hwnd,
+                        GWL_EXSTYLE,
+                        current_style & !WS_EX_LAYERED.0 as i32 & !WS_EX_COMPOSITED.0 as i32,
+                    );
+                }
+            }
+        }
     }
 
     fn minimize(&self) {
@@ -932,6 +968,23 @@ struct StyleAndBounds {
     cy: i32,
 }
 
+#[repr(C)]
+struct WINDOWCOMPOSITIONATTRIBDATA {
+    attrib: u32,
+    pv_data: *mut std::ffi::c_void,
+    cb_data: usize,
+}
+
+#[repr(C)]
+struct AccentPolicy {
+    accent_state: u32,
+    accent_flags: u32,
+    gradient_color: u32,
+    animation_id: u32,
+}
+
+type Color = (u8, u8, u8, u8);
+
 #[derive(Debug, Default, Clone, Copy)]
 pub(crate) struct WindowBorderOffset {
     width_offset: i32,
@@ -1136,6 +1189,44 @@ fn retrieve_window_placement(
     Ok(placement)
 }
 
+fn set_window_composition_attribute(hwnd: HWND, color: Option<Color>, state: u32) {
+    unsafe {
+        type SetWindowCompositionAttributeType =
+            unsafe extern "system" fn(HWND, *mut WINDOWCOMPOSITIONATTRIBDATA) -> BOOL;
+        let module_name = PCSTR::from_raw("user32.dll\0".as_ptr());
+        let user32 = GetModuleHandleA(module_name);
+        if user32.is_ok() {
+            let func_name = PCSTR::from_raw("SetWindowCompositionAttribute\0".as_ptr());
+            let set_window_composition_attribute: SetWindowCompositionAttributeType =
+                std::mem::transmute(GetProcAddress(user32.unwrap(), func_name));
+            let mut color = color.unwrap_or_default();
+            let is_acrylic = state == 4;
+            if is_acrylic && color.3 == 0 {
+                color.3 = 1;
+            }
+            let accent = AccentPolicy {
+                accent_state: state,
+                accent_flags: if is_acrylic { 0 } else { 2 },
+                gradient_color: (color.0 as u32)
+                    | ((color.1 as u32) << 8)
+                    | ((color.2 as u32) << 16)
+                    | (color.3 as u32) << 24,
+                animation_id: 0,
+            };
+            let mut data = WINDOWCOMPOSITIONATTRIBDATA {
+                attrib: 0x13,
+                pv_data: &accent as *const _ as *mut _,
+                cb_data: std::mem::size_of::<AccentPolicy>(),
+            };
+            let _ = set_window_composition_attribute(hwnd, &mut data as *mut _ as _);
+        } else {
+            let _ = user32
+                .inspect_err(|e| log::error!("Error getting module: {e}"))
+                .ok();
+        }
+    }
+}
+
 mod windows_renderer {
     use std::{num::NonZeroIsize, sync::Arc};