acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_disp.c (14368B)

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