Qt5.7 Qt for Embedded Linux

从Qt5.0开始,Qt不再包含自己的视窗系统了(QWS)。对于单屏幕的情况,使用QtPlatform Abstraction是一个很好的选择。多屏的情况可以通过Wayland实现。

         有许多跨平台的插件可以使用:EGLFS,LinuxFB,KMS,DirectFB,Wayland。可以通过配置Qt使用这些插件。默认的平台插件是特殊设备。例如,许多板子默认使用eglfs。如果默认的不合适,可以通过修改QT_QPA_PLATFORM环境变量来设置另一个插件。可选的,使用-platform 命令行也可以达到相同的效果。

配置一个特殊的设备

针对一个给定的设备平台编译Qt需要提供一个工具链和一个文件系统。另外,为了支持EGL和OpenGL ES2.0,一些设备需要特殊厂商修改的代码。这和非加速平台无关,例如,有些人使用LinuxFB,仅仅用于一些软件渲染。这就意味着Qt Quick 2的功能不可用,因为Qt Quick 2 使用OpenGL渲染。

qtbase/mkspecs/devices目录包含配置和图形配置代码。例如,linux-rasp-pi2-g++ mkspec目录包含编译设置使用可选的编译器和链接器标志用于Raspberry Pi 2设备。Mkspec还包含关于eglfs钩子的一些信息或者一个适合eglfs设备集成插件的一个参考。通过指定配置工具选项-device参数指定设备。后面的名称必须和devices目录下的一个子目录匹配。

下面是一个Raspberry Pi 2的配置示范。对于大多数嵌入式Linux板,配置命令是相似的:

./configure-release -opengl es2 -device linux-rasp-pi2-g++ -device-optionCROSS_COMPILE=$TOOLCHAIN/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf--sysroot $ROOTFS -prefix /usr/local/qt5

最重要的参数是-device和-sysroot,通过指定-sysroot,头文件和库文件用于配置的特征检测测试,也包含Qt本身,指定的路径是特定的目录,而不是主机PC标准路径。这就意味着安装开发包到哪一个主机环境没有关系。例如,为了获得libinput支持没有必要在主机上安装libinput开发头文件和库文件。取而代之,对应目标结构的头文件和库文件需要安装在sysroot中。

交叉编译的时候Pkg-config也是被支持的。Configure自动设置PKG_CONFIG_LIBDIR来使pkg-config报告基于sysroot的编译器和链接器设置而不是主机的设置。这通常不需要其它更多 的适配就可以工作得很好。然后,在运行configure之前,主机上的PKG_CONFIG_PATH环境变量必须unset。否则Qt组建可能会尝试使用主机上的不合适的头文件和库文件。

指定-sysroot自动的导致设置—sysroot参数。在一些情况下,这并不是希望的,这可以通过传递-no-gcc-sysroot 给configure来使之失效。

-prefix,-extprefix和-hostprefix控制qt组建时的目标目录。在上面的例子中,编译Arm上的Qt的目标板上的目录为/usr/local/qt5。注意,运行make install不部署任何东西到设备上。如果不设置extprefix,默认的安装目录为sysroot+prefix,然而有些时候我们不希望放到sysroot目录下,可以通过指定-extprefix目录来指定目标目录。最后,-hostprefix允许指定生成的主机工具比如:qmake,rcc uic,如果不指定-hostprefix 将会安装在extprefix目录下。

嵌入式linux设备的平台插件

EGLFS

EGL是OpenGL和本地视窗系统中间的一个接口。Qt可以使用EGL作为context和surface管理,然而,API包含非指定平台部分:本地视窗的创建必须通过特定平台的方式创建。因此,就需要对板子或者指定GPU修改代码。有两种修改的方式:一种是通过eglfs hooks,这种方式可以是一个单源文件编译进平台插件中,第二种方式就是动态加载EGL设备集成插件。

