feat(drivers): add x11 driver (display/input) support (#4795)
Co-authored-by: Gregor Copoix <gregor.copoix@ithinx.io>
This commit is contained in:
@@ -760,6 +760,14 @@
|
|||||||
#define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/
|
#define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/
|
||||||
|
#define LV_USE_X11 0
|
||||||
|
#if LV_USE_X11
|
||||||
|
#define LV_X11_DIRECT_EXIT 1
|
||||||
|
#define LV_X11_DOUBLE_BUFFER 1
|
||||||
|
#define LV_X11_RENDER_MODE_PARTIAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*Driver for /dev/fb*/
|
/*Driver for /dev/fb*/
|
||||||
#define LV_USE_LINUX_FBDEV 0
|
#define LV_USE_LINUX_FBDEV 0
|
||||||
#if LV_USE_LINUX_FBDEV
|
#if LV_USE_LINUX_FBDEV
|
||||||
|
|||||||
35
Kconfig
35
Kconfig
@@ -1277,10 +1277,43 @@ menu "LVGL configuration"
|
|||||||
depends on LV_USE_SDL
|
depends on LV_USE_SDL
|
||||||
default n
|
default n
|
||||||
config LV_SDL_DIRECT_EXIT
|
config LV_SDL_DIRECT_EXIT
|
||||||
bool "Exit the application when all SDL widows are closed"
|
bool "Exit the application when all SDL windows are closed"
|
||||||
depends on LV_USE_SDL
|
depends on LV_USE_SDL
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config LV_USE_X11
|
||||||
|
bool "Use X11 window manager to open window on Linux PC and handle mouse and keyboard"
|
||||||
|
default n
|
||||||
|
config LV_X11_DOUBLE_BUFFER
|
||||||
|
bool "Use double buffers for lvgl rendering"
|
||||||
|
depends on LV_USE_X11
|
||||||
|
default y
|
||||||
|
config LV_X11_DIRECT_EXIT
|
||||||
|
bool "Exit the application when all X11 windows have been closed"
|
||||||
|
depends on LV_USE_X11
|
||||||
|
default y
|
||||||
|
choice
|
||||||
|
prompt "X11 device render mode"
|
||||||
|
depends on LV_USE_X11
|
||||||
|
default LV_X11_RENDER_MODE_PARTIAL
|
||||||
|
|
||||||
|
config LV_X11_RENDER_MODE_PARTIAL
|
||||||
|
bool "Partial render mode (preferred)"
|
||||||
|
help
|
||||||
|
Use the buffer(s) to render the screen is smaller parts. This way the buffers can be smaller then the display to save RAM.
|
||||||
|
Appr. 1/10 screen size buffer(s) are used.
|
||||||
|
config LV_X11_RENDER_MODE_DIRECT
|
||||||
|
bool "Direct render mode"
|
||||||
|
help
|
||||||
|
The buffer(s) has to be screen sized and LVGL will render into the correct location of the buffer. This way the buffer always contain the whole image. Only the changed ares will be updated.
|
||||||
|
With 2 buffers the buffers' content are kept in sync automatically and in flush_cb only address change is required.
|
||||||
|
config LV_X11_RENDER_MODE_FULL
|
||||||
|
bool "Full render mode"
|
||||||
|
help
|
||||||
|
Always redraw the whole screen even if only one pixel has been changed.
|
||||||
|
With 2 buffers in flush_cb only and address change is required.
|
||||||
|
endchoice
|
||||||
|
|
||||||
config LV_USE_LINUX_FBDEV
|
config LV_USE_LINUX_FBDEV
|
||||||
bool "Use Linux framebuffer device"
|
bool "Use Linux framebuffer device"
|
||||||
default n
|
default n
|
||||||
|
|||||||
@@ -50,26 +50,26 @@ extern lv_font_t font_multilang_large;
|
|||||||
**********************/
|
**********************/
|
||||||
#define CARD_INFO_SET(_image, _name, _description) {.image = _image, .name = _name, .description = _description}
|
#define CARD_INFO_SET(_image, _name, _description) {.image = _image, .name = _name, .description = _description}
|
||||||
|
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_1)
|
LV_IMAGE_DECLARE(img_multilang_avatar_1);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_2)
|
LV_IMAGE_DECLARE(img_multilang_avatar_2);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_3)
|
LV_IMAGE_DECLARE(img_multilang_avatar_3);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_4)
|
LV_IMAGE_DECLARE(img_multilang_avatar_4);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_5)
|
LV_IMAGE_DECLARE(img_multilang_avatar_5);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_6)
|
LV_IMAGE_DECLARE(img_multilang_avatar_6);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_7)
|
LV_IMAGE_DECLARE(img_multilang_avatar_7);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_8)
|
LV_IMAGE_DECLARE(img_multilang_avatar_8);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_9)
|
LV_IMAGE_DECLARE(img_multilang_avatar_9);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_10)
|
LV_IMAGE_DECLARE(img_multilang_avatar_10);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_11)
|
LV_IMAGE_DECLARE(img_multilang_avatar_11);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_12)
|
LV_IMAGE_DECLARE(img_multilang_avatar_12);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_13)
|
LV_IMAGE_DECLARE(img_multilang_avatar_13);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_14)
|
LV_IMAGE_DECLARE(img_multilang_avatar_14);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_15)
|
LV_IMAGE_DECLARE(img_multilang_avatar_15);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_16)
|
LV_IMAGE_DECLARE(img_multilang_avatar_16);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_17)
|
LV_IMAGE_DECLARE(img_multilang_avatar_17);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_18)
|
LV_IMAGE_DECLARE(img_multilang_avatar_18);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_22)
|
LV_IMAGE_DECLARE(img_multilang_avatar_22);
|
||||||
LV_IMAGE_DECLARE(img_multilang_avatar_25)
|
LV_IMAGE_DECLARE(img_multilang_avatar_25);
|
||||||
|
|
||||||
static card_info_t card_info[] = {
|
static card_info_t card_info[] = {
|
||||||
CARD_INFO_SET(&img_multilang_avatar_5, "Zhang Wei", "对编程和技术充满热情。 开源倡导者🚀"),
|
CARD_INFO_SET(&img_multilang_avatar_5, "Zhang Wei", "对编程和技术充满热情。 开源倡导者🚀"),
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ static lv_style_t style_card;
|
|||||||
static lv_style_t style_avatar;
|
static lv_style_t style_avatar;
|
||||||
static lv_style_t style_btn;
|
static lv_style_t style_btn;
|
||||||
static lv_obj_t * card_to_transform;
|
static lv_obj_t * card_to_transform;
|
||||||
LV_IMAGE_DECLARE(img_transform_avatar_15)
|
LV_IMAGE_DECLARE(img_transform_avatar_15);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
@@ -133,7 +133,7 @@ static lv_obj_t * card_create(void)
|
|||||||
lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_START, 2, 1, LV_GRID_ALIGN_CENTER, 3, 1);
|
lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_START, 2, 1, LV_GRID_ALIGN_CENTER, 3, 1);
|
||||||
lv_obj_add_style(btn, &style_btn, 0);
|
lv_obj_add_style(btn, &style_btn, 0);
|
||||||
|
|
||||||
LV_IMAGE_DECLARE(img_multilang_like)
|
LV_IMAGE_DECLARE(img_multilang_like);
|
||||||
lv_obj_t * btn_img = lv_image_create(btn);
|
lv_obj_t * btn_img = lv_image_create(btn);
|
||||||
lv_image_set_src(btn_img, &img_multilang_like);
|
lv_image_set_src(btn_img, &img_multilang_like);
|
||||||
lv_obj_align(btn_img, LV_ALIGN_LEFT_MID, 30, 0);
|
lv_obj_align(btn_img, LV_ALIGN_LEFT_MID, 30, 0);
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ lv_micropython already contains these drivers:
|
|||||||
- Display drivers:
|
- Display drivers:
|
||||||
|
|
||||||
- SDL on Linux
|
- SDL on Linux
|
||||||
|
- X11 on Linux
|
||||||
- ESP32 specific:
|
- ESP32 specific:
|
||||||
|
|
||||||
- ILI9341
|
- ILI9341
|
||||||
@@ -149,6 +150,7 @@ lv_micropython already contains these drivers:
|
|||||||
- Input drivers:
|
- Input drivers:
|
||||||
|
|
||||||
- SDL
|
- SDL
|
||||||
|
- X11
|
||||||
- XPT2046
|
- XPT2046
|
||||||
- FT6X36
|
- FT6X36
|
||||||
- ESP32 ADC with resistive touch
|
- ESP32 ADC with resistive touch
|
||||||
|
|||||||
126
docs/integration/driver/X11.rst
Normal file
126
docs/integration/driver/X11.rst
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
=======
|
||||||
|
X11
|
||||||
|
=======
|
||||||
|
|
||||||
|
Overview
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The `X11 display/input driver <https://github.com/lvgl/lvgl/src/dev/x11>`__ offers support for simulating the LVGL display
|
||||||
|
in a X11 desktop window. It is an alternative to Wayland, XCB, SDL or Qt.
|
||||||
|
|
||||||
|
The main purpose for this display driver is for testing/debugging the LVGL application in a Linux simulation window.
|
||||||
|
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The X11 display driver uses XLib to access the linux window manager.
|
||||||
|
|
||||||
|
1. Install XLib: ``sudo apt-get install libx11-6`` (should be installed already)
|
||||||
|
2. Install XLib development package: ``sudo apt-get install libx11-dev``
|
||||||
|
|
||||||
|
|
||||||
|
Configure X11 display driver
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
1. Enable the X11 display driver support in lv_conf.h, by cmake compiler define or by KConfig
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define LV_USE_X11 1
|
||||||
|
|
||||||
|
2. Optional configuration options:
|
||||||
|
- Direct Exit
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define LV_X11_DIRECT_EXIT 1 /*preferred default - ends the application automatically if last window has been closed*/
|
||||||
|
// or
|
||||||
|
#define LV_X11_DIRECT_EXIT 0 /*applicaion is responsible for ending the application (e.g. by own LV_EVENT_DELETE handler*/
|
||||||
|
|
||||||
|
|
||||||
|
- Double buffering
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define LV_X11_DOUBLE_BUFFER 1 /*preferred default*/
|
||||||
|
// or
|
||||||
|
#define LV_X11_DOUBLE_BUFFER 0 /*not recommended*/
|
||||||
|
|
||||||
|
- Render mode
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define LV_X11_RENDER_MODE_PARTIAL 1 /*LV_DISPLAY_RENDER_MODE_PARTIAL, preferred default*/
|
||||||
|
// or
|
||||||
|
#define LV_X11_RENDER_MODE_DIRECT 1 /*LV_DISPLAY_RENDER_MODE_DIRECT, not recommended for X11 driver*/
|
||||||
|
// or
|
||||||
|
#define LV_X11_RENDER_MODE_DULL 1 /*LV_DISPLAY_RENDER_MODE_FULL, not recommended for X11 driver*/
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
The minimal initialisation (e.g. in main.c, LV_X11_DIRECT_EXIT must be 1):
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
/* initialize X11 display driver */
|
||||||
|
lv_disp_t * disp = lv_x11_window_create("LVGL X11 Simulation", monitor_hor_res, monitor_ver_res);
|
||||||
|
|
||||||
|
/* initialize X11 input drivers (for keyboard, mouse & mousewheel) */
|
||||||
|
lv_x11_inputs_create(disp, NULL);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
/* Periodically call the lv_task handler */
|
||||||
|
lv_task_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Full initialisation with mouse pointer symbol and
|
||||||
|
own application exit handling dependent on LV_X11_DIRECT_EXIT (can be 1 or 0)
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
bool terminated = false;
|
||||||
|
|
||||||
|
#if !LV_X11_DIRECT_EXIT
|
||||||
|
static void on_close_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
terminate = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
/* initialize X11 display driver */
|
||||||
|
lv_disp_t * disp = lv_x11_window_create("LVGL X11 Simulation", monitor_hor_res, monitor_ver_res);
|
||||||
|
lv_display_add_event(disp, on_close_cb, LV_EVENT_DELETE, disp);
|
||||||
|
|
||||||
|
/* initialize X11 input drivers (for keyboard, mouse & mousewheel) */
|
||||||
|
LV_IMG_DECLARE(my_mouse_cursor_icon);
|
||||||
|
lv_x11_inputs_create(disp, &my_mouse_cursor_icon);
|
||||||
|
|
||||||
|
#if !LV_X11_DIRECT_EXIT
|
||||||
|
/* set optional window close callback to enable applicaton cleanup and exit */
|
||||||
|
lv_x11_window_set_close_cb(disp, on_close_cb, disp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
while(!terminated)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
/* Periodically call the lv_task handler */
|
||||||
|
lv_task_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,3 +7,4 @@ Drivers
|
|||||||
|
|
||||||
display/index
|
display/index
|
||||||
touchpad/index
|
touchpad/index
|
||||||
|
X11
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Choose your favorite IDE, read its README on GitHub, download the project, and l
|
|||||||
- `Eclipse with SDLdriver <https://github.com/lvgl/lv_sim_eclipse_sdl>`__: Recommended on Linux and Mac
|
- `Eclipse with SDLdriver <https://github.com/lvgl/lv_sim_eclipse_sdl>`__: Recommended on Linux and Mac
|
||||||
- `CodeBlocks <https://github.com/lvgl/lv_sim_codeblocks_win>`__: Recommended on Windows
|
- `CodeBlocks <https://github.com/lvgl/lv_sim_codeblocks_win>`__: Recommended on Windows
|
||||||
- `VisualStudio <https://github.com/lvgl/lv_sim_visual_studio_sdl>`__: For Windows
|
- `VisualStudio <https://github.com/lvgl/lv_sim_visual_studio_sdl>`__: For Windows
|
||||||
- `VSCode with SDL driver <https://github.com/lvgl/lv_sim_vscode_sdl>`__: Recommended on Linux and Mac
|
- `VSCode with SDL/X11 driver <https://github.com/lvgl/lv_sim_vscode_sdl>`__: Recommended on Linux (SDL/X11) and Mac (SDL)
|
||||||
- `PlatformIO with SDL driver <https://github.com/lvgl/lv_platformio>`__: Recommended on Linux and Mac
|
- `PlatformIO with SDL driver <https://github.com/lvgl/lv_platformio>`__: Recommended on Linux and Mac
|
||||||
- `MDK with FastModel <https://github.com/lvgl/lv_port_an547_cm55_sim>`__: For Windows
|
- `MDK with FastModel <https://github.com/lvgl/lv_port_an547_cm55_sim>`__: For Windows
|
||||||
|
|
||||||
@@ -70,8 +70,11 @@ choose *Eclipse CDT* from the list.
|
|||||||
Install SDL 2
|
Install SDL 2
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
The PC simulator uses the `SDL2 <https://www.libsdl.org/download-2.0.php>`__ cross-platform library to
|
The PC simulator uses
|
||||||
simulate a TFT display and a touchpad.
|
- `SDL2 <https://www.libsdl.org/download-2.0.php>`__ cross-platform library or
|
||||||
|
- `X11 <https://www.x.org/releases/current/doc/libX11/libX11/libX11.html>`__ Linux library
|
||||||
|
|
||||||
|
to simulate a TFT display and a touchpad.
|
||||||
|
|
||||||
Linux
|
Linux
|
||||||
^^^^^
|
^^^^^
|
||||||
@@ -83,6 +86,11 @@ On **Linux** you can easily install SDL2 using a terminal:
|
|||||||
3. Install SDL2 development package: ``sudo apt-get install libsdl2-dev``
|
3. Install SDL2 development package: ``sudo apt-get install libsdl2-dev``
|
||||||
4. If build essentials are not installed yet: ``sudo apt-get install build-essential``
|
4. If build essentials are not installed yet: ``sudo apt-get install build-essential``
|
||||||
|
|
||||||
|
On **Linux** X11 is even easier to install by terminal:
|
||||||
|
|
||||||
|
1. Install XLib: ``sudo apt-get install libx11-6`` (should be installed already)
|
||||||
|
2. Install XLib development package: ``sudo apt-get install libx11-dev``
|
||||||
|
|
||||||
Windows
|
Windows
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ target_compile_definitions(
|
|||||||
# Add definition of LV_CONF_PATH only if needed
|
# Add definition of LV_CONF_PATH only if needed
|
||||||
if(LV_CONF_PATH)
|
if(LV_CONF_PATH)
|
||||||
target_compile_definitions(lvgl PUBLIC LV_CONF_PATH=${LV_CONF_PATH})
|
target_compile_definitions(lvgl PUBLIC LV_CONF_PATH=${LV_CONF_PATH})
|
||||||
target_compile_definitions(lvgl_thorvg PUBLIC LV_CONF_PATH=${LV_CONF_PATH})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Include root and optional parent path of LV_CONF_PATH
|
# Include root and optional parent path of LV_CONF_PATH
|
||||||
@@ -43,6 +42,9 @@ if(NOT LV_CONF_BUILD_DISABLE_THORVG_INTERNAL)
|
|||||||
add_library(lvgl_thorvg ${THORVG_SOURCES})
|
add_library(lvgl_thorvg ${THORVG_SOURCES})
|
||||||
add_library(lvgl::thorvg ALIAS lvgl_thorvg)
|
add_library(lvgl::thorvg ALIAS lvgl_thorvg)
|
||||||
target_include_directories(lvgl_thorvg SYSTEM PUBLIC ${LVGL_ROOT_DIR}/src/libs/thorvg)
|
target_include_directories(lvgl_thorvg SYSTEM PUBLIC ${LVGL_ROOT_DIR}/src/libs/thorvg)
|
||||||
|
if(LV_CONF_PATH)
|
||||||
|
target_compile_definitions(lvgl_thorvg PUBLIC LV_CONF_PATH=${LV_CONF_PATH})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build LVGL example library
|
# Build LVGL example library
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ Make sure `LV_MEM_SIZE` is no less than `(64*1024U)`.
|
|||||||
|
|
||||||
- LV_USE_SDL
|
- LV_USE_SDL
|
||||||
|
|
||||||
|
- LV_USE_X11
|
||||||
|
|
||||||
- LV_USE_LINUX_FBDEV
|
- LV_USE_LINUX_FBDEV
|
||||||
|
|
||||||
- LV_USE_NUTTX_FBDEV
|
- LV_USE_NUTTX_FBDEV
|
||||||
@@ -224,4 +226,3 @@ enter the following command:
|
|||||||
```sh
|
```sh
|
||||||
./gen_pack.sh
|
./gen_pack.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#if LV_BUILD_EXAMPLES
|
#if LV_BUILD_EXAMPLES
|
||||||
#if LV_USE_IMGFONT
|
#if LV_USE_IMGFONT
|
||||||
|
|
||||||
LV_IMAGE_DECLARE(emoji_F617)
|
LV_IMAGE_DECLARE(emoji_F617);
|
||||||
char path_buf[128];
|
char path_buf[128];
|
||||||
static const void * get_imgfont_path(const lv_font_t * font, uint32_t unicode, uint32_t unicode_next,
|
static const void * get_imgfont_path(const lv_font_t * font, uint32_t unicode, uint32_t unicode_next,
|
||||||
int32_t * offset_y, void * user_data)
|
int32_t * offset_y, void * user_data)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "../../lv_examples.h"
|
#include "../../lv_examples.h"
|
||||||
#if LV_USE_ANIMIMG && LV_BUILD_EXAMPLES
|
#if LV_USE_ANIMIMG && LV_BUILD_EXAMPLES
|
||||||
LV_IMAGE_DECLARE(animimg001)
|
LV_IMAGE_DECLARE(animimg001);
|
||||||
LV_IMAGE_DECLARE(animimg002)
|
LV_IMAGE_DECLARE(animimg002);
|
||||||
LV_IMAGE_DECLARE(animimg003)
|
LV_IMAGE_DECLARE(animimg003);
|
||||||
|
|
||||||
static const lv_image_dsc_t * anim_imgs[3] = {
|
static const lv_image_dsc_t * anim_imgs[3] = {
|
||||||
&animimg001,
|
&animimg001,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ void lv_example_dropdown_3(void)
|
|||||||
lv_dropdown_set_text(dropdown, "Menu");
|
lv_dropdown_set_text(dropdown, "Menu");
|
||||||
|
|
||||||
/*Use a custom image as down icon and flip it when the list is opened*/
|
/*Use a custom image as down icon and flip it when the list is opened*/
|
||||||
LV_IMAGE_DECLARE(img_caret_down)
|
LV_IMAGE_DECLARE(img_caret_down);
|
||||||
lv_dropdown_set_symbol(dropdown, &img_caret_down);
|
lv_dropdown_set_symbol(dropdown, &img_caret_down);
|
||||||
lv_obj_set_style_transform_rotation(dropdown, 1800, LV_PART_INDICATOR | LV_STATE_CHECKED);
|
lv_obj_set_style_transform_rotation(dropdown, 1800, LV_PART_INDICATOR | LV_STATE_CHECKED);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ void lv_example_image_2(void)
|
|||||||
lv_obj_align_to(intense_slider, blue_slider, LV_ALIGN_OUT_RIGHT_MID, 25, 0);
|
lv_obj_align_to(intense_slider, blue_slider, LV_ALIGN_OUT_RIGHT_MID, 25, 0);
|
||||||
|
|
||||||
/*Now create the actual image*/
|
/*Now create the actual image*/
|
||||||
LV_IMAGE_DECLARE(img_cogwheel_argb)
|
LV_IMAGE_DECLARE(img_cogwheel_argb);
|
||||||
img1 = lv_image_create(lv_screen_active());
|
img1 = lv_image_create(lv_screen_active());
|
||||||
lv_image_set_src(img1, &img_cogwheel_argb);
|
lv_image_set_src(img1, &img_cogwheel_argb);
|
||||||
lv_obj_align(img1, LV_ALIGN_RIGHT_MID, -20, 0);
|
lv_obj_align(img1, LV_ALIGN_RIGHT_MID, -20, 0);
|
||||||
|
|||||||
@@ -771,11 +771,22 @@
|
|||||||
#if LV_USE_SDL
|
#if LV_USE_SDL
|
||||||
#define LV_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
#define LV_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||||
#define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/
|
#define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/
|
||||||
#define LV_SDL_BUF_COUNT 1 /*1 or 2*/
|
#define LV_SDL_BUF_COUNT 1 /*1 or 2*/
|
||||||
#define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/
|
#define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/
|
||||||
#define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/
|
#define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/
|
||||||
|
#define LV_USE_X11 0
|
||||||
|
#if LV_USE_X11
|
||||||
|
#define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/
|
||||||
|
#define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/
|
||||||
|
/*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/
|
||||||
|
#define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/
|
||||||
|
#define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/
|
||||||
|
#define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/
|
||||||
|
#endif
|
||||||
|
|
||||||
/*Driver for /dev/fb*/
|
/*Driver for /dev/fb*/
|
||||||
#define LV_USE_LINUX_FBDEV 0
|
#define LV_USE_LINUX_FBDEV 0
|
||||||
#if LV_USE_LINUX_FBDEV
|
#if LV_USE_LINUX_FBDEV
|
||||||
|
|||||||
2
lvgl.h
2
lvgl.h
@@ -118,6 +118,8 @@ extern "C" {
|
|||||||
#include "src/dev/sdl/lv_sdl_mousewheel.h"
|
#include "src/dev/sdl/lv_sdl_mousewheel.h"
|
||||||
#include "src/dev/sdl/lv_sdl_keyboard.h"
|
#include "src/dev/sdl/lv_sdl_keyboard.h"
|
||||||
|
|
||||||
|
#include "src/dev/x11/lv_x11.h"
|
||||||
|
|
||||||
#include "src/dev/display/drm/lv_linux_drm.h"
|
#include "src/dev/display/drm/lv_linux_drm.h"
|
||||||
#include "src/dev/display/fb/lv_linux_fbdev.h"
|
#include "src/dev/display/fb/lv_linux_fbdev.h"
|
||||||
|
|
||||||
|
|||||||
81
src/dev/x11/lv_x11.h
Normal file
81
src/dev/x11/lv_x11.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_x11.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_X11_H
|
||||||
|
#define LV_X11_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../../display/lv_display.h"
|
||||||
|
#include "../../indev/lv_indev.h"
|
||||||
|
|
||||||
|
#if LV_USE_X11
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/** Header of private display driver user data - for internal use only */
|
||||||
|
typedef struct {
|
||||||
|
struct _XDisplay * display; /**< X11 display object */
|
||||||
|
struct _x11_inp_data * inp_data; /**< input user data object */
|
||||||
|
} _x11_user_hdr_t;
|
||||||
|
|
||||||
|
/** optional window close callback function type
|
||||||
|
* @see lv_x11_window_set_close_cb
|
||||||
|
*/
|
||||||
|
typedef void(*lv_x11_close_cb)(void * user_data);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create and add keyboard, mouse and scrillwheel objects and connect them to x11 display.
|
||||||
|
*
|
||||||
|
* This is a convenience method handling the typical input initialisation of an X11 window:
|
||||||
|
* - create keyboard (@ref lv_x11_keyboard_create)
|
||||||
|
* - create mouse (with scrollwheel, @ref lv_x11_mouse_create @ref lv_x11_mousewheel_create)
|
||||||
|
*
|
||||||
|
* @param[in] disp the created X11 display object from @ref lv_x11_window_create
|
||||||
|
* @param[in] mouse_img optional image description for the mouse cursor (NULL for no/invisible mouse cursor)
|
||||||
|
*/
|
||||||
|
void lv_x11_inputs_create(lv_display_t * disp, lv_image_dsc_t const * mouse_img);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the X11 display
|
||||||
|
*
|
||||||
|
* The minimal initialisation for initializing the X11 display driver with keyboard/mouse support:
|
||||||
|
* @code
|
||||||
|
* lv_display_t* disp = lv_x11_window_create("My Window Title", window_width, window_width);
|
||||||
|
* lv_x11_inputs_create(disp, NULL);
|
||||||
|
* @endcode
|
||||||
|
* or with mouse cursor icon:
|
||||||
|
* @code
|
||||||
|
* lv_img_dsc_t mouse_symbol = {.....};
|
||||||
|
* lv_display_t* disp = lv_x11_window_create("My Window Title", window_width, window_width);
|
||||||
|
* lv_x11_inputs_create(disp, &mouse_symbol);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @param[in] title title of the created X11 window
|
||||||
|
* @param[in] hor_res horizontal resolution (=width) of the X11 window
|
||||||
|
* @param[in] ver_res vertical resolution (=height) of the X11 window
|
||||||
|
* @return pointer to the display object
|
||||||
|
*/
|
||||||
|
lv_display_t * lv_x11_window_create(char const * title, int32_t hor_res, int32_t ver_res);
|
||||||
|
|
||||||
|
#endif /* LV_USE_X11 */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LV_X11_H */
|
||||||
395
src/dev/x11/lv_x11_display.c
Normal file
395
src/dev/x11/lv_x11_display.c
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_x11_display.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "lv_x11.h"
|
||||||
|
|
||||||
|
#if LV_USE_X11
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include "../../core/lv_obj_pos.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
|
||||||
|
#if LV_X11_RENDER_MODE_PARTIAL
|
||||||
|
#define LV_X11_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL
|
||||||
|
#elif defined LV_X11_RENDER_MODE_DIRECT
|
||||||
|
#define LV_X11_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT
|
||||||
|
#elif defined LV_X11_RENDER_MODE_FULL
|
||||||
|
#define LV_X11_RENDER_MODE LV_DISPLAY_RENDER_MODE_FULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* header (containing X Display + input user data pointer - keep aligned with x11_input module!) */
|
||||||
|
_x11_user_hdr_t hdr;
|
||||||
|
/* X11 related information */
|
||||||
|
Window window; /**< X11 window object */
|
||||||
|
GC gc; /**< X11 graphics context object */
|
||||||
|
Visual * visual; /**< X11 visual */
|
||||||
|
int dplanes; /**< X11 display depth */
|
||||||
|
XImage * ximage; /**< X11 XImage cache object for updating window content */
|
||||||
|
Atom wmDeleteMessage; /**< X11 atom to window object */
|
||||||
|
void * xdata; /**< allocated data for XImage */
|
||||||
|
/* LVGL related information */
|
||||||
|
lv_timer_t * timer; /**< timer object for @ref x11_event_handler */
|
||||||
|
lv_color_t * buffer[2]; /**< (double) lv display buffers, depending on @ref LV_X11_RENDER_MODE */
|
||||||
|
lv_area_t flush_area; /**< integrated area for a display update */
|
||||||
|
/* systemtick by thread related information */
|
||||||
|
pthread_t thr_tick; /**< pthread for SysTick simulation */
|
||||||
|
bool terminated; /**< flag to germinate SysTick simulation thread */
|
||||||
|
} x11_disp_data_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
#if LV_X11_DIRECT_EXIT
|
||||||
|
static unsigned int count_windows = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#if LV_COLOR_DEPTH == 32
|
||||||
|
typedef lv_color32_t color_t;
|
||||||
|
static inline lv_color32_t get_px(color_t p)
|
||||||
|
{
|
||||||
|
return (lv_color32_t)p;
|
||||||
|
}
|
||||||
|
#elif LV_COLOR_DEPTH == 24
|
||||||
|
typedef lv_color_t color_t;
|
||||||
|
static inline lv_color32_t get_px(color_t p)
|
||||||
|
{
|
||||||
|
lv_color32_t out = { .red = p.red, .green = p.green, .blue = p.blue };
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#elif LV_COLOR_DEPTH == 16
|
||||||
|
typedef lv_color16_t color_t;
|
||||||
|
static inline lv_color32_t get_px(color_t p)
|
||||||
|
{
|
||||||
|
lv_color32_t out = { .red = p.red << 3, .green = p.green << 2, .blue = p.blue << 3 };
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#elif LV_COLOR_DEPTH == 8
|
||||||
|
typedef uint8_t color_t;
|
||||||
|
static inline lv_color32_t get_px(color_t p)
|
||||||
|
{
|
||||||
|
lv_color32_t out = { .red = p, .green = p, .blue = p };
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#warning ("LV_COLOR_DEPTH=8 delivers black data only - open issue in lvgl?")
|
||||||
|
#else
|
||||||
|
#error ("Unsupported LV_COLOR_DEPTH")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the content of the internal buffer the specific area on the display.
|
||||||
|
* @param[in] disp the created X11 display object from @lv_x11_window_create
|
||||||
|
* @param[in] area area to be updated
|
||||||
|
* @param[in] px_map contains the rendered image as raw pixel map and it should be copied to `area` on the display.
|
||||||
|
* @note @ref lv_display_flush_ready has to be called when it's finished.
|
||||||
|
*/
|
||||||
|
static void x11_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||||
|
{
|
||||||
|
x11_disp_data_t * xd = lv_display_get_driver_data(disp);
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
static const lv_area_t inv_area = { .x1 = 0xFFFF,
|
||||||
|
.x2 = 0,
|
||||||
|
.y1 = 0xFFFF,
|
||||||
|
.y2 = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/* build display update area until lv_disp_flush_is_last */
|
||||||
|
xd->flush_area.x1 = MIN(xd->flush_area.x1, area->x1);
|
||||||
|
xd->flush_area.x2 = MAX(xd->flush_area.x2, area->x2);
|
||||||
|
xd->flush_area.y1 = MIN(xd->flush_area.y1, area->y1);
|
||||||
|
xd->flush_area.y2 = MAX(xd->flush_area.y2, area->y2);
|
||||||
|
|
||||||
|
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||||
|
|
||||||
|
uint32_t dst_offs;
|
||||||
|
lv_color32_t * dst_data;
|
||||||
|
color_t * src_data = (color_t *)px_map + (LV_X11_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL ? 0 : hor_res *
|
||||||
|
area->y1 + area->x1);
|
||||||
|
for(int16_t y = area->y1; y <= area->y2; y++) {
|
||||||
|
dst_offs = area->x1 + y * hor_res;
|
||||||
|
dst_data = &((lv_color32_t *)(xd->xdata))[dst_offs];
|
||||||
|
for(int16_t x = area->x1; x <= area->x2; x++, src_data++, dst_data++) {
|
||||||
|
*dst_data = get_px(*src_data);
|
||||||
|
}
|
||||||
|
src_data += (LV_X11_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL ? 0 : hor_res - (area->x2 - area->x1 + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lv_display_flush_is_last(disp)) {
|
||||||
|
LV_LOG_TRACE("(%d/%d), %dx%d)", xd->flush_area.x1, xd->flush_area.y1, xd->flush_area.x2 + 1 - xd->flush_area.x1,
|
||||||
|
xd->flush_area.y2 + 1 - xd->flush_area.y1);
|
||||||
|
|
||||||
|
/* refresh collected display update area only */
|
||||||
|
int16_t upd_w = xd->flush_area.x2 - xd->flush_area.x1 + 1;
|
||||||
|
int16_t upd_h = xd->flush_area.y2 - xd->flush_area.y1 + 1;
|
||||||
|
XPutImage(xd->hdr.display, xd->window, xd->gc, xd->ximage, xd->flush_area.x1, xd->flush_area.y1, xd->flush_area.x1,
|
||||||
|
xd->flush_area.y1, upd_w, upd_h);
|
||||||
|
|
||||||
|
/* invalidate collected area */
|
||||||
|
xd->flush_area = inv_area;
|
||||||
|
}
|
||||||
|
/* Inform the graphics library that you are ready with the flushing */
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event callbed by lvgl display if resolution has been changed (@ref lv_display_set_resolution has been called)
|
||||||
|
* @param[in] e event data, containing lv_display_t object
|
||||||
|
*/
|
||||||
|
static void x11_resolution_evt_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_event_get_user_data(e);
|
||||||
|
x11_disp_data_t * xd = lv_display_get_driver_data(disp);
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||||
|
int32_t ver_res = lv_display_get_vertical_resolution(disp);
|
||||||
|
|
||||||
|
if(LV_X11_RENDER_MODE != LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||||
|
/* update lvgl full-screen display draw buffers for new display size */
|
||||||
|
int sz_buffers = (hor_res * ver_res * (LV_COLOR_DEPTH + 7) / 8);
|
||||||
|
xd->buffer[0] = lv_realloc(xd->buffer[0], sz_buffers);
|
||||||
|
xd->buffer[1] = (LV_X11_DOUBLE_BUFFER ? lv_realloc(xd->buffer[1], sz_buffers) : NULL);
|
||||||
|
lv_display_set_draw_buffers(disp, xd->buffer[0], xd->buffer[1], sz_buffers, LV_X11_RENDER_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* re-create cache image with new size */
|
||||||
|
XDestroyImage(xd->ximage);
|
||||||
|
size_t sz_buffers = hor_res * ver_res * sizeof(lv_color32_t);
|
||||||
|
xd->xdata = malloc(sz_buffers); /* use clib method here, x11 memory not part of device footprint */
|
||||||
|
xd->ximage = XCreateImage(xd->hdr.display, xd->visual, xd->dplanes, ZPixmap, 0, xd->xdata,
|
||||||
|
hor_res, ver_res, lv_color_format_get_bpp(LV_COLOR_FORMAT_ARGB8888), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event callbed by lvgl display if display has been closed (@ref lv_display_remove has been called)
|
||||||
|
* @param[in] e event data, containing lv_display_t object
|
||||||
|
*/
|
||||||
|
static void x11_disp_delete_evt_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_event_get_user_data(e);
|
||||||
|
x11_disp_data_t * xd = lv_display_get_driver_data(disp);
|
||||||
|
|
||||||
|
lv_timer_delete(xd->timer);
|
||||||
|
|
||||||
|
lv_display_set_draw_buffers(disp, NULL, NULL, 0, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||||
|
lv_free(xd->buffer[0]);
|
||||||
|
if(LV_X11_DOUBLE_BUFFER) {
|
||||||
|
lv_free(xd->buffer[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
XDestroyImage(xd->ximage);
|
||||||
|
XFreeGC(xd->hdr.display, xd->gc);
|
||||||
|
XUnmapWindow(xd->hdr.display, xd->window);
|
||||||
|
XDestroyWindow(xd->hdr.display, xd->window);
|
||||||
|
XFlush(xd->hdr.display);
|
||||||
|
|
||||||
|
lv_free(xd);
|
||||||
|
#if LV_X11_DIRECT_EXIT
|
||||||
|
if(0 == --count_windows) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x11_hide_cursor(lv_display_t * disp)
|
||||||
|
{
|
||||||
|
x11_disp_data_t * xd = lv_display_get_driver_data(disp);
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
XColor black = { .red = 0, .green = 0, .blue = 0 };
|
||||||
|
char empty_data[] = { 0 };
|
||||||
|
|
||||||
|
Pixmap empty_bitmap = XCreateBitmapFromData(xd->hdr.display, xd->window, empty_data, 1, 1);
|
||||||
|
Cursor inv_cursor = XCreatePixmapCursor(xd->hdr.display, empty_bitmap, empty_bitmap, &black, &black, 0, 0);
|
||||||
|
XDefineCursor(xd->hdr.display, xd->window, inv_cursor);
|
||||||
|
XFreeCursor(xd->hdr.display, inv_cursor);
|
||||||
|
XFreePixmap(xd->hdr.display, empty_bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X11 input event handler, predicated to fetch and handle only display related events
|
||||||
|
* (Window changes)
|
||||||
|
*/
|
||||||
|
static int is_disp_event(Display * disp, XEvent * event, XPointer arg)
|
||||||
|
{
|
||||||
|
LV_UNUSED(disp);
|
||||||
|
LV_UNUSED(arg);
|
||||||
|
return (event->type == Expose
|
||||||
|
|| (event->type >= DestroyNotify && event->type <= CirculateNotify) /* events from StructureNotifyMask */
|
||||||
|
|| event->type == ClientMessage);
|
||||||
|
}
|
||||||
|
static void x11_event_handler(lv_timer_t * t)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_timer_get_user_data(t);
|
||||||
|
x11_disp_data_t * xd = lv_display_get_driver_data(disp);
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
/* handle all outstanding X events */
|
||||||
|
XEvent event;
|
||||||
|
while(XCheckIfEvent(xd->hdr.display, &event, is_disp_event, NULL)) {
|
||||||
|
LV_LOG_TRACE("Display Event %d", event.type);
|
||||||
|
switch(event.type) {
|
||||||
|
case Expose:
|
||||||
|
if(event.xexpose.count == 0) {
|
||||||
|
XPutImage(xd->hdr.display, xd->window, xd->gc, xd->ximage, 0, 0, 0, 0, event.xexpose.width, event.xexpose.height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ConfigureNotify:
|
||||||
|
if(event.xconfigure.width != lv_display_get_horizontal_resolution(disp)
|
||||||
|
|| event.xconfigure.height != lv_display_get_vertical_resolution(disp)) {
|
||||||
|
lv_display_set_resolution(disp, event.xconfigure.width, event.xconfigure.height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ClientMessage:
|
||||||
|
if(event.xclient.data.l[0] == (long)xd->wmDeleteMessage) {
|
||||||
|
xd->terminated = true;
|
||||||
|
void * ret = NULL;
|
||||||
|
pthread_join(xd->thr_tick, &ret);
|
||||||
|
lv_display_remove(disp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MapNotify:
|
||||||
|
case ReparentNotify:
|
||||||
|
/*supress unhandled warning*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_WARN("unhandled x11 event: %d", event.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * x11_tick_thread(void * data)
|
||||||
|
{
|
||||||
|
x11_disp_data_t * xd = data;
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
while(!xd->terminated) {
|
||||||
|
usleep(5000);
|
||||||
|
lv_tick_inc(5);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x11_window_create(lv_display_t * disp, char const * title)
|
||||||
|
{
|
||||||
|
x11_disp_data_t * xd = lv_display_get_driver_data(disp);
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
/* setup display/screen */
|
||||||
|
xd->hdr.display = XOpenDisplay(NULL);
|
||||||
|
int screen = XDefaultScreen(xd->hdr.display);
|
||||||
|
xd->visual = XDefaultVisual(xd->hdr.display, screen);
|
||||||
|
|
||||||
|
/* create window */
|
||||||
|
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||||
|
int32_t ver_res = lv_display_get_vertical_resolution(disp);
|
||||||
|
#if 0
|
||||||
|
/* drawing contexts for an window */
|
||||||
|
unsigned long col_fg = BlackPixel(xd->hdr.display, screen);
|
||||||
|
unsigned long col_bg = WhitePixel(xd->hdr.display, screen);
|
||||||
|
|
||||||
|
xd->window = XCreateSimpleWindow(xd->hdr.display, DefaultRootWindow(xd->hdr.display),
|
||||||
|
0, 0, hor_res, ver_res, 0, col_fg, col_bg);
|
||||||
|
#else
|
||||||
|
xd->window = XCreateWindow(xd->hdr.display, DefaultRootWindow(xd->hdr.display),
|
||||||
|
0, 0, hor_res, ver_res, 0,
|
||||||
|
DefaultDepth(xd->hdr.display, screen), InputOutput,
|
||||||
|
xd->visual, 0, NULL);
|
||||||
|
#endif
|
||||||
|
/* window manager properties (yes, use of StdProp is obsolete) */
|
||||||
|
XSetStandardProperties(xd->hdr.display, xd->window, title, NULL, None, NULL, 0, NULL);
|
||||||
|
xd->gc = XCreateGC(xd->hdr.display, xd->window, 0, 0);
|
||||||
|
|
||||||
|
/* allow receiving mouse, keyboard and window change/close events */
|
||||||
|
XSelectInput(xd->hdr.display, xd->window,
|
||||||
|
PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ExposureMask |
|
||||||
|
StructureNotifyMask);
|
||||||
|
xd->wmDeleteMessage = XInternAtom(xd->hdr.display, "WM_DELETE_WINDOW", False);
|
||||||
|
XSetWMProtocols(xd->hdr.display, xd->window, &xd->wmDeleteMessage, 1);
|
||||||
|
|
||||||
|
x11_hide_cursor(disp);
|
||||||
|
|
||||||
|
/* create cache XImage */
|
||||||
|
size_t sz_buffers = hor_res * ver_res * sizeof(lv_color32_t);
|
||||||
|
xd->dplanes = XDisplayPlanes(xd->hdr.display, screen);
|
||||||
|
xd->xdata = malloc(sz_buffers); /* use clib method here, x11 memory not part of device footprint */
|
||||||
|
xd->ximage = XCreateImage(xd->hdr.display, xd->visual, xd->dplanes, ZPixmap, 0, xd->xdata,
|
||||||
|
hor_res, ver_res, lv_color_format_get_bpp(LV_COLOR_FORMAT_ARGB8888), 0);
|
||||||
|
|
||||||
|
/* finally bring window on top of the other windows */
|
||||||
|
XMapRaised(xd->hdr.display, xd->window);
|
||||||
|
|
||||||
|
#if LV_X11_DIRECT_EXIT
|
||||||
|
count_windows++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
lv_display_t * lv_x11_window_create(char const * title, int32_t hor_res, int32_t ver_res)
|
||||||
|
{
|
||||||
|
x11_disp_data_t * xd = lv_malloc_zeroed(sizeof(x11_disp_data_t));
|
||||||
|
LV_ASSERT_MALLOC(xd);
|
||||||
|
if(NULL == xd) return NULL;
|
||||||
|
|
||||||
|
lv_display_t * disp = lv_display_create(hor_res, ver_res);
|
||||||
|
if(NULL == disp) {
|
||||||
|
lv_free(xd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lv_display_set_driver_data(disp, xd);
|
||||||
|
lv_display_set_flush_cb(disp, x11_flush_cb);
|
||||||
|
lv_display_add_event(disp, x11_resolution_evt_cb, LV_EVENT_RESOLUTION_CHANGED, disp);
|
||||||
|
lv_display_add_event(disp, x11_disp_delete_evt_cb, LV_EVENT_DELETE, disp);
|
||||||
|
|
||||||
|
x11_window_create(disp, title);
|
||||||
|
|
||||||
|
int sz_buffers = (hor_res * ver_res * (LV_COLOR_DEPTH + 7) / 8);
|
||||||
|
if(LV_X11_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||||
|
sz_buffers /= 10;
|
||||||
|
}
|
||||||
|
xd->buffer[0] = lv_malloc(sz_buffers);
|
||||||
|
xd->buffer[1] = (LV_X11_DOUBLE_BUFFER ? lv_malloc(sz_buffers) : NULL);
|
||||||
|
lv_display_set_draw_buffers(disp, xd->buffer[0], xd->buffer[1], sz_buffers, LV_X11_RENDER_MODE);
|
||||||
|
|
||||||
|
xd->timer = lv_timer_create(x11_event_handler, 5, disp);
|
||||||
|
|
||||||
|
/* initialize Tick simulation */
|
||||||
|
xd->terminated = false;
|
||||||
|
pthread_create(&xd->thr_tick, NULL, x11_tick_thread, xd);
|
||||||
|
|
||||||
|
return disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_X11*/
|
||||||
279
src/dev/x11/lv_x11_input.c
Normal file
279
src/dev/x11/lv_x11_input.c
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_x11_input.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "lv_x11.h"
|
||||||
|
|
||||||
|
#if LV_USE_X11
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include "../../stdlib/lv_string.h"
|
||||||
|
#include "../../widgets/image/lv_image.h"
|
||||||
|
#include "../../core/lv_obj.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
typedef struct _x11_inp_data {
|
||||||
|
/* LVGL related information */
|
||||||
|
lv_group_t * inp_group; /**< input group for X input elements */
|
||||||
|
lv_indev_t * keyboard; /**< keyboard input device object */
|
||||||
|
lv_indev_t * mousepointer; /**< mouse input device object */
|
||||||
|
lv_indev_t * mousewheel; /**< encoder input device object */
|
||||||
|
lv_timer_t * timer; /**< timer object for @ref x11_event_handler */
|
||||||
|
/* user input related information */
|
||||||
|
char kb_buffer[32]; /**< keyboard buffer for X keyboard inpputs */
|
||||||
|
lv_point_t mouse_pos; /**< current reported mouse position */
|
||||||
|
bool left_mouse_btn; /**< current state of left mouse button */
|
||||||
|
bool right_mouse_btn; /**< current state of right mouse button */
|
||||||
|
bool wheel_mouse_btn; /**< current state of wheel (=middle) mouse button */
|
||||||
|
int16_t wheel_cnt; /**< mouse wheel increments */
|
||||||
|
} x11_inp_data_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X11 input event handler, predicated to fetch and handle only input related events
|
||||||
|
* (MotionNotify, ButtonPress/Release, KeyPress/Release)
|
||||||
|
*/
|
||||||
|
static int is_inp_event(Display * disp, XEvent * event, XPointer arg)
|
||||||
|
{
|
||||||
|
LV_UNUSED(disp);
|
||||||
|
LV_UNUSED(arg);
|
||||||
|
return !(event->type == Expose
|
||||||
|
|| (event->type >= DestroyNotify && event->type <= CirculateNotify) /* events from StructureNotifyMask */
|
||||||
|
|| event->type == ClientMessage);
|
||||||
|
}
|
||||||
|
static void x11_inp_event_handler(lv_timer_t * t)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_timer_get_user_data(t);
|
||||||
|
_x11_user_hdr_t * disp_hdr = lv_display_get_driver_data(disp);
|
||||||
|
x11_inp_data_t * xd = disp_hdr->inp_data;
|
||||||
|
|
||||||
|
/* handle all outstanding X events */
|
||||||
|
XEvent event;
|
||||||
|
while(XCheckIfEvent(disp_hdr->display, &event, is_inp_event, NULL)) {
|
||||||
|
LV_LOG_TRACE("Input Event %d", event.type);
|
||||||
|
switch(event.type) {
|
||||||
|
case MotionNotify:
|
||||||
|
xd->mouse_pos.x = event.xmotion.x;
|
||||||
|
xd->mouse_pos.y = event.xmotion.y;
|
||||||
|
break;
|
||||||
|
case ButtonPress:
|
||||||
|
switch(event.xbutton.button) {
|
||||||
|
case Button1:
|
||||||
|
xd->left_mouse_btn = true;
|
||||||
|
break;
|
||||||
|
case Button2:
|
||||||
|
xd->wheel_mouse_btn = true;
|
||||||
|
break;
|
||||||
|
case Button3:
|
||||||
|
xd->right_mouse_btn = true;
|
||||||
|
break;
|
||||||
|
case Button4: /* Scrolled up */
|
||||||
|
xd->wheel_cnt--;
|
||||||
|
break;
|
||||||
|
case Button5: /* Scrolled down */
|
||||||
|
xd->wheel_cnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_WARN("unhandled button press : %d", event.xbutton.button);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ButtonRelease:
|
||||||
|
switch(event.xbutton.button) {
|
||||||
|
case Button1:
|
||||||
|
xd->left_mouse_btn = false;
|
||||||
|
break;
|
||||||
|
case Button2:
|
||||||
|
xd->wheel_mouse_btn = false;
|
||||||
|
break;
|
||||||
|
case Button3:
|
||||||
|
xd->right_mouse_btn = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KeyPress: {
|
||||||
|
size_t len = strlen(xd->kb_buffer);
|
||||||
|
if(len < (sizeof(xd->kb_buffer) - 2 /* space for 1 char + '\0' */)) {
|
||||||
|
KeySym key;
|
||||||
|
int n = XLookupString(&event.xkey, &xd->kb_buffer[len], sizeof(xd->kb_buffer) - (len + 1), &key, NULL);
|
||||||
|
xd->kb_buffer[len + n] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KeyRelease:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_WARN("unhandled x11 event: %d", event.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event callbed by lvgl display if display has been closed (@ref lv_display_remove has been called)
|
||||||
|
* @param[in] e event data, containing lv_display_t object
|
||||||
|
*/
|
||||||
|
static void x11_inp_delete_evt_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
x11_inp_data_t * xd = (x11_inp_data_t *)lv_event_get_user_data(e);
|
||||||
|
|
||||||
|
lv_timer_delete(xd->timer);
|
||||||
|
lv_free(xd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the local data/timers for the X11 input functionality.
|
||||||
|
* extracts the user data information from lv_display_t object and initializes the input user object on 1st use.
|
||||||
|
* @param[in] disp the created X11 display object from @lv_x11_window_create
|
||||||
|
* @return pointer to the local user data object @x11_inp_data_t
|
||||||
|
*/
|
||||||
|
static x11_inp_data_t * x11_input_get_user_data(lv_display_t * disp)
|
||||||
|
{
|
||||||
|
_x11_user_hdr_t * disp_hdr = lv_display_get_driver_data(disp);
|
||||||
|
LV_ASSERT_NULL(disp_hdr);
|
||||||
|
x11_inp_data_t ** inp_data = &disp_hdr->inp_data;
|
||||||
|
|
||||||
|
/* create input data set if initial call */
|
||||||
|
if(NULL == *inp_data) {
|
||||||
|
*inp_data = lv_malloc_zeroed(sizeof(x11_inp_data_t));
|
||||||
|
LV_ASSERT_MALLOC(*inp_data);
|
||||||
|
if(NULL != *inp_data) {
|
||||||
|
/* initialize timer callback for X11 kb/mouse input event reading */
|
||||||
|
(*inp_data)->timer = lv_timer_create(x11_inp_event_handler, 1, disp);
|
||||||
|
lv_display_add_event(disp, x11_inp_delete_evt_cb, LV_EVENT_DELETE, *inp_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *inp_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x11_keyboard_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_indev_get_driver_data(indev);
|
||||||
|
x11_inp_data_t * xd = x11_input_get_user_data(disp);
|
||||||
|
|
||||||
|
size_t len = strlen(xd->kb_buffer);
|
||||||
|
if(len > 0) {
|
||||||
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
|
data->key = xd->kb_buffer[0];
|
||||||
|
memmove(xd->kb_buffer, xd->kb_buffer + 1, len);
|
||||||
|
data->continue_reading = (len > 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->state = LV_INDEV_STATE_RELEASED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x11_mouse_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_indev_get_driver_data(indev);
|
||||||
|
x11_inp_data_t * xd = x11_input_get_user_data(disp);
|
||||||
|
|
||||||
|
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||||
|
int32_t ver_res = lv_display_get_vertical_resolution(disp);
|
||||||
|
|
||||||
|
xd->mouse_pos.x = MIN(xd->mouse_pos.x, hor_res - 1);
|
||||||
|
xd->mouse_pos.y = MIN(xd->mouse_pos.y, ver_res - 1);
|
||||||
|
|
||||||
|
data->point = xd->mouse_pos;
|
||||||
|
data->state = xd->left_mouse_btn ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x11_mousewheel_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = lv_indev_get_driver_data(indev);
|
||||||
|
x11_inp_data_t * xd = x11_input_get_user_data(disp);
|
||||||
|
|
||||||
|
data->state = xd->wheel_mouse_btn ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||||
|
data->enc_diff = xd->wheel_cnt;
|
||||||
|
xd->wheel_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_indev_t * lv_x11_keyboard_create(lv_display_t * disp)
|
||||||
|
{
|
||||||
|
lv_indev_t * indev = lv_indev_create();
|
||||||
|
LV_ASSERT_OBJ(indev, MY_CLASS);
|
||||||
|
if(NULL != indev) {
|
||||||
|
lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
|
||||||
|
lv_indev_set_read_cb(indev, x11_keyboard_read_cb);
|
||||||
|
lv_indev_set_driver_data(indev, disp);
|
||||||
|
}
|
||||||
|
return indev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_indev_t * lv_x11_mouse_create(lv_display_t * disp, lv_image_dsc_t const * symb)
|
||||||
|
{
|
||||||
|
lv_indev_t * indev = lv_indev_create();
|
||||||
|
LV_ASSERT_OBJ(indev, MY_CLASS);
|
||||||
|
if(NULL != indev) {
|
||||||
|
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
|
||||||
|
lv_indev_set_read_cb(indev, x11_mouse_read_cb);
|
||||||
|
lv_indev_set_driver_data(indev, disp);
|
||||||
|
|
||||||
|
/* optional mouse cursor symbol */
|
||||||
|
if(NULL != symb) {
|
||||||
|
lv_obj_t * mouse_cursor = lv_image_create(lv_screen_active());
|
||||||
|
lv_image_set_src(mouse_cursor, symb);
|
||||||
|
lv_indev_set_cursor(indev, mouse_cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return indev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_indev_t * lv_x11_mousewheel_create(lv_display_t * disp)
|
||||||
|
{
|
||||||
|
lv_indev_t * indev = lv_indev_create();
|
||||||
|
LV_ASSERT_OBJ(indev, MY_CLASS);
|
||||||
|
if(NULL != indev) {
|
||||||
|
lv_indev_set_type(indev, LV_INDEV_TYPE_ENCODER);
|
||||||
|
lv_indev_set_read_cb(indev, x11_mousewheel_read_cb);
|
||||||
|
lv_indev_set_driver_data(indev, disp);
|
||||||
|
}
|
||||||
|
return indev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_x11_inputs_create(lv_display_t * disp, lv_image_dsc_t const * mouse_img)
|
||||||
|
{
|
||||||
|
x11_inp_data_t * xd = x11_input_get_user_data(disp);
|
||||||
|
LV_ASSERT_NULL(xd);
|
||||||
|
|
||||||
|
xd->inp_group = lv_group_create();
|
||||||
|
lv_group_set_default(xd->inp_group);
|
||||||
|
|
||||||
|
xd->mousepointer = lv_x11_mouse_create(disp, mouse_img);
|
||||||
|
lv_indev_set_group(xd->mousepointer, xd->inp_group);
|
||||||
|
|
||||||
|
xd->mousewheel = lv_x11_mousewheel_create(disp);
|
||||||
|
lv_indev_set_group(xd->mousewheel, xd->inp_group);
|
||||||
|
|
||||||
|
xd->keyboard = lv_x11_keyboard_create(disp);
|
||||||
|
lv_indev_set_group(xd->keyboard, xd->inp_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_X11*/
|
||||||
@@ -2501,7 +2501,7 @@
|
|||||||
#define LV_SDL_BUF_COUNT 0
|
#define LV_SDL_BUF_COUNT 0
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define LV_SDL_BUF_COUNT 1 /*1 or 2*/
|
#define LV_SDL_BUF_COUNT 1 /*1 or 2*/
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef LV_SDL_FULLSCREEN
|
#ifndef LV_SDL_FULLSCREEN
|
||||||
@@ -2524,6 +2524,65 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/
|
||||||
|
#ifndef LV_USE_X11
|
||||||
|
#ifdef CONFIG_LV_USE_X11
|
||||||
|
#define LV_USE_X11 CONFIG_LV_USE_X11
|
||||||
|
#else
|
||||||
|
#define LV_USE_X11 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if LV_USE_X11
|
||||||
|
#ifndef LV_X11_DIRECT_EXIT
|
||||||
|
#ifdef _LV_KCONFIG_PRESENT
|
||||||
|
#ifdef CONFIG_LV_X11_DIRECT_EXIT
|
||||||
|
#define LV_X11_DIRECT_EXIT CONFIG_LV_X11_DIRECT_EXIT
|
||||||
|
#else
|
||||||
|
#define LV_X11_DIRECT_EXIT 0
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef LV_X11_DOUBLE_BUFFER
|
||||||
|
#ifdef _LV_KCONFIG_PRESENT
|
||||||
|
#ifdef CONFIG_LV_X11_DOUBLE_BUFFER
|
||||||
|
#define LV_X11_DOUBLE_BUFFER CONFIG_LV_X11_DOUBLE_BUFFER
|
||||||
|
#else
|
||||||
|
#define LV_X11_DOUBLE_BUFFER 0
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
/*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/
|
||||||
|
#ifndef LV_X11_RENDER_MODE_PARTIAL
|
||||||
|
#ifdef _LV_KCONFIG_PRESENT
|
||||||
|
#ifdef CONFIG_LV_X11_RENDER_MODE_PARTIAL
|
||||||
|
#define LV_X11_RENDER_MODE_PARTIAL CONFIG_LV_X11_RENDER_MODE_PARTIAL
|
||||||
|
#else
|
||||||
|
#define LV_X11_RENDER_MODE_PARTIAL 0
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef LV_X11_RENDER_MODE_DIRECT
|
||||||
|
#ifdef CONFIG_LV_X11_RENDER_MODE_DIRECT
|
||||||
|
#define LV_X11_RENDER_MODE_DIRECT CONFIG_LV_X11_RENDER_MODE_DIRECT
|
||||||
|
#else
|
||||||
|
#define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef LV_X11_RENDER_MODE_FULL
|
||||||
|
#ifdef CONFIG_LV_X11_RENDER_MODE_FULL
|
||||||
|
#define LV_X11_RENDER_MODE_FULL CONFIG_LV_X11_RENDER_MODE_FULL
|
||||||
|
#else
|
||||||
|
#define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*Driver for /dev/fb*/
|
/*Driver for /dev/fb*/
|
||||||
#ifndef LV_USE_LINUX_FBDEV
|
#ifndef LV_USE_LINUX_FBDEV
|
||||||
#ifdef CONFIG_LV_USE_LINUX_FBDEV
|
#ifdef CONFIG_LV_USE_LINUX_FBDEV
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ void _lv_ll_clear_custom(lv_ll_t * ll_p, void(*cleanup)(void *));
|
|||||||
*/
|
*/
|
||||||
static inline void _lv_ll_clear(lv_ll_t * ll_p)
|
static inline void _lv_ll_clear(lv_ll_t * ll_p)
|
||||||
{
|
{
|
||||||
return _lv_ll_clear_custom(ll_p, NULL);
|
_lv_ll_clear_custom(ll_p, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ lv_image_align_t lv_image_get_align(lv_obj_t * obj);
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/** Use this macro to declare an image in a C file*/
|
/** Use this macro to declare an image in a C file*/
|
||||||
#define LV_IMAGE_DECLARE(var_name) extern const lv_image_dsc_t var_name;
|
#define LV_IMAGE_DECLARE(var_name) extern const lv_image_dsc_t var_name
|
||||||
|
|
||||||
#endif /*LV_USE_IMG*/
|
#endif /*LV_USE_IMG*/
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
#include "unity/unity.h"
|
#include "unity/unity.h"
|
||||||
#include "lv_test_indev.h"
|
#include "lv_test_indev.h"
|
||||||
|
|
||||||
LV_IMAGE_DECLARE(test_animimg001)
|
LV_IMAGE_DECLARE(test_animimg001);
|
||||||
LV_IMAGE_DECLARE(test_animimg002)
|
LV_IMAGE_DECLARE(test_animimg002);
|
||||||
LV_IMAGE_DECLARE(test_animimg003)
|
LV_IMAGE_DECLARE(test_animimg003);
|
||||||
|
|
||||||
static const lv_image_dsc_t * anim_imgs[3] = {
|
static const lv_image_dsc_t * anim_imgs[3] = {
|
||||||
&test_animimg001,
|
&test_animimg001,
|
||||||
|
|||||||
Reference in New Issue
Block a user