Skip to content

Commit 8b106e2

Browse files
authored
feat(wayland): add Wayland support (#51)
* fix(wayland) Rebase master to get the latest changes * chore(wayland) adjust example code * chore(wayland) align with driver, wait only if the cycle was fully completed * feat(wayland) Simplify CMakeLists file Use external scripts to obtain the selected backend in lv_conf.h Generate wayland protocol via a shell script instead of CMake * fix(wayland) - Remove test script * doc(wayland) Update documentation Remove the step that tells to edit the CMakeLists.txt file and manually enable the option to select the backend * feat(wayland) Move wayland display init and runloop to a separate file Solve merge conflit with the main branch * fix(wayland) Re-apply the delay timer execution only until the next timer fires up * fix(wayland) adjust CI * fix(wayland) fix CI
1 parent eb945a8 commit 8b106e2

File tree

9 files changed

+306
-85
lines changed

9 files changed

+306
-85
lines changed

.github/workflows/build.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
sed -i "s/^#define LV_USE_LINUX_DRM.*$/#define LV_USE_LINUX_DRM 0/g" lv_conf.h && \
4242
sed -i "s/^#define LV_USE_SDL.*$/#define LV_USE_SDL 0/g" lv_conf.h && \
4343
docker run --rm -v "$(pwd)":/workdir -t test_${{ matrix.os.image }} \
44-
/bin/bash -ec "mkdir build/ && cd build/ && cmake .. && make -j && ldd ../bin/main"
44+
/bin/bash -ec "cmake -B build -S . && make -j -C build && ldd bin/lvglsim"
4545
4646
- name: DRM Test building the project
4747
run: |
@@ -50,7 +50,7 @@ jobs:
5050
sed -i "s/^#define LV_USE_LINUX_DRM.*$/#define LV_USE_LINUX_DRM 1/g" lv_conf.h && \
5151
sed -i "s/^#define LV_USE_SDL.*$/#define LV_USE_SDL 0/g" lv_conf.h && \
5252
docker run --rm -v "$(pwd)":/workdir -t test_${{ matrix.os.image }} \
53-
/bin/bash -ec "mkdir build/ && cd build/ && cmake .. && make -j && ldd ../bin/main"
53+
/bin/bash -ec "cmake -B build -S . && make -j -C build && ldd bin/lvglsim"
5454
5555
- name: SDL Test building the project
5656
run: |
@@ -59,4 +59,5 @@ jobs:
5959
sed -i "s/^#define LV_USE_LINUX_DRM.*$/#define LV_USE_LINUX_DRM 0/g" lv_conf.h && \
6060
sed -i "s/^#define LV_USE_SDL.*$/#define LV_USE_SDL 1/g" lv_conf.h && \
6161
docker run --rm -v "$(pwd)":/workdir -t test_${{ matrix.os.image }} \
62-
/bin/bash -ec "mkdir build/ && cd build/ && cmake .. && make -j && ldd ../bin/main"
62+
/bin/bash -ec "cmake -B build -S . && make -j -C build && ldd bin/lvglsim"
63+

CMakeLists.txt

+59-25
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,67 @@
11
cmake_minimum_required(VERSION 3.10)
22
project(lvgl)
33

4-
set(CMAKE_C_STANDARD 99)#C99 # lvgl officially support C99 and above
5-
set(CMAKE_CXX_STANDARD 17)#C17
6-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
4+
foreach(BACKEND_NAME "SDL" "LINUX_DRM" "LINUX_FBDEV" "X11" "WAYLAND")
5+
execute_process(COMMAND "scripts/backend_conf.sh" ${BACKEND_NAME} OUTPUT_VARIABLE IS_BACKEND_ENABLED)
6+
set("LV_USE_${BACKEND_NAME}" ${IS_BACKEND_ENABLED})
7+
endforeach()
78

8-
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
9+
# Uncomment if the program needs debugging
10+
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb")
911

12+
set(CMAKE_C_STANDARD 99) # LVGL officially supports C99 and above
13+
set(CMAKE_CXX_STANDARD 17) #C17
14+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
15+
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
1016
add_subdirectory(lvgl)
11-
add_executable(main main.c mouse_cursor_icon.c)
17+
target_include_directories(lvgl PUBLIC ${PROJECT_SOURCE_DIR})
1218

13-
find_package(PkgConfig REQUIRED) # We use the platform independent pkg-config to find all the libs
14-
pkg_check_modules(LIBDRM REQUIRED libdrm)
15-
pkg_check_modules(SDL2 REQUIRED sdl2)
16-
pkg_check_modules(SDL2_image REQUIRED SDL2_image)
19+
if (LV_USE_LINUX_DRM)
1720

18-
target_include_directories(lvgl PUBLIC ${PROJECT_SOURCE_DIR})
19-
target_include_directories(lvgl PRIVATE ${SDL2_INCLUDE_DIRS})
20-
target_include_directories(lvgl PRIVATE ${SDL2_IMAGE_INCLUDE_DIRS})
21-
target_include_directories(lvgl PRIVATE ${LIBDRM_INCLUDE_DIRS})
22-
23-
target_link_libraries(main PRIVATE lvgl) # Add '-static' if you want a standalone binary
24-
target_link_libraries(main PRIVATE lvgl::examples)
25-
target_link_libraries(main PRIVATE lvgl::demos)
26-
target_link_libraries(main PRIVATE lvgl::thorvg)
27-
target_link_libraries(main PRIVATE ${SDL2_LIBRARIES})
28-
target_link_libraries(main PRIVATE ${SDL2_IMAGE_LIBRARIES})
29-
target_link_libraries(main PRIVATE ${LIBDRM_LIBRARIES})
30-
target_link_libraries(main PRIVATE m)
31-
target_link_libraries(main PRIVATE pthread)
32-
33-
add_custom_target(run COMMAND ${EXECUTABLE_OUTPUT_PATH}/main DEPENDS main)
21+
find_package(PkgConfig REQUIRED)
22+
pkg_check_modules(LIBDRM REQUIRED libdrm)
23+
24+
target_include_directories(lvgl PUBLIC ${LIBDRM_INCLUDE_DIRS})
25+
add_executable(lvglsim main.c mouse_cursor_icon.c)
26+
target_link_libraries(lvglsim lvgl lvgl::examples lvgl::demos lvgl::thorvg ${LIBDRM_LIBRARIES} m pthread)
27+
28+
elseif (LV_USE_SDL)
29+
30+
find_package(PkgConfig REQUIRED)
31+
pkg_check_modules(SDL2 REQUIRED sdl2)
32+
pkg_check_modules(SDL2_image REQUIRED SDL2_image)
33+
34+
target_include_directories(lvgl PRIVATE ${SDL2_INCLUDE_DIRS})
35+
target_include_directories(lvgl PRIVATE ${SDL2_IMAGE_INCLUDE_DIRS})
36+
add_executable(lvglsim main.c mouse_cursor_icon.c)
37+
target_link_libraries(lvglsim lvgl lvgl::examples lvgl::demos lvgl::thorvg ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} m pthread)
38+
39+
elseif (LV_USE_WAYLAND)
40+
41+
find_package(PkgConfig REQUIRED)
42+
pkg_check_modules(wayland-client REQUIRED wayland-client)
43+
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
44+
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
45+
46+
# Wayland protocols
47+
pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.25)
48+
pkg_get_variable(WAYLAND_PROTOCOLS_BASE wayland-protocols pkgdatadir)
49+
50+
execute_process(COMMAND "scripts/gen_wl_protocols.sh" OUTPUT_VARIABLE WAYLAND_PROTOCOLS_SRC)
51+
52+
target_include_directories(lvgl PRIVATE ${PROJECT_SOURCE_DIR}
53+
"${PROJECT_SOURCE_DIR}/wl_protocols")
54+
add_executable(lvglsim main.c ${WAYLAND_PROTOCOLS_SRC}
55+
mouse_cursor_icon.c backends/wayland.c)
56+
target_compile_definitions(lvglsim PRIVATE LV_CONF_INCLUDE_SIMPLE)
57+
target_link_libraries(lvglsim lvgl lvgl::examples lvgl::demos lvgl::thorvg m
58+
wayland-client wayland-cursor xkbcommon)
59+
60+
else()
61+
62+
# No specific build steps required for FBDEV
63+
add_executable(lvglsim main.c mouse_cursor_icon.c)
64+
target_link_libraries(lvglsim lvgl lvgl::examples lvgl::demos lvgl::thorvg m pthread)
65+
endif()
66+
67+
add_custom_target (run COMMAND ${EXECUTABLE_OUTPUT_PATH}/lvglsim DEPENDS lvglsim)