EGLFS是一个为了Qt5应用运行的平台插件,Qt5运行在EGL和OpenGL ES2.0之上而且没有真实的视窗系统(比如 X11 Wayland)。对于Qt Quick 2和本地OpenGL应用,它也支持软件渲染视窗(例如QWidget)。在OpenGL应用中,widget的内容是使用CPU转化为图像渲染的,然后通过这个插件上传到纹理和混合。

这就是为什么当代嵌入式Linuxy设备建议包含一个GPU的原因。EGLFS强制第一个顶级窗口(QWidget或者QQucikView)为全屏。这个窗口也被选择成为根widget窗口,其它的顶级窗口(例如对话框,弹出菜单或者下拉菜单)都放入第一个窗口中。这很有必要,因为使用EGLFS总有一个真实存在的本地窗口和EGL窗口外观,并且其它的都属于第一个创建的widget或者window. 这种方式可以工作得很好,有一个主窗口存在在整个应用的生命周期里,其它的后来创建的所有的窗口都属于第一个窗口。

有更多的基于OpenGL视窗的限制。Qt 5.3,eglfs支持一个单全屏GL窗口(比如,一个基于OpenGL的QWindow,QQuickView或者QGLWidget)。打开另外的OpenGL窗口或者混合有基于QWidget内容的窗口就不被支持了。它会关闭这个应用然后报一个错误消息。

如果有必要,eglfs可以通过使用以下环境变量进行配置:

l  QT_QPA_EGLFS_FB-覆盖Framebuffer设备。默认的配置是/dev/fb0。在很多嵌入式平台上这不是非常适宜的了,因为framebuffer仅用于查询设置比如显示尺寸。然而在有一些设备上,多屏显示设置中这些参数提供设定显示参数的能力,参数和LinuxFB中fb的参数相似。

l  QT_QPA_EGLFS_WIDTH和QT_QPA_EGLFS_HEIGHT-屏幕像素宽度和屏幕像素高度。当然eglfs尝试从framebuffer设备/dev/fb0中读取这些参数,但是有时会不工作,所以手动设置尺寸变得很有必要。

l  QT_QPA_EGLFS_PHYSICAL_WIDTH和QT_QPA_EGLFS_PHYSICAL_HEIGHT-屏幕宽度和高度物理尺寸,单位是毫米。有些平台没有/dev/fb0或者查询失败的情况,这些值使用默认的DPI=100计算宽和高,这个变量可以用于覆盖任何默认值。

l  QT_QPA_EGLFS_DEPTH-重置屏幕的颜色深度。在没有/dev/fb0设备结点的平台上或者查询失败的平台上,颜色的默认深度为32.这个变量可以用于修改默认值。注意这仅仅会影响QScreen报告的颜色深度值。它和EGL配置或者OpenGL的颜色深度无关。

l  QT_QPA_EGLFS_SWAPINTERVAL-默认的交换值为1。这将会同步垂直刷新。例如,设置间隔为0,将会尽最快的方式运行不带任何同步。

l  QT_QPA_EGLFS_FORCEVSYNC-设置该变量,eglfs请求RBIO_WAITFORVSYNC。

l  QT_QPA_EGLFS_FORCE888-设置该变量时,红绿蓝通道大小被忽略。强制设置每一个通道为8位。

l  QT_QPA_EGLFS_DEBUG-如果设置该变量,调试信息将会打印到调试输出口。

l  QT_QPA_EGLFS_INTERGRATION-除了编译进的hooks,能够提供设备或者厂商修改的可动态加载的插件。该环境变量指定一个特定的插件。

除了QT_QPA_EGLFS_DEBUG,eglfs还提供更多的日志系统。有以下几种日志方式:

l  qt.qpa.egldeviceintegration – Enables logging for dynamically loaded backends. Veryuseful to check what backend is in use.

l  qt.qpa.input – Enables debug output both from the evdev and libinput input handlers.Very useful to check if a given input device was recognized and opened.

l  qt.qpa.eglfs.kms – Enables verbose logging in the KMS/DRM backend.

LinuxFB

