Skip to content

Commit 9c410ed

Browse files
authored
Merge pull request #79 from compio-rs/opt-backdrop
feat: optimize backdrop and some fixes
2 parents e2d3771 + 957372c commit 9c410ed

File tree

24 files changed

+718
-202
lines changed

24 files changed

+718
-202
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ winio-primitive = { path = "winio-primitive", version = "0.1.1" }
2929
winio-callback = { path = "winio-callback", version = "0.1.1" }
3030
winio-layout = { path = "winio-layout", version = "0.1.2" }
3131
winio-handle = { path = "winio-handle", version = "0.4.0" }
32-
winio-elm = { path = "winio-elm", version = "0.3.0" }
32+
winio-elm = { path = "winio-elm", version = "0.3.1" }
3333
winio-pollable = { path = "winio-pollable", version = "0.2.0" }
3434
winio-ui-windows-common = { path = "winio-ui-windows-common", version = "0.3.2" }
3535
winio-ui-win32 = { path = "winio-ui-win32", version = "0.3.2" }
36-
winio-ui-winui = { path = "winio-ui-winui", version = "0.3.1" }
36+
winio-ui-winui = { path = "winio-ui-winui", version = "0.3.3" }
3737
winio-ui-gtk = { path = "winio-ui-gtk", version = "0.3.1" }
3838
winio-ui-qt = { path = "winio-ui-qt", version = "0.3.1" }
39-
winio-ui-app-kit = { path = "winio-ui-app-kit", version = "0.3.1" }
39+
winio-ui-app-kit = { path = "winio-ui-app-kit", version = "0.3.3" }
4040

4141
compio = "0.16.0"
4242
compio-runtime = "0.9.1"
@@ -55,7 +55,7 @@ widestring = "1"
5555
windows-sys = "0.61"
5656
windows = "0.62"
5757
windows-core = "0.62"
58-
winui3 = { version = "0.3.5", package = "winio-winui3" }
58+
winui3 = { version = "0.3.6", package = "winio-winui3" }
5959
webview2 = { version = "0.1.0", package = "winio-webview2" }
6060

6161
send_wrapper = "0.6"

winio-elm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "winio-elm"
3-
version = "0.3.0"
3+
version = "0.3.1"
44
description = "ELM framework for winio."
55
edition = { workspace = true }
66
authors = { workspace = true }

