diff options
| author | Antoine Prieels <anp@odoo.com> | 2019-11-18 10:28:59 +0000 |
|---|---|---|
| committer | Antoine Prieels <anp@odoo.com> | 2019-11-27 14:15:18 +0000 |
| commit | ad846fcee5b1a548c2b2e1f9ac5cbf131d039042 (patch) | |
| tree | 48bced3e0e845d4b063af9b8519924156bc79a69 | |
| parent | c1c4404131bf2d2b913e6ef96106e1ef7754bcaa (diff) | |
[IMP] iot: Dual screen support for RPI4
We now support the RPI4 which has 2 micro-HDMI outputs, while the
prvious driver only supported one display. We add support for a second
display.
Taskid: 2123511
X-original-commit: 5886c3a864c990fcd7b852baafab752e7da90494
6 files changed, 97 insertions, 19 deletions
diff --git a/addons/hw_drivers/controllers/driver.py b/addons/hw_drivers/controllers/driver.py index d7982056190..fc61c8ed63e 100755 --- a/addons/hw_drivers/controllers/driver.py +++ b/addons/hw_drivers/controllers/driver.py @@ -6,7 +6,7 @@ from usb import core from gatt import DeviceManager as Gatt_DeviceManager import subprocess import json -from re import sub +from re import sub, finditer import urllib3 import os import socket @@ -302,14 +302,20 @@ class Manager(Thread): def get_connected_displays(self): display_devices = {} - hdmi = subprocess.check_output(['tvservice', '-n']).decode('utf-8').replace('\n', '') - if hdmi.find('=') != -1 and hdmi.split('=')[1] != "Unk-Composite dis": - hdmi_serial = sub('[^a-zA-Z0-9 ]+', '', hdmi.split('=')[1]).replace(' ', '_') + + displays = subprocess.check_output(['tvservice', '-l']).decode() + x_screen = 0 + for match in finditer('Display Number (\d), type HDMI (\d)', displays): + display_id, hdmi_id = match.groups() + display_name = subprocess.check_output(['tvservice', '-nv', display_id]).decode().rstrip().split('=')[1] + display_identifier = sub('[^a-zA-Z0-9 ]+', '', display_name).replace(' ', '_') + "_" + str(hdmi_id) iot_device = IoTDevice({ - 'identifier': hdmi_serial, - 'name': hdmi.split('=')[1], + 'identifier': display_identifier, + 'name': display_name, + 'x_screen': str(x_screen), }, 'display') - display_devices[hdmi_serial] = iot_device + display_devices[display_identifier] = iot_device + x_screen += 1 if not len(display_devices): # No display connected, create "fake" device to be accessed from another computer diff --git a/addons/hw_drivers/drivers/DisplayDriver.py b/addons/hw_drivers/drivers/DisplayDriver.py index 67d9f861708..167b485586d 100644 --- a/addons/hw_drivers/drivers/DisplayDriver.py +++ b/addons/hw_drivers/drivers/DisplayDriver.py @@ -35,8 +35,9 @@ class DisplayDriver(Driver): self.event_data = threading.Event() self.owner = False self.rendered_html = '' - self.load_url() - self.call_xdotools('F11') + if self.device_identifier != 'distant_display': + self._x_screen = device.get('x_screen', '0') + self.load_url() @property def device_identifier(self): @@ -68,20 +69,22 @@ class DisplayDriver(Driver): event_manager.device_changed(self) def run(self): - while True: + while self.device_identifier != 'distant_display': time.sleep(60) if self.url != 'http://localhost:8069/point_of_sale/display/': # Refresh the page every minute self.call_xdotools('F5') def update_url(self, url=None): + os.environ['DISPLAY'] = ":0." + self._x_screen + os.environ['XAUTHORITY'] = '/run/lightdm/pi/xauthority' firefox_env = os.environ.copy() - firefox_env['HOME'] = '/tmp' - firefox_env['DISPLAY'] = ':0.0' - firefox_env['XAUTHORITY'] = '/run/lightdm/pi/xauthority' + firefox_env['HOME'] = '/tmp/' + self._x_screen self.url = url or 'http://localhost:8069/point_of_sale/display/' - if self.device_identifier != 'distant_display': - subprocess.Popen(['firefox', self.url], env=firefox_env) + new_window = subprocess.call(['xdotool', 'search', '--onlyvisible', '--screen', self._x_screen, '--class', 'Firefox']) + subprocess.Popen(['firefox', self.url], env=firefox_env) + if new_window: + self.call_xdotools('F11') def load_url(self): url = None @@ -101,10 +104,10 @@ class DisplayDriver(Driver): return self.update_url(url) def call_xdotools(self, keystroke): - os.environ['DISPLAY'] = ":0.0" + os.environ['DISPLAY'] = ":0." + self._x_screen os.environ['XAUTHORITY'] = "/run/lightdm/pi/xauthority" try: - subprocess.call(['xdotool', 'search', '--sync', '--onlyvisible', '--class', 'Firefox', 'windowactivate', 'key', keystroke]) + subprocess.call(['xdotool', 'search', '--sync', '--onlyvisible', '--screen', self._x_screen, '--class', 'Firefox', 'key', keystroke]) return "xdotool succeeded in stroking " + keystroke except: return "xdotool threw an error, maybe it is not installed on the IoTBox" diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/X11/xorg.conf b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/X11/xorg.conf new file mode 100644 index 00000000000..b525e583c30 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/X11/xorg.conf @@ -0,0 +1,60 @@ +Section "Device" + Identifier "fbdev0" + Driver "fbdev" + Option "fbdev" "/dev/fb0" +EndSection + +Section "Device" + Identifier "fbdev1" + Driver "fbdev" + Option "fbdev" "/dev/fb1" +EndSection + +# Dummy device to use Xlib in KeyboardUSBDriver when no monitor is connected +Section "Device" + Identifier "dummy" + Driver "dummy" +EndSection + +Section "Monitor" + Identifier "Monitor0" +EndSection + +Section "Monitor" + Identifier "Monitor1" +EndSection + +Section "Monitor" + Identifier "DummyMonitor" +EndSection + +Section "Screen" + Identifier "Screen0" + Monitor "Monitor0" + Device "fbdev0" + Subsection "Display" + EndSubSection +EndSection + +Section "Screen" + Identifier "Screen1" + Monitor "Monitor1" + Device "fbdev1" + Subsection "Display" + EndSubSection +EndSection + +Section "Screen" + Identifier "DummyScreen" + Monitor "DummyMonitor" + Device "dummy" + Subsection "Display" + EndSubSection +EndSection + +Section "ServerLayout" + Identifier "Multihead" + Screen 0 "Screen0" + Screen 1 "Screen1" rightof "Screen0" + Screen 2 "DummyScreen" rightof "Screen1" +EndSection diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf index 977903c1c90..7b487b33ed8 100644 --- a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf @@ -3,6 +3,6 @@ user-authority-in-system-dir=true [SeatDefaults] -xserver-command=/usr/bin/X -s 0 dpms -nolisten tcp +xserver-command=/usr/bin/X -s 0 -layout Multihead dpms -nolisten tcp greeter-hide-users=false -autologin-user=pi
\ No newline at end of file +autologin-user=pi diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh index 9f2e8438770..f795d4a8857 100755 --- a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh @@ -50,6 +50,7 @@ PKGS_TO_INSTALL=" xdotool \ unclutter \ x11-utils \ + xserver-xorg-video-dummy \ openbox \ rpi-update \ adduser \ @@ -159,6 +160,9 @@ systemctl disable hostapd.service # cf: https://www.raspberrypi.org/documentation/configuration/raspi-config.md echo "disable_overscan=1" >> /boot/config.txt +# Separate framebuffers for both screens on RPI4 +sed -i '/dtoverlay/d' /boot/config.txt + # exclude /drivers folder from git info to be able to load specific drivers echo "addons/hw_drivers/drivers/" > /home/pi/odoo/.git/info/exclude diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/.xsession b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/.xsession new file mode 100644 index 00000000000..ddbeae99211 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/.xsession @@ -0,0 +1,5 @@ +# Start Openbox on the second display as described in +# http://openbox.org/wiki/Help:FAQ > "How do I run Openbox across multiple X screens?" + +XAUTHORITY=/run/lightdm/pi/xauthority DISPLAY=:0.1 openbox & +exec openbox-session |