这个插件直接写framebuffer.仅支持软件渲染内容。注意在一些设置上,显示性能将被限制。

         Linuxfb插件允许指定额外的设置,传递参数QT_QPA_PLATFORM环境变量或者通过-platform命令行选项。例如,QT_QPA_PLATFORM=linuxfb:fb=/dev/fb1指定framebuffer设备/dev/fb1而不是fb0.可以指定多设置通过冒号分割。

l  fb=/dev/fbN –指定framebuffer设备。在多显示器设置上,这通常允许运行应用在不同的显示器上。

l  size=<width>x<height> -

l  mmsize=<width>x<height>

l  offset=<width>x<height>

l  nographicsmodeswitch –禁止切换虚拟终端到图形模式(KD_GRAPHICS),另外,切换到图形模式,闪烁的光标和空白屏也同样无效。当设置这个参数时,这些会被跳过。

l  tty=/dev/ttyN –重置虚拟控制台。仅当nographicsmodeswitch未设置时使用

Input

相对于没有视窗系统,鼠标、键盘、触摸板输入直接从evdev读取或者使用第三方的库实现比如libinput、tslib.这需要/dev/input/event*可以被用户读取。Eglfs和Linuxfb内部有所有的输入处理。

使用libinput

         Libinput是一个用于处理输入设备的库。相对于Qt直接读取evdev,它提供了另一种实现方式。为了使用libinput,配置编译Qt时需要准备libudev和libinput开发文件。如果使用键盘支持,xkbcommon也是必需的。Eglfs和linuxfb不需要其它额外的配置由于它们默认使用libinput.如果没有libinput支持或者QT_QPA_EGLFS_NO_LIBINPUT设置了。Qt将会使用它自己的evdevhandlers处理。

Eglfs和linuxfb不使用libinput

有一些环境变量可以进行设置,QT_QPA_EVDEV_MOUSE_PARAMETERS, QT_QPA_EVDEV_KEYBOARD_PARAMETERS以及QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS.

QT_QPA_EGLFS_DISABLE_INPUT 禁用输入

QT_QPA_FB_DISABLE_INPUT禁用输入

QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS

鼠标输入

鼠标光标会一直显示,除非设置QT_QPA_EGLFS_HIDECURSOR (for eglfs) 或者QT_QPA_FB_HIDECURSOR (for linuxfb),Qt的基于libudev的设备会查看报告,报告中至少有一个鼠标可用。如果不使用libudev,鼠标箭头会一直显示除非通过修改环境变量禁止显示。

只有使用libudev时才支持热插拔.它允许在应用运行的时候插拔鼠标。

键盘输入

Evdev键盘处理支持以下额外参数:

·                    /dev/input/... – 指定输入设备名称.如果未指定,Qt通过libudev查找一个合适的设备,或者遍历所有的设备结点查找一个合适的设备。

·                    grab – 允许抢占输入设备

·                    keymap – 指定键盘映射文件

·                    enable-compose - Enables compositing.

l  repeat-delay – 设置一个用户定义的按键重复延时

l  repeat-rate -设置一个用户定义的按键重复率.

在嵌入式linux系统的终端处理中,按键行为是被谁处理是未知的,因为输入事件既可以被Qt应用处理也可以被终端处理。为了解决这个问题,可以设置以下选项

l  在应用启动的时候设置tty键盘的模式K_OFF来禁用终端键盘处理,这将阻止键盘事件进入终端。有些情况下,标准键盘行为需要被重新载入,这里把QT_QPA_ENABLE_TERMINAL_KEYBOARD设置为1.注意:这仅仅从远程终端(ssh)启动一个应用时有用,终端键盘输入保持可用。

l  一个可选择的实现方式是使用udev键盘处理的grab参数,QT_QPA_EVDEV_KEYBOARD_PARAMETERS的参数grab=1.这将导致抢占一次输入设备,如果抢占成功,系统中的其它组件就不会收到键盘事件。这种方式更适合于从远程启动的应用,因为不需要获取tty设备。

