summaryrefslogtreecommitdiff
diff options
-rwxr-xr-xbin/graphics_max_resolution.py148
-rwxr-xr-xbin/graphics_modes_info.py74
-rwxr-xr-xbin/network_device_info.py3
-rwxr-xr-xbin/touchpad_confidence_bit.py3
-rwxr-xr-xbin/touchpad_test.py72
-rw-r--r--units/graphics/jobs.pxu18
-rw-r--r--units/graphics/legacy.pxu8
-rw-r--r--units/touchpad/jobs.pxu33
-rw-r--r--units/touchpad/test-plan.pxu12
9 files changed, 211 insertions, 160 deletions
diff --git a/bin/graphics_max_resolution.py b/bin/graphics_max_resolution.py
new file mode 100755
index 0000000..56628a4
--- /dev/null
+++ b/bin/graphics_max_resolution.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+#
+# This file is part of Checkbox.
+#
+# Copyright 2022 Canonical Ltd.
+#
+# Authors:
+# Pierre Equoy <pierre.equoy@canonical.com>
+#
+# Checkbox is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+#
+# Checkbox is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
+
+import gi
+from glob import glob
+import os
+import sys
+from pathlib import Path
+
+gi.require_versions({"Gtk": "3.0", "Gdk": "3.0"})
+from gi.repository import Gdk, Gtk # noqa: E402
+
+
+def get_sysfs_info():
+ """
+ Go through each graphics cards sysfs entries to find max resolution if
+ connected to a monitor.
+ Return a list of ports with information about them.
+ """
+ ports = glob("/sys/class/drm/card*-*")
+ entries = []
+ for p in ports:
+ with open(Path(p) / "modes") as f:
+ # Topmost line in the modes file is the max resolution
+ max_resolution = f.readline().strip()
+ if max_resolution:
+ # e.g. "/sys/class/drm/card0-HDMI-A-1"
+ port = p.split("/")[-1]
+ width, height = max_resolution.split("x")
+ with open(Path(p) / "enabled") as f:
+ enabled = f.readline().strip()
+ with open(Path(p) / "dpms") as f:
+ dpms = f.readline().strip()
+ with open(Path(p) / "status") as f:
+ status = f.readline().strip()
+ port_info = {
+ "port": port,
+ "width": int(width),
+ "height": int(height),
+ "enabled": enabled, # "enabled" or "disabled"
+ "status": status, # "connected" or "disconnected"
+ "dpms": dpms, # "On" or "Off"
+ }
+ entries.append(port_info)
+ return entries
+
+
+def get_monitors_info():
+ """
+ Get information (model, manufacturer, resolution) from each connected
+ monitors using Gtk.
+ Return a list of monitors with their information.
+ """
+ Gtk.init()
+ display = Gdk.Display.get_default()
+ monitors = []
+ for i in range(display.get_n_monitors()):
+ mon = display.get_monitor(i)
+ monitor = {
+ "model": mon.get_model(),
+ "manufacturer": mon.get_manufacturer(),
+ "width": mon.get_geometry().width,
+ "height": mon.get_geometry().height,
+ "scale_factor": mon.get_scale_factor(),
+ }
+ monitors.append(monitor)
+ return monitors
+
+
+if __name__ == "__main__":
+ sysfs_entries = get_sysfs_info()
+ mons_entries = get_monitors_info()
+ total_sysfs_res = 0
+ total_mons_res = 0
+ compositor = os.environ.get("XDG_SESSION_TYPE")
+ print("Current compositor: {}".format(compositor))
+ print()
+ print("Maximum resolution found for each connected monitors:")
+ for p in sysfs_entries:
+ port = p["port"]
+ width = p["width"]
+ height = p["height"]
+ enabled = p["enabled"]
+ status = p["status"]
+ dpms = p["dpms"].lower()
+ print(
+ "\t{}: {}x{} ({}, {}, {})".format(
+ port, width, height, dpms, status, enabled
+ )
+ )
+ # If the monitor is disabled (e.g. "Single Display" mode), don't take
+ # its surface into account.
+ if enabled == "enabled":
+ total_sysfs_res += width * height
+ print()
+ print("Current resolution found for each connected monitors:")
+ for m in mons_entries:
+ model = m["model"]
+ manufacturer = m["manufacturer"]
+ scale = m["scale_factor"]
+ # Under X11, the returned width and height are in "application pixels",
+ # not "device pixels", so it has to be multiplied by the scale factor.
+ # However, Wayland always returns the "device pixels" width and height.
+ #
+ # Example: a 3840x2160 screen set to 200% scale will have
+ # width = 1920, height = 1080, scale_factor = 2 on X11
+ # width = 3840, height = 2160, scale_factor = 2 on Wayland
+ if compositor == "x11":
+ width = m["width"] * m["scale_factor"]
+ height = m["height"] * m["scale_factor"]
+ else:
+ width = m["width"]
+ height = m["height"]
+ print(
+ "\t{} ({}): {}x{} @{}%".format(
+ model, manufacturer, width, height, scale * 100
+ )
+ )
+ total_mons_res += width * height
+ print()
+ if total_sysfs_res == total_mons_res:
+ print("The displays are configured at their maximum resolution.")
+ else:
+ sys.exit(
+ (
+ "The displays do not seem to be configured at their maximum "
+ "resolution.\nPlease switch to the maximum resolution before "
+ "continuing."
+ )
+ )
diff --git a/bin/graphics_modes_info.py b/bin/graphics_modes_info.py
deleted file mode 100755
index f92cd76..0000000
--- a/bin/graphics_modes_info.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-#
-# graphics_modes_info.py
-#
-# This file is part of Checkbox.
-#
-# Copyright 2012 Canonical Ltd.
-#
-# Authors: Alberto Milone <alberto.milone@canonical.com>
-#
-# Checkbox is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3,
-# as published by the Free Software Foundation.
-
-#
-# Checkbox is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import print_function
-from __future__ import unicode_literals
-import sys
-
-from checkbox_support.contrib import xrandr
-
-
-def print_modes_info(screen):
- """Print some information about the detected screen and its outputs"""
- xrandr._check_required_version((1, 0))
- print("Screen %s: minimum %s x %s, current %s x %s, maximum %s x %s" %
- (screen._screen,
- screen._width_min, screen._height_min,
- screen._width, screen._height,
- screen._width_max, screen._height_max))
- print(" %smm x %smm" % (screen._width_mm, screen._height_mm))
- print("Outputs:")
- for o in list(screen.outputs.keys()):
- output = screen.outputs[o]
- print(" %s" % o, end=' ')
- if output.is_connected():
- print("(%smm x %smm)" % (output.get_physical_width(),
- output.get_physical_height()))
- modes = output.get_available_modes()
- print(" Modes:")
- for m in range(len(modes)):
- mode = modes[m]
- refresh = mode.dotClock / (mode.hTotal * mode.vTotal)
- print(
- " [%s] %s x %s @ %s Hz" %
- (m, mode.width, mode.height, refresh), end=' ')
- if mode.id == output._mode:
- print("(current)", end=' ')
- if m == output.get_preferred_mode():
- print("(preferred)", end=' ')
- print("")
- else:
- print("(not connected)")
-
-
-def main():
- screen = xrandr.get_current_screen()
- try:
- print_modes_info(screen)
- except(xrandr.UnsupportedRRError):
- print('Error: RandR version lower than 1.0', file=sys.stderr)
-
-
-if __name__ == '__main__':
- main()
diff --git a/bin/network_device_info.py b/bin/network_device_info.py
index 10865b9..9d31f75 100755
--- a/bin/network_device_info.py
+++ b/bin/network_device_info.py
@@ -343,7 +343,8 @@ class UdevDevices():
def _collect_devices(self):
cmd = ['udevadm', 'info', '--export-db']
try:
- output = check_output(cmd).decode(sys.stdout.encoding)
+ output = check_output(cmd).decode(sys.stdout.encoding,
+ errors='ignore')
except CalledProcessError as err:
sys.stderr.write(err)
return
diff --git a/bin/touchpad_confidence_bit.py b/bin/touchpad_confidence_bit.py
index ff47e6d..127dca4 100755
--- a/bin/touchpad_confidence_bit.py
+++ b/bin/touchpad_confidence_bit.py
@@ -14,7 +14,8 @@ class TouchpadDevices:
def _collect_devices(self):
cmd = ['udevadm', 'info', '--export-db']
try:
- output = check_output(cmd).decode(sys.stdout.encoding)
+ output = check_output(cmd).decode(sys.stdout.encoding,
+ errors='ignore')
except CalledProcessError as err:
sys.stderr.write(err)
return
diff --git a/bin/touchpad_test.py b/bin/touchpad_test.py
index 6ecde92..83940ec 100755
--- a/bin/touchpad_test.py
+++ b/bin/touchpad_test.py
@@ -3,6 +3,7 @@
import gi
import sys
import gettext
+from time import sleep
from gettext import gettext as _
gi.require_version('Gdk', '3.0')
@@ -43,7 +44,7 @@ class GtkScroller(object):
# Initialize GTK constants
self.ICON_SIZE = Gtk.IconSize.BUTTON
self.ICON_TESTED = Gtk.STOCK_YES
- self.ICON_UNTESTED = Gtk.STOCK_INDEX
+ self.ICON_UNTESTED = Gtk.STOCK_DIALOG_QUESTION
self.ICON_NOT_REQUIRED = Gtk.STOCK_REMOVE
self.button_factory = Gtk.Button
@@ -70,7 +71,7 @@ class GtkScroller(object):
button_hbox = self._add_hbox(vbox)
validation_hbox = self._add_hbox(vbox)
self.status = self._add_label(vbox)
- self.exit_button = self._add_button(vbox, Gtk.STOCK_CLOSE)
+ self.exit_button = self._add_button(vbox, "_Close")
self.exit_button.connect("clicked", lambda w: self.quit())
# Add widgets for each direction.
@@ -78,15 +79,15 @@ class GtkScroller(object):
for direction in self.directions:
self._add_label(button_hbox, direction.name)
self.icons[direction] = self._add_image(
- validation_hbox, Gtk.STOCK_INDEX)
+ validation_hbox, self.ICON_UNTESTED)
self.show_text(
_("Please move the mouse cursor to this window.") +
"\n" +
_("Then scroll in each direction on your touchpad."))
- def _add_button(self, context, stock):
- button = self.button_factory(stock=stock)
+ def _add_button(self, context, label):
+ button = self.button_factory.new_with_mnemonic(label)
context.add(button)
button.show()
return button
@@ -124,29 +125,33 @@ class GtkScroller(object):
def run(self):
# Save touchpad settings.
- if self.horiz_scroll_key:
- self.saved_horiz_scroll_enabled = \
- self.touchpad_settings.get_boolean("horiz-scroll-enabled")
- self.saved_scroll_method = self.touchpad_settings.get_string(
- "scroll-method")
+ self.saved_edge_scrolling_enabled = self.touchpad_settings.get_boolean(
+ "edge-scrolling-enabled")
+ self.saved_two_finger_enabled = self.touchpad_settings.get_boolean(
+ "two-finger-scrolling-enabled")
# Set touchpad settings.
- if self.horiz_scroll_key:
- self.touchpad_settings.set_boolean("horiz-scroll-enabled", True)
if self.edge_scroll:
- self.touchpad_settings.set_string(
- "scroll-method", "edge-scrolling")
-
+ self.touchpad_settings.set_boolean(
+ "edge-scrolling-enabled", True)
+ self.touchpad_settings.set_boolean(
+ "two-finger-scrolling-enabled", False)
+ else:
+ self.touchpad_settings.set_boolean(
+ "two-finger-scrolling-enabled", True)
+ self.touchpad_settings.set_boolean(
+ "edge-scrolling-enabled", False)
Gtk.main()
def quit(self):
# Reset touchpad settings.
- if self.horiz_scroll_key:
- self.touchpad_settings.set_boolean(
- "horiz-scroll-enabled", self.saved_horiz_scroll_enabled)
- self.touchpad_settings.set_string(
- "scroll-method", self.saved_scroll_method)
-
+ self.touchpad_settings.set_boolean(
+ "two-finger-scrolling-enabled", self.saved_two_finger_enabled)
+ # GNOME does not like when both settings are set at the same time, so
+ # waiting a bit.
+ sleep(0.1)
+ self.touchpad_settings.set_boolean(
+ "edge-scrolling-enabled", self.saved_edge_scrolling_enabled)
Gtk.main_quit()
def show_text(self, text, widget=None):
@@ -156,7 +161,7 @@ class GtkScroller(object):
def found_direction(self, direction):
direction.tested = True
- self.icons[direction].set_from_stock(
+ self.icons[direction].set_from_icon_name(
self.ICON_TESTED, size=self.ICON_SIZE)
self.check_directions()
@@ -169,10 +174,25 @@ class GtkScroller(object):
def on_scroll(self, window, event):
for direction in self.directions:
- if direction.value == event.direction:
- self.found_direction(direction)
- break
-
+ scroll_delta, delta_x, delta_y = event.get_scroll_deltas()
+ if scroll_delta:
+ event_direction = None
+ # Arbitrarily using 0.8, which requires a little bit of hand
+ # movement on the touchpads used for testing.
+ # Note that the directions are based on the default natural
+ # scrolling settings in GNOME settings.
+ if delta_x > 0.8:
+ event_direction = Direction("left")
+ elif delta_x < -0.8:
+ event_direction = Direction("right")
+ if delta_y > 0.8:
+ event_direction = Direction("up")
+ elif delta_y < -0.8:
+ event_direction = Direction("down")
+ if event_direction:
+ if direction.value == event_direction.value:
+ self.found_direction(direction)
+ break
return True
diff --git a/units/graphics/jobs.pxu b/units/graphics/jobs.pxu
index 4dde304..8206f1a 100644
--- a/units/graphics/jobs.pxu
+++ b/units/graphics/jobs.pxu
@@ -133,13 +133,7 @@ category_id: com.canonical.plainbox::graphics
requires:
device.category == 'VIDEO'
command:
- # shellcheck disable=SC1091
- source graphics_env.sh {driver} {index}
- maxi="$(xrandr -q |grep -A 1 "connected\( primary\)* [0-9]" |tail -1 |awk '{{print $1}}')"
- now="$(python3 -c 'from gi.repository import Gdk; screen=Gdk.Screen.get_default(); geo = screen.get_monitor_geometry(screen.get_primary_monitor()); print(geo.width, "x", geo.height, sep="")')"
- test "$maxi" != "$now" && notify="\nPlease switch to the maximum resolution \nfor every graphic tests"
- echo "Maximum resolution: $maxi"
- echo "Current resolution: $now $notify"
+ graphics_max_resolution.py
estimated_duration: 10.0
_summary: Test maximum supported resolution for {vendor} {product}
_description:
@@ -154,16 +148,6 @@ _description:
unit: template
template-resource: graphics_card
-id: graphics/{index}_modes_{product_slug}
-plugin: shell
-category_id: com.canonical.plainbox::graphics
-command: graphics_modes_info.py
-estimated_duration: 0.250
-_description: Collect info on graphics modes (screen resolution and refresh rate) for {vendor} {product}
-_summary: Test graphic modes info for {vendor} {product}
-
-unit: template
-template-resource: graphics_card
id: graphics/{index}_color_depth_{product_slug}
plugin: shell
category_id: com.canonical.plainbox::graphics
diff --git a/units/graphics/legacy.pxu b/units/graphics/legacy.pxu
index 14969b0..2b9545d 100644
--- a/units/graphics/legacy.pxu
+++ b/units/graphics/legacy.pxu
@@ -96,14 +96,6 @@ _description:
VERIFICATION:
Is this the display's maximum resolution?
-id: graphics/modes
-plugin: shell
-category_id: com.canonical.plainbox::graphics
-command: graphics_modes_info.py
-estimated_duration: 0.250
-_description: Collect info on graphics modes (screen resolution and refresh rate)
-_summary: Collect info on graphics modes
-
id: graphics/color_depth
plugin: shell
category_id: com.canonical.plainbox::graphics
diff --git a/units/touchpad/jobs.pxu b/units/touchpad/jobs.pxu
index 0a6c52c..11960ee 100644
--- a/units/touchpad/jobs.pxu
+++ b/units/touchpad/jobs.pxu
@@ -102,37 +102,20 @@ _siblings:
plugin: user-interact
category_id: com.canonical.plainbox::touchpad
-id: touchpad/multitouch-horizontal
+id: touchpad/multitouch
requires: dmi.product in ['Notebook','Laptop','Portable','Convertible']
-command: touchpad_test.py right left
+command: touchpad_test.py up down right left
estimated_duration: 120.0
_purpose:
- Touchpad 2-touch horizontal scroll verification
+ Touchpad 2-finger scroll verification
_steps:
- 1. Select "Test" when ready and place your cursor within the borders of the displayed test window.
- 2. Verify that you can move the horizontal slider by moving 2 fingers right and left along the touchpad.
+ 1. Press "Enter" when ready and place your cursor within the borders of the displayed test window.
+ 2. Verify that the scroll events are detected by moving two fingers in all four directions along the touchpad.
_verification:
- Could you scroll right and left?
-_siblings:
- [{ "id": "touchpad/multitouch-horizontal-after-suspend",
- "depends": "suspend/suspend_advanced_auto touchpad/multitouch-horizontal" }]
-
-plugin: user-interact
-category_id: com.canonical.plainbox::touchpad
-id: touchpad/multitouch-vertical
-requires: dmi.product in ['Notebook','Laptop','Portable','Convertible']
-command: touchpad_test.py up down
-estimated_duration: 120.0
-_purpose:
- Touchpad 2-touch vertical scroll verification
-_steps:
- 1. Select "Test" when ready and place your cursor within the borders of the displayed test window.
- 2. Verify that you can move the vertical slider by moving 2 fingers up and down along the touchpad.
-_verification:
- Could you scroll up and down?
+ Were scroll events detected for all four directions?
_siblings:
- [{ "id": "touchpad/multitouch-vertical-after-suspend",
- "depends": "suspend/suspend_advanced_auto touchpad/multitouch-vertical" }]
+ [{ "id": "touchpad/multitouch-after-suspend",
+ "depends": "suspend/suspend_advanced_auto touchpad/multitouch" }]
plugin: manual
category_id: com.canonical.plainbox::touchpad
diff --git a/units/touchpad/test-plan.pxu b/units/touchpad/test-plan.pxu
index e03ea54..74d41a5 100644
--- a/units/touchpad/test-plan.pxu
+++ b/units/touchpad/test-plan.pxu
@@ -20,8 +20,7 @@ include:
touchpad/singletouch-selection certification-status=blocker
touchpad/drag-and-drop certification-status=blocker
touchpad/multitouch-rightclick certification-status=blocker
- touchpad/multitouch-horizontal certification-status=blocker
- touchpad/multitouch-vertical certification-status=blocker
+ touchpad/multitouch certification-status=blocker
id: touchpad-cert-automated
unit: test plan
@@ -45,8 +44,7 @@ include:
touchpad/singletouch-selection-after-suspend certification-status=blocker
touchpad/drag-and-drop-after-suspend certification-status=blocker
touchpad/multitouch-rightclick-after-suspend certification-status=blocker
- touchpad/multitouch-horizontal-after-suspend certification-status=blocker
- touchpad/multitouch-vertical-after-suspend certification-status=blocker
+ touchpad/multitouch-after-suspend certification-status=blocker
id: touchpad-cert-blockers
unit: test plan
@@ -59,8 +57,7 @@ include:
touchpad/singletouch-selection certification-status=blocker
touchpad/drag-and-drop certification-status=blocker
touchpad/multitouch-rightclick certification-status=blocker
- touchpad/multitouch-horizontal certification-status=blocker
- touchpad/multitouch-vertical certification-status=blocker
+ touchpad/multitouch certification-status=blocker
id: after-suspend-touchpad-cert-blockers
unit: test plan
@@ -73,5 +70,4 @@ include:
touchpad/singletouch-selection-after-suspend certification-status=blocker
touchpad/drag-and-drop-after-suspend certification-status=blocker
touchpad/multitouch-rightclick-after-suspend certification-status=blocker
- touchpad/multitouch-horizontal-after-suspend certification-status=blocker
- touchpad/multitouch-vertical-after-suspend certification-status=blocker
+ touchpad/multitouch-after-suspend certification-status=blocker