winio-elm/src/child.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl<T: Component> Child<T> {
113113

114114
/// Respond to the child message.
115115
pub async fn update(&mut self) -> bool {
116-
let mut need_render = false;
116+
let mut need_render = self.model.update_children().await;
117117
for message in self.msg_cache.drain(..) {
118118
need_render |= self.model.update(message, &self.sender).await;
119119
}
@@ -123,6 +123,7 @@ impl<T: Component> Child<T> {
123123
/// Render the child component.
124124
pub fn render(&mut self) {
125125
self.model.render(&self.sender);
126+
self.model.render_children();
126127
}
127128
}
128129

winio-ui-app-kit/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "winio-ui-app-kit"
3-
version = "0.3.2"
3+
version = "0.3.3"
44
description = "AppKit backend for winio."
55
edition = { workspace = true }
66
authors = { workspace = true }

winio-ui-app-kit/src/ui/button.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ impl CheckBox {
106106

107107
pub fn set_enabled(&mut self, v: bool);
108108

109-
pub fn preferred_size(&self) -> Size;
109+
pub fn preferred_size(&self) -> Size {
110+
let mut s = self.handle.preferred_size();
111+
s.width += 4.0;
112+
s
113+
}
110114

111115
pub fn loc(&self) -> Point;
112116

winio-ui-app-kit/src/ui/label.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl Label {
3939

4040
pub fn preferred_size(&self) -> Size {
4141
let mut size = self.handle.preferred_size();
42-
size.width += 4.0;
42+
size.width += 8.0;
4343
size
4444
}
4545

winio-ui-app-kit/src/ui/window.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,13 @@ impl Widget {
370370
}
371371

372372
pub fn preferred_size(&self) -> Size {
373+
let s = self.view.fittingSize();
374+
if s != NSSize::ZERO {
375+
return from_cgsize(s);
376+
}
373377
self.view
374378
.downcast_ref::<NSControl>()
375-
.map(|c| from_cgsize(c.sizeThatFits(NSSize::new(f64::INFINITY, f64::INFINITY))))
379+
.map(|c| from_cgsize(c.sizeThatFits(NSSize::ZERO)))
376380
.unwrap_or_default()
377381
}
378382

winio-ui-winui/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "winio-ui-winui"
3-
version = "0.3.2"
3+
version = "0.3.3"
44
description = "WinUI backend for winio."
55
edition = { workspace = true }
66
authors = { workspace = true }
@@ -51,6 +51,7 @@ windows = { workspace = true, features = [
5151
"Win32_Graphics_Direct3D11",
5252
"Win32_Graphics_Dxgi",
5353
] }
54+
windows-core = { workspace = true }
5455

5556
slim-detours-sys = { workspace = true }
5657
sync-unsafe-cell = { workspace = true }

winio-ui-winui/src/ui/backdrop.rs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
use std::cell::RefCell;
2+
3+
use windows::{
4+
UI::Color,
5+
core::{IInspectable_Vtbl, Interface, Ref, Result, imp::WeakRefCount, implement},
6+
};
7+
use winio_primitive::ColorTheme;
8+
use winui3::{
9+
ChildClass, Compose, CreateInstanceFn,
10+
Microsoft::UI::{
11+
Composition::{
12+
ICompositionSupportsSystemBackdrop,
13+
SystemBackdrops::{DesktopAcrylicController, SystemBackdropConfiguration},
14+
},
15+
Xaml::{
16+
self as MUX,
17+
Media::{
18+
ISystemBackdropFactory, ISystemBackdropOverrides, ISystemBackdropOverrides_Impl,
19+
SystemBackdrop,
20+
},
21+
},
22+
},
23+
};
24+
25+
use crate::color_theme;
26+
27+
// Magic colors to match Win32.
28+
const fn color(dark: bool) -> Color {
29+
if dark {
30+
Color {
31+
A: 0xFF,
32+
R: 0x54,
33+
G: 0x54,
34+
B: 0x54,
35+
}
36+
} else {
37+
Color {
38+
A: 0xFF,
39+
R: 0xD3,
40+
G: 0xD3,
41+
B: 0xD3,
42+
}
43+
}
44+
}
45+
46+
fn update_color(controller: &DesktopAcrylicController) -> Result<()> {
47+
let color = color(color_theme() == ColorTheme::Dark);
48+
controller.SetTintColor(color)?;
49+
controller.SetFallbackColor(color)?;
50+
Ok(())
51+
}
52+
53+
struct CustomDesktopAcrylicBackdropControllerEntry {
54+
controller: DesktopAcrylicController,
55+
target: ICompositionSupportsSystemBackdrop,
56+
}
57+
58+
impl CustomDesktopAcrylicBackdropControllerEntry {
59+
pub fn new(
60+
target: ICompositionSupportsSystemBackdrop,
61+
controller: DesktopAcrylicController,
62+
configuration: &SystemBackdropConfiguration,
63+
) -> Result<Self> {
64+
controller.AddSystemBackdropTarget(&target)?;
65+
controller.SetSystemBackdropConfiguration(configuration)?;
66+
Ok(Self { target, controller })
67+
}
68+
}
69+
70+
impl Drop for CustomDesktopAcrylicBackdropControllerEntry {
71+
fn drop(&mut self) {
72+
self.controller
73+
.RemoveSystemBackdropTarget(&self.target)
74+
.ok();
75+
self.controller.Close().ok();
76+
}
77+
}
78+
79+
#[implement(ISystemBackdropOverrides, Agile = false)]
80+
pub struct CustomDesktopAcrylicBackdrop {
81+
controllers: RefCell<Vec<CustomDesktopAcrylicBackdropControllerEntry>>,
82+
}
83+
84+
impl CustomDesktopAcrylicBackdrop {
85+
pub fn compose() -> Result<SystemBackdrop> {
86+
Compose::compose(Self {
87+
controllers: RefCell::new(vec![]),
88+
})
89+
}
90+
}
91+
92+
impl ISystemBackdropOverrides_Impl for CustomDesktopAcrylicBackdrop_Impl {
93+
fn OnTargetConnected(
94+
&self,
95+
target: Ref<ICompositionSupportsSystemBackdrop>,
96+
root: Ref<MUX::XamlRoot>,
97+
) -> Result<()> {
98+
let base = unsafe { Compose::<CustomDesktopAcrylicBackdrop>::base(self) };
99+
let target = target.ok()?;
100+
let root = root.ok()?;
101+
102+
unsafe {
103+
let base = base.cast::<ISystemBackdropOverrides>()?;
104+
(base.vtable().OnTargetConnected)(base.as_raw(), target.as_raw(), root.as_raw())
105+
.ok()?;
106+
}
107+
108+
let configuration = base
109+
.cast::<SystemBackdrop>()?
110+
.GetDefaultSystemBackdropConfiguration(target, root)?;
111+
let controller = DesktopAcrylicController::new()?;
112+
// Magic number to match Win32.
113+
controller.SetLuminosityOpacity(0.65)?;
114+
update_color(&controller)?;
115+
116+
self.controllers
117+
.borrow_mut()
118+
.push(CustomDesktopAcrylicBackdropControllerEntry::new(
119+
target.clone(),
120+
controller,
121+
&configuration,
122+
)?);
123+
Ok(())
124+
}
125+
126+
fn OnTargetDisconnected(&self, target: Ref<ICompositionSupportsSystemBackdrop>) -> Result<()> {
127+
let base = unsafe { Compose::<CustomDesktopAcrylicBackdrop>::base(self) };
128+
let target = target.ok()?;
129+
unsafe {
130+
let base = base.cast::<ISystemBackdropOverrides>()?;
131+
(base.vtable().OnTargetDisconnected)(base.as_raw(), target.as_raw()).ok()?;
132+
}
133+
let mut controllers = self.controllers.borrow_mut();
134+
if let Some(pos) = controllers.iter().position(|entry| entry.target == *target) {
135+
controllers.remove(pos);
136+
}
137+
Ok(())
138+
}
139+
140+
fn OnDefaultSystemBackdropConfigurationChanged(
141+
&self,
142+
target: Ref<ICompositionSupportsSystemBackdrop>,
143+
root: Ref<MUX::XamlRoot>,
144+
) -> Result<()> {
145+
let base = unsafe { Compose::<CustomDesktopAcrylicBackdrop>::base(self) };
146+
let target = target.ok()?;
147+
let root = root.ok()?;
148+
unsafe {
149+
let base = base.cast::<ISystemBackdropOverrides>()?;
150+
(base.vtable().OnDefaultSystemBackdropConfigurationChanged)(
151+
base.as_raw(),
152+
target.as_raw(),
153+
root.as_raw(),
154+
)
155+
.ok()?;
156+
}
157+
for entry in self.controllers.borrow().iter() {
158+
if entry.target == *target {
159+
update_color(&entry.controller)?;
160+
break;
161+
}
162+
}
163+
Ok(())
164+
}
165+
}
166+
167+
impl ChildClass for CustomDesktopAcrylicBackdrop {
168+
type BaseType = SystemBackdrop;
169+
type FactoryInterface = ISystemBackdropFactory;
170+
171+
fn create_interface_fn(
172+
vtable: &<Self::FactoryInterface as Interface>::Vtable,
173+
) -> CreateInstanceFn {
174+
vtable.CreateInstance
175+
}
176+
177+
fn identity_vtable(vtable: &mut Self::Outer) -> &mut &'static IInspectable_Vtbl {
178+
&mut vtable.identity
179+
}
180+
181+
fn ref_count(vtable: &Self::Outer) -> &WeakRefCount {
182+
&vtable.count
183+
}
184+
185+
fn into_outer(self) -> Self::Outer {
186+
Self::into_outer(self)
187+
}
188+
}

winio-ui-winui/src/ui/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ pub fn color_theme() -> ColorTheme {
130130
mod window;
131131
pub use window::*;
132132

133+
mod backdrop;
134+
pub(crate) use backdrop::*;
135+
133136
mod widget;
134137
pub(crate) use widget::*;
135138

0 commit comments

Comments
 (0)