├── .clang-format ├── .gitignore ├── README.md ├── SConstruct ├── awtk-port ├── SConscript ├── devices.c ├── devices.h ├── egl_devices │ ├── egl_devices.h │ ├── fsl │ │ ├── egl_devices.c │ │ ├── fsl_egl.c │ │ └── fsl_egl.h │ ├── gbm │ │ └── egl_devices.c │ └── x11 │ │ └── egl_devices.c ├── input_thread │ ├── common_coord.c │ ├── common_coord.h │ ├── input_dispatcher.c │ ├── input_dispatcher.h │ ├── input_thread.c │ ├── input_thread.h │ ├── mouse_thread.c │ ├── mouse_thread.h │ ├── tslib_thread.c │ └── tslib_thread.h ├── lcd_linux │ ├── fb_info.h │ ├── lcd_linux_drm.c │ ├── lcd_linux_drm.h │ ├── lcd_linux_egl.c │ ├── lcd_linux_egl.h │ ├── lcd_linux_fb.c │ ├── lcd_linux_fb.h │ ├── lcd_mem_others.c │ └── lcd_mem_others.h ├── main_loop_linux.c ├── main_loop_linux.h └── test │ ├── fb_test.c │ ├── input_thread_test.c │ ├── mouse_thread_test.c │ └── tslib_thread_test.c ├── awtk-wayland ├── SConscript ├── egl_for_wayland │ ├── input_dispatch.c │ ├── lcd_wayland.c │ ├── lcd_wayland.h │ ├── main_loop_wayland.c │ ├── wayland_input_devices.c │ ├── wayland_keyboard.c │ ├── wayland_tools.c │ └── wayland_tools.h ├── protocol │ ├── fullscreen-shell-unstable-v1.xml │ └── xdg-shell.xml └── wayland │ ├── input_dispatch.c │ ├── lcd_wayland.c │ ├── lcd_wayland.h │ ├── main_loop_wayland.c │ ├── pthread_signal.h │ ├── wayland_input_devices.c │ ├── wayland_keyboard.c │ ├── wayland_tools.c │ └── wayland_tools.h ├── awtk_config.py ├── awtk_config_common.py ├── config ├── devices.json.in └── readme.md ├── docs ├── allwinner_linux_notes.md ├── changes.md ├── how_to_run_awtk_in_qemu.md ├── how_to_support_fb_resize.md ├── how_to_support_mouse_wheel.md ├── how_to_use_egl.md ├── how_to_use_in_android.md ├── how_to_use_in_rpi.md ├── how_to_use_in_vmware.md ├── how_to_use_in_wayland.md ├── how_to_use_library_and_custom_main.md ├── images │ ├── build_root_tool_chain.png │ ├── menu1.png │ ├── menu2.png │ ├── qemu_awtk.png │ └── t113-s3.png ├── imxull6_linux_notes.md └── vmware_linux_fb.md ├── format.sh ├── release.sh ├── release_zlg_im287a.sh ├── scons_argv.py └── scripts └── project_scripts ├── __init__.py └── release.py /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: false 15 | AllowShortIfStatementsOnASingleLine: true 16 | AllowShortLoopsOnASingleLine: true 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: true 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeBraces: Attach 41 | BreakBeforeInheritanceComma: false 42 | BreakBeforeTernaryOperators: true 43 | BreakConstructorInitializersBeforeComma: false 44 | BreakConstructorInitializers: BeforeColon 45 | BreakAfterJavaFieldAnnotations: false 46 | BreakStringLiterals: true 47 | ColumnLimit: 100 48 | CommentPragmas: '^ IWYU pragma:' 49 | CompactNamespaces: false 50 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 51 | ConstructorInitializerIndentWidth: 4 52 | ContinuationIndentWidth: 4 53 | Cpp11BracedListStyle: true 54 | DerivePointerAlignment: false 55 | DisableFormat: false 56 | ExperimentalAutoDetectBinPacking: false 57 | FixNamespaceComments: true 58 | ForEachMacros: 59 | - foreach 60 | - Q_FOREACH 61 | - BOOST_FOREACH 62 | IncludeCategories: 63 | - Regex: '^' 64 | Priority: 2 65 | - Regex: '^<.*\.h>' 66 | Priority: 1 67 | - Regex: '^<.*' 68 | Priority: 2 69 | - Regex: '.*' 70 | Priority: 3 71 | IncludeIsMainRegex: '([-_](test|unittest))?$' 72 | IndentCaseLabels: true 73 | IndentPPDirectives: None 74 | IndentWidth: 2 75 | IndentWrappedFunctionNames: false 76 | JavaScriptQuotes: Leave 77 | JavaScriptWrapImports: true 78 | KeepEmptyLinesAtTheStartOfBlocks: false 79 | MacroBlockBegin: '' 80 | MacroBlockEnd: '' 81 | MaxEmptyLinesToKeep: 1 82 | NamespaceIndentation: None 83 | ObjCBlockIndentWidth: 2 84 | ObjCSpaceAfterProperty: false 85 | ObjCSpaceBeforeProtocolList: false 86 | PenaltyBreakAssignment: 2 87 | PenaltyBreakBeforeFirstCallParameter: 1 88 | PenaltyBreakComment: 300 89 | PenaltyBreakFirstLessLess: 100 90 | PenaltyBreakString: 1000 91 | PenaltyExcessCharacter: 1000000 92 | PenaltyReturnTypeOnItsOwnLine: 200 93 | PointerAlignment: Left 94 | RawStringFormats: 95 | - Language: TextProto 96 | BasedOnStyle: google 97 | ReflowComments: true 98 | SortIncludes: false 99 | SortUsingDeclarations: true 100 | SpaceAfterCStyleCast: false 101 | SpaceAfterTemplateKeyword: true 102 | SpaceBeforeAssignmentOperators: true 103 | SpaceBeforeParens: ControlStatements 104 | SpaceInEmptyParentheses: false 105 | SpacesBeforeTrailingComments: 2 106 | SpacesInAngles: false 107 | SpacesInContainerLiterals: true 108 | SpacesInCStyleCastParentheses: false 109 | SpacesInParentheses: false 110 | SpacesInSquareBrackets: false 111 | Standard: Auto 112 | TabWidth: 2 113 | UseTab: Never 114 | ... 115 | 116 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | awtk 2 | bin 3 | lib 4 | *.o 5 | *.pyc 6 | 3rd 7 | release.zip 8 | release.tar.gz 9 | release 10 | .sconsign.dblite 11 | .vscode/*.* 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWTK 针对 arm-linux 平台的移植。 2 | 3 | [AWTK](https://github.com/zlgopen/awtk) 是为嵌入式系统开发的 GUI 引擎库。 4 | 5 | [awtk-linux-fb](https://github.com/zlgopen/awtk-linux-fb) 是 AWTK 在 arm-linux 上的移植。 6 | 7 | 本项目以 [ZLG 周立功 linux 开发套件 AWork 平台 iMX287A 入门级 ARM9 开发板](https://item.taobao.com/item.htm?spm=a230r.1.14.1.29c8b3f8qxjYf7&id=536334628394&ns=1&abbucket=17#detail) 为载体移植,其它开发板可能要做些修改,有问题请请创建 issue。 8 | 9 | ## 使用方法 10 | 11 | #### 准备工作 12 | 13 | * 1. 获取源码 14 | 15 | > 以下两者并列放在同一个目录,如果用户有自己的项目,也建议与以下两者并列放在同一目录。 16 | 17 | ``` 18 | git clone https://github.com/zlgopen/awtk.git 19 | git clone https://github.com/zlgopen/awtk-linux-fb.git 20 | cd awtk-linux-fb 21 | ``` 22 | 23 | * 2. 配置 scons 交叉编译工具链,在 awtk-linux-fb 目录创建 awtk_config_define.py 文件 24 | 25 | ``` 26 | # awtk_config_define.py 27 | TOOLS_PREFIX = "/opt/28x/gcc-4.4.4-glibc-2.11.1-multilib-1.0/arm-fsl-linux-gnueabi/bin/arm-linux-" 28 | TSLIB_LIB_DIR = "/opt/28x/tslib/lib" 29 | TSLIB_INC_DIR = "/opt/28x/tslib/include" 30 | ``` 31 | 32 | > 如果不需要 tslib,不定义 TSLIB\_LIB\_DIR 和 TSLIB\_INC\_DIR 即可。如: 33 | 34 | ``` 35 | # awtk_config_define.py 36 | TSLIB_LIB_DIR = "" 37 | TSLIB_INC_DIR = "" 38 | ``` 39 | 40 | > 详情可以看 scons help,或者可以通过 scons EXPORT_DEFINE_FILE=./awtk_config_define.py 导出一个完整的 awtk_config_define.py 文件。 41 | 42 | * 3. 配置设备文件路径,方法二选一: 43 | 1. 配置 config/devices.json 文件,详情请看 config/readme.md 文档。 44 | 45 | 2. 修改 awtk-port/main\_loop\_linux.c 文件设置输入输出设备的文件名。 46 | 47 | ```c 48 | // main_loop_linux.c 49 | // 这个方法将来会弃用,如果运行时有 devices.json 文件则会优先使用 devices.json 的配置 50 | // 51 | #define FB_DEVICE_FILENAME "/dev/fb0" 52 | #define TS_DEVICE_FILENAME "/dev/input/event0" 53 | #define KB_DEVICE_FILENAME "/dev/input/event1" 54 | #define MICE_DEVICE_FILENAME "/dev/input/mouse0" 55 | ``` 56 | 57 | **备注:** 58 | 可通过 "hexdump /dev/input/xx" 命令识别正确的触摸或鼠标设备文件名。触摸设备也可以通过tslib自带的命令测试,如 "ts_test"、"ts_print"。 59 | 60 | > 注意:在有些平台下,如果设置 "/dev/input/mice",会出现触摸不灵的问题。通过 hexdump /dev/input/mice 命令发现,该设备文件会同时接收触摸和鼠标事件,这种情况请不要使用该设备。 61 | 62 | #### 生成并部署AWTK内置DemoUI 63 | 64 | 1. 请先安装 scons,并完成上面的**准备工作** 65 | 2. 在命令行输入: 66 | 67 | ```bash 68 | cd /home/user/awtk-linux-fb 69 | scons 70 | ``` 71 | 72 | 3. 等待编译成功,生成发布压缩包,在命令行输入: 73 | 74 | ```bash 75 | sh ./release.sh 76 | ``` 77 | 78 | 4. 等待发布完成后,在 awtk-linux-fb 目录下会出现 release.tar.gz 的压缩包,该压缩包就是发布包 79 | 5. 运行 80 | 81 | 把 release.tar.gz (发布包)上传到开发板,并解压,然后运行: 82 | 83 | ```bash 84 | # 程序运行可能要依赖awtk的so文件,如运行失败请尝试设置so文件的绝对路径 85 | # export LD_LIBRARY_PATH=/path/to/bin 86 | sudo ./release/bin/demoui 87 | ``` 88 | 89 | #### 生成并部署用户自己的应用程序 90 | 91 | 1. 请先安装 scons,并完成上面的**准备工作** 92 | 2. awtk 与用户的程序目录结构如下所示 93 | 94 | ```bash 95 | /home/user/ 96 | |-- awtk/ 97 | |-- awtk-linux-fb/ 98 | |-- user_apps/ 99 | ``` 100 | 101 | 输入命令行命令: 102 | 103 | ```bash 104 | cd /home/user/awtk-linux-fb 105 | scons APP=../user_apps/HelloDesigner-Demo 106 | ``` 107 | 108 | 3. 等待编译成功,生成发布压缩包,在命令行输入: 109 | ```bash 110 | ./release.sh ../user_apps/HelloDesigner-Demo/res demo 111 | ``` 112 | 113 | 4. 等待发布完成后,在 awtk-linux-fb 目录下会出现 release.tar.gz 的压缩包,该压缩包就是发布包 114 | 5. 运行 115 | 116 | 把 release.tar.gz (发布包)上传到开发板,并解压,然后运行: 117 | 118 | ```bash 119 | # 程序运行可能要依赖awtk的so文件,如运行失败请尝试设置so文件的绝对路径 120 | # export LD_LIBRARY_PATH=/path/to/bin 121 | sudo ./release/bin/demo 122 | ``` 123 | 124 | ## 文档 125 | 126 | * [如何搭建 Ubuntu 调试环境](docs/how_to_use_in_vmware.md) 127 | 128 | ## 其他问题 129 | 130 | #### 1. 项目路径 131 | 132 | 默认情况下,scons 脚本假设以下文件夹在同一个目录。 133 | 134 | ``` 135 | zlgopen 136 | |-- awtk 137 | |-- awtk-linux-fb 138 | ``` 139 | 140 | #### 2. 使用 Direct Rendering Manager (DRM) 141 | 142 | 缺省使用 framebuffer,如果使用 DRM,请修改 awtk_config_define.py,指定 LCD_DEVICES 和 drm 的路径。 143 | 144 | ``` 145 | LCD_DEVICES = 'drm' 146 | ``` 147 | > DRM 目前只在虚拟机中测试过,如果有问题请参考 awtk-port/lcd\_linux\_drm.c 进行调试。 148 | 149 | #### 3. 使用 EGL 硬件加速 150 | 151 | 缺省使用 framebuffer,如果使用 EGL,请参考文档 [how_to_use_egl.md](docs/how_to_use_egl.md)。 152 | 153 | #### 4. 上传文件到开发板的方法 154 | 155 | 如果开发板支持 ssh,可以使用 scp 命令上传文件或文件夹,比如上传文件: 156 | 157 | ``` 158 | # 开发板ip:192.168.1.136 159 | # 登录用户名:root 160 | # 上传文件 release.tar.gz 到 /opt 目录 161 | scp release.tar.gz root@192.168.1.136:/opt/release.tar.gz 162 | ``` 163 | 164 | 上传文件夹: 165 | 166 | ``` 167 | # 创建文件夹 ./release 中所有文件到 /opt/awtk 目录 168 | scp -r ./release root@192.168.1.136:/opt/awtk 169 | ``` 170 | 171 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import atexit 4 | import scons_argv 5 | scons_argv.init(ARGUMENTS) 6 | 7 | import compile_config 8 | import awtk_config as awtk 9 | 10 | awtk.scons_db_check_and_remove() 11 | compile_helper = compile_config.get_curr_config() 12 | 13 | APP_CCFLAGS = ' ' 14 | 15 | AWTK_LIB_PATH = awtk.joinPath(awtk.BIN_DIR, "libawtk.so"); 16 | if os.path.exists(AWTK_LIB_PATH) : 17 | os.remove(AWTK_LIB_PATH) 18 | 19 | APP_ROOT = compile_helper.get_value('APP', '') 20 | if len (APP_ROOT) > 0: 21 | app_sconstruct = awtk.joinPath(APP_ROOT, 'SConstruct') 22 | if not os.path.exists(APP_ROOT) or not os.path.exists(app_sconstruct): 23 | print('APP: ' + APP_ROOT + ' not found!') 24 | exit(0) 25 | 26 | env = DefaultEnvironment(CCFLAGS = awtk.CCFLAGS + APP_CCFLAGS, 27 | ENV = os.environ, 28 | CFLAGS = awtk.CFLAGS, 29 | CC=awtk.CC, 30 | CXX=awtk.CXX, 31 | LD=awtk.LD, 32 | AR=awtk.AR, 33 | RANLIB=awtk.RANLIB, 34 | STRIP=awtk.STRIP, 35 | LIBS = awtk.LIBS, 36 | LIBPATH = awtk.LIBPATH, 37 | CPPPATH = awtk.CPPPATH + [awtk.joinPath(awtk.TK_ROOT, 'res')], 38 | LINKFLAGS = awtk.LINKFLAGS, 39 | OS_SUBSYSTEM_CONSOLE=awtk.OS_SUBSYSTEM_CONSOLE, 40 | OS_SUBSYSTEM_WINDOWS=awtk.OS_SUBSYSTEM_WINDOWS 41 | ) 42 | 43 | TK_ROOT_VAR = awtk.joinPath(awtk.VAR_DIR, 'awtk') 44 | VariantDir(TK_ROOT_VAR, awtk.TK_ROOT) 45 | 46 | if APP_ROOT == '' and compile_helper.get_value('BUILD_DEMOS', True): 47 | APP_PROJ_VAR = [awtk.joinPath(TK_ROOT_VAR, 'demos/SConscript')] 48 | else: 49 | APP_PROJ_VAR = [] 50 | 51 | if awtk.lcd_devices_is_egl(os.environ['LCD_DEVICES']) : 52 | APP_PROJ_VAR += [awtk.joinPath(TK_ROOT_VAR, '3rd/glad/SConscript')] 53 | 54 | SConscriptFiles=[ 55 | awtk.joinPath(TK_ROOT_VAR, '3rd/mbedtls/SConscript'), 56 | awtk.joinPath(TK_ROOT_VAR, '3rd/cjson/SConscript'), 57 | awtk.joinPath(TK_ROOT_VAR, '3rd/agg/SConscript'), 58 | awtk.joinPath(TK_ROOT_VAR, '3rd/agge/SConscript'), 59 | awtk.joinPath(TK_ROOT_VAR, '3rd/fribidi/SConscript'), 60 | awtk.joinPath(TK_ROOT_VAR, '3rd/gpinyin/SConscript'), 61 | awtk.joinPath(TK_ROOT_VAR, '3rd/libunibreak/SConscript'), 62 | awtk.joinPath(TK_ROOT_VAR, '3rd/miniz/SConscript'), 63 | awtk.joinPath(TK_ROOT_VAR, 'src/SConscript'), 64 | awtk.joinPath(TK_ROOT_VAR, 'src/xml/SConscript'), 65 | awtk.joinPath(TK_ROOT_VAR, 'src/charset/SConscript'), 66 | awtk.joinPath(TK_ROOT_VAR, 'src/fscript_ext/SConscript'), 67 | awtk.joinPath(TK_ROOT_VAR, 'src/streams/SConscript'), 68 | awtk.joinPath(TK_ROOT_VAR, 'src/csv/SConscript'), 69 | awtk.joinPath(TK_ROOT_VAR, 'src/conf_io/SConscript'), 70 | awtk.joinPath(TK_ROOT_VAR, 'src/hal/SConscript'), 71 | awtk.joinPath(TK_ROOT_VAR, 'src/debugger/SConscript'), 72 | awtk.joinPath(TK_ROOT_VAR, 'src/ubjson/SConscript'), 73 | awtk.joinPath(TK_ROOT_VAR, 'src/compressors/SConscript'), 74 | awtk.joinPath(TK_ROOT_VAR, 'src/romfs/SConscript'), 75 | ] + APP_PROJ_VAR + awtk.OS_PROJECTS; 76 | 77 | if os.environ['LCD_DEVICES'] == 'wayland' or os.environ['LCD_DEVICES'] == 'egl_for_wayland': 78 | SConscriptFiles += [ 'awtk-wayland/SConscript' ] 79 | else : 80 | SConscriptFiles += [ 'awtk-port/SConscript' ] 81 | 82 | os.environ['BUILD_TOOLS'] = str(compile_helper.get_value('BUILD_TOOLS', True)) 83 | if compile_helper.get_value('BUILD_TOOLS', True) : 84 | SConscriptFiles += [ 85 | awtk.joinPath(TK_ROOT_VAR, 'tools/common/SConscript'), 86 | awtk.joinPath(TK_ROOT_VAR, 'tools/ui_gen/xml_to_ui/SConscript'), 87 | ] 88 | 89 | SConscript(SConscriptFiles) 90 | 91 | 92 | def build_app(): 93 | if not os.path.exists(AWTK_LIB_PATH) : 94 | return 95 | if APP_ROOT == '': 96 | return 97 | 98 | print('======================== build app ========================') 99 | 100 | app_bin = awtk.joinPath(APP_ROOT, 'bin') 101 | linux_fb_bin = os.environ['BIN_DIR']; 102 | 103 | if env.GetOption('clean'): 104 | cmd = 'cd ' + APP_ROOT + ' && scons -c AWTK_ROOT=' + awtk.TK_ROOT 105 | print(cmd) 106 | os.system(cmd) 107 | else: 108 | cmd = 'cd ' + APP_ROOT + ' && scons LINUX_FB=true AWTK_ROOT=' + awtk.TK_ROOT 109 | print(cmd) 110 | os.system(cmd) 111 | 112 | files = os.listdir(app_bin) 113 | for file in files: 114 | print('copy ' + awtk.joinPath(app_bin, file) + ' to ' + linux_fb_bin) 115 | shutil.copy(awtk.joinPath(app_bin, file), linux_fb_bin) 116 | 117 | def compile_end() : 118 | compile_helper.save_last_compile_argv() 119 | compile_helper.output_compile_data(awtk.TK_ROOT) 120 | build_app() 121 | 122 | atexit.register(compile_end) 123 | -------------------------------------------------------------------------------- /awtk-port/SConscript: -------------------------------------------------------------------------------- 1 | import os 2 | import copy 3 | import scons_argv 4 | compile_helper = scons_argv.get_compile_config() 5 | 6 | BIN_DIR = os.environ['BIN_DIR']; 7 | LIB_DIR = os.environ['LIB_DIR']; 8 | LCD_DEVICES = os.environ['LCD_DEVICES'] 9 | 10 | env = DefaultEnvironment().Clone() 11 | SOURCES = [ 12 | 'input_thread/mouse_thread.c', 13 | 'input_thread/input_thread.c', 14 | 'input_thread/common_coord.c', 15 | 'input_thread/input_dispatcher.c', 16 | 'lcd_linux/lcd_linux_fb.c', 17 | 'lcd_linux/lcd_linux_drm.c', 18 | 'lcd_linux/lcd_linux_egl.c', 19 | 'lcd_linux/lcd_mem_others.c', 20 | 'devices.c', 21 | 'main_loop_linux.c', 22 | ] 23 | 24 | if os.environ['TSLIB_LIB_DIR']: 25 | SOURCES = ['input_thread/tslib_thread.c'] + SOURCES; 26 | 27 | if LCD_DEVICES =='egl_for_fsl' : 28 | SOURCES = Glob('egl_devices/fsl/*.c') + SOURCES; 29 | elif LCD_DEVICES =='egl_for_x11' : 30 | SOURCES = Glob('egl_devices/x11/*.c') + SOURCES; 31 | elif LCD_DEVICES =='egl_for_gbm' : 32 | SOURCES = Glob('egl_devices/gbm/*.c') + SOURCES; 33 | 34 | awtk_linux_fb = env.Library(os.path.join(LIB_DIR, 'awtk_linux_fb'), SOURCES) 35 | 36 | extern_codes = compile_helper.get_value('EXTERN_CODE', None) 37 | if extern_codes != None : 38 | all_extern_codes = [] 39 | for extern_code in extern_codes : 40 | all_extern_codes += Glob(extern_code); 41 | __extern_code = env.Library(os.path.join(LIB_DIR, '__extern_code'), all_extern_codes) 42 | Depends(awtk_linux_fb, __extern_code) 43 | 44 | env['LIBS'] = ['awtk_linux_fb'] + env['LIBS'] 45 | 46 | env.Program(os.path.join(BIN_DIR, 'mouse_test'), ["test/mouse_thread_test.c"]) 47 | env.Program(os.path.join(BIN_DIR, 'input_test'), ["test/input_thread_test.c"]) 48 | env.Program(os.path.join(BIN_DIR, 'fb_test'), ["test/fb_test.c"]) 49 | 50 | if os.environ['TSLIB_LIB_DIR']: 51 | env.Program(os.path.join(BIN_DIR, 'tslib_test'), ["test/tslib_thread_test.c"]) 52 | -------------------------------------------------------------------------------- /awtk-port/devices.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: devices.c 3 | * Author: AWTK Develop Team 4 | * Brief: devices 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * this program is distributed in the hope that it will be useful, 9 | * but without any warranty; without even the implied warranty of 10 | * merchantability or fitness for a particular purpose. see the 11 | * license file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * history: 17 | * ================================================================ 18 | * 2023-02-27 Shen ZhaoKun created 19 | * 20 | */ 21 | 22 | #include "devices.h" 23 | #include "tkc/mem.h" 24 | #include "tkc/path.h" 25 | #include "tkc/utils.h" 26 | #include "conf_io/conf_json.h" 27 | 28 | #define DEVICES_CONFIG_FILEPATH "config/devices.json" 29 | 30 | static uint32_t s_devices_nr = 0; 31 | static device_info_t* s_devices = NULL; 32 | static bool_t s_ext_set = FALSE; 33 | 34 | ret_t devices_load(void) { 35 | char abs_path[MAX_PATH + 1] = {0}, abs_path_with_schema[MAX_PATH + 8] = {0}; 36 | tk_object_t* conf = NULL; 37 | uint32_t i = 0; 38 | return_value_if_fail(RET_OK == devices_unload(), RET_FAIL); 39 | 40 | path_prepend_app_root(abs_path, DEVICES_CONFIG_FILEPATH); 41 | tk_snprintf(abs_path_with_schema, ARRAY_SIZE(abs_path_with_schema) - 1, STR_SCHEMA_FILE "%s", 42 | abs_path); 43 | 44 | log_debug("%s : path = %s\r\n", __FUNCTION__, abs_path_with_schema); 45 | 46 | conf = conf_json_load(abs_path_with_schema, FALSE); 47 | return_value_if_fail(conf != NULL, RET_OOM); 48 | 49 | s_devices_nr = tk_object_get_prop_uint32(conf, CONF_SPECIAL_ATTR_SIZE, 0); 50 | goto_error_if_fail(s_devices_nr > 0); 51 | 52 | s_devices = TKMEM_ZALLOCN(device_info_t, s_devices_nr); 53 | goto_error_if_fail(s_devices != NULL); 54 | 55 | for (i = 0; i < s_devices_nr; i++) { 56 | char key[TK_NAME_LEN + 1] = {0}; 57 | 58 | tk_snprintf(key, sizeof(key), "[%d]." CONF_SPECIAL_ATTR_NAME, i); 59 | tk_strncpy(s_devices[i].path, tk_object_get_prop_str(conf, key), sizeof(s_devices[i].path) - 1); 60 | 61 | tk_snprintf(key, sizeof(key), "[%d].type", i); 62 | tk_strncpy(s_devices[i].type, tk_object_get_prop_str(conf, key), sizeof(s_devices[i].type) - 1); 63 | 64 | log_debug("devices[%d]: path = %s, type = %s\r\n", i, s_devices[i].path, s_devices[i].type); 65 | } 66 | 67 | TK_OBJECT_UNREF(conf); 68 | return RET_OK; 69 | error: 70 | TK_OBJECT_UNREF(conf); 71 | return RET_FAIL; 72 | } 73 | 74 | ret_t devices_unload(void) { 75 | if (s_devices != NULL) { 76 | if (!s_ext_set) { 77 | TKMEM_FREE(s_devices); 78 | } 79 | s_devices = NULL; 80 | } 81 | s_devices_nr = 0; 82 | s_ext_set = FALSE; 83 | 84 | return RET_OK; 85 | } 86 | 87 | ret_t devices_set(device_info_t* devices, uint32_t nr) { 88 | uint32_t i = 0; 89 | return_value_if_fail(devices != NULL && nr > 0, RET_BAD_PARAMS); 90 | return_value_if_fail(RET_OK == devices_unload(), RET_FAIL); 91 | 92 | s_ext_set = TRUE; 93 | s_devices_nr = nr; 94 | s_devices = devices; 95 | 96 | for (i = 0; i < s_devices_nr; i++) { 97 | log_debug("devices[%d]: path = %s, type = %s\r\n", i, s_devices[i].path, s_devices[i].type); 98 | } 99 | 100 | return RET_OK; 101 | } 102 | 103 | ret_t devices_foreach(device_visit_t visit, void* ctx) { 104 | uint32_t i = 0; 105 | return_value_if_fail(visit != NULL, RET_BAD_PARAMS); 106 | return_value_if_fail(s_devices != NULL, RET_BAD_PARAMS); 107 | 108 | for (i = 0; i < s_devices_nr; i++) { 109 | if (RET_OK != visit(ctx, &s_devices[i])) { 110 | break; 111 | } 112 | } 113 | 114 | return RET_OK; 115 | } 116 | -------------------------------------------------------------------------------- /awtk-port/devices.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: devices.h 3 | * Author: AWTK Develop Team 4 | * Brief: devices 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * this program is distributed in the hope that it will be useful, 9 | * but without any warranty; without even the implied warranty of 10 | * merchantability or fitness for a particular purpose. see the 11 | * license file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * history: 17 | * ================================================================ 18 | * 2023-02-27 Shen ZhaoKun created 19 | * 20 | */ 21 | 22 | #ifndef TK_DEVICES_H 23 | #define TK_DEVICES_H 24 | 25 | #include "tkc/types_def.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | typedef struct _device_info_t { 30 | char type[TK_NAME_LEN + 1]; 31 | char path[MAX_PATH + 1]; 32 | } device_info_t; 33 | 34 | typedef ret_t (*device_visit_t)(void* ctx, const device_info_t* info); 35 | 36 | ret_t devices_load(void); 37 | 38 | ret_t devices_unload(void); 39 | 40 | ret_t devices_set(device_info_t* devices, uint32_t nr); 41 | 42 | ret_t devices_foreach(device_visit_t visit, void* ctx); 43 | 44 | END_C_DECLS 45 | 46 | #endif /*TK_DEVICES_H*/ 47 | -------------------------------------------------------------------------------- /awtk-port/egl_devices/egl_devices.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: egl_devices.h 3 | * Author: AWTK Develop Team 4 | * Brief: linux egl lcd 5 | * 6 | * Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2020-11-06 Lou ZhiMing created 19 | * 20 | */ 21 | 22 | #ifndef TK_EGL_DEVICES_H 23 | #define TK_EGL_DEVICES_H 24 | 25 | #include "base/types_def.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | void* egl_devices_create(const char* filename); 30 | ret_t egl_devices_dispose(void* ctx); 31 | 32 | float_t egl_devices_get_ratio(void* ctx); 33 | int32_t egl_devices_get_width(void* ctx); 34 | int32_t egl_devices_get_height(void* ctx); 35 | 36 | ret_t egl_devices_make_current(void* ctx); 37 | ret_t egl_devices_swap_buffers(void* ctx); 38 | 39 | ret_t egl_devices_resize(void* ctx, uint32_t w, uint32_t h); 40 | 41 | END_C_DECLS 42 | 43 | #endif /*TK_EGL_DEVICES_H*/ 44 | -------------------------------------------------------------------------------- /awtk-port/egl_devices/fsl/egl_devices.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: egl_devices.c 3 | * Author: AWTK Develop Team 4 | * Brief: egl devices for fsl 5 | * 6 | * Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2020-11-06 Lou ZhiMing created 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "fsl_egl.h" 26 | #include "../egl_devices.h" 27 | #include "tkc/mem.h" 28 | 29 | typedef struct _egl_devices_fsl_context_t { 30 | EGLint numconfigs; 31 | EGLDisplay egldisplay; 32 | EGLConfig eglconfig; 33 | EGLSurface eglsurface; 34 | EGLContext eglcontext; 35 | EGLNativeWindowType eglNativeWindow; 36 | EGLNativeDisplayType eglNativeDisplayType; 37 | } egl_devices_fsl_context_t; 38 | 39 | static const EGLint s_configAttribs[] = 40 | { 41 | EGL_SAMPLES, 0, 42 | EGL_RED_SIZE, 8, 43 | EGL_GREEN_SIZE, 8, 44 | EGL_BLUE_SIZE, 8, 45 | EGL_ALPHA_SIZE, EGL_DONT_CARE, 46 | EGL_STENCIL_SIZE, 8, 47 | EGL_DEPTH_SIZE, 0, 48 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 49 | EGL_MIN_SWAP_INTERVAL, 1, 50 | EGL_NONE, 51 | }; 52 | 53 | void* egl_devices_create(const char* filename) { 54 | egl_devices_fsl_context_t* ctx = TKMEM_ZALLOC(egl_devices_fsl_context_t); 55 | return_value_if_fail(ctx != NULL, NULL); 56 | 57 | ctx->eglNativeDisplayType = fsl_getNativeDisplay(); 58 | ctx->egldisplay = eglGetDisplay(ctx->eglNativeDisplayType); 59 | eglInitialize(ctx->egldisplay, NULL, NULL); 60 | assert(eglGetError() == EGL_SUCCESS); 61 | eglBindAPI(EGL_OPENGL_ES_API); 62 | 63 | eglChooseConfig(ctx->egldisplay, s_configAttribs, &(ctx->eglconfig), 1, &(ctx->numconfigs)); 64 | assert(eglGetError() == EGL_SUCCESS); 65 | assert(ctx->numconfigs == 1); 66 | 67 | ctx->eglNativeWindow = fsl_createwindow(ctx->egldisplay, ctx->eglNativeDisplayType, filename); 68 | assert(ctx->eglNativeWindow); 69 | 70 | ctx->eglsurface = eglCreateWindowSurface(ctx->egldisplay, ctx->eglconfig, ctx->eglNativeWindow, NULL); 71 | 72 | assert(eglGetError() == EGL_SUCCESS); 73 | EGLint ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 74 | ctx->eglcontext = eglCreateContext(ctx->egldisplay, ctx->eglconfig, EGL_NO_CONTEXT, ContextAttribList ); 75 | assert(eglGetError() == EGL_SUCCESS); 76 | eglMakeCurrent(ctx->egldisplay, ctx->eglsurface, ctx->eglsurface, ctx->eglcontext); 77 | assert(eglGetError() == EGL_SUCCESS); 78 | 79 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 80 | 81 | glDisable(GL_DEPTH_TEST); 82 | glDisable(GL_SCISSOR_TEST); 83 | 84 | eglSwapInterval(ctx->egldisplay, 1); 85 | assert(eglGetError() == EGL_SUCCESS); 86 | 87 | return (void*)ctx; 88 | } 89 | 90 | ret_t egl_devices_dispose(void* ctx) { 91 | egl_devices_fsl_context_t* context = (egl_devices_fsl_context_t*)ctx; 92 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 93 | 94 | eglMakeCurrent(context->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 95 | assert(eglGetError() == EGL_SUCCESS); 96 | eglTerminate(context->egldisplay); 97 | assert(eglGetError() == EGL_SUCCESS); 98 | eglReleaseThread(); 99 | 100 | TKMEM_FREE(context); 101 | return RET_OK; 102 | } 103 | 104 | float_t egl_devices_get_ratio(void* ctx) { 105 | (void)ctx; 106 | return 1.0f; 107 | } 108 | 109 | int32_t egl_devices_get_width(void* ctx) { 110 | EGLint width = 0; 111 | egl_devices_fsl_context_t* context = (egl_devices_fsl_context_t*)ctx; 112 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 113 | 114 | eglQuerySurface(context->egldisplay, context->eglsurface, EGL_WIDTH, &width); 115 | return (int32_t)width; 116 | } 117 | 118 | int32_t egl_devices_get_height(void* ctx) { 119 | EGLint height = 0; 120 | egl_devices_fsl_context_t* context = (egl_devices_fsl_context_t*)ctx; 121 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 122 | 123 | eglQuerySurface(context->egldisplay, context->eglsurface, EGL_HEIGHT, &height); 124 | return (int32_t)height; 125 | } 126 | 127 | ret_t egl_devices_make_current(void* ctx) { 128 | egl_devices_fsl_context_t* context = (egl_devices_fsl_context_t*)ctx; 129 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 130 | 131 | eglMakeCurrent(context->egldisplay, context->eglsurface, context->eglsurface, context->eglcontext); 132 | return eglGetError() == EGL_SUCCESS ? RET_OK : RET_FAIL; 133 | } 134 | 135 | ret_t egl_devices_swap_buffers(void* ctx) { 136 | egl_devices_fsl_context_t* context = (egl_devices_fsl_context_t*)ctx; 137 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 138 | 139 | eglSwapBuffers(context->egldisplay, context->eglsurface); 140 | return eglGetError() == EGL_SUCCESS ? RET_OK : RET_FAIL; 141 | } 142 | 143 | ret_t egl_devices_resize(void* ctx, uint32_t w, uint32_t h) { 144 | (void)ctx; 145 | (void)w; 146 | (void)h; 147 | return RET_NOT_IMPL; 148 | } 149 | -------------------------------------------------------------------------------- /awtk-port/egl_devices/fsl/fsl_egl.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (c) 2012 Freescale Semiconductor, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * * Neither the name of the Freescale Semiconductor, Inc. nor the names of 16 | * its contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Labels parameters 31 | 32 | *****************************************************************************/ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef EGL_USE_X11 42 | #include 43 | #include 44 | #endif 45 | 46 | EGLNativeDisplayType fsl_getNativeDisplay() 47 | { 48 | EGLNativeDisplayType eglNativeDisplayType = NULL; 49 | #if (defined EGL_USE_X11) 50 | eglNativeDisplayType = XOpenDisplay(NULL); 51 | assert(eglNativeDisplayType != NULL); 52 | #elif (defined EGL_API_FB) 53 | eglNativeDisplayType = fbGetDisplayByIndex(0); //Pass the argument as required to show the framebuffer 54 | #else 55 | display = EGL_DEFAULT_DISPLAY; 56 | #endif 57 | return eglNativeDisplayType; 58 | } 59 | 60 | EGLNativeWindowType fsl_createwindow(EGLDisplay egldisplay, EGLNativeDisplayType eglNativeDisplayType, const char* filename) 61 | { 62 | EGLNativeWindowType native_window = (EGLNativeWindowType)0; 63 | 64 | #if (defined EGL_USE_X11) 65 | Window window, rootwindow; 66 | int screen = DefaultScreen(eglNativeDisplayType); 67 | rootwindow = RootWindow(eglNativeDisplayType,screen); 68 | window = XCreateSimpleWindow(eglNativeDisplayType, rootwindow, 0, 0, 400, 533, 0, 0, WhitePixel (eglNativeDisplayType, screen)); 69 | XMapWindow(eglNativeDisplayType, window); 70 | native_window = window; 71 | #else 72 | const char *vendor = eglQueryString(egldisplay, EGL_VENDOR); 73 | printf("vendor:%s \r\n", vendor); 74 | if (strstr(vendor, "Imagination Technologies")) 75 | native_window = (EGLNativeWindowType)0; 76 | else if (strstr(vendor, "AMD")) 77 | native_window = (EGLNativeWindowType) open(filename, O_RDWR); 78 | else if (strstr(vendor, "Vivante")) //NEEDS FIX - functs don't exist on other platforms 79 | { 80 | #if (defined EGL_API_FB) 81 | native_window = fbCreateWindow(eglNativeDisplayType, 0, 0, 0, 0); 82 | #endif 83 | } 84 | else 85 | { 86 | printf("Unknown vendor [%s]\n", vendor); 87 | return 0; 88 | } 89 | #endif 90 | return native_window; 91 | 92 | } 93 | 94 | 95 | void fsl_destroywindow(EGLNativeWindowType eglNativeWindowType, EGLNativeDisplayType eglNativeDisplayType) 96 | { 97 | (void) eglNativeWindowType; 98 | #if (defined EGL_USE_X11) 99 | //close x display 100 | XCloseDisplay(eglNativeDisplayType); 101 | #endif 102 | } 103 | -------------------------------------------------------------------------------- /awtk-port/egl_devices/fsl/fsl_egl.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (c) 2012 Freescale Semiconductor, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * * Neither the name of the Freescale Semiconductor, Inc. nor the names of 16 | * its contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Labels parameters 31 | 32 | *****************************************************************************/ 33 | 34 | #ifndef _FSL_EGL_H_ 35 | #define _FSL_EGL_H_ 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | #include 40 | 41 | EGLNativeDisplayType fsl_getNativeDisplay(); 42 | EGLNativeWindowType fsl_createwindow(EGLDisplay egldisplay, EGLNativeDisplayType eglNativeDisplayType, const char* filename); 43 | void fsl_destroywindow(EGLNativeWindowType eglNativeWindowType,EGLNativeDisplayType eglNativeDisplayType); 44 | 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | #endif //_FSL_EGL_H_ 50 | 51 | -------------------------------------------------------------------------------- /awtk-port/egl_devices/x11/egl_devices.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: egl_devices.c 3 | * Author: AWTK Develop Team 4 | * Brief: egl devices for x11 5 | * 6 | * Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2020-11-06 Lou ZhiMing created 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "tkc/mem.h" 29 | #include "tkc/utils.h" 30 | #include "../egl_devices.h" 31 | 32 | 33 | const static EGLint g_attr[] = { 34 | // some attributes to set up our egl-interface 35 | // EGL_BUFFER_SIZE, 32, 36 | // EGL_RENDERABLE_TYPE, 37 | // EGL_OPENGL_ES2_BIT, 38 | EGL_SAMPLES, 0, 39 | EGL_RED_SIZE, 8, 40 | EGL_GREEN_SIZE, 8, 41 | EGL_BLUE_SIZE, 8, 42 | EGL_ALPHA_SIZE, EGL_DONT_CARE, 43 | EGL_STENCIL_SIZE, 8, 44 | EGL_DEPTH_SIZE, 0, 45 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 46 | EGL_MIN_SWAP_INTERVAL, 0, 47 | EGL_NONE, 48 | }; 49 | 50 | typedef struct _egl_devices_x11_context_t { 51 | Window win; 52 | Display* x_display; 53 | EGLDisplay egl_display; 54 | EGLContext egl_context; 55 | EGLSurface egl_surface; 56 | } egl_devices_x11_context_t; 57 | 58 | static void DeInit_GLES(egl_devices_x11_context_t* ctx) { 59 | //// cleaning up... 60 | eglDestroyContext(ctx->egl_display, ctx->egl_context); 61 | eglDestroySurface(ctx->egl_display, ctx->egl_surface); 62 | eglTerminate(ctx->egl_display); 63 | XDestroyWindow(ctx->x_display, ctx->win); 64 | XCloseDisplay(ctx->x_display); 65 | } 66 | 67 | static int Init_GLES(egl_devices_x11_context_t* ctx) { 68 | /////// the X11 part ////////////////////////////////////////////////////////////////// 69 | // in the first part the program opens a connection to the X11 window manager 70 | // 71 | Atom atom; 72 | XEvent xev; 73 | Window root; 74 | Atom wm_state; 75 | Atom fullscreen; 76 | XWMHints hints; 77 | EGLConfig ecfg; 78 | EGLint num_config; 79 | XSetWindowAttributes swa; 80 | XSetWindowAttributes xattr; 81 | XWindowAttributes getWinAttr; 82 | EGLint ctxattr[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; 83 | 84 | ctx->x_display = XOpenDisplay(NULL); // open the standard display (the primary screen) 85 | if (ctx->x_display == NULL) { 86 | assert(0); 87 | return 1; 88 | } 89 | 90 | root = DefaultRootWindow(ctx->x_display); // get the root window (usually the whole screen) 91 | swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; 92 | 93 | XGetWindowAttributes(ctx->x_display, root, &getWinAttr); 94 | 95 | ctx->win = XCreateWindow( // create a window with the provided parameters 96 | ctx->x_display, root, 0, 0, getWinAttr.width, getWinAttr.height, 0, CopyFromParent, InputOutput, CopyFromParent, 97 | CWEventMask, &swa); 98 | 99 | int one = 1; 100 | 101 | xattr.override_redirect = False; 102 | XChangeWindowAttributes(ctx->x_display, ctx->win, CWOverrideRedirect, &xattr); 103 | 104 | atom = XInternAtom(ctx->x_display, "_NET_WM_STATE_FULLSCREEN", False); 105 | XChangeProperty(ctx->x_display, ctx->win, XInternAtom(ctx->x_display, "_NET_WM_STATE", False), 106 | XA_ATOM, 32, PropModeReplace, (unsigned char*)&atom, 1); 107 | 108 | XChangeProperty(ctx->x_display, ctx->win, 109 | XInternAtom(ctx->x_display, "_HILDON_NON_COMPOSITED_WINDOW", False), XA_INTEGER, 110 | 32, PropModeReplace, (unsigned char*)&one, 1); 111 | 112 | hints.input = True; 113 | hints.flags = InputHint; 114 | XSetWMHints(ctx->x_display, ctx->win, &hints); 115 | 116 | XMapWindow(ctx->x_display, ctx->win); // make the window visible on the screen 117 | XStoreName(ctx->x_display, ctx->win, "GL test"); // give the window a name 118 | 119 | //// get identifiers for the provided atom name strings 120 | wm_state = XInternAtom(ctx->x_display, "_NET_WM_STATE", False); 121 | fullscreen = XInternAtom(ctx->x_display, "_NET_WM_STATE_FULLSCREEN", False); 122 | 123 | memset(&xev, 0, sizeof(xev)); 124 | 125 | xev.type = ClientMessage; 126 | xev.xclient.window = ctx->win; 127 | xev.xclient.message_type = wm_state; 128 | xev.xclient.format = 32; 129 | xev.xclient.data.l[0] = 1; 130 | xev.xclient.data.l[1] = fullscreen; 131 | XSendEvent( // send an event mask to the X-server 132 | ctx->x_display, DefaultRootWindow(ctx->x_display), False, SubstructureNotifyMask, &xev); 133 | 134 | /////// the egl part ////////////////////////////////////////////////////////////////// 135 | // egl provides an interface to connect the graphics related functionality of openGL ES 136 | // with the windowing interface and functionality of the native operation system (X11 137 | // in our case. 138 | 139 | ctx->egl_display = eglGetDisplay((EGLNativeDisplayType)ctx->x_display); 140 | if (ctx->egl_display == EGL_NO_DISPLAY) { 141 | assert(0); 142 | return 1; 143 | } 144 | 145 | if (!eglInitialize(ctx->egl_display, NULL, NULL)) { 146 | assert(0); 147 | return 1; 148 | } 149 | 150 | eglBindAPI(EGL_OPENGL_ES_API); 151 | 152 | if (!eglChooseConfig(ctx->egl_display, g_attr, &ecfg, 1, &num_config)) { 153 | assert(0); 154 | return 1; 155 | } 156 | 157 | if (num_config != 1) { 158 | assert(0); 159 | return 1; 160 | } 161 | 162 | ctx->egl_surface = eglCreateWindowSurface(ctx->egl_display, ecfg, ctx->win, NULL); 163 | if (ctx->egl_surface == EGL_NO_SURFACE) { 164 | assert(0); 165 | return 1; 166 | } 167 | 168 | //// egl-contexts collect all state descriptions needed required for operation 169 | ctx->egl_context = eglCreateContext(ctx->egl_display, ecfg, EGL_NO_CONTEXT, ctxattr); 170 | if (ctx->egl_context == EGL_NO_CONTEXT) { 171 | assert(0); 172 | return 1; 173 | } 174 | 175 | //// associate the egl-context with the egl-surface 176 | eglMakeCurrent(ctx->egl_display, ctx->egl_surface, ctx->egl_surface, ctx->egl_context); 177 | 178 | if (!eglSwapInterval(ctx->egl_display, 0)) { 179 | assert(0); 180 | return 1; 181 | } 182 | return 0; 183 | } 184 | 185 | void* egl_devices_create(const char* filename) { 186 | egl_devices_x11_context_t* ctx = TKMEM_ZALLOC(egl_devices_x11_context_t); 187 | return_value_if_fail(ctx != NULL, NULL); 188 | 189 | (void)filename; 190 | Init_GLES(ctx); 191 | return (void*)ctx; 192 | } 193 | 194 | ret_t egl_devices_dispose(void* ctx) { 195 | egl_devices_x11_context_t* context = (egl_devices_x11_context_t*)ctx; 196 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 197 | DeInit_GLES(context); 198 | TKMEM_FREE(ctx); 199 | return RET_OK; 200 | } 201 | 202 | float_t egl_devices_get_ratio(void* ctx) { 203 | (void)ctx; 204 | return 1.0f; 205 | } 206 | 207 | int32_t egl_devices_get_width(void* ctx) { 208 | EGLint width = 0; 209 | egl_devices_x11_context_t* context = (egl_devices_x11_context_t*)ctx; 210 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 211 | 212 | eglQuerySurface(context->egl_display, context->egl_surface, EGL_WIDTH, &width); 213 | return (int32_t)width; 214 | } 215 | 216 | int32_t egl_devices_get_height(void* ctx) { 217 | EGLint height = 0; 218 | egl_devices_x11_context_t* context = (egl_devices_x11_context_t*)ctx; 219 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 220 | 221 | eglQuerySurface(context->egl_display, context->egl_surface, EGL_HEIGHT, &height); 222 | return (int32_t)height; 223 | } 224 | 225 | ret_t egl_devices_make_current(void* ctx) { 226 | egl_devices_x11_context_t* context = (egl_devices_x11_context_t*)ctx; 227 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 228 | 229 | eglMakeCurrent(context->egl_display, context->egl_surface, context->egl_surface, context->egl_context); 230 | return eglGetError() == EGL_SUCCESS ? RET_OK : RET_FAIL; 231 | } 232 | 233 | ret_t egl_devices_swap_buffers(void* ctx) { 234 | egl_devices_x11_context_t* context = (egl_devices_x11_context_t*)ctx; 235 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 236 | 237 | eglSwapBuffers(context->egl_display, context->egl_surface); 238 | return eglGetError() == EGL_SUCCESS ? RET_OK : RET_FAIL; 239 | } 240 | 241 | static char* egl_x11_get_screen_name(char* line_data, uint32_t line_length) { 242 | int32_t i = 0; 243 | int32_t n = 0; 244 | char* screen_name = NULL; 245 | for (; i < line_length; i++) { 246 | if(line_data[i] == ' ' ){ 247 | n = i; 248 | break; 249 | } 250 | } 251 | screen_name = TKMEM_ZALLOCN(char, n + 1); 252 | if (screen_name != NULL) { 253 | memcpy(screen_name, line_data, n); 254 | } 255 | return screen_name; 256 | } 257 | 258 | static ret_t egl_x11_do_resize(wh_t w, wh_t h) { 259 | bool_t is_find = FALSE; 260 | int32_t line_number = 0; 261 | char cmd[255] = {0}; 262 | char* screen_name = NULL; 263 | char resize_name[20] = {0}; 264 | char line_data[4096] = {0}; 265 | FILE* fp = popen("xrandr", "r"); 266 | return_value_if_fail(fp != NULL, RET_BAD_PARAMS); 267 | tk_snprintf(resize_name, sizeof(resize_name), "%dx%d", w, h); 268 | while (fgets(line_data, sizeof(line_data), fp) != NULL) { 269 | if (line_number == 1) { 270 | screen_name = egl_x11_get_screen_name(line_data, sizeof(line_data)); 271 | } else { 272 | if (strstr(line_data, resize_name) != NULL) { 273 | is_find = TRUE; 274 | break; 275 | } 276 | } 277 | line_number++; 278 | } 279 | pclose(fp); 280 | 281 | return_value_if_fail(screen_name != NULL, RET_FAIL); 282 | // "xrandr --output HDMI-1 --mode 800x600" 283 | tk_snprintf(cmd, sizeof(cmd), "xrandr --output %s --mode %s", screen_name, resize_name); 284 | TKMEM_FREE(screen_name); 285 | 286 | return_value_if_fail(is_find, RET_FAIL); 287 | return system(cmd) == 0 ? RET_OK : RET_FAIL; 288 | } 289 | 290 | ret_t egl_devices_resize(void* ctx, uint32_t w, uint32_t h) { 291 | ret_t ret = egl_x11_do_resize(w, h); 292 | if (ret == RET_OK) { 293 | egl_devices_x11_context_t* context = (egl_devices_x11_context_t*)ctx; 294 | return_value_if_fail(context != NULL, RET_BAD_PARAMS); 295 | XResizeWindow(context->x_display, context->win, w, h); 296 | } 297 | return ret; 298 | } 299 | -------------------------------------------------------------------------------- /awtk-port/input_thread/common_coord.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: common_coord.c 3 | * Author: AWTK Develop Team 4 | * Brief: 公共坐标 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * this program is distributed in the hope that it will be useful, 9 | * but without any warranty; without even the implied warranty of 10 | * merchantability or fitness for a particular purpose. see the 11 | * license file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * history: 17 | * ================================================================ 18 | * 2023-08-11 Shen ZhaoKun created 19 | * 20 | */ 21 | 22 | #include "common_coord.h" 23 | #include "tkc/atomic.h" 24 | 25 | static tk_atomic_t s_coord; 26 | 27 | #define COMMON_COORD_POINT_TO_U64(p) (((uint64_t)p.x << 32) | p.y) 28 | #define COMMON_COORD_POINT_FROM_U64(num) \ 29 | point_init((xy_t)((num >> 32) & 0xFFFFFFFF), (xy_t)(num & 0xFFFFFFFF)) 30 | 31 | ret_t common_coord_init(void) { 32 | value_t v; 33 | ret_t ret = tk_atomic_init(&s_coord, value_set_uint64(&v, 0)); 34 | return_value_if_fail(RET_OK == ret, ret); 35 | return ret; 36 | } 37 | 38 | ret_t common_coord_get(point_t* p_coord) { 39 | value_t v; 40 | ret_t ret = RET_FAIL; 41 | return_value_if_fail(p_coord != NULL, RET_BAD_PARAMS); 42 | 43 | ret = tk_atomic_load(&s_coord, &v); 44 | if (RET_OK == ret) { 45 | uint64_t num = value_uint64(&v); 46 | *p_coord = COMMON_COORD_POINT_FROM_U64(num); 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | ret_t common_coord_set(point_t coord) { 53 | value_t v; 54 | return tk_atomic_store(&s_coord, value_set_uint64(&v, COMMON_COORD_POINT_TO_U64(coord))); 55 | } 56 | 57 | ret_t common_coord_deinit(void) { 58 | ret_t ret = tk_atomic_deinit(&s_coord); 59 | return_value_if_fail(RET_OK == ret, ret); 60 | return ret; 61 | } 62 | -------------------------------------------------------------------------------- /awtk-port/input_thread/common_coord.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: common_coord.h 3 | * Author: AWTK Develop Team 4 | * Brief: 公共坐标 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * this program is distributed in the hope that it will be useful, 9 | * but without any warranty; without even the implied warranty of 10 | * merchantability or fitness for a particular purpose. see the 11 | * license file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * history: 17 | * ================================================================ 18 | * 2023-08-11 Shen ZhaoKun created 19 | * 20 | */ 21 | 22 | #ifndef TK_COMMON_COORD_H 23 | #define TK_COMMON_COORD_H 24 | 25 | #include "tkc/types_def.h" 26 | #include "tkc/rect.h" 27 | 28 | BEGIN_C_DECLS 29 | 30 | ret_t common_coord_init(void); 31 | 32 | ret_t common_coord_get(point_t* p_coord); 33 | 34 | ret_t common_coord_set(point_t coord); 35 | 36 | ret_t common_coord_deinit(void); 37 | 38 | END_C_DECLS 39 | 40 | #endif /*TK_COMMON_COORD_H*/ 41 | -------------------------------------------------------------------------------- /awtk-port/input_thread/input_dispatcher.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: input_dispatcher. 3 | * Author: AWTK Develop Team 4 | * Brief: interface to dispatch input events 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include "input_dispatcher.h" 23 | 24 | ret_t input_dispatch_print(void* ctx, const event_queue_req_t* e, const char* msg) { 25 | switch (e->event.type) { 26 | case EVT_POINTER_DOWN: { 27 | log_debug("%s pointer down:%d %d\n", msg, e->pointer_event.x, e->pointer_event.y); 28 | break; 29 | } 30 | case EVT_POINTER_UP: { 31 | log_debug("%s pointer up:%d %d\n", msg, e->pointer_event.x, e->pointer_event.y); 32 | break; 33 | } 34 | case EVT_POINTER_MOVE: { 35 | log_debug("%s pointer move:%d %d\n", msg, e->pointer_event.x, e->pointer_event.y); 36 | break; 37 | } 38 | case EVT_CONTEXT_MENU: { 39 | log_debug("%s context menu:%d %d\n", msg, e->pointer_event.x, e->pointer_event.y); 40 | break; 41 | } 42 | case EVT_KEY_DOWN: { 43 | log_debug("%s keydown:%d\n", msg, e->key_event.key); 44 | break; 45 | } 46 | case EVT_KEY_UP: { 47 | log_debug("%s keyup:%d\n", msg, e->key_event.key); 48 | break; 49 | } 50 | } 51 | 52 | return RET_OK; 53 | } 54 | -------------------------------------------------------------------------------- /awtk-port/input_thread/input_dispatcher.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: input_dispatcher.h 3 | * Author: AWTK Develop Team 4 | * Brief: interface to dispatch input events 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef TK_INPUT_DISPATCHER_H 23 | #define TK_INPUT_DISPATCHER_H 24 | 25 | #include "base/event_queue.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | typedef ret_t (*input_dispatch_t)(void* ctx, const event_queue_req_t* e, const char* msg); 30 | 31 | ret_t input_dispatch_print(void* ctx, const event_queue_req_t* e, const char* msg); 32 | 33 | END_C_DECLS 34 | 35 | #endif /*TK_INPUT_DISPATCHER_H*/ 36 | -------------------------------------------------------------------------------- /awtk-port/input_thread/input_thread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: input_thread.h 3 | * Author: AWTK Develop Team 4 | * Brief: thread to read /dev/input/ 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef TK_INPUT_THREAD_H 23 | #define TK_INPUT_THREAD_H 24 | 25 | #include "tkc/thread.h" 26 | #include "input_dispatcher.h" 27 | 28 | BEGIN_C_DECLS 29 | 30 | tk_thread_t* input_thread_run(const char* filename, input_dispatch_t dispatch, void* ctx, 31 | int32_t max_x, int32_t max_y); 32 | ret_t input_thread_global_init(void); 33 | ret_t input_thread_global_deinit(void); 34 | 35 | END_C_DECLS 36 | 37 | #endif /*TK_INPUT_THREAD_H*/ 38 | -------------------------------------------------------------------------------- /awtk-port/input_thread/mouse_thread.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: mouse_thread.c 3 | * Author: AWTK Develop Team 4 | * Brief: thread to read /dev/input/ 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "tkc/mem.h" 27 | #include "tkc/utils.h" 28 | #include "tkc/thread.h" 29 | #include "base/keys.h" 30 | 31 | #include "mouse_thread.h" 32 | #include "common_coord.h" 33 | 34 | #ifndef EV_SYN 35 | #define EV_SYN 0x00 36 | #endif 37 | 38 | typedef struct _run_info_t { 39 | int fd; 40 | int32_t x; 41 | int32_t y; 42 | int32_t max_x; 43 | int32_t max_y; 44 | void* dispatch_ctx; 45 | char* filename; 46 | input_dispatch_t dispatch; 47 | union { 48 | int8_t d[3]; 49 | struct input_event e; /* for EasyARM-iMX280A_283A_287A */ 50 | } data; 51 | bool_t left_pressed; 52 | bool_t right_pressed; 53 | bool_t middle_pressed; 54 | event_queue_req_t req; 55 | } run_info_t; 56 | 57 | static ret_t input_dispatch(run_info_t* info) { 58 | ret_t ret = RET_FAIL; 59 | char message[MAX_PATH + 1] = {0}; 60 | tk_snprintf(message, sizeof(message) - 1, "mouse[%s]", info->filename); 61 | 62 | ret = info->dispatch(info->dispatch_ctx, &(info->req), message); 63 | info->req.event.type = EVT_NONE; 64 | 65 | return ret; 66 | } 67 | 68 | static ret_t input_dispatch_set_mouse_event(run_info_t* info, event_queue_req_t* req, bool_t left, 69 | bool_t right, bool_t middle, bool_t normal) { 70 | if (normal) { 71 | if (info->left_pressed || info->right_pressed || info->middle_pressed) { 72 | if (info->left_pressed) { 73 | info->left_pressed = FALSE; 74 | req->event.type = EVT_POINTER_UP; 75 | req->pointer_event.pressed = FALSE; 76 | } 77 | if (info->right_pressed) { 78 | info->right_pressed = FALSE; 79 | req->event.type = EVT_CONTEXT_MENU; 80 | } 81 | if (info->middle_pressed) { 82 | info->middle_pressed = FALSE; 83 | req->event.type = EVT_KEY_UP; 84 | req->key_event.key = TK_KEY_WHEEL; 85 | } 86 | } else { 87 | req->event.type = EVT_POINTER_MOVE; 88 | } 89 | } else { 90 | if (left) { 91 | if (!info->left_pressed) { 92 | info->left_pressed = TRUE; 93 | req->pointer_event.pressed = TRUE; 94 | req->event.type = EVT_POINTER_DOWN; 95 | } else { 96 | req->event.type = EVT_POINTER_MOVE; 97 | } 98 | } else if (middle) { 99 | info->middle_pressed = TRUE; 100 | req->event.type = EVT_KEY_DOWN; 101 | req->key_event.key = TK_KEY_WHEEL; 102 | } else if (right) { 103 | info->right_pressed = TRUE; 104 | req->event.type = EVT_POINTER_MOVE; 105 | } else { 106 | req->event.type = EVT_POINTER_MOVE; 107 | } 108 | } 109 | return RET_OK; 110 | } 111 | 112 | static ret_t input_dispatch_one_event(run_info_t* info) { 113 | int ret = 0; 114 | event_queue_req_t* req = &(info->req); 115 | 116 | if (info->fd < 0) { 117 | ret = -1; 118 | } else { 119 | ret = read(info->fd, &info->data.e, sizeof(info->data.e)); 120 | } 121 | 122 | if (ret < 0) { 123 | sleep(2); 124 | 125 | if (access(info->filename, R_OK) == 0) { 126 | if (info->fd >= 0) { 127 | close(info->fd); 128 | } 129 | 130 | info->fd = open(info->filename, O_RDONLY); 131 | if (info->fd < 0) { 132 | log_debug("%s:%d: open mouse failed, fd=%d, filename=%s\n", __func__, __LINE__, info->fd, 133 | info->filename); 134 | perror("print mouse: "); 135 | } else { 136 | log_debug("%s:%d: open mouse successful, fd=%d, filename=%s\n", __func__, __LINE__, 137 | info->fd, info->filename); 138 | } 139 | } 140 | } 141 | 142 | if (ret == 3) { 143 | bool_t left = info->data.d[0] & 0x1; 144 | bool_t right = info->data.d[0] & 0x2; 145 | bool_t middle = info->data.d[0] & 0x4; 146 | bool_t normal = !(info->data.d[0] & 0x7); 147 | int x = info->data.d[1]; 148 | int y = info->data.d[2]; 149 | 150 | point_t common_coord = {info->x, info->y}; 151 | if (RET_OK == common_coord_get(&common_coord)) { 152 | info->x = common_coord.x; 153 | info->y = common_coord.y; 154 | } 155 | 156 | info->x += x; 157 | info->y -= y; 158 | 159 | if (info->x < 0) { 160 | info->x = 0; 161 | } 162 | if (info->x > info->max_x) { 163 | info->x = info->max_x; 164 | } 165 | if (info->y < 0) { 166 | info->y = 0; 167 | } 168 | if (info->y > info->max_y) { 169 | info->y = info->max_y; 170 | } 171 | 172 | req->pointer_event.x = info->x; 173 | req->pointer_event.y = info->y; 174 | 175 | input_dispatch_set_mouse_event(info, req, left, right, middle, normal); 176 | input_dispatch(info); 177 | } else if (ret == sizeof(info->data.e)) { 178 | switch (info->data.e.type) { 179 | case EV_KEY: { 180 | bool_t left = 181 | info->data.e.value && (info->data.e.code == BTN_LEFT || info->data.e.code == BTN_TOUCH); 182 | bool_t right = info->data.e.value && info->data.e.code == BTN_RIGHT; 183 | bool_t middle = info->data.e.value && info->data.e.code == BTN_MIDDLE; 184 | bool_t normal = !(left || right || middle); 185 | input_dispatch_set_mouse_event(info, req, left, right, middle, normal); 186 | break; 187 | } 188 | case EV_ABS: { 189 | switch (info->data.e.code) { 190 | case ABS_X: { 191 | req->pointer_event.x = info->data.e.value; 192 | break; 193 | } 194 | case ABS_Y: { 195 | req->pointer_event.y = info->data.e.value; 196 | break; 197 | } 198 | default: 199 | break; 200 | } 201 | 202 | if (req->event.type == EVT_NONE) { 203 | req->event.type = EVT_POINTER_MOVE; 204 | } 205 | 206 | break; 207 | } 208 | case EV_REL: { 209 | point_t common_coord = {info->x, info->y}; 210 | if (RET_OK == common_coord_get(&common_coord)) { 211 | info->x = common_coord.x; 212 | info->y = common_coord.y; 213 | } 214 | 215 | switch (info->data.e.code) { 216 | case REL_X: { 217 | info->x += info->data.e.value; 218 | if (info->x < 0) { 219 | info->x = 0; 220 | } 221 | if (info->x > info->max_x) { 222 | info->x = info->max_x; 223 | } 224 | req->pointer_event.x = info->x; 225 | break; 226 | } 227 | case REL_Y: { 228 | info->y += info->data.e.value; 229 | if (info->y < 0) { 230 | info->y = 0; 231 | } 232 | if (info->y > info->max_y) { 233 | info->y = info->max_y; 234 | } 235 | req->pointer_event.y = info->y; 236 | break; 237 | } 238 | default: 239 | break; 240 | } 241 | 242 | if (req->event.type == EVT_NONE) { 243 | req->event.type = EVT_POINTER_MOVE; 244 | } 245 | 246 | break; 247 | } 248 | case EV_SYN: { 249 | switch (req->event.type) { 250 | case EVT_KEY_UP: 251 | case EVT_KEY_DOWN: 252 | case EVT_CONTEXT_MENU: 253 | case EVT_POINTER_DOWN: 254 | case EVT_POINTER_MOVE: 255 | case EVT_POINTER_UP: { 256 | return input_dispatch(info); 257 | } 258 | default: 259 | break; 260 | } 261 | break; 262 | } 263 | default: 264 | break; 265 | } 266 | } 267 | 268 | return RET_OK; 269 | } 270 | 271 | void* input_run(void* ctx) { 272 | run_info_t info = *(run_info_t*)ctx; 273 | if (info.fd < 0) { 274 | log_debug("%s:%d: open mouse failed, fd=%d, filename=%s\n", __func__, __LINE__, info.fd, 275 | info.filename); 276 | } else { 277 | log_debug("%s:%d: open mouse successful, fd=%d, filename=%s\n", __func__, __LINE__, info.fd, 278 | info.filename); 279 | } 280 | 281 | TKMEM_FREE(ctx); 282 | while (input_dispatch_one_event(&info) == RET_OK) { 283 | }; 284 | close(info.fd); 285 | TKMEM_FREE(info.filename); 286 | 287 | return NULL; 288 | } 289 | 290 | static run_info_t* info_dup(run_info_t* info) { 291 | run_info_t* new_info = TKMEM_ZALLOC(run_info_t); 292 | 293 | *new_info = *info; 294 | 295 | return new_info; 296 | } 297 | 298 | tk_thread_t* mouse_thread_run(const char* filename, input_dispatch_t dispatch, void* ctx, 299 | int32_t max_x, int32_t max_y) { 300 | run_info_t info; 301 | tk_thread_t* thread = NULL; 302 | return_value_if_fail(filename != NULL && dispatch != NULL, NULL); 303 | 304 | memset(&info, 0x00, sizeof(info)); 305 | 306 | info.max_x = max_x; 307 | info.max_y = max_y; 308 | info.dispatch_ctx = ctx; 309 | info.dispatch = dispatch; 310 | info.fd = open(filename, O_RDONLY); 311 | info.filename = tk_strdup(filename); 312 | 313 | thread = tk_thread_create(input_run, info_dup(&info)); 314 | if (thread != NULL) { 315 | tk_thread_start(thread); 316 | } else { 317 | close(info.fd); 318 | TKMEM_FREE(info.filename); 319 | } 320 | 321 | return thread; 322 | } 323 | -------------------------------------------------------------------------------- /awtk-port/input_thread/mouse_thread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: mouse_thread.h 3 | * Author: AWTK Develop Team 4 | * Brief: thread to read /dev/input/ 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef TK_MOUSE_THREAD_H 23 | #define TK_MOUSE_THREAD_H 24 | 25 | #include "tkc/thread.h" 26 | #include "input_dispatcher.h" 27 | 28 | BEGIN_C_DECLS 29 | 30 | tk_thread_t* mouse_thread_run(const char* filename, input_dispatch_t dispatch, void* ctx, 31 | int32_t max_x, int32_t max_y); 32 | 33 | END_C_DECLS 34 | 35 | #endif /*TK_MOUSE_THREAD_H*/ 36 | -------------------------------------------------------------------------------- /awtk-port/input_thread/tslib_thread.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: tslib_thread.c 3 | * Author: AWTK Develop Team 4 | * Brief: thread to handle touch screen events 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "tslib.h" 26 | #include "tkc/mem.h" 27 | #include "tkc/utils.h" 28 | #include "tkc/thread.h" 29 | #include "base/keys.h" 30 | 31 | #include "tslib_thread.h" 32 | 33 | typedef struct _run_info_t { 34 | int32_t max_x; 35 | int32_t max_y; 36 | struct tsdev* ts; 37 | void* dispatch_ctx; 38 | char* filename; 39 | input_dispatch_t dispatch; 40 | 41 | event_queue_req_t req; 42 | } run_info_t; 43 | 44 | static ret_t tslib_dispatch(run_info_t* info) { 45 | ret_t ret = RET_FAIL; 46 | char message[MAX_PATH + 1] = {0}; 47 | tk_snprintf(message, sizeof(message) - 1, "ts[%s]", info->filename); 48 | 49 | ret = info->dispatch(info->dispatch_ctx, &(info->req), message); 50 | info->req.event.type = EVT_NONE; 51 | 52 | return ret; 53 | } 54 | 55 | static ret_t tslib_dispatch_one_event(run_info_t* info) { 56 | struct ts_sample e = {0}; 57 | int ret = -1; 58 | 59 | if (info->ts != NULL) { 60 | ret = ts_read(info->ts, &e, 1); 61 | } 62 | 63 | event_queue_req_t* req = &(info->req); 64 | 65 | if (ret == 0) { 66 | log_warn("%s:%d: get tslib data failed, filename=%s\n", __func__, __LINE__, info->filename); 67 | sleep(1); 68 | return RET_OK; 69 | } else if (ret < 0) { 70 | sleep(2); 71 | 72 | if (access(info->filename, R_OK) == 0) { 73 | if (info->ts != NULL) { 74 | ts_close(info->ts); 75 | } 76 | info->ts = ts_open(info->filename, 0); 77 | return_value_if_fail(info->ts != NULL, RET_OK); 78 | ts_config(info->ts); 79 | 80 | if (info->ts == NULL) { 81 | log_debug("%s:%d: open tslib failed, filename=%s\n", __func__, __LINE__, info->filename); 82 | perror("print tslib: "); 83 | } else { 84 | log_debug("%s:%d: open tslib successful, filename=%s\n", __func__, __LINE__, 85 | info->filename); 86 | } 87 | } 88 | 89 | return RET_OK; 90 | } 91 | 92 | req->event.type = EVT_NONE; 93 | req->pointer_event.x = e.x; 94 | req->pointer_event.y = e.y; 95 | 96 | log_debug("%s%d: e.pressure=%d x=%d y=%d ret=%d\n", __func__, __LINE__, e.pressure, e.x, e.y, 97 | ret); 98 | 99 | if (e.pressure > 0) { 100 | if (req->pointer_event.pressed) { 101 | req->event.type = EVT_POINTER_MOVE; 102 | } else { 103 | req->event.type = EVT_POINTER_DOWN; 104 | req->pointer_event.pressed = TRUE; 105 | } 106 | } else { 107 | if (req->pointer_event.pressed) { 108 | req->event.type = EVT_POINTER_UP; 109 | } 110 | req->pointer_event.pressed = FALSE; 111 | } 112 | 113 | return tslib_dispatch(info); 114 | } 115 | 116 | void* tslib_run(void* ctx) { 117 | run_info_t info = *(run_info_t*)ctx; 118 | if (info.ts == NULL) { 119 | log_debug("%s:%d: open tslib failed, filename=%s\n", __func__, __LINE__, info.filename); 120 | } else { 121 | log_debug("%s:%d: open tslib successful, filename=%s\n", __func__, __LINE__, info.filename); 122 | } 123 | 124 | TKMEM_FREE(ctx); 125 | while (tslib_dispatch_one_event(&info) == RET_OK) { 126 | }; 127 | ts_close(info.ts); 128 | TKMEM_FREE(info.filename); 129 | 130 | return NULL; 131 | } 132 | 133 | static run_info_t* info_dup(run_info_t* info) { 134 | run_info_t* new_info = TKMEM_ZALLOC(run_info_t); 135 | 136 | *new_info = *info; 137 | 138 | return new_info; 139 | } 140 | 141 | tk_thread_t* tslib_thread_run(const char* filename, input_dispatch_t dispatch, void* ctx, 142 | int32_t max_x, int32_t max_y) { 143 | run_info_t info; 144 | tk_thread_t* thread = NULL; 145 | return_value_if_fail(filename != NULL && dispatch != NULL, NULL); 146 | 147 | memset(&info, 0x00, sizeof(info)); 148 | 149 | info.max_x = max_x; 150 | info.max_y = max_y; 151 | info.dispatch_ctx = ctx; 152 | info.dispatch = dispatch; 153 | info.ts = ts_open(filename, 0); 154 | info.filename = tk_strdup(filename); 155 | 156 | if (info.ts != NULL) { 157 | ts_config(info.ts); 158 | } 159 | 160 | thread = tk_thread_create(tslib_run, info_dup(&info)); 161 | if (thread != NULL) { 162 | tk_thread_start(thread); 163 | } else { 164 | ts_close(info.ts); 165 | TKMEM_FREE(info.filename); 166 | } 167 | 168 | return thread; 169 | } 170 | -------------------------------------------------------------------------------- /awtk-port/input_thread/tslib_thread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: tslib_thread.h 3 | * Author: AWTK Develop Team 4 | * Brief: thread to handle touch screen events 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef TK_TSLIB_THREAD_H 23 | #define TK_TSLIB_THREAD_H 24 | 25 | #include "tkc/thread.h" 26 | #include "input_dispatcher.h" 27 | 28 | BEGIN_C_DECLS 29 | 30 | tk_thread_t* tslib_thread_run(const char* filename, input_dispatch_t dispatch, void* ctx, 31 | int32_t max_x, int32_t max_y); 32 | 33 | END_C_DECLS 34 | 35 | #endif /*TK_TSLIB_THREAD_H*/ 36 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_linux_drm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_linux_drm.h 3 | * Author: AWTK Develop Team 4 | * Brief: linux drm lcd 5 | * 6 | * Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2020-05-16 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef TK_LCD_LINUX_DRM_H 23 | #define TK_LCD_LINUX_DRM_H 24 | 25 | #include "base/lcd.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | lcd_t* lcd_linux_drm_create(const char* card); 30 | 31 | END_C_DECLS 32 | 33 | #endif /*TK_LCD_LINUX_DRM_H*/ 34 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_linux_egl.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_linux_egl.c 3 | * Author: AWTK Develop Team 4 | * Brief: linux egl lcd 5 | * 6 | * Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2020-11-06 Lou ZhiMing created 19 | * 20 | */ 21 | 22 | #ifdef WITH_LINUX_EGL 23 | 24 | #include 25 | #include "tkc/mem.h" 26 | #include "glad/glad.h" 27 | #include "awtk_global.h" 28 | #include "lcd_linux_egl.h" 29 | #include "../egl_devices/egl_devices.h" 30 | #include "native_window/native_window_fb_gl.h" 31 | 32 | static lcd_egl_context_t* s_egl_context_lcd = NULL; 33 | 34 | static void on_app_exit(void) { 35 | 36 | } 37 | 38 | static void on_signal_int(int sig) { 39 | tk_quit(); 40 | } 41 | 42 | static ret_t lcd_linux_gles_swap_buffer(native_window_t* win) { 43 | lcd_egl_context_t* lcd = NULL; 44 | return_value_if_fail(win != NULL, RET_BAD_PARAMS); 45 | 46 | lcd = (lcd_egl_context_t*)(win->handle); 47 | return_value_if_fail(lcd != NULL, RET_BAD_PARAMS); 48 | 49 | return egl_devices_swap_buffers(lcd->elg_ctx); 50 | } 51 | 52 | static ret_t lcd_linux_gles_make_current(native_window_t* win) { 53 | ret_t ret = RET_OK; 54 | lcd_egl_context_t* lcd = NULL; 55 | return_value_if_fail(win != NULL, RET_BAD_PARAMS); 56 | 57 | lcd = (lcd_egl_context_t*)(win->handle); 58 | return_value_if_fail(lcd != NULL, RET_BAD_PARAMS); 59 | 60 | ret = egl_devices_make_current(lcd->elg_ctx); 61 | 62 | if (ret == RET_OK) { 63 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 64 | glViewport(0, 0, lcd->w, lcd->h); 65 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 66 | } 67 | return ret; 68 | } 69 | 70 | static ret_t lcd_linux_gles_destroy(native_window_t* win) { 71 | ret_t ret = RET_OK; 72 | lcd_egl_context_t* lcd = NULL; 73 | return_value_if_fail(win != NULL, RET_BAD_PARAMS); 74 | 75 | lcd = (lcd_egl_context_t*)(win->handle); 76 | return_value_if_fail(lcd != NULL, RET_BAD_PARAMS); 77 | 78 | ret = egl_devices_dispose(lcd->elg_ctx); 79 | if (ret == RET_OK) { 80 | TKMEM_FREE(lcd); 81 | } 82 | return ret; 83 | } 84 | 85 | static ret_t (*lcd_egl_linux_resize_default)(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length); 86 | static ret_t lcd_egl_linux_resize(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length) { 87 | ret_t ret = RET_OK; 88 | 89 | ret = egl_devices_resize(s_egl_context_lcd->elg_ctx, w, h); 90 | return_value_if_fail(ret == RET_OK, ret); 91 | 92 | s_egl_context_lcd->w = w; 93 | s_egl_context_lcd->h = h; 94 | 95 | if (lcd_egl_linux_resize_default != NULL) { 96 | lcd_egl_linux_resize_default(lcd, w, h, line_length); 97 | } 98 | 99 | return ret; 100 | } 101 | 102 | lcd_egl_context_t* lcd_linux_egl_create(const char* filename) { 103 | native_window_t* win = NULL; 104 | lcd_egl_context_t* lcd = TKMEM_ZALLOC(lcd_egl_context_t); 105 | return_value_if_fail(lcd != NULL, NULL); 106 | 107 | lcd->elg_ctx = egl_devices_create(filename); 108 | goto_error_if_fail(lcd->elg_ctx != NULL); 109 | 110 | lcd->w = egl_devices_get_width(lcd->elg_ctx); 111 | lcd->h = egl_devices_get_height(lcd->elg_ctx); 112 | lcd->ratio = egl_devices_get_ratio(lcd->elg_ctx); 113 | 114 | win = native_window_fb_gl_init(lcd->w, lcd->h, lcd->ratio); 115 | goto_error_if_fail(win != NULL); 116 | 117 | lcd_t* lcd_nanovg = native_window_get_lcd(win); 118 | goto_error_if_fail(lcd_nanovg != NULL); 119 | 120 | lcd_egl_linux_resize_default = lcd_nanovg->resize; 121 | lcd_nanovg->resize = lcd_egl_linux_resize; 122 | 123 | s_egl_context_lcd = lcd; 124 | win->handle = (void*)lcd; 125 | native_window_fb_gl_set_swap_buffer_func(win, lcd_linux_gles_swap_buffer); 126 | native_window_fb_gl_set_make_current_func(win, lcd_linux_gles_make_current); 127 | native_window_fb_gl_set_destroy_func(win, lcd_linux_gles_destroy); 128 | 129 | atexit(on_app_exit); 130 | signal(SIGINT, on_signal_int); 131 | signal(SIGTERM, on_signal_int); 132 | 133 | return lcd; 134 | error : 135 | native_window_fb_gl_deinit(); 136 | return NULL; 137 | } 138 | 139 | #endif /*WITH_LINUX_EGL*/ 140 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_linux_egl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_linux_egl.h 3 | * Author: AWTK Develop Team 4 | * Brief: linux egl lcd 5 | * 6 | * Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2020-11-06 Lou ZhiMing created 19 | * 20 | */ 21 | 22 | #ifndef TK_LCD_LINUX_EGL_H 23 | #define TK_LCD_LINUX_EGL_H 24 | 25 | #include "base/types_def.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | typedef struct _lcd_egl_context_t { 30 | int32_t w; 31 | int32_t h; 32 | float_t ratio; 33 | void* elg_ctx; 34 | } lcd_egl_context_t; 35 | 36 | lcd_egl_context_t* lcd_linux_egl_create(const char* filename); 37 | 38 | END_C_DECLS 39 | 40 | #endif /*TK_LCD_LINUX_EGL_H*/ 41 | 42 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_linux_fb.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_linux_fb.h 3 | * Author: AWTK Develop Team 4 | * Brief: linux framebuffer lcd 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifdef WITH_LINUX_FB 23 | 24 | #include 25 | #include "fb_info.h" 26 | #include "tkc/mem.h" 27 | #include "base/lcd.h" 28 | #include "tkc/thread.h" 29 | #include "awtk_global.h" 30 | #include "tkc/time_now.h" 31 | #include "tkc/mutex.h" 32 | #include "tkc/semaphore.h" 33 | #include "lcd_mem_others.h" 34 | #include "blend/image_g2d.h" 35 | #include "base/system_info.h" 36 | #include "lcd/lcd_mem_bgr565.h" 37 | #include "lcd/lcd_mem_rgb565.h" 38 | #include "lcd/lcd_mem_bgra8888.h" 39 | #include "lcd/lcd_mem_rgba8888.h" 40 | #include "lcd/lcd_mem_bgr888.h" 41 | #include "lcd/lcd_mem_rgb888.h" 42 | #include "base/lcd_orientation_helper.h" 43 | 44 | #define __FB_SUP_RESIZE 1 45 | #define __FB_WAIT_VSYNC 1 46 | 47 | static fb_info_t s_fb; 48 | static int s_ttyfd = -1; 49 | 50 | static bool_t lcd_linux_fb_open(fb_info_t* fb, const char* filename) { 51 | if (fb_open(fb, filename) == 0) { 52 | s_ttyfd = open("/dev/tty1", O_RDWR); 53 | if (s_ttyfd >= 0) { 54 | ioctl(s_ttyfd, KDSETMODE, KD_GRAPHICS); 55 | } 56 | 57 | // fix FBIOPAN_DISPLAY block issue when run in vmware double fb mode 58 | if (check_if_run_in_vmware()) { 59 | log_info("run in vmware and fix FBIOPAN_DISPLAY block issue\n"); 60 | // if memset/memcpy the entire fb then call FBIOPAN_DISPLAY immediately, 61 | // the ubuntu in vmware will stuck by unknown reason, sleep for avoid this bug 62 | fb->var.activate = FB_ACTIVATE_INV_MODE; 63 | fb->var.pixclock = 60; 64 | usleep(500000); 65 | } 66 | return TRUE; 67 | } 68 | return FALSE; 69 | } 70 | 71 | static void lcd_linux_fb_close(fb_info_t* fb) { 72 | if (s_ttyfd >= 0) { 73 | ioctl(s_ttyfd, KDSETMODE, KD_TEXT); 74 | } 75 | fb_close(fb); 76 | } 77 | 78 | static void on_app_exit(void) { 79 | fb_info_t* fb = &s_fb; 80 | lcd_linux_fb_close(fb); 81 | log_debug("on_app_exit\n"); 82 | } 83 | 84 | #if __FB_SUP_RESIZE 85 | static ret_t (*lcd_mem_linux_resize_default)(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length); 86 | static ret_t lcd_mem_linux_resize(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length) { 87 | ret_t ret = RET_OK; 88 | fb_info_t* fb = &s_fb; 89 | return_value_if_fail(lcd != NULL, RET_BAD_PARAMS); 90 | 91 | ret = fb_resize_reopen(fb, w, h); 92 | lcd_mem_set_double_fb_bitmap(lcd, fb->online_fb, fb->offline_fb); 93 | lcd_mem_set_line_length(lcd, fb_line_length(fb)); 94 | 95 | if (lcd_mem_linux_resize_default && ret == RET_OK) { 96 | lcd_mem_linux_resize_default(lcd, w, h, line_length); 97 | } 98 | 99 | log_debug("lcd_linux_fb_resize \r\n"); 100 | return ret; 101 | } 102 | #endif 103 | 104 | static void on_signal_int(int sig) { 105 | tk_quit(); 106 | } 107 | 108 | static ret_t (*lcd_mem_linux_flush_default)(lcd_t* lcd); 109 | static ret_t lcd_mem_linux_flush(lcd_t* lcd) { 110 | #if __FB_WAIT_VSYNC 111 | fb_info_t* fb = &s_fb; 112 | if (!fb_is_1fb(fb)) { 113 | struct fb_var_screeninfo vi = (fb->var); 114 | vi.yoffset = 0; 115 | ioctl(fb->fd, FBIOPAN_DISPLAY, &vi); 116 | } 117 | int dummy = 0; 118 | ioctl(fb->fd, FBIO_WAITFORVSYNC, &dummy); 119 | #endif 120 | 121 | if (lcd_mem_linux_flush_default) { 122 | lcd_mem_linux_flush_default(lcd); 123 | } 124 | return RET_OK; 125 | } 126 | 127 | static lcd_t* lcd_linux_create_flushable(fb_info_t* fb) { 128 | lcd_t* lcd = NULL; 129 | int bpp = fb_bpp(fb); 130 | int line_length = fb_line_length(fb); 131 | bitmap_t* online_fb = fb->online_fb; 132 | bitmap_t* offline_fb = fb->offline_fb; 133 | return_value_if_fail(offline_fb != NULL, NULL); 134 | 135 | if (bpp == 16) { 136 | if (fb_is_bgra5551(fb)) { 137 | lcd = lcd_mem_bgra5551_create(fb); 138 | } else if (fb_is_bgr565(fb)) { 139 | lcd = lcd_mem_bgr565_create_double_fb_bitmap(online_fb, offline_fb); 140 | } else if (fb_is_rgb565(fb)) { 141 | lcd = lcd_mem_rgb565_create_double_fb_bitmap(online_fb, offline_fb); 142 | } else { 143 | assert(!"not supported framebuffer format."); 144 | } 145 | } else if (bpp == 32) { 146 | if (fb_is_bgra8888(fb)) { 147 | lcd = lcd_mem_bgra8888_create_double_fb_bitmap(online_fb, offline_fb); 148 | } else if (fb_is_rgba8888(fb)) { 149 | lcd = lcd_mem_rgba8888_create_double_fb_bitmap(online_fb, offline_fb); 150 | } else { 151 | assert(!"not supported framebuffer format."); 152 | } 153 | } else if (bpp == 24) { 154 | if (fb_is_bgr888(fb)) { 155 | lcd = lcd_mem_bgr888_create_double_fb_bitmap(online_fb, offline_fb); 156 | } else if (fb_is_rgb888(fb)) { 157 | lcd = lcd_mem_rgb888_create_double_fb_bitmap(online_fb, offline_fb); 158 | } else { 159 | assert(!"not supported framebuffer format."); 160 | } 161 | } else { 162 | assert(!"not supported framebuffer format."); 163 | } 164 | 165 | if (lcd != NULL) { 166 | lcd_mem_linux_flush_default = lcd->flush; 167 | lcd->flush = lcd_mem_linux_flush; 168 | lcd_mem_set_line_length(lcd, line_length); 169 | 170 | #if __FB_SUP_RESIZE 171 | lcd_mem_linux_resize_default = lcd->resize; 172 | lcd->resize = lcd_mem_linux_resize; 173 | #endif 174 | } 175 | 176 | return lcd; 177 | } 178 | 179 | static lcd_t* lcd_linux_create(fb_info_t* fb) { 180 | printf("=========fb_number=%d\n", fb_number(fb)); 181 | return lcd_linux_create_flushable(fb); 182 | } 183 | 184 | lcd_t* lcd_linux_fb_create(const char* filename) { 185 | lcd_t* lcd = NULL; 186 | fb_info_t* fb = &s_fb; 187 | return_value_if_fail(filename != NULL, NULL); 188 | 189 | if (lcd_linux_fb_open(fb, filename)) { 190 | lcd = lcd_linux_create(fb); 191 | } 192 | 193 | atexit(on_app_exit); 194 | signal(SIGINT, on_signal_int); 195 | signal(SIGTERM, on_signal_int); 196 | 197 | return lcd; 198 | } 199 | 200 | #endif /*WITH_LINUX_FB*/ 201 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_linux_fb.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_linux_fb.h 3 | * Author: AWTK Develop Team 4 | * Brief: linux framebuffer lcd 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef TK_LCD_LINUX_FB_H 23 | #define TK_LCD_LINUX_FB_H 24 | 25 | #include "base/lcd.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | lcd_t* lcd_linux_fb_create(const char* filename); 30 | 31 | END_C_DECLS 32 | 33 | #endif /*TK_LCD_LINUX_FB_H*/ 34 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_mem_others.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_mem_others.c 3 | * Author: AWTK Develop Team 4 | * Brief: support other special format linux framebuffers 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2019-06-17 Li XianJing created 19 | * 20 | */ 21 | 22 | #include "lcd_mem_others.h" 23 | 24 | static ret_t lcd_bgra5551_flush(lcd_t* lcd) { 25 | rect_t* dr = &(lcd->dirty_rect); 26 | lcd_mem_special_t* special = (lcd_mem_special_t*)lcd; 27 | fb_info_t* info = (fb_info_t*)(special->ctx); 28 | 29 | if (dr->w > 0 && dr->h > 0) { 30 | uint32_t x = 0; 31 | uint32_t y = 0; 32 | int src_line_length = lcd->w; 33 | int dst_line_length = info->fix.line_length / 2; 34 | uint16_t* dst = (uint16_t*)(info->fbmem0); 35 | uint16_t* src = (uint16_t*)(lcd_mem_get_offline_fb((lcd_mem_t*)lcd)); 36 | 37 | src += dr->y * src_line_length + dr->x; 38 | dst += dr->y * dst_line_length + dr->x; 39 | 40 | for (y = 0; y < dr->h; y++) { 41 | for (x = 0; x < dr->w; x++) { 42 | uint16_t s = src[x]; 43 | uint8_t b = 0x1f & s; 44 | uint8_t g = (0x7e0 & s) >> 5; 45 | uint8_t r = (0xf800 & s) >> 11; 46 | 47 | dst[x] = 0x8000 | (r << 10) | (g << 5) | b; 48 | } 49 | 50 | src += src_line_length; 51 | dst += dst_line_length; 52 | } 53 | } 54 | 55 | return RET_OK; 56 | } 57 | 58 | lcd_t* lcd_mem_bgra5551_create(fb_info_t* info) { 59 | wh_t w = fb_width(info); 60 | wh_t h = fb_height(info); 61 | 62 | return lcd_mem_special_create(w, h, BITMAP_FMT_BGR565, lcd_bgra5551_flush, NULL, NULL, info); 63 | } 64 | -------------------------------------------------------------------------------- /awtk-port/lcd_linux/lcd_mem_others.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_mem_others.h 3 | * Author: AWTK Develop Team 4 | * Brief: support other special format linux framebuffers 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2019-06-17 Li XianJing created 19 | * 20 | */ 21 | 22 | #ifndef LCD_MEM_OTHERS_H 23 | #define LCD_MEM_OTHERS_H 24 | 25 | #include "fb_info.h" 26 | #include "lcd/lcd_mem_special.h" 27 | 28 | BEGIN_C_DECLS 29 | 30 | lcd_t* lcd_mem_bgra5551_create(fb_info_t* fb); 31 | 32 | END_C_DECLS 33 | 34 | #endif /*LCD_MEM_OTHERS_H*/ 35 | -------------------------------------------------------------------------------- /awtk-port/main_loop_linux.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: main_loop_linux.c 3 | * Author: AWTK Develop Team 4 | * Brief: linux implemented main_loop interface 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * this program is distributed in the hope that it will be useful, 9 | * but without any warranty; without even the implied warranty of 10 | * merchantability or fitness for a particular purpose. see the 11 | * license file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * history: 17 | * ================================================================ 18 | * 2018-09-09 li xianjing created 19 | * 20 | */ 21 | 22 | #include "base/idle.h" 23 | #include "base/timer.h" 24 | #include "base/font_manager.h" 25 | #include "base/window_manager.h" 26 | #include "main_loop/main_loop_simple.h" 27 | #include "native_window/native_window_raw.h" 28 | 29 | #include "tslib_thread.h" 30 | #include "input_thread.h" 31 | #include "mouse_thread.h" 32 | #include "lcd_linux_fb.h" 33 | #include "lcd_linux_drm.h" 34 | #include "lcd_linux_egl.h" 35 | #include "main_loop_linux.h" 36 | #include "devices.h" 37 | #include "common_coord.h" 38 | 39 | #ifdef WITH_LINUX_EGL 40 | #define LCD_T lcd_egl_context_t 41 | #else 42 | #define LCD_T lcd_t 43 | #endif 44 | 45 | #ifndef FB_DEVICE_FILENAME 46 | #define FB_DEVICE_FILENAME "/dev/fb0" 47 | #endif /*FB_DEVICE_FILENAME*/ 48 | 49 | #ifndef DRM_DEVICE_FILENAME 50 | #define DRM_DEVICE_FILENAME "/dev/dri/card0" 51 | #endif /*DRM_DEVICE_FILENAME*/ 52 | 53 | #ifndef TS_DEVICE_FILENAME 54 | #define TS_DEVICE_FILENAME "/dev/input/event0" 55 | #endif /*TS_DEVICE_FILENAME*/ 56 | 57 | #ifndef KB_DEVICE_FILENAME 58 | #define KB_DEVICE_FILENAME "/dev/input/event1" 59 | #endif /*KB_DEVICE_FILENAME*/ 60 | 61 | #ifndef MICE_DEVICE_FILENAME 62 | #define MICE_DEVICE_FILENAME "/dev/input/event2" 63 | #endif /*MICE_DEVICE_FILENAME*/ 64 | 65 | static device_info_t s_devices_default[] = {{"fb", FB_DEVICE_FILENAME}, 66 | {"drm", DRM_DEVICE_FILENAME}, 67 | {"ts", TS_DEVICE_FILENAME}, 68 | {"input", KB_DEVICE_FILENAME}, 69 | {"mouse", MICE_DEVICE_FILENAME}}; 70 | static slist_t s_device_threads_list; 71 | 72 | static ret_t main_loop_linux_destroy(main_loop_t* l) { 73 | main_loop_simple_t* loop = (main_loop_simple_t*)l; 74 | 75 | main_loop_simple_reset(loop); 76 | 77 | #ifdef WITH_LINUX_EGL 78 | #else 79 | native_window_raw_deinit(); 80 | #endif 81 | 82 | return RET_OK; 83 | } 84 | 85 | ret_t input_dispatch_to_main_loop(void* ctx, const event_queue_req_t* evt, const char* msg) { 86 | main_loop_simple_t* l = (main_loop_simple_t*)ctx; 87 | event_queue_req_t event = *evt; 88 | event_queue_req_t* e = &event; 89 | 90 | if (l != NULL && l->base.queue_event != NULL) { 91 | switch (e->event.type) { 92 | case EVT_KEY_DOWN: 93 | case EVT_KEY_UP: 94 | case EVT_KEY_LONG_PRESS: { 95 | e->event.size = sizeof(e->key_event); 96 | break; 97 | } 98 | case EVT_CONTEXT_MENU: { 99 | e->event.size = sizeof(e->pointer_event); 100 | break; 101 | } 102 | case EVT_POINTER_DOWN: { 103 | l->pressed = TRUE; 104 | e->pointer_event.pressed = l->pressed; 105 | e->event.size = sizeof(e->pointer_event); 106 | break; 107 | } 108 | case EVT_POINTER_MOVE: { 109 | point_t common_coord = {e->pointer_event.x, e->pointer_event.y}; 110 | common_coord_set(common_coord); 111 | e->pointer_event.pressed = l->pressed; 112 | e->event.size = sizeof(e->pointer_event); 113 | break; 114 | } 115 | case EVT_POINTER_UP: { 116 | e->pointer_event.pressed = l->pressed; 117 | l->pressed = FALSE; 118 | e->event.size = sizeof(e->pointer_event); 119 | break; 120 | } 121 | case EVT_WHEEL: { 122 | e->event.size = sizeof(e->wheel_event); 123 | break; 124 | } 125 | default: 126 | break; 127 | } 128 | 129 | main_loop_queue_event(&(l->base), e); 130 | input_dispatch_print(ctx, e, msg); 131 | } else { 132 | return RET_BAD_PARAMS; 133 | } 134 | return RET_OK; 135 | } 136 | 137 | static void on_app_exit(void) { 138 | slist_deinit(&s_device_threads_list); 139 | input_thread_global_deinit(); 140 | common_coord_deinit(); 141 | devices_unload(); 142 | } 143 | 144 | static ret_t lcd_create_on_devices_visit(void* ctx, const device_info_t* info) { 145 | LCD_T** p_lcd = (LCD_T**)ctx; 146 | 147 | #ifdef WITH_LINUX_EGL 148 | if (tk_str_eq(info->type, "fb")) { 149 | *p_lcd = lcd_linux_egl_create(info->path); 150 | } 151 | #elif WITH_LINUX_DRM 152 | if (tk_str_eq(info->type, "drm")) { 153 | *p_lcd = lcd_linux_drm_create(info->path); 154 | } 155 | #else 156 | if (tk_str_eq(info->type, "fb")) { 157 | *p_lcd = lcd_linux_fb_create(info->path); 158 | } 159 | #endif 160 | 161 | if (*p_lcd != NULL) { 162 | return RET_STOP; 163 | } 164 | 165 | return RET_OK; 166 | } 167 | 168 | static ret_t device_thread_run_on_devices_visit(void* ctx, const device_info_t* info) { 169 | main_loop_simple_t* loop = (main_loop_simple_t*)ctx; 170 | tk_thread_t* thread = NULL; 171 | ret_t ret = RET_OK; 172 | 173 | if (tk_str_eq(info->type, "input")) { 174 | thread = input_thread_run(info->path, input_dispatch_to_main_loop, loop, loop->w, loop->h); 175 | } else if (tk_str_eq(info->type, "mouse")) { 176 | thread = mouse_thread_run(info->path, input_dispatch_to_main_loop, loop, loop->w, loop->h); 177 | } else if (tk_str_eq(info->type, "ts")) { 178 | #ifdef HAS_TSLIB 179 | thread = tslib_thread_run(info->path, input_dispatch_to_main_loop, loop, loop->w, loop->h); 180 | #endif /*HAS_TSLIB*/ 181 | } 182 | 183 | if (thread != NULL) { 184 | ret = slist_append(&s_device_threads_list, thread); 185 | } 186 | 187 | return ret; 188 | } 189 | 190 | main_loop_t* main_loop_init(int w, int h) { 191 | main_loop_simple_t* loop = NULL; 192 | LCD_T* lcd = NULL; 193 | 194 | if (RET_OK != devices_load()) { 195 | log_warn("Devices load fail! Used default.\r\n"); 196 | devices_set(s_devices_default, ARRAY_SIZE(s_devices_default)); 197 | } 198 | devices_foreach(lcd_create_on_devices_visit, &lcd); 199 | return_value_if_fail(lcd != NULL, NULL); 200 | 201 | #ifdef WITH_LINUX_EGL 202 | #else 203 | native_window_raw_init(lcd); 204 | #endif 205 | 206 | loop = main_loop_simple_init(lcd->w, lcd->h, NULL, NULL); 207 | loop->base.destroy = main_loop_linux_destroy; 208 | 209 | common_coord_init(); 210 | input_thread_global_init(); 211 | slist_init(&s_device_threads_list, (tk_destroy_t)tk_thread_destroy, NULL); 212 | devices_foreach(device_thread_run_on_devices_visit, loop); 213 | 214 | atexit(on_app_exit); 215 | 216 | return (main_loop_t*)loop; 217 | } 218 | -------------------------------------------------------------------------------- /awtk-port/main_loop_linux.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: main_loop_linux.h 3 | * Author: AWTK Develop Team 4 | * Brief: linux implemented main_loop interface 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * this program is distributed in the hope that it will be useful, 9 | * but without any warranty; without even the implied warranty of 10 | * merchantability or fitness for a particular purpose. see the 11 | * license file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * history: 17 | * ================================================================ 18 | * 2018-09-09 li xianjing created 19 | * 20 | */ 21 | 22 | #ifndef TK_MAIN_LOOP_LINUX_H 23 | #define TK_MAIN_LOOP_LINUX_H 24 | 25 | #include "base/main_loop.h" 26 | 27 | BEGIN_C_DECLS 28 | 29 | main_loop_t* main_loop_init(int w, int h); 30 | 31 | END_C_DECLS 32 | 33 | #endif /*TK_MAIN_LOOP_LINUX_H*/ 34 | -------------------------------------------------------------------------------- /awtk-port/test/fb_test.c: -------------------------------------------------------------------------------- 1 | #include "tkc/platform.h" 2 | #include "tkc/time_now.h" 3 | #include "tkc/utils.h" 4 | #include "fb_info.h" 5 | #include 6 | 7 | static int s_ttyfd = -1; 8 | static bool_t s_quited = FALSE; 9 | static uint32_t s_buff_index = 0; 10 | 11 | static void fb_draw_test(fb_info_t* fb, color_t color) { 12 | 13 | uint32_t cost = 0; 14 | int fb_nr = fb_number(fb); 15 | uint32_t fb_bpp = fb_bpp(fb); 16 | uint32_t start = time_now_ms(); 17 | uint32_t buff_size = fb_size(fb); 18 | struct fb_var_screeninfo vi = (fb->var); 19 | uint32_t size = fb->var.xres_virtual * fb_height(fb); 20 | uint8_t* buff = fb->fbmem0 + buff_size * s_buff_index; 21 | 22 | if (fb_bpp == 16) { 23 | uint16_t c = ((color.rgba.r >> 3) << 11) | ((color.rgba.g >> 2) << 5) | (color.rgba.b >> 3); 24 | tk_memset16((uint16_t*)buff, c, size); 25 | } else if (fb_bpp == 32) { 26 | uint32_t c = ((color.rgba.r << 24) | (color.rgba.g << 16) | (color.rgba.b << 8) | 0xff); 27 | tk_memset32((uint32_t*)buff, c, size); 28 | } else if (fb_bpp == 24) { 29 | int32_t i = 0; 30 | for (i = 0; i < size; i++) { 31 | *buff++ = color.rgba.r; 32 | *buff++ = color.rgba.g; 33 | *buff++ = color.rgba.b; 34 | } 35 | } else { 36 | log_error(" fb_test don't supported \r\n"); 37 | } 38 | 39 | if (fb_nr > 1) { 40 | vi.yoffset = s_buff_index * fb_height(fb); 41 | vi.yres_virtual = vi.yres * fb_nr; 42 | 43 | if (ioctl(fb->fd, FBIOPUT_VSCREENINFO, &vi) < 0) { 44 | perror("active fb swap failed"); 45 | } 46 | cost = time_now_ms() - start; 47 | log_info("i=%d: cost=%u fb=%p yoffset=%u size=%u\n", s_buff_index, cost, buff, vi.yoffset, buff_size); 48 | 49 | s_buff_index++; 50 | if (s_buff_index >= fb_nr) { 51 | s_buff_index = 0; 52 | } 53 | } else { 54 | fb_sync(fb); 55 | } 56 | } 57 | 58 | static void on_fb_test_exit(void) { 59 | s_quited = TRUE; 60 | sleep_ms(10); 61 | if (s_ttyfd >= 0) { 62 | ioctl(s_ttyfd, KDSETMODE, KD_TEXT); 63 | } 64 | log_info("on_fb_test_exit \r\n"); 65 | } 66 | 67 | static void on_signal_int(int sig) { 68 | on_fb_test_exit(); 69 | } 70 | 71 | int main(int argc, char* argv[]) { 72 | fb_info_t fb; 73 | const char* fbname = "/dev/fb0"; 74 | color_t color = color_init(0xff, 0, 0, 0xff); 75 | 76 | platform_prepare(); 77 | 78 | atexit(on_fb_test_exit); 79 | signal(SIGINT, on_signal_int); 80 | 81 | if (argc != 2) { 82 | log_info("Usage: %s fbdevice\n", argv[0]); 83 | return 0; 84 | } 85 | 86 | fbname = argv[1]; 87 | memset(&fb, 0x00, sizeof(fb)); 88 | 89 | if (fb_open(&fb, fbname) == 0) { 90 | int32_t i = 0; 91 | s_ttyfd = open("/dev/tty1", O_RDWR); 92 | if (s_ttyfd >= 0) { 93 | ioctl(s_ttyfd, KDSETMODE, KD_GRAPHICS); 94 | } 95 | 96 | // fix FBIOPUT_VSCREENINFO block issue when run in vmware double fb mode 97 | if (check_if_run_in_vmware() && fb_number((&fb)) > 1) { 98 | log_info("run in vmware and fix FBIOPUT_VSCREENINFO block issue\n"); 99 | fb.var.activate = FB_ACTIVATE_INV_MODE; 100 | fb.var.pixclock = 60; 101 | } 102 | 103 | for (i = 0; i < 0xff * 2; i++) { 104 | if (s_quited) { 105 | break; 106 | } 107 | fb_draw_test(&fb, color); 108 | 109 | if (i > 0xff) { 110 | uint32_t c = (i - 0xff); 111 | color.color = (c << 16) | ((0xff - c) << 8) | 0xff0000ff; 112 | } else { 113 | color.color = (i << 8) | 0xff0000ff; 114 | } 115 | 116 | log_info("i:%d, color:(%d, %d, %d, %d) \r\n", i, color.rgba.r, color.rgba.g, color.rgba.b, color.rgba.a); 117 | sleep_ms(100); 118 | } 119 | log_info(" fb_test finished and quited \r\n"); 120 | fb_close(&fb); 121 | } 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /awtk-port/test/input_thread_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: input_thread_test.c 3 | * Author: AWTK Develop Team 4 | * Brief: test input thread 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include "input_thread.h" 23 | 24 | int main(int argc, char* argv[]) { 25 | tk_thread_t* thread = NULL; 26 | if (argc < 2) { 27 | printf("%s filename\n", argv[0]); 28 | return 0; 29 | } 30 | 31 | thread = input_thread_run(argv[1], input_dispatch_print, NULL, 320, 480); 32 | 33 | tk_thread_join(thread); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /awtk-port/test/mouse_thread_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: mouse_thread_test.c 3 | * Author: AWTK Develop Team 4 | * Brief: test mouse thread 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include "mouse_thread.h" 23 | 24 | int main(int argc, char* argv[]) { 25 | tk_thread_t* thread = NULL; 26 | if (argc < 2) { 27 | printf("%s filename\n", argv[0]); 28 | return 0; 29 | } 30 | 31 | thread = mouse_thread_run(argv[1], input_dispatch_print, NULL, 320, 480); 32 | 33 | tk_thread_join(thread); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /awtk-port/test/tslib_thread_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: tslib_thread_test.c 3 | * Author: AWTK Develop Team 4 | * Brief: test tslib thread 5 | * 6 | * Copyright (c) 2018 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include "tslib_thread.h" 23 | 24 | int main(int argc, char* argv[]) { 25 | tk_thread_t* thread = NULL; 26 | if (argc < 2) { 27 | printf("%s filename\n", argv[0]); 28 | return 0; 29 | } 30 | 31 | thread = tslib_thread_run(argv[1], input_dispatch_print, NULL, 320, 480); 32 | 33 | tk_thread_join(thread); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /awtk-wayland/SConscript: -------------------------------------------------------------------------------- 1 | import os 2 | import copy 3 | import scons_argv 4 | compile_helper = scons_argv.get_compile_config() 5 | 6 | BIN_DIR = os.environ['BIN_DIR']; 7 | LIB_DIR = os.environ['LIB_DIR']; 8 | LCD_DEVICES = os.environ['LCD_DEVICES'] 9 | 10 | env = DefaultEnvironment().Clone() 11 | 12 | WAYLAND_SCANNER_PATH = compile_helper.get_value('WAYLAND_SCANNER_PATH', None) 13 | if WAYLAND_SCANNER_PATH != None : 14 | os.system(WAYLAND_SCANNER_PATH + '/wayland-scanner ' + ' client-header ' + ' protocol/xdg-shell.xml ' + ' protocol/xdg-shell-protocol.h') 15 | os.system(WAYLAND_SCANNER_PATH + '/wayland-scanner ' + ' private-code ' + ' protocol/xdg-shell.xml ' + ' protocol/xdg-shell-protocol.c') 16 | os.system(WAYLAND_SCANNER_PATH + '/wayland-scanner ' + ' client-header ' + ' protocol/fullscreen-shell-unstable-v1.xml ' + ' protocol/fullscreen-shell-protocol.h') 17 | os.system(WAYLAND_SCANNER_PATH + '/wayland-scanner ' + ' private-code ' + ' protocol/fullscreen-shell-unstable-v1.xml ' + 'protocol/fullscreen-shell-protocol.c') 18 | 19 | SOURCES = [] 20 | SOURCES += Glob('protocol/*.c') 21 | 22 | if LCD_DEVICES == 'wayland' : 23 | SOURCES += Glob('wayland/*.c'); 24 | elif LCD_DEVICES == 'egl_for_wayland' : 25 | SOURCES += Glob('egl_for_wayland/*.c'); 26 | 27 | awtk_linux_fb = env.Library(os.path.join(LIB_DIR, 'awtk_linux_fb'), SOURCES) 28 | 29 | extern_codes = compile_helper.get_value('EXTERN_CODE', None) 30 | if extern_codes != None : 31 | all_extern_codes = [] 32 | for extern_code in extern_codes : 33 | all_extern_codes += Glob(extern_code); 34 | __extern_code = env.Library(os.path.join(LIB_DIR, '__extern_code'), all_extern_codes) 35 | Depends(awtk_linux_fb, __extern_code) 36 | 37 | env['LIBS'] = ['awtk_linux_fb'] + env['LIBS'] 38 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/input_dispatch.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/awtk-wayland/egl_for_wayland/input_dispatch.c -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/lcd_wayland.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_wayland.c 3 | * Author: AWTK Develop Team 4 | * Brief: lcd wayland 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #include "lcd_wayland.h" 23 | 24 | #include "base/idle.h" 25 | #include "base/timer.h" 26 | #include "base/window_manager.h" 27 | #include "main_loop/main_loop_simple.h" 28 | #include "tkc/thread.h" 29 | 30 | #ifndef FULLSCREEN 31 | #define FULLSCREEN FALSE 32 | #endif 33 | 34 | enum key_repeat_state { 35 | repeat_key_released = 0, 36 | repeat_key_pressed = 10, 37 | repeat_key_delay, 38 | repeat_key_rate, 39 | }; 40 | 41 | lcd_wayland_t* lw = NULL; 42 | enum key_repeat_state __repeat_state = repeat_key_released; 43 | static int32_t key_value; 44 | extern int32_t map_key(uint8_t code); 45 | 46 | void on_app_exit(void) { 47 | if (lw) { 48 | destroy_wayland_data(&lw->objs); 49 | } 50 | } 51 | 52 | static ret_t input_dispatch_to_main_loop(void* ctx, const event_queue_req_t* e) { 53 | main_loop_queue_event((main_loop_t*)ctx, e); 54 | return RET_OK; 55 | } 56 | 57 | static void key_input_dispatch(int32_t state, int32_t key) { 58 | event_queue_req_t req; 59 | 60 | req.event.type = (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? EVT_KEY_DOWN : EVT_KEY_UP; 61 | req.key_event.key = map_key(key); 62 | 63 | input_dispatch_to_main_loop(main_loop(), &req); 64 | 65 | req.event.type = EVT_NONE; 66 | 67 | if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { 68 | __repeat_state = repeat_key_pressed; 69 | key_value = key; 70 | } else { 71 | __repeat_state = repeat_key_released; 72 | } 73 | } 74 | 75 | static void mouse_point_dispatch(int32_t state, int32_t button, int32_t x, int32_t y) { 76 | event_queue_req_t r; 77 | event_queue_req_t* req = &r; 78 | main_loop_simple_t* l = (main_loop_simple_t*)main_loop(); 79 | static int32_t __x,__y; 80 | 81 | if (x > 0) { 82 | __x = x; 83 | } 84 | 85 | if (y > 0) { 86 | __y = y; 87 | } 88 | 89 | req->pointer_event.x = __x; 90 | req->pointer_event.y = __y; 91 | req->event.time = time_now_ms(); 92 | 93 | if (button == BTN_LEFT) { 94 | req->event.size = sizeof(req->pointer_event); 95 | switch (state) { 96 | case WL_POINTER_BUTTON_STATE_PRESSED: 97 | req->event.type = EVT_POINTER_DOWN; 98 | l->pressed = TRUE; 99 | req->pointer_event.pressed = TRUE; 100 | break; 101 | case WL_POINTER_BUTTON_STATE_RELEASED: 102 | req->event.type = EVT_POINTER_UP; 103 | req->pointer_event.pressed = l->pressed; 104 | l->pressed = FALSE; 105 | break; 106 | } 107 | } else if (button == BTN_RIGHT) { 108 | req->event.size = sizeof(req->pointer_event); 109 | if (state == WL_POINTER_BUTTON_STATE_RELEASED) { 110 | req->event.type = EVT_CONTEXT_MENU; 111 | req->pointer_event.pressed = FALSE; 112 | } 113 | } else if (button == BTN_MIDDLE) { 114 | req->event.size = sizeof(req->key_event); 115 | switch (state) { 116 | case WL_POINTER_BUTTON_STATE_PRESSED: 117 | req->event.type = EVT_KEY_DOWN; 118 | req->key_event.key = TK_KEY_WHEEL; 119 | break; 120 | case WL_POINTER_BUTTON_STATE_RELEASED: 121 | req->event.type = EVT_KEY_UP; 122 | req->key_event.key = TK_KEY_WHEEL; 123 | break; 124 | } 125 | } else { 126 | req->event.size = sizeof(req->pointer_event); 127 | req->event.type = EVT_POINTER_MOVE; 128 | } 129 | 130 | input_dispatch_to_main_loop(main_loop(), req); 131 | } 132 | 133 | void kb_repeat(void) { 134 | static uint32_t repeat_count = 0; 135 | switch (__repeat_state) { 136 | case repeat_key_pressed: 137 | repeat_count = 0; 138 | __repeat_state = repeat_key_delay; 139 | break; 140 | case repeat_key_delay: 141 | repeat_count ++; 142 | if(repeat_count >= 20){ 143 | repeat_count = 0; 144 | __repeat_state = repeat_key_rate; 145 | } 146 | break; 147 | case repeat_key_rate: 148 | repeat_count ++; 149 | if ((repeat_count % 2) == 0) { 150 | event_queue_req_t req; 151 | 152 | req.event.type = EVT_KEY_DOWN; 153 | req.key_event.key = map_key(key_value); 154 | printf("key down\n"); 155 | input_dispatch_to_main_loop(main_loop(), &(req)); 156 | } 157 | break; 158 | case repeat_key_released: 159 | break; 160 | } 161 | return; 162 | } 163 | 164 | lcd_wayland_t* lcd_wayland_create(int w, int h) { 165 | lw = calloc(1, sizeof(lcd_wayland_t)); 166 | if (lw && setup_wayland(&lw->objs, FULLSCREEN) != SETUP_OK) { 167 | destroy_wayland_data(&lw->objs); 168 | return NULL; 169 | } 170 | 171 | lw->objs.inputs.keyboard.keyboard_dispatch = key_input_dispatch; 172 | lw->objs.inputs.mouse.pointer_dispatch = mouse_point_dispatch; 173 | lw->objs.inputs.touch.pointer_dispatch = mouse_point_dispatch; 174 | 175 | wayland_data_t* objs = &lw->objs; 176 | wayland_output_t* out = container_of(objs->monitors->next, 177 | wayland_output_t, 178 | link); 179 | lw->objs.width = w; 180 | lw->objs.height = h; 181 | 182 | if(out->info.transform == WL_OUTPUT_TRANSFORM_90 || 183 | out->info.transform == WL_OUTPUT_TRANSFORM_270) { 184 | lw->objs.height = w; 185 | lw->objs.width = h; 186 | } 187 | 188 | atexit(on_app_exit); 189 | 190 | return lw; 191 | } 192 | 193 | 194 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/lcd_wayland.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_wayland.h 3 | * Author: AWTK Develop Team 4 | * Brief: lcd wayland 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #ifndef UI_AWTK_WAYLAND_LCD_WAYLAND_H 23 | #define UI_AWTK_WAYLAND_LCD_WAYLAND_H 24 | 25 | #include "wayland_tools.h" 26 | #include "tkc/mem.h" 27 | #include "base/lcd.h" 28 | 29 | typedef struct _lcd_wayland_t{ 30 | wayland_data_t objs; 31 | void *impl_data; 32 | } lcd_wayland_t; 33 | 34 | lcd_wayland_t* lcd_wayland_create(int w, int h); 35 | void kb_repeat(void); 36 | 37 | #endif /* UI_AWTK_WAYLAND_LCD_WAYLAND_H */ 38 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/main_loop_wayland.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: main_loop_wayland.c 3 | * Author: AWTK Develop Team 4 | * Brief: main loop for wayland 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #include 23 | #include "GLES2/gl2.h" 24 | #include "GLES2/gl2ext.h" 25 | #include "EGL/egl.h" 26 | #include "main_loop/main_loop_simple.h" 27 | #include "native_window/native_window_fb_gl.h" 28 | #include "tkc/thread.h" 29 | 30 | #include "lcd_wayland.h" 31 | 32 | static EGLint numconfigs; 33 | static EGLDisplay egldisplay; 34 | static EGLConfig EglConfig; 35 | static EGLSurface eglsurface; 36 | static EGLContext EglContext; 37 | static EGLNativeWindowType eglNativeWindow; 38 | static EGLNativeDisplayType eglNativeDisplayType; 39 | static lcd_wayland_t *lw; 40 | 41 | static void *wayland_run(void* ctx); 42 | 43 | static ret_t main_loop_linux_destroy(main_loop_t* l) { 44 | main_loop_simple_t* loop = (main_loop_simple_t*)l; 45 | 46 | main_loop_simple_reset(loop); 47 | 48 | return RET_OK; 49 | } 50 | 51 | void Init_GLES(lcd_wayland_t *lw) { 52 | static const EGLint ContextAttributes[] = { 53 | EGL_CONTEXT_CLIENT_VERSION, 2, 54 | EGL_NONE 55 | }; 56 | static const EGLint s_configAttribs[] = { 57 | EGL_RED_SIZE, 1, 58 | EGL_GREEN_SIZE, 1, 59 | EGL_BLUE_SIZE, 1, 60 | EGL_ALPHA_SIZE, 1, 61 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 62 | EGL_NONE 63 | }; 64 | 65 | eglNativeDisplayType = (EGLNativeDisplayType)lw->objs.display; // wl_display * 66 | egldisplay = eglGetDisplay(eglNativeDisplayType); 67 | eglInitialize(egldisplay, NULL, NULL); 68 | assert(eglGetError() == EGL_SUCCESS); 69 | eglBindAPI(EGL_OPENGL_ES_API); 70 | 71 | EGLint ConfigCount; 72 | EGLint ConfigNumberOfFrameBufferConfigurations; 73 | EGLint ConfigValue; 74 | 75 | eglGetConfigs(egldisplay, 0, 0, &ConfigCount); 76 | EGLConfig* EglAllConfigs = calloc(ConfigCount, sizeof(*EglAllConfigs)); 77 | eglChooseConfig(egldisplay, s_configAttribs, EglAllConfigs, 78 | ConfigCount, &ConfigNumberOfFrameBufferConfigurations); 79 | for (int i = 0; i < ConfigNumberOfFrameBufferConfigurations; ++i) { 80 | eglGetConfigAttrib(egldisplay, EglAllConfigs[i], EGL_BUFFER_SIZE, &ConfigValue); 81 | if (ConfigValue == 32) { // NOTE(Felix): Magic value from weston example 82 | EglConfig = EglAllConfigs[i]; 83 | break; 84 | } 85 | } 86 | free(EglAllConfigs); 87 | EglContext = eglCreateContext(egldisplay, EglConfig, EGL_NO_CONTEXT, ContextAttributes); 88 | 89 | eglNativeWindow = (EGLNativeWindowType)wl_egl_window_create(lw->objs.surface, lw->objs.width, lw->objs.height); 90 | assert(eglNativeWindow); 91 | 92 | eglsurface = eglCreateWindowSurface(egldisplay, EglConfig, eglNativeWindow, NULL); 93 | assert(eglGetError() == EGL_SUCCESS); 94 | 95 | eglMakeCurrent(egldisplay, eglsurface, eglsurface, EglContext); 96 | assert(eglGetError() == EGL_SUCCESS); 97 | 98 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 99 | 100 | glDisable(GL_DEPTH_TEST); 101 | glDisable(GL_SCISSOR_TEST); 102 | 103 | eglSwapInterval(egldisplay, 60); 104 | assert(eglGetError() == EGL_SUCCESS); 105 | 106 | } 107 | 108 | static ret_t gles_swap_buffer(native_window_t* win) { 109 | eglSwapBuffers(egldisplay, eglsurface); 110 | return RET_OK; 111 | } 112 | 113 | static ret_t gles_make_current(native_window_t* win) { 114 | EGLint width = 0; 115 | EGLint height = 0; 116 | eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &width); 117 | eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &height); 118 | 119 | eglMakeCurrent(egldisplay, eglsurface, eglsurface, EglContext); 120 | assert(eglGetError() == EGL_SUCCESS); 121 | 122 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 123 | glViewport(0, 0, width, height); 124 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f ); 125 | 126 | return RET_OK; 127 | } 128 | 129 | static ret_t gles_destroy(native_window_t* win) { 130 | eglDestroyContext(egldisplay, EglContext); 131 | eglDestroySurface(egldisplay, eglsurface); 132 | eglTerminate(egldisplay); 133 | if (lw) { 134 | destroy_wayland_data (&lw->objs); 135 | } 136 | } 137 | 138 | main_loop_t* main_loop_init(int w, int h) { 139 | lw = lcd_wayland_create(w, h); 140 | 141 | return_value_if_fail(lw != NULL, NULL); 142 | 143 | Init_GLES(lw); 144 | 145 | eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &w); 146 | eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &h); 147 | 148 | native_window_t* win = native_window_fb_gl_init(w, h, 1.0); 149 | 150 | native_window_fb_gl_set_swap_buffer_func(win, gles_swap_buffer); 151 | native_window_fb_gl_set_make_current_func(win, gles_make_current); 152 | native_window_fb_gl_set_destroy_func(win, gles_destroy); 153 | 154 | main_loop_simple_t *loop = main_loop_simple_init(w, h, NULL, NULL); 155 | 156 | loop->base.destroy = main_loop_linux_destroy; 157 | 158 | tk_thread_t* thread = tk_thread_create(wayland_run, lw); 159 | if (thread != NULL) { 160 | tk_thread_start(thread); 161 | } 162 | 163 | return (main_loop_t*)loop; 164 | } 165 | 166 | static void PlatformPollEvents(wayland_data_t* objs) { 167 | struct wl_display* display = objs->display; 168 | struct pollfd fds[] = { 169 | { wl_display_get_fd(display), POLLIN }, 170 | }; 171 | 172 | while (wl_display_prepare_read(display) != 0) { 173 | wl_display_dispatch_pending(display); 174 | } 175 | 176 | wl_display_flush(display); 177 | 178 | if (poll(fds, 1, -1) > 0) { 179 | wl_display_read_events(display); 180 | wl_display_dispatch_pending(display); 181 | } else { 182 | wl_display_cancel_read(display); 183 | } 184 | kb_repeat(); 185 | } 186 | 187 | static void* wayland_run(void* ctx) { 188 | lcd_wayland_t* lw = (lcd_wayland_t*)ctx; 189 | 190 | while(1) { 191 | PlatformPollEvents(&lw->objs); 192 | } 193 | } 194 | 195 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/wayland_input_devices.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_input_devices.c 3 | * Author: AWTK Develop Team 4 | * Brief: wayland input devices 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #include "wayland_tools.h" 23 | 24 | #define POINTER_BUTTON_STATE_MOTION -1 25 | 26 | static void keymap_format_cb(void* data, struct wl_keyboard* keyboard, uint32_t format, 27 | int32_t fd, uint32_t keymap_size) { 28 | wayland_keyboard_t* kbd = data; 29 | char* str = mmap(NULL, keymap_size, PROT_READ, MAP_SHARED, fd, 0); 30 | xkb_keymap_unref(kbd->map); 31 | kbd->map = xkb_keymap_new_from_string(kbd->ctx, str, XKB_KEYMAP_FORMAT_TEXT_V1, 32 | XKB_KEYMAP_COMPILE_NO_FLAGS); 33 | munmap(str, keymap_size); 34 | close(fd); 35 | xkb_state_unref(kbd->kb_state); 36 | kbd->kb_state = xkb_state_new(kbd->map); 37 | } 38 | 39 | static void key_cb(void* data, struct wl_keyboard* keyboard, uint32_t serial, 40 | uint32_t time, uint32_t key, uint32_t state) { 41 | (void) keyboard; 42 | (void) serial; 43 | (void) time; 44 | wayland_keyboard_t* keydata = data; 45 | if (keydata->keyboard_dispatch) { 46 | keydata->keyboard_dispatch(state, key); 47 | } 48 | } 49 | 50 | static void _keyboard_repeat_info(void* data, struct wl_keyboard* keyboard, 51 | int32_t rate, int32_t delay) { 52 | printf("repeat_info: rate %d, delay %d\n", rate, delay); 53 | } 54 | 55 | const struct wl_keyboard_listener xkb_keyboard_listener = { 56 | keymap_format_cb, 57 | do_nothing, 58 | do_nothing, 59 | key_cb, 60 | do_nothing, 61 | _keyboard_repeat_info 62 | }; 63 | 64 | static void motion_pointer_cb(void* data, struct wl_pointer* pointer, uint32_t time, 65 | wl_fixed_t surface_x, wl_fixed_t surface_y) { 66 | input_bundle_t* input = data; 67 | if (input->mouse.pointer_dispatch) { 68 | input->mouse.pointer_dispatch(POINTER_BUTTON_STATE_MOTION, 0, 69 | wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); 70 | } 71 | } 72 | 73 | static void button_pointer_cb(void* data, struct wl_pointer* pointer, uint32_t serial, 74 | uint32_t time, uint32_t button, uint32_t state) { 75 | input_bundle_t* input = data; 76 | if (input->mouse.pointer_dispatch) { 77 | input->mouse.pointer_dispatch(state, button, -1, -1); 78 | } 79 | } 80 | 81 | static void enter_pointer_cb(void* data, struct wl_pointer* wl_pointer, uint32_t serial, 82 | struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { 83 | input_bundle_t* inputs = data; 84 | struct wl_cursor* default_cursor = wl_cursor_theme_get_cursor(inputs->mouse.cursor_theme, "left_ptr"); 85 | struct wl_cursor_image* image = default_cursor->images[0]; 86 | struct wl_buffer* buffer = wl_cursor_image_get_buffer(image); 87 | wl_pointer_set_cursor(inputs->mouse.pointer, 1, inputs->mouse.point_surface, 0, 0); 88 | wl_surface_attach(inputs->mouse.point_surface, buffer, 0, 0); 89 | wl_surface_damage(inputs->mouse.point_surface, 0, 0, image->width, image->height); 90 | wl_surface_commit(inputs->mouse.point_surface); 91 | } 92 | 93 | const struct wl_pointer_listener pointer_listener = { 94 | enter_pointer_cb, 95 | do_nothing, 96 | motion_pointer_cb, 97 | button_pointer_cb, 98 | do_nothing, 99 | do_nothing, 100 | do_nothing, 101 | do_nothing, 102 | do_nothing 103 | }; 104 | 105 | static void touch_down_cb(void* data, struct wl_touch* wl_touch, uint32_t serial, uint32_t time, 106 | struct wl_surface* surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { 107 | wayland_touch_t* point = data; 108 | if (point->pointer_dispatch) { 109 | point->pointer_dispatch(WL_POINTER_BUTTON_STATE_PRESSED, BTN_LEFT, 110 | wl_fixed_to_int(x), wl_fixed_to_int(y)); 111 | } 112 | } 113 | 114 | static void touch_up_cb(void* data, struct wl_touch* wl_touch, 115 | uint32_t serial, uint32_t time, int32_t id) { 116 | wayland_touch_t* point = data; 117 | if (point->pointer_dispatch) { 118 | point->pointer_dispatch(WL_POINTER_BUTTON_STATE_RELEASED, BTN_LEFT, -1, -1); 119 | } 120 | } 121 | 122 | static void touch_motion_cb(void* data, struct wl_touch* wl_touch, uint32_t time, 123 | int32_t id, wl_fixed_t x, wl_fixed_t y) { 124 | wayland_touch_t* point = data; 125 | if (point->pointer_dispatch) { 126 | point->pointer_dispatch(POINTER_BUTTON_STATE_MOTION, 0, 127 | wl_fixed_to_int(x), wl_fixed_to_int(y)); 128 | } 129 | } 130 | 131 | const struct wl_touch_listener touch_listerner = { 132 | touch_down_cb, 133 | touch_up_cb, 134 | touch_motion_cb, 135 | do_nothing, 136 | do_nothing, 137 | do_nothing, 138 | do_nothing 139 | }; 140 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/wayland_keyboard.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_keyboard.c 3 | * Author: AWTK Develop Team 4 | * Brief: wayland key map 5 | * 6 | * Copyright (c) 2018 - 2018 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "tkc/mem.h" 27 | #include "base/keys.h" 28 | #include "tkc/thread.h" 29 | 30 | #ifndef EV_SYN 31 | #define EV_SYN 0x00 32 | #endif 33 | 34 | static const int32_t s_key_map[0x100] = {[KEY_1] = TK_KEY_1, 35 | [KEY_2] = TK_KEY_2, 36 | [KEY_3] = TK_KEY_3, 37 | [KEY_4] = TK_KEY_4, 38 | [KEY_5] = TK_KEY_5, 39 | [KEY_6] = TK_KEY_6, 40 | [KEY_7] = TK_KEY_7, 41 | [KEY_8] = TK_KEY_8, 42 | [KEY_9] = TK_KEY_9, 43 | [KEY_0] = TK_KEY_0, 44 | [KEY_A] = TK_KEY_a, 45 | [KEY_B] = TK_KEY_b, 46 | [KEY_C] = TK_KEY_c, 47 | [KEY_D] = TK_KEY_d, 48 | [KEY_E] = TK_KEY_e, 49 | [KEY_F] = TK_KEY_f, 50 | [KEY_G] = TK_KEY_g, 51 | [KEY_H] = TK_KEY_h, 52 | [KEY_I] = TK_KEY_i, 53 | [KEY_J] = TK_KEY_j, 54 | [KEY_K] = TK_KEY_k, 55 | [KEY_L] = TK_KEY_l, 56 | [KEY_M] = TK_KEY_m, 57 | [KEY_N] = TK_KEY_n, 58 | [KEY_O] = TK_KEY_o, 59 | [KEY_P] = TK_KEY_p, 60 | [KEY_Q] = TK_KEY_q, 61 | [KEY_R] = TK_KEY_r, 62 | [KEY_S] = TK_KEY_s, 63 | [KEY_T] = TK_KEY_t, 64 | [KEY_U] = TK_KEY_u, 65 | [KEY_V] = TK_KEY_v, 66 | [KEY_W] = TK_KEY_w, 67 | [KEY_X] = TK_KEY_x, 68 | [KEY_Y] = TK_KEY_y, 69 | [KEY_Z] = TK_KEY_z, 70 | [KEY_RIGHTCTRL] = TK_KEY_RCTRL, 71 | [KEY_RIGHTALT] = TK_KEY_RALT, 72 | [KEY_HOME] = TK_KEY_HOME, 73 | [KEY_UP] = TK_KEY_UP, 74 | [KEY_PAGEUP] = TK_KEY_PAGEUP, 75 | [KEY_LEFT] = TK_KEY_LEFT, 76 | [KEY_RIGHT] = TK_KEY_RIGHT, 77 | [KEY_END] = TK_KEY_END, 78 | [KEY_DOWN] = TK_KEY_DOWN, 79 | [KEY_PAGEDOWN] = TK_KEY_PAGEDOWN, 80 | [KEY_INSERT] = TK_KEY_INSERT, 81 | [KEY_DELETE] = TK_KEY_DELETE, 82 | [KEY_F1] = TK_KEY_F1, 83 | [KEY_F2] = TK_KEY_F2, 84 | [KEY_F3] = TK_KEY_F3, 85 | [KEY_F4] = TK_KEY_F4, 86 | [KEY_F5] = TK_KEY_F5, 87 | [KEY_F6] = TK_KEY_F6, 88 | [KEY_F7] = TK_KEY_F7, 89 | [KEY_F8] = TK_KEY_F8, 90 | [KEY_F9] = TK_KEY_F9, 91 | [KEY_F10] = TK_KEY_F10, 92 | [KEY_F11] = TK_KEY_F11, 93 | [KEY_F12] = TK_KEY_F12, 94 | [KEY_COMMA] = TK_KEY_COMMA, 95 | [KEY_DOT] = TK_KEY_DOT, 96 | [KEY_SLASH] = TK_KEY_SLASH, 97 | [KEY_RIGHTSHIFT] = TK_KEY_RSHIFT, 98 | [KEY_LEFTALT] = TK_KEY_LALT, 99 | [KEY_SPACE] = TK_KEY_SPACE, 100 | [KEY_CAPSLOCK] = TK_KEY_CAPSLOCK, 101 | [KEY_SEMICOLON] = TK_KEY_SEMICOLON, 102 | [KEY_LEFTSHIFT] = TK_KEY_LSHIFT, 103 | [KEY_BACKSLASH] = TK_KEY_BACKSLASH, 104 | [KEY_LEFTBRACE] = TK_KEY_LEFTBRACE, 105 | [KEY_RIGHTBRACE] = TK_KEY_RIGHTBRACE, 106 | [KEY_ENTER] = TK_KEY_SPACE, 107 | [KEY_LEFTCTRL] = TK_KEY_LCTRL, 108 | [KEY_MINUS] = TK_KEY_MINUS, 109 | [KEY_EQUAL] = TK_KEY_EQUAL, 110 | [KEY_BACKSPACE] = TK_KEY_BACKSPACE, 111 | [KEY_TAB] = TK_KEY_TAB, 112 | [KEY_ESC] = TK_KEY_ESCAPE}; 113 | 114 | int32_t map_key(uint8_t code) { 115 | return s_key_map[code]; 116 | } 117 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/wayland_tools.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_tools.c 3 | * Author: AWTK Develop Team 4 | * Brief: wayland tools 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #include "wayland_tools.h" 23 | 24 | static void output_mode_cb(void* data, struct wl_output* out, uint32_t flags, 25 | int32_t width, int32_t height, int32_t refresh_rate) { 26 | output_info_t* info = data; 27 | if (flags & WL_OUTPUT_MODE_CURRENT) { 28 | info->width = width; 29 | info->height = height; 30 | info->hertz = refresh_rate; 31 | } 32 | } 33 | 34 | static void output_geometry_cb(void* data, struct wl_output* wl_output, 35 | int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, 36 | int32_t subpixel, const char* make, const char* model, 37 | int32_t transform) { 38 | output_info_t* info = data; 39 | info->transform = transform; 40 | } 41 | 42 | static const struct wl_output_listener output_listener = { 43 | output_geometry_cb, 44 | output_mode_cb, 45 | do_nothing, 46 | do_nothing 47 | }; 48 | 49 | static void shell_ping_respond(void* data, struct xdg_wm_base* shell, 50 | uint32_t serial) { 51 | (void) data; 52 | xdg_wm_base_pong(shell, serial); 53 | } 54 | 55 | static const struct xdg_wm_base_listener xdg_shell_listener = { 56 | shell_ping_respond 57 | }; 58 | 59 | static const struct zwp_fullscreen_shell_v1_listener fullscreen_shell_listener = { 60 | do_nothing 61 | }; 62 | 63 | extern const struct wl_keyboard_listener xkb_keyboard_listener; 64 | extern const struct wl_pointer_listener pointer_listener; 65 | extern const struct wl_touch_listener touch_listerner; 66 | 67 | static void calc_capabilities(void* data, struct wl_seat* s, uint32_t cap) { 68 | wayland_data_t* objs = data; 69 | input_bundle_t* inputs = &(objs->inputs); 70 | (void) s; 71 | //Cap is a bitfield. The WL_SEAT_CAPABILITY_XXX enum is a mask 72 | // that selects the corresponding bit. 73 | inputs->seat = s; 74 | if (cap & WL_SEAT_CAPABILITY_KEYBOARD) { 75 | if (inputs->keyboard.kbd == NULL) { 76 | inputs->keyboard.kbd = wl_seat_get_keyboard(s); 77 | wl_keyboard_add_listener(inputs->keyboard.kbd, &xkb_keyboard_listener, 78 | &inputs->keyboard); 79 | } 80 | } 81 | if (cap & WL_SEAT_CAPABILITY_POINTER) { 82 | inputs->mouse.pointer = wl_seat_get_pointer(s); 83 | if (inputs->mouse.pointer) { 84 | inputs->mouse.point_surface = wl_compositor_create_surface(objs->compositor); 85 | wl_pointer_add_listener(inputs->mouse.pointer, &pointer_listener, inputs); 86 | } 87 | } else { 88 | if (inputs->mouse.pointer) { 89 | wl_surface_destroy(inputs->mouse.point_surface); 90 | wl_pointer_release(inputs->mouse.pointer); 91 | inputs->mouse.pointer = NULL; 92 | } 93 | } 94 | if (cap & WL_SEAT_CAPABILITY_TOUCH) { 95 | inputs->touch.pointer = wl_seat_get_touch(s); 96 | if (inputs->touch.pointer) { 97 | wl_touch_add_listener(inputs->touch.pointer, &touch_listerner, &inputs->touch); 98 | } else { 99 | wl_touch_release(inputs->touch.pointer); 100 | } 101 | } 102 | } 103 | 104 | static const struct wl_seat_listener seat_listener = { 105 | calc_capabilities, 106 | do_nothing, 107 | }; 108 | 109 | static void global_registry_handler(void* data, struct wl_registry* registry, uint32_t id, 110 | const char* interface, uint32_t version) { 111 | wayland_data_t* objs = data; 112 | if (strcmp(interface, wl_compositor_interface.name) == 0) { 113 | objs->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4); 114 | objs->surface = wl_compositor_create_surface(objs->compositor); 115 | } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { 116 | objs->xdg_wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); 117 | xdg_wm_base_add_listener(objs->xdg_wm_base, &xdg_shell_listener, NULL); 118 | } else if (strcmp(interface, zwp_fullscreen_shell_v1_interface.name) == 0) { 119 | objs->fullscreen_shell = wl_registry_bind(registry, id, &zwp_fullscreen_shell_v1_interface, 1); 120 | zwp_fullscreen_shell_v1_add_listener(objs->fullscreen_shell, &fullscreen_shell_listener, NULL); 121 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { 122 | objs->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); 123 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { 124 | objs->inputs.seat = wl_registry_bind(registry, id, &wl_seat_interface, 5); 125 | wl_seat_add_listener(objs->inputs.seat, &seat_listener, objs); 126 | } else if (strcmp(interface, wl_output_interface.name) == 0) { 127 | struct wl_output* wl_out = wl_registry_bind(registry, id, &wl_output_interface, 2); 128 | wayland_output_t* ua_out = malloc(sizeof(wayland_output_t)); 129 | ua_out->out = wl_out; 130 | wl_output_add_listener(ua_out->out, &output_listener, &ua_out->info); 131 | wl_list_insert(objs->monitors, &ua_out->link); 132 | } 133 | } 134 | 135 | static const struct wl_registry_listener registry_listener = { 136 | global_registry_handler, 137 | do_nothing, 138 | }; 139 | 140 | static void surface_configure_cb(void* data, struct xdg_surface* surface, 141 | uint32_t serial) { 142 | (void) data; 143 | xdg_surface_ack_configure(surface, serial); 144 | } 145 | 146 | static const struct xdg_surface_listener xdg_surface_listener = { 147 | surface_configure_cb, 148 | }; 149 | 150 | static const struct xdg_toplevel_listener xdg_top_listener = { 151 | do_nothing, 152 | do_nothing 153 | }; 154 | 155 | #define RETURN_WITH(s) {printf("return with " #s "\n");return s;} 156 | 157 | WAYLAND_SETUP_ERR setup_wayland(wayland_data_t* objs, bool_t fullscreen) { 158 | memset(objs, 0, sizeof(wayland_data_t)); 159 | objs->monitors = malloc(sizeof(struct wl_list)); 160 | wl_list_init(objs->monitors); 161 | 162 | memset(&objs->inputs, 0, sizeof(input_bundle_t)); 163 | objs->inputs.keyboard.ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 164 | 165 | objs->display = wl_display_connect(NULL); 166 | if (objs->display == NULL) 167 | RETURN_WITH (NO_WAY_DISP); 168 | 169 | objs->registry = wl_display_get_registry(objs->display); 170 | if (objs->registry == NULL) 171 | RETURN_WITH (NO_REG); 172 | wl_registry_add_listener(objs->registry, ®istry_listener, objs); 173 | wl_display_roundtrip(objs->display); // Wait for registry listener to run 174 | if (objs->compositor == NULL) 175 | RETURN_WITH (NO_COMP); 176 | if (objs->xdg_wm_base == NULL && objs->fullscreen_shell == NULL) 177 | RETURN_WITH (NO_SHELL); 178 | if (objs->inputs.seat == NULL) 179 | RETURN_WITH (NO_SEAT); 180 | if (objs->shm == NULL) 181 | RETURN_WITH (NO_SHM); 182 | objs->inputs.mouse.cursor_theme = wl_cursor_theme_load(NULL, 1, objs->shm); 183 | if (wl_list_empty(objs->monitors)) 184 | RETURN_WITH (NO_MONITORS); 185 | if (objs->surface == NULL) 186 | RETURN_WITH (NO_SURFACE); 187 | 188 | if (objs->xdg_wm_base != NULL) { 189 | objs->xdg_surface = xdg_wm_base_get_xdg_surface(objs->xdg_wm_base, objs->surface); 190 | if (objs->xdg_surface == NULL) 191 | RETURN_WITH (NO_SHELL_SURFACE); 192 | 193 | xdg_surface_add_listener(objs->xdg_surface, &xdg_surface_listener, NULL); 194 | 195 | objs->xdg_toplevel = xdg_surface_get_toplevel(objs->xdg_surface); 196 | if (objs->xdg_toplevel == NULL) 197 | RETURN_WITH (NO_TOPLEVEL); 198 | 199 | if (fullscreen) { 200 | xdg_toplevel_set_minimized(objs->xdg_toplevel); 201 | xdg_toplevel_set_title(objs->xdg_toplevel, "Unknown Animal"); 202 | wl_display_roundtrip(objs->display); 203 | 204 | wayland_output_t* out = container_of(objs->monitors->next, 205 | wayland_output_t, link); 206 | 207 | xdg_toplevel_set_fullscreen(objs->xdg_toplevel, out->out); 208 | xdg_toplevel_add_listener(objs->xdg_toplevel, &xdg_top_listener, NULL); 209 | } 210 | } else if (objs->fullscreen_shell != NULL) { 211 | zwp_fullscreen_shell_v1_present_surface(objs->fullscreen_shell, objs->surface, 212 | ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, NULL); 213 | } 214 | 215 | wl_surface_commit(objs->surface); 216 | 217 | wl_display_roundtrip(objs->display); 218 | 219 | return SETUP_OK; 220 | } 221 | 222 | void destroy_wayland_data(wayland_data_t* objs) { 223 | wayland_output_t* out = NULL; 224 | struct wl_list* head = objs->monitors; 225 | struct wl_list* current = head->next; 226 | 227 | while (current != head) { 228 | struct wl_list* next = current->next; 229 | out = container_of(current, wayland_output_t, link); 230 | wl_output_destroy(out->out); 231 | free(out); 232 | current = next; 233 | } 234 | free(head); 235 | xkb_keymap_unref(objs->inputs.keyboard.map); 236 | xkb_state_unref(objs->inputs.keyboard.kb_state); 237 | xkb_context_unref(objs->inputs.keyboard.ctx); 238 | if (objs->inputs.keyboard.kbd) 239 | wl_keyboard_destroy(objs->inputs.keyboard.kbd); 240 | if (objs->inputs.mouse.pointer) 241 | wl_pointer_destroy(objs->inputs.mouse.pointer); 242 | if (objs->inputs.touch.pointer) 243 | wl_touch_destroy(objs->inputs.touch.pointer); 244 | if (objs->inputs.seat) 245 | wl_seat_destroy(objs->inputs.seat); 246 | if (objs->shm) 247 | wl_shm_destroy(objs->shm); 248 | if (objs->xdg_toplevel) 249 | xdg_toplevel_destroy(objs->xdg_toplevel); 250 | if (objs->xdg_surface) 251 | xdg_surface_destroy(objs->xdg_surface); 252 | if (objs->xdg_wm_base) 253 | xdg_wm_base_destroy(objs->xdg_wm_base); 254 | if (objs->fullscreen_shell) 255 | zwp_fullscreen_shell_v1_destroy(objs->fullscreen_shell); 256 | if (objs->surface) 257 | wl_surface_destroy(objs->surface); 258 | if (objs->compositor) 259 | wl_compositor_destroy(objs->compositor); 260 | if (objs->registry) 261 | wl_registry_destroy(objs->registry); 262 | if (objs->display) 263 | wl_display_disconnect(objs->display); 264 | } 265 | 266 | void ref_display(struct wl_surface* surface, struct wl_buffer* buffer, 267 | int32_t width, int32_t height) { 268 | wl_surface_attach(surface, buffer, 0, 0); 269 | wl_surface_damage(surface, 0, 0, width, height); 270 | wl_surface_commit(surface); 271 | } 272 | -------------------------------------------------------------------------------- /awtk-wayland/egl_for_wayland/wayland_tools.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_tools.h 3 | * Author: AWTK Develop Team 4 | * Brief: wayland tools 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #ifndef WAYLAND_TOOLS_H 23 | #define WAYLAND_TOOLS_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "tkc/types_def.h" 43 | 44 | #include "../protocol/xdg-shell-protocol.h" 45 | #include "../protocol/fullscreen-shell-protocol.h" 46 | 47 | #define container_of(ptr, type, member) ({ \ 48 | const typeof(((type*)0)->member)* __mptr = (ptr); \ 49 | (type*)((char*)__mptr - offsetof(type, member));}) 50 | 51 | static void do_nothing () {} 52 | 53 | typedef void (*pointer_dispatch_t)(int32_t state, int32_t button, int32_t x, int32_t y); 54 | typedef void (*keyboard_dispatch_t)(int32_t state, int32_t key); 55 | 56 | typedef struct _wayland_keyboard_t { 57 | struct wl_keyboard* kbd; 58 | uint32_t buf_size; 59 | int32_t keymap_fd; 60 | struct xkb_context* ctx; 61 | struct xkb_keymap* map; 62 | struct xkb_state* kb_state; 63 | keyboard_dispatch_t keyboard_dispatch; 64 | } wayland_keyboard_t; 65 | 66 | typedef struct _wayland_pointer_t { 67 | struct wl_pointer* pointer; 68 | struct wl_surface* point_surface; 69 | struct wl_cursor_theme* cursor_theme; 70 | pointer_dispatch_t pointer_dispatch; 71 | } wayland_pointer_t; 72 | 73 | typedef struct _wayland_touch_t { 74 | struct wl_touch* pointer; 75 | pointer_dispatch_t pointer_dispatch; 76 | } wayland_touch_t; 77 | 78 | typedef struct _input_bundle_t { 79 | wayland_keyboard_t keyboard; 80 | wayland_pointer_t mouse; 81 | wayland_touch_t touch; 82 | struct wl_seat* seat; 83 | } input_bundle_t; 84 | 85 | typedef struct _wayland_data_t { 86 | int32_t width; 87 | int32_t height; 88 | struct wl_display* display; 89 | struct wl_registry* registry; 90 | struct wl_compositor* compositor; 91 | struct wl_surface* surface; 92 | struct xdg_wm_base* xdg_wm_base; 93 | struct xdg_surface* xdg_surface; 94 | struct xdg_toplevel* xdg_toplevel; 95 | struct zwp_fullscreen_shell_v1* fullscreen_shell; 96 | struct wl_shm* shm; 97 | /* List of outputs */ 98 | struct wl_list* monitors; 99 | input_bundle_t inputs; 100 | } wayland_data_t; 101 | 102 | typedef struct _output_info_t { 103 | int32_t width; 104 | int32_t height; 105 | int32_t hertz; 106 | int32_t transform; 107 | } output_info_t; 108 | 109 | typedef struct _wayland_output_t { 110 | struct wl_output* out; 111 | struct wl_list link; 112 | output_info_t info; 113 | } wayland_output_t; 114 | 115 | typedef enum { 116 | SETUP_OK, 117 | NO_WAY_DISP, 118 | NO_REG, 119 | NO_COMP, 120 | NO_SHELL, 121 | NO_SEAT, 122 | NO_SHM, 123 | NO_MONITORS, 124 | NO_SURFACE, 125 | NO_SHELL_SURFACE, 126 | NO_TOPLEVEL 127 | } WAYLAND_SETUP_ERR; 128 | 129 | WAYLAND_SETUP_ERR setup_wayland(wayland_data_t* objs, bool_t fullscreen); 130 | void destroy_wayland_data(wayland_data_t* objs); 131 | void ref_display(struct wl_surface* surface, struct wl_buffer* buffer, int32_t width, int32_t height); 132 | 133 | #endif /*WAYLAND_TOOLS_H*/ 134 | -------------------------------------------------------------------------------- /awtk-wayland/wayland/input_dispatch.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/awtk-wayland/wayland/input_dispatch.c -------------------------------------------------------------------------------- /awtk-wayland/wayland/lcd_wayland.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_wayland.c 3 | * Author: AWTK Develop Team 4 | * Brief: lcd wayland 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | #include "lcd_wayland.h" 22 | 23 | #include "base/idle.h" 24 | #include "base/timer.h" 25 | #include "base/window_manager.h" 26 | #include "main_loop/main_loop_simple.h" 27 | #include "tkc/thread.h" 28 | #include "base/lcd_fb_dirty_rects.h" 29 | 30 | #ifndef FULLSCREEN 31 | #define FULLSCREEN FALSE 32 | #endif 33 | 34 | enum key_repeat_state { 35 | repeat_key_released = 0, 36 | repeat_key_pressed = 10, 37 | repeat_key_delay, 38 | repeat_key_rate, 39 | }; 40 | 41 | lcd_wayland_t* lw = NULL; 42 | enum key_repeat_state __repeat_state = repeat_key_released; 43 | static int key_value; 44 | extern int32_t map_key(uint8_t code); 45 | 46 | void on_app_exit(void) { 47 | if (lw) { 48 | destroy_wayland_data(&lw->objs); 49 | } 50 | } 51 | 52 | static ret_t wayland_flush(lcd_t* lcd) { 53 | lcd_wayland_t* lw = lcd->impl_data; 54 | ref_display(lw->objs.surface, lw->current->wl_buffer, lcd->w, lcd->h); 55 | wl_display_flush(lw->objs.display); 56 | return RET_OK; 57 | } 58 | 59 | static ret_t wayland_sync(lcd_t* lcd) { 60 | lcd_wayland_t* lw = lcd->impl_data; 61 | buffer_t* buf = lw->impl_data; 62 | ThreadSignal_Wait(&buf->used); 63 | return RET_OK; 64 | } 65 | 66 | static ret_t input_dispatch_to_main_loop(void* ctx, const event_queue_req_t* e) { 67 | main_loop_queue_event((main_loop_t*)ctx, e); 68 | return RET_OK; 69 | } 70 | 71 | static void key_input_dispatch(int32_t state, int32_t key) { 72 | event_queue_req_t req; 73 | 74 | req.event.type = (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? EVT_KEY_DOWN : EVT_KEY_UP; 75 | req.key_event.key = map_key(key); 76 | 77 | input_dispatch_to_main_loop(main_loop(), &req); 78 | 79 | req.event.type = EVT_NONE; 80 | 81 | if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { 82 | __repeat_state = repeat_key_pressed; 83 | key_value = key; 84 | } else { 85 | __repeat_state = repeat_key_released; 86 | } 87 | } 88 | 89 | static void mouse_point_dispatch(int32_t state, int32_t button, int32_t x, int32_t y) { 90 | event_queue_req_t r; 91 | event_queue_req_t* req = &r; 92 | main_loop_simple_t* l = (main_loop_simple_t*)main_loop(); 93 | static int __x,__y; 94 | 95 | if (x > 0) { 96 | __x = x; 97 | } 98 | 99 | if (y > 0) { 100 | __y = y; 101 | } 102 | 103 | req->pointer_event.x = __x; 104 | req->pointer_event.y = __y; 105 | req->event.time = time_now_ms(); 106 | 107 | if (button == BTN_LEFT) { 108 | req->event.size = sizeof(req->pointer_event); 109 | switch (state) { 110 | case WL_POINTER_BUTTON_STATE_PRESSED: 111 | req->event.type = EVT_POINTER_DOWN; 112 | l->pressed = TRUE; 113 | req->pointer_event.pressed = TRUE; 114 | break; 115 | case WL_POINTER_BUTTON_STATE_RELEASED: 116 | req->event.type = EVT_POINTER_UP; 117 | req->pointer_event.pressed = l->pressed; 118 | l->pressed = FALSE; 119 | break; 120 | } 121 | } else if (button == BTN_RIGHT) { 122 | req->event.size = sizeof(req->pointer_event); 123 | if (state == WL_POINTER_BUTTON_STATE_RELEASED) { 124 | req->event.type = EVT_CONTEXT_MENU; 125 | req->pointer_event.pressed = FALSE; 126 | } 127 | } else if (button == BTN_MIDDLE) { 128 | req->event.size = sizeof(req->key_event); 129 | switch (state) { 130 | case WL_POINTER_BUTTON_STATE_PRESSED: 131 | req->event.type = EVT_KEY_DOWN; 132 | req->key_event.key = TK_KEY_WHEEL; 133 | break; 134 | case WL_POINTER_BUTTON_STATE_RELEASED: 135 | req->event.type = EVT_KEY_UP; 136 | req->key_event.key = TK_KEY_WHEEL; 137 | break; 138 | } 139 | } else { 140 | req->event.size = sizeof(req->pointer_event); 141 | req->event.type = EVT_POINTER_MOVE; 142 | } 143 | 144 | input_dispatch_to_main_loop(main_loop(), req); 145 | } 146 | 147 | static lcd_t* lcd_linux_create_flushable(lcd_wayland_t* lw, int w, int h) { 148 | wayland_data_t* objs = &lw->objs; 149 | wayland_output_t* out = container_of(objs->monitors->next, 150 | wayland_output_t, 151 | link); 152 | size_t width = w; 153 | size_t height = h; 154 | 155 | if(out->info.transform == WL_OUTPUT_TRANSFORM_90 || out->info.transform == WL_OUTPUT_TRANSFORM_270) { 156 | height = w; 157 | width = w; 158 | } 159 | 160 | int line_length = width * 4; 161 | 162 | buffer_t *buffer = wayland_create_double_buffer(objs->shm, width, height); 163 | 164 | uint8_t* online_fb = (void*)buffer->bufs->pixels; 165 | 166 | lw->current = buffer->bufs; 167 | lw->impl_data = buffer; 168 | 169 | lcd_t* lcd = lcd_mem_bgra8888_create_single_fb(width, height, online_fb); 170 | 171 | if(lcd != NULL) { 172 | lcd->impl_data = lw; 173 | lcd->sync = wayland_sync; 174 | lcd->flush = wayland_flush; 175 | lcd_mem_set_line_length(lcd, line_length); 176 | } 177 | 178 | lw->objs.inputs.keyboard.keyboard_dispatch = key_input_dispatch; 179 | lw->objs.inputs.mouse.pointer_dispatch = mouse_point_dispatch; 180 | lw->objs.inputs.touch.pointer_dispatch = mouse_point_dispatch; 181 | 182 | atexit(on_app_exit); 183 | 184 | return lcd; 185 | } 186 | 187 | // 为了实现按下重复发送 修改写法(可能出现抬起后又发送按下的事件) 188 | void kb_repeat(wayland_data_t *objs) { 189 | static uint32_t repeat_count = 0; 190 | switch(__repeat_state){ 191 | case repeat_key_pressed: 192 | repeat_count = 0; 193 | __repeat_state = repeat_key_delay; 194 | break; 195 | case repeat_key_delay: 196 | repeat_count ++; 197 | if(repeat_count >= 20){ 198 | repeat_count = 0; 199 | __repeat_state = repeat_key_rate; 200 | } 201 | break; 202 | case repeat_key_rate: 203 | repeat_count ++; 204 | if((repeat_count % 2) == 0){ 205 | event_queue_req_t req; 206 | 207 | req.event.type = EVT_KEY_DOWN; 208 | req.key_event.key = map_key(key_value); 209 | input_dispatch_to_main_loop(main_loop(), &(req)); 210 | } 211 | break; 212 | default: 213 | case repeat_key_released: 214 | break; 215 | } 216 | } 217 | 218 | lcd_t *lcd_wayland_create(int w, int h) { 219 | lw = calloc(1, sizeof(lcd_wayland_t)); 220 | if (lw && setup_wayland(&lw->objs, FULLSCREEN) != SETUP_OK) { 221 | destroy_wayland_data(&lw->objs); 222 | return NULL; 223 | } 224 | 225 | return lcd_linux_create_flushable(lw, w, h); 226 | } 227 | 228 | 229 | -------------------------------------------------------------------------------- /awtk-wayland/wayland/lcd_wayland.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: lcd_wayland.h 3 | * Author: AWTK Develop Team 4 | * Brief: lcd wayland 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | #ifndef UI_AWTK_WAYLAND_LCD_WAYLAND_H 22 | #define UI_AWTK_WAYLAND_LCD_WAYLAND_H 23 | 24 | #include "pthread_signal.h" 25 | #include "wayland_tools.h" 26 | #include "tkc/mem.h" 27 | #include "base/lcd.h" 28 | #include "lcd/lcd_mem_bgr565.h" 29 | #include "lcd/lcd_mem_rgb565.h" 30 | #include "lcd/lcd_mem_bgra8888.h" 31 | #include "lcd/lcd_mem_rgba8888.h" 32 | 33 | typedef struct _lcd_wayland_t{ 34 | double_buffer_list_t* current; 35 | wayland_data_t objs; 36 | void* impl_data; 37 | } lcd_wayland_t; 38 | 39 | lcd_t* lcd_wayland_create(int w, int h); 40 | void kb_repeat(wayland_data_t* objs); 41 | 42 | #endif /* UI_AWTK_WAYLAND_LCD_WAYLAND_H */ 43 | -------------------------------------------------------------------------------- /awtk-wayland/wayland/main_loop_wayland.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: main_loop_wayland.c 3 | * Author: AWTK Develop Team 4 | * Brief: main loop for wayland 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #include 23 | #include "main_loop/main_loop_simple.h" 24 | #include "tkc/thread.h" 25 | 26 | #include "lcd_wayland.h" 27 | 28 | static void *wayland_run(void* ctx); 29 | 30 | static ret_t main_loop_wayland_destroy(main_loop_t* l) { 31 | main_loop_simple_t* loop = (main_loop_simple_t*)l; 32 | 33 | main_loop_simple_reset(loop); 34 | native_window_raw_deinit(); 35 | 36 | return RET_OK; 37 | } 38 | 39 | main_loop_t* main_loop_init(int w, int h) { 40 | lcd_t* lcd = lcd_wayland_create(w, h); 41 | return_value_if_fail(lcd != NULL, NULL); 42 | 43 | native_window_raw_init(lcd); 44 | main_loop_simple_t* loop = main_loop_simple_init(lcd->w, lcd->h, NULL, NULL); 45 | 46 | loop->base.destroy = main_loop_wayland_destroy; 47 | 48 | tk_thread_t* thread = tk_thread_create(wayland_run, lcd); 49 | if (thread != NULL) { 50 | tk_thread_start(thread); 51 | } 52 | 53 | return (main_loop_t*)loop; 54 | } 55 | 56 | static void PlatformPollEvents(wayland_data_t* objs) { 57 | struct wl_display* display = objs->display; 58 | struct pollfd fds[] = { 59 | { wl_display_get_fd(display), POLLIN }, 60 | }; 61 | 62 | while (wl_display_prepare_read(display) != 0) 63 | wl_display_dispatch_pending(display); 64 | 65 | if (poll(fds, 1, -1) > 0) { 66 | wl_display_read_events(display); 67 | wl_display_dispatch_pending(display); 68 | } else { 69 | wl_display_cancel_read(display); 70 | } 71 | kb_repeat(NULL); 72 | } 73 | 74 | static void* wayland_run(void* ctx) { 75 | lcd_wayland_t* lw = ((lcd_t*)ctx)->impl_data; 76 | 77 | while (1) { 78 | PlatformPollEvents(&lw->objs); 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /awtk-wayland/wayland/pthread_signal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: pthread_signal.h 3 | * Author: AWTK Develop Team 4 | * Brief: thread signal 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #ifndef UI_AWTK_WAYLAND_PTHREAD_SIGNAL_H 23 | #define UI_AWTK_WAYLAND_PTHREAD_SIGNAL_H 24 | 25 | #include 26 | 27 | typedef struct ThreadSignal_T { 28 | pthread_cond_t cond; 29 | pthread_mutex_t mutex; 30 | 31 | pthread_condattr_t cattr; 32 | } ThreadSignal; 33 | 34 | static void ThreadSignal_Init(ThreadSignal *signal) { 35 | pthread_mutex_init(&signal->mutex, NULL); 36 | 37 | pthread_cond_init(&signal->cond, NULL); 38 | } 39 | 40 | static void ThreadSignal_Close(ThreadSignal *signal) { 41 | pthread_mutex_destroy(&signal->mutex); 42 | pthread_cond_destroy(&signal->cond); 43 | } 44 | 45 | static void ThreadSignal_Wait(ThreadSignal *signal) { 46 | pthread_mutex_lock(&signal->mutex); 47 | pthread_cond_wait(&signal->cond, &signal->mutex); 48 | pthread_mutex_unlock(&signal->mutex); 49 | } 50 | 51 | static void ThreadSignal_Signal(ThreadSignal *signal) { 52 | pthread_mutex_lock(&signal->mutex); 53 | pthread_cond_signal(&signal->cond); 54 | pthread_mutex_unlock(&signal->mutex); 55 | } 56 | 57 | #endif /* UI_AWTK_WAYLAND_PTHREAD_SIGNAL_H */ 58 | -------------------------------------------------------------------------------- /awtk-wayland/wayland/wayland_input_devices.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_input_devices.c 3 | * Author: AWTK Develop Team 4 | * Brief: wayland input devices 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | #include "wayland_tools.h" 22 | 23 | #define POINTER_BUTTON_STATE_MOTION -1 24 | 25 | void keymap_format_cb(void* data, struct wl_keyboard* keyboard, uint32_t format, 26 | int32_t fd, uint32_t keymap_size) { 27 | wayland_keyboard_t* kbd = data; 28 | char* str = mmap(NULL, keymap_size, PROT_READ, MAP_SHARED, fd, 0); 29 | xkb_keymap_unref(kbd->map); 30 | kbd->map = xkb_keymap_new_from_string(kbd->ctx, str, XKB_KEYMAP_FORMAT_TEXT_V1, 31 | XKB_KEYMAP_COMPILE_NO_FLAGS); 32 | munmap(str, keymap_size); 33 | close(fd); 34 | xkb_state_unref(kbd->kb_state); 35 | //查看是否有释放new的内存 36 | kbd->kb_state = xkb_state_new(kbd->map); 37 | } 38 | 39 | void key_cb(void *data, struct wl_keyboard* keyboard, uint32_t serial, 40 | uint32_t time, uint32_t key, uint32_t state) { 41 | (void) keyboard; 42 | (void) serial; 43 | (void) time; 44 | wayland_keyboard_t* keydata = data; 45 | if(keydata->keyboard_dispatch){ 46 | keydata->keyboard_dispatch(state, key); 47 | } 48 | } 49 | 50 | static void keyboard_repeat_cb(void *data, struct wl_keyboard *keyboard, 51 | int32_t rate, int32_t delay) { 52 | wayland_keyboard_t* keydata = data; 53 | if (keydata->keyboard_dispatch) { 54 | keydata->keyboard_dispatch(WL_KEYBOARD_KEY_STATE_PRESSED, -1); 55 | } 56 | } 57 | 58 | const struct wl_keyboard_listener xkb_keyboard_listener = { 59 | keymap_format_cb, 60 | do_nothing, 61 | do_nothing, 62 | key_cb, 63 | do_nothing, 64 | keyboard_repeat_cb 65 | }; 66 | 67 | static void motion_pointer_cb(void* data, struct wl_pointer* pointer, uint32_t time, 68 | wl_fixed_t surface_x, wl_fixed_t surface_y) { 69 | wayland_pointer_t* point = data; 70 | if(point->pointer_dispatch){ 71 | point->pointer_dispatch(POINTER_BUTTON_STATE_MOTION, 0, 72 | wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); 73 | } 74 | } 75 | 76 | static void button_pointer_cb(void* data, struct wl_pointer* pointer, uint32_t serial, 77 | uint32_t time, uint32_t button, uint32_t state) { 78 | wayland_pointer_t* point = data; 79 | if (point->pointer_dispatch) { 80 | point->pointer_dispatch(state, button, -1, -1); 81 | } 82 | } 83 | 84 | static void enter_pointer_cb(void* data, struct wl_pointer* wl_pointer, uint32_t serial, 85 | struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { 86 | // printf ("enter_pointer_cb .\n"); 87 | } 88 | 89 | const struct wl_pointer_listener pointer_listener = {enter_pointer_cb, 90 | do_nothing, 91 | motion_pointer_cb, 92 | button_pointer_cb, 93 | do_nothing, 94 | do_nothing, 95 | do_nothing, 96 | do_nothing, 97 | do_nothing 98 | }; 99 | 100 | static void touch_down_cb(void* data, struct wl_touch* wl_touch, uint32_t serial, uint32_t time, 101 | struct wl_surface* surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { 102 | wayland_touch_t* point = data; 103 | if (point->pointer_dispatch) { 104 | point->pointer_dispatch(WL_POINTER_BUTTON_STATE_PRESSED, BTN_LEFT, 105 | wl_fixed_to_int(x), wl_fixed_to_int(y)); 106 | } 107 | } 108 | 109 | static void touch_up_cb(void* data, struct wl_touch* wl_touch, 110 | uint32_t serial, uint32_t time, int32_t id) { 111 | wayland_touch_t* point = data; 112 | if (point->pointer_dispatch) { 113 | point->pointer_dispatch(WL_POINTER_BUTTON_STATE_RELEASED, BTN_LEFT, -1, -1); 114 | } 115 | } 116 | 117 | static void touch_motion_cb(void* data, struct wl_touch* wl_touch, uint32_t time, 118 | int32_t id, wl_fixed_t x, wl_fixed_t y) { 119 | wayland_touch_t* point = data; 120 | if (point->pointer_dispatch) { 121 | point->pointer_dispatch(POINTER_BUTTON_STATE_MOTION, 0, 122 | wl_fixed_to_int(x), wl_fixed_to_int(y)); 123 | } 124 | } 125 | 126 | const struct wl_touch_listener touch_listener = { 127 | touch_down_cb, 128 | touch_up_cb, 129 | touch_motion_cb, 130 | do_nothing, 131 | do_nothing, 132 | do_nothing, 133 | do_nothing 134 | }; -------------------------------------------------------------------------------- /awtk-wayland/wayland/wayland_keyboard.c: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_keyboard.c 3 | * Author: AWTK Develop Team 4 | * Brief: wayland map key 5 | * 6 | * Copyright (c) 2018 - 2018 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2018-09-07 Li XianJing created 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "tkc/mem.h" 27 | #include "base/keys.h" 28 | #include "tkc/thread.h" 29 | 30 | #ifndef EV_SYN 31 | #define EV_SYN 0x00 32 | #endif 33 | 34 | 35 | static const int32_t s_key_map[0x100] = {[KEY_1] = TK_KEY_1, 36 | [KEY_2] = TK_KEY_2, 37 | [KEY_3] = TK_KEY_3, 38 | [KEY_4] = TK_KEY_4, 39 | [KEY_5] = TK_KEY_5, 40 | [KEY_6] = TK_KEY_6, 41 | [KEY_7] = TK_KEY_7, 42 | [KEY_8] = TK_KEY_8, 43 | [KEY_9] = TK_KEY_9, 44 | [KEY_0] = TK_KEY_0, 45 | [KEY_A] = TK_KEY_a, 46 | [KEY_B] = TK_KEY_b, 47 | [KEY_C] = TK_KEY_c, 48 | [KEY_D] = TK_KEY_d, 49 | [KEY_E] = TK_KEY_e, 50 | [KEY_F] = TK_KEY_f, 51 | [KEY_G] = TK_KEY_g, 52 | [KEY_H] = TK_KEY_h, 53 | [KEY_I] = TK_KEY_i, 54 | [KEY_J] = TK_KEY_j, 55 | [KEY_K] = TK_KEY_k, 56 | [KEY_L] = TK_KEY_l, 57 | [KEY_M] = TK_KEY_m, 58 | [KEY_N] = TK_KEY_n, 59 | [KEY_O] = TK_KEY_o, 60 | [KEY_P] = TK_KEY_p, 61 | [KEY_Q] = TK_KEY_q, 62 | [KEY_R] = TK_KEY_r, 63 | [KEY_S] = TK_KEY_s, 64 | [KEY_T] = TK_KEY_t, 65 | [KEY_U] = TK_KEY_u, 66 | [KEY_V] = TK_KEY_v, 67 | [KEY_W] = TK_KEY_w, 68 | [KEY_X] = TK_KEY_x, 69 | [KEY_Y] = TK_KEY_y, 70 | [KEY_Z] = TK_KEY_z, 71 | [KEY_RIGHTCTRL] = TK_KEY_RCTRL, 72 | [KEY_RIGHTALT] = TK_KEY_RALT, 73 | [KEY_HOME] = TK_KEY_HOME, 74 | [KEY_UP] = TK_KEY_UP, 75 | [KEY_PAGEUP] = TK_KEY_PAGEUP, 76 | [KEY_LEFT] = TK_KEY_LEFT, 77 | [KEY_RIGHT] = TK_KEY_RIGHT, 78 | [KEY_END] = TK_KEY_END, 79 | [KEY_DOWN] = TK_KEY_DOWN, 80 | [KEY_PAGEDOWN] = TK_KEY_PAGEDOWN, 81 | [KEY_INSERT] = TK_KEY_INSERT, 82 | [KEY_DELETE] = TK_KEY_DELETE, 83 | [KEY_F1] = TK_KEY_F1, 84 | [KEY_F2] = TK_KEY_F2, 85 | [KEY_F3] = TK_KEY_F3, 86 | [KEY_F4] = TK_KEY_F4, 87 | [KEY_F5] = TK_KEY_F5, 88 | [KEY_F6] = TK_KEY_F6, 89 | [KEY_F7] = TK_KEY_F7, 90 | [KEY_F8] = TK_KEY_F8, 91 | [KEY_F9] = TK_KEY_F9, 92 | [KEY_F10] = TK_KEY_F10, 93 | [KEY_F11] = TK_KEY_F11, 94 | [KEY_F12] = TK_KEY_F12, 95 | [KEY_COMMA] = TK_KEY_COMMA, 96 | [KEY_DOT] = TK_KEY_DOT, 97 | [KEY_SLASH] = TK_KEY_SLASH, 98 | [KEY_RIGHTSHIFT] = TK_KEY_RSHIFT, 99 | [KEY_LEFTALT] = TK_KEY_LALT, 100 | [KEY_SPACE] = TK_KEY_SPACE, 101 | [KEY_CAPSLOCK] = TK_KEY_CAPSLOCK, 102 | [KEY_SEMICOLON] = TK_KEY_SEMICOLON, 103 | [KEY_LEFTSHIFT] = TK_KEY_LSHIFT, 104 | [KEY_BACKSLASH] = TK_KEY_BACKSLASH, 105 | [KEY_LEFTBRACE] = TK_KEY_LEFTBRACE, 106 | [KEY_RIGHTBRACE] = TK_KEY_RIGHTBRACE, 107 | [KEY_ENTER] = TK_KEY_SPACE, 108 | [KEY_LEFTCTRL] = TK_KEY_LCTRL, 109 | [KEY_MINUS] = TK_KEY_MINUS, 110 | [KEY_EQUAL] = TK_KEY_EQUAL, 111 | [KEY_BACKSPACE] = TK_KEY_BACKSPACE, 112 | [KEY_TAB] = TK_KEY_TAB, 113 | [KEY_ESC] = TK_KEY_ESCAPE}; 114 | 115 | int32_t map_key(uint8_t code) { 116 | return s_key_map[code]; 117 | } 118 | -------------------------------------------------------------------------------- /awtk-wayland/wayland/wayland_tools.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File: wayland_tools.h 3 | * Author: AWTK Develop Team 4 | * Brief: wayland tools 5 | * 6 | * Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * License file for more details. 12 | * 13 | */ 14 | 15 | /** 16 | * History: 17 | * ================================================================ 18 | * 2024-07-17 Yang Zewu created 19 | * 20 | */ 21 | 22 | #ifndef WAYLAND_TOOLS_H 23 | #define WAYLAND_TOOLS_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "tkc/types_def.h" 42 | 43 | #include "pthread_signal.h" 44 | #include "../protocol/xdg-shell-protocol.h" 45 | #include "../protocol/fullscreen-shell-protocol.h" 46 | 47 | #define container_of(ptr, type, member) ({ \ 48 | const typeof(((type*)0)->member)* __mptr = (ptr); \ 49 | (type*)((char*)__mptr - offsetof(type, member));}) 50 | 51 | static void do_nothing () {} 52 | 53 | typedef void (*pointer_dispatch_t)(int32_t state, int32_t button, int32_t x, int32_t y); 54 | typedef void (*keyboard_dispatch_t)(int32_t state, int32_t key); 55 | 56 | typedef struct _wayland_keyboard_t { 57 | struct wl_keyboard* kbd; 58 | uint32_t buf_size; 59 | int32_t keymap_fd; 60 | struct xkb_context* ctx; 61 | struct xkb_keymap* map; 62 | struct xkb_state* kb_state; 63 | keyboard_dispatch_t keyboard_dispatch; 64 | } wayland_keyboard_t; 65 | 66 | typedef struct _wayland_pointer_t { 67 | struct wl_pointer* pointer; 68 | struct wl_surface* point_surface; 69 | struct wl_cursor_theme* cursor_theme; 70 | pointer_dispatch_t pointer_dispatch; 71 | } wayland_pointer_t; 72 | 73 | typedef struct _wayland_touch_t { 74 | struct wl_touch* touch; 75 | pointer_dispatch_t pointer_dispatch; 76 | } wayland_touch_t; 77 | 78 | typedef struct _input_bundle_t { 79 | wayland_keyboard_t keyboard; 80 | wayland_pointer_t mouse; 81 | wayland_touch_t touch; 82 | struct wl_seat* seat; 83 | } input_bundle_t; 84 | 85 | typedef struct _wayland_data_t { 86 | struct wl_display* display; 87 | struct wl_registry* registry; 88 | struct wl_compositor* compositor; 89 | struct wl_surface* surface; 90 | struct xdg_wm_base* xdg_wm_base; 91 | struct xdg_surface* xdg_surface; 92 | struct xdg_toplevel* xdg_toplevel; 93 | struct zwp_fullscreen_shell_v1* fullscreen_shell; 94 | struct wl_shm* shm; 95 | /* List of outputs */ 96 | struct wl_list* monitors; 97 | input_bundle_t inputs; 98 | } wayland_data_t; 99 | 100 | typedef struct _output_info_t { 101 | int32_t width; 102 | int32_t height; 103 | int32_t hertz; 104 | int32_t transform; 105 | } output_info_t; 106 | 107 | typedef struct _wayland_output_t { 108 | struct wl_output* out; 109 | struct wl_list link; 110 | output_info_t info; 111 | } wayland_output_t; 112 | 113 | typedef struct _double_buffer_list_t { 114 | struct wl_buffer* wl_buffer; 115 | uint32_t* pixels; 116 | struct double_buffer_list* next; 117 | } double_buffer_list_t; 118 | 119 | typedef struct _buffer_t { 120 | ThreadSignal used; 121 | uint32_t width; 122 | uint32_t height; 123 | double_buffer_list_t* bufs; 124 | } buffer_t; 125 | 126 | typedef enum { 127 | SETUP_OK, 128 | NO_WAY_DISP, 129 | NO_REG, 130 | NO_COMP, 131 | NO_SHELL, 132 | NO_SEAT, 133 | NO_SHM, 134 | NO_MONITORS, 135 | NO_SURFACE, 136 | NO_SHELL_SURFACE, 137 | NO_TOPLEVEL 138 | } WAYLAND_SETUP_ERR; 139 | 140 | WAYLAND_SETUP_ERR setup_wayland(wayland_data_t* objs, bool_t fullscreen); 141 | void destroy_wayland_data(wayland_data_t* objs); 142 | void ref_display(struct wl_surface* surface, struct wl_buffer* buffer, int width, int height); 143 | buffer_t* wayland_create_double_buffer(struct wl_shm* shm, int width, int height); 144 | 145 | #endif /* WAYLAND_TOOLS_H */ 146 | -------------------------------------------------------------------------------- /config/devices.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "/dev/fb0" : { 3 | "type" : "fb" 4 | }, 5 | "/dev/dri/card0" : { 6 | "type" : "drm" 7 | }, 8 | "/dev/input/event0" : { 9 | "type" : "ts" 10 | }, 11 | "/dev/input/event1" : { 12 | "type" : "input" 13 | }, 14 | "/dev/input/event2" : { 15 | "type" : "mouse" 16 | } 17 | } -------------------------------------------------------------------------------- /config/readme.md: -------------------------------------------------------------------------------- 1 | # 设备配置文件说明 2 | 3 | 1. 复制模板文件 devices.json.in 并改名为 devices.json,该配置文件会随后续打包命令一起部署。 4 | 5 | (如果运行时没有 devices.json 文件则使用 main_loop_linux.c 默认设备宏配置) 6 | 7 | 2. 编辑 devices.json 指定输入设备的文件路径及对应的设备类型。 8 | 9 | ```json 10 | { 11 | "/dev/fb0" : { 12 | "type" : "fb" 13 | }, 14 | "/dev/dri/card0" : { 15 | "type" : "drm" 16 | }, 17 | "/dev/input/event0" : { 18 | "type" : "ts" 19 | }, 20 | "/dev/input/event1" : { 21 | "type" : "input" 22 | }, 23 | "/dev/input/mouse0" : { 24 | "type" : "mouse" 25 | } 26 | } 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/allwinner_linux_notes.md: -------------------------------------------------------------------------------- 1 | # 在全智 T113-S3 开发板上运行 AWTK 2 | 3 | ## 1. 准备工作 4 | 5 | > 如果某些步骤已经完成,请跳过。 6 | 7 | ## 1.1 安装 Ubuntu 22 虚拟机 8 | 9 | ## 1.2 安装 sshd 服务并启动 10 | 11 | ```bash 12 | sudo apt-get install openssh-server 13 | sudo systemctl start sshd 14 | ``` 15 | 16 | ## 1.3 安装 awtk 需要的编译环境 17 | 18 | ```bash 19 | sudo apt-get install gcc g++ scons libsndio-dev libgtk-3-dev libglu1-mesa libglu1-mesa-dev libgl1-mesa-glx libgl1-mesa-dev libasound2-dev libibus-1.0-dev fcitx-libs-dev git vim clang-format libharfbuzz-dev nodejs libreadline-dev 20 | ``` 21 | 22 | ## 1.4 安装交叉编译工具链 23 | 24 | ```bash 25 | sudo apt-get install g++-arm-linux-gnueabi 26 | ``` 27 | 28 | ## 1.5 下载 awtk/awtk-linux-fb 源码 29 | 30 | * 创建工作目录 31 | 32 | ```bash 33 | mkdir -p ~/work/awtk-root 34 | cd ~/work/awtk-root 35 | ``` 36 | 37 | * 下载 awtk 源码 38 | 39 | ```bash 40 | git clone https://github.com/zlgopen/awtk 41 | ``` 42 | 43 | * 下载 awtk-linux-fb 源码 44 | 45 | ```bash 46 | git clone https://github.com/zlgopen/awtk-linux-fb 47 | ``` 48 | 49 | ## 2. 构建 rootfs 50 | 51 | > 因为笔者用的 MacPro M2,上面安装的是 Ubuntu 22 虚拟机,由于是 arm64 的 CPU,官方的工具链运行不了,而 Ubuntu 上工具链编译的程序,在板子自带的系统上运行不了,所以只能自己编译 rootfs。 52 | > 其它系统,如果不需要请跳过。 53 | 54 | ### 2.1 下载 busybox 源码 55 | 56 | ```bash 57 | mkdir -p ~/work/awtk-root/rootfs 58 | cd ~/work/awtk-root/rootfs 59 | wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 60 | tar -xvf busybox-1.36.1.tar.bz2 61 | ``` 62 | 63 | ### 2.2 编译 busybox 64 | 65 | ```bash 66 | cd busybox-1.36.1 67 | make defconfig 68 | make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm 69 | make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm install CONFIG_PREFIX=~/work/awtk-root/rootfs/rootfs 70 | ``` 71 | 72 | * 拷贝库文件 73 | 74 | ```bash 75 | cd ~/work/awtk-root/rootfs/rootfs/ 76 | cp -arf /usr/arm-linux-gnueabi/lib . 77 | rm -f lib/libasan.so.6* lib/*.a lib/*.o 78 | ``` 79 | 80 | * 创建必要的文件和目录 81 | 82 | ```bash 83 | mkdir -p proc dev sys var tmp run etc 84 | ``` 85 | 86 | * 创建 etc/fstab 文件,其内容如下: 87 | 88 | ```bash 89 | proc /proc proc defaults 0 0 90 | sysfs /sys sysfs defaults 0 0 91 | tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0 92 | tmpfs /tmp tmpfs defaults 0 0 93 | devtmpfs /dev devtmpfs defaults 0 0 94 | ``` 95 | 96 | * 创建 rootfs 压缩文件包 97 | 98 | ``` 99 | cd .. 100 | tar czf rootfs.tar.gz rootfs 101 | ``` 102 | 103 | * 启动 http 服务 104 | 105 | > 打开一个新的终端 106 | 107 | ```bash 108 | ~/work/awtk-root 109 | python3 -m http.server 8080 --directory . 110 | ``` 111 | 112 | 113 | ## 3. 编译 awtk-linux-fb 114 | 115 | ### 3.1 编译 116 | 117 | ```bash 118 | cd ~/work/awtk-root/awtk-linux-fb 119 | scons TOOLS_PREFIX=arm-linux-gnueabi- 120 | ``` 121 | 122 | ### 3.2 生成压缩包 123 | 124 | ```bash 125 | ./release.sh 126 | ``` 127 | 128 | * 创建设备配置文件:release/config/devices.json 其内容如下: 129 | 130 | ```json 131 | { 132 | "/dev/fb0" : { 133 | "type" : "fb" 134 | }, 135 | "/dev/input/event2" : { 136 | "type" : "input" 137 | } 138 | } 139 | ``` 140 | 141 | * 重新生成压缩包 142 | 143 | ``` 144 | tar czf release.tar.gz release 145 | ``` 146 | 147 | ## 4. 下载 rootfs.tar.gz 和 release.tar.gz 到开发板 148 | 149 | ### 4.1 启动网络 150 | 151 | > 下列参数据实际情况修改 152 | 153 | ```bash 154 | ifconfig eth0 192.168.8.139 netmask 255.255.255.0 up 155 | route add default gw 192.168.8.1 eth0 156 | 157 | ifconfig 158 | route -n 159 | ``` 160 | 161 | ### 4.2 下载 rootfs.tar.gz 162 | 163 | > flash 比较小,这里下载到内存 164 | 165 | * 下载 rootfs.tar.gz 166 | 167 | ```bash 168 | cd /tmp 169 | wget http://192.168.8.242:8080/rootfs/rootfs.tar.gz 170 | ``` 171 | 172 | * 解压 rootfs.tar.gz 173 | 174 | ```bash 175 | tar xf rootfs.tar.gz 176 | ``` 177 | 178 | * 挂载 rootfs 179 | 180 | ```bash 181 | chroot rootfs 182 | mount -a 183 | ``` 184 | 185 | ### 4.3 下载 release.tar.gz 186 | 187 | * 下载 release.tar.gz 188 | 189 | ```bash 190 | wget http://192.168.8.242:8080/awtk-linux-fb/release.tar.gz 191 | ``` 192 | 193 | * 解压 release.tar.gz 194 | 195 | ```bash 196 | tar xf release.tar.gz 197 | ``` 198 | 199 | ## 5. 运行 awtk-linux-fb 200 | 201 | ```bash 202 | cd release/ 203 | ./bin/demoui 204 | ``` 205 | 206 | > 如果一切正常,可以用触摸屏操作,切换语言到中文,会看到如下界面: 207 | 208 | ![](images/t113-s3.png) 209 | 210 | -------------------------------------------------------------------------------- /docs/changes.md: -------------------------------------------------------------------------------- 1 | # 最新动态 2 | 3 | 2025/05/26 4 | * 修正使用CAIRO时,PNG图片渲染颜色不正确问题,因为CAIRO只支持CAIRO_FORMAT_ARGB32这一种32位色的表面 5 | 6 | 2025/04/27 7 | * 修正运行中途插入USB键盘时,没有正确识别的问题(感谢智明提供补丁) 8 | * 修正kill命令杀死进程时,不触发正常退出流程,导致设备资源没有完全释放的问题(感谢智明提供补丁) 9 | 10 | 2025/04/24 11 | * 完善 awtk-wayland (感谢泽武提供补丁) 12 | * 完善 awtk-linux-fb 文档 (感谢泽武提供补丁) 13 | 14 | 2025/02/07 15 | * 修复COMMON_COORD_POINT_FROM_U64(感谢兆坤提供补丁) 16 | 17 | 2025/01/15 18 | * 修正drm模式每次drm_vsync刷新屏幕时,都调用srand重置随机种子的Bug,避免程序中使用rand会出现重复的数字的问题 19 | 20 | 2025/01/09 21 | * 配合最近awtk的g2d重构,删除lcd_linux_fb.c中swap和多线程模式相关代码,避免在多fb的时候运行崩溃 22 | * 修改awtk_config.py脚本,链接时加入atomic库,以及修正AWTK_STATIC_LIBS的赋值,避免链接libawtk.so时出现重复包含库 23 | 24 | 2024/12/30 25 | * 修改编译脚本拼写错误(感谢兆坤提供补丁) 26 | 27 | 2024/12/29 28 | * 公共坐标改用原子操作(感谢兆坤提供补丁) 29 | * 支持原子操作(感谢兆坤提供补丁) 30 | 31 | 2024/12/28 32 | * 重构支持G2D加速。 33 | 34 | 2024/12/04 35 | * 上报多点触摸事件。 36 | 37 | 2024/12/01 38 | * 完善触摸事件,兼容单点和多点。 39 | * 完善触摸事件,去掉冗余的pointer move事件 40 | 41 | 2024/10/31 42 | * 完善 devices(感谢兆坤提供补丁) 43 | 44 | 2024/08/28 45 | * 增加 wayland 渲染支持,使用方法见 how_to_use_in_wayland.md。(感谢泽武提供补丁) 46 | 47 | 2024/07/23 48 | * 编译脚本新增 scons 使用版本不一致判断函数。(感谢高源提供补丁) 49 | 50 | 2023/12/15 51 | * 添加project_scripts脚本,提供给应用的发布脚本scripts/release.py去使用,把awtk-linux-fb中独有的资源比如devices.json也发布到应用的release文件夹中(感智明提供补丁) 52 | 53 | 2023/11/17 54 | * 为兼容老的使用习惯,删除config/devices.json文件改为模板文件devices.json.in,并增加使用说明(感智明提供补丁) 55 | 56 | 2023/08/28 57 | * 重构scons脚本支持awtk_config_define.py和命令行参数,可以用scons help查看命令,注意要配合最新awtk使用(感智明提供补丁) 58 | 59 | 2023/08/11 60 | * 修复当同时使用触摸屏后再使用鼠标时,指针位置不对的问题(感谢兆坤提供补丁) 61 | * 完善调试log信息(感谢兆坤提供补丁) 62 | 63 | 2023/03/24 64 | * 完善README(感谢泽武提供补丁) 65 | * 完善编译脚本(感谢泽武提供补丁) 66 | 67 | 2023/03/20 68 | * 修复linux fb拼写错误的问题(感谢兆坤提供补丁) 69 | 70 | 2023/03/14 71 | * SConstruct编译脚本在编译前检查参数是否合法(感谢泽武提供补丁) 72 | * 完善README(感谢泽武提供补丁) 73 | 74 | 2023/02/27 75 | * 修改输入设备配置的方式,这样做device容易拓展,而且更改device也比较方便,不用重新编译 (感谢兆坤提供补丁) 76 | 77 | 2023/02/07 78 | * 自定义键值支持255以上的键值(感谢兆坤提供补丁) 79 | 80 | 2022/11/16 81 | * 增加自定义键值功能(感谢兆坤提供补丁) 82 | 83 | 2022/08/13 84 | * 修复编译报错的问题(感谢雨欣提供补丁) 85 | 86 | 2022/08/06 87 | * 修复点击鼠标滚轮时x坐标被覆盖的问题,并添加支持鼠标滚轮事件的文档 88 | 89 | 2022/07/12 90 | * 完善drm(感谢雨欣提供补丁) 91 | 92 | 2021/07/02 93 | * 修复linux-fb无法修改lcd分辨率问题(感谢智明提供补丁) 94 | -------------------------------------------------------------------------------- /docs/how_to_run_awtk_in_qemu.md: -------------------------------------------------------------------------------- 1 | # 在 qemu 中运行 AWTK 2 | 3 | 虽然在 VMware 中也可以跑 awtk-linux-fb 版本,但是 [qemu](https://www.qemu.org) 能模拟一个更接近开发板的 arm-linux 环境。另外用来调试和学习一下 framebuffer 的驱动,也是很有意思的事。这里写个文档供大家参考。 4 | 5 | > 在 Ubuntu 20 上测试运行。 6 | 7 | ## 构建 arm-linux 运行环境 8 | 9 | 手工从头构建 linux 系统还是挺麻烦的(以前干过这活), 现在有 [buildroot](https://buildroot.org/) 这个神器,从头构建 linux 系统,实在太方便了。 10 | 11 | * 确定工作目录 12 | 13 | > 我们把工作目录固定到/opt/qemu 下,方便后面说明。 14 | 15 | ``` 16 | sudo mkdir /opt/qemu 17 | sudo chown yourusername.yourgroup /opt/qemu 18 | cd /opt/qemu 19 | ``` 20 | 21 | * 下载 awtk 和 awtk-linux-fb 22 | 23 | ``` 24 | git clone https://gitee.com/zlgopen/awtk.git 25 | git clone https://gitee.com/zlgopen/awtk-linux-fb.git 26 | ``` 27 | 28 | * 下载 buildroot 29 | 30 | ``` 31 | wget https://buildroot.org/downloads/buildroot-2021.02.2.tar.gz 32 | tar xf buildroot-2021.02.2.tar.gz 33 | cd buildroot-2021.02.2 34 | ``` 35 | 36 | * 配置 37 | 38 | ``` 39 | make qemu_arm_vexpress_defconfig 40 | make menuconfig 41 | ``` 42 | 43 | 在缺省配置下,修改 toolchain 的配置,增加 glibc/c++/gdb 三个配置项目。 44 | 45 | ![image](images/build_root_tool_chain.png) 46 | 47 | > 新版 AWTK 需要 Enable WCHAR support 48 | 49 | 保存退出。 50 | 51 | * 编译 52 | 53 | ``` 54 | make -j4 55 | ``` 56 | 57 | > 时间比较久,请耐心等待。 58 | 59 | ## 构建 awtk-linux-fb 60 | 61 | 进入 awtk-linux-fb 目录: 62 | 63 | * 编译 64 | 65 | ``` 66 | scons TOOLS_PREFIX='/opt/qemu/buildroot-2021.02.2/output/host/bin/arm-linux-' TSLIB_LIB_DIR='' 67 | ``` 68 | 69 | * release 70 | 71 | ``` 72 | ./release.sh 73 | ``` 74 | 75 | ## 将 AWTK 加入 rootfs 76 | 77 | * 回到 buildroot 的生成结果目录: 78 | 79 | ``` 80 | cd /opt/qemu/buildroot-2021.02.2/output/images 81 | ``` 82 | 83 | * 将 awtk 可执行文件拷贝到 rootfs 84 | 85 | ``` 86 | mkdir root 87 | sudo mount -o loop rootfs.ext2 ./root 88 | cd root/opt/ 89 | sudo cp -rf /opt/qemu/awtk-linux-fb/release . 90 | cd - 91 | ``` 92 | 93 | ## 运行 94 | 95 | * 启动 qemu 96 | 97 | ``` 98 | ./start-qemu.sh 99 | ``` 100 | 101 | * 进入 qemu 的中终端下启动 AWTK: 102 | 103 | > 用户名 root 密码为空 104 | 105 | ``` 106 | cd /opt/release 107 | ./bin/demoui 108 | ``` 109 | 110 | * 在 Linux 主机的终端下启动 VNC Viewer 111 | 112 | ``` 113 | vncviewer localhost 114 | ``` 115 | 116 | 可以看到并操作 AWTK 应用程序了: 117 | 118 | ![](images/qemu_awtk.png) 119 | 120 | ## 附 121 | 122 | ### 修改分辨率 123 | 124 | * 增加配置 125 | 126 | vi /etc/fb.modes 127 | 128 | ``` 129 | mode "640x480-0" 130 | # D: 0.000 MHz, H: 0.000 kHz, V: 0.000 Hz 131 | geometry 640 480 640 480 16 132 | timings 0 48 16 33 10 96 2 133 | accel true 134 | rgba 5/11,6/5,5/0,0/0 135 | endmode 136 | ``` 137 | 138 | * 使其生效 139 | 140 | ``` 141 | fbset 640x480-60 142 | ``` 143 | 144 | ### debug kernel 145 | 146 | 画蛇添足一下,如果希望调试 linux 内核,比如 framebuffer,可以这样: 147 | 148 | 修改 start-qemu.sh,增加启动参数主机-s -S,让 qemu 启动 gdbserver,并等待 gdb 连接。然后启动 qemu。 149 | 150 | ``` 151 | #!/bin/sh 152 | ( 153 | BINARIES_DIR="${0%/*}/" 154 | cd ${BINARIES_DIR} 155 | 156 | if [ "${1}" = "serial-only" ]; then 157 | EXTRA_ARGS='-nographic' 158 | else 159 | EXTRA_ARGS='-serial stdio' 160 | fi 161 | 162 | export PATH="/opt/qemu/buildroot-2021.02.2/output/host/bin:${PATH}" 163 | exec qemu-system-arm -M vexpress-a9 -smp 1 -m 256 -kernel zImage -dtb vexpress-v2p-ca9.dtb -drive file=rootfs.ext2,if=sd,format=raw -append "console=ttyAMA0,115200 rootwait root=/dev/mmcblk0" -net nic,model=lan9118 -net user ${EXTRA_ARGS} -s -S 164 | ) 165 | ``` 166 | 167 | * 使用 arm-linux-gdb 连接到 qemu。 168 | 169 | ``` 170 | export PATH=$PATH:/opt/qemu/buildroot-2021.02.2/output/host/bin 171 | 172 | cd output/build/linux-5.10.7 173 | arm-linux-gdb vmlinux 174 | target remote :1234 175 | ``` 176 | 177 | 设置断点并调试 178 | 179 | ``` 180 | b start_kernel 181 | c 182 | ``` 183 | -------------------------------------------------------------------------------- /docs/how_to_support_fb_resize.md: -------------------------------------------------------------------------------- 1 | # 如何支持动态切换屏幕分辨率 2 | 3 | #### 应用程序使用说明 4 | 5 | 在 AWTK 应用中,用户可以简单的调用 window_manager_resize 函数实现分辨率切换。 6 | 7 | ~~~h 8 | /** 9 | * @method window_manager_resize 10 | * 调整原生窗口的大小。 11 | * @annotation ["scriptable"] 12 | * @param {widget_t*} widget 窗口管理器对象。 13 | * @param {wh_t} w 宽度 14 | * @param {wh_t} h 高度 15 | * 16 | * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 17 | */ 18 | ret_t window_manager_resize(widget_t* widget, wh_t w, wh_t h); 19 | ~~~ 20 | 21 | #### 适配层实现方法 22 | 23 | 通常开发者在适配层创建 LCD 对象时,需要绑定 lcd->resize 回调函数,在这个回调中实现分辨率切换的系统调用。 24 | 25 | ``` 26 | static lcd_t* lcd_linux_create_flushable(fb_info_t* fb) { 27 | /*.....省略无关代码......*/ 28 | lcd = lcd_mem_bgr565_create_double_fb(w, h, online_fb, offline_fb); 29 | lcd_mem_linux_resize_default = lcd->resize; 30 | lcd->resize = lcd_mem_linux_resize; 31 | /*.....省略无关代码......*/ 32 | } 33 | ``` 34 | 35 | awtk-linux-fb 提供了多个默认的切换分辨率的方案,比如当 LCD_DEVICES = fb 时,相关代码在 lcd_linux_fb.c 文件的 lcd_mem_linux_resize() 函数中: 36 | 37 | ``` 38 | static ret_t lcd_mem_linux_resize(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length) { 39 | ret_t ret = RET_OK; 40 | fb_info_t* fb = &s_fb; 41 | lcd_mem_t* mem = (lcd_mem_t*)lcd; 42 | return_value_if_fail(lcd != NULL, RET_BAD_PARAMS); 43 | 44 | ret = fb_resize_reopen(fb, w, h); 45 | mem->online_fb = (uint8_t*)(fb->fbmem0); 46 | mem->offline_fb = fb->fbmem_offline; 47 | lcd_mem_set_line_length(lcd, fb_line_length(fb)); 48 | 49 | if (lcd_mem_linux_resize_default && ret == RET_OK) { 50 | lcd_mem_linux_resize_default(lcd, w, h, line_length); 51 | } 52 | 53 | log_debug("lcd_linux_fb_resize \r\n"); 54 | return ret; 55 | } 56 | ``` 57 | 58 | 其中,fb_resize_reopen() 实现了分辨率切换的系统调用,其他代码为对接 AWTK 环境的上下文。如果目标平台 API 比较特殊,使用默认的方案无法实现分辨率切换,请自行修改该函数。 59 | 60 | > 备注:LCD_DEVICES 的类型在 awtk_config.py 中设置 61 | 62 | -------------------------------------------------------------------------------- /docs/how_to_support_mouse_wheel.md: -------------------------------------------------------------------------------- 1 | # 如何支持鼠标滚轮事件 2 | 3 | 由于不同的嵌入式 linux 硬件其鼠标驱动文件对滚轮事件的表现不同,甚至部分硬件的驱动并不支持滚轮事件,因此,鼠标滚轮事件并不作为通用功能点直接加到 awtk-linux-fb 的源码里面。 4 | 5 | 此处,以树莓派为例,讲解如何让 awtk-linux-fb 支持鼠标滚轮事件,其他嵌入式 Linux 平台操作类似。 6 | 7 | ## 1.判断鼠标驱动是否支持滚轮事件 8 | 9 | 在终端中执行以下命令查看输入驱动的具体属性: 10 | 11 | ```bash 12 | cat /proc/bus/input/devices 13 | ``` 14 | 15 | 例如,树莓派中鼠标驱动的属性如下,其中有 "B: REL = xxx" 的字样,即表示该鼠标驱动支持相对坐标事件(EV\_REL),其中包括鼠标滚轮事件: 16 | 17 | > 相对坐标事件 (REL) 的类型通常有 REL_X、REL_Y、REL_WHEEL,分别表示鼠标在 x、y 方向上移动和鼠标滚轮滚动。 18 | 19 | ```bash 20 | I: Bus=0003 Vendor=093a Product=2510 Version=0111 21 | N: Name="PixArt USB Optical Mouse" 22 | P: Phys=usb-3f980000.usb-1.1.3/input0 23 | S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.3/1-1.1.3:1.0/0003:093A:2510.0004/input/input4 24 | U: Uniq= 25 | H: Handlers=mouse0 event3 26 | B: PROP=0 27 | B: EV=17 28 | B: KEY=70000 0 0 0 0 0 0 0 0 29 | B: REL=903 30 | B: MSC=10 31 | ``` 32 | 33 | ## 2.找到正确的鼠标设备文件名 34 | 35 | 根据上述鼠标驱动文件属性,可知鼠标设备文件有两个,分别是 /dev/input/mouse0 和 /dev/input/event3,通过 "hexdump /dev/input/xxx" 命令找到能正确识别滚轮事件的鼠标设备文件名。 36 | 37 | 例如,在终端中执行以下命令: 38 | 39 | ```bash 40 | hexdump "/dev/input/event3" 41 | ``` 42 | 43 | 然后,滚动鼠标滚轮,有输出相关数据,并且向上滚动与向下滚动时,其输出信息不同,即表明该鼠标设备文件能正确识别滚轮事件。 44 | 45 | > 也可通过命令 "cat /dev/input/event3 | od -t x1 -w16" 来查看指定格式的输出,od 命令的使用方法请上网搜索。 46 | 47 | ## 3.适配鼠标滚轮事件 48 | 49 | awtk-linux-fb 在树莓派中,鼠标消息处理线程是 awtk-port/input_thread/mouse_thread.c 文件中的 input_dispatch_one_event() 函数,因此只需在该函数中捕捉鼠标驱动文件的滚轮事件,转化成 AWTK 的 EVT\_WHEEL 事件,再调用 input_dispatch() 函数将其分发给 AWTK 即可。 50 | 51 | ### 3.1 捕捉滚轮事件并将其转化后分发给AWTK 52 | 53 | 鼠标设备文件返回的滚轮事件 type 为 EV_REL,其中 code 对应 REL_WHEEL(垂直滚动)和 REL_HWHEEL(水平滚轮),事件的 value 对应前后左右的方向和滚动的次数(单位)。 54 | 55 | > Linux 驱动事件详情请参阅:https://www.kernel.org/doc/Documentation/input/event-codes.txt。 56 | 57 | 此处仅以 REL_WHEEL 垂直滚动为例,向上滚动时,value 为正数;向下滚动时,value 为负数。滚动一次,value的绝对值即为 1 ,滚动两次,绝对值即为 2。 58 | 59 | 假设每滚动一次,滚动的距离为 #define MIN_WHEEL_DELTA 12,那么捕捉滚轮事件,并将其转化为 EVT_WHEEL 事件分发给AWTK的的代码如下: 60 | 61 | ```c 62 | // awtk-port/input_thread/mouse_thread.c 63 | ... 64 | /* 滚动一次的最小距离 */ 65 | #define MIN_WHEEL_DELTA 12 66 | 67 | /* 设置鼠标滚轮事件 */ 68 | static ret_t input_dispatch_set_mouse_wheel_event(run_info_t* info, event_queue_req_t* req, int32_t dy) { 69 | if (dy > 0) { 70 | req->wheel_event.dy = tk_max(MIN_WHEEL_DELTA, dy); 71 | } else if (dy < 0) { 72 | req->wheel_event.dy = tk_min(-MIN_WHEEL_DELTA, dy); 73 | } 74 | req->event.type = EVT_WHEEL; 75 | return RET_OK; 76 | } 77 | 78 | static ret_t input_dispatch_one_event(run_info_t* info) { 79 | ... 80 | else if (ret == sizeof(info->data.e)) { 81 | switch (info->data.e.type) { 82 | ... 83 | case EV_REL: { 84 | switch (info->data.e.code) { 85 | ... 86 | /* 从鼠标设备文件中捕捉鼠标滚轮事件 */ 87 | case REL_WHEEL: { 88 | int32_t dy = MIN_WHEEL_DELTA * info->data.e.value; 89 | /* 将该事件转化为 AWTK 的 EVT_WHEEL 事件 */ 90 | input_dispatch_set_mouse_wheel_event(info, req, dy); 91 | break; 92 | } 93 | ... 94 | } 95 | 96 | if (req->event.type == EVT_NONE) { 97 | req->event.type = EVT_POINTER_MOVE; 98 | } 99 | 100 | break; 101 | } 102 | case EV_SYN: { 103 | switch (req->event.type) { 104 | case EVT_KEY_UP: 105 | case EVT_KEY_DOWN: 106 | case EVT_CONTEXT_MENU: 107 | case EVT_POINTER_DOWN: 108 | case EVT_POINTER_MOVE: 109 | case EVT_POINTER_UP: 110 | case EVT_WHEEL: { /* 将转化后的滚轮事件(EVT_WHEEL)分发给AWTK */ 111 | return input_dispatch(info); 112 | ... 113 | } 114 | } 115 | 116 | return RET_OK; 117 | } 118 | ... 119 | ``` 120 | 121 | ### 3.2 适配其他嵌入式 Linux 平台或其他事件 122 | 123 | 其他嵌入式 Linux 平台操作支持鼠标滚轮事件以及其他事件的步骤一样: 124 | 1. 从设备文件中捕捉目标事件; 125 | 2. 将目标事件转化为AWTK的事件; 126 | 3. 分发给AWTK进行处理。 127 | 128 | > 需要注意的是若新增其他鼠标事件,还需修改 awtk-prot/main_loop_linux.c 中的 input_dispatch_to_main_loop() 函数,根据消息类型设置 event_queue_req_t 中的 event.size 属性,代码如下: 129 | 130 | ```c 131 | // awtk-port/main_loop_linux.c 132 | ... 133 | ret_t input_dispatch_to_main_loop(void* ctx, const event_queue_req_t* evt, const char* msg) { 134 | main_loop_t* l = (main_loop_t*)ctx; 135 | event_queue_req_t event = *evt; 136 | event_queue_req_t* e = &event; 137 | 138 | if (l != NULL && l->queue_event != NULL) { 139 | switch (e->event.type) { 140 | case EVT_KEY_DOWN: 141 | case EVT_KEY_UP: 142 | case EVT_KEY_LONG_PRESS: { 143 | e->event.size = sizeof(e->key_event); 144 | break; 145 | } 146 | case EVT_CONTEXT_MENU: 147 | case EVT_POINTER_DOWN: 148 | case EVT_POINTER_MOVE: 149 | case EVT_POINTER_UP: { 150 | e->event.size = sizeof(e->pointer_event); 151 | break; 152 | } 153 | /* 设置的滚轮消息 event.size 属性 */ 154 | case EVT_WHEEL: { 155 | e->event.size = sizeof(e->wheel_event); 156 | break; 157 | } 158 | default: 159 | break; 160 | } 161 | 162 | main_loop_queue_event(l, e); 163 | input_dispatch_print(ctx, e, msg); 164 | } else { 165 | return RET_BAD_PARAMS; 166 | } 167 | return RET_OK; 168 | } 169 | ... 170 | ``` 171 | -------------------------------------------------------------------------------- /docs/how_to_use_egl.md: -------------------------------------------------------------------------------- 1 | # linux-fb 如何使用 egl 2 | 3 | ## 1.配置默认支持的 egl 平台 4 | 5 | ​ 在 linux-fb 中默认适配了三种平台的 egl,分别是飞思卡尔(fsl)平台和支持 x11 平台以及树莓派,如果是默认已经适配的平台,直接在 awtk_config.py 中开启相关的配置就可以使用,如下: 6 | 7 | ```python 8 | # awtk_config.py 9 | 10 | # lcd devices 11 | LCD_DEVICES='fb' 12 | # LCD_DEVICES='drm' 13 | # LCD_DEVICES='egl_for_fsl' 14 | # LCD_DEVICES='egl_for_x11' 15 | # LCD_DEVICES='egl_for_rpi' 16 | ``` 17 | 18 | ### 2.适配其他 egl 平台 19 | 20 | ​ 这里假设需要适配的平台名字为 AAA。 21 | 22 | 1. 在 egl_devices 目录下创建 AAA/egl_devices.c 文件重载实现 liunx-fb 的 egl 接口(egl_devices.h 文件),egl 接口(egl_devices.h 文件)如下: 23 | 24 | ```h 25 | /* egl_devices.h */ 26 | #ifndef TK_EGL_DEVICES_H 27 | #define TK_EGL_DEVICES_H 28 | 29 | #include "base/types_def.h" 30 | 31 | BEGIN_C_DECLS 32 | 33 | void* egl_devices_create(const char* filename); 34 | ret_t egl_devices_dispose(void* ctx); 35 | 36 | float_t egl_devices_get_ratio(void* ctx); 37 | int32_t egl_devices_get_width(void* ctx); 38 | int32_t egl_devices_get_height(void* ctx); 39 | 40 | ret_t egl_devices_make_current(void* ctx); 41 | ret_t egl_devices_swap_buffers(void* ctx); 42 | 43 | END_C_DECLS 44 | 45 | #endif /*TK_EGL_DEVICES_H*/ 46 | ``` 47 | 48 | 2. 修改 SConscript 文件,加入对应平台的适配文件(AAA/egl_devices.c 文件),如下: 49 | 50 | ```python 51 | # SConscript 52 | 53 | if LCD_DEVICES =='egl_for_fsl' : 54 | SOURCES = Glob('egl_devices/fsl/*.c') + SOURCES; 55 | elif LCD_DEVICES =='egl_for_x11' : 56 | SOURCES = Glob('egl_devices/x11/*.c') + SOURCES; 57 | elif LCD_DEVICES =='egl_for_rpi' : 58 | SOURCES = Glob('egl_devices/rpi/*.c') + SOURCES; 59 | elif LCD_DEVICES =='egl_for_AAA' : # 这里加入适配文件代码 60 | SOURCES = Glob('egl_devices/AAA/*.c') + SOURCES; 61 | ``` 62 | 63 | 3. 在 awtk_config.py 加入编译选项,如下: 64 | 65 | ```python 66 | # awtk_config.py 67 | ... 68 | 69 | # lcd devices 70 | # LCD_DEVICES='fb' 71 | # LCD_DEVICES='drm' 72 | # LCD_DEVICES='egl_for_fsl' 73 | # LCD_DEVICES='egl_for_x11' 74 | # LCD_DEVICES='egl_for_rpi' 75 | LCD_DEVICES='egl_for_AAA' # 这里让 LCD_DEVICES 等于 egl_for_AAA,因为 SConscript 中需要 LCD_DEVICES 来确定编译文件。 76 | 77 | ... 78 | 79 | if LCD_DEVICES =='drm' : 80 | #for drm 81 | OS_FLAGS=OS_FLAGS + ' -DWITH_LINUX_DRM=1 -I/usr/include/libdrm ' 82 | OS_LIBS=OS_LIBS + ['drm'] 83 | elif LCD_DEVICES =='egl_for_fsl': 84 | #for egl for fsl 85 | OS_FLAGS=OS_FLAGS + ' -DEGL_API_FB ' 86 | OS_LIBS=OS_LIBS + [ 'GLESv2', 'EGL'] 87 | elif LCD_DEVICES =='egl_for_x11' : 88 | #for egl for fsl 89 | OS_FLAGS=OS_FLAGS + ' -fPIC ' 90 | OS_LIBS=OS_LIBS + [ 'X11', 'EGL', 'GLESv2' ] 91 | elif LCD_DEVICES =='egl_for_rpi' : 92 | #for egl for rpi 93 | OS_LIBPATH += ['/opt/vc/lib'] 94 | OS_CPPPATH += ['/opt/vc/include'] 95 | OS_LIBS=OS_LIBS + [ 'brcmEGL', 'brcmGLESv2', 'bcm_host' ] 96 | COMMON_CCFLAGS += ' -DWITH_GLAD_SPECIAL_OPENGL_LIB=\\\"\"/opt/vc/lib/libbrcmGLESv2.so\\\"\" ' 97 | elif LCD_DEVICES =='egl_for_AAA': 98 | # 这里添加链接相关的宏和链接类库以及头文件路径。 99 | # OS_FLAGS, OS_LIBPATH, OS_LIBS, COMMON_CCFLAGS 100 | ``` 101 | 102 | 103 | > 其中 WITH_GLAD_SPECIAL_OPENGL_LIB 宏是定义特殊链接的 egl 类库,提供给 glad 获取 OpenGLES 的相关函数使用的,如果调用默认的 libGLESv2.so 的话,则可以不需要设置,如 egl_for_x11 和 egl_for_fsl。 -------------------------------------------------------------------------------- /docs/how_to_use_in_android.md: -------------------------------------------------------------------------------- 1 | # 如何搭建 Android 调试环境 2 | 3 | awtk-linux-fb 是为嵌入式 linux 准备的,但为了调试方便,可以让 awtk-linux-fb 运行在手机 Android 环境中。需要让 Android 不要启动图形桌面,这样 awtk 程序才可以正常显示到 framebuffer 上。 4 | 5 | 所有操作步骤在 PC Ubuntu 中进行。 6 | 7 | ## 操作步骤 8 | 9 | ##### 一、准备工作 10 | 11 | 1. 下载交叉编译工具链 android-ndk-r21e-linux-x86_64.zip 12 | 13 | 2. 安装 adb 调试工具 14 | 15 | ``` 16 | sudo apt install adb android-tools-adb 17 | ``` 18 | 19 | ##### 二、用 NDK 交叉编译 awtk-linux-fb 20 | 21 | 1. 解压交叉编译工具链 android-ndk-r21e-linux-x86_64.zip 到 /opt 22 | 23 | 2. scons 参数的可以配置交叉编译工具链,并设置正确的编译器路径 24 | 25 | ``` 26 | scons TOOLS_PREFIX="/opt/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/" TOOLS_CC="armv7a-linux-androideabi16-clang" TOOLS_CXX="armv7a-linux-androideabi16-clang++" TOOLS_LD="arm-linux-androideabi-ld" TOOLS_AR="arm-linux-androideabi-ar" TOOLS_STRIP="arm-linux-androideabi-strip" TOOLS_RANLIB="arm-linux-androideabi-ranlib" 27 | ``` 28 | 29 | 3. 编译 awtk 源码并部署到 release 文件夹 30 | 31 | ``` 32 | cd awtk-linux-fb 33 | scons && sh release.sh 34 | ``` 35 | 36 | 4. 拷贝 libc++_shared.so 动态库 37 | 38 | 由于编译选项默认使用动态链接方式使用标准C++库,所以需要把相关的 so 文件也上传到 Android 设备。 39 | 40 | ``` 41 | cp /opt/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./release/bin 42 | ``` 43 | 44 | ##### 三、连接 Android 设备 45 | 46 | 1. 手机启动开发者模式,把手机通过 USB 线连接到 PC 47 | 48 | 2. 把编译好的bin和资源文件上传到手机 49 | 50 | ``` 51 | cd awtk-linux-fb 52 | adb push ./release /data/local/tmp 53 | ``` 54 | 55 | ##### 四、进入手机 shell 环境操作 56 | 57 | 1. 进入手机 shell 并配置运行环境 58 | 59 | ``` 60 | adb shell 61 | su 62 | chmod 777 /data/local/tmp/bin/demoui 63 | # 设置so文件搜索路径 64 | export LD_LIBRARY_PATH=$LD_LIBRARY:/data/local/tmp/bin 65 | ``` 66 | 67 | 2. 关闭 Android 桌面准备运行程序 68 | 69 | ``` 70 | # 关闭桌面 71 | setprop ctl.stop zygote 72 | setprop ctl.stop bootanim 73 | # 如果运行过程出现黑屏,可能是系统的其他进程在抢占 fb,用下面的命令关闭冲突的进程 74 | setprop ctl.stop servicemanager 75 | setprop ctl.start servicemanager 76 | # 运行程序 77 | /data/local/tmp/bin/demoui 78 | ``` -------------------------------------------------------------------------------- /docs/how_to_use_in_rpi.md: -------------------------------------------------------------------------------- 1 | # 在树莓派中使用awtk的方法(fb&egl) 2 | 3 | ### FrameBuffer 模式 4 | 5 | 1. 确保系统没有启动X或桌面,可以在 raspi-config 中配置系统启动时只进入命令行 CLI 6 | 7 | ``` 8 | sudo raspi-config 9 | ``` 10 | 11 | 2. 修改 awtk-linux-fb/awtk_config.py 文件的编译器和编译选项 12 | 13 | ``` 14 | #for pc build 15 | TOOLS_PREFIX='' 16 | TSLIB_LIB_DIR='' 17 | ``` 18 | 19 | 3. 直接在树莓派中编译 awtk 并运行 20 | 21 | ``` 22 | cd awtk-linux-fb 23 | scons 24 | sh release.sh 25 | sudo release/bin/demoui 26 | ``` 27 | 28 | ### EGL-X11 模式 29 | 30 | 1. 修改 raspi-config 开启 GL 加速 31 | 32 | ``` 33 | sudo raspi-config 34 | 开启 GL full KMS 驱动 35 | ``` 36 | 37 | 2. 进入桌面或 X 38 | 39 | ``` 40 | sudo X & 41 | ``` 42 | 43 | 3. 修改环境变量指定 EGL 首选的显示设备 44 | 45 | ``` 46 | export DISPLAY=:0.0 47 | ``` 48 | 49 | 4. 安装编译依赖库 50 | 51 | ``` 52 | sudo apt install libx11-dev 53 | sudo apt install libgles2-mesa libgles2-mesa-dev 54 | ``` 55 | 56 | 5. 修改 awtk-linux-fb/awtk_config.py 文件的 LCD_DEVICES 模式 57 | 58 | ``` 59 | # lcd devices 60 | LCD_DEVICES='egl_for_x11' 61 | 62 | #for pc build 63 | TOOLS_PREFIX='' 64 | TSLIB_LIB_DIR='' 65 | ``` 66 | 67 | 6. 直接在树莓派中编译 awtk 并运行 68 | 69 | ``` 70 | cd awtk-linux-fb 71 | scons 72 | sh release.sh 73 | sudo release/bin/demoui 74 | ``` 75 | 76 | ### EGL-gbm 模式 77 | 78 | 1. 修改 raspi-config 开启 GL 加速 79 | 80 | ``` 81 | sudo raspi-config 82 | 开启 GL full KMS 驱动 83 | ``` 84 | 85 | 2. 修改 awtk-linux-fb/awtk_config.py 文件的 LCD_DEVICES 模式 86 | 87 | ``` 88 | # lcd devices 89 | LCD_DEVICES='egl_for_gbm' 90 | 91 | #for pc build 92 | TOOLS_PREFIX='' 93 | TSLIB_LIB_DIR='' 94 | ``` 95 | 96 | 3. 直接在树莓派中编译 awtk 并运行 97 | 98 | ``` 99 | cd awtk-linux-fb 100 | scons 101 | sh release.sh 102 | sudo release/bin/demoui 103 | ``` 104 | -------------------------------------------------------------------------------- /docs/how_to_use_in_vmware.md: -------------------------------------------------------------------------------- 1 | # 如何搭建 Ubuntu 调试环境 2 | 3 | awtk-linux-fb 是为嵌入式 linux 准备的,但为了调试方便,可以让 awtk-linux-fb 运行在 PC 机的 Ubuntu 环境中。需要让 Ubuntu 开机时不要启动图形桌面,而是启动普通的字符模式,目的是让 /dev/fb0 设备不被抢占,这样 awtk 程序才可以正常显示到 framebuffer 上。 4 | 5 | ## 操作步骤 6 | 7 | ##### 1. 在命令行执行 systemctl 命令切换图形和字符模式 8 | 9 | 如果当前在图形桌面模式,执行下面的命令重启后进入字符模式: 10 | 11 | ``` 12 | sudo systemctl set-default multi-user.target 13 | sudo reboot 14 | ``` 15 | 16 | 如果当前在字符模式,执行下面的命令重启后进入桌面模式: 17 | 18 | ``` 19 | sudo systemctl set-default graphical.target 20 | sudo reboot 21 | ``` 22 | 23 | ##### 2. 设置编译器 24 | 25 | 修改 **awtk-linux-fb/awtk_config.py** 使用 Ubuntu 自带的 GCC 编译器,把下面两行代码的注释去掉: 26 | 27 | ``` 28 | #for pc build 29 | TOOLS_PREFIX='' 30 | TSLIB_LIB_DIR='' 31 | ``` 32 | 33 | 也可以在该配置文件中选择使用 fb 模式或 drm 模式,新的系统建议使用 drm 模式,效率更高: 34 | 35 | ``` 36 | # lcd devices 37 | LCD_DEVICES='fb' 38 | # LCD_DEVICES='drm' 39 | ``` 40 | 41 | ##### 3. 编译 demo 并抽取资源文件 42 | 43 | 确保 awtk 和 awtk-linux-fb 在同一级目录 44 | 45 | ``` 46 | cd awtk-linux-fb 47 | scons 48 | sh release.sh 49 | ``` 50 | 51 | ##### 4. 运行 demo 52 | 53 | 需要在管理员模式运行 demo 程序,运行前请确保当前 Ubuntu 是以字符模式启动 54 | 55 | ``` 56 | cd awtk-linux-fb 57 | sudo release/bin/demoui 58 | ``` 59 | 60 | ## 配置 VMware 显存 61 | 62 | 如果 Ubuntu 是安装在 VMware 虚拟机中,默认只能使用 awtk-linux-fb 单缓冲模式,因为 VMware 虚拟机默认 svga 显存大小是 4MB,不够分配 awtk 使用的双缓冲显存。如需要调试双缓冲模式,则要将虚拟机的 svga 显存调整为 8MB。 63 | 64 | #### 调整方法 65 | 66 | 打开 **Ubuntu 64 位.vmx** 文件修改,加入下面两行配置: 67 | 68 | ``` 69 | svga.minVRAMSize=8388608 70 | svga.minVRAM8MB=TRUE 71 | ``` 72 | 73 | #### 调整显存前 74 | 75 | fb 分辨率是 800x600:yres=600,调整前 yres_virtual==885,yres_virtual < yres*2 不满足双缓冲的最低要求,fbset 命令显示如下: 76 | 77 | ``` 78 | mode "800x600" 79 | geometry 800 600 1176 885 32 80 | timings 0 0 0 0 0 0 0 81 | rgba 8/16,8/8,8/0,0/0 82 | endmode 83 | 84 | Frame buffer device information: 85 | Name : svgadrmfb 86 | Address : 0 87 | Size : 4163040 88 | Type : PACKED PIXELS 89 | Visual : TRUECOLOR 90 | XPanStep : 1 91 | YPanStep : 1 92 | YWrapStep : 0 93 | LineLength : 4704 94 | Accelerator : No 95 | ``` 96 | 97 | #### 调整显存后 98 | 99 | 调整后 yres_virtual==1254,yres_virtual >= yres*2 满足双缓冲要求,fbset 命令显示如下: 100 | 101 | ``` 102 | mode "800x600" 103 | geometry 800 600 1672 1254 32 104 | timings 0 0 0 0 0 0 0 105 | rgba 8/16,8/8,8/0,0/0 106 | endmode 107 | 108 | Frame buffer device information: 109 | Name : svgadrmfb 110 | Address : 0 111 | Size : 8386752 112 | Type : PACKED PIXELS 113 | Visual : TRUECOLOR 114 | XPanStep : 1 115 | YPanStep : 1 116 | YWrapStep : 0 117 | LineLength : 6688 118 | Accelerator : No 119 | ``` 120 | 121 | > 双缓冲判断请参考 awtk-port/fb_info.h 中的代码 122 | 123 | #### 修改屏幕分辨率的方法 124 | 125 | 比如要调整屏幕为 800x480x32bit,虚拟分辨率为 800x960(双缓冲)时,可以用 fbset 命令进行设置: 126 | 127 | ``` 128 | sudo fbset -g 800 480 800 960 32 129 | ``` 130 | 131 | > 这种方法同样适用于真正的嵌入式 Linux 板子设备 -------------------------------------------------------------------------------- /docs/how_to_use_in_wayland.md: -------------------------------------------------------------------------------- 1 | # awtk-linux-fb 如何适配 wayland 平台 2 | 3 | ## 1.支持的 shell 类型 4 | 5 | 目前awtk-wayland支持两种weston shell类型,一种是desktop-shell,一种是fullscreen-shell,weston默认使用desktop-shell,如果需要使用fullscreen-shell类型,请修改weston的配置文件后 "weston.ini" 启动weston,如下所示: 6 | 7 | ```ini 8 | [core] 9 | shell=fullscreen-shell.so 10 | ``` 11 | 12 | ## 2.生成协议文件 13 | 14 | 在进行编译之前,需要先生成协议文件,这些文件会参与到项目的编译当中,使用 wayland-scanner 进行协议的生成,在使用前请保证 wayland-scanner 的版本与设备上的一致,使用以下命令查看版本(也可以通过配置 wayland-scanner 路径自动生成协议文件,详见第三点): 15 | 16 | ```shell 17 | wayland-scanner -v 18 | ``` 19 | 20 | 比如在 M3568 的工具链中就自带了 wayland-scanner 工具,生成协议文件的命令如下(文件名请勿更改): 21 | 22 | ```shell 23 | cd awtk-linux-fb/awtk-wayland/protocol/ 24 | /opt/m3568-sdk-v1.0.0-ga/host/bin/wayland-scanner client-header xdg-shell.xml xdg-shell-protocol.h 25 | /opt/m3568-sdk-v1.0.0-ga/host/bin/wayland-scanner private-code xdg-shell.xml xdg-shell-protocol.c 26 | /opt/m3568-sdk-v1.0.0-ga/host/bin/wayland-scanner client-header fullscreen-shell-unstable-v1.xml fullscreen-shell-protocol.h 27 | /opt/m3568-sdk-v1.0.0-ga/host/bin/wayland-scanner private-code fullscreen-shell-unstable-v1.xml fullscreen-shell-protocol.c 28 | ``` 29 | 30 | ## 3.如何编译 awtk-wayland 31 | 32 | 在 awtk-linux-fb 下先参照 README.md 生成 awtk_config_define.py,配置好 TOOLS_PREFIX 和 LCD_DEVICES 等参数。 33 | 34 | 配置 awtk_config_define.py: 35 | 36 | ```python 37 | TOOLS_PREFIX = "/opt/m3568-sdk-v1.0.0-ga/host/usr/bin/aarch64-linux-" # 按自己的板子配置交叉编译工具路径 38 | # 设置LCD_DEVICES二选一 39 | LCD_DEVICES = "wayland" # 使用软件渲染 40 | LCD_DEVICES = "egl_for_wayland" # 使用OpenGL渲染 41 | OS_LINKFLAGS = " -Wl,--copy-dt-needed-entries " # 解决部分工具链的DSO missing错误 42 | WAYLAND_SCANNER_PATH = '/opt/m3568-sdk-v1.0.0-ga/host/bin' # 若没有使用第二点的方法生成协议文件,则需要指定wayland-scanner的路径 43 | OS_FLAGS = " -DFULLSCREEN=1 " #若想全屏显示程序,则定义该宏,使用全屏模式时需要确保LCD大小与屏幕大小一致 44 | ``` 45 | 46 | 使用以下命令编译 awtk-linux-fb: 47 | 48 | ```shell 49 | cd awtk-linux-fb 50 | scons 51 | ``` 52 | 53 | 如果不想使用 awtk_config_define.py,也可以在 scons 编译时直接指定参数: 54 | 55 | ```shell 56 | cd awtk-linux-fb 57 | #不使用 OpenGL 58 | scons LCD_DEVICES='wayland' 59 | #使用 OpenGL 60 | scons LCD_DEVICES='egl_for_wayland' 61 | ``` 62 | 63 | 若在编译时出现未找到动态库等错误,并根据实际情况添加 wayland 动态库和头文件的路径,请添加在 OS_LIBPATH 和 OS_CPPPATH 中。 -------------------------------------------------------------------------------- /docs/how_to_use_library_and_custom_main.md: -------------------------------------------------------------------------------- 1 | # 如何使用 AWTK 静态/动态库以及自定义 main 函数 2 | 3 | ## 1 生成 AWTK 静态/动态库 4 | 5 | 生成 AWTK 静态/动态库 的步骤如下: 6 | 7 | 1. 确保 awtk 与 awtk-linux-fb 的目录结构如下: 8 | 9 | ``` 10 | xxxx 11 | |-- awtk 12 | |-- awtk-linux-fb 13 | ``` 14 | 15 | 2. 参照 awtk-linux-fb/README.md 文档配置好交叉编译工具链与输入设备文件名。 16 | 17 | 3. 在 awtk-linux-fb 目录下打开终端,执行以下命令进行编译: 18 | 19 | ``` 20 | scons 21 | ``` 22 | 23 | AWTK 动态库放在 awtk-linux-fb/bin 目录,包含 libawtk.so 和 libtkc.so 两个文件;AWTK 静态库的功能比较零散,文件较多,都放在 awtk-linux-fb/lib 目录下,此处就不逐一列出了。 24 | 25 | ## 2 使用 gcc 编译项目源文件 26 | 27 | 使用 AWTK 静态库或动态库通常需要用户自己编译项目,这里列举出编译所需的宏定义与包含路径,方便用户参考。 28 | 29 | ### 2.1 宏定义 30 | 31 | | 宏定义 | 用途 | 是否必须 | 缺省值 | 备注 | 32 | | ----------------------------- | ---------------------------------- | -------- | ------- | ------------------------------------------------ | 33 | | LCD_WIDTH=[number] | LCD 的宽度 | 否 | 320 | | 34 | | LCD_HEIGHT=[number] | LCD 的高度 | 否 | 480 | | 35 | | APP_DEFAULT_FONT=[string] | 项目默认使用的字库名称 | 否 | default | | 36 | | APP_THEME=[string] | 项目默认使用的主题名称 | 否 | default | | 37 | | APP_RES_ROOT=[string] | 项目的资源根目录 | 否 | NULL | 缺省按照相对路径搜索 | 38 | | APP_DEFAULT_LANGUAGE=[string] | 项目默认使用的语言 | 否 | | 缺省语言环境为 en,即英文,常用值还有 zh,即中文 | 39 | | APP_DEFAULT_COUNTRY=[string] | 项目默认使用的国家 | 否 | | 缺省语言环境为 US,即美国,常用值还有 CN,即中国 | 40 | | APP_ROOT=[string] | 项目路径 | 否 | | 缺省按照相对路径搜索 | 41 | | **HAS_STDIO** | **存在标准输入输出** | **是** | | | 42 | | **LINUX** | **Linux 平台** | **是** | | | 43 | | **LOAD_ASSET_WITH_MMAP** | **支持内存映射文件** | **是** | | **与宏 WITH_FS_RES 一起使用** | 44 | | **WITH_FS_RES** | **支持文件系统** | **是** | | | 45 | | **WITH_WIDGET_TYPE_CHECK** | **启用 widget 类型检查** | **是** | | | 46 | | WITH_VGCANVAS | 支持矢量画布 | 否 | | | 47 | | WITH_SOCKET | 支持套接字 | 否 | | | 48 | | WITH_STB_IMAGE | 支持 png/jpeg 图片 | 否 | | | 49 | | WITH_STB_FONT | 用 stb 支持 Truetype 字体 | 否 | | | 50 | | WITH_TEXT_BIDI | 支持文字双向排版算法(如阿拉伯语言) | 否 | | | 51 | | ENABLE_CURSOR | 启用鼠标指针 | 否 | | 资源中需要有指针(cursor)图片 | 52 | 53 | ### 2.2 包含路径 54 | 55 | | 包含路径 | 说明 | 56 | | -------------------- | ----------------- | 57 | | awtk | awtk 根目录 | 58 | | awtk/src | awtk 源码目录 | 59 | | awtk/src/ext_widgets | awtk 扩展控件目录 | 60 | | %app%src | 项目源码目录 | 61 | | %app%res | 项目资源目录 | 62 | 63 | 64 | ### 3.2 gcc 示例命令 65 | 66 | 此处,以为一个简单的项目源文件 app_main.c 为例,编译该文件的 gcc 命令如下,项目其他源文件的编译命令类似: 67 | 68 | ```bash 69 | gcc -o src/app_main.o -c -std=gnu99 -DLCD_WIDTH=480 -DLCD_HEIGHT=272 -Wall -Os -DHAS_STDIO -DLINUX -DLOAD_ASSET_WITH_MMAP -DWITH_FS_RES -DWITH_WIDGET_TYPE_CHECK -fPIC -I/home/user/zlgopen/awtk -I/home/user/zlgopen/awtk/src -I/home/user/zlgopen/awtk/src/ext_widgets -Isrc -Ires src/app_main.c 70 | ``` 71 | 72 | ## 3 链接静态库 73 | 74 | 编译好项目源文件后,只需将生成的 .o 文件与 AWTK 静态库链接生成可执行程序即可,链接时需要包含 awtk-linux-fb/lib 目录并链接该目录下的所有静态库,例如,此处链接生成可执行程序 bin/demo,指令如下: 75 | 76 | ```bash 77 | gcc -o bin/demo -Wl,-rpath=./bin -Wl,-rpath=./ -Wl,-rpath=/home/user/zlgopen/AwtkApplication/bin src/app_main.o src/window_main.o -Llib -L/home/user/zlgopen/awtk-linux-fb/lib -lawtk_global -lextwidgets -lwidgets -lawtk_linux_fb -lbase -lgpinyin -lstreams -lconf_io -lhal -lcsv -lcompressors -lminiz -lubjson -ltkc_static -llinebreak -lmbedtls -lfribidi -lnanovg-agge -lagge -lnanovg -lstdc++ -lpthread -lrt -lm -ldl 78 | ``` 79 | 80 | > 备注:其中 app_main.o 和 window_main.o 为项目源文件的中间文件。 81 | 82 | ## 4 链接动态库 83 | 84 | 链接动态库的命令与链接静态库的命令相似,修改包含路径和库文件名即可,指令如下: 85 | 86 | ```bash 87 | gcc -o bin/demo -Wl,-rpath=./bin -Wl,-rpath=./ -Wl,-rpath=/home/user/zlgopen/AwtkApplication/bin src/app_main.o src/window_main.o -L/home/user/zlgopen/awtk-linux-fb/bin -lawtk -ltkc -lstdc++ -lpthread -lrt -lm -ldl 88 | ``` 89 | 90 | > 备注:其中 app_main.o 和 window_main.o 为项目源文件的中间文件。 91 | 92 | ## 5 自定义 main 函数 93 | 94 | AWTK 支持用户自定义 main 函数,通常只需在包含 awtk_main.inc 文件前,定义宏 USE_GUI_MAIN,然后在自定义的 main 函数中调用 gui_app_start 函数即可。 95 | 96 | ### 5.1 示例 97 | 98 | 例如,使用 Designer 新建一个 AWTK 项目,该项目的 app_main.c 文件中默认使用 AWTK 内置的 main 函数,代码如下,内置 main 函数的实现详见 awtk/src/awtk_main.inc。 99 | 100 | ```c 101 | #include "awtk.h" 102 | 103 | ... 104 | 105 | extern ret_t application_init(void); 106 | 107 | extern ret_t application_exit(void); 108 | 109 | #include "awtk_main.inc" 110 | ``` 111 | 112 | 此时,在包含 awtk_main.inc 文件前定义宏 USE_GUI_MAIN,并在自定义 main 函数中调用gui_app_start 函数初始化 AWTK 并启动 GUI 线程(主循环),代码如下: 113 | ```c 114 | #include "awtk.h" 115 | 116 | ... 117 | 118 | /** 119 | * 嵌入式系统有自己的main函数时,请定义本宏。 120 | */ 121 | #define USE_GUI_MAIN 1 122 | 123 | extern ret_t application_init(void); 124 | 125 | extern ret_t application_exit(void); 126 | 127 | #include "awtk_main.inc" 128 | 129 | /** 130 | * 自定义 main 函数 131 | * 备注:此处将 main 函数放在 awtk_main.inc 文件后是为了声明 gui_app_start 函数。 132 | */ 133 | int main(void) { 134 | return gui_app_start(LCD_WIDTH, LCD_HEIGHT); /* 需要指定 LCD 的宽高 */ 135 | } 136 | ``` 137 | -------------------------------------------------------------------------------- /docs/images/build_root_tool_chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/docs/images/build_root_tool_chain.png -------------------------------------------------------------------------------- /docs/images/menu1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/docs/images/menu1.png -------------------------------------------------------------------------------- /docs/images/menu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/docs/images/menu2.png -------------------------------------------------------------------------------- /docs/images/qemu_awtk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/docs/images/qemu_awtk.png -------------------------------------------------------------------------------- /docs/images/t113-s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlgopen/awtk-linux-fb/09bede0e40728b0b35d574be87676042085a4846/docs/images/t113-s3.png -------------------------------------------------------------------------------- /docs/imxull6_linux_notes.md: -------------------------------------------------------------------------------- 1 | # 在NXP i.MX6ULL 开发板上运行 AWTK 2 | 3 | ## 1. 准备工作 4 | 5 | > 如果某些步骤已经完成,请跳过。 6 | 7 | ## 1.1 安装 Ubuntu 22 虚拟机 8 | 9 | ## 1.2 安装 sshd 服务并启动 10 | 11 | ```bash 12 | sudo apt-get install openssh-server 13 | sudo systemctl start sshd 14 | ``` 15 | 16 | ## 1.3 安装 awtk 需要的编译环境 17 | 18 | ```bash 19 | sudo apt-get install gcc g++ scons libsndio-dev libgtk-3-dev libglu1-mesa libglu1-mesa-dev libgl1-mesa-glx libgl1-mesa-dev libasound2-dev libibus-1.0-dev fcitx-libs-dev git vim clang-format libharfbuzz-dev nodejs libreadline-dev 20 | ``` 21 | 22 | ## 1.4 安装交叉编译工具链 23 | 24 | ```bash 25 | sudo apt-get install g++-arm-linux-gnueabihf 26 | ``` 27 | 28 | ## 1.5 下载 awtk/awtk-linux-fb 源码 29 | 30 | * 创建工作目录 31 | 32 | ```bash 33 | mkdir -p ~/work/awtk-root 34 | cd ~/work/awtk-root 35 | ``` 36 | 37 | * 下载 awtk 源码 38 | 39 | ```bash 40 | git clone https://github.com/zlgopen/awtk 41 | ``` 42 | 43 | * 下载 awtk-linux-fb 源码 44 | 45 | ```bash 46 | git clone https://github.com/zlgopen/awtk-linux-fb 47 | ``` 48 | 49 | ## 2. 构建 rootfs 50 | 51 | > 因为笔者用的 MacPro M2,上面安装的是 Ubuntu 22 虚拟机,由于是 arm64 的 CPU,官方的工具链运行不了,而 Ubuntu 上工具链编译的程序,在板子自带的系统上运行不了,所以只能自己编译 rootfs。 52 | > 其它系统,如果不需要请跳过。 53 | 54 | ### 2.1 下载 busybox 源码 55 | 56 | ```bash 57 | mkdir -p ~/work/awtk-root/rootfs 58 | cd ~/work/awtk-root/rootfs 59 | wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 60 | tar -xvf busybox-1.36.1.tar.bz2 61 | ``` 62 | 63 | ### 2.2 编译 busybox 64 | 65 | ```bash 66 | cd busybox-1.36.1 67 | make defconfig 68 | make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm 69 | make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm install CONFIG_PREFIX=~/work/awtk-root/rootfs/rootfs 70 | ``` 71 | 72 | * 拷贝库文件 73 | 74 | ```bash 75 | cd ~/work/awtk-root/rootfs/rootfs/ 76 | cp -arf /usr/arm-linux-gnueabihf/lib . 77 | rm -f lib/libasan.so.6* lib/*.a lib/*.o 78 | ``` 79 | 80 | * 创建必要的文件和目录 81 | 82 | ```bash 83 | mkdir -p proc dev sys var tmp run etc 84 | ``` 85 | 86 | * 创建 etc/fstab 文件,其内容如下: 87 | 88 | ```bash 89 | proc /proc proc defaults 0 0 90 | sysfs /sys sysfs defaults 0 0 91 | tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0 92 | tmpfs /tmp tmpfs defaults 0 0 93 | devtmpfs /dev devtmpfs defaults 0 0 94 | ``` 95 | 96 | * 创建 rootfs 压缩文件包 97 | 98 | ``` 99 | cd .. 100 | tar czf rootfs.tar.gz rootfs 101 | ``` 102 | 103 | * 启动 http 服务 104 | 105 | > 打开一个新的终端 106 | 107 | ```bash 108 | ~/work/awtk-root 109 | python3 -m http.server 8080 --directory . 110 | ``` 111 | 112 | 113 | ## 3. 编译 awtk-linux-fb 114 | 115 | ### 3.1 编译 116 | 117 | ```bash 118 | cd ~/work/awtk-root/awtk-linux-fb 119 | scons TOOLS_PREFIX=arm-linux-gnueabihf- 120 | ``` 121 | 122 | ### 3.2 生成压缩包 123 | 124 | ```bash 125 | ./release.sh 126 | ``` 127 | 128 | * 创建设备配置文件:release/config/devices.json 其内容如下: 129 | 130 | ```json 131 | { 132 | "/dev/fb0" : { 133 | "type" : "fb" 134 | }, 135 | "/dev/input/event1" : { 136 | "type" : "input" 137 | } 138 | } 139 | ``` 140 | 141 | * 重新生成压缩包 142 | 143 | ``` 144 | tar czf release.tar.gz release 145 | ``` 146 | 147 | ## 4. 下载 rootfs.tar.gz 和 release.tar.gz 到开发板 148 | 149 | ### 4.1 启动网络 150 | 151 | > 下列参数据实际情况修改 152 | 153 | ```bash 154 | ifconfig eth0 192.168.8.139 netmask 255.255.255.0 up 155 | route add default gw 192.168.8.1 eth0 156 | 157 | ifconfig 158 | route -n 159 | ``` 160 | 161 | ### 4.2 下载 rootfs.tar.gz 162 | 163 | > flash 比较小,这里下载到内存 164 | 165 | * 下载 rootfs.tar.gz 166 | 167 | ```bash 168 | cd /tmp 169 | wget http://192.168.8.242:8080/rootfs/rootfs.tar.gz 170 | ``` 171 | 172 | * 解压 rootfs.tar.gz 173 | 174 | ```bash 175 | tar xf rootfs.tar.gz 176 | ``` 177 | 178 | * 挂载 rootfs 179 | 180 | ```bash 181 | chroot rootfs 182 | mount -a 183 | ``` 184 | 185 | ### 4.3 下载 release.tar.gz 186 | 187 | * 下载 release.tar.gz 188 | 189 | ```bash 190 | wget http://192.168.8.242:8080/awtk-linux-fb/release.tar.gz 191 | ``` 192 | 193 | * 解压 release.tar.gz 194 | 195 | ```bash 196 | tar xf release.tar.gz 197 | ``` 198 | 199 | ## 5. 运行 awtk-linux-fb 200 | 201 | ```bash 202 | cd release/ 203 | ./bin/demoui 204 | ``` 205 | 206 | 207 | -------------------------------------------------------------------------------- /docs/vmware_linux_fb.md: -------------------------------------------------------------------------------- 1 | 2 | # 在虚拟机中使用 awtk-linux-fb 3 | 4 | 在 Linux 桌面模式下,不能直接运行 awtk-linux-fb。要运行 awtk-linux-fb 需要满足两个条件: 5 | 6 | * 启动到 level 3,进入字符模式。 7 | 8 | * 开启 vga 字符模式,同时指定 framebuffer 的分辨率。 9 | 10 | 为了做到以上两点,我们需要给 grub 增加一个菜单。用 vim 编辑 grub.cfg: 11 | 12 | ``` 13 | sudo vim /boot/grub/grub.cfg 14 | ``` 15 | 16 | 把当前的缺省菜单拷贝一份,并作如下修改: 17 | 18 | * 修改菜单标题。 19 | 20 | * linux 在启动参数的最后添加下面的参数。 21 | 22 | ``` 23 | vga=788 3 24 | ``` 25 | 26 | > vga 用来设置 framebuffer 的分辨率。取值请参考:http://pierre.baudu.in/other/grub.vga.modes.html 27 | 28 | > 3 表示不进入桌面模式。 29 | 30 | 示例: 31 | 32 | ``` 33 | menuentry 'Ubuntu, with Linux 5.3.0-51-vga' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.3.0-51-generic-advanced-8e398504-f63e-4a7d-8d2e-8c839bc28666' { 34 | recordfail 35 | load_video 36 | gfxmode $linux_gfx_mode 37 | insmod gzio 38 | if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi 39 | insmod part_msdos 40 | insmod ext2 41 | set root='hd0,msdos1' 42 | if [ x$feature_platform_search_hint = xy ]; then 43 | search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 8e398504-f63e-4a7d-8d2e-8c839bc28666 44 | else 45 | search --no-floppy --fs-uuid --set=root 8e398504-f63e-4a7d-8d2e-8c839bc28666 46 | fi 47 | echo 'Loading Linux 5.3.0-51-generic ...' 48 | linux /boot/vmlinuz-5.3.0-51-generic root=UUID=8e398504-f63e-4a7d-8d2e-8c839bc28666 ro find_preseed=/preseed.cfg auto noprompt priority=critical locale=en_US quiet vga=788 3 49 | echo 'Loading initial ramdisk ...' 50 | initrd /boot/initrd.img-5.3.0-51-generic 51 | } 52 | ``` 53 | 54 | 把菜单等待时间修改为 10s : 55 | 56 | ``` 57 | if [ "${recordfail}" = 1 ] ; then 58 | set timeout=30 59 | else 60 | if [ x$feature_timeout_style = xy ] ; then 61 | set timeout_style=hidden 62 | set timeout=10 63 | # Fallback hidden-timeout code in case the timeout_style feature is 64 | # unavailable. 65 | elif sleep --interruptible 0 ; then 66 | set timeout=10 67 | fi 68 | fi 69 | ``` 70 | 71 | 保存退出,重新启动系统。 72 | 73 | 在开机时,按下 Esc 键。选择上面所加的菜单项: 74 | 75 | ![](images/menu1.png) 76 | 77 | ![](images/menu2.png) 78 | 79 | 进入命令行模式后,由于分辨率不高,操作不方便。建议安装 sshd 服务,在 host 端,用 ssh 终端连接上来工作。 80 | 81 | ``` 82 | sudo apt-get install openssh-server 83 | ``` 84 | 85 | > 以上 Ubuntu 18 为例子,其它 linux 系统请自行调整。 -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | find awtk-port -name \*.c -exec clang-format -i {} \; 2 | find awtk-port -name \*.h -exec clang-format -i {} \; 3 | 4 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #example: ./release.sh ../awtk-examples/HelloWorld-Demo exename 4 | 5 | # 在应用程序目录下运行: 6 | # ~/work/awtk-root/awtk-linux-fb/release.sh . demo 7 | 8 | AWTK_LINUX_FB_DIR="$(dirname "${BASH_SOURCE[0]}")" 9 | AWTK_LINUX_FB_DIR="$(cd "$AWTK_LINUX_FB_DIR" && pwd)" 10 | AWTK_DIR=$AWTK_LINUX_FB_DIR"/../awtk" 11 | 12 | EXE_NAME=demoui 13 | APP_ROOT=$AWTK_DIR 14 | 15 | if [ $1 ]; then 16 | if [ ! -d $1 ]; then 17 | echo "input dir : $1 is not exist!" 18 | exit 19 | fi 20 | APP_ROOT=$1 21 | fi 22 | 23 | if [ $2 ]; then 24 | EXE_NAME=$2 25 | fi 26 | 27 | echo "EXE_NAME = ${EXE_NAME}" 28 | echo "APP_ROOT = ${APP_ROOT}" 29 | 30 | rm -rf release release.tar.gz 31 | python3 $AWTK_DIR/scripts/release.py ${EXE_NAME} ${APP_ROOT} 32 | cp -rvf $AWTK_LINUX_FB_DIR/config release/config 33 | 34 | tar -czf release.tar.gz release/ 35 | -------------------------------------------------------------------------------- /release_zlg_im287a.sh: -------------------------------------------------------------------------------- 1 | scons -j 4 2 | ./release.sh 3 | scp release.tar.gz root@192.168.1.136:/opt/awtk 4 | 5 | -------------------------------------------------------------------------------- /scons_argv.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | global INIT 5 | INIT = False 6 | 7 | COMPILE_CONFIG = { 8 | 'OUTPUT_DIR' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compiled export directory '], 'help_info' : 'set awtk-linux-fb compiled export directory, default value is None, None is system\'s value'}, 9 | 'OS_FLAGS' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile flags', '..example: OS_FLAGS = " -flag1 -flag2 "'], 'help_info' : 'set compile\'s flags, so care of system and compile tools'}, 10 | 'OS_LINKFLAGS' : { 'value' : None, 'type' : str.__name__, 'desc' : ['link flags', '..example: OS_LINKFLAGS = " -flag1 -flag2 "'], 'help_info' : 'set compile\'s link flags, so care of system and compile tools'}, 11 | 'OS_LIBS' : { 'value' : [], 'type' : list.__name__, 'desc' : ['compile libs', '..example: OS_LIBS = ["lib1", "lib2"]'], 'help_info' : 'set compile\'s libs, so care of system and compile tools, use \',\' split muliple libraries '}, 12 | 'OS_LIBPATH' : { 'value' : [], 'type' : list.__name__, 'desc' : ['compile lib paths', '..example: OS_LIBPATH = ["/path/to/libdir1", "/path/to/libdir2"]'], 'help_info' : 'set compile\'s lib paths, so care of system and compile tools, use \',\' split muliple librarie\'s paths '}, 13 | 'OS_CPPPATH' : { 'value' : [], 'type' : list.__name__, 'desc' : ['compile include paths', '..example: OS_CPPPATH = ["/path/to/incdir1", "/path/to/incdir2"]'], 'help_info' : 'set compile\'s include paths, so care of system and compile tools, use \',\' split muliple include path '}, 14 | 'TOOLS_CC' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix CC\'s name'], 'help_info' : 'set compile tools prefix CC\'s name, TOOLS_CC=XXXXX, CC=TOOLS_PREFIX+TOOLS_CC '}, 15 | 'TOOLS_CXX' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix CXX\'s name'], 'help_info' : 'set compile tools prefix CXX\'s name, TOOLS_CXX=XXXXX, CXX=TOOLS_PREFIX+TOOLS_CXX '}, 16 | 'TOOLS_LD' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix LD\'s name'], 'help_info' : 'set compile tools prefix LD\'s name, TOOLS_LD=XXXXX, LD=TOOLS_PREFIX+TOOLS_LD '}, 17 | 'TOOLS_AR' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix AR\'s name'], 'help_info' : 'set compile tools prefix AR\'s name, TOOLS_AR=XXXXX, AR=TOOLS_PREFIX+TOOLS_AR '}, 18 | 'TOOLS_STRIP' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix STRIP\'s name'], 'help_info' : 'set compile tools prefix STRIP\'s name, TOOLS_STRIP=XXXXX, STRIP=TOOLS_PREFIX+TOOLS_STRIP '}, 19 | 'TOOLS_RANLIB' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix RANLIB\'s name'], 'help_info' : 'set compile tools prefix RANLIB\'s name, TOOLS_RANLIB=XXXXX, RANLIB=TOOLS_PREFIX+TOOLS_RANLIB '}, 20 | 'TOOLS_PREFIX' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compile tools prefix path', '..example: TOOLS_PREFIX = "/path/to/arm-linux-gnueabihf-"'], 'help_info' : 'set compile tools prefix path, value allow set \'\''}, 21 | 'TSLIB_LIB_DIR' : { 'value' : None, 'type' : str.__name__, 'desc' : ['tslib lib path', '..example: TSLIB_LIB_DIR = "/path/to/tslib/lib"'], 'help_info' : 'set use tslib lib path, value allow set \'\''}, 22 | 'TSLIB_INC_DIR' : { 'value' : None, 'type' : str.__name__, 'desc' : ['tslib include path', '..example: TSLIB_INC_DIR = "/path/to/tslib/include"'], 'help_info' : 'set use tslib lib path, value allow set \'\''}, 23 | 'ENABLE_CURSOR' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['enable cursor mouse'], 'help_info' : 'set enable cursor mouse, value is true or false'}, 24 | 'INPUT_ENGINE' : { 'value' : None, 'type' : str.__name__, 'desc' : ['null/spinyin/t9/t9ext/pinyin', '..example: INPUT_ENGINE = "pinyin"'], 'help_info' : 'set awtk use input engine' }, 25 | 'VGCANVAS' : { 'value' : None, 'type' : str.__name__, 'desc' : ['NANOVG/NANOVG_PLUS/CAIRO', '..example: VGCANVAS = "NANOVG"'], 'help_info' : 'set awtk use render vgcanvas type' }, 26 | 'DEBUG' : { 'value' : False, 'type' : bool.__name__, 'desc' : ['awtk\'s compile is debug'], 'help_info' : 'awtk\'s compile is debug, value is true or false' }, 27 | 'APP' : { 'value' : None, 'type' : str.__name__, 'save_file' : False, 'desc' : ['build this app'], 'help_info' : 'set app is build, value is app\'s root' }, 28 | 'LCD_DEVICES' : { 'value' : None, 'type' : str.__name__, 'desc' : ['linux\'s lcd devices type, value is fb/drm/wayland/egl_for_fsl/egl_for_x11/egl_for_gbm/egl_for_wayland', '..example: LCD_DEVICES = "fb"'], 'help_info' : 'when building, use linux\'s lcd devices type, value is fb/drm/wayland/egl_for_fsl/egl_for_x11/egl_for_gbm/egl_for_wayland' }, 29 | 'BUILD_TOOLS' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['build awtk\'s linux-fb\'s tools'], 'help_info' : 'build awtk\'s linux-fb\'s tools, value is true or false' }, 30 | 'BUILD_DEMOS' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['build awtk\'s linux-fb\'s demos'], 'help_info' : 'build awtk\'s linux-fb\'s demos, value is true or false' }, 31 | 'PLATFORM' : { 'value' : None, 'type' : str.__name__, 'desc' : ['build awtk\'s linux-fb\'s operation platform'], 'help_info' : 'build awtk\'s linux-fb\'s operation platform value is linux/android, value default is linux' }, 32 | 'EXTERN_CODE' : { 'value' : None, 'type' : str.__name__, 'desc' : ['add extern code list'], 'help_info' : 'when build awtk\'s linux-fb\, user add extern code list, example is EXTERN_CODE=XXXXX/*.c,XXXXX/*.c , use \',\' split muliple libraries' }, 33 | 'WITH_G2D' : { 'value' : False, 'type' : bool.__name__, 'desc' : ['enable g2d model '], 'help_info' : 'enable awtk\'s g2d model, value is true or false' }, 34 | "WITH_CUSTOM_GRAPHIC_BUFFER" : { 'value' : False, 'type' : bool.__name__, 'desc' : ['use custom graphic_buffer '], 'help_info' : 'disable awtk default graphic_buffer and use custom graphic_buffer, value is true or false' }, 35 | 'WAYLAND_SCANNER_PATH' : { 'value' : None, 'type' : str.__name__, 'desc' : ['wayland_scanner path'], 'help_info' : 'set the path of wayland_scanner' }, 36 | } 37 | 38 | CWD = os.path.normpath(os.path.abspath(os.path.dirname(__file__))); 39 | SCRIPT_ROOT = os.path.normpath(os.path.join(CWD, '../awtk/scripts')) 40 | sys.path.append(SCRIPT_ROOT) 41 | 42 | if not os.path.exists(os.path.normpath(os.path.join(SCRIPT_ROOT, 'compile_config.py'))) : 43 | sys.exit("this is linux-fb must use new AWTK version !!!!!!!!!!") 44 | 45 | import compile_config 46 | 47 | def get_compile_config() : 48 | global INIT 49 | if INIT : 50 | return compile_config.get_curr_config() 51 | else : 52 | INIT = True 53 | compile_helper = compile_config.get_curr_config_for_awtk() 54 | return compile_helper 55 | 56 | 57 | def init(ARGUMENTS) : 58 | global INIT 59 | INIT = True 60 | compile_helper = compile_config.compile_helper() 61 | compile_helper.set_compile_config(COMPILE_CONFIG) 62 | compile_helper.try_load_default_config() 63 | compile_helper.scons_user_sopt(ARGUMENTS) 64 | compile_config.set_curr_config(compile_helper) 65 | -------------------------------------------------------------------------------- /scripts/project_scripts/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | APP_SCRIPTS_ROOT = os.path.abspath(os.path.dirname(__file__)) 4 | sys.path.insert(0, APP_SCRIPTS_ROOT) 5 | -------------------------------------------------------------------------------- /scripts/project_scripts/release.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import platform 4 | import shutil 5 | import json 6 | import collections 7 | import fnmatch 8 | 9 | PRJ_DIR = os.getcwd(); 10 | OUTPUT_DIR = os.path.join(PRJ_DIR, 'release') 11 | FILE_DIR_PATH = os.path.abspath(os.path.dirname(__file__)) 12 | BIN_DIR = os.path.join(os.getcwd(), 'bin') 13 | AWTK_ROOT = os.path.join(FILE_DIR_PATH, '../../../awtk') 14 | 15 | def release(): 16 | import imp 17 | awtk_scripts_root = os.path.abspath(os.path.join(AWTK_ROOT, 'scripts')) 18 | print(awtk_scripts_root) 19 | sys.path.insert(0, awtk_scripts_root) 20 | file, path, desc = imp.find_module('release', [os.path.join(awtk_scripts_root, 'project_scripts')]) 21 | release_helper = imp.load_module('release', file, path, desc) 22 | copyLinuxFBConfigFiles() 23 | 24 | def ignore_patterns_list(patterns_list): 25 | def _ignore_patterns(path, names): 26 | ignored_names = [] 27 | for pattern in patterns_list: 28 | ignored_names.extend(fnmatch.filter(names, pattern)) 29 | return set(ignored_names) 30 | return _ignore_patterns 31 | 32 | def read_file(filename): 33 | content = '' 34 | if sys.version_info >= (3, 0): 35 | with open(filename, 'r', encoding='utf8') as f: 36 | content = f.read() 37 | else: 38 | with open(filename, 'r') as f: 39 | content = f.read() 40 | return content 41 | 42 | def copyLinuxFBConfigFiles() : 43 | uses_sdk_path = os.path.join(BIN_DIR, 'uses_sdk.json') 44 | content = read_file(uses_sdk_path) 45 | uses_sdk = json.loads(content, object_pairs_hook=collections.OrderedDict) 46 | if 'linux_fb' in uses_sdk['compileSDK']['awtk'] : 47 | if uses_sdk['compileSDK']['awtk']['linux_fb'] : 48 | dst_dir = os.path.join(OUTPUT_DIR, 'config') 49 | config_dir = os.path.join(uses_sdk['compileSDK']['awtk']['path'], 'config'); 50 | if os.path.exists(config_dir) : 51 | shutil.rmtree(dst_dir, True) 52 | ignore_files = ['*.md', '*.in'] 53 | shutil.copytree(config_dir, dst_dir, ignore=ignore_patterns_list(ignore_files)) 54 | 55 | release() 56 | --------------------------------------------------------------------------------