README.md

+48-29
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# LVGL on top of Linux graphics stack
22

33
Example project to use LVGL on top of Linux graphics stack.
4-
Currently supported backends are either legacy framebuffer
5-
(fbdev), modern DRM/KMS, or SDL2.
4+
Currently supported backends are legacy framebuffer
5+
(fbdev), modern DRM/KMS, Wayland or SDL2.
66

77
By default, legacy framebuffer backend uses `/dev/fb0` device node,
88
DRM/KMS backend uses '/dev/dri/card0' card node, SDL2 uses window
@@ -24,38 +24,47 @@ cd lv_port_linux/
2424
git submodule update --init --recursive
2525
```
2626

27-
## Select graphics backend (optional)
27+
## Select graphics backend
2828

2929
To use legacy framebuffer (fbdev) support, adjust `lv_conf.h` as follows:
3030
```
3131
#define LV_USE_LINUX_FBDEV 1
3232
#define LV_USE_LINUX_DRM 0
3333
#define LV_USE_SDL 0
34+
#define LV_USE_WAYLAND 0
3435
```
3536

3637
To use modern DRM/KMS support, adjust `lv_conf.h` as follows:
3738
```
3839
#define LV_USE_LINUX_FBDEV 0
3940
#define LV_USE_LINUX_DRM 1
4041
#define LV_USE_SDL 0
42+
#define LV_USE_WAYLAND 0
4143
```
4244

4345
To use SDL2 support, adjust `lv_conf.h` as follows:
4446
```
4547
#define LV_USE_LINUX_FBDEV 0
4648
#define LV_USE_LINUX_DRM 0
4749
#define LV_USE_SDL 1
50+
#define LV_USE_WAYLAND 0
51+
```
52+
53+
54+
To use wayland, adjust `lv_conf.h` as follows:
55+
```
56+
#define LV_USE_LINUX_FBDEV 0
57+
#define LV_USE_LINUX_DRM 0
58+
#define LV_USE_SDL 0
59+
#define LV_USE_WAYLAND 1
4860
```
4961

50-
## Build the project (cmake or Makefile)
5162

5263
### cmake
5364

5465
```
55-
mkdir build
56-
cd build
57-
cmake ..
58-
make -j
66+
cmake -B build -S .
67+
make -C build -j
5968
```
6069

6170
### Makefile
@@ -64,10 +73,25 @@ make -j
6473
make -j
6574
```
6675