l  Finally, for many specialized Embedded Linux images it does not makesense to have the standard terminal sessions enabled in the first place. Referto your build environment's documentation on how to disable them. For example,when generating images using the Yocto Project, unsetting SYSVINIT_ENABLED_GETTYS results in having no getty process running, andthus no input, on any of the virtual terminals.

如果内建的键盘映射不能满足要求,可以使用eglfs的loadKeymap()函数或者使用keymap参数来加载一个键盘映射文件。LoadKeyMap()允许在程序运行时改变键盘映射。注意,这需要使用eglfs内部的键盘处理,如果键盘处理是通过-plugin命令行参数的方式加载的不可以使用loadkeymap().

    注意:特殊系统的键盘组合现在不被支持会被忽略比如(Ctrl+Alt+Fx) (Ctrl+Alt+Backspace

    生成一个自定义键盘映射,可以使用kmap2qmap工具。这个工具在qttools模块里。源文件必须是标准Linux kmap格式,这种格式可以被内核的loadkeys命令理解。也就是说可以使用以下源来生成qmap文件:

 

·        The LinuxConsole Tools (LCT) project.

  • Xorg X11 keymaps 通过使用ckbcomp工具转化 kmap 格式
  • kamp文件是纯文本文件,可以手动编写。

Kmap2qmap是一个命令行程序,至少需要两个文件参数最后一个是生成的.qmap文件,其它所有的参数都将作为输入的.kmap文件。例如:

kmap2qmapi386/qwertz/de-latin1-nodeadkeys.kmap include/compose.latin1.incde-latin1-nodeadkeys.qmap

注意:kmap2qmap并不能支持Linux内核支持的所有的符号,当转化标准keymap文件时,会显示许多的警告信息Show_Registers, Hex_A等等;忽略这些信息即可。

触摸

对于一些电阻单点触摸屏,需要退回使用tslib。可以通过设置环境变量QT_QPA_EGLFS_TSLIB or QT_QPA_FB_TSLIB为1来启动tslib支持。设置TSLIB_TSDEVICE或者通过命令行传设备名称参数来改变设备。注意:tslib输入处理产生鼠标事件并仅支持单点触摸,与之相对的,evdevtouch产生真正的多点触摸QTouchEvent事件。

笔控板

Evdevtablet插件为Wacom和相似的pen-basedtables提供基础支持,它产生QTabletEvent事件。QT_QPA_GENERIC_PLUGINS=evdevtablet或者命令行传递参数-plugin evdevtablet来使能evdevtablet。该插件可以有一个设备结点参数,例如

QT_QPA_GENERIC_PLUGINS=evdevtablet:/dev/event1,这时Qt自动查找设备就不进行自动查找了。

调试输入设备

通过使能qt.qpa.input日志规则,可以打印一些调试信息输出。例如:设置QT_LOGGING_RULES环境变量qt.qpa.input=true。这对于检测哪一个设备被使用或者查找设备过程中的问题解决很有帮助。

使用用户写入鼠标光标图片

Eglfs使用它自己的32x32的鼠标图片。如果这不能满足,用户可以指定自己的图片,方法是设置QT_QPA_EGLFS_CURSOR环境变量,这个环境变量是一个JSON文件名称。这个文件也可以通过Qt资源文件嵌入到应用中。

例如:一个嵌入的鼠标光标使用8张鼠标图片,每一行可以进行如下指定:

{

   "image": ":/cursor-atlas.png",

   "cursorsPerRow": 8,

   "hotSpots": [

        [7, 2],

        [12, 3],

        [12, 12],

        ...

   ]

 }

注意:theimages are expected to be tightly packed in the atlas: the width and height ofthe cursors are decided based on the total image size and the cursorsPerRow setting. Atlases have to provide an image for all the supportedcursors.


以上是个人心血来潮翻译一下Qt的官方说明,这是本人第一次翻译英文,有很多地方不知道怎么翻译,大家凑合看吧。

技术交流群:589805575,欢迎志同道合者加入

猜你喜欢

转载自blog.csdn.net/chongzi865458/article/details/54406865
今日推荐