Screensaver, change clickable flag

Description

I want to make a screensaver. When no touch input is received then the brightness of the hole screen goes down and I remove the LV_OBJ_FLAG_CLICKABLE. If the user click on the screen or widgets, it should go to the normal mode. But if I click on the button while the screen has a lower brightness the button makes the animation (PRESSED). I tried to use the function lv_obj_clear_state(btn, LV_EVENT_ALL); , after the button was pressed, but it doesn’t work.

What MCU/Processor/Board and compiler are you using?

ESP32S3 Touch Display

What LVGL version are you using?

8.3.4

What do you want to achieve?

To make a screensaver wich doesn’t react on the first touch, it should on the second.

What have you tried so far?

I also tried to make a transparent layer on top of the normal layer.

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

    ledcWrite(0, 255); 

    screensaver_active = false;
    screen_off_active = false;

    lv_obj_clear_state(btn, LV_EVENT_ALL);
    delay(1000);
    lv_obj_clear_state(btn, LV_EVENT_ALL);
    lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE);

Screenshot and/or video

Problem_Screensaver (1)

What platform are you using?

Arduino or ESP IDF?

I‘m using Arduino IDE

I found a solution, but maybe there is a better one. Let me know, if you will find one. :wink:

Here is my code:

#include <lvgl.h>
//#include <Arduino.h>
#include <Arduino_GFX_Library.h>
#include <HardwareSerial.h>

#define TFT_BL 2
#define SCREENSAVER_TIMEOUT 5000 // 5 Sekunden in ms
#define SCREEN_OFF_TIMEOUT 5000  // 5 Sekunden in ms
#define MAKE_OBJ_CLICKABLE_DELAY 300

#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else
Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
    GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
    40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
    45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
    5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
    8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
);

Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
    bus,
    800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
    480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
    1 /* pclk_active_neg */, 14000000 /* prefer_speed */, true /* auto_flush */);
#endif

#include "touch.h"

static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf;
static lv_disp_drv_t disp_drv;

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif
  lv_disp_flush_ready(disp);
}

static lv_timer_t *screensaver_timer;
static lv_timer_t *screen_off_timer;
static lv_timer_t *make_obj_clickable_timer;
static bool screensaver_active = false;
static bool screen_off_active = false;
static lv_obj_t *btn;
static lv_obj_t *label;
static lv_obj_t *src_layer;

void make_obj_clickable_cb(lv_timer_t *timer)
{
  lv_timer_reset(make_obj_clickable_timer);
  lv_timer_pause(make_obj_clickable_timer);
  Serial.println("clickable");
  lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE);
}
void reset_screensaver_timer(void)
{
  Serial.println("Reset_Funktion");
  if (screensaver_active || screen_off_active)
  {
    lv_timer_reset(make_obj_clickable_timer);
    lv_timer_resume(make_obj_clickable_timer);

    ledcWrite(0, 255); // Helligkeit auf Maximum setzen

    screensaver_active = false;
    screen_off_active = false;
    Serial.println("255_Prozent");
  }
  lv_timer_reset(screensaver_timer);
  lv_timer_reset(screen_off_timer);

  lv_timer_pause(screen_off_timer);
  lv_timer_resume(screensaver_timer);
}

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
  if (touch_has_signal())
  {
    if (touch_touched())
    {
      data->state = LV_INDEV_STATE_PR;
      data->point.x = touch_last_x;
      data->point.y = touch_last_y;

      Serial.println("Aufruf Reset screensaver");
      reset_screensaver_timer();
    }
    else if (touch_released())
    {
      data->state = LV_INDEV_STATE_REL;
    }
    else
    {
      data->state = LV_INDEV_STATE_REL;
    }
  }
}

void screensaver_cb(lv_timer_t *timer)
{
  screensaver_active = true;
  ledcWrite(0, 100);                // Helligkeit auf 100 (von 255) reduzieren
  lv_timer_reset(screen_off_timer); // Startet den Timer für den vollständigen Ausschaltmodus
  lv_timer_resume(screen_off_timer);

  // lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
  lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);

  lv_timer_reset(screensaver_timer);
  lv_timer_pause(screensaver_timer);
  Serial.println("100_Prozent");
}

void screen_off_cb(lv_timer_t *timer)
{
  Serial.println("OFF_Funktion");
  if (screensaver_active && !screen_off_active)
  {
    screen_off_active = true;
    ledcWrite(0, 0); // Helligkeit auf 0 setzen, um die Hintergrundbeleuchtung auszuschalten
    Serial.println("0_Prozent");
    lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
  }
  lv_timer_pause(screensaver_timer);
  lv_timer_pause(screen_off_timer);
}

void setup()
{
  Serial.begin(9600);
  Serial.println("LVGL Widgets Demo");

  gfx->begin();
  ledcWrite(0, 255); // Helligkeit auf Maximum setzen
#ifdef TFT_BL
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);

  ledcSetup(0, 300, 8);
  ledcAttachPin(TFT_BL, 0);
#endif
  gfx->fillScreen(BLACK);
  delay(100);

  lv_init();

  pinMode(TOUCH_GT911_RST, OUTPUT);
  digitalWrite(TOUCH_GT911_RST, LOW);
  delay(10);
  digitalWrite(TOUCH_GT911_RST, HIGH);
  delay(10);
  touch_init();

  screenWidth = gfx->width();
  screenHeight = gfx->height();
#ifdef ESP32
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
  disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4);
#endif

  if (!disp_draw_buf)
  {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  }
  else
  {
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 4);

    lv_disp_drv_init(&disp_drv);
    disp_drv.sw_rotate = 1;
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    lv_disp_set_rotation(NULL, LV_DISP_ROT_90);
    lv_disp_drv_register(&disp_drv);

    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;
    lv_indev_drv_register(&indev_drv);
  }

  // Erstelle den src-Layer für normale Inhalte
  src_layer = lv_obj_create(lv_scr_act());
  lv_obj_set_size(src_layer, LV_HOR_RES, LV_VER_RES);
  lv_obj_set_style_bg_color(src_layer, lv_color_hex(0xFFFFFF), LV_PART_MAIN); // Setze Hintergrundfarbe

  // Erstelle den Button im src-Layer
  btn = lv_btn_create(src_layer);
  lv_obj_set_size(btn, 120, 50);            // Größe des Buttons festlegen
  lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0); // Button in der Mitte des Bildschirms positionieren

  label = lv_label_create(btn);            // Label für den Button erstellen
  lv_label_set_text(label, "Test Button"); // Text des Labels festlegen
  lv_obj_center(label);                    // Label im Button zentrieren

  screensaver_timer = lv_timer_create(screensaver_cb, SCREENSAVER_TIMEOUT, NULL);
  screen_off_timer = lv_timer_create(screen_off_cb, SCREEN_OFF_TIMEOUT, NULL);
  make_obj_clickable_timer = lv_timer_create(make_obj_clickable_cb, MAKE_OBJ_CLICKABLE_DELAY, NULL);

  lv_timer_pause(make_obj_clickable_timer);
  lv_timer_reset(screen_off_timer);
  lv_timer_pause(screen_off_timer);

  ledcWrite(0, 255);
}

void loop()
{
  lv_task_handler();
  lv_timer_handler();
  delay(5);
}
1 Like