1use super::lvgl;
2use crate::{Color, Error, EventKind, Result, event::Event};
3use alloc::boxed::Box;
4use alloc::collections::VecDeque;
5use core::{mem::forget, str};
6
7struct UserData {
8 pub queue: VecDeque<Event>,
9 pub icon_text: [u8; 2],
10 pub icon_color: Color,
11}
12
13pub struct Window {
14 window: *mut lvgl::lv_obj_t,
15}
16
17impl Drop for Window {
18 fn drop(&mut self) {
19 if !self.is_valid() {
20 return;
21 }
22
23 unsafe {
24 let user_data = lvgl::lv_obj_get_user_data(self.window) as *mut UserData;
25
26 let _user_data = Box::from_raw(user_data);
27
28 lvgl::lv_obj_delete(self.window);
29 }
30 }
31}
32
33unsafe extern "C" fn event_callback(event: *mut lvgl::lv_event_t) {
34 unsafe {
35 let code = lvgl::lv_event_get_code(event);
36
37 let queue = lvgl::lv_event_get_user_data(event) as *mut VecDeque<Event>;
38
39 let target = lvgl::lv_event_get_target(event) as *mut lvgl::lv_obj_t;
40
41 match code {
42 lvgl::lv_event_code_t_LV_EVENT_CHILD_CREATED => {
43 lvgl::lv_obj_add_flag(target, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE);
44
45 (*queue).push_back(Event::new(EventKind::ChildCreated, target, None));
46 }
47 lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN
48 | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_BEGIN
49 | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_END
50 | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST
51 | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST_BEGIN
52 | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST_END
53 | lvgl::lv_event_code_t_LV_EVENT_GET_SELF_SIZE
54 | lvgl::lv_event_code_t_LV_EVENT_COVER_CHECK => {
55 }
57 lvgl::lv_event_code_t_LV_EVENT_KEY => {
58 let key = lvgl::lv_indev_get_key(lvgl::lv_indev_active());
59
60 (*queue).push_back(Event::new(EventKind::Key, target, Some(key.into())));
61 }
62 _ => {
63 (*queue).push_back(Event::new(EventKind::from_lvgl_code(code), target, None));
64 }
65 }
66 }
67}
68
69impl Window {
70 fn is_valid(&self) -> bool {
71 unsafe { lvgl::lv_obj_is_valid(self.window) }
72 }
73
74 pub unsafe fn new(parent_object: *mut lvgl::lv_obj_t) -> Result<Self> {
89 let window = unsafe { lvgl::lv_obj_create(parent_object) };
90
91 if window.is_null() {
92 return Err(Error::FailedToCreateObject);
93 }
94
95 let user_data = UserData {
96 queue: VecDeque::with_capacity(10),
97 icon_text: [b'I', b'c'],
98 icon_color: Color::BLACK,
99 };
100
101 let mut user_data = Box::new(user_data);
102
103 unsafe {
104 lvgl::lv_obj_add_event_cb(
106 window,
107 Some(event_callback),
108 lvgl::lv_event_code_t_LV_EVENT_ALL,
109 &mut user_data.queue as *mut _ as *mut core::ffi::c_void,
110 );
111 lvgl::lv_obj_add_flag(window, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE);
112 lvgl::lv_obj_set_user_data(window, Box::into_raw(user_data) as *mut core::ffi::c_void);
113 lvgl::lv_obj_set_size(window, lvgl::lv_pct(100), lvgl::lv_pct(100));
115 lvgl::lv_obj_set_style_border_width(window, 0, lvgl::LV_STATE_DEFAULT);
116 lvgl::lv_obj_set_style_radius(window, 0, lvgl::LV_STATE_DEFAULT);
117 }
118
119 Ok(Self { window })
120 }
121
122 pub fn get_identifier(&self) -> usize {
123 self.window as usize
124 }
125
126 pub fn peek_event(&self) -> Option<Event> {
127 if !self.is_valid() {
128 return None;
129 }
130
131 let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData };
132
133 let user_data = unsafe { Box::from_raw(user_data) };
134
135 let event = user_data.queue.front().cloned();
136
137 forget(user_data);
138
139 event
140 }
141
142 pub fn pop_event(&mut self) -> Option<Event> {
143 if !self.is_valid() {
144 return None;
145 }
146
147 let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData };
148
149 let mut user_data = unsafe { Box::from_raw(user_data) };
150
151 let event = user_data.queue.pop_front();
152
153 forget(user_data);
154
155 event
156 }
157
158 pub fn get_object(&self) -> *mut lvgl::lv_obj_t {
159 self.window
160 }
161
162 pub fn get_icon(&self) -> (&str, Color) {
163 let user_data = unsafe {
164 let user_data = lvgl::lv_obj_get_user_data(self.window) as *mut UserData;
165
166 &*user_data
167 };
168
169 unsafe {
170 (
171 str::from_utf8_unchecked(&user_data.icon_text),
172 user_data.icon_color,
173 )
174 }
175 }
176
177 pub fn set_icon(&mut self, icon_string: &str, icon_color: Color) {
178 let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData };
179
180 let user_data = unsafe { &mut *user_data };
181
182 let mut iterator = icon_string.chars();
183
184 if let Some(character) = iterator.next() {
185 user_data.icon_text[0] = character as u8;
186 }
187
188 if let Some(character) = iterator.next() {
189 user_data.icon_text[1] = character as u8;
190 }
191
192 user_data.icon_color = icon_color;
193 }
194
195 pub unsafe fn from_raw(window: *mut lvgl::lv_obj_t) -> Self {
206 Self { window }
207 }
208
209 pub fn into_raw(self) -> *mut lvgl::lv_obj_t {
210 let window = self.window;
211
212 forget(self);
213
214 window
215 }
216}