diff --git a/Cargo.toml b/Cargo.toml index 4f736360..4bcbac53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,16 +37,18 @@ glutin_core_graphics = "0" glutin_core_foundation = "0" [target.i686-pc-windows-gnu.dependencies] -winapi = "0.1" +winapi = "~0.1.18" gdi32-sys = "0.1" user32-sys = "~0.1.1" kernel32-sys = "0.1" +dwmapi-sys = "0.1" [target.x86_64-pc-windows-gnu.dependencies] -winapi = "0.1" +winapi = "~0.1.18" gdi32-sys = "0.1" user32-sys = "~0.1.1" kernel32-sys = "0.1" +dwmapi-sys = "0.1" [target.i686-unknown-linux-gnu.dependencies] osmesa-sys = "0.0.5" diff --git a/examples/transparent.rs b/examples/transparent.rs new file mode 100644 index 00000000..553c16d4 --- /dev/null +++ b/examples/transparent.rs @@ -0,0 +1,38 @@ +#[cfg(target_os = "android")] +#[macro_use] +extern crate android_glue; + +extern crate glutin; + +mod support; + +#[cfg(target_os = "android")] +android_start!(main); + +#[cfg(not(feature = "window"))] +fn main() { println!("This example requires glutin to be compiled with the `window` feature"); } + +#[cfg(feature = "window")] +fn resize_callback(width: u32, height: u32) { + println!("Window resized to {}x{}", width, height); +} + +#[cfg(feature = "window")] +fn main() { + let mut window = glutin::WindowBuilder::new().with_decorations(false).with_transparency(true) + .build().unwrap(); + window.set_title("A fantastic window!"); + window.set_window_resize_callback(Some(resize_callback as fn(u32, u32))); + unsafe { window.make_current() }; + + println!("Pixel format of the window: {:?}", window.get_pixel_format()); + + let context = support::load(&window); + + while !window.is_closed() { + context.draw_frame((0.0, 0.0, 0.0, 0.0)); + window.swap_buffers(); + + println!("{:?}", window.wait_events().next()); + } +} diff --git a/src/api/win32/callback.rs b/src/api/win32/callback.rs index 1ea95a54..86d5f1c2 100644 --- a/src/api/win32/callback.rs +++ b/src/api/win32/callback.rs @@ -44,6 +44,7 @@ fn send_event(input_window: winapi::HWND, event: Event) { /// This is the callback that is called by `DispatchMessage` in the events loop. /// /// Returning 0 tells the Win32 API that the message has been processed. +// FIXME: detect WM_DWMCOMPOSITIONCHANGED and call DwmEnableBlurBehindWindow if necessary pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, wparam: winapi::WPARAM, lparam: winapi::LPARAM) -> winapi::LRESULT diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs index fb4e1812..f46c3953 100644 --- a/src/api/win32/init.rs +++ b/src/api/win32/init.rs @@ -25,6 +25,7 @@ use std::sync::mpsc::channel; use winapi; use kernel32; +use dwmapi; use user32; use api::wgl; @@ -102,7 +103,7 @@ unsafe fn init(title: Vec, builder: BuilderAttribs<'static>, } // computing the style and extended style of the window - let (ex_style, style) = if builder.monitor.is_some() { + let (ex_style, style) = if builder.monitor.is_some() || builder.decorations == false { (winapi::WS_EX_APPWINDOW, winapi::WS_POPUP | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN) } else { (winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, @@ -214,6 +215,20 @@ unsafe fn init(title: Vec, builder: BuilderAttribs<'static>, } }; + // making the window transparent + if builder.transparent { + let bb = winapi::DWM_BLURBEHIND { + dwFlags: 0x1, // FIXME: DWM_BB_ENABLE; + fEnable: 1, + hRgnBlur: ptr::null_mut(), + fTransitionOnMaximized: 0, + }; + + unsafe { + dwmapi::DwmEnableBlurBehindWindow(real_window.0, &bb); + } + } + // calling SetForegroundWindow if fullscreen if builder.monitor.is_some() { user32::SetForegroundWindow(real_window.0); diff --git a/src/lib.rs b/src/lib.rs index 1169513d..612206ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,8 @@ extern crate kernel32; extern crate gdi32; #[cfg(target_os = "windows")] extern crate user32; +#[cfg(target_os = "windows")] +extern crate dwmapi; #[cfg(target_os = "macos")] #[macro_use] extern crate objc; @@ -295,6 +297,8 @@ pub struct BuilderAttribs<'a> { alpha_bits: Option, stereoscopy: bool, srgb: Option, + transparent: bool, + decorations: bool, } impl BuilderAttribs<'static> { @@ -318,6 +322,8 @@ impl BuilderAttribs<'static> { alpha_bits: None, stereoscopy: false, srgb: None, + transparent: false, + decorations: true, } } } @@ -346,6 +352,8 @@ impl<'a> BuilderAttribs<'a> { alpha_bits: self.alpha_bits, stereoscopy: self.stereoscopy, srgb: self.srgb, + transparent: self.transparent, + decorations: self.decorations, }; (new_attribs, sharing) diff --git a/src/window.rs b/src/window.rs index c21b82dc..578c237d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -137,10 +137,22 @@ impl<'a> WindowBuilder<'a> { self } + /// Sets whether the background of the window should be transparent. + pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder<'a> { + self.attribs.transparent = transparent; + self + } + + /// Sets whether the window should have a border, a title bar, etc. + pub fn with_decorations(mut self, decorations: bool) -> WindowBuilder<'a> { + self.attribs.decorations = decorations; + self + } + /// Builds the window. /// /// Error should be very rare and only occur in case of permission denied, incompatible system, - /// out of memory, etc. + /// out of memory, etc. pub fn build(mut self) -> Result { // resizing the window to the dimensions of the monitor when fullscreen if self.attribs.dimensions.is_none() && self.attribs.monitor.is_some() {