From 2cb28267f93e14014abad62e86b39082a288a720 Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Sat, 2 Jun 2018 00:13:00 +0200 Subject: [PATCH 1/9] Blur: WIP/experimental MacOS implementation --- examples/blur.rs | 49 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ src/os/macos.rs | 7 ++++++ src/platform/macos/view.rs | 29 ++++++++++++++++----- src/platform/macos/window.rs | 11 +++++--- src/window.rs | 9 +++++++ 6 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 examples/blur.rs diff --git a/examples/blur.rs b/examples/blur.rs new file mode 100644 index 0000000000..1cfe8a8399 --- /dev/null +++ b/examples/blur.rs @@ -0,0 +1,49 @@ +extern crate winit; + +use std::{time::{Instant, Duration}, thread::sleep}; + +fn main() { + let mut running = true; + let mut material = 0i64; + let mut events_loop = winit::EventsLoop::new(); + let mut timer = Instant::now(); + let material_duration = Duration::from_secs(2); + + let window = winit::WindowBuilder::new() + .with_title("A blurry window!") + .with_blur(true) + .build(&events_loop) + .unwrap(); + + while running { + events_loop.poll_events(|event| { + match event { + winit::Event::WindowEvent { + event: winit::WindowEvent::CloseRequested, + .. + } => running = false, + winit::Event::WindowEvent { + event: winit::WindowEvent::KeyboardInput { + input: winit::KeyboardInput { + virtual_keycode: Some(winit::VirtualKeyCode::Escape), + .. + }, + .. + }, + .. + } => running = false, + _ => {}, + } + }); + + if timer.elapsed() >= material_duration { + use winit::os::macos::WindowExt; + window.set_blur_material(material); + println!("Set blur material: {}", material); + material = (material + 1) % 10; + timer = Instant::now(); + } + + sleep(Duration::from_millis(16)); + } +} diff --git a/src/lib.rs b/src/lib.rs index b4120d7505..ddbc6abfc7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -466,6 +466,8 @@ pub struct WindowAttributes { /// [iOS only] Enable multitouch, /// see [multipleTouchEnabled](https://developer.apple.com/documentation/uikit/uiview/1622519-multipletouchenabled) pub multitouch: bool, + + pub blur: bool, } impl Default for WindowAttributes { @@ -484,6 +486,7 @@ impl Default for WindowAttributes { always_on_top: false, window_icon: None, multitouch: false, + blur: false, } } } diff --git a/src/os/macos.rs b/src/os/macos.rs index c560336c22..4e8d57cf8f 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -16,6 +16,9 @@ pub trait WindowExt { /// /// The pointer will become invalid when the `Window` is destroyed. fn get_nsview(&self) -> *mut c_void; + + /// Just for testing purposes. + fn set_blur_material(&self, material_id: i64); } impl WindowExt for Window { @@ -28,6 +31,10 @@ impl WindowExt for Window { fn get_nsview(&self) -> *mut c_void { self.window.get_nsview() } + + fn set_blur_material(&self, material_id: i64) { + self.window.set_blur_material(material_id); + } } /// Corresponds to `NSApplicationActivationPolicy`. diff --git a/src/platform/macos/view.rs b/src/platform/macos/view.rs index 8d20778498..6a1745a0dd 100644 --- a/src/platform/macos/view.rs +++ b/src/platform/macos/view.rs @@ -13,7 +13,7 @@ use cocoa::foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger}; use objc::declare::ClassDecl; use objc::runtime::{Class, Object, Protocol, Sel, BOOL}; -use {ElementState, Event, KeyboardInput, WindowEvent, WindowId}; +use {ElementState, Event, KeyboardInput, WindowEvent, WindowId, WindowAttributes}; use platform::platform::events_loop::{DEVICE_ID, event_mods, Shared, to_virtual_key_code}; use platform::platform::util; use platform::platform::ffi::*; @@ -27,7 +27,7 @@ struct ViewState { last_insert: Option, } -pub fn new_view(window: id, shared: Weak) -> IdRef { +pub fn new_view(window: id, shared: Weak, win_attribs: &WindowAttributes) -> IdRef { let state = ViewState { window, shared, @@ -38,8 +38,14 @@ pub fn new_view(window: id, shared: Weak) -> IdRef { unsafe { // This is free'd in `dealloc` let state_ptr = Box::into_raw(Box::new(state)) as *mut c_void; - let view: id = msg_send![VIEW_CLASS.0, alloc]; - IdRef::new(msg_send![view, initWithWinit:state_ptr]) + let view_class = if win_attribs.blur { VISUAL_EFFECT_VIEW_CLASS.0 } else { VIEW_CLASS.0 }; + let view: id = msg_send![view_class, alloc]; + msg_send![view, initWithWinit:state_ptr]; + if win_attribs.blur { + msg_send![view, setMaterial: 2i64]; + msg_send![view, setBlendingMode: 0i64]; + } + IdRef::new(view) } } @@ -65,6 +71,18 @@ unsafe impl Sync for ViewClass {} lazy_static! { static ref VIEW_CLASS: ViewClass = unsafe { let superclass = Class::get("NSView").unwrap(); + let decl = common_view_decl(superclass); + ViewClass(decl.register()) + }; + + static ref VISUAL_EFFECT_VIEW_CLASS: ViewClass = unsafe { + let superclass = Class::get("NSVisualEffectView").unwrap(); + let decl = common_view_decl(superclass); + ViewClass(decl.register()) + }; +} + +unsafe fn common_view_decl(superclass: &'static Class) -> ClassDecl { let mut decl = ClassDecl::new("WinitView", superclass).unwrap(); decl.add_method(sel!(dealloc), dealloc as extern fn(&Object, Sel)); decl.add_method( @@ -116,8 +134,7 @@ lazy_static! { decl.add_ivar::("markedText"); let protocol = Protocol::get("NSTextInputClient").unwrap(); decl.add_protocol(&protocol); - ViewClass(decl.register()) - }; + decl } extern fn dealloc(this: &Object, _sel: Sel) { diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index 0828364e80..3cf5b10fbc 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -553,6 +553,11 @@ impl WindowExt for Window2 { fn get_nsview(&self) -> *mut c_void { *self.view as *mut c_void } + + fn set_blur_material(&self, material_id: i64) { + let view = self.get_nsview() as *mut objc::runtime::Object; + unsafe { msg_send![view, setMaterial: material_id]; } + } } impl Window2 { @@ -585,7 +590,7 @@ impl Window2 { return Err(OsError(format!("Couldn't create NSWindow"))); }, }; - let view = match Window2::create_view(*window, Weak::clone(&shared)) { + let view = match Window2::create_view(*window, Weak::clone(&shared), &win_attribs) { Some(view) => view, None => { let _: () = unsafe { msg_send![autoreleasepool, drain] }; @@ -795,9 +800,9 @@ impl Window2 { } } - fn create_view(window: id, shared: Weak) -> Option { + fn create_view(window: id, shared: Weak, win_attribs: &WindowAttributes) -> Option { unsafe { - let view = new_view(window, shared); + let view = new_view(window, shared, win_attribs); view.non_nil().map(|view| { view.setWantsBestResolutionOpenGLSurface_(YES); window.setContentView_(*view); diff --git a/src/window.rs b/src/window.rs index cae1f239a2..c7c0c43bb1 100644 --- a/src/window.rs +++ b/src/window.rs @@ -82,6 +82,15 @@ impl WindowBuilder { #[inline] pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder { self.window.transparent = transparent; + self.window.blur = !transparent; + self + } + + /// Sets whether the background of the window should be blurred. + #[inline] + pub fn with_blur(mut self, blur: bool) -> WindowBuilder { + self.window.blur = blur; + self.window.transparent = !blur; self } From 03e7eb2a050889c9625eefd06f8c0e55439de359 Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Mon, 11 Jun 2018 19:11:45 +0200 Subject: [PATCH 2/9] MacOS: Basic blur implementation --- examples/blur.rs | 54 ++++++++++++++---------------------- src/os/macos.rs | 31 +++++++++++++++++++-- src/platform/macos/view.rs | 3 +- src/platform/macos/window.rs | 8 +++--- 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/examples/blur.rs b/examples/blur.rs index 1cfe8a8399..58069ace7a 100644 --- a/examples/blur.rs +++ b/examples/blur.rs @@ -1,13 +1,7 @@ extern crate winit; -use std::{time::{Instant, Duration}, thread::sleep}; - fn main() { - let mut running = true; - let mut material = 0i64; let mut events_loop = winit::EventsLoop::new(); - let mut timer = Instant::now(); - let material_duration = Duration::from_secs(2); let window = winit::WindowBuilder::new() .with_title("A blurry window!") @@ -15,35 +9,29 @@ fn main() { .build(&events_loop) .unwrap(); - while running { - events_loop.poll_events(|event| { - match event { - winit::Event::WindowEvent { - event: winit::WindowEvent::CloseRequested, - .. - } => running = false, - winit::Event::WindowEvent { - event: winit::WindowEvent::KeyboardInput { - input: winit::KeyboardInput { - virtual_keycode: Some(winit::VirtualKeyCode::Escape), - .. - }, + #[cfg(target_os = "macos")] + { + use winit::os::macos::{BlurMaterial, WindowExt}; + window.set_blur_material(BlurMaterial::UltraDark); + } + + events_loop.run_forever(|event| { + match event { + winit::Event::WindowEvent { + event: winit::WindowEvent::CloseRequested, + .. + } => winit::ControlFlow::Break, + winit::Event::WindowEvent { + event: winit::WindowEvent::KeyboardInput { + input: winit::KeyboardInput { + virtual_keycode: Some(winit::VirtualKeyCode::Escape), .. }, .. - } => running = false, - _ => {}, - } - }); - - if timer.elapsed() >= material_duration { - use winit::os::macos::WindowExt; - window.set_blur_material(material); - println!("Set blur material: {}", material); - material = (material + 1) % 10; - timer = Instant::now(); + }, + .. + } => winit::ControlFlow::Break, + _ => winit::ControlFlow::Continue, } - - sleep(Duration::from_millis(16)); - } + }); } diff --git a/src/os/macos.rs b/src/os/macos.rs index 4e8d57cf8f..e56fc0ff82 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -18,7 +18,7 @@ pub trait WindowExt { fn get_nsview(&self) -> *mut c_void; /// Just for testing purposes. - fn set_blur_material(&self, material_id: i64); + fn set_blur_material(&self, material: BlurMaterial); } impl WindowExt for Window { @@ -32,8 +32,9 @@ impl WindowExt for Window { self.window.get_nsview() } - fn set_blur_material(&self, material_id: i64) { - self.window.set_blur_material(material_id); + #[inline] + fn set_blur_material(&self, material: BlurMaterial) { + self.window.set_blur_material(material); } } @@ -164,3 +165,27 @@ impl MonitorIdExt for MonitorId { self.inner.get_nsscreen().map(|s| s as *mut c_void) } } + +#[repr(i64)] +// Applies to MacOS Mojave. +pub enum BlurMaterial { + AppearanceBased = 0, // Deperecated + Light = 1, // Deperecated + Dark = 2, // Deprecated + Titlebar = 3, + Selection = 4, + Menu = 5, + Popover = 6, + Sidebar = 7, + MediumLight = 8, // Deprecated + UltraDark = 9, // Deprecated + HeaderView = 10, + Sheet = 11, + WindowBackground = 12, + HudWindow = 13, + FullScreenUi = 15, + ToolTip = 17, + ContentBackground = 18, + UnderWindowBackground = 21, + UnderPageBackground = 22, +} \ No newline at end of file diff --git a/src/platform/macos/view.rs b/src/platform/macos/view.rs index 6a1745a0dd..4ee3d3ca73 100644 --- a/src/platform/macos/view.rs +++ b/src/platform/macos/view.rs @@ -18,6 +18,7 @@ use platform::platform::events_loop::{DEVICE_ID, event_mods, Shared, to_virtual_ use platform::platform::util; use platform::platform::ffi::*; use platform::platform::window::{get_window_id, IdRef}; +use os::macos::BlurMaterial; struct ViewState { window: id, @@ -42,7 +43,7 @@ pub fn new_view(window: id, shared: Weak, win_attribs: &WindowAttributes let view: id = msg_send![view_class, alloc]; msg_send![view, initWithWinit:state_ptr]; if win_attribs.blur { - msg_send![view, setMaterial: 2i64]; + msg_send![view, setMaterial: BlurMaterial::Light as i64]; msg_send![view, setBlendingMode: 0i64]; } IdRef::new(view) diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index 3cf5b10fbc..936ac7c030 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -3,8 +3,7 @@ use CreationError::OsError; use libc; use WindowAttributes; -use os::macos::ActivationPolicy; -use os::macos::WindowExt; +use os::macos::{ActivationPolicy, WindowExt, BlurMaterial}; use objc; use objc::runtime::{Class, Object, Sel, BOOL, YES, NO}; @@ -554,9 +553,10 @@ impl WindowExt for Window2 { *self.view as *mut c_void } - fn set_blur_material(&self, material_id: i64) { + #[inline] + fn set_blur_material(&self, material: BlurMaterial) { let view = self.get_nsview() as *mut objc::runtime::Object; - unsafe { msg_send![view, setMaterial: material_id]; } + unsafe { msg_send![view, setMaterial: material as i64]; } } } From a0e9484e1d3994a550e70738903cd6fb36429fc8 Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Mon, 11 Jun 2018 19:29:39 +0200 Subject: [PATCH 3/9] Add macOS related comment to blur example --- examples/blur.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/blur.rs b/examples/blur.rs index 58069ace7a..13405a62a0 100644 --- a/examples/blur.rs +++ b/examples/blur.rs @@ -11,8 +11,10 @@ fn main() { #[cfg(target_os = "macos")] { + // On macOS the blur material is 'light' by default. + // Let's change it to a dark theme! use winit::os::macos::{BlurMaterial, WindowExt}; - window.set_blur_material(BlurMaterial::UltraDark); + window.set_blur_material(BlurMaterial::Dark); } events_loop.run_forever(|event| { From e7686aa92cd6ac35f46fffeca038746b19f79f0c Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Fri, 15 Jun 2018 20:37:45 +0200 Subject: [PATCH 4/9] Comment blur member --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index dc8e5a7e12..98ac5cdc79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -472,6 +472,9 @@ pub struct WindowAttributes { /// see [multipleTouchEnabled](https://developer.apple.com/documentation/uikit/uiview/1622519-multipletouchenabled) pub multitouch: bool, + /// Whether the window should be blurry. This is similar to transparency. + /// + /// The default is `false`. pub blur: bool, } From 916eec22aa75795740ccab8d7569ff36e96017ec Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Sun, 17 Jun 2018 16:08:49 +0200 Subject: [PATCH 5/9] Several changes based on code review - Improve documentation for BlurMaterial, methods and members. - Reorganize imports - Annotate return type of msg_send! usages - Rebind view to the return value of init, as is idiomatic in Objective-C - Mark set_blur_material as unsafe - Change some code styling for consistency --- examples/blur.rs | 2 +- src/lib.rs | 9 +++++-- src/os/macos.rs | 48 +++++++++++++++++++++++++++++------- src/platform/macos/view.rs | 10 ++++---- src/platform/macos/window.rs | 8 +++--- src/window.rs | 3 ++- 6 files changed, 57 insertions(+), 23 deletions(-) diff --git a/examples/blur.rs b/examples/blur.rs index 13405a62a0..b6dadccc60 100644 --- a/examples/blur.rs +++ b/examples/blur.rs @@ -14,7 +14,7 @@ fn main() { // On macOS the blur material is 'light' by default. // Let's change it to a dark theme! use winit::os::macos::{BlurMaterial, WindowExt}; - window.set_blur_material(BlurMaterial::Dark); + unsafe { window.set_blur_material(BlurMaterial::Dark) }; } events_loop.run_forever(|event| { diff --git a/src/lib.rs b/src/lib.rs index b23d8444a0..be7c1213f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -483,8 +483,13 @@ pub struct WindowAttributes { /// see [multipleTouchEnabled](https://developer.apple.com/documentation/uikit/uiview/1622519-multipletouchenabled) pub multitouch: bool, - /// Whether the window should be blurry. This is similar to transparency. - /// + /// Whether the window should have a blur effect. + /// + /// Blur is similar to transparency in that both allow you to "look though" the window, + /// except that with blur the seethrough content has an effect applied that gives it a + /// milky or smeared look. + /// The exact look can be controlled per platform via traits like `WindowExt`. + /// /// The default is `false`. pub blur: bool, } diff --git a/src/os/macos.rs b/src/os/macos.rs index 749fcf8272..0460b3bd03 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -17,8 +17,12 @@ pub trait WindowExt { /// The pointer will become invalid when the `Window` is destroyed. fn get_nsview(&self) -> *mut c_void; - /// Just for testing purposes. - fn set_blur_material(&self, material: BlurMaterial); + /// For windows created with the [blurred](WindowBuilder::with_blur) option, + /// this controls the appearance of the blur effect. + /// + /// Marked as unsafe because depending on the version of macOS and the `BlurMaterial` variant passed, + /// this might cause a crash. + unsafe fn set_blur_material(&self, material: BlurMaterial); } impl WindowExt for Window { @@ -33,7 +37,7 @@ impl WindowExt for Window { } #[inline] - fn set_blur_material(&self, material: BlurMaterial) { + unsafe fn set_blur_material(&self, material: BlurMaterial) { self.window.set_blur_material(material); } } @@ -166,26 +170,52 @@ impl MonitorIdExt for MonitorId { } } +/// Enumeration of all possible blur materials for macOS. Applies to macOS SDK 10.10+. +/// +/// Not all versions of macOS support all the variants listed here. +/// Check [Apple's documentation](https://developer.apple.com/documentation/appkit/nsvisualeffectview/material) +/// to find out what your target version supports. +/// The behaviour for using a material which is not supported depends how it is implemented in cocoa, +/// but will most likely cause a crash. #[repr(i64)] -// Applies to MacOS Mojave. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum BlurMaterial { - AppearanceBased = 0, // Deperecated - Light = 1, // Deperecated - Dark = 2, // Deprecated + /// A default material for the view’s effective appearance. + AppearanceBased = 0, + /// A material with a light effect. + Light = 1, + /// A material with a dark effect. + Dark = 2, + /// The material for a window’s titlebar. Titlebar = 3, + /// The material used to indicate a selection. Selection = 4, + /// The material for menus. Menu = 5, + /// The material for the background of popover windows. Popover = 6, + /// The material for the background of window sidebars. Sidebar = 7, - MediumLight = 8, // Deprecated - UltraDark = 9, // Deprecated + /// A material with a medium-light effect. + MediumLight = 8, + /// A material with an ultra-dark effect. + UltraDark = 9, + /// The material for in-line header or footer views. HeaderView = 10, + /// The material for the background of sheet windows. Sheet = 11, + /// The material for the background of opaque windows. WindowBackground = 12, + /// The material for the background of heads-up display (HUD) windows. HudWindow = 13, + /// The material for the background of a full-screen modal interface. FullScreenUi = 15, + /// The material for the background of a tool tip. ToolTip = 17, + /// The material for the background of opaque content. ContentBackground = 18, + /// The material for under a window's background. UnderWindowBackground = 21, + /// The material for the area behind the pages of a document. UnderPageBackground = 22, } \ No newline at end of file diff --git a/src/platform/macos/view.rs b/src/platform/macos/view.rs index a0d0292954..82be876dd4 100644 --- a/src/platform/macos/view.rs +++ b/src/platform/macos/view.rs @@ -13,12 +13,12 @@ use cocoa::foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger}; use objc::declare::ClassDecl; use objc::runtime::{Class, Object, Protocol, Sel, BOOL}; -use {ElementState, Event, KeyboardInput, MouseButton, WindowEvent, WindowId, WindowAttributes}; +use os::macos::BlurMaterial; +use {ElementState, Event, KeyboardInput, MouseButton, WindowAttributes, WindowEvent, WindowId}; use platform::platform::events_loop::{DEVICE_ID, event_mods, Shared, to_virtual_key_code}; use platform::platform::util; use platform::platform::ffi::*; use platform::platform::window::{get_window_id, IdRef}; -use os::macos::BlurMaterial; struct ViewState { window: id, @@ -41,10 +41,10 @@ pub fn new_view(window: id, shared: Weak, win_attribs: &WindowAttributes let state_ptr = Box::into_raw(Box::new(state)) as *mut c_void; let view_class = if win_attribs.blur { VISUAL_EFFECT_VIEW_CLASS.0 } else { VIEW_CLASS.0 }; let view: id = msg_send![view_class, alloc]; - msg_send![view, initWithWinit:state_ptr]; + let view: id = msg_send![view, initWithWinit:state_ptr]; if win_attribs.blur { - msg_send![view, setMaterial: BlurMaterial::Light as i64]; - msg_send![view, setBlendingMode: 0i64]; + let _: () = msg_send![view, setMaterial:BlurMaterial::Light as i64]; + let _: () = msg_send![view, setBlendingMode:0i64]; } IdRef::new(view) } diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index 03e460c41a..fd445b7528 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -3,7 +3,6 @@ use std::ops::Deref; use std::os::raw::c_void; use std::sync::Weak; use std::cell::{Cell, RefCell}; -use os::macos::BlurMaterial; use cocoa; use cocoa::appkit::{ @@ -38,7 +37,7 @@ use { WindowId, }; use CreationError::OsError; -use os::macos::{ActivationPolicy, WindowExt}; +use os::macos::{ActivationPolicy, BlurMaterial, WindowExt}; use platform::platform::{ffi, util}; use platform::platform::events_loop::{EventsLoop, Shared}; use platform::platform::view::{new_view, set_ime_spot}; @@ -585,9 +584,8 @@ impl WindowExt for Window2 { } #[inline] - fn set_blur_material(&self, material: BlurMaterial) { - let view = self.get_nsview() as *mut objc::runtime::Object; - unsafe { msg_send![view, setMaterial: material as i64]; } + unsafe fn set_blur_material(&self, material: BlurMaterial) { + let _: () = msg_send![*self.view, setMaterial:material as i64]; } } diff --git a/src/window.rs b/src/window.rs index b6c0092fbb..a3beee15c0 100644 --- a/src/window.rs +++ b/src/window.rs @@ -100,7 +100,8 @@ impl WindowBuilder { self } - /// Sets whether the background of the window should be blurred. + /// Sets whether the background of the window should be blurred. + /// See the blur member on [WindowAttributes](::WindowAttributes) for more info. #[inline] pub fn with_blur(mut self, blur: bool) -> WindowBuilder { self.window.blur = blur; From 79d1f944f80e08ef04801449ba5131046e33d91b Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Sun, 17 Jun 2018 16:27:21 +0200 Subject: [PATCH 6/9] Fix buggy mutual exclusion between trans. and blur --- src/window.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/window.rs b/src/window.rs index a3beee15c0..2e8fbcc55e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -96,7 +96,9 @@ impl WindowBuilder { #[inline] pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder { self.window.transparent = transparent; - self.window.blur = !transparent; + if transparent { + self.window.blur = false; + } self } @@ -105,7 +107,9 @@ impl WindowBuilder { #[inline] pub fn with_blur(mut self, blur: bool) -> WindowBuilder { self.window.blur = blur; - self.window.transparent = !blur; + if blur { + self.window.transparent = false; + } self } From ea119fffec930b96202eed018e2afe77e3f55e48 Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Mon, 18 Jun 2018 23:45:07 +0200 Subject: [PATCH 7/9] WIP (broken) Windows blur implementation --- .gitignore | 1 + Cargo.toml | 3 + examples/blur.rs | 32 ++-- src/lib.rs | 46 ++++-- src/platform/windows/blur.rs | 194 ++++++++++++++++++++++++ src/platform/windows/mod.rs | 1 + src/platform/windows/window.rs | 265 ++++++++++++++++++--------------- 7 files changed, 390 insertions(+), 152 deletions(-) create mode 100644 src/platform/windows/blur.rs diff --git a/.gitignore b/.gitignore index 9fdb6f0115..bf5cea56b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ Cargo.lock target/ rls/ +.vscode/ *~ #*# diff --git a/Cargo.toml b/Cargo.toml index d7257077e0..15fe3a24f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,9 @@ cocoa = "0.15" core-foundation = "0.6" core-graphics = "0.14" +[target.'cfg(target_os = "windows")'.dependencies] +libloading = "0.5.0" + [target.'cfg(target_os = "windows")'.dependencies.winapi] version = "0.3.5" features = [ diff --git a/examples/blur.rs b/examples/blur.rs index b6dadccc60..4628ee8cdc 100644 --- a/examples/blur.rs +++ b/examples/blur.rs @@ -17,23 +17,23 @@ fn main() { unsafe { window.set_blur_material(BlurMaterial::Dark) }; } - events_loop.run_forever(|event| { - match event { - winit::Event::WindowEvent { - event: winit::WindowEvent::CloseRequested, - .. - } => winit::ControlFlow::Break, - winit::Event::WindowEvent { - event: winit::WindowEvent::KeyboardInput { - input: winit::KeyboardInput { - virtual_keycode: Some(winit::VirtualKeyCode::Escape), - .. - }, + events_loop.run_forever(|event| match event { + winit::Event::WindowEvent { + event: winit::WindowEvent::CloseRequested, + .. + } => winit::ControlFlow::Break, + winit::Event::WindowEvent { + event: + winit::WindowEvent::KeyboardInput { + input: + winit::KeyboardInput { + virtual_keycode: Some(winit::VirtualKeyCode::Escape), + .. + }, .. }, - .. - } => winit::ControlFlow::Break, - _ => winit::ControlFlow::Continue, - } + .. + } => winit::ControlFlow::Break, + _ => winit::ControlFlow::Continue, }); } diff --git a/src/lib.rs b/src/lib.rs index be7c1213f6..c4dca9d47e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,10 +87,12 @@ #[allow(unused_imports)] #[macro_use] extern crate lazy_static; -extern crate libc; #[cfg(feature = "icon_loading")] extern crate image; +extern crate libc; +#[cfg(target_os = "windows")] +extern crate libloading; #[cfg(target_os = "windows")] extern crate winapi; #[cfg(any(target_os = "macos", target_os = "ios"))] @@ -102,19 +104,27 @@ extern crate cocoa; extern crate core_foundation; #[cfg(target_os = "macos")] extern crate core_graphics; -#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] -extern crate x11_dl; -#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] +#[cfg( + any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd") +)] extern crate parking_lot; -#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] +#[cfg( + any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd") +)] extern crate percent_encoding; -#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))] +#[cfg( + any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd") +)] extern crate smithay_client_toolkit as sctk; +#[cfg( + any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd") +)] +extern crate x11_dl; pub(crate) use dpi::*; // TODO: Actually change the imports throughout the codebase. pub use events::*; -pub use window::{AvailableMonitorsIter, MonitorId}; pub use icon::*; +pub use window::{AvailableMonitorsIter, MonitorId}; pub mod dpi; mod events; @@ -179,7 +189,7 @@ pub struct DeviceId(platform::DeviceId); /// `EventsLoopProxy` allows you to wakeup an `EventsLoop` from an other thread. pub struct EventsLoop { events_loop: platform::EventsLoop, - _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync + _marker: ::std::marker::PhantomData<*mut ()>, // Not Send nor Sync } /// Returned by the user callback given to the `EventsLoop::run_forever` method. @@ -213,20 +223,25 @@ impl EventsLoop { #[inline] pub fn get_available_monitors(&self) -> AvailableMonitorsIter { let data = self.events_loop.get_available_monitors(); - AvailableMonitorsIter{ data: data.into_iter() } + AvailableMonitorsIter { + data: data.into_iter(), + } } /// Returns the primary monitor of the system. #[inline] pub fn get_primary_monitor(&self) -> MonitorId { - MonitorId { inner: self.events_loop.get_primary_monitor() } + MonitorId { + inner: self.events_loop.get_primary_monitor(), + } } /// Fetches all the events that are pending, calls the callback function for each of them, /// and returns. #[inline] pub fn poll_events(&mut self, callback: F) - where F: FnMut(Event) + where + F: FnMut(Event), { self.events_loop.poll_events(callback) } @@ -241,7 +256,8 @@ impl EventsLoop { /// at a sufficient rate. Rendering in the callback with vsync enabled **will** cause significant lag. #[inline] pub fn run_forever(&mut self, callback: F) - where F: FnMut(Event) -> ControlFlow + where + F: FnMut(Event) -> ControlFlow, { self.events_loop.run_forever(callback) } @@ -484,12 +500,12 @@ pub struct WindowAttributes { pub multitouch: bool, /// Whether the window should have a blur effect. - /// + /// /// Blur is similar to transparency in that both allow you to "look though" the window, /// except that with blur the seethrough content has an effect applied that gives it a - /// milky or smeared look. + /// milky or smeared look. /// The exact look can be controlled per platform via traits like `WindowExt`. - /// + /// /// The default is `false`. pub blur: bool, } diff --git a/src/platform/windows/blur.rs b/src/platform/windows/blur.rs new file mode 100644 index 0000000000..3487e27869 --- /dev/null +++ b/src/platform/windows/blur.rs @@ -0,0 +1,194 @@ +//! This module contains the multiple implementations for controlling +//! both transparency and blur for windows. +//! +//! On `Windows` there are, depending on the version of the OS, different +//! APIs to use for enabling transparency and blur. +//! This modules abstracts over these different APIs and provides a single, +//! simple interface to use the correct API automatically. + +use std::os::raw; +use std::ptr; + +use libloading; +use winapi::shared::minwindef::ULONG; +use winapi::shared::windef::HWND; +use winapi::um::{dwmapi, errhandlingapi, winuser}; + +use platform::platform::window::WindowWrapper; + +lazy_static! { + static ref USER32_DLL: Option = + { libloading::Library::new("user32.dll").ok() }; + static ref POINTERS: Option = { + Some(AcrylicBlurPointers { + swca: unsafe { + USER32_DLL + .as_ref()? + .get(b"SetWindowCompositionAttribute") + .ok()? + }, + }) + }; +} + +static DWM: Dwm = Dwm; +static ACRYLIC_BLUR: AcrylicBlur = AcrylicBlur; + +pub fn implementation() -> &'static Implementation { + // unsafe { + // let ver = sysinfoapi::GetVersion(); + // let (major, minor) = (ver & 0xFF, (ver & 0xFF00) >> 8); + // println!("Major: {}, minor: {}", major, minor); + // } + + if let Some(_) = *POINTERS { + &ACRYLIC_BLUR + } else { + &DWM + } +} + +pub trait Implementation { + fn set_opaque(&self, window: &mut WindowWrapper); + fn set_transparent(&self, window: &mut WindowWrapper); + fn set_blur(&self, window: &mut WindowWrapper); +} + +struct Dwm; + +impl Implementation for Dwm { + fn set_opaque(&self, window: &mut WindowWrapper) { + let bb = dwmapi::DWM_BLURBEHIND { + dwFlags: 0x1, // FIXME: DWM_BB_ENABLE; + fEnable: 0, + hRgnBlur: ptr::null_mut(), + fTransitionOnMaximized: 0, + }; + unsafe { + dwmapi::DwmEnableBlurBehindWindow(window.0, &bb); + } + } + + fn set_transparent(&self, window: &mut WindowWrapper) { + self.set_blur(window); // TODO: Can you even do actual transparency with DWM? + } + + fn set_blur(&self, window: &mut WindowWrapper) { + let bb = dwmapi::DWM_BLURBEHIND { + dwFlags: 0x1, // FIXME: DWM_BB_ENABLE; + fEnable: 1, + hRgnBlur: ptr::null_mut(), + fTransitionOnMaximized: 0, + }; + unsafe { + dwmapi::DwmEnableBlurBehindWindow(window.0, &bb); + } + } +} + +struct AcrylicBlur; + +struct AcrylicBlurPointers { + swca: libloading::Symbol< + 'static, + unsafe extern "system" fn(hwnd: HWND, attribute: *const WindowCompositionAttributeData) + -> raw::c_int, + >, +} + +impl AcrylicBlurPointers { + fn set_window_composite_attribute( + &self, + window: &mut WindowWrapper, + attribute: &WindowCompositionAttributeData, + ) -> raw::c_int { + unsafe { (self.swca)(window.0, attribute as *const _) } + } +} + +#[repr(u32)] +enum AccentState { + Disable = 0, + // EnableGradient = 1, + // EnableTransparentGradient = 2, + EnableBlurBehind = 3, + // EnableAcrylicBlurBehind = 4, + // InvalidState = 5, +} + +#[repr(C)] +struct AccentPolicy { + state: AccentState, + flags: raw::c_int, + gradient_color: raw::c_uint, + animation_id: raw::c_int, +} + +#[repr(u32)] +enum WindowCompositionAttribute { + AccentPolicy = 19, +} + +#[repr(C)] +struct WindowCompositionAttributeData { + attribute: WindowCompositionAttribute, + policy: *const AccentPolicy, + size: ULONG, +} + +impl AcrylicBlur {} + +impl Implementation for AcrylicBlur { + fn set_opaque(&self, window: &mut WindowWrapper) { + POINTERS.as_ref().unwrap().set_window_composite_attribute( + window, + &WindowCompositionAttributeData { + attribute: WindowCompositionAttribute::AccentPolicy, + policy: &AccentPolicy { + state: AccentState::Disable, + flags: 0, + gradient_color: 0x00000000, + animation_id: 0, + } as *const _, + size: ::std::mem::size_of::() as _, + }, + ); + } + + fn set_transparent(&self, window: &mut WindowWrapper) { + self.set_blur(window); // Also, apparently no 'true' transparency support based on WCA. + } + + fn set_blur(&self, window: &mut WindowWrapper) { + POINTERS.as_ref().unwrap().set_window_composite_attribute( + window, + &WindowCompositionAttributeData { + attribute: WindowCompositionAttribute::AccentPolicy, + policy: &AccentPolicy { + // TODO: Decide between EnableBlurBehind and EnableAcrylicBlurBehind (since build 17063) + // based on the Windows version. + // When choosing EnableAcrylicBlurBehind, set gradient_color + // to something non-zero (apparently mandatory). + state: AccentState::EnableBlurBehind, + flags: 0, + gradient_color: 0x00000000, + animation_id: 0, + } as *const _, + size: ::std::mem::size_of::() as _, + }, + ); + + unsafe { + let res = winuser::RedrawWindow( + window.0, + ptr::null(), + ptr::null_mut(), + winuser::RDW_INVALIDATE | winuser::RDW_UPDATENOW, + ); + println!("res {}, err {}", res, errhandlingapi::GetLastError()); + + let res = winuser::SendMessageW(window.0, winuser::WM_ERASEBKGND, 0, 0); + println!("res {}, err {}", res, errhandlingapi::GetLastError()); + } + } +} diff --git a/src/platform/windows/mod.rs b/src/platform/windows/mod.rs index 69c96d68f8..d3259aba3b 100644 --- a/src/platform/windows/mod.rs +++ b/src/platform/windows/mod.rs @@ -47,6 +47,7 @@ pub struct WindowId(HWND); unsafe impl Send for WindowId {} unsafe impl Sync for WindowId {} +mod blur; mod dpi; mod event; mod events_loop; diff --git a/src/platform/windows/window.rs b/src/platform/windows/window.rs index 516ec93322..aaacbfdf9a 100644 --- a/src/platform/windows/window.rs +++ b/src/platform/windows/window.rs @@ -2,36 +2,31 @@ use std::cell::{Cell, RefCell}; use std::ffi::OsStr; -use std::{io, mem, ptr}; use std::os::windows::ffi::OsStrExt; -use std::sync::{Arc, Mutex}; use std::sync::mpsc::channel; +use std::sync::{Arc, Mutex}; +use std::{io, mem, ptr}; use winapi::ctypes::c_int; use winapi::shared::minwindef::{BOOL, DWORD, FALSE, LPARAM, TRUE, UINT, WORD, WPARAM}; use winapi::shared::windef::{HDC, HWND, LPPOINT, POINT, RECT}; -use winapi::um::{combaseapi, dwmapi, libloaderapi, winuser}; -use winapi::um::objbase::{COINIT_MULTITHREADED}; +use winapi::um::objbase::COINIT_MULTITHREADED; use winapi::um::shobjidl_core::{CLSID_TaskbarList, ITaskbarList2}; use winapi::um::winnt::{LONG, LPCWSTR}; +use winapi::um::{combaseapi, dwmapi, libloaderapi, winuser}; -use { - CreationError, - CursorState, - Icon, - LogicalPosition, - LogicalSize, - MonitorId as RootMonitorId, - MouseCursor, - PhysicalSize, - WindowAttributes, +use platform::platform::dpi::{ + dpi_to_scale_factor, get_window_dpi, get_window_scale_factor, BASE_DPI, }; -use platform::platform::{Cursor, EventsLoop, PlatformSpecificWindowBuilderAttributes, WindowId}; -use platform::platform::dpi::{BASE_DPI, dpi_to_scale_factor, get_window_dpi, get_window_scale_factor}; use platform::platform::events_loop::{self, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID}; use platform::platform::icon::{self, IconType, WinIcon}; use platform::platform::raw_input::register_all_mice_and_keyboards_for_raw_input; use platform::platform::util; +use platform::platform::{Cursor, EventsLoop, PlatformSpecificWindowBuilderAttributes, WindowId}; +use { + CreationError, CursorState, Icon, LogicalPosition, LogicalSize, MonitorId as RootMonitorId, + MouseCursor, PhysicalSize, WindowAttributes, +}; /// The Win32 implementation of the main `Window` object. pub struct Window { @@ -121,17 +116,15 @@ impl Window { } pub(crate) fn get_position_physical(&self) -> Option<(i32, i32)> { - util::get_window_rect(self.window.0) - .map(|rect| (rect.left as i32, rect.top as i32)) + util::get_window_rect(self.window.0).map(|rect| (rect.left as i32, rect.top as i32)) } #[inline] pub fn get_position(&self) -> Option { - self.get_position_physical() - .map(|physical_position| { - let dpi_factor = self.get_hidpi_factor(); - LogicalPosition::from_physical(physical_position, dpi_factor) - }) + self.get_position_physical().map(|physical_position| { + let dpi_factor = self.get_hidpi_factor(); + LogicalPosition::from_physical(physical_position, dpi_factor) + }) } pub(crate) fn get_inner_position_physical(&self) -> Option<(i32, i32)> { @@ -144,11 +137,10 @@ impl Window { #[inline] pub fn get_inner_position(&self) -> Option { - self.get_inner_position_physical() - .map(|physical_position| { - let dpi_factor = self.get_hidpi_factor(); - LogicalPosition::from_physical(physical_position, dpi_factor) - }) + self.get_inner_position_physical().map(|physical_position| { + let dpi_factor = self.get_hidpi_factor(); + LogicalPosition::from_physical(physical_position, dpi_factor) + }) } pub(crate) fn set_position_physical(&self, x: i32, y: i32) { @@ -186,28 +178,27 @@ impl Window { #[inline] pub fn get_inner_size(&self) -> Option { - self.get_inner_size_physical() - .map(|physical_size| { - let dpi_factor = self.get_hidpi_factor(); - LogicalSize::from_physical(physical_size, dpi_factor) - }) + self.get_inner_size_physical().map(|physical_size| { + let dpi_factor = self.get_hidpi_factor(); + LogicalSize::from_physical(physical_size, dpi_factor) + }) } pub(crate) fn get_outer_size_physical(&self) -> Option<(u32, u32)> { - util::get_window_rect(self.window.0) - .map(|rect| ( + util::get_window_rect(self.window.0).map(|rect| { + ( (rect.right - rect.left) as u32, (rect.bottom - rect.top) as u32, - )) + ) + }) } #[inline] pub fn get_outer_size(&self) -> Option { - self.get_outer_size_physical() - .map(|physical_size| { - let dpi_factor = self.get_hidpi_factor(); - LogicalSize::from_physical(physical_size, dpi_factor) - }) + self.get_outer_size_physical().map(|physical_size| { + let dpi_factor = self.get_hidpi_factor(); + LogicalSize::from_physical(physical_size, dpi_factor) + }) } pub(crate) fn set_inner_size_physical(&self, x: u32, y: u32) { @@ -232,9 +223,9 @@ impl Window { outer_x, outer_y, winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOZORDER - | winuser::SWP_NOREPOSITION - | winuser::SWP_NOMOVE, + | winuser::SWP_NOZORDER + | winuser::SWP_NOREPOSITION + | winuser::SWP_NOMOVE, ); winuser::UpdateWindow(self.window.0); } @@ -290,9 +281,7 @@ impl Window { return; } - let mut style = unsafe { - winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE) - }; + let mut style = unsafe { winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE) }; if resizable { style |= winuser::WS_SIZEBOX as LONG; } else { @@ -300,11 +289,7 @@ impl Window { } unsafe { - winuser::SetWindowLongW( - self.window.0, - winuser::GWL_STYLE, - style as _, - ); + winuser::SetWindowLongW(self.window.0, winuser::GWL_STYLE, style as _); }; self.resizable.replace(resizable); } @@ -323,16 +308,24 @@ impl Window { MouseCursor::Crosshair => winuser::IDC_CROSS, MouseCursor::Text | MouseCursor::VerticalText => winuser::IDC_IBEAM, MouseCursor::NotAllowed | MouseCursor::NoDrop => winuser::IDC_NO, - MouseCursor::Grab | MouseCursor::Grabbing | - MouseCursor::Move | MouseCursor::AllScroll => winuser::IDC_SIZEALL, - MouseCursor::EResize | MouseCursor::WResize | - MouseCursor::EwResize | MouseCursor::ColResize => winuser::IDC_SIZEWE, - MouseCursor::NResize | MouseCursor::SResize | - MouseCursor::NsResize | MouseCursor::RowResize => winuser::IDC_SIZENS, - MouseCursor::NeResize | MouseCursor::SwResize | - MouseCursor::NeswResize => winuser::IDC_SIZENESW, - MouseCursor::NwResize | MouseCursor::SeResize | - MouseCursor::NwseResize => winuser::IDC_SIZENWSE, + MouseCursor::Grab + | MouseCursor::Grabbing + | MouseCursor::Move + | MouseCursor::AllScroll => winuser::IDC_SIZEALL, + MouseCursor::EResize + | MouseCursor::WResize + | MouseCursor::EwResize + | MouseCursor::ColResize => winuser::IDC_SIZEWE, + MouseCursor::NResize + | MouseCursor::SResize + | MouseCursor::NsResize + | MouseCursor::RowResize => winuser::IDC_SIZENS, + MouseCursor::NeResize | MouseCursor::SwResize | MouseCursor::NeswResize => { + winuser::IDC_SIZENESW + } + MouseCursor::NwResize | MouseCursor::SeResize | MouseCursor::NwseResize => { + winuser::IDC_SIZENWSE + } MouseCursor::Wait => winuser::IDC_WAIT, MouseCursor::Progress => winuser::IDC_APPSTARTING, MouseCursor::Help => winuser::IDC_HELP, @@ -354,7 +347,8 @@ impl Window { if winuser::ClientToScreen(self.window.0, &mut client_rect.left as *mut _ as LPPOINT) == 0 { return Err("`ClientToScreen` (left, top) failed".to_owned()); } - if winuser::ClientToScreen(self.window.0, &mut client_rect.right as *mut _ as LPPOINT) == 0 { + if winuser::ClientToScreen(self.window.0, &mut client_rect.right as *mut _ as LPPOINT) == 0 + { return Err("`ClientToScreen` (right, bottom) failed".to_owned()); } if winuser::GetClipCursor(&mut clip_rect) == 0 { @@ -387,8 +381,7 @@ impl Window { winuser::ShowCursor(TRUE); }, - (CursorState::Normal, CursorState::Grab) - | (CursorState::Hide, CursorState::Grab) => unsafe { + (CursorState::Normal, CursorState::Grab) | (CursorState::Hide, CursorState::Grab) => unsafe { let mut rect = mem::uninitialized(); if winuser::GetClientRect(window.0, &mut rect) == 0 { return Err("`GetClientRect` failed".to_owned()); @@ -431,10 +424,9 @@ impl Window { CursorState::Grab if !is_grabbed => CursorState::Normal, current_state => current_state, }; - let result = Self::change_cursor_state(&window, current_state, state) - .map(|_| { - window_state_lock.cursor_state = state; - }); + let result = Self::change_cursor_state(&window, current_state, state).map(|_| { + window_state_lock.cursor_state = state; + }); let _ = tx.send(result); }); rx.recv().unwrap() @@ -474,7 +466,9 @@ impl Window { pub fn set_maximized(&self, maximized: bool) { self.maximized.replace(maximized); // We only maximize if we're not in fullscreen. - if self.fullscreen.borrow().is_some() { return; } + if self.fullscreen.borrow().is_some() { + return; + } let window = self.window.clone(); unsafe { @@ -511,7 +505,8 @@ impl Window { let mut placement: winuser::WINDOWPLACEMENT = mem::zeroed(); placement.length = mem::size_of::() as u32; winuser::GetWindowPlacement(self.window.0, &mut placement); - self.maximized.replace(placement.showCmd == (winuser::SW_SHOWMAXIMIZED as u32)); + self.maximized + .replace(placement.showCmd == (winuser::SW_SHOWMAXIMIZED as u32)); let saved_window_info = window_state.saved_window_info.as_ref().unwrap(); (saved_window_info.style, saved_window_info.ex_style) @@ -561,9 +556,9 @@ impl Window { rect.right - rect.left, rect.bottom - rect.top, winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOZORDER - | winuser::SWP_NOACTIVATE - | winuser::SWP_FRAMECHANGED, + | winuser::SWP_NOZORDER + | winuser::SWP_NOACTIVATE + | winuser::SWP_FRAMECHANGED, ); // We apply any requested changes to maximization state that occurred while we were in fullscreen. @@ -603,7 +598,8 @@ impl Window { window.0, winuser::GWL_EXSTYLE, ((ex_style as DWORD) - & !(winuser::WS_EX_DLGMODALFRAME | winuser::WS_EX_WINDOWEDGE + & !(winuser::WS_EX_DLGMODALFRAME + | winuser::WS_EX_WINDOWEDGE | winuser::WS_EX_CLIENTEDGE | winuser::WS_EX_STATICEDGE)) as LONG, @@ -616,7 +612,8 @@ impl Window { y as c_int, width as c_int, height as c_int, - winuser::SWP_ASYNCWINDOWPOS | winuser::SWP_NOZORDER + winuser::SWP_ASYNCWINDOWPOS + | winuser::SWP_NOZORDER | winuser::SWP_NOACTIVATE | winuser::SWP_FRAMECHANGED, ); @@ -705,9 +702,9 @@ impl Window { rect.right - rect.left, rect.bottom - rect.top, winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOZORDER - | winuser::SWP_NOACTIVATE - | winuser::SWP_FRAMECHANGED, + | winuser::SWP_NOZORDER + | winuser::SWP_NOACTIVATE + | winuser::SWP_FRAMECHANGED, ); }); } @@ -798,7 +795,7 @@ impl Drop for Window { /// A simple non-owning wrapper around a window. #[doc(hidden)] #[derive(Clone)] -pub struct WindowWrapper(HWND, HDC); +pub struct WindowWrapper(pub HWND, pub HDC); // Send is not implemented for HWND and HDC, we have to wrap it and implement it manually. // For more info see: @@ -806,9 +803,18 @@ pub struct WindowWrapper(HWND, HDC); // https://github.com/retep998/winapi-rs/issues/396 unsafe impl Send for WindowWrapper {} -pub unsafe fn adjust_size(physical_size: PhysicalSize, style: DWORD, ex_style: DWORD) -> (LONG, LONG) { +pub unsafe fn adjust_size( + physical_size: PhysicalSize, + style: DWORD, + ex_style: DWORD, +) -> (LONG, LONG) { let (width, height): (u32, u32) = physical_size.into(); - let mut rect = RECT { left: 0, right: width as LONG, top: 0, bottom: height as LONG }; + let mut rect = RECT { + left: 0, + right: width as LONG, + top: 0, + bottom: height as LONG, + }; winuser::AdjustWindowRectEx(&mut rect, style, 0, ex_style); (rect.right - rect.left, rect.bottom - rect.top) } @@ -825,9 +831,7 @@ unsafe fn init( .collect::>(); let window_icon = { - let icon = attributes.window_icon - .take() - .map(WinIcon::from_icon); + let icon = attributes.window_icon.take().map(WinIcon::from_icon); if icon.is_some() { Some(icon.unwrap().map_err(|err| { CreationError::OsError(format!("Failed to create `ICON_SMALL`: {:?}", err)) @@ -837,9 +841,7 @@ unsafe fn init( } }; let taskbar_icon = { - let icon = pl_attribs.taskbar_icon - .take() - .map(WinIcon::from_icon); + let icon = pl_attribs.taskbar_icon.take().map(WinIcon::from_icon); if icon.is_some() { Some(icon.unwrap().map_err(|err| { CreationError::OsError(format!("Failed to create `ICON_BIG`: {:?}", err)) @@ -852,9 +854,7 @@ unsafe fn init( // registering the window class let class_name = register_window_class(&window_icon, &taskbar_icon); - let (width, height) = attributes.dimensions - .map(Into::into) - .unwrap_or((1024, 768)); + let (width, height) = attributes.dimensions.map(Into::into).unwrap_or((1024, 768)); // building a RECT object with coordinates let mut rect = RECT { left: 0, @@ -865,18 +865,20 @@ unsafe fn init( // computing the style and extended style of the window let (mut ex_style, style) = if !attributes.decorations { - (winuser::WS_EX_APPWINDOW, + ( + winuser::WS_EX_APPWINDOW, //winapi::WS_POPUP is incompatible with winapi::WS_CHILD if pl_attribs.parent.is_some() { winuser::WS_CLIPSIBLINGS | winuser::WS_CLIPCHILDREN - } - else { + } else { winuser::WS_POPUP | winuser::WS_CLIPSIBLINGS | winuser::WS_CLIPCHILDREN - } + }, ) } else { - (winuser::WS_EX_APPWINDOW | winuser::WS_EX_WINDOWEDGE, - winuser::WS_OVERLAPPEDWINDOW | winuser::WS_CLIPSIBLINGS | winuser::WS_CLIPCHILDREN) + ( + winuser::WS_EX_APPWINDOW | winuser::WS_EX_WINDOWEDGE, + winuser::WS_OVERLAPPEDWINDOW | winuser::WS_CLIPSIBLINGS | winuser::WS_CLIPCHILDREN, + ) }; if attributes.always_on_top { @@ -887,19 +889,29 @@ unsafe fn init( winuser::AdjustWindowRectEx(&mut rect, style, 0, ex_style); // creating the real window this time, by using the functions in `extra_functions` - let real_window = { + let mut real_window = { let (adjusted_width, adjusted_height) = if attributes.dimensions.is_some() { - let min_dimensions = attributes.min_dimensions + let min_dimensions = attributes + .min_dimensions .map(|logical_size| PhysicalSize::from_logical(logical_size, 1.0)) .map(|physical_size| adjust_size(physical_size, style, ex_style)) .unwrap_or((0, 0)); - let max_dimensions = attributes.max_dimensions + let max_dimensions = attributes + .max_dimensions .map(|logical_size| PhysicalSize::from_logical(logical_size, 1.0)) .map(|physical_size| adjust_size(physical_size, style, ex_style)) .unwrap_or((c_int::max_value(), c_int::max_value())); ( - Some((rect.right - rect.left).min(max_dimensions.0).max(min_dimensions.0)), - Some((rect.bottom - rect.top).min(max_dimensions.1).max(min_dimensions.1)) + Some( + (rect.right - rect.left) + .min(max_dimensions.0) + .max(min_dimensions.0), + ), + Some( + (rect.bottom - rect.top) + .min(max_dimensions.1) + .max(min_dimensions.1), + ), ) } else { (None, None) @@ -919,11 +931,13 @@ unsafe fn init( style |= winuser::WS_CHILD; } - let handle = winuser::CreateWindowExW(ex_style | winuser::WS_EX_ACCEPTFILES, + let handle = winuser::CreateWindowExW( + ex_style | winuser::WS_EX_ACCEPTFILES, class_name.as_ptr(), title.as_ptr() as LPCWSTR, style | winuser::WS_CLIPSIBLINGS | winuser::WS_CLIPCHILDREN, - winuser::CW_USEDEFAULT, winuser::CW_USEDEFAULT, + winuser::CW_USEDEFAULT, + winuser::CW_USEDEFAULT, adjusted_width.unwrap_or(winuser::CW_USEDEFAULT), adjusted_height.unwrap_or(winuser::CW_USEDEFAULT), pl_attribs.parent.unwrap_or(ptr::null_mut()), @@ -933,14 +947,18 @@ unsafe fn init( ); if handle.is_null() { - return Err(CreationError::OsError(format!("CreateWindowEx function failed: {}", - format!("{}", io::Error::last_os_error())))); + return Err(CreationError::OsError(format!( + "CreateWindowEx function failed: {}", + format!("{}", io::Error::last_os_error()) + ))); } let hdc = winuser::GetDC(handle); if hdc.is_null() { - return Err(CreationError::OsError(format!("GetDC function failed: {}", - format!("{}", io::Error::last_os_error())))); + return Err(CreationError::OsError(format!( + "GetDC function failed: {}", + format!("{}", io::Error::last_os_error()) + ))); } WindowWrapper(handle, hdc) @@ -951,9 +969,9 @@ unsafe fn init( // Register for touch events if applicable { - let digitizer = winuser::GetSystemMetrics( winuser::SM_DIGITIZER ) as u32; + let digitizer = winuser::GetSystemMetrics(winuser::SM_DIGITIZER) as u32; if digitizer & winuser::NID_READY != 0 { - winuser::RegisterTouchWindow( real_window.0, winuser::TWF_WANTPALM ); + winuser::RegisterTouchWindow(real_window.0, winuser::TWF_WANTPALM); } } @@ -974,9 +992,11 @@ unsafe fn init( } let window_state = { - let max_size = attributes.max_dimensions + let max_size = attributes + .max_dimensions .map(|logical_size| PhysicalSize::from_logical(logical_size, dpi_factor)); - let min_size = attributes.min_dimensions + let min_size = attributes + .min_dimensions .map(|logical_size| PhysicalSize::from_logical(logical_size, dpi_factor)); let mut window_state = events_loop::WindowState { cursor: Cursor(winuser::IDC_ARROW), // use arrow by default @@ -993,14 +1013,18 @@ unsafe fn init( // making the window transparent if attributes.transparent { - let bb = dwmapi::DWM_BLURBEHIND { - dwFlags: 0x1, // FIXME: DWM_BB_ENABLE; - fEnable: 1, - hRgnBlur: ptr::null_mut(), - fTransitionOnMaximized: 0, - }; - - dwmapi::DwmEnableBlurBehindWindow(real_window.0, &bb); + // let bb = dwmapi::DWM_BLURBEHIND { + // dwFlags: 0x1, // FIXME: DWM_BB_ENABLE; + // fEnable: 1, + // hRgnBlur: ptr::null_mut(), + // fTransitionOnMaximized: 0, + // }; + + // dwmapi::DwmEnableBlurBehindWindow(real_window.0, &bb); + + super::blur::implementation().set_transparent(&mut real_window); + } else if attributes.blur { + super::blur::implementation().set_blur(&mut real_window); } let win = Window { @@ -1069,7 +1093,6 @@ unsafe fn register_window_class( class_name } - struct ComInitialized(*mut ()); impl Drop for ComInitialized { fn drop(&mut self) { From bc53f54aae73b3f69faec9e65ad3db69eaa8d7d4 Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Mon, 6 May 2019 19:53:42 +0200 Subject: [PATCH 8/9] Working Windows implementation including example --- _.swp | Bin 0 -> 12288 bytes examples/.blur.rs.swp | Bin 0 -> 12288 bytes examples/.swp | Bin 0 -> 12288 bytes examples/blur.rs | 30 +++++++++++++++++++-- src/.swp | Bin 0 -> 12288 bytes src/platform/.swp | Bin 0 -> 12288 bytes src/platform/windows/.blur.rs.swp | Bin 0 -> 20480 bytes src/platform/windows/.events_loop.rs.swp | Bin 0 -> 65536 bytes src/platform/windows/.swp | Bin 0 -> 12288 bytes src/platform/windows/blur.rs | 33 ++++++++--------------- src/platform/windows/events_loop.rs | 3 ++- 11 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 _.swp create mode 100644 examples/.blur.rs.swp create mode 100644 examples/.swp create mode 100644 src/.swp create mode 100644 src/platform/.swp create mode 100644 src/platform/windows/.blur.rs.swp create mode 100644 src/platform/windows/.events_loop.rs.swp create mode 100644 src/platform/windows/.swp diff --git a/_.swp b/_.swp new file mode 100644 index 0000000000000000000000000000000000000000..0aab8f8879c8359d861c87806e070e39ad15ee20 GIT binary patch literal 12288 zcmeI2y>AmS7>8Y^g7{{lET&WlXnVPqR!AqP6ea10lopXv1~`N+cP25p+#R-)HVXqC z5hG$nY>25FBLfo?0~_KW=*EK7h4Q`3-A~ zp`A{;GY>VNe^4cX-B{X(6a#sYGi;6kO4A42FL&zAOmE843Ggb zKnBRbe`3H382fpgvE~W9A^hf_eh08}iZLHdfXm?PNye7JD6qgF;Ghqj0lnZCo?in$ zz$*9#zJO2Q19%VKfLGupSO)2t=fP31hC8f+@8C1|2v)#5@D{uVFTitPKo#5vGr$3Z zpbt__~)QP0@;#)vAYVS7HBj_wwzlx5rkin{@*m zxGmlYH!GXt#8EGtp0L_741QL@}Hm;pv- zn8Dt{WSCZdhKVJwp5UDTzQ z2os0joE({Ost7qBb}BJ%Bs`Fc^Sl#?P#D2^$x$Nm>WH+XV`YZREzXx5o#38c*xqm+ zWv<23hKPLO@CR<@;lPk_j8JJpMrbgi;i!|-gNyQ2tr zdQ{rd^V{{D<1T2SwA=l=yqg!gX5z$Ml#w)8G$)K& Q&o@WL$F5?xgS5|n1AfG7)Bpeg literal 0 HcmV?d00001 diff --git a/examples/.blur.rs.swp b/examples/.blur.rs.swp new file mode 100644 index 0000000000000000000000000000000000000000..dfa54a34047ab96a2b55aeec98d00fdadffc69e4 GIT binary patch literal 12288 zcmeI2&u`pB6vwAUf>NNM_5>Fusg&$Ow3`+rq={NcHmQh6lPcLJNKh89J)5=SwcVL< zH=&J$_#wd+6}WQa!XJQCaYq~whYAGuUI2l(z!ARBV`n#MnidHz)j0ZQZO?me-uuk> zSxUA&xjKKIzfgOg;dp|v2h4Y`)9DeM2VNY?*5u?Q-8kSlw>;fwPA?o_VTT%`eo;%M z>pOw#vr=!EB(3+uI5c&+>Gje`>UulMR88r-Msx;_fFp441dg%iPM?}QIXc2m9KU$) zZqCvXa0DCyN5Bzq1RMcJz!7i+?h67YJ;eS-C5NGD=ujbixWf@}1RMcJz!7i+905nb z5pV<8$3=o{!0=wql0y#$RzN1?xt zG4>~P6Z#a|fKEeyJjU2B(9h79&~@k%vs0!VBn6b~HccC_P7CHePhkiQ3*pJZH(EHGf z&`s3-5%dA{4n!=T!hLr*0*-(q;0QPZ|1E)S#&K*j`mty9n+|(z&pD5z;VpiK&AC^b{8@ggO2+$5g`mUf&dBvJ{`U#nn#7>& z3)Az9&6Vcz#YPk1wF!ji$(|5zNtMW;GE{RGYp)~uRklNc2v}M+GhnN&OVjH1V|Y>_ zG%7nnyu7wJJ2h}b`7{(7ArdWwje(Q39R1v;8IUeay)+a;cReMMppCk}O@`btPJpe! z$=CeOdc}B(GD|cv9WCY?tzJSkw3PKaZ+0bbN1ngI{Uk~h4>j+3f#gPcu}(2>Y+d`mtt;nN6C`MQU=^4Jf;0qxKKs*~8X!8J}j2D{`RvK^fuv1jl3Il#7f5K>EgtR4)t0i8V+i0-dotwM@-uW&a0GP|~ ziDlVQQg;XTMIFWPn%zQVJ2chyohZ#H>1_;RQCc;-s%3`sxrbaiw2x&ubO(=e_yA8b zxe_Xqc~NUaZuv!oaz#bZ#@Xgu__>lVDE3caW@gRAq! zg%Goz+Nknv+pZ|op7z-DeCm={hrK3>euG{)0l6ND@km|}ar1m!+h3j22PF)W@+{+?kAB=q(YM!BOrz{VSU$rdm zD=!^>gVfqt7zLHFA-dIpeLpnaoKwZ9Ozs^pp^0Q=bQ(=GQ);VVJ2GnR_P&V*U1Nr( zr1yI)`<1F)Dzc^*;ZPp-1x9Xj)H?J6R=)6=q6XbVD@XsrTFXr!in*_Vin73)Y3jC{ IA>LsB04RCA$^ZZW literal 0 HcmV?d00001 diff --git a/examples/.swp b/examples/.swp new file mode 100644 index 0000000000000000000000000000000000000000..00e4f42b48be7f382cfefc98932c72c0f7a1b040 GIT binary patch literal 12288 zcmeI2PiqrF7>B1ldC*!aco2j!MzGRmx3)!CR45Hap$b;xrIE0Irs*`B-F0TyBt7)% z$#cJfHxD9S#BWd#@16wD9=*ojY?`!brM1$7$~*Av%=^yFJCi53WIg-o{RjM3X^x?d zGxommxoU=IFb>>EikfZPCUHbtT3J|pvao!_ir&fDDiUGC&5%02v?yWPl9(CkEVrv59kxZ2|NDzxfT| z?Rmz0Fb^(+oiWBX!6di_3g8kL2czHz_I?9jzz+Bb-htO(8@vLhz5`|f2jSK9y+Pcn$^BzL9*&}t z(g!mKW2G5VL)oDqHbt;x-;sVlw|5Kw(EOo9e$L?9zq+cqh*{9zYWhE=uV?qJz0iD; zRJoB(TqUB^gi2_+>3X3sL89Vz#|)ZTn9999O&QgiZo7u1`8sK;CQ+TOyHOCzs9y8K zSm#r9<$4}6rpj6thT2y` winit::ControlFlow::Break, + winit::Event::WindowEvent { + event: winit::WindowEvent::Refresh, + window_id, + } if window_id == window.id() => { + paint_window(&window); // Important! + winit::ControlFlow::Continue + }, _ => winit::ControlFlow::Continue, }); } + +fn paint_window(window: &winit::Window) { + // On Windows we need to paint the color black onto the window. + // The black color is made transparent by the compositor. + #[cfg(target_os = "windows")] { + use winapi::um::winuser; + use winapi::shared::windef; + use winit::os::windows::WindowExt; + + let window = window.get_hwnd() as windef::HWND; + + unsafe { + let mut ps: winuser::PAINTSTRUCT = std::mem::zeroed(); + let hdc = winuser::BeginPaint(window, &mut ps as *mut _); + let _ = winuser::FillRect(hdc, &ps.rcPaint as *const _, (winuser::COLOR_WINDOWTEXT + 1) as _); + let _ = winuser::EndPaint(window, &mut ps as *mut _); + } + } +} diff --git a/src/.swp b/src/.swp new file mode 100644 index 0000000000000000000000000000000000000000..619a215d05201cbf7e45a94d79b4ca17aa1500d0 GIT binary patch literal 12288 zcmeI2F>ljA6vwYjT_~tbY>zZjp=xahS|M3bscKY#RFEiyg&^eE*XD@pGk2GUE+9St zI}!_@0EwNAFVJtoj2O!Q+$4$^8dP&$*IjaY*}e+IBpy^rR_Ogh67b77h02sQ@ij2 zHoykXW?-&$=XN7nsNJAz^R2VB;9YEh4X^<=zy{a=8(;%$fDQb&23$EKj&b*w0RHle znIT9VY=8~00XDz}*Z><~18jf|umLu}2H3y_F_2_Je7-EiPvBnw_;&!`t_YEW7}UVg zoDlCp0G7ZaSOC|-JeUOn{2KQ8f&3kO1z*4?@DY3f7IXmz8(;%$fDNz#Hoykh02^Qf zY~Z3Ah@!P)eB_+zK`>DoD<)?X^{5xc$6b^}EAgJDeo2`!M9nyp zxpb0fCpNN3_EFi`YU5TqheU59~YY6m#k4mwE>>0N!?QD)>X<-=dUI{q(Tv}568>CAwd%E;7db4c6D aI#ukQG@Cx&EUNtnjkVQV=ysk@K>Pva#_kmW literal 0 HcmV?d00001 diff --git a/src/platform/.swp b/src/platform/.swp new file mode 100644 index 0000000000000000000000000000000000000000..e61371c509bcd919406a068564883c0055255e79 GIT binary patch literal 12288 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 MQH8|!F!(;}->CJKwg3PC literal 0 HcmV?d00001 diff --git a/src/platform/windows/.events_loop.rs.swp b/src/platform/windows/.events_loop.rs.swp new file mode 100644 index 0000000000000000000000000000000000000000..6329fd2476cf7a9b16d0b8353d1b7592789ed1ef GIT binary patch literal 65536 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 MuT7!bUcM6c7Z)W;umAu6 literal 0 HcmV?d00001 diff --git a/src/platform/windows/blur.rs b/src/platform/windows/blur.rs index 3487e27869..0f756d6f50 100644 --- a/src/platform/windows/blur.rs +++ b/src/platform/windows/blur.rs @@ -88,12 +88,14 @@ impl Implementation for Dwm { struct AcrylicBlur; +/// SetWindowCompositionAttribute function pointer +type SwcaFn = unsafe extern "system" fn( + hwnd: HWND, + attribute: *const WindowCompositionAttributeData +) -> raw::c_int; + struct AcrylicBlurPointers { - swca: libloading::Symbol< - 'static, - unsafe extern "system" fn(hwnd: HWND, attribute: *const WindowCompositionAttributeData) - -> raw::c_int, - >, + swca: libloading::Symbol<'static, SwcaFn>, } impl AcrylicBlurPointers { @@ -109,11 +111,11 @@ impl AcrylicBlurPointers { #[repr(u32)] enum AccentState { Disable = 0, - // EnableGradient = 1, - // EnableTransparentGradient = 2, + EnableGradient = 1, + EnableTransparentGradient = 2, EnableBlurBehind = 3, - // EnableAcrylicBlurBehind = 4, - // InvalidState = 5, + EnableAcrylicBlurBehind = 4, + InvalidState = 5, } #[repr(C)] @@ -177,18 +179,5 @@ impl Implementation for AcrylicBlur { size: ::std::mem::size_of::() as _, }, ); - - unsafe { - let res = winuser::RedrawWindow( - window.0, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INVALIDATE | winuser::RDW_UPDATENOW, - ); - println!("res {}, err {}", res, errhandlingapi::GetLastError()); - - let res = winuser::SendMessageW(window.0, winuser::WM_ERASEBKGND, 0, 0); - println!("res {}, err {}", res, errhandlingapi::GetLastError()); - } } } diff --git a/src/platform/windows/events_loop.rs b/src/platform/windows/events_loop.rs index 1f51ac1dd7..40c6ed41dc 100644 --- a/src/platform/windows/events_loop.rs +++ b/src/platform/windows/events_loop.rs @@ -473,7 +473,8 @@ pub unsafe extern "system" fn callback( window_id: SuperWindowId(WindowId(window)), event: Refresh, }); - winuser::DefWindowProcW(window, msg, wparam, lparam) + //winuser::DefWindowProcW(window, msg, wparam, lparam) // TODO: Why was this here? + 0 }, // WM_MOVE supplies client area positions, so we send Moved here instead. From 4eb989c6f7d03425a6870fec18d5f6f3ff33ef02 Mon Sep 17 00:00:00 2001 From: Daniel Hauser Date: Mon, 6 May 2019 20:02:33 +0200 Subject: [PATCH 9/9] Delete vim swap files --- _.swp | Bin 12288 -> 0 bytes examples/.blur.rs.swp | Bin 12288 -> 0 bytes examples/.swp | Bin 12288 -> 0 bytes src/.swp | Bin 12288 -> 0 bytes src/platform/.swp | Bin 12288 -> 0 bytes src/platform/windows/.blur.rs.swp | Bin 20480 -> 0 bytes src/platform/windows/.events_loop.rs.swp | Bin 65536 -> 0 bytes src/platform/windows/.swp | Bin 12288 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 _.swp delete mode 100644 examples/.blur.rs.swp delete mode 100644 examples/.swp delete mode 100644 src/.swp delete mode 100644 src/platform/.swp delete mode 100644 src/platform/windows/.blur.rs.swp delete mode 100644 src/platform/windows/.events_loop.rs.swp delete mode 100644 src/platform/windows/.swp diff --git a/_.swp b/_.swp deleted file mode 100644 index 0aab8f8879c8359d861c87806e070e39ad15ee20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2y>AmS7>8Y^g7{{lET&WlXnVPqR!AqP6ea10lopXv1~`N+cP25p+#R-)HVXqC z5hG$nY>25FBLfo?0~_KW=*EK7h4Q`3-A~ zp`A{;GY>VNe^4cX-B{X(6a#sYGi;6kO4A42FL&zAOmE843Ggb zKnBRbe`3H382fpgvE~W9A^hf_eh08}iZLHdfXm?PNye7JD6qgF;Ghqj0lnZCo?in$ zz$*9#zJO2Q19%VKfLGupSO)2t=fP31hC8f+@8C1|2v)#5@D{uVFTitPKo#5vGr$3Z zpbt__~)QP0@;#)vAYVS7HBj_wwzlx5rkin{@*m zxGmlYH!GXt#8EGtp0L_741QL@}Hm;pv- zn8Dt{WSCZdhKVJwp5UDTzQ z2os0joE({Ost7qBb}BJ%Bs`Fc^Sl#?P#D2^$x$Nm>WH+XV`YZREzXx5o#38c*xqm+ zWv<23hKPLO@CR<@;lPk_j8JJpMrbgi;i!|-gNyQ2tr zdQ{rd^V{{D<1T2SwA=l=yqg!gX5z$Ml#w)8G$)K& Q&o@WL$F5?xgS5|n1AfG7)Bpeg diff --git a/examples/.blur.rs.swp b/examples/.blur.rs.swp deleted file mode 100644 index dfa54a34047ab96a2b55aeec98d00fdadffc69e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2&u`pB6vwAUf>NNM_5>Fusg&$Ow3`+rq={NcHmQh6lPcLJNKh89J)5=SwcVL< zH=&J$_#wd+6}WQa!XJQCaYq~whYAGuUI2l(z!ARBV`n#MnidHz)j0ZQZO?me-uuk> zSxUA&xjKKIzfgOg;dp|v2h4Y`)9DeM2VNY?*5u?Q-8kSlw>;fwPA?o_VTT%`eo;%M z>pOw#vr=!EB(3+uI5c&+>Gje`>UulMR88r-Msx;_fFp441dg%iPM?}QIXc2m9KU$) zZqCvXa0DCyN5Bzq1RMcJz!7i+?h67YJ;eS-C5NGD=ujbixWf@}1RMcJz!7i+905nb z5pV<8$3=o{!0=wql0y#$RzN1?xt zG4>~P6Z#a|fKEeyJjU2B(9h79&~@k%vs0!VBn6b~HccC_P7CHePhkiQ3*pJZH(EHGf z&`s3-5%dA{4n!=T!hLr*0*-(q;0QPZ|1E)S#&K*j`mty9n+|(z&pD5z;VpiK&AC^b{8@ggO2+$5g`mUf&dBvJ{`U#nn#7>& z3)Az9&6Vcz#YPk1wF!ji$(|5zNtMW;GE{RGYp)~uRklNc2v}M+GhnN&OVjH1V|Y>_ zG%7nnyu7wJJ2h}b`7{(7ArdWwje(Q39R1v;8IUeay)+a;cReMMppCk}O@`btPJpe! z$=CeOdc}B(GD|cv9WCY?tzJSkw3PKaZ+0bbN1ngI{Uk~h4>j+3f#gPcu}(2>Y+d`mtt;nN6C`MQU=^4Jf;0qxKKs*~8X!8J}j2D{`RvK^fuv1jl3Il#7f5K>EgtR4)t0i8V+i0-dotwM@-uW&a0GP|~ ziDlVQQg;XTMIFWPn%zQVJ2chyohZ#H>1_;RQCc;-s%3`sxrbaiw2x&ubO(=e_yA8b zxe_Xqc~NUaZuv!oaz#bZ#@Xgu__>lVDE3caW@gRAq! zg%Goz+Nknv+pZ|op7z-DeCm={hrK3>euG{)0l6ND@km|}ar1m!+h3j22PF)W@+{+?kAB=q(YM!BOrz{VSU$rdm zD=!^>gVfqt7zLHFA-dIpeLpnaoKwZ9Ozs^pp^0Q=bQ(=GQ);VVJ2GnR_P&V*U1Nr( zr1yI)`<1F)Dzc^*;ZPp-1x9Xj)H?J6R=)6=q6XbVD@XsrTFXr!in*_Vin73)Y3jC{ IA>LsB04RCA$^ZZW diff --git a/examples/.swp b/examples/.swp deleted file mode 100644 index 00e4f42b48be7f382cfefc98932c72c0f7a1b040..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2PiqrF7>B1ldC*!aco2j!MzGRmx3)!CR45Hap$b;xrIE0Irs*`B-F0TyBt7)% z$#cJfHxD9S#BWd#@16wD9=*ojY?`!brM1$7$~*Av%=^yFJCi53WIg-o{RjM3X^x?d zGxommxoU=IFb>>EikfZPCUHbtT3J|pvao!_ir&fDDiUGC&5%02v?yWPl9(CkEVrv59kxZ2|NDzxfT| z?Rmz0Fb^(+oiWBX!6di_3g8kL2czHz_I?9jzz+Bb-htO(8@vLhz5`|f2jSK9y+Pcn$^BzL9*&}t z(g!mKW2G5VL)oDqHbt;x-;sVlw|5Kw(EOo9e$L?9zq+cqh*{9zYWhE=uV?qJz0iD; zRJoB(TqUB^gi2_+>3X3sL89Vz#|)ZTn9999O&QgiZo7u1`8sK;CQ+TOyHOCzs9y8K zSm#r9<$4}6rpj6thT2y`ljA6vwYjT_~tbY>zZjp=xahS|M3bscKY#RFEiyg&^eE*XD@pGk2GUE+9St zI}!_@0EwNAFVJtoj2O!Q+$4$^8dP&$*IjaY*}e+IBpy^rR_Ogh67b77h02sQ@ij2 zHoykXW?-&$=XN7nsNJAz^R2VB;9YEh4X^<=zy{a=8(;%$fDQb&23$EKj&b*w0RHle znIT9VY=8~00XDz}*Z><~18jf|umLu}2H3y_F_2_Je7-EiPvBnw_;&!`t_YEW7}UVg zoDlCp0G7ZaSOC|-JeUOn{2KQ8f&3kO1z*4?@DY3f7IXmz8(;%$fDNz#Hoykh02^Qf zY~Z3Ah@!P)eB_+zK`>DoD<)?X^{5xc$6b^}EAgJDeo2`!M9nyp zxpb0fCpNN3_EFi`YU5TqheU59~YY6m#k4mwE>>0N!?QD)>X<-=dUI{q(Tv}568>CAwd%E;7db4c6D aI#ukQG@Cx&EUNtnjkVQV=ysk@K>Pva#_kmW diff --git a/src/platform/.swp b/src/platform/.swp deleted file mode 100644 index e61371c509bcd919406a068564883c0055255e79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 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 MQH8|!F!(;}->CJKwg3PC diff --git a/src/platform/windows/.events_loop.rs.swp b/src/platform/windows/.events_loop.rs.swp deleted file mode 100644 index 6329fd2476cf7a9b16d0b8353d1b7592789ed1ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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 MuT7!bUcM6c7Z)W;umAu6