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 unsafe {
20 let user_data = lvgl::lv_obj_get_user_data(self.window) as *mut UserData;
21
22 let _user_data = Box::from_raw(user_data);
23
24 lvgl::lv_obj_delete(self.window);
25 }
26 }
27}
28
29unsafe extern "C" fn event_callback(event: *mut lvgl::lv_event_t) {
30 unsafe {
31 let code = lvgl::lv_event_get_code(event);
32
33 let queue = lvgl::lv_event_get_user_data(event) as *mut VecDeque<Event>;
34
35 let target = lvgl::lv_event_get_target(event) as *mut lvgl::lv_obj_t;
36
37 match code {
38 lvgl::lv_event_code_t_LV_EVENT_CHILD_CREATED => {
39 lvgl::lv_obj_add_flag(target, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE);
40
41 (*queue).push_back(Event::new(EventKind::ChildCreated, target, None));
42 }
43 lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN
44 | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_BEGIN
45 | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_END
46 | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST
47 | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST_BEGIN
48 | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST_END
49 | lvgl::lv_event_code_t_LV_EVENT_GET_SELF_SIZE
50 | lvgl::lv_event_code_t_LV_EVENT_COVER_CHECK => {
51 }
53 lvgl::lv_event_code_t_LV_EVENT_KEY => {
54 let key = lvgl::lv_indev_get_key(lvgl::lv_indev_active());
55
56 (*queue).push_back(Event::new(EventKind::Key, target, Some(key.into())));
57 }
58 _ => {
59 (*queue).push_back(Event::new(EventKind::from_lvgl_code(code), target, None));
60 }
61 }
62 }
63}
64
65impl Window {
66 pub unsafe fn new(parent_object: *mut lvgl::lv_obj_t) -> Result<Self> {
81 let window = unsafe { lvgl::lv_obj_create(parent_object) };
82
83 if window.is_null() {
84 return Err(Error::FailedToCreateObject);
85 }
86
87 let user_data = UserData {
88 queue: VecDeque::with_capacity(10),
89 icon_text: [b'I', b'c'],
90 icon_color: Color::BLACK,
91 };
92
93 let mut user_data = Box::new(user_data);
94
95 unsafe {
96 lvgl::lv_obj_add_event_cb(
98 window,
99 Some(event_callback),
100 lvgl::lv_event_code_t_LV_EVENT_ALL,
101 &mut user_data.queue as *mut _ as *mut core::ffi::c_void,
102 );
103 lvgl::lv_obj_add_flag(window, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE);
104 lvgl::lv_obj_set_user_data(window, Box::into_raw(user_data) as *mut core::ffi::c_void);
105 lvgl::lv_obj_set_size(window, lvgl::lv_pct(100), lvgl::lv_pct(100));
107 lvgl::lv_obj_set_style_border_width(window, 0, lvgl::LV_STATE_DEFAULT);
108 lvgl::lv_obj_set_style_radius(window, 0, lvgl::LV_STATE_DEFAULT);
109 }
110
111 Ok(Self { window })
112 }
113
114 pub fn get_identifier(&self) -> usize {
115 self.window as usize
116 }
117
118 pub fn peek_event(&self) -> Option<Event> {
119 let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData };
120
121 let user_data = unsafe { Box::from_raw(user_data) };
122
123 let event = user_data.queue.front().cloned();
124
125 forget(user_data);
126
127 event
128 }
129
130 pub fn pop_event(&mut self) -> Option<Event> {
131 let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData };
132
133 let mut user_data = unsafe { Box::from_raw(user_data) };
134
135 let event = user_data.queue.pop_front();
136
137 forget(user_data);
138
139 event
140 }
141
142 pub fn get_object(&self) -> *mut lvgl::lv_obj_t {
143 self.window
144 }
145
146 pub fn get_icon(&self) -> (&str, Color) {
147 let user_data = unsafe {
148 let user_data = lvgl::lv_obj_get_user_data(self.window) as *mut UserData;
149
150 &*user_data
151 };
152
153 unsafe {
154 (
155 str::from_utf8_unchecked(&user_data.icon_text),
156 user_data.icon_color,
157 )
158 }
159 }
160
161 pub fn set_icon(&mut self, icon_string: &str, icon_color: Color) {
162 let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData };
163
164 let user_data = unsafe { &mut *user_data };
165
166 let mut iterator = icon_string.chars();
167
168 if let Some(character) = iterator.next() {
169 user_data.icon_text[0] = character as u8;
170 }
171
172 if let Some(character) = iterator.next() {
173 user_data.icon_text[1] = character as u8;
174 }
175
176 user_data.icon_color = icon_color;
177 }
178
179 pub unsafe fn from_raw(window: *mut lvgl::lv_obj_t) -> Self {
190 Self { window }
191 }
192
193 pub fn into_raw(self) -> *mut lvgl::lv_obj_t {
194 let window = self.window;
195
196 forget(self);
197
198 window
199 }
200}