76+
## Command line options
77+
78+
Command line options are used to modify behavior of the demo, they take precedence over environment variables.
79+
80+
### Wayland
81+
82+
- `-f` - enters fullscreen on startup
83+
- `-m` - maximizes window on startup
84+
- `-w <window width>` - set the width of the window
85+
- `-h <window height>` - set the height of the window
86+
87+
### SDL2
88+
89+
- `-w <window width>` - set the width of the window
90+
- `-h <window height>` - set the height of the window
91+
6792
## Environment variables
6893

69-
Environment variables can be set to modify behavior of the demo.
70-
The following variables are supported.
94+
Environment variables can be set to modify the behavior of the demo.
7195

7296
### Legacy framebuffer (fbdev)
7397

@@ -84,19 +108,25 @@ The following variables are supported.
84108

85109
### SDL2
86110

87-
- `LV_SDL_VIDEO_WIDTH` - width of SDL2 surface (default `800`).
88-
- `LV_SDL_VIDEO_HEIGHT` - height of SDL2 surface (default `480`).
111+
- `LV_SIM_WINDOW_WIDTH` - width of SDL2 surface (default `800`).
112+
- `LV_SIM_WINDOW_HEIGHT` - height of SDL2 surface (default `480`).
113+
114+
### Wayland
115+
116+
- `LV_SIM_WINDOW_WIDTH` - width of the window (default `800`).
117+
- `LV_SIM_WINDOW_HEIGHT` - height of the window (default `480`).
118+
89119

