1 /**
2 * @file lv_disp.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_disp.h"
10 #include "../lv_misc/lv_math.h"
11 #include "../lv_core/lv_refr.h"
12
13 /*********************
14 * DEFINES
15 *********************/
16
17 /**********************
18 * TYPEDEFS
19 **********************/
20
21 /**********************
22 * STATIC PROTOTYPES
23 **********************/
24
25 #if LV_USE_ANIMATION
26 static void scr_load_anim_start(lv_anim_t * a);
27 static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v);
28 static void scr_anim_ready(lv_anim_t * a);
29 #endif
30
31 /**********************
32 * STATIC VARIABLES
33 **********************/
34
35 /**********************
36 * MACROS
37 **********************/
38
39 /**********************
40 * GLOBAL FUNCTIONS
41 **********************/
42
43 /**
44 * Return with a pointer to the active screen
45 * @param disp pointer to display which active screen should be get. (NULL to use the default
46 * screen)
47 * @return pointer to the active screen object (loaded by 'lv_scr_load()')
48 */
lv_disp_get_scr_act(lv_disp_t * disp)49 lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp)
50 {
51 if(!disp) disp = lv_disp_get_default();
52 if(!disp) {
53 LV_LOG_WARN("no display registered to get its active screen");
54 return NULL;
55 }
56
57 return disp->act_scr;
58 }
59
60 /**
61 * Return with a pointer to the previous screen. Only used during screen transitions.
62 * @param disp pointer to display which previous screen should be get. (NULL to use the default
63 * screen)
64 * @return pointer to the previous screen object or NULL if not used now
65 */
lv_disp_get_scr_prev(lv_disp_t * disp)66 lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp)
67 {
68 if(!disp) disp = lv_disp_get_default();
69 if(!disp) {
70 LV_LOG_WARN("no display registered to get its previous screen");
71 return NULL;
72 }
73
74 return disp->prev_scr;
75 }
76
77 /**
78 * Make a screen active
79 * @param scr pointer to a screen
80 */
lv_disp_load_scr(lv_obj_t * scr)81 void lv_disp_load_scr(lv_obj_t * scr)
82 {
83 lv_disp_t * d = lv_obj_get_disp(scr);
84 if(!d) return; /*Shouldn't happen, just to be sure*/
85 d->act_scr = scr;
86
87 lv_obj_invalidate(scr);
88 }
89
90 /**
91 * Return with the top layer. (Same on every screen and it is above the normal screen layer)
92 * @param disp pointer to display which top layer should be get. (NULL to use the default screen)
93 * @return pointer to the top layer object (transparent screen sized lv_obj)
94 */
lv_disp_get_layer_top(lv_disp_t * disp)95 lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp)
96 {
97 if(!disp) disp = lv_disp_get_default();
98 if(!disp) {
99 LV_LOG_WARN("lv_layer_top: no display registered to get its top layer");
100 return NULL;
101 }
102
103 return disp->top_layer;
104 }
105
106 /**
107 * Return with the sys. layer. (Same on every screen and it is above the normal screen and the top
108 * layer)
109 * @param disp pointer to display which sys. layer should be get. (NULL to use the default screen)
110 * @return pointer to the sys layer object (transparent screen sized lv_obj)
111 */
lv_disp_get_layer_sys(lv_disp_t * disp)112 lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp)
113 {
114 if(!disp) disp = lv_disp_get_default();
115 if(!disp) {
116 LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer");
117 return NULL;
118 }
119
120 return disp->sys_layer;
121 }
122
123 /**
124 * Assign a screen to a display.
125 * @param disp pointer to a display where to assign the screen
126 * @param scr pointer to a screen object to assign
127 */
lv_disp_assign_screen(lv_disp_t * disp,lv_obj_t * scr)128 void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr)
129 {
130 if(lv_obj_get_parent(scr) != NULL) {
131 LV_LOG_WARN("lv_disp_assign_screen: try to assign a non-screen object");
132 return;
133 }
134
135 lv_disp_t * old_disp = lv_obj_get_disp(scr);
136
137 if(old_disp == disp) return;
138
139 _lv_ll_chg_list(&old_disp->scr_ll, &disp->scr_ll, scr, true);
140 }
141
142 /**
143 * Set the background color of a display
144 * @param disp pointer to a display
145 * @param color color of the background
146 */
lv_disp_set_bg_color(lv_disp_t * disp,lv_color_t color)147 void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color)
148 {
149 if(!disp) disp = lv_disp_get_default();
150 if(!disp) {
151 LV_LOG_WARN("no display registered");
152 return;
153 }
154
155 disp->bg_color = color;
156
157 lv_area_t a;
158 lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
159 _lv_inv_area(disp, &a);
160
161 }
162
163 /**
164 * Set the background image of a display
165 * @param disp pointer to a display
166 * @param img_src path to file or pointer to an `lv_img_dsc_t` variable
167 */
lv_disp_set_bg_image(lv_disp_t * disp,const void * img_src)168 void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src)
169 {
170 if(!disp) disp = lv_disp_get_default();
171 if(!disp) {
172 LV_LOG_WARN("no display registered");
173 return;
174 }
175
176 disp->bg_img = img_src;
177
178 lv_area_t a;
179 lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
180 _lv_inv_area(disp, &a);
181 }
182
183
184 /**
185 * Opacity of the background
186 * @param disp pointer to a display
187 * @param opa opacity (0..255)
188 */
lv_disp_set_bg_opa(lv_disp_t * disp,lv_opa_t opa)189 void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa)
190 {
191 if(!disp) disp = lv_disp_get_default();
192 if(!disp) {
193 LV_LOG_WARN("no display registered");
194 return;
195 }
196
197 disp->bg_opa = opa;
198
199 lv_area_t a;
200 lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
201 _lv_inv_area(disp, &a);
202 }
203
204 #if LV_USE_ANIMATION
205
206 /**
207 * Switch screen with animation
208 * @param scr pointer to the new screen to load
209 * @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
210 * @param time time of the animation
211 * @param delay delay before the transition
212 * @param auto_del true: automatically delete the old screen
213 */
lv_scr_load_anim(lv_obj_t * new_scr,lv_scr_load_anim_t anim_type,uint32_t time,uint32_t delay,bool auto_del)214 void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del)
215 {
216 lv_disp_t * d = lv_obj_get_disp(new_scr);
217
218 if(d->prev_scr && d->del_prev) {
219 lv_obj_del(d->prev_scr);
220 d->prev_scr = NULL;
221 }
222
223 d->del_prev = auto_del;
224
225 /*Be sure there is no other animation on the screens*/
226 lv_anim_del(new_scr, NULL);
227 lv_anim_del(lv_scr_act(), NULL);
228
229 /*Be sure both screens are in a normal position*/
230 lv_obj_set_pos(new_scr, 0, 0);
231 lv_obj_set_pos(lv_scr_act(), 0, 0);
232 lv_style_remove_prop(lv_obj_get_local_style(new_scr, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE);
233 lv_style_remove_prop(lv_obj_get_local_style(lv_scr_act(), LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE);
234
235 lv_anim_t a_new;
236 lv_anim_init(&a_new);
237 lv_anim_set_var(&a_new, new_scr);
238 lv_anim_set_start_cb(&a_new, scr_load_anim_start);
239 lv_anim_set_ready_cb(&a_new, scr_anim_ready);
240 lv_anim_set_time(&a_new, time);
241 lv_anim_set_delay(&a_new, delay);
242
243 lv_anim_t a_old;
244 lv_anim_init(&a_old);
245 lv_anim_set_var(&a_old, d->act_scr);
246 lv_anim_set_time(&a_old, time);
247 lv_anim_set_delay(&a_old, delay);
248
249 switch(anim_type) {
250 case LV_SCR_LOAD_ANIM_NONE:
251 /* Create a dummy animation to apply the delay*/
252 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
253 lv_anim_set_values(&a_new, 0, 0);
254 break;
255 case LV_SCR_LOAD_ANIM_OVER_LEFT:
256 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
257 lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
258 break;
259 case LV_SCR_LOAD_ANIM_OVER_RIGHT:
260 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
261 lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
262 break;
263 case LV_SCR_LOAD_ANIM_OVER_TOP:
264 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
265 lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
266 break;
267 case LV_SCR_LOAD_ANIM_OVER_BOTTOM:
268 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
269 lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
270 break;
271 case LV_SCR_LOAD_ANIM_MOVE_LEFT:
272 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
273 lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
274
275 lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_x);
276 lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
277 break;
278 case LV_SCR_LOAD_ANIM_MOVE_RIGHT:
279 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
280 lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
281
282 lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_x);
283 lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
284 break;
285 case LV_SCR_LOAD_ANIM_MOVE_TOP:
286 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
287 lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
288
289 lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_y);
290 lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
291 break;
292 case LV_SCR_LOAD_ANIM_MOVE_BOTTOM:
293 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
294 lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
295
296 lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_y);
297 lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
298 break;
299
300 case LV_SCR_LOAD_ANIM_FADE_ON:
301 lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) opa_scale_anim);
302 lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER);
303 break;
304 }
305
306 lv_anim_start(&a_new);
307 lv_anim_start(&a_old);
308 }
309
310 #endif
311
312 /**
313 * Get elapsed time since last user activity on a display (e.g. click)
314 * @param disp pointer to an display (NULL to get the overall smallest inactivity)
315 * @return elapsed ticks (milliseconds) since the last activity
316 */
lv_disp_get_inactive_time(const lv_disp_t * disp)317 uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp)
318 {
319 if(!disp) disp = lv_disp_get_default();
320 if(!disp) {
321 LV_LOG_WARN("lv_disp_get_inactive_time: no display registered");
322 return 0;
323 }
324
325 if(disp) return lv_tick_elaps(disp->last_activity_time);
326
327 lv_disp_t * d;
328 uint32_t t = UINT32_MAX;
329 d = lv_disp_get_next(NULL);
330 while(d) {
331 uint32_t elaps = lv_tick_elaps(d->last_activity_time);
332 t = LV_MATH_MIN(t, elaps);
333 d = lv_disp_get_next(d);
334 }
335
336 return t;
337 }
338
339 /**
340 * Manually trigger an activity on a display
341 * @param disp pointer to an display (NULL to use the default display)
342 */
lv_disp_trig_activity(lv_disp_t * disp)343 void lv_disp_trig_activity(lv_disp_t * disp)
344 {
345 if(!disp) disp = lv_disp_get_default();
346 if(!disp) {
347 LV_LOG_WARN("lv_disp_trig_activity: no display registered");
348 return;
349 }
350
351 disp->last_activity_time = lv_tick_get();
352 }
353
354 /**
355 * Clean any CPU cache that is related to the display.
356 * @param disp pointer to an display (NULL to use the default display)
357 */
lv_disp_clean_dcache(lv_disp_t * disp)358 void lv_disp_clean_dcache(lv_disp_t * disp)
359 {
360 if(!disp) disp = lv_disp_get_default();
361 if(!disp) {
362 LV_LOG_WARN("lv_disp_clean_dcache: no display registered");
363 return;
364 }
365
366 if(disp->driver.clean_dcache_cb)
367 disp->driver.clean_dcache_cb(&disp->driver);
368 }
369
370 /**
371 * Get a pointer to the screen refresher task to
372 * modify its parameters with `lv_task_...` functions.
373 * @param disp pointer to a display
374 * @return pointer to the display refresher task. (NULL on error)
375 */
_lv_disp_get_refr_task(lv_disp_t * disp)376 lv_task_t * _lv_disp_get_refr_task(lv_disp_t * disp)
377 {
378 if(!disp) disp = lv_disp_get_default();
379 if(!disp) {
380 LV_LOG_WARN("lv_disp_get_refr_task: no display registered");
381 return NULL;
382 }
383
384 return disp->refr_task;
385 }
386
387 /**********************
388 * STATIC FUNCTIONS
389 **********************/
390
391 #if LV_USE_ANIMATION
scr_load_anim_start(lv_anim_t * a)392 static void scr_load_anim_start(lv_anim_t * a)
393 {
394 lv_disp_t * d = lv_obj_get_disp(a->var);
395 d->prev_scr = lv_scr_act();
396
397 lv_disp_load_scr(a->var);
398 }
399
opa_scale_anim(lv_obj_t * obj,lv_anim_value_t v)400 static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v)
401 {
402 lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, v);
403 }
404
405
scr_anim_ready(lv_anim_t * a)406 static void scr_anim_ready(lv_anim_t * a)
407 {
408 lv_disp_t * d = lv_obj_get_disp(a->var);
409
410 if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr);
411 d->prev_scr = NULL;
412 lv_style_remove_prop(lv_obj_get_local_style(a->var, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE);
413 }
414 #endif
415