i_slint_backend_qt/qt_widgets/
palette.rs1use i_slint_core::{items::ColorScheme, Brush};
7
8use super::*;
9
10cpp! {{
11namespace {
12struct PaletteStyleChangeListener : QWidget {
13 const void *qtStylePalette = nullptr;
14 PaletteStyleChangeListener(const void *qtStylePalette) : qtStylePalette(qtStylePalette) {}
15 bool event(QEvent *event) override {
16 auto ty = event->type();
17 if (ty == QEvent::StyleChange || ty == QEvent::PaletteChange || ty == QEvent::FontChange) {
18 rust!(Slint_qt_style_change_event [qtStylePalette: Pin<&NativePalette> as "const void*"] {
19 qtStylePalette.init_impl();
20 });
21 }
22 return QWidget::event(event);
23 }
24};
25}
26}}
27
28#[repr(C)]
29#[derive(FieldOffsets, SlintElement)]
30#[pin]
31#[pin_drop]
32pub struct NativePalette {
33 pub background: Property<Brush>,
34 pub foreground: Property<Brush>,
35 pub alternate_background: Property<Brush>,
36 pub alternate_foreground: Property<Brush>,
37 pub accent_background: Property<Brush>,
38 pub accent_foreground: Property<Brush>,
39 pub control_background: Property<Brush>,
40 pub control_foreground: Property<Brush>,
41 pub selection_background: Property<Brush>,
42 pub selection_foreground: Property<Brush>,
43 pub border: Property<Brush>,
44 pub color_scheme: Property<ColorScheme>,
45 pub style_change_listener: core::cell::Cell<*const u8>,
46}
47
48impl const_field_offset::PinnedDrop for NativePalette {
49 fn drop(self: Pin<&mut Self>) {
50 slint_native_palette_deinit(self);
51 }
52}
53
54impl NativePalette {
55 pub fn new() -> Pin<Rc<Self>> {
56 Rc::pin(NativePalette {
57 background: Default::default(),
58 alternate_background: Default::default(),
59 alternate_foreground: Default::default(),
60 foreground: Default::default(),
61 accent_background: Default::default(),
62 accent_foreground: Default::default(),
63 control_background: Default::default(),
64 control_foreground: Default::default(),
65 border: Default::default(),
66 selection_background: Default::default(),
67 selection_foreground: Default::default(),
68 color_scheme: Default::default(),
69 style_change_listener: core::cell::Cell::new(core::ptr::null()),
70 })
71 }
72
73 pub fn init<T>(self: Pin<Rc<Self>>, _root: &T) {
74 self.as_ref().init_impl();
75 }
76
77 fn init_impl(self: Pin<&Self>) {
78 let wrong_thread = cpp!(unsafe [] -> bool as "bool" {
79 static QMutex mtx;
80 QMutexLocker locker(&mtx);
81 ensure_initialized();
82 return qApp->thread() != QThread::currentThread();
83 });
84 if wrong_thread {
85 return;
86 }
87
88 let background = cpp!(unsafe[] -> u32 as "QRgb" {
89 return qApp->palette().color(QPalette::Window).rgba();
90 });
91 let background = Color::from_argb_encoded(background);
92 self.background.set(Brush::from(background));
93
94 let alternate_background = cpp!(unsafe[] -> u32 as "QRgb" {
95 return qApp->palette().color(QPalette::Base).rgba();
96 });
97 let alternate_background = Color::from_argb_encoded(alternate_background);
98 self.alternate_background.set(Brush::from(alternate_background));
99
100 let alternate_foreground = cpp!(unsafe[] -> u32 as "QRgb" {
101 return qApp->palette().color(QPalette::Text).rgba();
102 });
103 let alternate_foreground = Color::from_argb_encoded(alternate_foreground);
104 self.alternate_foreground.set(Brush::from(alternate_foreground));
105
106 let foreground = cpp!(unsafe[] -> u32 as "QRgb" {
107 return qApp->palette().color(QPalette::WindowText).rgba();
108 });
109 let foreground = Color::from_argb_encoded(foreground);
110 self.foreground.set(Brush::from(foreground));
111
112 let accent_background = cpp!(unsafe[] -> u32 as "QRgb" {
113 return qApp->palette().color(QPalette::Link).rgba();
114 });
115 let accent_background = Color::from_argb_encoded(accent_background);
116 self.accent_background.set(Brush::from(accent_background));
117
118 let accent_foreground = cpp!(unsafe[] -> u32 as "QRgb" {
119 #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
120 return qApp->palette().color(QPalette::Accent).rgba();
121 #else
122 return qApp->palette().color(QPalette::Highlight).rgba();
123 #endif
124 });
125 let accent_foreground = Color::from_argb_encoded(accent_foreground);
126 self.accent_foreground.set(Brush::from(accent_foreground));
127
128 let control_background = cpp!(unsafe[] -> u32 as "QRgb" {
129 return qApp->palette().color(QPalette::Button).rgba();
130 });
131 let control_background = Color::from_argb_encoded(control_background);
132 self.control_background.set(Brush::from(control_background));
133
134 let control_foreground = cpp!(unsafe[] -> u32 as "QRgb" {
135 return qApp->palette().color(QPalette::ButtonText).rgba();
136 });
137 let control_foreground = Color::from_argb_encoded(control_foreground);
138 self.control_foreground.set(Brush::from(control_foreground));
139
140 let border = cpp!(unsafe[] -> u32 as "QRgb" {
141 return qApp->palette().color(QPalette::Midlight).rgba();
142 });
143 let border = Color::from_argb_encoded(border);
144 self.border.set(Brush::from(border));
145
146 let selection_background = cpp!(unsafe[] -> u32 as "QRgb" {
147 return qApp->palette().color(QPalette::Highlight).rgba();
148 });
149 let selection_background = Color::from_argb_encoded(selection_background);
150 self.selection_background.set(Brush::from(selection_background));
151
152 let selection_foreground = cpp!(unsafe[] -> u32 as "QRgb" {
153 return qApp->palette().color(QPalette::HighlightedText).rgba();
154 });
155 let selection_foreground = Color::from_argb_encoded(selection_foreground);
156 self.selection_foreground.set(Brush::from(selection_foreground));
157
158 self.color_scheme.set(
159 if (background.red() as u32 + background.green() as u32 + background.blue() as u32) / 3
160 < 128
161 {
162 ColorScheme::Dark
163 } else {
164 ColorScheme::Light
165 },
166 );
167
168 if self.style_change_listener.get().is_null() {
169 self.style_change_listener.set(cpp!(unsafe [self as "void*"] -> *const u8 as "void*"{
170 return new PaletteStyleChangeListener(self);
171 }));
172 }
173 }
174}
175
176#[cfg(feature = "rtti")]
177impl i_slint_core::rtti::BuiltinGlobal for NativePalette {
178 fn new() -> Pin<Rc<Self>> {
179 let r = NativePalette::new();
180 r.as_ref().init_impl();
181 r
182 }
183}
184
185#[unsafe(no_mangle)]
186pub extern "C" fn slint_native_palette_init(self_: Pin<&NativePalette>) {
187 self_.style_change_listener.set(core::ptr::null()); self_.init_impl();
189}
190
191#[unsafe(no_mangle)]
192pub extern "C" fn slint_native_palette_deinit(self_: Pin<&mut NativePalette>) {
193 let scl = self_.style_change_listener.get();
194 cpp!(unsafe [scl as "PaletteStyleChangeListener*"] { delete scl; });
195 self_.style_change_listener.set(core::ptr::null());
196}