90120
## Run the demo application
91121

92-
### As root
122+
### FBDEV
93123

94-
Normal users don't have access to `/dev/fb0` so use `sudo` (or see below) :
124+
Unpriviledged users don't have access to the framebuffer device `/dev/fb0`
125+
`sudo` or `su` must be used.
95126

96127
cmake:
97128
```
98-
cd ../bin
99-
sudo main
129+
sudo ./bin/lvglsim
100130
```
101131

102132
Makefile:
@@ -105,23 +135,12 @@ cd build/bin/
105135
sudo main
106136
```
107137

108-
### Userland
109-
110-
You can give a normal user access to the framebuffer by adding them to the `video` group :
111-
138+
Access to the framebuffer device can be granted by adding the unpriviledged user to the `video` group
112139

113140
cmake:
114141
```
115142
sudo adduser $USER video
116143
newgrp video
117-
cd ../bin
118-
./main
144+
./bin/lvglsim
119145
```
120146

121-
Makefile:
122-
```
123-
sudo adduser $USER video
124-
newgrp video
125-
cd build/bin/
126-
./main
127-
```

backends/interface.h

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
/* Enters the run loop of the selected backend */
3+
void lv_linux_run_loop(void);
4+
5+
/* Initializes the display */
6+
void lv_linux_disp_init(void);

backends/settings.h

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <stdbool.h>
2+
#include <stdint.h>
3+
4+
/* Settings defined in main.c */
5+
6+
extern uint16_t window_width;
7+
extern uint16_t window_height;
8+
9+
extern bool fullscreen;
10+
extern bool maximize;
11+

backends/wayland.c

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include <unistd.h>
2+
#include <stdlib.h>
3+
4+
#include "lvgl/lvgl.h"
5+
#include "settings.h"
6+
7+
/* Currently, the wayland driver calls lv_timer_handler internaly */
8+
void lv_linux_run_loop(void)
9+
{
10+
11+
bool completed;
12+
13+
/* Handle LVGL tasks */
14+
while (1) {
15+
16+
completed = lv_wayland_timer_handler();
17+
18+
if (completed) {
19+
/* wait only if the cycle was completed */
20+
usleep(LV_DEF_REFR_PERIOD * 1000);
21+
}
22+
23+
/* Run until the last window closes */
24+
if (!lv_wayland_window_is_open(NULL)) {
25+
break;
26+
}
27+
}
28+
29+
}
30+
31+
void lv_linux_disp_init(void)
32+
{
33+
lv_display_t *disp;
34+
lv_group_t *g;
35+
36+
disp = lv_wayland_window_create(window_width, window_height,
37+
"LVGL Simulator", NULL);
38+
39+
if (fullscreen) {
40+
lv_wayland_window_set_fullscreen(disp, fullscreen);
41+
} else if (maximize) {
42+
lv_wayland_window_set_maximized(disp, maximize);
43+
}
44+
45+
g = lv_group_create();
46+
lv_group_set_default(g);
47+
lv_indev_set_group(lv_wayland_get_keyboard(disp), g);
48+
lv_indev_set_group(lv_wayland_get_pointeraxis(disp), g);
49+
50+
}

0 commit comments

Comments
 (0)