1 /**
2  * @file lv_disp.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "../display/lv_display_private.h"
10 #include "../misc/lv_event_private.h"
11 #include "../misc/lv_anim_private.h"
12 #include "../draw/lv_draw_private.h"
13 #include "../core/lv_obj_private.h"
14 #include "lv_display.h"
15 #include "../misc/lv_math.h"
16 #include "../core/lv_refr_private.h"
17 #include "../stdlib/lv_string.h"
18 #include "../themes/lv_theme.h"
19 #include "../core/lv_global.h"
20 #include "../others/sysmon/lv_sysmon.h"
21 
22 #if LV_USE_DRAW_SW
23     #include "../draw/sw/lv_draw_sw.h"
24 #endif
25 
26 /*********************
27  *      DEFINES
28  *********************/
29 #define disp_def LV_GLOBAL_DEFAULT()->disp_default
30 #define disp_ll_p &(LV_GLOBAL_DEFAULT()->disp_ll)
31 
32 /**********************
33  *      TYPEDEFS
34  **********************/
35 
36 /**********************
37  *  STATIC PROTOTYPES
38  **********************/
39 static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data);
40 static void update_resolution(lv_display_t * disp);
41 static void scr_load_internal(lv_obj_t * scr);
42 static void scr_load_anim_start(lv_anim_t * a);
43 static void opa_scale_anim(void * obj, int32_t v);
44 static void set_x_anim(void * obj, int32_t v);
45 static void set_y_anim(void * obj, int32_t v);
46 static void scr_anim_completed(lv_anim_t * a);
47 static bool is_out_anim(lv_screen_load_anim_t a);
48 static void disp_event_cb(lv_event_t * e);
49 
50 /**********************
51  *  STATIC VARIABLES
52  **********************/
53 
54 /**********************
55  *      MACROS
56  **********************/
57 
58 /**********************
59  *   GLOBAL FUNCTIONS
60  **********************/
61 
lv_display_create(int32_t hor_res,int32_t ver_res)62 lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res)
63 {
64     lv_display_t * disp = lv_ll_ins_head(disp_ll_p);
65     LV_ASSERT_MALLOC(disp);
66     if(!disp) return NULL;
67 
68     lv_memzero(disp, sizeof(lv_display_t));
69 
70     disp->hor_res          = hor_res;
71     disp->ver_res          = ver_res;
72     disp->physical_hor_res = -1;
73     disp->physical_ver_res = -1;
74     disp->offset_x         = 0;
75     disp->offset_y         = 0;
76     disp->antialiasing     = LV_COLOR_DEPTH > 8 ? 1 : 0;
77     disp->dpi              = LV_DPI_DEF;
78     disp->color_format = LV_COLOR_FORMAT_NATIVE;
79 
80 
81 #if defined(LV_DRAW_SW_DRAW_UNIT_CNT) && (LV_DRAW_SW_DRAW_UNIT_CNT != 0)
82     disp->tile_cnt = LV_DRAW_SW_DRAW_UNIT_CNT;
83 #else
84     disp->tile_cnt = 1;
85 #endif
86 
87     disp->layer_head = lv_malloc(sizeof(lv_layer_t));
88     LV_ASSERT_MALLOC(disp->layer_head);
89     if(disp->layer_head == NULL) return NULL;
90     lv_layer_init(disp->layer_head);
91 
92     if(disp->layer_init) disp->layer_init(disp, disp->layer_head);
93     disp->layer_head->buf_area.x1 = 0;
94     disp->layer_head->buf_area.y1 = 0;
95     disp->layer_head->buf_area.x2 = hor_res - 1;
96     disp->layer_head->buf_area.y2 = ver_res - 1;
97     disp->layer_head->color_format = disp->color_format;
98 
99     disp->inv_en_cnt = 1;
100     disp->last_activity_time = lv_tick_get();
101 
102     lv_ll_init(&disp->sync_areas, sizeof(lv_area_t));
103 
104     lv_display_t * disp_def_tmp = disp_def;
105     disp_def                 = disp; /*Temporarily change the default screen to create the default screens on the
106                                         new display*/
107     /*Create a refresh timer*/
108     disp->refr_timer = lv_timer_create(lv_display_refr_timer, LV_DEF_REFR_PERIOD, disp);
109     LV_ASSERT_MALLOC(disp->refr_timer);
110     if(disp->refr_timer == NULL) {
111         lv_free(disp);
112         return NULL;
113     }
114 
115 #if LV_USE_THEME_DEFAULT
116     if(lv_theme_default_is_inited() == false) {
117         disp->theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
118                                             LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT);
119     }
120     else {
121         disp->theme = lv_theme_default_get();
122     }
123 #elif LV_USE_THEME_SIMPLE
124     if(lv_theme_simple_is_inited() == false) {
125         disp->theme = lv_theme_simple_init(disp);
126     }
127     else {
128         disp->theme = lv_theme_simple_get();
129     }
130 #endif
131 
132     disp->bottom_layer = lv_obj_create(NULL); /*Create bottom layer on the display*/
133     disp->act_scr   = lv_obj_create(NULL); /*Create a default screen on the display*/
134     disp->top_layer = lv_obj_create(NULL); /*Create top layer on the display*/
135     disp->sys_layer = lv_obj_create(NULL); /*Create sys layer on the display*/
136     lv_obj_remove_style_all(disp->bottom_layer);
137     lv_obj_remove_style_all(disp->top_layer);
138     lv_obj_remove_style_all(disp->sys_layer);
139     lv_obj_remove_flag(disp->top_layer, LV_OBJ_FLAG_CLICKABLE);
140     lv_obj_remove_flag(disp->sys_layer, LV_OBJ_FLAG_CLICKABLE);
141 
142     lv_obj_set_scrollbar_mode(disp->bottom_layer, LV_SCROLLBAR_MODE_OFF);
143     lv_obj_set_scrollbar_mode(disp->top_layer, LV_SCROLLBAR_MODE_OFF);
144     lv_obj_set_scrollbar_mode(disp->sys_layer, LV_SCROLLBAR_MODE_OFF);
145 
146     lv_obj_invalidate(disp->act_scr);
147 
148     disp_def = disp_def_tmp; /*Revert the default display*/
149     if(disp_def == NULL) disp_def = disp; /*Initialize the default display*/
150 
151     lv_display_add_event_cb(disp, disp_event_cb, LV_EVENT_REFR_REQUEST, NULL);
152 
153     lv_timer_ready(disp->refr_timer); /*Be sure the screen will be refreshed immediately on start up*/
154 
155 #if LV_USE_PERF_MONITOR
156     lv_sysmon_show_performance(disp);
157 #endif
158 
159 #if LV_USE_MEM_MONITOR
160     lv_sysmon_show_memory(disp);
161 #endif
162 
163     return disp;
164 }
165 
lv_display_delete(lv_display_t * disp)166 void lv_display_delete(lv_display_t * disp)
167 {
168     bool was_default = false;
169     bool was_refr = false;
170     if(disp == lv_display_get_default()) was_default = true;
171     if(disp == lv_refr_get_disp_refreshing()) was_refr = true;
172 
173     lv_display_send_event(disp, LV_EVENT_DELETE, NULL);
174     lv_event_remove_all(&(disp->event_list));
175 
176     /*Detach the input devices*/
177     lv_indev_t * indev;
178     indev = lv_indev_get_next(NULL);
179     while(indev) {
180         if(lv_indev_get_display(indev) == disp) {
181             lv_indev_set_display(indev, NULL);
182         }
183         indev = lv_indev_get_next(indev);
184     }
185 
186     /* Delete screen and other obj */
187     if(disp->sys_layer) {
188         lv_obj_delete(disp->sys_layer);
189         disp->sys_layer = NULL;
190     }
191     if(disp->top_layer) {
192         lv_obj_delete(disp->top_layer);
193         disp->top_layer = NULL;
194     }
195 
196     if(disp->bottom_layer) {
197         lv_obj_delete(disp->bottom_layer);
198         disp->bottom_layer = NULL;
199     }
200 
201     disp->act_scr = NULL;
202 
203     while(disp->screen_cnt != 0) {
204         /*Delete the screens*/
205         lv_obj_delete(disp->screens[0]);
206     }
207 
208     lv_ll_clear(&disp->sync_areas);
209     lv_ll_remove(disp_ll_p, disp);
210     if(disp->refr_timer) lv_timer_delete(disp->refr_timer);
211 
212     if(disp->layer_deinit) disp->layer_deinit(disp, disp->layer_head);
213     lv_free(disp->layer_head);
214 
215     lv_free(disp);
216 
217     if(was_default) lv_display_set_default(lv_ll_get_head(disp_ll_p));
218 
219     if(was_refr) lv_refr_set_disp_refreshing(NULL);
220 }
221 
lv_display_set_default(lv_display_t * disp)222 void lv_display_set_default(lv_display_t * disp)
223 {
224     disp_def = disp;
225 }
226 
lv_display_get_default(void)227 lv_display_t * lv_display_get_default(void)
228 {
229     return disp_def;
230 }
231 
lv_display_get_next(lv_display_t * disp)232 lv_display_t * lv_display_get_next(lv_display_t * disp)
233 {
234     if(disp == NULL)
235         return lv_ll_get_head(disp_ll_p);
236     else
237         return lv_ll_get_next(disp_ll_p, disp);
238 }
239 
240 /*---------------------
241  * RESOLUTION
242  *--------------------*/
243 
lv_display_set_resolution(lv_display_t * disp,int32_t hor_res,int32_t ver_res)244 void lv_display_set_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res)
245 {
246     if(disp == NULL) disp = lv_display_get_default();
247     if(disp == NULL) return;
248 
249     if(disp->hor_res == hor_res && disp->ver_res == ver_res) return;
250 
251     disp->hor_res = hor_res;
252     disp->ver_res = ver_res;
253 
254     update_resolution(disp);
255 }
256 
lv_display_set_physical_resolution(lv_display_t * disp,int32_t hor_res,int32_t ver_res)257 void lv_display_set_physical_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res)
258 {
259     if(disp == NULL) disp = lv_display_get_default();
260     if(disp == NULL) return;
261 
262     disp->physical_hor_res = hor_res;
263     disp->physical_ver_res = ver_res;
264 
265     lv_obj_invalidate(disp->sys_layer);
266 
267 }
268 
lv_display_set_offset(lv_display_t * disp,int32_t x,int32_t y)269 void lv_display_set_offset(lv_display_t * disp, int32_t x, int32_t y)
270 {
271     if(disp == NULL) disp = lv_display_get_default();
272     if(disp == NULL) return;
273 
274     disp->offset_x = x;
275     disp->offset_y = y;
276 
277     lv_obj_invalidate(disp->sys_layer);
278 
279 }
280 
lv_display_set_dpi(lv_display_t * disp,int32_t dpi)281 void lv_display_set_dpi(lv_display_t * disp, int32_t dpi)
282 {
283     if(disp == NULL) disp = lv_display_get_default();
284     if(disp == NULL) return;
285 
286     disp->dpi = dpi;
287 }
288 
lv_display_get_horizontal_resolution(const lv_display_t * disp)289 int32_t lv_display_get_horizontal_resolution(const lv_display_t * disp)
290 {
291     if(disp == NULL) disp = lv_display_get_default();
292 
293     if(disp == NULL) {
294         return 0;
295     }
296     else {
297         switch(disp->rotation) {
298             case LV_DISPLAY_ROTATION_90:
299             case LV_DISPLAY_ROTATION_270:
300                 return disp->ver_res;
301             default:
302                 return disp->hor_res;
303         }
304     }
305 }
306 
lv_display_get_vertical_resolution(const lv_display_t * disp)307 int32_t lv_display_get_vertical_resolution(const lv_display_t * disp)
308 {
309     if(disp == NULL) disp = lv_display_get_default();
310 
311     if(disp == NULL) {
312         return 0;
313     }
314     else {
315         switch(disp->rotation) {
316             case LV_DISPLAY_ROTATION_90:
317             case LV_DISPLAY_ROTATION_270:
318                 return disp->hor_res;
319             default:
320                 return disp->ver_res;
321         }
322     }
323 }
324 
lv_display_get_physical_horizontal_resolution(const lv_display_t * disp)325 int32_t lv_display_get_physical_horizontal_resolution(const lv_display_t * disp)
326 {
327     if(disp == NULL) disp = lv_display_get_default();
328 
329     if(disp == NULL) {
330         return 0;
331     }
332     else {
333         switch(disp->rotation) {
334             case LV_DISPLAY_ROTATION_90:
335             case LV_DISPLAY_ROTATION_270:
336                 return disp->physical_ver_res > 0 ? disp->physical_ver_res : disp->ver_res;
337             default:
338                 return disp->physical_hor_res > 0 ? disp->physical_hor_res : disp->hor_res;
339         }
340     }
341 }
342 
lv_display_get_physical_vertical_resolution(const lv_display_t * disp)343 int32_t lv_display_get_physical_vertical_resolution(const lv_display_t * disp)
344 {
345     if(disp == NULL) disp = lv_display_get_default();
346 
347     if(disp == NULL) {
348         return 0;
349     }
350     else {
351         switch(disp->rotation) {
352             case LV_DISPLAY_ROTATION_90:
353             case LV_DISPLAY_ROTATION_270:
354                 return disp->physical_hor_res > 0 ? disp->physical_hor_res : disp->hor_res;
355             default:
356                 return disp->physical_ver_res > 0 ? disp->physical_ver_res : disp->ver_res;
357         }
358     }
359 }
360 
lv_display_get_offset_x(const lv_display_t * disp)361 int32_t lv_display_get_offset_x(const lv_display_t * disp)
362 {
363     if(disp == NULL) disp = lv_display_get_default();
364 
365     if(disp == NULL) {
366         return 0;
367     }
368     else {
369         switch(disp->rotation) {
370             case LV_DISPLAY_ROTATION_90:
371                 return disp->offset_y;
372             case LV_DISPLAY_ROTATION_180:
373                 return lv_display_get_physical_horizontal_resolution(disp) - disp->offset_x;
374             case LV_DISPLAY_ROTATION_270:
375                 return lv_display_get_physical_horizontal_resolution(disp) - disp->offset_y;
376             default:
377                 return disp->offset_x;
378         }
379     }
380 }
381 
lv_display_get_offset_y(const lv_display_t * disp)382 int32_t lv_display_get_offset_y(const lv_display_t * disp)
383 {
384     if(disp == NULL) disp = lv_display_get_default();
385 
386     if(disp == NULL) {
387         return 0;
388     }
389     else {
390         switch(disp->rotation) {
391             case LV_DISPLAY_ROTATION_90:
392                 return disp->offset_x;
393             case LV_DISPLAY_ROTATION_180:
394                 return lv_display_get_physical_vertical_resolution(disp) - disp->offset_y;
395             case LV_DISPLAY_ROTATION_270:
396                 return lv_display_get_physical_vertical_resolution(disp) - disp->offset_x;
397             default:
398                 return disp->offset_y;
399         }
400     }
401 }
402 
lv_display_get_dpi(const lv_display_t * disp)403 int32_t lv_display_get_dpi(const lv_display_t * disp)
404 {
405     if(disp == NULL) disp = lv_display_get_default();
406     if(disp == NULL) return LV_DPI_DEF;  /*Do not return 0 because it might be a divider*/
407     return disp->dpi;
408 }
409 
410 /*---------------------
411  * BUFFERING
412  *--------------------*/
413 
lv_display_set_draw_buffers(lv_display_t * disp,lv_draw_buf_t * buf1,lv_draw_buf_t * buf2)414 void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2)
415 {
416     if(disp == NULL) disp = lv_display_get_default();
417     if(disp == NULL) return;
418 
419     disp->buf_1 = buf1;
420     disp->buf_2 = buf2;
421     disp->buf_act = disp->buf_1;
422 }
423 
lv_display_set_buffers(lv_display_t * disp,void * buf1,void * buf2,uint32_t buf_size,lv_display_render_mode_t render_mode)424 void lv_display_set_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size,
425                             lv_display_render_mode_t render_mode)
426 {
427     LV_ASSERT_MSG(buf1 != NULL, "Null buffer");
428     lv_color_format_t cf = lv_display_get_color_format(disp);
429     uint32_t w = lv_display_get_horizontal_resolution(disp);
430     uint32_t h = lv_display_get_vertical_resolution(disp);
431 
432     LV_ASSERT_MSG(w != 0 && h != 0, "display resolution is 0");
433 
434     /* buf1 or buf2 is not aligned according to LV_DRAW_BUF_ALIGN */
435     LV_ASSERT_FORMAT_MSG(buf1 == lv_draw_buf_align(buf1, cf), "buf1 is not aligned: %p", buf1);
436     LV_ASSERT_FORMAT_MSG(buf2 == NULL || buf2 == lv_draw_buf_align(buf2, cf), "buf2 is not aligned: %p", buf2);
437 
438     uint32_t stride = lv_draw_buf_width_to_stride(w, cf);
439     if(render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) {
440         /* for partial mode, we calculate the height based on the buf_size and stride */
441         h = buf_size / stride;
442         LV_ASSERT_MSG(h != 0, "the buffer is too small");
443     }
444     else {
445         LV_ASSERT_FORMAT_MSG(stride * h <= buf_size, "%s mode requires screen sized buffer(s)",
446                              render_mode == LV_DISPLAY_RENDER_MODE_FULL ? "FULL" : "DIRECT");
447     }
448 
449     lv_draw_buf_init(&disp->_static_buf1, w, h, cf, stride, buf1, buf_size);
450     lv_draw_buf_init(&disp->_static_buf2, w, h, cf, stride, buf2, buf_size);
451     lv_display_set_draw_buffers(disp, &disp->_static_buf1, buf2 ? &disp->_static_buf2 : NULL);
452     lv_display_set_render_mode(disp, render_mode);
453 }
454 
lv_display_set_buffers_with_stride(lv_display_t * disp,void * buf1,void * buf2,uint32_t buf_size,uint32_t stride,lv_display_render_mode_t render_mode)455 void lv_display_set_buffers_with_stride(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size,
456                                         uint32_t stride, lv_display_render_mode_t render_mode)
457 {
458     LV_ASSERT_MSG(buf1 != NULL, "Null buffer");
459     lv_color_format_t cf = lv_display_get_color_format(disp);
460     uint32_t w = lv_display_get_horizontal_resolution(disp);
461     uint32_t h = lv_display_get_vertical_resolution(disp);
462     LV_ASSERT_MSG(w != 0 && h != 0, "display resolution is 0");
463 
464     if(render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) {
465         /* for partial mode, we calculate the height based on the buf_size and stride */
466         h = buf_size / stride;
467         LV_ASSERT_MSG(h != 0, "the buffer is too small");
468     }
469     else {
470         LV_ASSERT_FORMAT_MSG(stride * h <= buf_size, "%s mode requires screen sized buffer(s)",
471                              render_mode == LV_DISPLAY_RENDER_MODE_FULL ? "FULL" : "DIRECT");
472     }
473 
474     lv_draw_buf_init(&disp->_static_buf1, w, h, cf, stride, buf1, buf_size);
475     lv_draw_buf_init(&disp->_static_buf2, w, h, cf, stride, buf2, buf_size);
476     lv_display_set_draw_buffers(disp, &disp->_static_buf1, buf2 ? &disp->_static_buf2 : NULL);
477     lv_display_set_render_mode(disp, render_mode);
478 }
479 
lv_display_set_render_mode(lv_display_t * disp,lv_display_render_mode_t render_mode)480 void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode)
481 {
482     if(disp == NULL) disp = lv_display_get_default();
483     if(disp == NULL) return;
484     disp->render_mode = render_mode;
485 }
486 
lv_display_set_flush_cb(lv_display_t * disp,lv_display_flush_cb_t flush_cb)487 void lv_display_set_flush_cb(lv_display_t * disp, lv_display_flush_cb_t flush_cb)
488 {
489     if(disp == NULL) disp = lv_display_get_default();
490     if(disp == NULL) return;
491 
492     disp->flush_cb = flush_cb;
493 }
494 
lv_display_set_flush_wait_cb(lv_display_t * disp,lv_display_flush_wait_cb_t wait_cb)495 void lv_display_set_flush_wait_cb(lv_display_t * disp, lv_display_flush_wait_cb_t wait_cb)
496 {
497     if(disp == NULL) disp = lv_display_get_default();
498     if(disp == NULL) return;
499 
500     disp->flush_wait_cb = wait_cb;
501 }
502 
lv_display_set_color_format(lv_display_t * disp,lv_color_format_t color_format)503 void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_format)
504 {
505     if(disp == NULL) disp = lv_display_get_default();
506     if(disp == NULL) return;
507 
508     disp->color_format = color_format;
509     disp->layer_head->color_format = color_format;
510     if(disp->buf_1) disp->buf_1->header.cf = color_format;
511     if(disp->buf_2) disp->buf_2->header.cf = color_format;
512 
513     lv_display_send_event(disp, LV_EVENT_COLOR_FORMAT_CHANGED, NULL);
514 }
515 
lv_display_get_color_format(lv_display_t * disp)516 lv_color_format_t lv_display_get_color_format(lv_display_t * disp)
517 {
518     if(disp == NULL) disp = lv_display_get_default();
519     if(disp == NULL) return LV_COLOR_FORMAT_UNKNOWN;
520 
521     return disp->color_format;
522 }
523 
lv_display_set_tile_cnt(lv_display_t * disp,uint32_t tile_cnt)524 void lv_display_set_tile_cnt(lv_display_t * disp, uint32_t tile_cnt)
525 {
526     LV_ASSERT_FORMAT_MSG(tile_cnt < 256, "tile_cnt must be smaller than 256 (%" LV_PRId32 " was used)", tile_cnt);
527 
528     if(disp == NULL) disp = lv_display_get_default();
529     if(disp == NULL) return;
530 
531     disp->tile_cnt = tile_cnt;
532 }
533 
lv_display_get_tile_cnt(lv_display_t * disp)534 uint32_t lv_display_get_tile_cnt(lv_display_t * disp)
535 {
536     if(disp == NULL) disp = lv_display_get_default();
537     if(disp == NULL) return 0;
538 
539     return disp->tile_cnt;
540 }
541 
lv_display_set_antialiasing(lv_display_t * disp,bool en)542 void lv_display_set_antialiasing(lv_display_t * disp, bool en)
543 {
544     if(disp == NULL) disp = lv_display_get_default();
545     if(disp == NULL) return;
546 
547     disp->antialiasing = en;
548 }
549 
lv_display_get_antialiasing(lv_display_t * disp)550 bool lv_display_get_antialiasing(lv_display_t * disp)
551 {
552     if(disp == NULL) disp = lv_display_get_default();
553     if(disp == NULL) return false;
554 
555     return disp->antialiasing;
556 }
557 
lv_display_flush_ready(lv_display_t * disp)558 LV_ATTRIBUTE_FLUSH_READY void lv_display_flush_ready(lv_display_t * disp)
559 {
560     disp->flushing = 0;
561 }
562 
lv_display_flush_is_last(lv_display_t * disp)563 LV_ATTRIBUTE_FLUSH_READY bool lv_display_flush_is_last(lv_display_t * disp)
564 {
565     return disp->flushing_last;
566 }
567 
lv_display_is_double_buffered(lv_display_t * disp)568 bool lv_display_is_double_buffered(lv_display_t * disp)
569 {
570     return disp->buf_2 != NULL;
571 }
572 
573 /*---------------------
574   * SCREENS
575   *--------------------*/
576 
lv_display_get_screen_active(lv_display_t * disp)577 lv_obj_t * lv_display_get_screen_active(lv_display_t * disp)
578 {
579     if(!disp) disp = lv_display_get_default();
580     if(!disp) {
581         LV_LOG_WARN("no display registered to get its active screen");
582         return NULL;
583     }
584 
585     return disp->act_scr;
586 }
587 
lv_display_get_screen_prev(lv_display_t * disp)588 lv_obj_t * lv_display_get_screen_prev(lv_display_t * disp)
589 {
590     if(!disp) disp = lv_display_get_default();
591     if(!disp) {
592         LV_LOG_WARN("no display registered to get its previous screen");
593         return NULL;
594     }
595 
596     return disp->prev_scr;
597 }
598 
lv_display_get_layer_top(lv_display_t * disp)599 lv_obj_t * lv_display_get_layer_top(lv_display_t * disp)
600 {
601     if(!disp) disp = lv_display_get_default();
602     if(!disp) {
603         LV_LOG_WARN("lv_layer_top: no display registered to get its top layer");
604         return NULL;
605     }
606 
607     return disp->top_layer;
608 }
609 
lv_display_get_layer_sys(lv_display_t * disp)610 lv_obj_t * lv_display_get_layer_sys(lv_display_t * disp)
611 {
612     if(!disp) disp = lv_display_get_default();
613     if(!disp) {
614         LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer");
615         return NULL;
616     }
617 
618     return disp->sys_layer;
619 }
620 
lv_display_get_layer_bottom(lv_display_t * disp)621 lv_obj_t * lv_display_get_layer_bottom(lv_display_t * disp)
622 {
623     if(!disp) disp = lv_display_get_default();
624     if(!disp) {
625         LV_LOG_WARN("lv_layer_bottom: no display registered to get its bottom layer");
626         return NULL;
627     }
628 
629     return disp->bottom_layer;
630 }
631 
lv_screen_load(struct _lv_obj_t * scr)632 void lv_screen_load(struct _lv_obj_t * scr)
633 {
634     lv_screen_load_anim(scr, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
635 }
636 
lv_screen_load_anim(lv_obj_t * new_scr,lv_screen_load_anim_t anim_type,uint32_t time,uint32_t delay,bool auto_del)637 void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, uint32_t time, uint32_t delay,
638                          bool auto_del)
639 {
640     lv_display_t * d = lv_obj_get_display(new_scr);
641     lv_obj_t * act_scr = d->act_scr;
642 
643     if(act_scr == new_scr || d->scr_to_load == new_scr) {
644         return;
645     }
646 
647     /*If another screen load animation is in progress
648      *make target screen loaded immediately. */
649     if(d->scr_to_load && act_scr != d->scr_to_load) {
650         lv_anim_delete(d->scr_to_load, NULL);
651         lv_obj_set_pos(d->scr_to_load, 0, 0);
652         lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0);
653 
654         d->prev_scr = d->act_scr;
655         act_scr = d->scr_to_load; /*Active screen changed.*/
656 
657         scr_load_internal(d->scr_to_load);
658     }
659 
660     d->scr_to_load = new_scr;
661 
662     if(d->prev_scr && d->del_prev) lv_obj_delete(d->prev_scr);
663     d->prev_scr = NULL;
664 
665     d->draw_prev_over_act = is_out_anim(anim_type);
666     d->del_prev = auto_del;
667 
668     /*Be sure there is no other animation on the screens*/
669     lv_anim_delete(new_scr, NULL);
670     if(act_scr) lv_anim_delete(act_scr, NULL);
671 
672     /*Be sure both screens are in a normal position*/
673     lv_obj_set_pos(new_scr, 0, 0);
674     if(act_scr) lv_obj_set_pos(act_scr, 0, 0);
675     lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0);
676     if(act_scr) lv_obj_remove_local_style_prop(act_scr, LV_STYLE_OPA, 0);
677 
678     /*Shortcut for immediate load*/
679     if(time == 0 && delay == 0) {
680         scr_load_internal(new_scr);
681         if(auto_del && act_scr) lv_obj_delete(act_scr);
682         return;
683     }
684 
685     lv_anim_t a_new;
686     lv_anim_init(&a_new);
687     lv_anim_set_var(&a_new, new_scr);
688     lv_anim_set_start_cb(&a_new, scr_load_anim_start);
689     lv_anim_set_completed_cb(&a_new, scr_anim_completed);
690     lv_anim_set_duration(&a_new, time);
691     lv_anim_set_delay(&a_new, delay);
692 
693     lv_anim_t a_old;
694     lv_anim_init(&a_old);
695     lv_anim_set_var(&a_old, act_scr);
696     lv_anim_set_duration(&a_old, time);
697     lv_anim_set_delay(&a_old, delay);
698 
699     switch(anim_type) {
700         case LV_SCR_LOAD_ANIM_NONE:
701             /*Create a dummy animation to apply the delay*/
702             lv_anim_set_exec_cb(&a_new, set_x_anim);
703             lv_anim_set_values(&a_new, 0, 0);
704             break;
705         case LV_SCR_LOAD_ANIM_OVER_LEFT:
706             lv_anim_set_exec_cb(&a_new, set_x_anim);
707             lv_anim_set_values(&a_new, lv_display_get_horizontal_resolution(d), 0);
708             break;
709         case LV_SCR_LOAD_ANIM_OVER_RIGHT:
710             lv_anim_set_exec_cb(&a_new, set_x_anim);
711             lv_anim_set_values(&a_new, -lv_display_get_horizontal_resolution(d), 0);
712             break;
713         case LV_SCR_LOAD_ANIM_OVER_TOP:
714             lv_anim_set_exec_cb(&a_new, set_y_anim);
715             lv_anim_set_values(&a_new, lv_display_get_vertical_resolution(d), 0);
716             break;
717         case LV_SCR_LOAD_ANIM_OVER_BOTTOM:
718             lv_anim_set_exec_cb(&a_new, set_y_anim);
719             lv_anim_set_values(&a_new, -lv_display_get_vertical_resolution(d), 0);
720             break;
721         case LV_SCR_LOAD_ANIM_MOVE_LEFT:
722             lv_anim_set_exec_cb(&a_new, set_x_anim);
723             lv_anim_set_values(&a_new, lv_display_get_horizontal_resolution(d), 0);
724 
725             lv_anim_set_exec_cb(&a_old, set_x_anim);
726             lv_anim_set_values(&a_old, 0, -lv_display_get_horizontal_resolution(d));
727             break;
728         case LV_SCR_LOAD_ANIM_MOVE_RIGHT:
729             lv_anim_set_exec_cb(&a_new, set_x_anim);
730             lv_anim_set_values(&a_new, -lv_display_get_horizontal_resolution(d), 0);
731 
732             lv_anim_set_exec_cb(&a_old, set_x_anim);
733             lv_anim_set_values(&a_old, 0, lv_display_get_horizontal_resolution(d));
734             break;
735         case LV_SCR_LOAD_ANIM_MOVE_TOP:
736             lv_anim_set_exec_cb(&a_new, set_y_anim);
737             lv_anim_set_values(&a_new, lv_display_get_vertical_resolution(d), 0);
738 
739             lv_anim_set_exec_cb(&a_old, set_y_anim);
740             lv_anim_set_values(&a_old, 0, -lv_display_get_vertical_resolution(d));
741             break;
742         case LV_SCR_LOAD_ANIM_MOVE_BOTTOM:
743             lv_anim_set_exec_cb(&a_new, set_y_anim);
744             lv_anim_set_values(&a_new, -lv_display_get_vertical_resolution(d), 0);
745 
746             lv_anim_set_exec_cb(&a_old, set_y_anim);
747             lv_anim_set_values(&a_old, 0, lv_display_get_vertical_resolution(d));
748             break;
749         case LV_SCR_LOAD_ANIM_FADE_IN:
750             lv_anim_set_exec_cb(&a_new, opa_scale_anim);
751             lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER);
752             break;
753         case LV_SCR_LOAD_ANIM_FADE_OUT:
754             lv_anim_set_exec_cb(&a_old, opa_scale_anim);
755             lv_anim_set_values(&a_old, LV_OPA_COVER, LV_OPA_TRANSP);
756             break;
757         case LV_SCR_LOAD_ANIM_OUT_LEFT:
758             lv_anim_set_exec_cb(&a_old, set_x_anim);
759             lv_anim_set_values(&a_old, 0, -lv_display_get_horizontal_resolution(d));
760             break;
761         case LV_SCR_LOAD_ANIM_OUT_RIGHT:
762             lv_anim_set_exec_cb(&a_old, set_x_anim);
763             lv_anim_set_values(&a_old, 0, lv_display_get_horizontal_resolution(d));
764             break;
765         case LV_SCR_LOAD_ANIM_OUT_TOP:
766             lv_anim_set_exec_cb(&a_old, set_y_anim);
767             lv_anim_set_values(&a_old, 0, -lv_display_get_vertical_resolution(d));
768             break;
769         case LV_SCR_LOAD_ANIM_OUT_BOTTOM:
770             lv_anim_set_exec_cb(&a_old, set_y_anim);
771             lv_anim_set_values(&a_old, 0, lv_display_get_vertical_resolution(d));
772             break;
773     }
774 
775     if(act_scr) lv_obj_send_event(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL);
776 
777     lv_anim_start(&a_new);
778     if(act_scr) lv_anim_start(&a_old);
779 }
780 
781 /*---------------------
782  * OTHERS
783  *--------------------*/
784 
lv_display_add_event_cb(lv_display_t * disp,lv_event_cb_t event_cb,lv_event_code_t filter,void * user_data)785 void lv_display_add_event_cb(lv_display_t * disp, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
786 {
787     LV_ASSERT_NULL(disp);
788 
789     lv_event_add(&disp->event_list, event_cb, filter, user_data);
790 }
791 
lv_display_get_event_count(lv_display_t * disp)792 uint32_t lv_display_get_event_count(lv_display_t * disp)
793 {
794     LV_ASSERT_NULL(disp);
795     return lv_event_get_count(&disp->event_list);
796 }
797 
lv_display_get_event_dsc(lv_display_t * disp,uint32_t index)798 lv_event_dsc_t * lv_display_get_event_dsc(lv_display_t * disp, uint32_t index)
799 {
800     LV_ASSERT_NULL(disp);
801     return lv_event_get_dsc(&disp->event_list, index);
802 
803 }
804 
lv_display_delete_event(lv_display_t * disp,uint32_t index)805 bool lv_display_delete_event(lv_display_t * disp, uint32_t index)
806 {
807     LV_ASSERT_NULL(disp);
808 
809     return lv_event_remove(&disp->event_list, index);
810 }
811 
lv_display_remove_event_cb_with_user_data(lv_display_t * disp,lv_event_cb_t event_cb,void * user_data)812 uint32_t lv_display_remove_event_cb_with_user_data(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data)
813 {
814     LV_ASSERT_NULL(disp);
815 
816     uint32_t event_cnt = lv_display_get_event_count(disp);
817     uint32_t removed_count = 0;
818     int32_t i;
819 
820     for(i = event_cnt - 1; i >= 0; i--) {
821         lv_event_dsc_t * dsc = lv_display_get_event_dsc(disp, i);
822         if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) {
823             lv_display_delete_event(disp, i);
824             removed_count ++;
825         }
826     }
827 
828     return removed_count;
829 }
830 
lv_display_send_event(lv_display_t * disp,lv_event_code_t code,void * param)831 lv_result_t lv_display_send_event(lv_display_t * disp, lv_event_code_t code, void * param)
832 {
833 
834     lv_event_t e;
835     lv_memzero(&e, sizeof(e));
836     e.code = code;
837     e.current_target = disp;
838     e.original_target = disp;
839     e.param = param;
840     lv_result_t res;
841     res = lv_event_send(&disp->event_list, &e, true);
842     if(res != LV_RESULT_OK) return res;
843 
844     res = lv_event_send(&disp->event_list, &e, false);
845     if(res != LV_RESULT_OK) return res;
846 
847     return res;
848 }
849 
lv_event_get_invalidated_area(lv_event_t * e)850 lv_area_t * lv_event_get_invalidated_area(lv_event_t * e)
851 {
852     if(e->code == LV_EVENT_INVALIDATE_AREA) {
853         return lv_event_get_param(e);
854     }
855     else {
856         LV_LOG_WARN("Not interpreted with this event code");
857         return NULL;
858     }
859 }
860 
lv_display_set_rotation(lv_display_t * disp,lv_display_rotation_t rotation)861 void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation)
862 {
863     if(disp == NULL) disp = lv_display_get_default();
864     if(disp == NULL) return;
865 
866     disp->rotation = rotation;
867     update_resolution(disp);
868 }
869 
lv_display_get_rotation(lv_display_t * disp)870 lv_display_rotation_t lv_display_get_rotation(lv_display_t * disp)
871 {
872     if(disp == NULL) disp = lv_display_get_default();
873     if(disp == NULL) return LV_DISPLAY_ROTATION_0;
874     return disp->rotation;
875 }
876 
lv_display_set_theme(lv_display_t * disp,lv_theme_t * th)877 void lv_display_set_theme(lv_display_t * disp, lv_theme_t * th)
878 {
879     if(!disp) disp = lv_display_get_default();
880     if(!disp) {
881         LV_LOG_WARN("no display registered");
882         return;
883     }
884 
885     disp->theme = th;
886 
887     if(disp->screen_cnt == 4 &&
888        lv_obj_get_child_count(disp->screens[0]) == 0 &&
889        lv_obj_get_child_count(disp->screens[1]) == 0 &&
890        lv_obj_get_child_count(disp->screens[2]) == 0) {
891         lv_theme_apply(disp->screens[0]);
892     }
893 }
894 
lv_display_get_theme(lv_display_t * disp)895 lv_theme_t * lv_display_get_theme(lv_display_t * disp)
896 {
897     if(disp == NULL) disp = lv_display_get_default();
898     return disp->theme;
899 }
900 
lv_display_get_inactive_time(const lv_display_t * disp)901 uint32_t lv_display_get_inactive_time(const lv_display_t * disp)
902 {
903     if(disp) return lv_tick_elaps(disp->last_activity_time);
904 
905     lv_display_t * d;
906     uint32_t t = UINT32_MAX;
907     d          = lv_display_get_next(NULL);
908     while(d) {
909         uint32_t elaps = lv_tick_elaps(d->last_activity_time);
910         t = LV_MIN(t, elaps);
911         d = lv_display_get_next(d);
912     }
913 
914     return t;
915 }
916 
lv_display_trigger_activity(lv_display_t * disp)917 void lv_display_trigger_activity(lv_display_t * disp)
918 {
919     if(!disp) disp = lv_display_get_default();
920     if(!disp) {
921         LV_LOG_WARN("lv_display_trigger_activity: no display registered");
922         return;
923     }
924 
925     disp->last_activity_time = lv_tick_get();
926 }
927 
lv_display_enable_invalidation(lv_display_t * disp,bool en)928 void lv_display_enable_invalidation(lv_display_t * disp, bool en)
929 {
930     if(!disp) disp = lv_display_get_default();
931     if(!disp) {
932         LV_LOG_WARN("no display registered");
933         return;
934     }
935 
936     disp->inv_en_cnt += en ? 1 : -1;
937 }
938 
lv_display_is_invalidation_enabled(lv_display_t * disp)939 bool lv_display_is_invalidation_enabled(lv_display_t * disp)
940 {
941     if(!disp) disp = lv_display_get_default();
942     if(!disp) {
943         LV_LOG_WARN("no display registered");
944         return false;
945     }
946 
947     return (disp->inv_en_cnt > 0);
948 }
949 
lv_display_get_refr_timer(lv_display_t * disp)950 lv_timer_t * lv_display_get_refr_timer(lv_display_t * disp)
951 {
952     if(!disp) disp = lv_display_get_default();
953     if(!disp) return NULL;
954 
955     return disp->refr_timer;
956 }
957 
lv_display_delete_refr_timer(lv_display_t * disp)958 void lv_display_delete_refr_timer(lv_display_t * disp)
959 {
960     if(!disp) disp = lv_display_get_default();
961     if(!disp || !disp->refr_timer) return;
962 
963     lv_timer_delete(disp->refr_timer);
964     disp->refr_timer = NULL;
965 }
966 
lv_display_set_user_data(lv_display_t * disp,void * user_data)967 void lv_display_set_user_data(lv_display_t * disp, void * user_data)
968 {
969     if(!disp) disp = lv_display_get_default();
970     if(!disp) return;
971     disp->user_data = user_data;
972 }
973 
lv_display_set_driver_data(lv_display_t * disp,void * driver_data)974 void lv_display_set_driver_data(lv_display_t * disp, void * driver_data)
975 {
976     if(!disp) disp = lv_display_get_default();
977     if(!disp) return;
978 
979     disp->driver_data = driver_data;
980 }
981 
lv_display_get_user_data(lv_display_t * disp)982 void * lv_display_get_user_data(lv_display_t * disp)
983 {
984     if(!disp) disp = lv_display_get_default();
985     if(!disp) return NULL;
986     return disp->user_data;
987 }
988 
lv_display_get_driver_data(lv_display_t * disp)989 void * lv_display_get_driver_data(lv_display_t * disp)
990 {
991     if(!disp) disp = lv_display_get_default();
992     if(!disp) return NULL;
993 
994     return disp->driver_data;
995 }
996 
lv_display_get_buf_active(lv_display_t * disp)997 lv_draw_buf_t * lv_display_get_buf_active(lv_display_t * disp)
998 {
999     if(!disp) disp = lv_display_get_default();
1000     if(!disp) return NULL;
1001     return disp->buf_act;
1002 }
1003 
lv_display_rotate_area(lv_display_t * disp,lv_area_t * area)1004 void lv_display_rotate_area(lv_display_t * disp, lv_area_t * area)
1005 {
1006     lv_display_rotation_t rotation = lv_display_get_rotation(disp);
1007 
1008     int32_t w = lv_area_get_width(area);
1009     int32_t h = lv_area_get_height(area);
1010 
1011     switch(rotation) {
1012         case LV_DISPLAY_ROTATION_0:
1013             return;
1014         case LV_DISPLAY_ROTATION_90:
1015             area->y2 = disp->ver_res - area->x1 - 1;
1016             area->x1 = area->y1;
1017             area->x2 = area->x1 + h - 1;
1018             area->y1 = area->y2 - w + 1;
1019             break;
1020         case LV_DISPLAY_ROTATION_180:
1021             area->y2 = disp->ver_res - area->y1 - 1;
1022             area->y1 = area->y2 - h + 1;
1023             area->x2 = disp->hor_res - area->x1 - 1;
1024             area->x1 = area->x2 - w + 1;
1025             break;
1026         case LV_DISPLAY_ROTATION_270:
1027             area->x1 = disp->hor_res - area->y2 - 1;
1028             area->y2 = area->x2;
1029             area->x2 = area->x1 + h - 1;
1030             area->y1 = area->y2 - w + 1;
1031             break;
1032     }
1033 }
1034 
lv_display_get_draw_buf_size(lv_display_t * disp)1035 uint32_t lv_display_get_draw_buf_size(lv_display_t * disp)
1036 {
1037     if(!disp) disp = lv_display_get_default();
1038     if(!disp) return 0;
1039 
1040     if(disp->buf_1) {
1041         return disp->buf_1->data_size;
1042     }
1043     return 0;
1044 }
1045 
lv_display_get_invalidated_draw_buf_size(lv_display_t * disp,uint32_t width,uint32_t height)1046 uint32_t lv_display_get_invalidated_draw_buf_size(lv_display_t * disp, uint32_t width, uint32_t height)
1047 {
1048     if(!disp) disp = lv_display_get_default();
1049     if(!disp) return 0;
1050 
1051     if(disp->render_mode == LV_DISPLAY_RENDER_MODE_FULL) {
1052         width = lv_display_get_horizontal_resolution(disp);
1053         height = lv_display_get_vertical_resolution(disp);
1054     }
1055 
1056     lv_color_format_t cf = lv_display_get_color_format(disp);
1057     uint32_t stride = lv_draw_buf_width_to_stride(width, cf);
1058     uint32_t buf_size = stride * height;
1059 
1060     LV_ASSERT(disp->buf_1 && disp->buf_1->data_size >= buf_size);
1061     if(disp->buf_2) LV_ASSERT(disp->buf_2->data_size >= buf_size);
1062 
1063     return buf_size;
1064 }
1065 
lv_screen_active(void)1066 lv_obj_t * lv_screen_active(void)
1067 {
1068     return lv_display_get_screen_active(lv_display_get_default());
1069 }
1070 
lv_layer_top(void)1071 lv_obj_t * lv_layer_top(void)
1072 {
1073     return lv_display_get_layer_top(lv_display_get_default());
1074 }
1075 
lv_layer_sys(void)1076 lv_obj_t * lv_layer_sys(void)
1077 {
1078     return lv_display_get_layer_sys(lv_display_get_default());
1079 }
1080 
lv_layer_bottom(void)1081 lv_obj_t * lv_layer_bottom(void)
1082 {
1083     return lv_display_get_layer_bottom(lv_display_get_default());
1084 }
1085 
lv_dpx(int32_t n)1086 int32_t lv_dpx(int32_t n)
1087 {
1088     return LV_DPX(n);
1089 }
1090 
lv_display_dpx(const lv_display_t * disp,int32_t n)1091 int32_t lv_display_dpx(const lv_display_t * disp, int32_t n)
1092 {
1093     return LV_DPX_CALC(lv_display_get_dpi(disp), n);
1094 }
1095 
1096 /**********************
1097  *   STATIC FUNCTIONS
1098  **********************/
1099 
update_resolution(lv_display_t * disp)1100 static void update_resolution(lv_display_t * disp)
1101 {
1102     int32_t hor_res = lv_display_get_horizontal_resolution(disp);
1103     int32_t ver_res = lv_display_get_vertical_resolution(disp);
1104 
1105     lv_area_t prev_coords;
1106     lv_obj_get_coords(disp->sys_layer, &prev_coords);
1107     uint32_t i;
1108     for(i = 0; i < disp->screen_cnt; i++) {
1109         lv_area_set_width(&disp->screens[i]->coords, hor_res);
1110         lv_area_set_height(&disp->screens[i]->coords, ver_res);
1111         lv_obj_send_event(disp->screens[i], LV_EVENT_SIZE_CHANGED, &prev_coords);
1112     }
1113 
1114     lv_area_set_width(&disp->top_layer->coords, hor_res);
1115     lv_area_set_height(&disp->top_layer->coords, ver_res);
1116     lv_obj_send_event(disp->top_layer, LV_EVENT_SIZE_CHANGED, &prev_coords);
1117 
1118     lv_area_set_width(&disp->sys_layer->coords, hor_res);
1119     lv_area_set_height(&disp->sys_layer->coords, ver_res);
1120     lv_obj_send_event(disp->sys_layer, LV_EVENT_SIZE_CHANGED, &prev_coords);
1121 
1122     lv_area_set_width(&disp->bottom_layer->coords, hor_res);
1123     lv_area_set_height(&disp->bottom_layer->coords, ver_res);
1124     lv_obj_send_event(disp->bottom_layer, LV_EVENT_SIZE_CHANGED, &prev_coords);
1125 
1126     lv_memzero(disp->inv_areas, sizeof(disp->inv_areas));
1127     lv_memzero(disp->inv_area_joined, sizeof(disp->inv_area_joined));
1128     disp->inv_p = 0;
1129     lv_obj_invalidate(disp->sys_layer);
1130 
1131     lv_obj_tree_walk(NULL, invalidate_layout_cb, NULL);
1132 
1133     lv_display_send_event(disp, LV_EVENT_RESOLUTION_CHANGED, NULL);
1134 }
1135 
invalidate_layout_cb(lv_obj_t * obj,void * user_data)1136 static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data)
1137 {
1138     LV_UNUSED(user_data);
1139     lv_obj_mark_layout_as_dirty(obj);
1140     return LV_OBJ_TREE_WALK_NEXT;
1141 }
1142 
scr_load_internal(lv_obj_t * scr)1143 static void scr_load_internal(lv_obj_t * scr)
1144 {
1145     /*scr must not be NULL, but d->act_scr might be*/
1146     LV_ASSERT_NULL(scr);
1147     if(scr == NULL) return;
1148 
1149     lv_display_t * d = lv_obj_get_display(scr);
1150     if(!d) return;  /*Shouldn't happen, just to be sure*/
1151 
1152     lv_obj_t * old_scr = d->act_scr;
1153 
1154     if(old_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL);
1155     lv_obj_send_event(scr, LV_EVENT_SCREEN_LOAD_START, NULL);
1156 
1157     d->act_scr = scr;
1158     d->scr_to_load = NULL;
1159 
1160     lv_obj_send_event(scr, LV_EVENT_SCREEN_LOADED, NULL);
1161     if(old_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
1162 
1163     lv_obj_invalidate(scr);
1164 }
1165 
scr_load_anim_start(lv_anim_t * a)1166 static void scr_load_anim_start(lv_anim_t * a)
1167 {
1168     lv_display_t * d = lv_obj_get_display(a->var);
1169 
1170     d->prev_scr = d->act_scr;
1171     d->act_scr = a->var;
1172 
1173     lv_obj_send_event(d->act_scr, LV_EVENT_SCREEN_LOAD_START, NULL);
1174 }
1175 
opa_scale_anim(void * obj,int32_t v)1176 static void opa_scale_anim(void * obj, int32_t v)
1177 {
1178     lv_obj_set_style_opa(obj, v, 0);
1179 }
1180 
set_x_anim(void * obj,int32_t v)1181 static void set_x_anim(void * obj, int32_t v)
1182 {
1183     lv_obj_set_x(obj, v);
1184 }
1185 
set_y_anim(void * obj,int32_t v)1186 static void set_y_anim(void * obj, int32_t v)
1187 {
1188     lv_obj_set_y(obj, v);
1189 }
1190 
scr_anim_completed(lv_anim_t * a)1191 static void scr_anim_completed(lv_anim_t * a)
1192 {
1193     lv_display_t * d = lv_obj_get_display(a->var);
1194 
1195     lv_obj_send_event(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL);
1196     lv_obj_send_event(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
1197 
1198     if(d->prev_scr && d->del_prev) lv_obj_delete(d->prev_scr);
1199     d->prev_scr = NULL;
1200     d->draw_prev_over_act = false;
1201     d->scr_to_load = NULL;
1202     lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
1203     lv_obj_invalidate(d->act_scr);
1204 }
1205 
is_out_anim(lv_screen_load_anim_t anim_type)1206 static bool is_out_anim(lv_screen_load_anim_t anim_type)
1207 {
1208     return anim_type == LV_SCR_LOAD_ANIM_FADE_OUT  ||
1209            anim_type == LV_SCR_LOAD_ANIM_OUT_LEFT  ||
1210            anim_type == LV_SCR_LOAD_ANIM_OUT_RIGHT ||
1211            anim_type == LV_SCR_LOAD_ANIM_OUT_TOP   ||
1212            anim_type == LV_SCR_LOAD_ANIM_OUT_BOTTOM;
1213 }
1214 
disp_event_cb(lv_event_t * e)1215 static void disp_event_cb(lv_event_t * e)
1216 {
1217     lv_event_code_t code = lv_event_get_code(e);
1218     lv_display_t * disp = lv_event_get_target(e);
1219     switch(code) {
1220         case LV_EVENT_REFR_REQUEST:
1221             if(disp->refr_timer) lv_timer_resume(disp->refr_timer);
1222             break;
1223 
1224         default:
1225             break;
1226     }
1227 }
1228