summaryrefslogtreecommitdiffstats
path: root/doc/src/platforms/emb-linux.qdoc
blob: 19816f85c78d8c78347687eacc906ce1df77434f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
  \page embedded-linux.html
  \title Qt for Embedded Linux
  \brief Provides information about Embedded Linux support in Qt.
  \ingroup supportedplatform

  On Embedded Linux systems, there are multiple platform plugins that you can
  use: EGLFS, LinuxFB, DirectFB, or Wayland. However, the availability of these
  plugins depend on how Qt is configured.

  EGLFS is the default plugin on many boards. If it's not suitable, use the
  \c QT_QPA_PLATFORM environment variable to request another plugin.
  Alternatively, for quick tests, use the \c -platform command-line argument
  with the same syntax.

  \note As of Qt 5.0, Qt no longer has its own window system (QWS)
  implementation. For single-process use cases, the \l{Qt Platform Abstraction}
  is a superior solution; multi-process use cases are supported through
  \l{Qt Wayland Compositor}{Wayland}.

  \section1 Platform Plugins for Embedded Linux Devices

  \target embedded eglfs
  \section2 EGLFS

  \l {http://www.khronos.org/egl}{EGL} is an interface between OpenGL and the
  native windowing system. Qt can use EGL for context and surface management,
  however the API contains no platform-specifics. Creating a \e {native window},
  which won't necessarily be an actual window on the screen, must still be
  done by platform-specific means. This is why we need the board or GPU-specific
  adaptation code. Typically, these adaptations are provided as:

  \list
    \li \e{EGLFS hooks} -- a single source file compiled into the platform
        plugin
    \li \e{EGL device integration} -- dynamically loaded plugins
  \endlist

  EGLFS is a platform plugin for running Qt5 applications on top of EGL and
  OpenGL ES 2.0, without an actual windowing system like X11 or Wayland. In
  addition to Qt Quick 2 and native OpenGL applications, EGLFS supports
  software-rendered windows, like QWidget, too. For QWidget, the widgets'
  contents are rendered using the CPU into images, which are then
  uploaded into textures and composited by the plugin.

  EGLFS is the recommended plugin for modern Embedded Linux devices that
  include a GPU.

  EGLFS forces the first top-level window - either a QWidget or a QQuickView
  - to become fullscreen. This window is also chosen to be the \e root widget
  window into which all other top-level widgets are composited. For example,
  dialogs, popup menus, or combo boxes. This behavior is necessary because
  with EGLFS there is always exactly one native window and one EGL window
  surface; these belong to the widget or window that is created first. This
  approach works well when there is a main window that exists for the
  application's lifetime and all other widgets are either non top-levels or are
  created afterwards, once the main window is shown.

  There are further restrictions for OpenGL-based windows. EGLFS supports a
  single single fullscreen GL window (as of Qt 5.3), like OpenGL-based QWindow,
  a QQuickView, or a QOpenGLWidget. Opening additional OpenGL windows or mixing
  such windows with QWidget-based content isn't supported; Qt terminates the
  application with an error message.

  If necessary, \c eglfs can be configured using the following environment
  variables:

  \table 100%
    \header
      \li Environment Variable
      \li Description
    \row
      \li \c {QT_QPA_EGLFS_INTEGRATION}
      \li In addition to the compiled-in \e hooks, it is also possible to use
          dynamically loaded plugins to provide device or vendor-specific
          adaptation. This environment variable enforces a specific plugin.
          For example, setting it to \e{eglfs_kms} uses the KMS/DRM backend.
          This is only an option when no static or compiled-in hooks were
          specified in the device makespecs. In practice, the traditional
          compiled-in hooks are rarely used, almost all backends are now
          migrated to plugins. The device makespecs still contain a relevant
          \c EGLFS_DEVICE_INTEGRATION entry: the name of the preferred backend
          for that particular device. This is optional, but very useful to
          avoid the need to set this environment variable if there are more
          than one plugin present in the target system. In a desktop
          environment the KMS or X11 backends are prioritized, depending on
          the presence of the \c DISPLAY environment variable.
          \note On some boards a special value of \c none is used instead
          of an actual plugin. This indicates that no special integration is
          necessary to use EGL with the framebuffer; no plugins must be loaded.
    \row
      \li \c {QT_QPA_EGLFS_PHYSICAL_WIDTH} and \c {QT_QPA_EGLFS_PHYSICAL_HEIGHT}
      \li Specifies the physical screen's width and height in millimeters. On
          platforms where the value can't be queried from the framebuffer
          device \e{/dev/fb0} or via other means, a default DPI of 100 is used.
          Use this variable to override any such defaults. Setting this variable
          is important because QWidget- or Qt Quick Controls-based applications
          rely on these values. Running these applications with the hard-coded
          settings may result in user interface elements with sizes that are
          unsuitable for the display in use.
    \row
      \li \c {QT_QPA_EGLFS_ROTATION}
      \li Specifies the rotation applied to software-rendered content in
          QWidget-based applications. Supported values are 180, 90, and -90.
          This variable does not apply to OpenGL-based windows, including Qt
          Quick. Qt Quick applications can apply transformations in their QML
          scene instead. The standard \c eglfs mouse cursor always takes the
          value into account, with an appropriately positioned and rotated
          pointer image, regardless of the application type. However, special
          cursor implementations, such as the KMS/DRM backend's hardware
          cursor, may not support rotation.
    \row
      \li \c {QT_QPA_EGLFS_FORCEVSYNC}
      \li When set, \c eglfs requests \c FBIO_WAITFORVSYNC on the framebuffer
          device after each call to eglSwapBuffers(). This variable is only
          relevant for backends relying on the legacy Linux \c fbdev subsystem.
          Normally, with a default swap interval of 1, Qt assumes that calling
          eglSwapBuffers() takes care of vsync; if it doesn't (for example,
          due to driver bugs), try setting \c QT_QPA_EGLFS_FORCEVSYNC to a
          non-zero value.
    \row
      \li \c {QT_QPA_EGLFS_FORCE888}
      \li When set, the red, green, and blue color channel sizes are ignored
          when \c eglfs creates a new context, window or offscreen surface.
          Instead, the plugin requests a configuration with 8 bits per channel.
          This can be helpful on devices where configurations with less than 32
          or 24 bits per pixel (for example, 5-6-5 or 4-4-4) are chosen by
          default despite knowing they are not ideal, for example, due to
          banding effects. Instead of changing application code, this variable
          provides a shortcut to force 24 or 32 bpp configurations.
  \endtable

  Additionally, the following less commonly used variables are available:

  \table 100%
    \header
      \li Environment Variable
      \li Description
    \row
      \li \c {QT_QPA_EGLFS_FB}
      \li Overrides the framebuffer device. The default is \c /dev/fb0. On most
          embedded platforms this variable isn't very relevant because the
          framebuffer is used only to query settings like the display
          dimensions. However, on certain devices, this variable provides the
          ability to specify which display to use in multiple display setups,
          similar to the \c fb parameter in LinuxFB.
    \row
      \li \c {QT_QPA_EGLFS_WIDTH} and \c {QT_QPA_EGLFS_HEIGHT}
      \li Contains the screen's width and height in pixels. While \c eglfs
          tries to determine the dimensions from the framebuffer device
          \e{/dev/fb0}, this doesn't always work. It may be necessary to
          manually specify the sizes.
    \row
      \li \c {QT_QPA_EGLFS_DEPTH}
      \li Overrides the color depth for the screen. On platforms where the
          framebuffer device \e{/dev/fb0} is not available or the query is not
          successful, a default of \c 32 is used. Use this variable to override
          any such defaults.
          \note This variable only affects the color depth value reported by
          QScreen. It has no connection to EGL configurations and the color
          depth used for OpenGL rendering.
    \row
      \li \c {QT_QPA_EGLFS_SWAPINTERVAL}
      \li By default, a swap interval of \c 1 is requested. This variable
          enables synchronizing to the display's vertical refresh. Use this
          variable to override the swap interval's value. For instance, passing
          0 disables blocking on swap, resulting in running as fast as possible
          without any synchronization.
    \row
      \li \c {QT_QPA_EGLFS_DEBUG}
      \li When set, some debugging information is printed on the debug output.
          For example, the input QSurfaceFormat and the properties of the
          chosen EGL configuration are printed while creating a new context.
          When used together with Qt Quick's \c {QSG_INFO} variable, you can
          get useful information for troubleshooting issues related to the EGL
          configuration.
  \endtable

  In addition to \c {QT_QPA_EGLFS_DEBUG}, \c eglfs also supports Qt's modern
  categorized logging system. The following logging categories are available:

  \list

    \li \c qt.qpa.egldeviceintegration – Enables logging for dynamically loaded
        backends. Use this category to check what backend is in use.
    \li \c qt.qpa.input – Enables debug output both from the \c evdev and
        \c libinput input handlers. Use this category to check if a given input
        device was recognized and opened.
    \li \c qt.qpa.eglfs.kms – Enables verbose logging in the KMS/DRM backend.
  \endlist

  After running \c configure, make sure to inspect its output. This is the
  easiest, quickest way to identify whether you have the necessary EGLFS
  backend, libudev, or libinput enabled. In short, if there's an undesired
  "no" in your \c configure output, run:

  \code
  ./configure -v
  \endcode

  to turn on the verbose output, so that you can see the compiler and linker
  invocations for each configure test.

  \note If you encounter errors about missing headers, libraries, or seemingly
  cryptic linker failures, often, they are a sign of an incomplete or broken
  sysroot and isn't related to Qt.

  As an example, when targeting the Raspberry Pi with the Broadcom proprietary
  graphics drivers, the output should contain something like the following:

  \badcode
    QPA backends:
    EGLFS ................................ yes
    EGLFS details:
      EGLFS i.Mx6 ........................ no
      EGLFS i.Mx6 Wayland ................ no
      EGLFS EGLDevice .................... no
      EGLFS GBM .......................... no
      EGLFS Mali ......................... no
      EGLFS Rasberry Pi .................. yes
      EGL on X11 ......................... no
  \endcode

  If this is not the case, it's not advisable to proceed further with the build
  since accelerated graphics won't be functional without the Raspberry
  Pi-specific backend, even if the rest of Qt compiles successfully.

  \section2 LinuxFB

  This plugin writes directly to the framebuffer via Linux's fbdev subsystem.
  Only software-rendered content is supported. Note that on some setups
  the display performance is expected to be limited.

  However, since fbdev is being deprecated in the Linux kernel, the DRM dumb
  buffer support is also available, as of Qt 5.9. To use it, set the
  \c QT_QPA_FB_DRM environment variable to a non-zero value. When set, provided
  that dumb buffers are supported by your system, legacy framebuffer devices
  like \c{/dev/fb0} won't be accessed. Instead, the rendering is set up via the
  DRM APIs, similar to the \c{eglfs_kms} backend in EGLFS. The output is
  double-buffered and page flipped, providing proper vsync for
  software-rendered content as well.

  \note When dumb buffers are in use, none of the options described below are
  applicable since properties like physical and logical screen sizes are all
  queried automatically.

  The \c linuxfb plugin allows you to specify additional settings via the
  \c QT_QPA_PLATFORM environment variable or \c -platform command-line option.
  For example, \c {QT_QPA_PLATFORM=linuxfb:fb=/dev/fb1} specifies that the
  framebuffer device \c /dev/fb1 must be used instead of the default \c fb0.
  To specify multiple settings, separate the mwith a colon (:).

  \table
    \header
      \li Settings
      \li Description
    \row
      \li \c {fb=/dev/fbN}
      \li Specifies the framebuffer devices. On multiple display setups,
          this setting allows you to run the application on different displays.
          Currently, there's no way to use multiple framebuffers from one Qt
          application.
    \row
      \li \c{size=}\e{<width>}\c{x}\e{<height>}
      \li Specifies the screen size in pixels. The plugin tries to query the
          display dimensions, both physical and logical, from the framebuffer
          device. However, this query may not always lead to proper results;
          it may be necessary to specify the values explicitly.
    \row
      \li \c{mmsize=}\e{<width>}\c{x}\e{<height>}
      \li Specifies the physical width and height in millimeters.
    \row
      \li \c{offset=}\e{<width>}\c{x}\e{<height>}
      \li Specifies the top-left corner of the screen offset in pixels. The
          default position is at \c{(0, 0)}.
    \row
      \li \c {nographicsmodeswitch}
      \li Specifies not to switch the virtual terminal to graphics mode
          (\c KD_GRAPHICS). Typically, \e enabling graphics mode disables the
          blinking cursor and screen blanking. However, when this parameter is
          set, those two features are also skipped.
    \row
      \li \c {tty=/dev/ttyN}
      \li Overrides the virtual console. Only used when \c{nographicsmodeswitch}
          isn't set.
  \endtable

  As of Qt 5.9, the behavior of EGLFS and LinuxFB have been synchronized, with
  regards to the window sizing policy: the first top-level window is forced to
  cover the entire screen, with both platform plugins. If this is not desired,
  set the \c{QT_QPA_FB_FORCE_FULLSCREEN} environment variable to \c 0 to
  restore the behavior from earlier Qt versions.

  \section1 Input

  When no windowing system is present, the mouse, keyboard, and touch input are
  read directly via \c evdev or using helper libraries such as \c libinput or
  \c tslib.  Note that this requires that device nodes \c {/dev/input/event*} are
  readable by the user. \c eglfs and \c linuxfb have all the input handling code
  compiled-in.

  \section2 Using libinput

  \l{http://www.freedesktop.org/wiki/Software/libinput}{libinput} is a library
  to handle input devices. It offers an alternative to the Qt's own \c evdev
  input support. To enable using \c libinput, make sure the development files
  for \c libudev and \c libinput are available when configuring and building
  Qt. \c xkbcommon is also necessary if keyboard support is desired. With
  \c eglfs and \c linuxfb no further actions are necessary as these plugins use
  \c libinput by default. If \c libinput support is not available or the
  environment variable \c QT_QPA_EGLFS_NO_LIBINPUT is set, Qt's own evdev
  handlers come in to play.

  \section2 Input on eglfs and linuxfb without libinput

  Parameters like the device node name can be set in the environment variables
  \c QT_QPA_EVDEV_MOUSE_PARAMETERS, \c QT_QPA_EVDEV_KEYBOARD_PARAMETERS and
  \c QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS. Separate the entries with colons.  These
  parameters act as an alternative to passing the settings in the \c{-plugin}
  command-line argument, and with some backends they are essential: eglfs and
  linuxfb use built-in input handlers so there is no separate \c {-plugin}
  argument in use.

  Additionally, the built-in input handlers can be disabled by setting
  \c QT_QPA_EGLFS_DISABLE_INPUT or \c QT_QPA_FB_DISABLE_INPUT to \c 1.

  \section2 Mouse

  The mouse cursor shows up whenever \c QT_QPA_EGLFS_HIDECURSOR (for eglfs)
  or \c QT_QPA_FB_HIDECURSOR (for linuxfb) is not set and Qt's libudev-based
  device discovery reports that at least one mouse is available. When \c libudev
  support is not present, the mouse cursor always show up unless explicitly
  disabled via the environment variable.

  Hot plugging is supported, but only if Qt was configured with \c libudev support
  (that is, if the \e libudev development headers are present in the sysroot at
  configure time). This allows connecting or disconnecting an input device while
  the application is running.

  The \e evdev mouse handler supports the following extra parameters:

  \list

  \li \c {/dev/input/...} - Specifies the name of the input device. When not
  given, Qt looks for a suitable device either via \e libudev or by walking
  through the available nodes.

  \li \c nocompress - By default, input events that do not lead to changing the
  position compared to the last Qt mouse event are compressed; a new Qt mouse
  event is sent only after a change in the position or button state.  This can
  be disabled by setting the \c nocompress parameter.

  \li \c dejitter - Specifies a jitter limit. By default dejittering is disabled.

  \li \c grab - When 1, Qt will grab the device for exclusive use.

  \li \c abs - Some touchscreens report absolute coordinates and cannot be
  differentiated from touchpads.  In this special situation pass \c abs to
  indicate that the device is using absolute events.

  \endlist

  \section2 Keyboard

  The \e evdev keyboard handler supports the following extra parameters:

  \list

  \li \c {/dev/input/...} - Specifies the name of the input device. When not
  given, Qt looks for a suitable device either via \e libudev or by walking
  through the available nodes.
  \li \c {grab} - Enables grabbing the input device.
  \li \c {keymap} - Specifies the name of a custom keyboard map file.
  \li \c {enable-compose} - Enables compositing.
  \li \c {repeat-delay} - Sets a custom key repeat delay.
  \li \c {repeat-rate} - Sets a custom key repeat rate.
  \endlist

  On Embedded Linux systems that do not have their terminal sessions disabled,
  the behavior on a key press can be confusing as input event is processed by
  the Qt application and the tty. To overcome this, the following options are
  available:

  \list

  \li \e EGLFS and \e LinuxFB attempt to disable the terminal keyboard on
  application startup by setting the tty's keyboard mode to \c K_OFF. This
  prevents keystrokes from going to the terminal. If the standard behavior needs
  to be restored for some reason, set the environment variable
  \c QT_QPA_ENABLE_TERMINAL_KEYBOARD to \c 1. Note that this works only when the
  application is launched from a remote console (for example, via \c ssh) and
  the terminal keyboard input remains enabled.

  \li An alternative approach is to use the \e evdev keyboard handler's \c grab
  parameter by passing \e{grab=1} in \c QT_QPA_EVDEV_KEYBOARD_PARAMETERS. This
  results in trying to get a grab on the input device. If the \c grab is
  successful, no other components in the system receive events from it as long as
  the Qt application is running. This approach is more suitable for applications
  started remotely as it does not need access to the tty device.

  \li Finally, for many specialized Embedded Linux images it does not make sense
  to have the standard terminal sessions enabled in the first place. Refer to
  your build environment's documentation on how to disable them. For example,
  when generating images using the \l {http://www.yoctoproject.org}{Yocto
  Project}, unsetting \c SYSVINIT_ENABLED_GETTYS results in having no
  \c getty process running, and thus no input, on any of the virtual terminals.

  \endlist

  If the default built-in keymap is not sufficient, a different one can be
  specified either via the \c keymap parameter or by using the eglfs-specific
  \l{QEglFSFunctions::loadKeymap()}{loadKeymap()} function. The latter allows
  switching the keymap at runtime. Note however that this requires using eglfs'
  built-in keyboard handler; it is not supported when the keyboard handler is
  loaded via the \c -plugin command-line parameter.

  \note Special system key combinations, such as console switching
  (\e{Ctrl+Alt+Fx}) or zap (\e{Ctrl+Alt+Backspace}) are not currently supported
  and are ignored.

  To generate a custom keymap, the \e kmap2qmap utility can be used. This can be
  found in the \e qttools module. The source files have to be in standard Linux
  \c kmap format, which is understood by the kernel's \c loadkeys command.
  This means one can use the following sources to generate \c qmap files:

  \list
  \li The \l {http://lct.sourceforge.net/}{Linux Console Tools (LCT)} project.
  \li \l {http://www.x.org/}{Xorg} X11 keymaps can be converted to the
  \c kmap format with the \c ckbcomp utility.
  \li As \c kmap files are plain-text files, they can also be hand crafted.
  \endlist

  \c kmap2qmap is a command line program, that needs at least 2 files as
  parameters.  The last one is the generated \c .qmap file, while all the
  others are parsed as input \c .kmap files.  For example:

  \badcode
  kmap2qmap i386/qwertz/de-latin1-nodeadkeys.kmap include/compose.latin1.inc de-latin1-nodeadkeys.qmap
  \endcode

  \note \c kmap2qmap does not support all the (pseudo) symbols that the Linux
  kernel supports.  When converting a standard keymap, a number of warnings will
  be shown regarding \c Show_Registers, \c Hex_A, and so on; these messages can
  safely be ignored.

  \section2 Touch

  For some resistive, single-touch touch screens it may be necessary to fall
  back to using \c tslib instead of relying on the Linux multi-touch protocol and
  the event devices. For modern touch screens this is not necessary. \c tslib
  support can be enabled by setting the environment variable
  \c QT_QPA_EGLFS_TSLIB or \c QT_QPA_FB_TSLIB to 1. To change the device, set the
  environment variable \c TSLIB_TSDEVICE or pass the device name on the
  command-line. Note that the \c tslib input handler generates mouse events and
  supports single touch only, as opposed to \c evdevtouch which generates true
  multi-touch QTouchEvent events too.

  The \e evdev touch handler supports the following extra parameters:

  \list

  \li \c {/dev/input/...} - Specifies the name of the input device. When not
  given, Qt looks for a suitable device either via \e libudev or by walking
  through the available nodes.

  \li \c rotate - On some touch screens the coordinates must be rotated, which
  is done by setting \c rotate to 90, 180, or 270.

  \li \c invertx and \c inverty - To invert the X or Y coordinates in the input
  events, pass \c invertx or \c inverty.

  \endlist

  For example, doing \c{export
  QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event5:rotate=180} before
  launching applications results in an explicitly specified touch device and
  flipping the coordinates - useful when the orientation of the actual
  screen and the touch screen do not match.

  \section2 Pen-based tablets

  The \c evdevtablet plugin provides basic support for Wacom and similar,
  pen-based tablets. It generates QTabletEvent events only. To enable it,
  pass \c {QT_QPA_GENERIC_PLUGINS=evdevtablet} in the environment or,
  alternatively, pass \c {-plugin evdevtablet} argument on the command-line.
  The plugin can take a device node parameter, for example
  \c{QT_QPA_GENERIC_PLUGINS=evdevtablet:/dev/event1}, in case the Qt's automatic
  device discovery (based either on \e libudev or a walkthrough of
  \c{/dev/input/event*}) is not functional or misbehaving.

  \section2 Debugging Input Devices

  It is possible to print some information to the debug output by enabling
  the \c qt.qpa.input logging rule, for example by setting the \c QT_LOGGING_RULES
  environment variable to \c{qt.qpa.input=true}. This is useful for detecting
  which device is being used, or to troubleshoot device discovery issues.

  \section2 Using Custom Mouse Cursor Images

  \c eglfs comes with its own set of 32x32 sized mouse cursor images. If these are
  not sufficient, a custom cursor atlas can be provided by setting the \c
  QT_QPA_EGLFS_CURSOR environment variable to the name of a JSON file. The file
  can also be embedded into the application via Qt's resource system.

  For example, an embedded cursor atlas with 8 cursor images per row can be
  specified like the following:

  \badcode
    {
      "image": ":/cursor-atlas.png",
      "cursorsPerRow": 8,
      "hotSpots": [
          [7, 2],
          [12, 3],
          [12, 12],
          ...
      ]
    }
  \endcode

  Note that the images are expected to be tightly packed in the atlas: the
  width and height of the cursors are decided based on the total image size and
  the \c cursorsPerRow setting. Atlases have to provide an image for all the
  supported cursors.

  \section1 Display Output

  When having multiple displays connected, the level of support for targeting
  one or more of these from one single Qt application varies between the
  platform plugins and often depends on the device and its graphics stack.

  \section2 eglfs with eglfs_kms backend

  When the KMS/DRM backend is in use, eglfs reports all available screens in
  QGuiApplication::screens(). Applications can target different screens with
  different windows via QWindow::setScreen().

  \note The restriction of one single fullscreen window per screen still
  applies. Changing screens after making the QWindow visible is not supported
  either. Therefore, it is essential that embedded applications make all the
  necessary QWindow::setScreen() calls before calling QWindow::show().

  When getting started with developing on a given embedded device, it is often
  necessary to verify the behavior of the device and drivers, and that the
  connected displays are working as they should. One easy way is to use the
  hellowindow example. Launching it with \c{-platform eglfs --multiscreen
  --timeout} arguments shows a rotating Qt logo on each connected screen for a few
  seconds.

  \note Most of the configuration options described below apply to all
  KMS/DRM-based backends, regardless of the buffer management technology (GBM or
  EGLStreams).

  The KMS/DRM backend also supports custom configurations via a JSON file.  Set
  the environment variable \c QT_QPA_EGLFS_KMS_CONFIG to the name of the file to
  enable this. The file can also be embedded into the application via the Qt
  resource system. An example configuration is below:

  \badcode
    {
      "device": "/dev/dri/card1",
      "hwcursor": false,
      "pbuffers": true,
      "outputs": [
        {
          "name": "VGA1",
          "mode": "off"
        },
        {
          "name": "HDMI1",
          "mode": "1024x768"
        }
      ]
    }
  \endcode

  Here we configure the specified device so that

  \list

  \li it will not use the hardware cursor (falls back to rendering the mouse
  cursor via OpenGL; by default hardware cursors are enabled as they are more
  efficient),

  \li it will back QOffscreenSurface with standard EGL pbuffer surfaces (by
  default this is disabled and a gbm surface is used instead),

  \li output on the VGA connector is disabled, while HDMI is active with a
  resolution of 1024x768.

  \endlist

  Additionally, such a configuration also disables looking for a device via
  \c libudev and instead the specified device is used.

  When \c mode is not defined, the mode that is reported as preferred by the
  system is chosen. The accepted values for \c mode are: \c off, \c current,
  \c preferred, \c skip, width\c{x}height, width\c{x}height\c{@}vrefresh, or a
  modeline string.

  Specifying \c current will choose a mode with a resolution matching the
  current one. Due to the fact that modesetting is done only when the desired
  mode is actually different from the active one (unless forced via the
  \c QT_QPA_EGLFS_ALWAYS_SET_MODE environment variable), this value is useful to
  keep the current mode and any content in the planes not touched by Qt. \c skip
  causes the connector for the output to be ignored, just as if it was
  disconnected. \c off is similar, but it changes the mode as well to turn off
  the display.

  All screens reported by the DRM layer will be treated as one big virtual
  desktop by default. The mouse cursor implementation will take this into
  account and move across the screens as expected. Although not recommended, the
  virtual desktop mode can be disabled by setting \c separateScreens to \c false
  in the configuration, if desired.

  By default, the virtual desktop is formed left to right, based on the order of
  connectors as reported by the system. This can be changed by setting
  \c virtualIndex to a value starting from 0. For example, the following
  configuration uses the preferred resolution but ensures that the left side in
  the virtual desktop is the screen connected to the HDMI port, while the right
  side is the screen connected to the DisplayPort:

  \badcode
    {
      "device": "drm-nvdc",
      "outputs": [
        {
          "name": "HDMI1",
          "virtualIndex": 0
        },
        {
          "name": "DP1",
          "virtualIndex": 1
        }
      ]
    }
  \endcode

  The order of elements in the array is not relevant. Outputs with unspecified
  virtual indices will be placed after the others, with the original order in
  the DRM connector list preserved.

  To create a vertical desktop space (that is, to stack top to bottom instead of
  left to right), add a \c virtualDesktopLayout property after \c device
  with the value of \c vertical.

  \note It is recommended that all screens in the virtual desktop use the same
  resolution, otherwise elements like the mouse cursor may behave in unexpected
  ways when entering areas that only exist on one given screen.

  When \c virtualIndex is not sufficient, the property \c virtualPos can be used
  to explicitly specify the top-left position of the screen in question. Taking
  the previous example and assuming a resolution of 1080p for HDMI1, the
  following places a second HDMI-based screen below the first one:

  \badcode
    {
       ...
      "outputs": [
        ...
        {
          "name": "HDMI2",
          "virtualPos": "0, 1080"
        }
      ]
    }
  \endcode

  \note Avoid such configurations when mouse support is desired. The mouse
  cursor's behavior may be unexpected with non-linear layouts. Touch should
  present no issues however.

  In some cases the automatic querying of the physical screen size via DRM may
  fail. Normally the \c QT_QPA_EGLFS_PHYSICAL_WIDTH and
  \c QT_QPA_EGLFS_PHYSICAL_HEIGHT environment variable would be used to provide the
  missing values, however this is not suitable anymore when multiple screens are
  present. Instead, use the \c physicalWidth and \c physicalHeight properties
  in the \c outputs list to specify the sizes in millimeters.

  \note Different physical sizes and thus differing logical DPIs are discouraged
  because it may lead to unexpected issues due to some graphics stack components
  not knowing about multiple screens and relying solely on the first screen's
  values.

  Each active output from the \c outputs array corresponds to one QScreen
  instance reported from QGuiApplication::screens(). The primary screen reported
  by QGuiApplication::primaryScreen() is by default the screen that gets
  registered first. When not using \c virtualIndex, this means the decision is
  based on the DRM connector order. To override this, set the property
  \c primary to \c true on the desired entry in the \c outputs list. For example,
  to ensure the screen corresponding to the VGA output will be the primary even
  when the system happens to report the HDMI one first, one can do the following:

  \badcode
    {
      "device": "/dev/dri/card0",
      "outputs": [
          { "name": "HDMI1" },
          { "name": "VGA1", "mode": "1280x720", "primary": true },
          { "name": "LVDS1", "mode": "off" }
      ]
    }
  \endcode

  For troubleshooting it might be useful to enable debug logs from the KMS/DRM
  backend. To do this, enable the categorized logging rule, \c qt.qpa.eglfs.kms.

  \note In an embedded environment virtual desktops are more limited than with a
  full windowing system. Windows overlapping multiple screens, non-fullscreen
  windows and moving windows between screens should be avoided and may not
  function as expected.

  The most common and best supported use case for a multi-screen setup is to
  open a dedicated QQuickWindow or QQuickView for each screen. With the default
  \c threaded render loop of the Qt Quick scenegraph, each of these windows will
  get its own dedicated render thread. This is good because the threads can be
  throttled independently based on vsync, and will not interfere with each
  other. With the \c basic loop this can get problematic and animations may
  degrade as a result.

  As an example, discovering all connected screens and creating a QQuickView for
  each of them can be done like this:

  \badcode
    int main(int argc, char **argv)
    {
        QGuiApplication app(argc, argv);

        QVector<QQuickView *> views;
        for (QScreen *screen : app.screens()) {
            QQuickView *view = new QQuickView;
            view->setScreen(screen);
            view->setResizeMode(QQuickView::SizeRootObjectToView);
            view->setSource(QUrl("qrc:/main.qml"));
            QObject::connect(view->engine(), &QQmlEngine::quit, qGuiApp, &QCoreApplication::quit);
            views.append(view);
            view->showFullScreen();
        }

        int result = app.exec();

        qDeleteAll(views);
        return result;
    }
  \endcode

  \section2 Advanced eglfs_kms features

  Screen cloning (mirroring) is supported as of Qt 5.11. It can be enabled by
  the \c clones property:

  \badcode
    {
      "device": "/dev/dri/card0",
      "outputs": [
          { "name": "HDMI1", "mode": "1920x1080" },
          { "name": "DP1", "mode": "1920x1080", "clones": "HDMI1" }
     ]
    }
  \endcode

  Here the content on the display connected via DisplayPort will be the same as
  on the HDMI one. This is ensured by simply scanning out the same buffer on
  both.

  \note This can only work if the resolutions are the same, there are no
  incompatibilities when it comes to accepted buffer formats, and the
  application does not have any output on the QScreen associated with a clone
  destination. In practice the latter means that no QWindow associated with the
  QScreen in question - DP1 in the example - must ever perform a
  QOpenGLContext::swapBuffers() operation. It is up to the configuration and the
  application to ensure these.

  Headless mode via DRM render nodes is supported as of Qt 5.11. This allows
  performing GPU compute (OpenGL compute shaders, OpenCL) or offscreen OpenGL
  rendering without needing DRM master privileges. In this mode applications can
  function even when there is already another process outputting to the screen.

  Just switching \c device from \c{/dev/dri/card0} to \c{/dev/dri/renderD128} is
  futile on its own since there are a number of operations that cannot be
  performed in headless mode. Therefore, this must be combined with a
  \c headless property, for example:

  \badcode
    {
        "device": "/dev/dri/renderD128",
        "headless": "1024x768"
    }
  \endcode

  Keep in mind that windows are still sized to match the - now virtual -
  screen size, hence the need for specifying a size in the \c headless
  property. There is also a lack of vsync-based throttling.

  Once enabled, applications have two typical choices to perform offscreen
  rendering in headless mode:

  Use an ordinary window, such as a QOpenGLWindow subclass, targeting the
  window's default framebuffer, meaning a \c{gbm_surface} in practice:

  \badcode
      MyOpenGLWindow w;
      w.show(); // will not actually show up on screen
      w.grabFramebuffer().save("output.png");
  \endcode

  Or the typical offscreen approach with an extra FBO:

  \badcode
     QOffscreenSurface s;
     s.setFormat(ctx.format());
     s.create();
     ctx.makeCurrent(&s);
     QOpenGLFramebufferObject fbo(1024, 768);
     fbo.bind();
     ctx.functions()->glClearColor(1, 0, 0, 1);
     ctx.functions()->glClear(GL_COLOR_BUFFER_BIT);
     fbo.toImage().save("output.png");
     ctx.doneCurrent();
  \endcode

  KMS/DRM can be used with two different DRM APIs which are \e legacy and \e atomic.
  The main benefit of DRM atomic API is to allow several DRM plane updates
  within the same renderloop, whereas legacy API would require one plane update
  per vsync.

  Atomic API is useful when you application needs to blend content into overlays
  keeping all the updates within the same vsync. Still not all devices
  support this API and it could be unavailable on some older devices.
  KMS backend will by default use the legacy API, but you can enable the DRM
  atomic API with \c QT_QPA_EGLFS_KMS_ATOMIC environment variable set to 1.

  Using a smaller framebuffer than screen resolution can also be useful.
  This is possible with DRM atomic using the \c size parameter in the JSON file.
  The example below uses a 1280x720 framebuffer on a 3840x2160 videomode :

  \badcode
    {
      "device": "/dev/dri/card0",
      "outputs": [
        { "name": "HDMI1", "mode": "3840x2160", "size": "1280x720", "format": "argb8888" }
      ]
    }
  \endcode

  \section2 eglfs with eglfs_kms_egldevice backend

  This backend, typically used on Tegra devices, is similar to the KMS/DRM
  backend mentioned above, except that it relies on the EGLDevice and EGLStream
  extensions instead of GBM.

  For technical details about this approach, check out
  \l {https://wiki.qt.io/Qt_for_Embedded_Linux/XDC2014RitgerEGLNonMesa}{this presentation}.

  As of Qt 5.7 this backend shares many of its internal implementation with the
  GBM-based backend. This means that multiple screens and the advanced
  configuration via \c QT_QPA_EGLFS_KMS_CONFIG are supported. Some settings,
  such as \c hwcursor and \c pbuffers are not applicable however.

  By default the backend will automatically choose the correct EGL layer for the
  default plane of each output. When necessary, this can be overridden by
  setting the \c QT_QPA_EGLFS_LAYER_INDEX environment variable to the index of
  the desired layer. This approach does not currently support multiple outputs,
  so its usage should be limited to systems with a single screen. To see which
  layers are available, and to debug potential startup issues, enable the
  logging category \c qt.qpa.eglfs.kms.

  In some cases it may be necessary to perform a video mode set on application
  startup even when the screen reports that the desired resolution is already
  set. This is normally optimized away, but if the screen stays powered down,
  try setting the environment variable \c QT_QPA_EGLFS_ALWAYS_SET_MODE to a
  non-zero value and relaunch the application.

  To configure the behavior of the EGLStream object used by the backend, use the
  \c QT_QPA_EGLFS_STREAM_FIFO_LENGTH environment variable. This assumes that
  \c KHR_stream_fifo is supported by the target system. By default the stream
  operates in mailbox mode. To switch to FIFO mode, set a value of 1 or
  greater. The value specifies the maximum number of frames the stream can hold.

  On some systems it may become necessary to target a specific overlay plane
  through a pre-defined connector. Just forcing a layer index via
  \c QT_QPA_EGLFS_LAYER_INDEX does not perform plane configuration and is therefore
  not suitable in itself. Instead, in such special scenarios use the
  \c QT_QPA_EGLFS_KMS_CONNECTOR_INDEX and \c QT_QPA_EGLFS_KMS_PLANE_INDEX
  environment variables. When these are set, only the specified connector and
  plane will be in use, all other outputs will get ignored. The backend will
  take care of picking the EGL layer that corresponds to the desired plane, and
  the configuring of the plane.

  \section2 Touch input in systems with multiple screens on KMS/DRM

  Touchscreens require additional considerations in multi-display systems
  because touch events have to be routed to the correct virtual screen, and this
  requires a correct mapping between touchscreens and display outputs.

  The mapping is done via the JSON configuration file specified in
  \c QT_QPA_EGLFS_KMS_CONFIG and described in the previous sections. When a
  \c touchDevice property is present in an element of the \c outputs array, the
  value is treated as a device node and the touch device is associated with the
  display output in question.

  For example, assuming our touchscreen has a device node of /dev/input/event5
  and is a touchscreen integrated into the monitor connected via HDMI as the
  secondary screen, the following configuration ensures correct touch (and
  synthesized mouse) event translation:

  \badcode
     {
        "device": "drm-nvdc",
        "outputs": [
          {
            "name": "HDMI1",
            "touchDevice": "/dev/input/event5",
            "virtualIndex": 1
          },
          {
            "name": "DP1",
            "virtualIndex": 0
          }
        ]
    }
  \endcode

  \note When in doubt, enable logging from both the graphics and input
  subsystems by setting the environment variable
  \c{QT_LOGGING_RULES=qt.qpa.*=true} before launching the application. This will
  help identifying the correct input device nodes and may uncover output
  configuration issues that can be difficult to debug otherwise.

  \note As of Qt 5.8, the above is only supported for the evdevtouch input
  backend. Other variants, such as the libinput-based one, will continue to
  route events to the primary screen. To force the usage of evdevtouch on
  systems where multiple input backends are available, set the environment
  variable \c QT_QPA_EGLFS_NO_LIBINPUT to \c 1.

  \section2 eglfs with other backends

  Other backends, that are typically based on targeting the framebuffer or a
  composition API directly via the vendor's EGL implementation, usually provide
  limited or no support for multiple displays. On i.MX6-based boards with
  Vivante GPUs the \c{QT_QPA_EGLFS_FB} environment variable can be used to
  specify the framebuffer to target, similarly to linuxfb. On the Raspberry Pi
  the \c{QT_QPA_EGLFS_DISPMANX_ID} environment variable can be used to specify
  the screen to output to. The value corresponds to one of the \c{DISPMANX_ID_}
  constants, refer to the Dispmanx documentation. Note that these approaches,
  unlike KMS/DRM, will not typically allow to output to multiple screens from
  the same application. Alternatively, driver-specific environment variables or
  kernel parameters may also be available as well to control the used
  framebuffer. Refer to the embedded board's documentation.

  \section2 Video Memory

  Systems with a fixed amount of dedicated video memory may need extra care
  before running Qt application based on Qt Quick or classes like
  QOpenGLWidget. The default setting may be insufficient for such applications,
  especially when they are displayed on a high resolution (for example, full HD)
  screen. In this case, they may start failing in unexpected ways. It is
  recommended to ensure that there is at least 128 MB of GPU memory available.
  For systems that do not have a fixed amount of memory reserved for
  the GPU this is not an issue.

  \section2 linuxfb

  Use the \c fb plugin parameter to specify the framebuffer device to use.

  \section1 Unix Signal Handlers

  The console-oriented platform plugins like eglfs and linuxfb install signal
  handlers by default to capture interrupt (\c SIGINT), suspend and continue
  (\c SIGTSTP, \c SIGCONT) and termination (\c SIGTERM). This way the keyboard,
  terminal cursor, and possibly other graphics state can be restored when the
  application terminates or gets suspended due to \c kill, or \c{Ctrl+C} or
  \c{Ctrl+Z}. (although terminating or suspending via the keyboard is only
  possible when \c{QT_QPA_ENABLE_TERMINAL_KEYBOARD} is set, as outlined above in
  the Input section). However, in some cases capturing \c SIGINT can be
  undesirable as it may conflict with remote debugging for instance. Therefore,
  the environment variable \c{QT_QPA_NO_SIGNAL_HANDLER} is provided to opt out
  from all built-in signal handling.

  \section1 Fonts

  Qt normally uses \c fontconfig to provide access to system fonts. If
  \c fontconfig is not available, Qt will fall back to using
  \c QBasicFontDatabase. In this case, Qt applications will look for fonts in Qt's
  \c lib/fonts directory. Qt will automatically detect pre-rendered fonts and
  TrueType fonts. This directory can be overridden by setting the \c
  QT_QPA_FONTDIR environment variable.

  For more information on the supported formats, see \l{Qt for Embedded Linux Fonts}.

  \note Qt no longer ships any fonts in the \c lib/fonts directory. This
  means that it is up to the platform (the system image) to provide the
  necessary fonts.

  \section1 Platform Plugins for Windowing Systems on Embedded Linux Devices

  \section2 XCB

  This is the X11 plugin used on regular desktop Linux platforms. In some
  embedded environments, that provide X and the necessary development files for
  \l {http://xcb.freedesktop.org}{xcb}, this plugin functions just like it
  does on a regular PC desktop.

  \note On some devices there is no EGL and OpenGL support available under X
  because the EGL implementation is not compatible with Xlib. In this case the
  XCB plugin is built without EGL support, meaning that Qt Quick 2 or other
  OpenGL-based applications does not work with this platform plugin. It can
  still be used however to run software-rendered applications (based on QWidget
  for example).

  As a general rule, the usage of XCB on embedded devices is not
  advisable. Plugins like eglfs are likely to provide better performance, and
  hardware acceleration.

  \section2 Wayland

  \l{http://wayland.freedesktop.org/}{Wayland} is a light-weight windowing
  system; or more precisely, it is a protocol for clients to talk to a display
  server.

  Qt Wayland provides a \c wayland platform plugin that allows Qt applications
  to connect to a Wayland compositor.

  For more details, see \l{Wayland and Qt}.

  \note You may experience issues with touch screen input while using the
  \l{http://wayland.freedesktop.org/}{Weston} reference compositor. For more
  information, see \l{https://wiki.qt.io/WestonTouchScreenIssues}.

  \section1 Related Topics

  \list
   \li \l{Qt for Device Creation}
   \li \l{Configure an Embedded Linux Device}
   \li \l Emulator
   \li \l{Qt Virtual Keyboard}
   \li \l{Qt Quick WebGL}
  \endlist

*/