From aa0fd839afccd2340680500f0804d72b1f3b6b7b Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Fri, 13 Mar 2026 11:59:48 +0900 Subject: [PATCH 01/16] Introducing NixOS end-to-end test framework The time has finally come! This system should allow interactive tests by simulating the mouse and keyboard and comparing against screenshots (and maybe also ensure GNOME hasn't crashed). --- flake.lock | 6 +-- flake.nix | 73 ++++++++++++++++++++++------------- tests/README.md | 23 +++++++++++ tests/default.nix | 44 +++++++++++++++++++++ tests/features/basic.feature | 5 +++ tests/features/steps/basic.py | 12 ++++++ tests/template.nix | 23 +++++++++++ 7 files changed, 157 insertions(+), 29 deletions(-) create mode 100644 tests/README.md create mode 100644 tests/default.nix create mode 100644 tests/features/basic.feature create mode 100644 tests/features/steps/basic.py create mode 100644 tests/template.nix diff --git a/flake.lock b/flake.lock index 3f2508ec..59dc9ee2 100644 --- a/flake.lock +++ b/flake.lock @@ -19,11 +19,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1768571051, - "narHash": "sha256-BKah+ebcZu6GNPan/wwXmPoE93ctPMW4BHIiqjlem9U=", + "lastModified": 1773371044, + "narHash": "sha256-UioNXlVNmX+3QQ0ZjdZkZFq7ctHyObpcvdHm9aZV0/c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8e13ad6266acf92aa1c61d006f51a30c53d43851", + "rev": "65feaa4cdcddbc1659abb8796810f29c4531aad8", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 11a4e052..8916c2ff 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,35 @@ inputs."nixpkgs-gnome".url = github:NixOS/nixpkgs/wip-gnome; outputs = { self, nixpkgs, nixpkgs-gnome, flake-utils, ... }: + let + testSystem = "x86_64-linux"; + pkgs-gnome = import nixpkgs-gnome { system = testSystem; }; + gnomeOverlay = (s: super: { + gnome-desktop = pkgs-gnome.gnome-desktop; + gnome-shell = pkgs-gnome.gnome-shell.override { + evolution-data-server-gtk4 = super.evolution-data-server-gtk4.override { + inherit (super) webkitgtk_4_1 webkitgtk_6_0; + }; + }; + gnome-session = pkgs-gnome.gnome-session.override { + inherit (s) gnome-shell; + }; + gnome-control-center = pkgs-gnome.gnome-control-center; + gnome-initial-setup = pkgs-gnome.gnome-initial-setup.override { + inherit (super) webkitgtk_6_0; + }; + gnome-settings-daemon = pkgs-gnome.gnome-settings-daemon; + mutter = pkgs-gnome.mutter; + gdm = pkgs-gnome.gdm; + xdg-desktop-portal-gnome = pkgs-gnome.xdg-desktop-portal-gnome; + xdg-desktop-portal-gtk = pkgs-gnome.xdg-desktop-portal-gtk; + }); + + # NixOS usually takes its sweet time updating to latest GNOME. + # Enable this to use the GNOME version from their dedicated dev branch. + #WARN: build times may increase significantly! + useGnomeStaging = false; + in flake-utils.lib.eachDefaultSystem (system: let hostPkgs = import nixpkgs { inherit system; }; @@ -21,40 +50,32 @@ }) ]; }; - in localConfig.config.system.build.vm; + in localConfig.config.system.build.vm; + + checks = import ./tests { + system = testSystem; + pkgs = import nixpkgs { system = testSystem; }; + defaultConfig = { + imports = [ ./vm.nix ]; + nixpkgs.overlays = [ + (s: super: { paperwm = self.packages.${testSystem}.default; }) + + (if useGnomeStaging then gnomeOverlay else (s: super: {})) + ]; + }; + }; }) // { nixosConfigurations."testbox" = - let system = "x86_64-linux"; - pkgs-gnome = import nixpkgs-gnome { inherit system; }; - in nixpkgs.lib.nixosSystem { - inherit system; + nixpkgs.lib.nixosSystem { + system = testSystem; modules = [ ./vm.nix { nixpkgs.overlays = [ # Introduce PaperWM into our extensions - (s: super: { paperwm = self.packages.${system}.default; }) + (s: super: { paperwm = self.packages.${testSystem}.default; }) # Pull GNOME-specific packages from GNOME staging - #(s: super: { - # gnome-desktop = pkgs-gnome.gnome-desktop; - # gnome-shell = pkgs-gnome.gnome-shell.override { - # evolution-data-server-gtk4 = super.evolution-data-server-gtk4.override { - # inherit (super) webkitgtk_4_1 webkitgtk_6_0; - # }; - # }; - # gnome-session = pkgs-gnome.gnome-session.override { - # inherit (s) gnome-shell; - # }; - # gnome-control-center = pkgs-gnome.gnome-control-center; - # gnome-initial-setup = pkgs-gnome.gnome-initial-setup.override { - # inherit (super) webkitgtk_6_0; - # }; - # gnome-settings-daemon = pkgs-gnome.gnome-settings-daemon; - # mutter = pkgs-gnome.mutter; - # gdm = pkgs-gnome.gdm; - # xdg-desktop-portal-gnome = pkgs-gnome.xdg-desktop-portal-gnome; - # xdg-desktop-portal-gtk = pkgs-gnome.xdg-desktop-portal-gtk; - #}) + (if useGnomeStaging then gnomeOverlay else (s: super: {})) ]; } ]; diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..813b8191 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,23 @@ +# PaperWM end-to-end tests + +Unit tests on PaperWM are carried out using the [test VM](https://github.com/PaperWM/PaperWM/wiki/Using-the-test-VM), a NixOS virtual machine connected to a Python testing harness, and [Behave](https://behave.readthedocs.io), an implementation of the Gherkin unit testing language. + +## Layout + +### `default.nix` and `template.nix` + +These files are NixOS boilerplate code that scan for features in the `features` directory and generate test VMs accordingly. You can use them to register tests that require extra dependencies not found in the base test VM, such as specific misbehaving applications. + +### `features` + +This is the directory where Behave feature tests and their Python implementations are found. Each `.feature` file maps to a NixOS unit test, which can be overridden in `default.nix` as mentioned above. + +The usual testing loop is to record user input from within the VM, and replay them in the order specified in the feature file. + +### `recordings` + +This directory contains recordings of all input devices in the VM (touchpad, touchscreen, keyboard...), meant to be replayed as-is in the VM by the feature tests. Please only add recordings made from within the test VM. + +### `screenshots` + +This directory contains predicate screenshots to check against, to determine whether a test was successful. diff --git a/tests/default.nix b/tests/default.nix new file mode 100644 index 00000000..7992596f --- /dev/null +++ b/tests/default.nix @@ -0,0 +1,44 @@ +{ pkgs ? import {} +, system ? builtins.currentSystem +, runTest ? pkgs.testers.nixosTest +, defaultConfig ? + { ... }: { imports = [ ../vm.nix ]; } +, ... }: + +# +# Root file for the set of unit tests on PaperWM. These make use of the NixOS +# unit test framework, and individual tests can be registered as Behave feature +# files. +# Documentation on the unit test framework is available in the NixOS manual: +# +# https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests +# + +let + lib = pkgs.lib; + + # Run a single Behave feature file + behaveTest = featureName: as: runTest + (import ./template.nix ({ inherit defaultConfig pkgs featureName; } // as)); + + allBehaveTests = + let allBehaveFiles = + lib.filterAttrs (k: v: lib.hasSuffix ".feature" k && v == "regular") + (builtins.readDir ./features); + testName = s: lib.removeSuffix ".feature" s; + in builtins.foldl' + (l: r: l // { "${testName r}" = behaveTest r {}; }) + {} (builtins.attrNames allBehaveFiles); + +in allBehaveTests // +{ + # Tests that require a specific system configuration go here +} + +# Note: To run an individual unit test automatically (as part of the suite), +# run the following: +# nix build .#checks.x86_64-linux.(test name) +# +# To debug a test (i.e. run it interactively), the command isn't very different +# nix run .#checks.x86_64-linux.(test name).driverInteractive + diff --git a/tests/features/basic.feature b/tests/features/basic.feature new file mode 100644 index 00000000..aa92f170 --- /dev/null +++ b/tests/features/basic.feature @@ -0,0 +1,5 @@ +Feature: The test machine starts + + Scenario: The test machine starts + When the machine starts + Then the machine should reach graphics diff --git a/tests/features/steps/basic.py b/tests/features/steps/basic.py new file mode 100644 index 00000000..28c534fd --- /dev/null +++ b/tests/features/steps/basic.py @@ -0,0 +1,12 @@ +from behave import given, when, then +from types import SimpleNamespace + +@when("the machine starts") +def machine_boot(context): + nixos = SimpleNamespace(**context.config.userdata) + # no-op: our test template starts the machine already + +@then("the machine should reach graphics") +def graphical_target(context): + nixos = SimpleNamespace(**context.config.userdata) + nixos.machine.wait_for_unit("graphical.target") diff --git a/tests/template.nix b/tests/template.nix new file mode 100644 index 00000000..1086c63c --- /dev/null +++ b/tests/template.nix @@ -0,0 +1,23 @@ +{ pkgs, defaultConfig +, testsDir ? ./. +, featureName +, ... }@opts: + +{ + name = featureName; + nodes = { machine = defaultConfig; }; + + extraPythonPackages = p: with p; [ behave ]; + + skipTypeCheck = true; + + testScript = '' + from behave.configuration import Configuration + from behave.__main__ import run_behave + + conf = Configuration("${testsDir}/features/${featureName}", userdata = driver.test_symbols()) + start_all() + if run_behave(conf) != 0: + raise AssertionError("One or more Behave features have failed. Check the logs above for details.") + ''; +} // (pkgs.lib.filterAttrs (n: v: n != "pkgs" && n != "defaultConfig" && n != "testsDir" && n != "featureName") opts) From 56e6ff0f77ebb5af70744406a8fa5f58bc51f286 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Fri, 13 Mar 2026 04:56:11 +0100 Subject: [PATCH 02/16] Added test libinput playback --- tests/features/basic.feature | 6 + tests/features/steps/basic.py | 6 +- tests/features/steps/common.py | 14 + tests/features/steps/input.py | 7 + tests/recordings/three-finger-swipe.yaml | 1626 ++++++++++++++++++++++ tests/template.nix | 3 +- 6 files changed, 1657 insertions(+), 5 deletions(-) create mode 100644 tests/features/steps/common.py create mode 100644 tests/features/steps/input.py create mode 100644 tests/recordings/three-finger-swipe.yaml diff --git a/tests/features/basic.feature b/tests/features/basic.feature index aa92f170..04b605c6 100644 --- a/tests/features/basic.feature +++ b/tests/features/basic.feature @@ -1,5 +1,11 @@ Feature: The test machine starts + Basic scenario to make sure our virtual machine actually starts. + Demonstrates what a NixOS test in this repository looks like in practice. + Scenario: The test machine starts When the machine starts Then the machine should reach graphics + + Scenario: Three finger swipe (stub) + When the user performs three-finger-swipe diff --git a/tests/features/steps/basic.py b/tests/features/steps/basic.py index 28c534fd..26ad8cbb 100644 --- a/tests/features/steps/basic.py +++ b/tests/features/steps/basic.py @@ -1,12 +1,12 @@ from behave import given, when, then -from types import SimpleNamespace +from common import unpack @when("the machine starts") def machine_boot(context): - nixos = SimpleNamespace(**context.config.userdata) + nixos = unpack(context) # no-op: our test template starts the machine already @then("the machine should reach graphics") def graphical_target(context): - nixos = SimpleNamespace(**context.config.userdata) + nixos = unpack(context) nixos.machine.wait_for_unit("graphical.target") diff --git a/tests/features/steps/common.py b/tests/features/steps/common.py new file mode 100644 index 00000000..a7e415e0 --- /dev/null +++ b/tests/features/steps/common.py @@ -0,0 +1,14 @@ +from types import SimpleNamespace +from pathlib import Path + +def unpack(context): + ''' Shortcut to SimpleNamespace, helps unpack our NixOS test objects from the + userdata dict. + ''' + return SimpleNamespace(**context.config.userdata) + +def libinput_play(recording, nixos): + ''' Play the specified libinput recording file. + ''' + recordFile = Path().resolve() / "recordings" / recording + nixos.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) diff --git a/tests/features/steps/input.py b/tests/features/steps/input.py new file mode 100644 index 00000000..15ff9e25 --- /dev/null +++ b/tests/features/steps/input.py @@ -0,0 +1,7 @@ +from behave import given, when, then +from common import unpack, libinput_play + +@when("the user performs {gesture}") +def play_gesture(context, gesture): + nixos = unpack(context) + libinput_play(gesture + ".yaml", nixos) diff --git a/tests/recordings/three-finger-swipe.yaml b/tests/recordings/three-finger-swipe.yaml new file mode 100644 index 00000000..510a51d6 --- /dev/null +++ b/tests/recordings/three-finger-swipe.yaml @@ -0,0 +1,1626 @@ +# libinput record +version: 1 +ndevices: 1 +libinput: + version: "1.29.2" + git: "unknown" +system: + os: "fedora:43" + kernel: "6.18.13-200.fc43.x86_64" + dmi: "unknown" +devices: +- node: /dev/input/event6 + evdev: + # Name: VEN_0488:00 0488:102C Touchpad + # ID: bus 0x0018 (i2c) vendor 0x0488 product 0x102c version 0x0100 + # Size in mm: 111x68 + # Supported Events: + # Event type 0 (EV_SYN) + # Event type 1 (EV_KEY) + # Event code 272 (BTN_LEFT) + # Event code 325 (BTN_TOOL_FINGER) + # Event code 328 (BTN_TOOL_QUINTTAP) + # Event code 330 (BTN_TOUCH) + # Event code 333 (BTN_TOOL_DOUBLETAP) + # Event code 334 (BTN_TOOL_TRIPLETAP) + # Event code 335 (BTN_TOOL_QUADTAP) + # Event type 3 (EV_ABS) + # Event code 0 (ABS_X) + # Value 994 + # Min 0 + # Max 1448 + # Fuzz 0 + # Flat 0 + # Resolution 13 + # Event code 1 (ABS_Y) + # Value 230 + # Min 0 + # Max 894 + # Fuzz 0 + # Flat 0 + # Resolution 13 + # Event code 47 (ABS_MT_SLOT) + # Value 2 + # Min 0 + # Max 4 + # Fuzz 0 + # Flat 0 + # Resolution 0 + # Event code 53 (ABS_MT_POSITION_X) + # Value 0 + # Min 0 + # Max 1448 + # Fuzz 0 + # Flat 0 + # Resolution 13 + # Event code 54 (ABS_MT_POSITION_Y) + # Value 0 + # Min 0 + # Max 894 + # Fuzz 0 + # Flat 0 + # Resolution 13 + # Event code 55 (ABS_MT_TOOL_TYPE) + # Value 0 + # Min 0 + # Max 2 + # Fuzz 0 + # Flat 0 + # Resolution 0 + # Event code 57 (ABS_MT_TRACKING_ID) + # Value 0 + # Min 0 + # Max 65535 + # Fuzz 0 + # Flat 0 + # Resolution 0 + # Event type 4 (EV_MSC) + # Event code 5 (MSC_TIMESTAMP) + # Properties: + # Property 0 (INPUT_PROP_POINTER) + # Property 2 (INPUT_PROP_BUTTONPAD) + name: "VEN_0488:00 0488:102C Touchpad" + id: [24, 1160, 4140, 256] + codes: + 0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] # EV_SYN + 1: [272, 325, 328, 330, 333, 334, 335] # EV_KEY + 3: [0, 1, 47, 53, 54, 55, 57] # EV_ABS + 4: [5] # EV_MSC + absinfo: + 0: [0, 1448, 0, 0, 13] + 1: [0, 894, 0, 0, 13] + 47: [0, 4, 0, 0, 0] + 53: [0, 1448, 0, 0, 13] + 54: [0, 894, 0, 0, 13] + 55: [0, 2, 0, 0, 0] + 57: [0, 65535, 0, 0, 0] + properties: [0, 2] + hid: [ + 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x85, 0x06, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, + 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, + 0x81, 0x03, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, + 0x95, 0x03, 0x81, 0x06, 0xc0, 0xc0, 0x05, 0x0d, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x22, + 0xa1, 0x02, 0x15, 0x00, 0x25, 0x01, 0x09, 0x47, 0x09, 0x42, 0x95, 0x02, 0x75, 0x01, 0x81, 0x02, + 0x95, 0x01, 0x75, 0x03, 0x25, 0x05, 0x09, 0x51, 0x81, 0x02, 0x81, 0x03, 0x05, 0x01, 0x15, 0x00, + 0x26, 0xa8, 0x05, 0x75, 0x10, 0x55, 0x0e, 0x65, 0x11, 0x09, 0x30, 0x35, 0x00, 0x46, 0x7e, 0x04, + 0x95, 0x01, 0x81, 0x02, 0x26, 0x7e, 0x03, 0x46, 0xc6, 0x02, 0x09, 0x31, 0x81, 0x02, 0xc0, 0x55, + 0x0c, 0x66, 0x01, 0x10, 0x47, 0xff, 0xff, 0x00, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x75, 0x10, + 0x95, 0x01, 0x05, 0x0d, 0x09, 0x56, 0x81, 0x02, 0x09, 0x54, 0x25, 0x05, 0x95, 0x01, 0x75, 0x08, + 0x81, 0x02, 0x05, 0x09, 0x09, 0x01, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x81, 0x02, 0x95, 0x07, + 0x81, 0x03, 0x05, 0x0d, 0x85, 0x02, 0x09, 0x55, 0x75, 0x08, 0x95, 0x01, 0x25, 0x05, 0xb1, 0x02, + 0x09, 0x59, 0xb1, 0x02, 0x06, 0x00, 0xff, 0x85, 0x03, 0x09, 0xc5, 0x15, 0x00, 0x26, 0xff, 0x00, + 0x75, 0x08, 0x96, 0x00, 0x01, 0xb1, 0x02, 0xc0, 0x05, 0x0d, 0x09, 0x0e, 0xa1, 0x01, 0x85, 0x04, + 0x09, 0x22, 0xa1, 0x02, 0x09, 0x52, 0x15, 0x00, 0x25, 0x0a, 0x75, 0x08, 0x95, 0x01, 0xb1, 0x02, + 0xc0, 0x09, 0x22, 0xa1, 0x00, 0x85, 0x05, 0x09, 0x57, 0x09, 0x58, 0x75, 0x01, 0x95, 0x02, 0x25, + 0x01, 0xb1, 0x02, 0x95, 0x06, 0xb1, 0x03, 0xc0, 0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, + 0x85, 0x09, 0x19, 0x01, 0x29, 0x08, 0x15, 0x80, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x32, 0x81, 0x02, + 0xc0, 0x06, 0x01, 0xff, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x00, 0x85, 0x07, 0x15, 0x00, 0x26, 0xff, + 0x00, 0x75, 0x08, 0x96, 0x12, 0x02, 0xb1, 0x02, 0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, + 0x85, 0x0d, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x0d, 0x09, 0x01, 0x81, 0x02, 0x09, + 0x01, 0x91, 0x02, 0xc0 + ] + udev: + properties: + - ID_INPUT=1 + - ID_INPUT_HEIGHT_MM=68 + - ID_INPUT_TOUCHPAD=1 + - ID_INPUT_WIDTH_MM=111 + - LIBINPUT_DEVICE_GROUP=18/488/102c:i2c-VEN_0488:00 + - DRIVER=hid-multitouch + virtual: false + quirks: + - ModelTouchpadVisibleMarker=1 + - AttrMscTimestamp=watch + - AttrPalmPressureThreshold=180 + events: + # Current time is 04:30:33 + # Current time is 04:30:36 + - evdev: + - [ 0, 0, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 0, 3, 57, 1985] # EV_ABS / ABS_MT_TRACKING_ID 1985 + - [ 0, 0, 3, 53, 481] # EV_ABS / ABS_MT_POSITION_X 481 (-513) + - [ 0, 0, 3, 54, 532] # EV_ABS / ABS_MT_POSITION_Y 532 (+302) + - [ 0, 0, 1, 330, 1] # EV_KEY / BTN_TOUCH 1 + - [ 0, 0, 1, 325, 1] # EV_KEY / BTN_TOOL_FINGER 1 + - [ 0, 0, 3, 0, 481] # EV_ABS / ABS_X 481 (-513) + - [ 0, 0, 3, 1, 532] # EV_ABS / ABS_Y 532 (+302) + - [ 0, 0, 4, 5, 0] # EV_MSC / MSC_TIMESTAMP 0 + - [ 0, 0, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +0ms + - evdev: + - [ 0, 1695, 4, 5, 5900] # EV_MSC / MSC_TIMESTAMP 5900 + - [ 0, 1695, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +1ms + - evdev: + - [ 0, 3543, 4, 5, 11800] # EV_MSC / MSC_TIMESTAMP 11800 + - [ 0, 3543, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +2ms + - evdev: + - [ 0, 9120, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 9120, 3, 57, 1986] # EV_ABS / ABS_MT_TRACKING_ID 1986 + - [ 0, 9120, 3, 53, 605] # EV_ABS / ABS_MT_POSITION_X 605 (+72) + - [ 0, 9120, 3, 54, 303] # EV_ABS / ABS_MT_POSITION_Y 303 (-231) + - [ 0, 9120, 1, 325, 0] # EV_KEY / BTN_TOOL_FINGER 0 + - [ 0, 9120, 1, 333, 1] # EV_KEY / BTN_TOOL_DOUBLETAP 1 + - [ 0, 9120, 4, 5, 43800] # EV_MSC / MSC_TIMESTAMP 43800 + - [ 0, 9120, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 15869, 4, 5, 49200] # EV_MSC / MSC_TIMESTAMP 49200 + - [ 0, 15869, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 21813, 4, 5, 57300] # EV_MSC / MSC_TIMESTAMP 57300 + - [ 0, 21813, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 31886, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 31886, 3, 57, 1987] # EV_ABS / ABS_MT_TRACKING_ID 1987 + - [ 0, 31886, 3, 53, 948] # EV_ABS / ABS_MT_POSITION_X 948 (+286) + - [ 0, 31886, 3, 54, 188] # EV_ABS / ABS_MT_POSITION_Y 188 (-145) + - [ 0, 31886, 1, 333, 0] # EV_KEY / BTN_TOOL_DOUBLETAP 0 + - [ 0, 31886, 1, 334, 1] # EV_KEY / BTN_TOOL_TRIPLETAP 1 + - [ 0, 31886, 4, 5, 67200] # EV_MSC / MSC_TIMESTAMP 67200 + - [ 0, 31886, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +10ms + - evdev: + - [ 0, 37913, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 37913, 3, 53, 482] # EV_ABS / ABS_MT_POSITION_X 482 (+1) + - [ 0, 37913, 3, 0, 482] # EV_ABS / ABS_X 482 (+1) + - [ 0, 37913, 4, 5, 71800] # EV_MSC / MSC_TIMESTAMP 71800 + - [ 0, 37913, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 44342, 3, 53, 483] # EV_ABS / ABS_MT_POSITION_X 483 (+1) + - [ 0, 44342, 3, 54, 533] # EV_ABS / ABS_MT_POSITION_Y 533 (+1) + - [ 0, 44342, 3, 0, 483] # EV_ABS / ABS_X 483 (+1) + - [ 0, 44342, 3, 1, 533] # EV_ABS / ABS_Y 533 (+1) + - [ 0, 44342, 4, 5, 78700] # EV_MSC / MSC_TIMESTAMP 78700 + - [ 0, 44342, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 50967, 3, 53, 484] # EV_ABS / ABS_MT_POSITION_X 484 (+1) + - [ 0, 50967, 3, 0, 484] # EV_ABS / ABS_X 484 (+1) + - [ 0, 50967, 4, 5, 85700] # EV_MSC / MSC_TIMESTAMP 85700 + - [ 0, 50967, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 57664, 3, 53, 489] # EV_ABS / ABS_MT_POSITION_X 489 (+5) + - [ 0, 57664, 3, 54, 534] # EV_ABS / ABS_MT_POSITION_Y 534 (+1) + - [ 0, 57664, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 57664, 3, 53, 950] # EV_ABS / ABS_MT_POSITION_X 950 (+2) + - [ 0, 57664, 3, 0, 489] # EV_ABS / ABS_X 489 (+5) + - [ 0, 57664, 3, 1, 534] # EV_ABS / ABS_Y 534 (+1) + - [ 0, 57664, 4, 5, 92800] # EV_MSC / MSC_TIMESTAMP 92800 + - [ 0, 57664, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 64474, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 64474, 3, 53, 493] # EV_ABS / ABS_MT_POSITION_X 493 (+4) + - [ 0, 64474, 3, 54, 535] # EV_ABS / ABS_MT_POSITION_Y 535 (+1) + - [ 0, 64474, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 64474, 3, 53, 951] # EV_ABS / ABS_MT_POSITION_X 951 (+1) + - [ 0, 64474, 3, 54, 189] # EV_ABS / ABS_MT_POSITION_Y 189 (+1) + - [ 0, 64474, 3, 0, 493] # EV_ABS / ABS_X 493 (+4) + - [ 0, 64474, 3, 1, 535] # EV_ABS / ABS_Y 535 (+1) + - [ 0, 64474, 4, 5, 97400] # EV_MSC / MSC_TIMESTAMP 97400 + - [ 0, 64474, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 71162, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 71162, 3, 53, 500] # EV_ABS / ABS_MT_POSITION_X 500 (+7) + - [ 0, 71162, 3, 54, 536] # EV_ABS / ABS_MT_POSITION_Y 536 (+1) + - [ 0, 71162, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 71162, 3, 53, 954] # EV_ABS / ABS_MT_POSITION_X 954 (+3) + - [ 0, 71162, 3, 54, 190] # EV_ABS / ABS_MT_POSITION_Y 190 (+1) + - [ 0, 71162, 3, 0, 500] # EV_ABS / ABS_X 500 (+7) + - [ 0, 71162, 3, 1, 536] # EV_ABS / ABS_Y 536 (+1) + - [ 0, 71162, 4, 5, 104500] # EV_MSC / MSC_TIMESTAMP 104500 + - [ 0, 71162, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 77846, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 77846, 3, 53, 508] # EV_ABS / ABS_MT_POSITION_X 508 (+8) + - [ 0, 77846, 3, 54, 537] # EV_ABS / ABS_MT_POSITION_Y 537 (+1) + - [ 0, 77846, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 77846, 3, 53, 607] # EV_ABS / ABS_MT_POSITION_X 607 (+2) + - [ 0, 77846, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 77846, 3, 53, 959] # EV_ABS / ABS_MT_POSITION_X 959 (+5) + - [ 0, 77846, 3, 54, 192] # EV_ABS / ABS_MT_POSITION_Y 192 (+2) + - [ 0, 77846, 3, 0, 508] # EV_ABS / ABS_X 508 (+8) + - [ 0, 77846, 3, 1, 537] # EV_ABS / ABS_Y 537 (+1) + - [ 0, 77846, 4, 5, 111600] # EV_MSC / MSC_TIMESTAMP 111600 + - [ 0, 77846, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 84448, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 84448, 3, 53, 520] # EV_ABS / ABS_MT_POSITION_X 520 (+12) + - [ 0, 84448, 3, 54, 538] # EV_ABS / ABS_MT_POSITION_Y 538 (+1) + - [ 0, 84448, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 84448, 3, 53, 611] # EV_ABS / ABS_MT_POSITION_X 611 (+4) + - [ 0, 84448, 3, 54, 304] # EV_ABS / ABS_MT_POSITION_Y 304 (+1) + - [ 0, 84448, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 84448, 3, 53, 968] # EV_ABS / ABS_MT_POSITION_X 968 (+9) + - [ 0, 84448, 3, 54, 195] # EV_ABS / ABS_MT_POSITION_Y 195 (+3) + - [ 0, 84448, 3, 0, 520] # EV_ABS / ABS_X 520 (+12) + - [ 0, 84448, 3, 1, 538] # EV_ABS / ABS_Y 538 (+1) + - [ 0, 84448, 4, 5, 118700] # EV_MSC / MSC_TIMESTAMP 118700 + - [ 0, 84448, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 91302, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 91302, 3, 53, 526] # EV_ABS / ABS_MT_POSITION_X 526 (+6) + - [ 0, 91302, 3, 54, 539] # EV_ABS / ABS_MT_POSITION_Y 539 (+1) + - [ 0, 91302, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 91302, 3, 53, 613] # EV_ABS / ABS_MT_POSITION_X 613 (+2) + - [ 0, 91302, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 91302, 3, 53, 973] # EV_ABS / ABS_MT_POSITION_X 973 (+5) + - [ 0, 91302, 3, 54, 197] # EV_ABS / ABS_MT_POSITION_Y 197 (+2) + - [ 0, 91302, 3, 0, 526] # EV_ABS / ABS_X 526 (+6) + - [ 0, 91302, 3, 1, 539] # EV_ABS / ABS_Y 539 (+1) + - [ 0, 91302, 4, 5, 123400] # EV_MSC / MSC_TIMESTAMP 123400 + - [ 0, 91302, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 97945, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 97945, 3, 53, 532] # EV_ABS / ABS_MT_POSITION_X 532 (+6) + - [ 0, 97945, 3, 54, 540] # EV_ABS / ABS_MT_POSITION_Y 540 (+1) + - [ 0, 97945, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 97945, 3, 53, 619] # EV_ABS / ABS_MT_POSITION_X 619 (+6) + - [ 0, 97945, 3, 54, 305] # EV_ABS / ABS_MT_POSITION_Y 305 (+1) + - [ 0, 97945, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 97945, 3, 53, 981] # EV_ABS / ABS_MT_POSITION_X 981 (+8) + - [ 0, 97945, 3, 54, 200] # EV_ABS / ABS_MT_POSITION_Y 200 (+3) + - [ 0, 97945, 3, 0, 532] # EV_ABS / ABS_X 532 (+6) + - [ 0, 97945, 3, 1, 540] # EV_ABS / ABS_Y 540 (+1) + - [ 0, 97945, 4, 5, 130500] # EV_MSC / MSC_TIMESTAMP 130500 + - [ 0, 97945, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 104574, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 104574, 3, 53, 537] # EV_ABS / ABS_MT_POSITION_X 537 (+5) + - [ 0, 104574, 3, 54, 541] # EV_ABS / ABS_MT_POSITION_Y 541 (+1) + - [ 0, 104574, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 104574, 3, 53, 629] # EV_ABS / ABS_MT_POSITION_X 629 (+10) + - [ 0, 104574, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 104574, 3, 53, 992] # EV_ABS / ABS_MT_POSITION_X 992 (+11) + - [ 0, 104574, 3, 54, 203] # EV_ABS / ABS_MT_POSITION_Y 203 (+3) + - [ 0, 104574, 3, 0, 537] # EV_ABS / ABS_X 537 (+5) + - [ 0, 104574, 3, 1, 541] # EV_ABS / ABS_Y 541 (+1) + - [ 0, 104574, 4, 5, 137500] # EV_MSC / MSC_TIMESTAMP 137500 + - [ 0, 104574, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 111212, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 111212, 3, 53, 541] # EV_ABS / ABS_MT_POSITION_X 541 (+4) + - [ 0, 111212, 3, 54, 542] # EV_ABS / ABS_MT_POSITION_Y 542 (+1) + - [ 0, 111212, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 111212, 3, 53, 634] # EV_ABS / ABS_MT_POSITION_X 634 (+5) + - [ 0, 111212, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 111212, 3, 53, 998] # EV_ABS / ABS_MT_POSITION_X 998 (+6) + - [ 0, 111212, 3, 54, 205] # EV_ABS / ABS_MT_POSITION_Y 205 (+2) + - [ 0, 111212, 3, 0, 541] # EV_ABS / ABS_X 541 (+4) + - [ 0, 111212, 3, 1, 542] # EV_ABS / ABS_Y 542 (+1) + - [ 0, 111212, 4, 5, 142400] # EV_MSC / MSC_TIMESTAMP 142400 + - [ 0, 111212, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 117773, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 117773, 3, 53, 547] # EV_ABS / ABS_MT_POSITION_X 547 (+6) + - [ 0, 117773, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 117773, 3, 53, 643] # EV_ABS / ABS_MT_POSITION_X 643 (+9) + - [ 0, 117773, 3, 54, 306] # EV_ABS / ABS_MT_POSITION_Y 306 (+1) + - [ 0, 117773, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 117773, 3, 53, 1005] # EV_ABS / ABS_MT_POSITION_X 1005 (+7) + - [ 0, 117773, 3, 54, 207] # EV_ABS / ABS_MT_POSITION_Y 207 (+2) + - [ 0, 117773, 3, 0, 547] # EV_ABS / ABS_X 547 (+6) + - [ 0, 117773, 4, 5, 149600] # EV_MSC / MSC_TIMESTAMP 149600 + - [ 0, 117773, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 124873, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 124873, 3, 53, 552] # EV_ABS / ABS_MT_POSITION_X 552 (+5) + - [ 0, 124873, 3, 54, 543] # EV_ABS / ABS_MT_POSITION_Y 543 (+1) + - [ 0, 124873, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 124873, 3, 53, 655] # EV_ABS / ABS_MT_POSITION_X 655 (+12) + - [ 0, 124873, 3, 54, 308] # EV_ABS / ABS_MT_POSITION_Y 308 (+2) + - [ 0, 124873, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 124873, 3, 53, 1011] # EV_ABS / ABS_MT_POSITION_X 1011 (+6) + - [ 0, 124873, 3, 54, 209] # EV_ABS / ABS_MT_POSITION_Y 209 (+2) + - [ 0, 124873, 3, 0, 552] # EV_ABS / ABS_X 552 (+5) + - [ 0, 124873, 3, 1, 543] # EV_ABS / ABS_Y 543 (+1) + - [ 0, 124873, 4, 5, 156800] # EV_MSC / MSC_TIMESTAMP 156800 + - [ 0, 124873, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 131179, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 131179, 3, 53, 557] # EV_ABS / ABS_MT_POSITION_X 557 (+5) + - [ 0, 131179, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 131179, 3, 53, 663] # EV_ABS / ABS_MT_POSITION_X 663 (+8) + - [ 0, 131179, 3, 54, 309] # EV_ABS / ABS_MT_POSITION_Y 309 (+1) + - [ 0, 131179, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 131179, 3, 53, 1018] # EV_ABS / ABS_MT_POSITION_X 1018 (+7) + - [ 0, 131179, 3, 54, 211] # EV_ABS / ABS_MT_POSITION_Y 211 (+2) + - [ 0, 131179, 3, 0, 557] # EV_ABS / ABS_X 557 (+5) + - [ 0, 131179, 4, 5, 163800] # EV_MSC / MSC_TIMESTAMP 163800 + - [ 0, 131179, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 137960, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 137960, 3, 53, 563] # EV_ABS / ABS_MT_POSITION_X 563 (+6) + - [ 0, 137960, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 137960, 3, 53, 668] # EV_ABS / ABS_MT_POSITION_X 668 (+5) + - [ 0, 137960, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 137960, 3, 53, 1025] # EV_ABS / ABS_MT_POSITION_X 1025 (+7) + - [ 0, 137960, 3, 54, 212] # EV_ABS / ABS_MT_POSITION_Y 212 (+1) + - [ 0, 137960, 3, 0, 563] # EV_ABS / ABS_X 563 (+6) + - [ 0, 137960, 4, 5, 170700] # EV_MSC / MSC_TIMESTAMP 170700 + - [ 0, 137960, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 144503, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 144503, 3, 53, 566] # EV_ABS / ABS_MT_POSITION_X 566 (+3) + - [ 0, 144503, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 144503, 3, 53, 669] # EV_ABS / ABS_MT_POSITION_X 669 (+1) + - [ 0, 144503, 3, 54, 308] # EV_ABS / ABS_MT_POSITION_Y 308 (-1) + - [ 0, 144503, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 144503, 3, 53, 1029] # EV_ABS / ABS_MT_POSITION_X 1029 (+4) + - [ 0, 144503, 3, 54, 213] # EV_ABS / ABS_MT_POSITION_Y 213 (+1) + - [ 0, 144503, 3, 0, 566] # EV_ABS / ABS_X 566 (+3) + - [ 0, 144503, 4, 5, 175400] # EV_MSC / MSC_TIMESTAMP 175400 + - [ 0, 144503, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 150764, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 150764, 3, 53, 571] # EV_ABS / ABS_MT_POSITION_X 571 (+5) + - [ 0, 150764, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 150764, 3, 53, 675] # EV_ABS / ABS_MT_POSITION_X 675 (+6) + - [ 0, 150764, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 150764, 3, 53, 1036] # EV_ABS / ABS_MT_POSITION_X 1036 (+7) + - [ 0, 150764, 3, 54, 214] # EV_ABS / ABS_MT_POSITION_Y 214 (+1) + - [ 0, 150764, 3, 0, 571] # EV_ABS / ABS_X 571 (+5) + - [ 0, 150764, 4, 5, 182500] # EV_MSC / MSC_TIMESTAMP 182500 + - [ 0, 150764, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 158808, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 158808, 3, 53, 577] # EV_ABS / ABS_MT_POSITION_X 577 (+6) + - [ 0, 158808, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 158808, 3, 53, 681] # EV_ABS / ABS_MT_POSITION_X 681 (+6) + - [ 0, 158808, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 158808, 3, 53, 1042] # EV_ABS / ABS_MT_POSITION_X 1042 (+6) + - [ 0, 158808, 3, 54, 215] # EV_ABS / ABS_MT_POSITION_Y 215 (+1) + - [ 0, 158808, 3, 0, 577] # EV_ABS / ABS_X 577 (+6) + - [ 0, 158808, 4, 5, 189600] # EV_MSC / MSC_TIMESTAMP 189600 + - [ 0, 158808, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +8ms + - evdev: + - [ 0, 164912, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 164912, 3, 53, 581] # EV_ABS / ABS_MT_POSITION_X 581 (+4) + - [ 0, 164912, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 164912, 3, 53, 686] # EV_ABS / ABS_MT_POSITION_X 686 (+5) + - [ 0, 164912, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 164912, 3, 53, 1046] # EV_ABS / ABS_MT_POSITION_X 1046 (+4) + - [ 0, 164912, 3, 54, 216] # EV_ABS / ABS_MT_POSITION_Y 216 (+1) + - [ 0, 164912, 3, 0, 581] # EV_ABS / ABS_X 581 (+4) + - [ 0, 164912, 4, 5, 194300] # EV_MSC / MSC_TIMESTAMP 194300 + - [ 0, 164912, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 171513, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 171513, 3, 53, 586] # EV_ABS / ABS_MT_POSITION_X 586 (+5) + - [ 0, 171513, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 171513, 3, 53, 692] # EV_ABS / ABS_MT_POSITION_X 692 (+6) + - [ 0, 171513, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 171513, 3, 53, 1052] # EV_ABS / ABS_MT_POSITION_X 1052 (+6) + - [ 0, 171513, 3, 54, 217] # EV_ABS / ABS_MT_POSITION_Y 217 (+1) + - [ 0, 171513, 3, 0, 586] # EV_ABS / ABS_X 586 (+5) + - [ 0, 171513, 4, 5, 201600] # EV_MSC / MSC_TIMESTAMP 201600 + - [ 0, 171513, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 178232, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 178232, 3, 53, 591] # EV_ABS / ABS_MT_POSITION_X 591 (+5) + - [ 0, 178232, 3, 54, 542] # EV_ABS / ABS_MT_POSITION_Y 542 (-1) + - [ 0, 178232, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 178232, 3, 53, 698] # EV_ABS / ABS_MT_POSITION_X 698 (+6) + - [ 0, 178232, 3, 54, 307] # EV_ABS / ABS_MT_POSITION_Y 307 (-1) + - [ 0, 178232, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 178232, 3, 53, 1058] # EV_ABS / ABS_MT_POSITION_X 1058 (+6) + - [ 0, 178232, 3, 54, 218] # EV_ABS / ABS_MT_POSITION_Y 218 (+1) + - [ 0, 178232, 3, 0, 591] # EV_ABS / ABS_X 591 (+5) + - [ 0, 178232, 3, 1, 542] # EV_ABS / ABS_Y 542 (-1) + - [ 0, 178232, 4, 5, 208800] # EV_MSC / MSC_TIMESTAMP 208800 + - [ 0, 178232, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 184834, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 184834, 3, 53, 594] # EV_ABS / ABS_MT_POSITION_X 594 (+3) + - [ 0, 184834, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 184834, 3, 53, 702] # EV_ABS / ABS_MT_POSITION_X 702 (+4) + - [ 0, 184834, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 184834, 3, 53, 1062] # EV_ABS / ABS_MT_POSITION_X 1062 (+4) + - [ 0, 184834, 3, 0, 594] # EV_ABS / ABS_X 594 (+3) + - [ 0, 184834, 4, 5, 213600] # EV_MSC / MSC_TIMESTAMP 213600 + - [ 0, 184834, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 191528, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 191528, 3, 53, 599] # EV_ABS / ABS_MT_POSITION_X 599 (+5) + - [ 0, 191528, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 191528, 3, 53, 708] # EV_ABS / ABS_MT_POSITION_X 708 (+6) + - [ 0, 191528, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 191528, 3, 53, 1068] # EV_ABS / ABS_MT_POSITION_X 1068 (+6) + - [ 0, 191528, 3, 54, 219] # EV_ABS / ABS_MT_POSITION_Y 219 (+1) + - [ 0, 191528, 3, 0, 599] # EV_ABS / ABS_X 599 (+5) + - [ 0, 191528, 4, 5, 220900] # EV_MSC / MSC_TIMESTAMP 220900 + - [ 0, 191528, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 198101, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 198101, 3, 53, 603] # EV_ABS / ABS_MT_POSITION_X 603 (+4) + - [ 0, 198101, 3, 54, 541] # EV_ABS / ABS_MT_POSITION_Y 541 (-1) + - [ 0, 198101, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 198101, 3, 53, 712] # EV_ABS / ABS_MT_POSITION_X 712 (+4) + - [ 0, 198101, 3, 54, 306] # EV_ABS / ABS_MT_POSITION_Y 306 (-1) + - [ 0, 198101, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 198101, 3, 53, 1074] # EV_ABS / ABS_MT_POSITION_X 1074 (+6) + - [ 0, 198101, 3, 0, 603] # EV_ABS / ABS_X 603 (+4) + - [ 0, 198101, 3, 1, 541] # EV_ABS / ABS_Y 541 (-1) + - [ 0, 198101, 4, 5, 228100] # EV_MSC / MSC_TIMESTAMP 228100 + - [ 0, 198101, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 205042, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 205042, 3, 53, 608] # EV_ABS / ABS_MT_POSITION_X 608 (+5) + - [ 0, 205042, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 205042, 3, 53, 717] # EV_ABS / ABS_MT_POSITION_X 717 (+5) + - [ 0, 205042, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 205042, 3, 53, 1080] # EV_ABS / ABS_MT_POSITION_X 1080 (+6) + - [ 0, 205042, 3, 0, 608] # EV_ABS / ABS_X 608 (+5) + - [ 0, 205042, 4, 5, 235400] # EV_MSC / MSC_TIMESTAMP 235400 + - [ 0, 205042, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 211804, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 211804, 3, 53, 611] # EV_ABS / ABS_MT_POSITION_X 611 (+3) + - [ 0, 211804, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 211804, 3, 53, 720] # EV_ABS / ABS_MT_POSITION_X 720 (+3) + - [ 0, 211804, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 211804, 3, 53, 1084] # EV_ABS / ABS_MT_POSITION_X 1084 (+4) + - [ 0, 211804, 3, 0, 611] # EV_ABS / ABS_X 611 (+3) + - [ 0, 211804, 4, 5, 240100] # EV_MSC / MSC_TIMESTAMP 240100 + - [ 0, 211804, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 218465, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 218465, 3, 53, 617] # EV_ABS / ABS_MT_POSITION_X 617 (+6) + - [ 0, 218465, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 218465, 3, 53, 724] # EV_ABS / ABS_MT_POSITION_X 724 (+4) + - [ 0, 218465, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 218465, 3, 53, 1089] # EV_ABS / ABS_MT_POSITION_X 1089 (+5) + - [ 0, 218465, 3, 54, 220] # EV_ABS / ABS_MT_POSITION_Y 220 (+1) + - [ 0, 218465, 3, 0, 617] # EV_ABS / ABS_X 617 (+6) + - [ 0, 218465, 4, 5, 247200] # EV_MSC / MSC_TIMESTAMP 247200 + - [ 0, 218465, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 224839, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 224839, 3, 53, 623] # EV_ABS / ABS_MT_POSITION_X 623 (+6) + - [ 0, 224839, 3, 54, 542] # EV_ABS / ABS_MT_POSITION_Y 542 (+1) + - [ 0, 224839, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 224839, 3, 53, 729] # EV_ABS / ABS_MT_POSITION_X 729 (+5) + - [ 0, 224839, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 224839, 3, 53, 1094] # EV_ABS / ABS_MT_POSITION_X 1094 (+5) + - [ 0, 224839, 3, 0, 623] # EV_ABS / ABS_X 623 (+6) + - [ 0, 224839, 3, 1, 542] # EV_ABS / ABS_Y 542 (+1) + - [ 0, 224839, 4, 5, 254300] # EV_MSC / MSC_TIMESTAMP 254300 + - [ 0, 224839, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 231919, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 231919, 3, 53, 628] # EV_ABS / ABS_MT_POSITION_X 628 (+5) + - [ 0, 231919, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 231919, 3, 53, 733] # EV_ABS / ABS_MT_POSITION_X 733 (+4) + - [ 0, 231919, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 231919, 3, 53, 1099] # EV_ABS / ABS_MT_POSITION_X 1099 (+5) + - [ 0, 231919, 3, 54, 221] # EV_ABS / ABS_MT_POSITION_Y 221 (+1) + - [ 0, 231919, 3, 0, 628] # EV_ABS / ABS_X 628 (+5) + - [ 0, 231919, 4, 5, 261300] # EV_MSC / MSC_TIMESTAMP 261300 + - [ 0, 231919, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 238222, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 238222, 3, 53, 633] # EV_ABS / ABS_MT_POSITION_X 633 (+5) + - [ 0, 238222, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 238222, 3, 53, 738] # EV_ABS / ABS_MT_POSITION_X 738 (+5) + - [ 0, 238222, 3, 54, 305] # EV_ABS / ABS_MT_POSITION_Y 305 (-1) + - [ 0, 238222, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 238222, 3, 53, 1103] # EV_ABS / ABS_MT_POSITION_X 1103 (+4) + - [ 0, 238222, 3, 0, 633] # EV_ABS / ABS_X 633 (+5) + - [ 0, 238222, 4, 5, 268400] # EV_MSC / MSC_TIMESTAMP 268400 + - [ 0, 238222, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 244960, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 244960, 3, 53, 636] # EV_ABS / ABS_MT_POSITION_X 636 (+3) + - [ 0, 244960, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 244960, 3, 53, 741] # EV_ABS / ABS_MT_POSITION_X 741 (+3) + - [ 0, 244960, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 244960, 3, 53, 1107] # EV_ABS / ABS_MT_POSITION_X 1107 (+4) + - [ 0, 244960, 3, 0, 636] # EV_ABS / ABS_X 636 (+3) + - [ 0, 244960, 4, 5, 273100] # EV_MSC / MSC_TIMESTAMP 273100 + - [ 0, 244960, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 251737, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 251737, 3, 53, 640] # EV_ABS / ABS_MT_POSITION_X 640 (+4) + - [ 0, 251737, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 251737, 3, 53, 745] # EV_ABS / ABS_MT_POSITION_X 745 (+4) + - [ 0, 251737, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 251737, 3, 53, 1111] # EV_ABS / ABS_MT_POSITION_X 1111 (+4) + - [ 0, 251737, 3, 0, 640] # EV_ABS / ABS_X 640 (+4) + - [ 0, 251737, 4, 5, 280400] # EV_MSC / MSC_TIMESTAMP 280400 + - [ 0, 251737, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 258472, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 258472, 3, 53, 643] # EV_ABS / ABS_MT_POSITION_X 643 (+3) + - [ 0, 258472, 3, 54, 541] # EV_ABS / ABS_MT_POSITION_Y 541 (-1) + - [ 0, 258472, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 258472, 3, 53, 749] # EV_ABS / ABS_MT_POSITION_X 749 (+4) + - [ 0, 258472, 3, 54, 304] # EV_ABS / ABS_MT_POSITION_Y 304 (-1) + - [ 0, 258472, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 258472, 3, 53, 1114] # EV_ABS / ABS_MT_POSITION_X 1114 (+3) + - [ 0, 258472, 3, 0, 643] # EV_ABS / ABS_X 643 (+3) + - [ 0, 258472, 3, 1, 541] # EV_ABS / ABS_Y 541 (-1) + - [ 0, 258472, 4, 5, 285200] # EV_MSC / MSC_TIMESTAMP 285200 + - [ 0, 258472, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 265372, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 265372, 3, 53, 647] # EV_ABS / ABS_MT_POSITION_X 647 (+4) + - [ 0, 265372, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 265372, 3, 53, 754] # EV_ABS / ABS_MT_POSITION_X 754 (+5) + - [ 0, 265372, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 265372, 3, 53, 1117] # EV_ABS / ABS_MT_POSITION_X 1117 (+3) + - [ 0, 265372, 3, 0, 647] # EV_ABS / ABS_X 647 (+4) + - [ 0, 265372, 4, 5, 292500] # EV_MSC / MSC_TIMESTAMP 292500 + - [ 0, 265372, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 271753, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 271753, 3, 53, 652] # EV_ABS / ABS_MT_POSITION_X 652 (+5) + - [ 0, 271753, 3, 54, 540] # EV_ABS / ABS_MT_POSITION_Y 540 (-1) + - [ 0, 271753, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 271753, 3, 53, 758] # EV_ABS / ABS_MT_POSITION_X 758 (+4) + - [ 0, 271753, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 271753, 3, 53, 1121] # EV_ABS / ABS_MT_POSITION_X 1121 (+4) + - [ 0, 271753, 3, 0, 652] # EV_ABS / ABS_X 652 (+5) + - [ 0, 271753, 3, 1, 540] # EV_ABS / ABS_Y 540 (-1) + - [ 0, 271753, 4, 5, 299700] # EV_MSC / MSC_TIMESTAMP 299700 + - [ 0, 271753, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 278720, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 278720, 3, 53, 654] # EV_ABS / ABS_MT_POSITION_X 654 (+2) + - [ 0, 278720, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 278720, 3, 53, 761] # EV_ABS / ABS_MT_POSITION_X 761 (+3) + - [ 0, 278720, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 278720, 3, 53, 1124] # EV_ABS / ABS_MT_POSITION_X 1124 (+3) + - [ 0, 278720, 3, 54, 222] # EV_ABS / ABS_MT_POSITION_Y 222 (+1) + - [ 0, 278720, 3, 0, 654] # EV_ABS / ABS_X 654 (+2) + - [ 0, 278720, 4, 5, 304600] # EV_MSC / MSC_TIMESTAMP 304600 + - [ 0, 278720, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 285221, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 285221, 3, 53, 657] # EV_ABS / ABS_MT_POSITION_X 657 (+3) + - [ 0, 285221, 3, 54, 539] # EV_ABS / ABS_MT_POSITION_Y 539 (-1) + - [ 0, 285221, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 285221, 3, 53, 765] # EV_ABS / ABS_MT_POSITION_X 765 (+4) + - [ 0, 285221, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 285221, 3, 53, 1127] # EV_ABS / ABS_MT_POSITION_X 1127 (+3) + - [ 0, 285221, 3, 0, 657] # EV_ABS / ABS_X 657 (+3) + - [ 0, 285221, 3, 1, 539] # EV_ABS / ABS_Y 539 (-1) + - [ 0, 285221, 4, 5, 311800] # EV_MSC / MSC_TIMESTAMP 311800 + - [ 0, 285221, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 291824, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 291824, 3, 53, 661] # EV_ABS / ABS_MT_POSITION_X 661 (+4) + - [ 0, 291824, 3, 54, 538] # EV_ABS / ABS_MT_POSITION_Y 538 (-1) + - [ 0, 291824, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 291824, 3, 53, 770] # EV_ABS / ABS_MT_POSITION_X 770 (+5) + - [ 0, 291824, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 291824, 3, 53, 1131] # EV_ABS / ABS_MT_POSITION_X 1131 (+4) + - [ 0, 291824, 3, 0, 661] # EV_ABS / ABS_X 661 (+4) + - [ 0, 291824, 3, 1, 538] # EV_ABS / ABS_Y 538 (-1) + - [ 0, 291824, 4, 5, 318900] # EV_MSC / MSC_TIMESTAMP 318900 + - [ 0, 291824, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 298764, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 298764, 3, 53, 664] # EV_ABS / ABS_MT_POSITION_X 664 (+3) + - [ 0, 298764, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 298764, 3, 53, 774] # EV_ABS / ABS_MT_POSITION_X 774 (+4) + - [ 0, 298764, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 298764, 3, 53, 1136] # EV_ABS / ABS_MT_POSITION_X 1136 (+5) + - [ 0, 298764, 3, 0, 664] # EV_ABS / ABS_X 664 (+3) + - [ 0, 298764, 4, 5, 326100] # EV_MSC / MSC_TIMESTAMP 326100 + - [ 0, 298764, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 305234, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 305234, 3, 53, 667] # EV_ABS / ABS_MT_POSITION_X 667 (+3) + - [ 0, 305234, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 305234, 3, 53, 778] # EV_ABS / ABS_MT_POSITION_X 778 (+4) + - [ 0, 305234, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 305234, 3, 53, 1140] # EV_ABS / ABS_MT_POSITION_X 1140 (+4) + - [ 0, 305234, 3, 0, 667] # EV_ABS / ABS_X 667 (+3) + - [ 0, 305234, 4, 5, 333100] # EV_MSC / MSC_TIMESTAMP 333100 + - [ 0, 305234, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 311893, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 311893, 3, 53, 670] # EV_ABS / ABS_MT_POSITION_X 670 (+3) + - [ 0, 311893, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 311893, 3, 53, 780] # EV_ABS / ABS_MT_POSITION_X 780 (+2) + - [ 0, 311893, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 311893, 3, 53, 1143] # EV_ABS / ABS_MT_POSITION_X 1143 (+3) + - [ 0, 311893, 3, 0, 670] # EV_ABS / ABS_X 670 (+3) + - [ 0, 311893, 4, 5, 337800] # EV_MSC / MSC_TIMESTAMP 337800 + - [ 0, 311893, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 318775, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 318775, 3, 53, 673] # EV_ABS / ABS_MT_POSITION_X 673 (+3) + - [ 0, 318775, 3, 54, 537] # EV_ABS / ABS_MT_POSITION_Y 537 (-1) + - [ 0, 318775, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 318775, 3, 53, 783] # EV_ABS / ABS_MT_POSITION_X 783 (+3) + - [ 0, 318775, 3, 54, 303] # EV_ABS / ABS_MT_POSITION_Y 303 (-1) + - [ 0, 318775, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 318775, 3, 53, 1147] # EV_ABS / ABS_MT_POSITION_X 1147 (+4) + - [ 0, 318775, 3, 0, 673] # EV_ABS / ABS_X 673 (+3) + - [ 0, 318775, 3, 1, 537] # EV_ABS / ABS_Y 537 (-1) + - [ 0, 318775, 4, 5, 344900] # EV_MSC / MSC_TIMESTAMP 344900 + - [ 0, 318775, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 325241, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 325241, 3, 53, 676] # EV_ABS / ABS_MT_POSITION_X 676 (+3) + - [ 0, 325241, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 325241, 3, 53, 786] # EV_ABS / ABS_MT_POSITION_X 786 (+3) + - [ 0, 325241, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 325241, 3, 53, 1151] # EV_ABS / ABS_MT_POSITION_X 1151 (+4) + - [ 0, 325241, 3, 0, 676] # EV_ABS / ABS_X 676 (+3) + - [ 0, 325241, 4, 5, 352000] # EV_MSC / MSC_TIMESTAMP 352000 + - [ 0, 325241, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 332152, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 332152, 3, 53, 679] # EV_ABS / ABS_MT_POSITION_X 679 (+3) + - [ 0, 332152, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 332152, 3, 53, 789] # EV_ABS / ABS_MT_POSITION_X 789 (+3) + - [ 0, 332152, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 332152, 3, 53, 1154] # EV_ABS / ABS_MT_POSITION_X 1154 (+3) + - [ 0, 332152, 3, 0, 679] # EV_ABS / ABS_X 679 (+3) + - [ 0, 332152, 4, 5, 356800] # EV_MSC / MSC_TIMESTAMP 356800 + - [ 0, 332152, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 338655, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 338655, 3, 53, 683] # EV_ABS / ABS_MT_POSITION_X 683 (+4) + - [ 0, 338655, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 338655, 3, 53, 792] # EV_ABS / ABS_MT_POSITION_X 792 (+3) + - [ 0, 338655, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 338655, 3, 53, 1158] # EV_ABS / ABS_MT_POSITION_X 1158 (+4) + - [ 0, 338655, 3, 54, 221] # EV_ABS / ABS_MT_POSITION_Y 221 (-1) + - [ 0, 338655, 3, 0, 683] # EV_ABS / ABS_X 683 (+4) + - [ 0, 338655, 4, 5, 364000] # EV_MSC / MSC_TIMESTAMP 364000 + - [ 0, 338655, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 345187, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 345187, 3, 53, 686] # EV_ABS / ABS_MT_POSITION_X 686 (+3) + - [ 0, 345187, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 345187, 3, 53, 795] # EV_ABS / ABS_MT_POSITION_X 795 (+3) + - [ 0, 345187, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 345187, 3, 53, 1163] # EV_ABS / ABS_MT_POSITION_X 1163 (+5) + - [ 0, 345187, 3, 0, 686] # EV_ABS / ABS_X 686 (+3) + - [ 0, 345187, 4, 5, 371200] # EV_MSC / MSC_TIMESTAMP 371200 + - [ 0, 345187, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 352386, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 352386, 3, 53, 690] # EV_ABS / ABS_MT_POSITION_X 690 (+4) + - [ 0, 352386, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 352386, 3, 53, 799] # EV_ABS / ABS_MT_POSITION_X 799 (+4) + - [ 0, 352386, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 352386, 3, 53, 1167] # EV_ABS / ABS_MT_POSITION_X 1167 (+4) + - [ 0, 352386, 3, 54, 220] # EV_ABS / ABS_MT_POSITION_Y 220 (-1) + - [ 0, 352386, 3, 0, 690] # EV_ABS / ABS_X 690 (+4) + - [ 0, 352386, 4, 5, 378400] # EV_MSC / MSC_TIMESTAMP 378400 + - [ 0, 352386, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 358736, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 358736, 3, 53, 692] # EV_ABS / ABS_MT_POSITION_X 692 (+2) + - [ 0, 358736, 3, 54, 536] # EV_ABS / ABS_MT_POSITION_Y 536 (-1) + - [ 0, 358736, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 358736, 3, 53, 801] # EV_ABS / ABS_MT_POSITION_X 801 (+2) + - [ 0, 358736, 3, 54, 302] # EV_ABS / ABS_MT_POSITION_Y 302 (-1) + - [ 0, 358736, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 358736, 3, 53, 1169] # EV_ABS / ABS_MT_POSITION_X 1169 (+2) + - [ 0, 358736, 3, 0, 692] # EV_ABS / ABS_X 692 (+2) + - [ 0, 358736, 3, 1, 536] # EV_ABS / ABS_Y 536 (-1) + - [ 0, 358736, 4, 5, 383200] # EV_MSC / MSC_TIMESTAMP 383200 + - [ 0, 358736, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 365555, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 365555, 3, 53, 695] # EV_ABS / ABS_MT_POSITION_X 695 (+3) + - [ 0, 365555, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 365555, 3, 53, 804] # EV_ABS / ABS_MT_POSITION_X 804 (+3) + - [ 0, 365555, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 365555, 3, 53, 1172] # EV_ABS / ABS_MT_POSITION_X 1172 (+3) + - [ 0, 365555, 3, 0, 695] # EV_ABS / ABS_X 695 (+3) + - [ 0, 365555, 4, 5, 390400] # EV_MSC / MSC_TIMESTAMP 390400 + - [ 0, 365555, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 372028, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 372028, 3, 53, 699] # EV_ABS / ABS_MT_POSITION_X 699 (+4) + - [ 0, 372028, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 372028, 3, 53, 808] # EV_ABS / ABS_MT_POSITION_X 808 (+4) + - [ 0, 372028, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 372028, 3, 53, 1175] # EV_ABS / ABS_MT_POSITION_X 1175 (+3) + - [ 0, 372028, 3, 0, 699] # EV_ABS / ABS_X 699 (+4) + - [ 0, 372028, 4, 5, 397700] # EV_MSC / MSC_TIMESTAMP 397700 + - [ 0, 372028, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 378842, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 378842, 3, 53, 701] # EV_ABS / ABS_MT_POSITION_X 701 (+2) + - [ 0, 378842, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 378842, 3, 53, 810] # EV_ABS / ABS_MT_POSITION_X 810 (+2) + - [ 0, 378842, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 378842, 3, 53, 1177] # EV_ABS / ABS_MT_POSITION_X 1177 (+2) + - [ 0, 378842, 3, 54, 221] # EV_ABS / ABS_MT_POSITION_Y 221 (+1) + - [ 0, 378842, 3, 0, 701] # EV_ABS / ABS_X 701 (+2) + - [ 0, 378842, 4, 5, 402500] # EV_MSC / MSC_TIMESTAMP 402500 + - [ 0, 378842, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 385337, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 385337, 3, 53, 704] # EV_ABS / ABS_MT_POSITION_X 704 (+3) + - [ 0, 385337, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 385337, 3, 53, 813] # EV_ABS / ABS_MT_POSITION_X 813 (+3) + - [ 0, 385337, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 385337, 3, 53, 1180] # EV_ABS / ABS_MT_POSITION_X 1180 (+3) + - [ 0, 385337, 3, 0, 704] # EV_ABS / ABS_X 704 (+3) + - [ 0, 385337, 4, 5, 409700] # EV_MSC / MSC_TIMESTAMP 409700 + - [ 0, 385337, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 392321, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 392321, 3, 53, 706] # EV_ABS / ABS_MT_POSITION_X 706 (+2) + - [ 0, 392321, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 392321, 3, 53, 816] # EV_ABS / ABS_MT_POSITION_X 816 (+3) + - [ 0, 392321, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 392321, 3, 53, 1182] # EV_ABS / ABS_MT_POSITION_X 1182 (+2) + - [ 0, 392321, 3, 54, 222] # EV_ABS / ABS_MT_POSITION_Y 222 (+1) + - [ 0, 392321, 3, 0, 706] # EV_ABS / ABS_X 706 (+2) + - [ 0, 392321, 4, 5, 416800] # EV_MSC / MSC_TIMESTAMP 416800 + - [ 0, 392321, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 399086, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 399086, 3, 53, 708] # EV_ABS / ABS_MT_POSITION_X 708 (+2) + - [ 0, 399086, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 399086, 3, 53, 819] # EV_ABS / ABS_MT_POSITION_X 819 (+3) + - [ 0, 399086, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 399086, 3, 53, 1184] # EV_ABS / ABS_MT_POSITION_X 1184 (+2) + - [ 0, 399086, 3, 0, 708] # EV_ABS / ABS_X 708 (+2) + - [ 0, 399086, 4, 5, 424000] # EV_MSC / MSC_TIMESTAMP 424000 + - [ 0, 399086, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 405591, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 405591, 3, 53, 709] # EV_ABS / ABS_MT_POSITION_X 709 (+1) + - [ 0, 405591, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 405591, 3, 53, 821] # EV_ABS / ABS_MT_POSITION_X 821 (+2) + - [ 0, 405591, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 405591, 3, 53, 1185] # EV_ABS / ABS_MT_POSITION_X 1185 (+1) + - [ 0, 405591, 3, 0, 709] # EV_ABS / ABS_X 709 (+1) + - [ 0, 405591, 4, 5, 428800] # EV_MSC / MSC_TIMESTAMP 428800 + - [ 0, 405591, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 412234, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 412234, 3, 53, 711] # EV_ABS / ABS_MT_POSITION_X 711 (+2) + - [ 0, 412234, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 412234, 3, 53, 823] # EV_ABS / ABS_MT_POSITION_X 823 (+2) + - [ 0, 412234, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 412234, 3, 53, 1187] # EV_ABS / ABS_MT_POSITION_X 1187 (+2) + - [ 0, 412234, 3, 54, 223] # EV_ABS / ABS_MT_POSITION_Y 223 (+1) + - [ 0, 412234, 3, 0, 711] # EV_ABS / ABS_X 711 (+2) + - [ 0, 412234, 4, 5, 436000] # EV_MSC / MSC_TIMESTAMP 436000 + - [ 0, 412234, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 418871, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 418871, 3, 53, 713] # EV_ABS / ABS_MT_POSITION_X 713 (+2) + - [ 0, 418871, 3, 54, 535] # EV_ABS / ABS_MT_POSITION_Y 535 (-1) + - [ 0, 418871, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 418871, 3, 53, 825] # EV_ABS / ABS_MT_POSITION_X 825 (+2) + - [ 0, 418871, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 418871, 3, 53, 1188] # EV_ABS / ABS_MT_POSITION_X 1188 (+1) + - [ 0, 418871, 3, 0, 713] # EV_ABS / ABS_X 713 (+2) + - [ 0, 418871, 3, 1, 535] # EV_ABS / ABS_Y 535 (-1) + - [ 0, 418871, 4, 5, 443200] # EV_MSC / MSC_TIMESTAMP 443200 + - [ 0, 418871, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 425612, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 425612, 3, 53, 714] # EV_ABS / ABS_MT_POSITION_X 714 (+1) + - [ 0, 425612, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 425612, 3, 53, 826] # EV_ABS / ABS_MT_POSITION_X 826 (+1) + - [ 0, 425612, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 425612, 3, 53, 1189] # EV_ABS / ABS_MT_POSITION_X 1189 (+1) + - [ 0, 425612, 3, 0, 714] # EV_ABS / ABS_X 714 (+1) + - [ 0, 425612, 4, 5, 448000] # EV_MSC / MSC_TIMESTAMP 448000 + - [ 0, 425612, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 432300, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 432300, 3, 53, 716] # EV_ABS / ABS_MT_POSITION_X 716 (+2) + - [ 0, 432300, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 432300, 3, 53, 828] # EV_ABS / ABS_MT_POSITION_X 828 (+2) + - [ 0, 432300, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 432300, 3, 53, 1191] # EV_ABS / ABS_MT_POSITION_X 1191 (+2) + - [ 0, 432300, 3, 0, 716] # EV_ABS / ABS_X 716 (+2) + - [ 0, 432300, 4, 5, 455200] # EV_MSC / MSC_TIMESTAMP 455200 + - [ 0, 432300, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 439084, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 439084, 3, 53, 718] # EV_ABS / ABS_MT_POSITION_X 718 (+2) + - [ 0, 439084, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 439084, 3, 53, 830] # EV_ABS / ABS_MT_POSITION_X 830 (+2) + - [ 0, 439084, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 439084, 3, 53, 1192] # EV_ABS / ABS_MT_POSITION_X 1192 (+1) + - [ 0, 439084, 3, 0, 718] # EV_ABS / ABS_X 718 (+2) + - [ 0, 439084, 4, 5, 462500] # EV_MSC / MSC_TIMESTAMP 462500 + - [ 0, 439084, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 445864, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 445864, 3, 53, 720] # EV_ABS / ABS_MT_POSITION_X 720 (+2) + - [ 0, 445864, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 445864, 3, 53, 832] # EV_ABS / ABS_MT_POSITION_X 832 (+2) + - [ 0, 445864, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 445864, 3, 53, 1193] # EV_ABS / ABS_MT_POSITION_X 1193 (+1) + - [ 0, 445864, 3, 0, 720] # EV_ABS / ABS_X 720 (+2) + - [ 0, 445864, 4, 5, 469600] # EV_MSC / MSC_TIMESTAMP 469600 + - [ 0, 445864, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 452281, 3, 53, 1194] # EV_ABS / ABS_MT_POSITION_X 1194 (+1) + - [ 0, 452281, 4, 5, 474300] # EV_MSC / MSC_TIMESTAMP 474300 + - [ 0, 452281, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 458630, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 458630, 3, 53, 721] # EV_ABS / ABS_MT_POSITION_X 721 (+1) + - [ 0, 458630, 3, 54, 534] # EV_ABS / ABS_MT_POSITION_Y 534 (-1) + - [ 0, 458630, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 458630, 3, 53, 833] # EV_ABS / ABS_MT_POSITION_X 833 (+1) + - [ 0, 458630, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 458630, 3, 53, 1195] # EV_ABS / ABS_MT_POSITION_X 1195 (+1) + - [ 0, 458630, 3, 0, 721] # EV_ABS / ABS_X 721 (+1) + - [ 0, 458630, 3, 1, 534] # EV_ABS / ABS_Y 534 (-1) + - [ 0, 458630, 4, 5, 481400] # EV_MSC / MSC_TIMESTAMP 481400 + - [ 0, 458630, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 465747, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 465747, 3, 53, 722] # EV_ABS / ABS_MT_POSITION_X 722 (+1) + - [ 0, 465747, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 465747, 3, 53, 834] # EV_ABS / ABS_MT_POSITION_X 834 (+1) + - [ 0, 465747, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 465747, 3, 53, 1196] # EV_ABS / ABS_MT_POSITION_X 1196 (+1) + - [ 0, 465747, 3, 0, 722] # EV_ABS / ABS_X 722 (+1) + - [ 0, 465747, 4, 5, 488500] # EV_MSC / MSC_TIMESTAMP 488500 + - [ 0, 465747, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 472437, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 472437, 3, 53, 835] # EV_ABS / ABS_MT_POSITION_X 835 (+1) + - [ 0, 472437, 4, 5, 495600] # EV_MSC / MSC_TIMESTAMP 495600 + - [ 0, 472437, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 479172, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 479172, 3, 53, 721] # EV_ABS / ABS_MT_POSITION_X 721 (-1) + - [ 0, 479172, 3, 0, 721] # EV_ABS / ABS_X 721 (-1) + - [ 0, 479172, 4, 5, 500400] # EV_MSC / MSC_TIMESTAMP 500400 + - [ 0, 479172, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 485895, 4, 5, 507500] # EV_MSC / MSC_TIMESTAMP 507500 + - [ 0, 485895, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 492568, 4, 5, 514700] # EV_MSC / MSC_TIMESTAMP 514700 + - [ 0, 492568, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 499313, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 499313, 3, 53, 834] # EV_ABS / ABS_MT_POSITION_X 834 (-1) + - [ 0, 499313, 4, 5, 519500] # EV_MSC / MSC_TIMESTAMP 519500 + - [ 0, 499313, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 505767, 4, 5, 526700] # EV_MSC / MSC_TIMESTAMP 526700 + - [ 0, 505767, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 512528, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 512528, 3, 53, 722] # EV_ABS / ABS_MT_POSITION_X 722 (+1) + - [ 0, 512528, 3, 0, 722] # EV_ABS / ABS_X 722 (+1) + - [ 0, 512528, 4, 5, 533900] # EV_MSC / MSC_TIMESTAMP 533900 + - [ 0, 512528, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 519542, 4, 5, 541100] # EV_MSC / MSC_TIMESTAMP 541100 + - [ 0, 519542, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 526753, 4, 5, 548200] # EV_MSC / MSC_TIMESTAMP 548200 + - [ 0, 526753, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 533223, 4, 5, 552900] # EV_MSC / MSC_TIMESTAMP 552900 + - [ 0, 533223, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 539730, 4, 5, 560100] # EV_MSC / MSC_TIMESTAMP 560100 + - [ 0, 539730, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 546701, 4, 5, 567200] # EV_MSC / MSC_TIMESTAMP 567200 + - [ 0, 546701, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 553363, 3, 53, 721] # EV_ABS / ABS_MT_POSITION_X 721 (-1) + - [ 0, 553363, 3, 0, 721] # EV_ABS / ABS_X 721 (-1) + - [ 0, 553363, 4, 5, 572000] # EV_MSC / MSC_TIMESTAMP 572000 + - [ 0, 553363, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 559952, 4, 5, 579200] # EV_MSC / MSC_TIMESTAMP 579200 + - [ 0, 559952, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 566605, 4, 5, 586300] # EV_MSC / MSC_TIMESTAMP 586300 + - [ 0, 566605, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 573210, 4, 5, 593500] # EV_MSC / MSC_TIMESTAMP 593500 + - [ 0, 573210, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 580283, 4, 5, 598200] # EV_MSC / MSC_TIMESTAMP 598200 + - [ 0, 580283, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 586487, 4, 5, 605300] # EV_MSC / MSC_TIMESTAMP 605300 + - [ 0, 586487, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 593592, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 593592, 3, 53, 1195] # EV_ABS / ABS_MT_POSITION_X 1195 (-1) + - [ 0, 593592, 3, 54, 224] # EV_ABS / ABS_MT_POSITION_Y 224 (+1) + - [ 0, 593592, 4, 5, 612300] # EV_MSC / MSC_TIMESTAMP 612300 + - [ 0, 593592, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 0, 599777, 4, 5, 621100] # EV_MSC / MSC_TIMESTAMP 621100 + - [ 0, 599777, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 0, 606510, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 0, 606510, 3, 57, -1] # EV_ABS / ABS_MT_TRACKING_ID -1 + - [ 0, 606510, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 0, 606510, 3, 57, -1] # EV_ABS / ABS_MT_TRACKING_ID -1 + - [ 0, 606510, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 0, 606510, 3, 57, -1] # EV_ABS / ABS_MT_TRACKING_ID -1 + - [ 0, 606510, 1, 330, 0] # EV_KEY / BTN_TOUCH 0 + - [ 0, 606510, 1, 334, 0] # EV_KEY / BTN_TOOL_TRIPLETAP 0 + - [ 0, 606510, 4, 5, 637100] # EV_MSC / MSC_TIMESTAMP 637100 + - [ 0, 606510, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + # Touch device in neutral state + - evdev: + - [ 1, 405157, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 405157, 3, 57, 1988] # EV_ABS / ABS_MT_TRACKING_ID 1988 + - [ 1, 405157, 3, 53, 893] # EV_ABS / ABS_MT_POSITION_X 893 (+172) + - [ 1, 405157, 3, 54, 257] # EV_ABS / ABS_MT_POSITION_Y 257 (-277) + - [ 1, 405157, 1, 330, 1] # EV_KEY / BTN_TOUCH 1 + - [ 1, 405157, 1, 325, 1] # EV_KEY / BTN_TOOL_FINGER 1 + - [ 1, 405157, 3, 0, 893] # EV_ABS / ABS_X 893 (+172) + - [ 1, 405157, 3, 1, 257] # EV_ABS / ABS_Y 257 (-277) + - [ 1, 405157, 4, 5, 1412400] # EV_MSC / MSC_TIMESTAMP 1412400 + - [ 1, 405157, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +799ms + - evdev: + - [ 1, 411871, 4, 5, 1416400] # EV_MSC / MSC_TIMESTAMP 1416400 + - [ 1, 411871, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 420341, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 420341, 3, 57, 1989] # EV_ABS / ABS_MT_TRACKING_ID 1989 + - [ 1, 420341, 3, 53, 1268] # EV_ABS / ABS_MT_POSITION_X 1268 (+434) + - [ 1, 420341, 3, 54, 181] # EV_ABS / ABS_MT_POSITION_Y 181 (-121) + - [ 1, 420341, 1, 325, 0] # EV_KEY / BTN_TOOL_FINGER 0 + - [ 1, 420341, 1, 333, 1] # EV_KEY / BTN_TOOL_DOUBLETAP 1 + - [ 1, 420341, 4, 5, 1421800] # EV_MSC / MSC_TIMESTAMP 1421800 + - [ 1, 420341, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +9ms + - evdev: + - [ 1, 426589, 4, 5, 1429100] # EV_MSC / MSC_TIMESTAMP 1429100 + - [ 1, 426589, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 435450, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 435450, 3, 57, 1990] # EV_ABS / ABS_MT_TRACKING_ID 1990 + - [ 1, 435450, 3, 53, 764] # EV_ABS / ABS_MT_POSITION_X 764 (-431) + - [ 1, 435450, 3, 54, 485] # EV_ABS / ABS_MT_POSITION_Y 485 (+261) + - [ 1, 435450, 1, 333, 0] # EV_KEY / BTN_TOOL_DOUBLETAP 0 + - [ 1, 435450, 1, 334, 1] # EV_KEY / BTN_TOOL_TRIPLETAP 1 + - [ 1, 435450, 4, 5, 1433000] # EV_MSC / MSC_TIMESTAMP 1433000 + - [ 1, 435450, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +9ms + - evdev: + - [ 1, 442172, 4, 5, 1439500] # EV_MSC / MSC_TIMESTAMP 1439500 + - [ 1, 442172, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 448684, 4, 5, 1446000] # EV_MSC / MSC_TIMESTAMP 1446000 + - [ 1, 448684, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 455519, 4, 5, 1450500] # EV_MSC / MSC_TIMESTAMP 1450500 + - [ 1, 455519, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 462028, 4, 5, 1457500] # EV_MSC / MSC_TIMESTAMP 1457500 + - [ 1, 462028, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 469247, 4, 5, 1464400] # EV_MSC / MSC_TIMESTAMP 1464400 + - [ 1, 469247, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 475659, 4, 5, 1471400] # EV_MSC / MSC_TIMESTAMP 1471400 + - [ 1, 475659, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 482345, 4, 5, 1476000] # EV_MSC / MSC_TIMESTAMP 1476000 + - [ 1, 482345, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 489059, 4, 5, 1482900] # EV_MSC / MSC_TIMESTAMP 1482900 + - [ 1, 489059, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 495971, 4, 5, 1489800] # EV_MSC / MSC_TIMESTAMP 1489800 + - [ 1, 495971, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 502519, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 502519, 3, 53, 1266] # EV_ABS / ABS_MT_POSITION_X 1266 (-2) + - [ 1, 502519, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 502519, 3, 53, 763] # EV_ABS / ABS_MT_POSITION_X 763 (-1) + - [ 1, 502519, 4, 5, 1496700] # EV_MSC / MSC_TIMESTAMP 1496700 + - [ 1, 502519, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 509237, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 509237, 3, 53, 1264] # EV_ABS / ABS_MT_POSITION_X 1264 (-2) + - [ 1, 509237, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 509237, 3, 53, 762] # EV_ABS / ABS_MT_POSITION_X 762 (-1) + - [ 1, 509237, 3, 54, 486] # EV_ABS / ABS_MT_POSITION_Y 486 (+1) + - [ 1, 509237, 4, 5, 1503700] # EV_MSC / MSC_TIMESTAMP 1503700 + - [ 1, 509237, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 515772, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 515772, 3, 53, 1261] # EV_ABS / ABS_MT_POSITION_X 1261 (-3) + - [ 1, 515772, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 515772, 3, 53, 760] # EV_ABS / ABS_MT_POSITION_X 760 (-2) + - [ 1, 515772, 4, 5, 1510500] # EV_MSC / MSC_TIMESTAMP 1510500 + - [ 1, 515772, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 522323, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 522323, 3, 53, 891] # EV_ABS / ABS_MT_POSITION_X 891 (-2) + - [ 1, 522323, 3, 54, 258] # EV_ABS / ABS_MT_POSITION_Y 258 (+1) + - [ 1, 522323, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 522323, 3, 53, 1256] # EV_ABS / ABS_MT_POSITION_X 1256 (-5) + - [ 1, 522323, 3, 54, 182] # EV_ABS / ABS_MT_POSITION_Y 182 (+1) + - [ 1, 522323, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 522323, 3, 53, 757] # EV_ABS / ABS_MT_POSITION_X 757 (-3) + - [ 1, 522323, 3, 54, 487] # EV_ABS / ABS_MT_POSITION_Y 487 (+1) + - [ 1, 522323, 3, 0, 891] # EV_ABS / ABS_X 891 (-2) + - [ 1, 522323, 3, 1, 258] # EV_ABS / ABS_Y 258 (+1) + - [ 1, 522323, 4, 5, 1517300] # EV_MSC / MSC_TIMESTAMP 1517300 + - [ 1, 522323, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 529323, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 529323, 3, 53, 889] # EV_ABS / ABS_MT_POSITION_X 889 (-2) + - [ 1, 529323, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 529323, 3, 53, 1249] # EV_ABS / ABS_MT_POSITION_X 1249 (-7) + - [ 1, 529323, 3, 54, 183] # EV_ABS / ABS_MT_POSITION_Y 183 (+1) + - [ 1, 529323, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 529323, 3, 53, 752] # EV_ABS / ABS_MT_POSITION_X 752 (-5) + - [ 1, 529323, 3, 0, 889] # EV_ABS / ABS_X 889 (-2) + - [ 1, 529323, 4, 5, 1524000] # EV_MSC / MSC_TIMESTAMP 1524000 + - [ 1, 529323, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 536508, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 536508, 3, 53, 886] # EV_ABS / ABS_MT_POSITION_X 886 (-3) + - [ 1, 536508, 3, 54, 259] # EV_ABS / ABS_MT_POSITION_Y 259 (+1) + - [ 1, 536508, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 536508, 3, 53, 1243] # EV_ABS / ABS_MT_POSITION_X 1243 (-6) + - [ 1, 536508, 3, 54, 184] # EV_ABS / ABS_MT_POSITION_Y 184 (+1) + - [ 1, 536508, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 536508, 3, 53, 746] # EV_ABS / ABS_MT_POSITION_X 746 (-6) + - [ 1, 536508, 3, 54, 488] # EV_ABS / ABS_MT_POSITION_Y 488 (+1) + - [ 1, 536508, 3, 0, 886] # EV_ABS / ABS_X 886 (-3) + - [ 1, 536508, 3, 1, 259] # EV_ABS / ABS_Y 259 (+1) + - [ 1, 536508, 4, 5, 1530700] # EV_MSC / MSC_TIMESTAMP 1530700 + - [ 1, 536508, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 543295, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 543295, 3, 53, 878] # EV_ABS / ABS_MT_POSITION_X 878 (-8) + - [ 1, 543295, 3, 54, 260] # EV_ABS / ABS_MT_POSITION_Y 260 (+1) + - [ 1, 543295, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 543295, 3, 53, 1234] # EV_ABS / ABS_MT_POSITION_X 1234 (-9) + - [ 1, 543295, 3, 54, 186] # EV_ABS / ABS_MT_POSITION_Y 186 (+2) + - [ 1, 543295, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 543295, 3, 53, 738] # EV_ABS / ABS_MT_POSITION_X 738 (-8) + - [ 1, 543295, 3, 54, 489] # EV_ABS / ABS_MT_POSITION_Y 489 (+1) + - [ 1, 543295, 3, 0, 878] # EV_ABS / ABS_X 878 (-8) + - [ 1, 543295, 3, 1, 260] # EV_ABS / ABS_Y 260 (+1) + - [ 1, 543295, 4, 5, 1537400] # EV_MSC / MSC_TIMESTAMP 1537400 + - [ 1, 543295, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 549748, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 549748, 3, 53, 873] # EV_ABS / ABS_MT_POSITION_X 873 (-5) + - [ 1, 549748, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 549748, 3, 53, 1229] # EV_ABS / ABS_MT_POSITION_X 1229 (-5) + - [ 1, 549748, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 549748, 3, 53, 733] # EV_ABS / ABS_MT_POSITION_X 733 (-5) + - [ 1, 549748, 3, 54, 490] # EV_ABS / ABS_MT_POSITION_Y 490 (+1) + - [ 1, 549748, 3, 0, 873] # EV_ABS / ABS_X 873 (-5) + - [ 1, 549748, 4, 5, 1541900] # EV_MSC / MSC_TIMESTAMP 1541900 + - [ 1, 549748, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 556647, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 556647, 3, 53, 866] # EV_ABS / ABS_MT_POSITION_X 866 (-7) + - [ 1, 556647, 3, 54, 262] # EV_ABS / ABS_MT_POSITION_Y 262 (+2) + - [ 1, 556647, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 556647, 3, 53, 1221] # EV_ABS / ABS_MT_POSITION_X 1221 (-8) + - [ 1, 556647, 3, 54, 187] # EV_ABS / ABS_MT_POSITION_Y 187 (+1) + - [ 1, 556647, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 556647, 3, 53, 727] # EV_ABS / ABS_MT_POSITION_X 727 (-6) + - [ 1, 556647, 3, 54, 491] # EV_ABS / ABS_MT_POSITION_Y 491 (+1) + - [ 1, 556647, 3, 0, 866] # EV_ABS / ABS_X 866 (-7) + - [ 1, 556647, 3, 1, 262] # EV_ABS / ABS_Y 262 (+2) + - [ 1, 556647, 4, 5, 1548800] # EV_MSC / MSC_TIMESTAMP 1548800 + - [ 1, 556647, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 563282, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 563282, 3, 53, 857] # EV_ABS / ABS_MT_POSITION_X 857 (-9) + - [ 1, 563282, 3, 54, 263] # EV_ABS / ABS_MT_POSITION_Y 263 (+1) + - [ 1, 563282, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 563282, 3, 53, 1214] # EV_ABS / ABS_MT_POSITION_X 1214 (-7) + - [ 1, 563282, 3, 54, 188] # EV_ABS / ABS_MT_POSITION_Y 188 (+1) + - [ 1, 563282, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 563282, 3, 53, 721] # EV_ABS / ABS_MT_POSITION_X 721 (-6) + - [ 1, 563282, 3, 54, 492] # EV_ABS / ABS_MT_POSITION_Y 492 (+1) + - [ 1, 563282, 3, 0, 857] # EV_ABS / ABS_X 857 (-9) + - [ 1, 563282, 3, 1, 263] # EV_ABS / ABS_Y 263 (+1) + - [ 1, 563282, 4, 5, 1555700] # EV_MSC / MSC_TIMESTAMP 1555700 + - [ 1, 563282, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 569947, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 569947, 3, 53, 848] # EV_ABS / ABS_MT_POSITION_X 848 (-9) + - [ 1, 569947, 3, 54, 265] # EV_ABS / ABS_MT_POSITION_Y 265 (+2) + - [ 1, 569947, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 569947, 3, 53, 1207] # EV_ABS / ABS_MT_POSITION_X 1207 (-7) + - [ 1, 569947, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 569947, 3, 53, 715] # EV_ABS / ABS_MT_POSITION_X 715 (-6) + - [ 1, 569947, 3, 0, 848] # EV_ABS / ABS_X 848 (-9) + - [ 1, 569947, 3, 1, 265] # EV_ABS / ABS_Y 265 (+2) + - [ 1, 569947, 4, 5, 1562500] # EV_MSC / MSC_TIMESTAMP 1562500 + - [ 1, 569947, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 576755, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 576755, 3, 53, 840] # EV_ABS / ABS_MT_POSITION_X 840 (-8) + - [ 1, 576755, 3, 54, 266] # EV_ABS / ABS_MT_POSITION_Y 266 (+1) + - [ 1, 576755, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 576755, 3, 53, 1199] # EV_ABS / ABS_MT_POSITION_X 1199 (-8) + - [ 1, 576755, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 576755, 3, 53, 708] # EV_ABS / ABS_MT_POSITION_X 708 (-7) + - [ 1, 576755, 3, 54, 493] # EV_ABS / ABS_MT_POSITION_Y 493 (+1) + - [ 1, 576755, 3, 0, 840] # EV_ABS / ABS_X 840 (-8) + - [ 1, 576755, 3, 1, 266] # EV_ABS / ABS_Y 266 (+1) + - [ 1, 576755, 4, 5, 1569400] # EV_MSC / MSC_TIMESTAMP 1569400 + - [ 1, 576755, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 583460, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 583460, 3, 53, 834] # EV_ABS / ABS_MT_POSITION_X 834 (-6) + - [ 1, 583460, 3, 54, 267] # EV_ABS / ABS_MT_POSITION_Y 267 (+1) + - [ 1, 583460, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 583460, 3, 53, 1189] # EV_ABS / ABS_MT_POSITION_X 1189 (-10) + - [ 1, 583460, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 583460, 3, 53, 700] # EV_ABS / ABS_MT_POSITION_X 700 (-8) + - [ 1, 583460, 3, 0, 834] # EV_ABS / ABS_X 834 (-6) + - [ 1, 583460, 3, 1, 267] # EV_ABS / ABS_Y 267 (+1) + - [ 1, 583460, 4, 5, 1576200] # EV_MSC / MSC_TIMESTAMP 1576200 + - [ 1, 583460, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 590144, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 590144, 3, 53, 829] # EV_ABS / ABS_MT_POSITION_X 829 (-5) + - [ 1, 590144, 3, 54, 268] # EV_ABS / ABS_MT_POSITION_Y 268 (+1) + - [ 1, 590144, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 590144, 3, 53, 1184] # EV_ABS / ABS_MT_POSITION_X 1184 (-5) + - [ 1, 590144, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 590144, 3, 53, 695] # EV_ABS / ABS_MT_POSITION_X 695 (-5) + - [ 1, 590144, 3, 0, 829] # EV_ABS / ABS_X 829 (-5) + - [ 1, 590144, 3, 1, 268] # EV_ABS / ABS_Y 268 (+1) + - [ 1, 590144, 4, 5, 1580700] # EV_MSC / MSC_TIMESTAMP 1580700 + - [ 1, 590144, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 596610, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 596610, 3, 53, 822] # EV_ABS / ABS_MT_POSITION_X 822 (-7) + - [ 1, 596610, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 596610, 3, 53, 1176] # EV_ABS / ABS_MT_POSITION_X 1176 (-8) + - [ 1, 596610, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 596610, 3, 53, 689] # EV_ABS / ABS_MT_POSITION_X 689 (-6) + - [ 1, 596610, 3, 54, 494] # EV_ABS / ABS_MT_POSITION_Y 494 (+1) + - [ 1, 596610, 3, 0, 822] # EV_ABS / ABS_X 822 (-7) + - [ 1, 596610, 4, 5, 1587500] # EV_MSC / MSC_TIMESTAMP 1587500 + - [ 1, 596610, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 603560, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 603560, 3, 53, 814] # EV_ABS / ABS_MT_POSITION_X 814 (-8) + - [ 1, 603560, 3, 54, 269] # EV_ABS / ABS_MT_POSITION_Y 269 (+1) + - [ 1, 603560, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 603560, 3, 53, 1170] # EV_ABS / ABS_MT_POSITION_X 1170 (-6) + - [ 1, 603560, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 603560, 3, 53, 682] # EV_ABS / ABS_MT_POSITION_X 682 (-7) + - [ 1, 603560, 3, 0, 814] # EV_ABS / ABS_X 814 (-8) + - [ 1, 603560, 3, 1, 269] # EV_ABS / ABS_Y 269 (+1) + - [ 1, 603560, 4, 5, 1594400] # EV_MSC / MSC_TIMESTAMP 1594400 + - [ 1, 603560, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 609914, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 609914, 3, 53, 807] # EV_ABS / ABS_MT_POSITION_X 807 (-7) + - [ 1, 609914, 3, 54, 270] # EV_ABS / ABS_MT_POSITION_Y 270 (+1) + - [ 1, 609914, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 609914, 3, 53, 1163] # EV_ABS / ABS_MT_POSITION_X 1163 (-7) + - [ 1, 609914, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 609914, 3, 53, 675] # EV_ABS / ABS_MT_POSITION_X 675 (-7) + - [ 1, 609914, 3, 54, 495] # EV_ABS / ABS_MT_POSITION_Y 495 (+1) + - [ 1, 609914, 3, 0, 807] # EV_ABS / ABS_X 807 (-7) + - [ 1, 609914, 3, 1, 270] # EV_ABS / ABS_Y 270 (+1) + - [ 1, 609914, 4, 5, 1601300] # EV_MSC / MSC_TIMESTAMP 1601300 + - [ 1, 609914, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 616672, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 616672, 3, 53, 799] # EV_ABS / ABS_MT_POSITION_X 799 (-8) + - [ 1, 616672, 3, 54, 271] # EV_ABS / ABS_MT_POSITION_Y 271 (+1) + - [ 1, 616672, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 616672, 3, 53, 1155] # EV_ABS / ABS_MT_POSITION_X 1155 (-8) + - [ 1, 616672, 3, 54, 187] # EV_ABS / ABS_MT_POSITION_Y 187 (-1) + - [ 1, 616672, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 616672, 3, 53, 669] # EV_ABS / ABS_MT_POSITION_X 669 (-6) + - [ 1, 616672, 3, 0, 799] # EV_ABS / ABS_X 799 (-8) + - [ 1, 616672, 3, 1, 271] # EV_ABS / ABS_Y 271 (+1) + - [ 1, 616672, 4, 5, 1608300] # EV_MSC / MSC_TIMESTAMP 1608300 + - [ 1, 616672, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 623276, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 623276, 3, 53, 792] # EV_ABS / ABS_MT_POSITION_X 792 (-7) + - [ 1, 623276, 3, 54, 272] # EV_ABS / ABS_MT_POSITION_Y 272 (+1) + - [ 1, 623276, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 623276, 3, 53, 1147] # EV_ABS / ABS_MT_POSITION_X 1147 (-8) + - [ 1, 623276, 3, 54, 186] # EV_ABS / ABS_MT_POSITION_Y 186 (-1) + - [ 1, 623276, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 623276, 3, 53, 662] # EV_ABS / ABS_MT_POSITION_X 662 (-7) + - [ 1, 623276, 3, 54, 496] # EV_ABS / ABS_MT_POSITION_Y 496 (+1) + - [ 1, 623276, 3, 0, 792] # EV_ABS / ABS_X 792 (-7) + - [ 1, 623276, 3, 1, 272] # EV_ABS / ABS_Y 272 (+1) + - [ 1, 623276, 4, 5, 1615200] # EV_MSC / MSC_TIMESTAMP 1615200 + - [ 1, 623276, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 630117, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 630117, 3, 53, 785] # EV_ABS / ABS_MT_POSITION_X 785 (-7) + - [ 1, 630117, 3, 54, 274] # EV_ABS / ABS_MT_POSITION_Y 274 (+2) + - [ 1, 630117, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 630117, 3, 53, 1139] # EV_ABS / ABS_MT_POSITION_X 1139 (-8) + - [ 1, 630117, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 630117, 3, 53, 655] # EV_ABS / ABS_MT_POSITION_X 655 (-7) + - [ 1, 630117, 3, 54, 497] # EV_ABS / ABS_MT_POSITION_Y 497 (+1) + - [ 1, 630117, 3, 0, 785] # EV_ABS / ABS_X 785 (-7) + - [ 1, 630117, 3, 1, 274] # EV_ABS / ABS_Y 274 (+2) + - [ 1, 630117, 4, 5, 1622000] # EV_MSC / MSC_TIMESTAMP 1622000 + - [ 1, 630117, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 636891, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 636891, 3, 53, 781] # EV_ABS / ABS_MT_POSITION_X 781 (-4) + - [ 1, 636891, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 636891, 3, 53, 1133] # EV_ABS / ABS_MT_POSITION_X 1133 (-6) + - [ 1, 636891, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 636891, 3, 53, 650] # EV_ABS / ABS_MT_POSITION_X 650 (-5) + - [ 1, 636891, 3, 0, 781] # EV_ABS / ABS_X 781 (-4) + - [ 1, 636891, 4, 5, 1626500] # EV_MSC / MSC_TIMESTAMP 1626500 + - [ 1, 636891, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 643507, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 643507, 3, 53, 775] # EV_ABS / ABS_MT_POSITION_X 775 (-6) + - [ 1, 643507, 3, 54, 275] # EV_ABS / ABS_MT_POSITION_Y 275 (+1) + - [ 1, 643507, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 643507, 3, 53, 1124] # EV_ABS / ABS_MT_POSITION_X 1124 (-9) + - [ 1, 643507, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 643507, 3, 53, 643] # EV_ABS / ABS_MT_POSITION_X 643 (-7) + - [ 1, 643507, 3, 0, 775] # EV_ABS / ABS_X 775 (-6) + - [ 1, 643507, 3, 1, 275] # EV_ABS / ABS_Y 275 (+1) + - [ 1, 643507, 4, 5, 1633300] # EV_MSC / MSC_TIMESTAMP 1633300 + - [ 1, 643507, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 650200, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 650200, 3, 53, 768] # EV_ABS / ABS_MT_POSITION_X 768 (-7) + - [ 1, 650200, 3, 54, 276] # EV_ABS / ABS_MT_POSITION_Y 276 (+1) + - [ 1, 650200, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 650200, 3, 53, 1117] # EV_ABS / ABS_MT_POSITION_X 1117 (-7) + - [ 1, 650200, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 650200, 3, 53, 635] # EV_ABS / ABS_MT_POSITION_X 635 (-8) + - [ 1, 650200, 3, 0, 768] # EV_ABS / ABS_X 768 (-7) + - [ 1, 650200, 3, 1, 276] # EV_ABS / ABS_Y 276 (+1) + - [ 1, 650200, 4, 5, 1640400] # EV_MSC / MSC_TIMESTAMP 1640400 + - [ 1, 650200, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 656884, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 656884, 3, 53, 763] # EV_ABS / ABS_MT_POSITION_X 763 (-5) + - [ 1, 656884, 3, 54, 277] # EV_ABS / ABS_MT_POSITION_Y 277 (+1) + - [ 1, 656884, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 656884, 3, 53, 1112] # EV_ABS / ABS_MT_POSITION_X 1112 (-5) + - [ 1, 656884, 3, 54, 185] # EV_ABS / ABS_MT_POSITION_Y 185 (-1) + - [ 1, 656884, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 656884, 3, 53, 630] # EV_ABS / ABS_MT_POSITION_X 630 (-5) + - [ 1, 656884, 3, 0, 763] # EV_ABS / ABS_X 763 (-5) + - [ 1, 656884, 3, 1, 277] # EV_ABS / ABS_Y 277 (+1) + - [ 1, 656884, 4, 5, 1645200] # EV_MSC / MSC_TIMESTAMP 1645200 + - [ 1, 656884, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 663578, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 663578, 3, 53, 755] # EV_ABS / ABS_MT_POSITION_X 755 (-8) + - [ 1, 663578, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 663578, 3, 53, 1106] # EV_ABS / ABS_MT_POSITION_X 1106 (-6) + - [ 1, 663578, 3, 54, 184] # EV_ABS / ABS_MT_POSITION_Y 184 (-1) + - [ 1, 663578, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 663578, 3, 53, 621] # EV_ABS / ABS_MT_POSITION_X 621 (-9) + - [ 1, 663578, 3, 54, 496] # EV_ABS / ABS_MT_POSITION_Y 496 (-1) + - [ 1, 663578, 3, 0, 755] # EV_ABS / ABS_X 755 (-8) + - [ 1, 663578, 4, 5, 1652300] # EV_MSC / MSC_TIMESTAMP 1652300 + - [ 1, 663578, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 670287, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 670287, 3, 53, 748] # EV_ABS / ABS_MT_POSITION_X 748 (-7) + - [ 1, 670287, 3, 54, 278] # EV_ABS / ABS_MT_POSITION_Y 278 (+1) + - [ 1, 670287, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 670287, 3, 53, 1099] # EV_ABS / ABS_MT_POSITION_X 1099 (-7) + - [ 1, 670287, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 670287, 3, 53, 614] # EV_ABS / ABS_MT_POSITION_X 614 (-7) + - [ 1, 670287, 3, 0, 748] # EV_ABS / ABS_X 748 (-7) + - [ 1, 670287, 3, 1, 278] # EV_ABS / ABS_Y 278 (+1) + - [ 1, 670287, 4, 5, 1659300] # EV_MSC / MSC_TIMESTAMP 1659300 + - [ 1, 670287, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 676842, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 676842, 3, 53, 741] # EV_ABS / ABS_MT_POSITION_X 741 (-7) + - [ 1, 676842, 3, 54, 279] # EV_ABS / ABS_MT_POSITION_Y 279 (+1) + - [ 1, 676842, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 676842, 3, 53, 1093] # EV_ABS / ABS_MT_POSITION_X 1093 (-6) + - [ 1, 676842, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 676842, 3, 53, 608] # EV_ABS / ABS_MT_POSITION_X 608 (-6) + - [ 1, 676842, 3, 0, 741] # EV_ABS / ABS_X 741 (-7) + - [ 1, 676842, 3, 1, 279] # EV_ABS / ABS_Y 279 (+1) + - [ 1, 676842, 4, 5, 1666400] # EV_MSC / MSC_TIMESTAMP 1666400 + - [ 1, 676842, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 683429, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 683429, 3, 53, 737] # EV_ABS / ABS_MT_POSITION_X 737 (-4) + - [ 1, 683429, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 683429, 3, 53, 1089] # EV_ABS / ABS_MT_POSITION_X 1089 (-4) + - [ 1, 683429, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 683429, 3, 53, 604] # EV_ABS / ABS_MT_POSITION_X 604 (-4) + - [ 1, 683429, 3, 0, 737] # EV_ABS / ABS_X 737 (-4) + - [ 1, 683429, 4, 5, 1671300] # EV_MSC / MSC_TIMESTAMP 1671300 + - [ 1, 683429, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 689873, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 689873, 3, 53, 731] # EV_ABS / ABS_MT_POSITION_X 731 (-6) + - [ 1, 689873, 3, 54, 280] # EV_ABS / ABS_MT_POSITION_Y 280 (+1) + - [ 1, 689873, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 689873, 3, 53, 1082] # EV_ABS / ABS_MT_POSITION_X 1082 (-7) + - [ 1, 689873, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 689873, 3, 53, 598] # EV_ABS / ABS_MT_POSITION_X 598 (-6) + - [ 1, 689873, 3, 0, 731] # EV_ABS / ABS_X 731 (-6) + - [ 1, 689873, 3, 1, 280] # EV_ABS / ABS_Y 280 (+1) + - [ 1, 689873, 4, 5, 1678600] # EV_MSC / MSC_TIMESTAMP 1678600 + - [ 1, 689873, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 696952, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 696952, 3, 53, 727] # EV_ABS / ABS_MT_POSITION_X 727 (-4) + - [ 1, 696952, 3, 54, 279] # EV_ABS / ABS_MT_POSITION_Y 279 (-1) + - [ 1, 696952, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 696952, 3, 53, 1077] # EV_ABS / ABS_MT_POSITION_X 1077 (-5) + - [ 1, 696952, 3, 54, 183] # EV_ABS / ABS_MT_POSITION_Y 183 (-1) + - [ 1, 696952, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 696952, 3, 53, 594] # EV_ABS / ABS_MT_POSITION_X 594 (-4) + - [ 1, 696952, 3, 0, 727] # EV_ABS / ABS_X 727 (-4) + - [ 1, 696952, 3, 1, 279] # EV_ABS / ABS_Y 279 (-1) + - [ 1, 696952, 4, 5, 1683600] # EV_MSC / MSC_TIMESTAMP 1683600 + - [ 1, 696952, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 703470, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 703470, 3, 53, 722] # EV_ABS / ABS_MT_POSITION_X 722 (-5) + - [ 1, 703470, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 703470, 3, 53, 1069] # EV_ABS / ABS_MT_POSITION_X 1069 (-8) + - [ 1, 703470, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 703470, 3, 53, 589] # EV_ABS / ABS_MT_POSITION_X 589 (-5) + - [ 1, 703470, 3, 0, 722] # EV_ABS / ABS_X 722 (-5) + - [ 1, 703470, 4, 5, 1690800] # EV_MSC / MSC_TIMESTAMP 1690800 + - [ 1, 703470, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 710195, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 710195, 3, 53, 717] # EV_ABS / ABS_MT_POSITION_X 717 (-5) + - [ 1, 710195, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 710195, 3, 53, 1062] # EV_ABS / ABS_MT_POSITION_X 1062 (-7) + - [ 1, 710195, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 710195, 3, 53, 584] # EV_ABS / ABS_MT_POSITION_X 584 (-5) + - [ 1, 710195, 3, 0, 717] # EV_ABS / ABS_X 717 (-5) + - [ 1, 710195, 4, 5, 1697900] # EV_MSC / MSC_TIMESTAMP 1697900 + - [ 1, 710195, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 717003, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 717003, 3, 53, 712] # EV_ABS / ABS_MT_POSITION_X 712 (-5) + - [ 1, 717003, 3, 54, 280] # EV_ABS / ABS_MT_POSITION_Y 280 (+1) + - [ 1, 717003, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 717003, 3, 53, 1057] # EV_ABS / ABS_MT_POSITION_X 1057 (-5) + - [ 1, 717003, 3, 54, 184] # EV_ABS / ABS_MT_POSITION_Y 184 (+1) + - [ 1, 717003, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 717003, 3, 53, 579] # EV_ABS / ABS_MT_POSITION_X 579 (-5) + - [ 1, 717003, 3, 54, 495] # EV_ABS / ABS_MT_POSITION_Y 495 (-1) + - [ 1, 717003, 3, 0, 712] # EV_ABS / ABS_X 712 (-5) + - [ 1, 717003, 3, 1, 280] # EV_ABS / ABS_Y 280 (+1) + - [ 1, 717003, 4, 5, 1705000] # EV_MSC / MSC_TIMESTAMP 1705000 + - [ 1, 717003, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 723386, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 723386, 3, 53, 708] # EV_ABS / ABS_MT_POSITION_X 708 (-4) + - [ 1, 723386, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 723386, 3, 53, 1051] # EV_ABS / ABS_MT_POSITION_X 1051 (-6) + - [ 1, 723386, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 723386, 3, 53, 575] # EV_ABS / ABS_MT_POSITION_X 575 (-4) + - [ 1, 723386, 3, 0, 708] # EV_ABS / ABS_X 708 (-4) + - [ 1, 723386, 4, 5, 1711900] # EV_MSC / MSC_TIMESTAMP 1711900 + - [ 1, 723386, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 730332, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 730332, 3, 53, 704] # EV_ABS / ABS_MT_POSITION_X 704 (-4) + - [ 1, 730332, 3, 54, 281] # EV_ABS / ABS_MT_POSITION_Y 281 (+1) + - [ 1, 730332, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 730332, 3, 53, 1047] # EV_ABS / ABS_MT_POSITION_X 1047 (-4) + - [ 1, 730332, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 730332, 3, 53, 571] # EV_ABS / ABS_MT_POSITION_X 571 (-4) + - [ 1, 730332, 3, 0, 704] # EV_ABS / ABS_X 704 (-4) + - [ 1, 730332, 3, 1, 281] # EV_ABS / ABS_Y 281 (+1) + - [ 1, 730332, 4, 5, 1718700] # EV_MSC / MSC_TIMESTAMP 1718700 + - [ 1, 730332, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 736749, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 736749, 3, 53, 700] # EV_ABS / ABS_MT_POSITION_X 700 (-4) + - [ 1, 736749, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 736749, 3, 53, 1045] # EV_ABS / ABS_MT_POSITION_X 1045 (-2) + - [ 1, 736749, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 736749, 3, 53, 567] # EV_ABS / ABS_MT_POSITION_X 567 (-4) + - [ 1, 736749, 3, 54, 496] # EV_ABS / ABS_MT_POSITION_Y 496 (+1) + - [ 1, 736749, 3, 0, 700] # EV_ABS / ABS_X 700 (-4) + - [ 1, 736749, 4, 5, 1725500] # EV_MSC / MSC_TIMESTAMP 1725500 + - [ 1, 736749, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 743753, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 743753, 3, 53, 697] # EV_ABS / ABS_MT_POSITION_X 697 (-3) + - [ 1, 743753, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 743753, 3, 53, 1042] # EV_ABS / ABS_MT_POSITION_X 1042 (-3) + - [ 1, 743753, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 743753, 3, 53, 564] # EV_ABS / ABS_MT_POSITION_X 564 (-3) + - [ 1, 743753, 3, 0, 697] # EV_ABS / ABS_X 697 (-3) + - [ 1, 743753, 4, 5, 1732300] # EV_MSC / MSC_TIMESTAMP 1732300 + - [ 1, 743753, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 750465, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 750465, 3, 53, 695] # EV_ABS / ABS_MT_POSITION_X 695 (-2) + - [ 1, 750465, 3, 54, 282] # EV_ABS / ABS_MT_POSITION_Y 282 (+1) + - [ 1, 750465, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 750465, 3, 53, 1040] # EV_ABS / ABS_MT_POSITION_X 1040 (-2) + - [ 1, 750465, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 750465, 3, 53, 562] # EV_ABS / ABS_MT_POSITION_X 562 (-2) + - [ 1, 750465, 3, 0, 695] # EV_ABS / ABS_X 695 (-2) + - [ 1, 750465, 3, 1, 282] # EV_ABS / ABS_Y 282 (+1) + - [ 1, 750465, 4, 5, 1739000] # EV_MSC / MSC_TIMESTAMP 1739000 + - [ 1, 750465, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 757177, 3, 53, 561] # EV_ABS / ABS_MT_POSITION_X 561 (-1) + - [ 1, 757177, 4, 5, 1743500] # EV_MSC / MSC_TIMESTAMP 1743500 + - [ 1, 757177, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 764083, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 764083, 3, 53, 693] # EV_ABS / ABS_MT_POSITION_X 693 (-2) + - [ 1, 764083, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 764083, 3, 53, 1039] # EV_ABS / ABS_MT_POSITION_X 1039 (-1) + - [ 1, 764083, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 764083, 3, 53, 559] # EV_ABS / ABS_MT_POSITION_X 559 (-2) + - [ 1, 764083, 3, 0, 693] # EV_ABS / ABS_X 693 (-2) + - [ 1, 764083, 4, 5, 1750600] # EV_MSC / MSC_TIMESTAMP 1750600 + - [ 1, 764083, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 770502, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 770502, 3, 53, 692] # EV_ABS / ABS_MT_POSITION_X 692 (-1) + - [ 1, 770502, 3, 54, 283] # EV_ABS / ABS_MT_POSITION_Y 283 (+1) + - [ 1, 770502, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 770502, 3, 53, 1038] # EV_ABS / ABS_MT_POSITION_X 1038 (-1) + - [ 1, 770502, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 770502, 3, 54, 497] # EV_ABS / ABS_MT_POSITION_Y 497 (+1) + - [ 1, 770502, 3, 0, 692] # EV_ABS / ABS_X 692 (-1) + - [ 1, 770502, 3, 1, 283] # EV_ABS / ABS_Y 283 (+1) + - [ 1, 770502, 4, 5, 1757600] # EV_MSC / MSC_TIMESTAMP 1757600 + - [ 1, 770502, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 777230, 4, 5, 1764500] # EV_MSC / MSC_TIMESTAMP 1764500 + - [ 1, 777230, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 783943, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 783943, 3, 53, 691] # EV_ABS / ABS_MT_POSITION_X 691 (-1) + - [ 1, 783943, 3, 0, 691] # EV_ABS / ABS_X 691 (-1) + - [ 1, 783943, 4, 5, 1769200] # EV_MSC / MSC_TIMESTAMP 1769200 + - [ 1, 783943, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 790563, 4, 5, 1776200] # EV_MSC / MSC_TIMESTAMP 1776200 + - [ 1, 790563, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 797226, 3, 53, 692] # EV_ABS / ABS_MT_POSITION_X 692 (+1) + - [ 1, 797226, 3, 0, 692] # EV_ABS / ABS_X 692 (+1) + - [ 1, 797226, 4, 5, 1783100] # EV_MSC / MSC_TIMESTAMP 1783100 + - [ 1, 797226, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 804333, 4, 5, 1790200] # EV_MSC / MSC_TIMESTAMP 1790200 + - [ 1, 804333, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 811196, 3, 53, 691] # EV_ABS / ABS_MT_POSITION_X 691 (-1) + - [ 1, 811196, 3, 0, 691] # EV_ABS / ABS_X 691 (-1) + - [ 1, 811196, 4, 5, 1797200] # EV_MSC / MSC_TIMESTAMP 1797200 + - [ 1, 811196, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 817883, 4, 5, 1801900] # EV_MSC / MSC_TIMESTAMP 1801900 + - [ 1, 817883, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 824542, 4, 5, 1809000] # EV_MSC / MSC_TIMESTAMP 1809000 + - [ 1, 824542, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 831400, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 831400, 3, 53, 558] # EV_ABS / ABS_MT_POSITION_X 558 (-1) + - [ 1, 831400, 4, 5, 1816000] # EV_MSC / MSC_TIMESTAMP 1816000 + - [ 1, 831400, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 838245, 4, 5, 1823000] # EV_MSC / MSC_TIMESTAMP 1823000 + - [ 1, 838245, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 844760, 4, 5, 1829800] # EV_MSC / MSC_TIMESTAMP 1829800 + - [ 1, 844760, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 851360, 4, 5, 1836700] # EV_MSC / MSC_TIMESTAMP 1836700 + - [ 1, 851360, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 857869, 4, 5, 1841300] # EV_MSC / MSC_TIMESTAMP 1841300 + - [ 1, 857869, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 864640, 4, 5, 1848200] # EV_MSC / MSC_TIMESTAMP 1848200 + - [ 1, 864640, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 871296, 4, 5, 1855100] # EV_MSC / MSC_TIMESTAMP 1855100 + - [ 1, 871296, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 878089, 4, 5, 1861900] # EV_MSC / MSC_TIMESTAMP 1861900 + - [ 1, 878089, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 884879, 3, 53, 557] # EV_ABS / ABS_MT_POSITION_X 557 (-1) + - [ 1, 884879, 4, 5, 1868700] # EV_MSC / MSC_TIMESTAMP 1868700 + - [ 1, 884879, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 891511, 4, 5, 1875600] # EV_MSC / MSC_TIMESTAMP 1875600 + - [ 1, 891511, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 898364, 4, 5, 1880200] # EV_MSC / MSC_TIMESTAMP 1880200 + - [ 1, 898364, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 905016, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 905016, 3, 53, 690] # EV_ABS / ABS_MT_POSITION_X 690 (-1) + - [ 1, 905016, 3, 0, 690] # EV_ABS / ABS_X 690 (-1) + - [ 1, 905016, 4, 5, 1887200] # EV_MSC / MSC_TIMESTAMP 1887200 + - [ 1, 905016, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 911524, 4, 5, 1894200] # EV_MSC / MSC_TIMESTAMP 1894200 + - [ 1, 911524, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 918842, 4, 5, 1901200] # EV_MSC / MSC_TIMESTAMP 1901200 + - [ 1, 918842, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 925492, 4, 5, 1908200] # EV_MSC / MSC_TIMESTAMP 1908200 + - [ 1, 925492, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 932285, 4, 5, 1915200] # EV_MSC / MSC_TIMESTAMP 1915200 + - [ 1, 932285, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 939173, 4, 5, 1919800] # EV_MSC / MSC_TIMESTAMP 1919800 + - [ 1, 939173, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 945604, 3, 53, 691] # EV_ABS / ABS_MT_POSITION_X 691 (+1) + - [ 1, 945604, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 945604, 3, 54, 183] # EV_ABS / ABS_MT_POSITION_Y 183 (-1) + - [ 1, 945604, 3, 0, 691] # EV_ABS / ABS_X 691 (+1) + - [ 1, 945604, 4, 5, 1926700] # EV_MSC / MSC_TIMESTAMP 1926700 + - [ 1, 945604, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 952416, 4, 5, 1933700] # EV_MSC / MSC_TIMESTAMP 1933700 + - [ 1, 952416, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 958835, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 958835, 3, 53, 692] # EV_ABS / ABS_MT_POSITION_X 692 (+1) + - [ 1, 958835, 3, 0, 692] # EV_ABS / ABS_X 692 (+1) + - [ 1, 958835, 4, 5, 1940700] # EV_MSC / MSC_TIMESTAMP 1940700 + - [ 1, 958835, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +6ms + - evdev: + - [ 1, 965881, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 965881, 3, 54, 184] # EV_ABS / ABS_MT_POSITION_Y 184 (+1) + - [ 1, 965881, 4, 5, 1945400] # EV_MSC / MSC_TIMESTAMP 1945400 + - [ 1, 965881, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + - evdev: + - [ 1, 972142, 3, 47, 0] # EV_ABS / ABS_MT_SLOT 0 + - [ 1, 972142, 3, 57, -1] # EV_ABS / ABS_MT_TRACKING_ID -1 + - [ 1, 972142, 3, 47, 1] # EV_ABS / ABS_MT_SLOT 1 + - [ 1, 972142, 3, 57, -1] # EV_ABS / ABS_MT_TRACKING_ID -1 + - [ 1, 972142, 3, 47, 2] # EV_ABS / ABS_MT_SLOT 2 + - [ 1, 972142, 3, 57, -1] # EV_ABS / ABS_MT_TRACKING_ID -1 + - [ 1, 972142, 1, 330, 0] # EV_KEY / BTN_TOUCH 0 + - [ 1, 972142, 1, 334, 0] # EV_KEY / BTN_TOOL_TRIPLETAP 0 + - [ 1, 972142, 4, 5, 1965500] # EV_MSC / MSC_TIMESTAMP 1965500 + - [ 1, 972142, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +7ms + # Touch device in neutral state diff --git a/tests/template.nix b/tests/template.nix index 1086c63c..a216e3da 100644 --- a/tests/template.nix +++ b/tests/template.nix @@ -17,7 +17,6 @@ conf = Configuration("${testsDir}/features/${featureName}", userdata = driver.test_symbols()) start_all() - if run_behave(conf) != 0: - raise AssertionError("One or more Behave features have failed. Check the logs above for details.") + exit(run_behave(conf)) ''; } // (pkgs.lib.filterAttrs (n: v: n != "pkgs" && n != "defaultConfig" && n != "testsDir" && n != "featureName") opts) From 6d6ab22efe886b7c4658b15509f47165f7e8ab4b Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Wed, 18 Mar 2026 12:15:14 +0900 Subject: [PATCH 03/16] Run unsafe Shell, allow JS injection --- tests/features/steps/basic.py | 6 +++--- tests/features/steps/common.py | 29 ++++++++++++++++++++--------- tests/features/steps/input.py | 6 +++--- vm.nix | 18 +++++++++++++----- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/tests/features/steps/basic.py b/tests/features/steps/basic.py index 26ad8cbb..144b9d59 100644 --- a/tests/features/steps/basic.py +++ b/tests/features/steps/basic.py @@ -1,12 +1,12 @@ from behave import given, when, then -from common import unpack +from common import NixOSNamespace @when("the machine starts") def machine_boot(context): - nixos = unpack(context) + nixos = NixOSNamespace(context) # no-op: our test template starts the machine already @then("the machine should reach graphics") def graphical_target(context): - nixos = unpack(context) + nixos = NixOSNamespace(context) nixos.machine.wait_for_unit("graphical.target") diff --git a/tests/features/steps/common.py b/tests/features/steps/common.py index a7e415e0..a7c46dd0 100644 --- a/tests/features/steps/common.py +++ b/tests/features/steps/common.py @@ -1,14 +1,25 @@ from types import SimpleNamespace from pathlib import Path -def unpack(context): - ''' Shortcut to SimpleNamespace, helps unpack our NixOS test objects from the - userdata dict. +class NixOSNamespace(SimpleNamespace): + ''' Derived version of SimpleNamespace, helps unpack our NixOS test objects + and add utility functions for commonly used test steps. ''' - return SimpleNamespace(**context.config.userdata) -def libinput_play(recording, nixos): - ''' Play the specified libinput recording file. - ''' - recordFile = Path().resolve() / "recordings" / recording - nixos.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) + def __init__(self, context): + self.__dict__.update(**context.config.userdata) + + def libinput_play(self, recording): + ''' Play the specified libinput recording file. + ''' + recordFile = Path().resolve() / "recordings" / recording + self.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) + + def gjs_eval(self, code): + ''' Execute the specified GJS code from within the GNOME Shell process. + ''' + SHELL_DBUS = "org.gnome.Shell" + SHELL_OBJECT = "/org/gnome/Shell" + EVAL_DBUS = "org.gnome.Shell.Eval" + esc_code = code.replace('"', '\\"') + self.machine.succeed(f"gdbus call --session {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{code}\"") diff --git a/tests/features/steps/input.py b/tests/features/steps/input.py index 15ff9e25..257d65e7 100644 --- a/tests/features/steps/input.py +++ b/tests/features/steps/input.py @@ -1,7 +1,7 @@ from behave import given, when, then -from common import unpack, libinput_play +from common import NixOSNamespace @when("the user performs {gesture}") def play_gesture(context, gesture): - nixos = unpack(context) - libinput_play(gesture + ".yaml", nixos) + nixos = NixOSNamespace(context) + nixos.libinput_play(gesture + ".yaml") diff --git a/vm.nix b/vm.nix index 164621cc..00f04198 100644 --- a/vm.nix +++ b/vm.nix @@ -8,14 +8,22 @@ ]; ### Set graphical session to auto-login GNOME - services.xserver = - { enable = true; - displayManager.autoLogin = + services.displayManager = { + gdm.enable = true; + autoLogin = { enable = true; user = "user"; }; - displayManager.gdm.enable = true; - desktopManager.gnome.enable = true; + }; + services.desktopManager.gnome = { + enable = true; + debug = true; + }; + + ### Enable unsafe mode by default + systemd.user.services."org.gnome.Shell@wayland" = { + overrideStrategy = "asDropin"; + serviceConfig.ExecStart = ["" "${pkgs.gnome-shell}/bin/gnome-shell --unsafe-mode"]; }; ### Set dconf to enable PaperWM out of the box From 0ea96394fad58a859594d4513d50e96c7536904a Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Wed, 18 Mar 2026 12:48:11 +0900 Subject: [PATCH 04/16] Introduce module introspection --- app.js | 2 ++ default.nix | 2 +- extension.js | 5 +++++ gestures.js | 2 ++ grab.js | 2 ++ keybindings.js | 2 ++ liveAltTab.js | 2 ++ navigator.js | 2 ++ patches.js | 2 ++ scratch.js | 2 ++ settings.js | 2 ++ stackoverlay.js | 2 ++ tests/features/steps/common.py | 8 ++++++-- tiling.js | 2 ++ topbar.js | 2 ++ utils.js | 2 ++ workspace.js | 2 ++ 17 files changed, 40 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 6c7fa569..72b9c3af 100644 --- a/app.js +++ b/app.js @@ -6,6 +6,8 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import { Patches, Tiling } from './imports.js'; +export const name = "app"; + /* Application functionality, like global new window actions etc. */ diff --git a/default.nix b/default.nix index a55647dc..92a98dda 100644 --- a/default.nix +++ b/default.nix @@ -10,7 +10,7 @@ stdenv.mkDerivation { makeFlags = [ "SOURCE=$(src)" "EXT_DIR=$(out)/share/gnome-shell/extensions" ]; - nativeBuildInputs = with pkgs; + nativeBuildInputs = [ glib ]; diff --git a/extension.js b/extension.js index e9163272..54d8ef0d 100644 --- a/extension.js +++ b/extension.js @@ -52,6 +52,11 @@ export default class PaperWM extends Extension { Workspace, Tiling, Topbar, App, Grab, ]; + // Name-based introspection for unit tests + findModule(name) { + return this.modules.find((m) => m.name == name); + } + #userStylesheet = null; enable() { diff --git a/gestures.js b/gestures.js index d1d35179..cdc19cb6 100644 --- a/gestures.js +++ b/gestures.js @@ -9,6 +9,8 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import { Patches, Settings, Tiling, Utils, Lib, Navigator } from './imports.js'; import { Easer } from './utils.js'; +export const name = "gestures"; + const DIRECTIONS = { Horizontal: true, Vertical: false, diff --git a/grab.js b/grab.js index ed5fe3d5..1b025ca3 100644 --- a/grab.js +++ b/grab.js @@ -9,6 +9,8 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import { Settings, Utils, Tiling, Navigator, Scratch, Gestures } from './imports.js'; import { Easer } from './utils.js'; +export const name = "grab"; + export let grabbed = false; let dragDriftTimeout; diff --git a/keybindings.js b/keybindings.js index 8928a9c4..92299407 100644 --- a/keybindings.js +++ b/keybindings.js @@ -9,6 +9,8 @@ import { App, Scratch, LiveAltTab, Topbar } from './imports.js'; +export const name = "keybindings"; + const Seat = Clutter.get_default_backend().get_default_seat(); const display = global.display; diff --git a/liveAltTab.js b/liveAltTab.js index cb8ee71d..53ae6b86 100644 --- a/liveAltTab.js +++ b/liveAltTab.js @@ -9,6 +9,8 @@ import * as AltTab from 'resource:///org/gnome/shell/ui/altTab.js'; import { Settings, Keybindings, Tiling, Scratch, Utils } from './imports.js'; import { Easer } from './utils.js'; +export const name = "liveAltTab"; + let switcherSettings; export function enable() { switcherSettings = new Gio.Settings({ diff --git a/navigator.js b/navigator.js index fa79b1ca..bd1e6998 100644 --- a/navigator.js +++ b/navigator.js @@ -10,6 +10,8 @@ import { Scratch, Minimap, Settings } from './imports.js'; +export const name = "navigator"; + /** Navigation and previewing functionality. diff --git a/patches.js b/patches.js index e4943806..105a42e6 100644 --- a/patches.js +++ b/patches.js @@ -18,6 +18,8 @@ import * as Screenshot from 'resource:///org/gnome/shell/ui/screenshot.js'; import { Utils, Tiling, Scratch, Settings, OverviewLayout } from './imports.js'; +export const name = "patches"; + /** Some of Gnome Shell's default behavior is really sub-optimal when using paperWM. Other features are simply not possible to implement without monkey diff --git a/scratch.js b/scratch.js index ec9aef7b..6e223daa 100644 --- a/scratch.js +++ b/scratch.js @@ -8,6 +8,8 @@ import * as WindowMenu from 'resource:///org/gnome/shell/ui/windowMenu.js'; import { Settings, Utils, Tiling, Topbar } from './imports.js'; import { Easer } from './utils.js'; +export const name = "scratch"; + let originalBuildMenu; let float, scratchFrame; // symbols used for expando properties on metawindow export function enable() { diff --git a/settings.js b/settings.js index c35d34c2..f4c4d974 100644 --- a/settings.js +++ b/settings.js @@ -9,6 +9,8 @@ import { AcceleratorParse } from './acceleratorparse.js'; at the top). */ +export const name = "settings"; + const KEYBINDINGS_KEY = 'org.gnome.shell.extensions.paperwm.keybindings'; const RESTORE_KEYBINDS_KEY = 'restore-keybinds'; diff --git a/stackoverlay.js b/stackoverlay.js index d2cb7629..14f3000b 100644 --- a/stackoverlay.js +++ b/stackoverlay.js @@ -9,6 +9,8 @@ import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.j import { Settings, Utils, Tiling, Grab, Scratch } from './imports.js'; +export const name = "stackoverlay"; + /* The stack overlay decorates the top stacked window with its icon and captures mouse input such that a mouse click only _activates_ the diff --git a/tests/features/steps/common.py b/tests/features/steps/common.py index a7c46dd0..b787fe66 100644 --- a/tests/features/steps/common.py +++ b/tests/features/steps/common.py @@ -21,5 +21,9 @@ def gjs_eval(self, code): SHELL_DBUS = "org.gnome.Shell" SHELL_OBJECT = "/org/gnome/Shell" EVAL_DBUS = "org.gnome.Shell.Eval" - esc_code = code.replace('"', '\\"') - self.machine.succeed(f"gdbus call --session {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{code}\"") + code_full = f''' + paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; + {code} + ''' + esc_code = code_full.replace('"', '\\"').replace('`', '\\`') + return self.machine.succeed(f"gdbus call --session {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{esc_code}\"") diff --git a/tiling.js b/tiling.js index e84d7310..49c478d6 100644 --- a/tiling.js +++ b/tiling.js @@ -15,6 +15,8 @@ import { Easer } from './utils.js'; import { ClickOverlay } from './stackoverlay.js'; import { WorkspaceSettings } from './workspace.js'; +export const name = "tiling"; + const { signals: Signals } = imports; const workspaceManager = global.workspace_manager; const display = global.display; diff --git a/topbar.js b/topbar.js index c9822a6a..cc250ba0 100644 --- a/topbar.js +++ b/topbar.js @@ -13,6 +13,8 @@ import * as popupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; import { Settings, Utils, Tiling, Navigator, Scratch } from './imports.js'; +export const name = "topbar"; + // eslint-disable-next-line no-undef const workspaceManager = global.workspace_manager; // eslint-disable-next-line no-undef diff --git a/utils.js b/utils.js index 15bb86af..ae036a52 100644 --- a/utils.js +++ b/utils.js @@ -12,6 +12,8 @@ import * as Config from 'resource:///org/gnome/shell/misc/config.js'; import { Lib } from './imports.js'; +export const name = "utils"; + const Display = global.display; export let version = Config.PACKAGE_VERSION.split('.').map(Number); diff --git a/workspace.js b/workspace.js index 73fdf659..a9dda0e4 100644 --- a/workspace.js +++ b/workspace.js @@ -3,6 +3,8 @@ import GLib from 'gi://GLib'; import * as Lib from './lib.js'; +export const name = "workspace"; + /** * Workspace related utility functions used by other modules. */ From 0679f6bd0ec2a13917488380266c84c024042920 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Thu, 19 Mar 2026 14:31:42 +0900 Subject: [PATCH 05/16] Fix path lookup for recordings --- tests/features/steps/common.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/features/steps/common.py b/tests/features/steps/common.py index b787fe66..8375a94e 100644 --- a/tests/features/steps/common.py +++ b/tests/features/steps/common.py @@ -8,12 +8,13 @@ class NixOSNamespace(SimpleNamespace): def __init__(self, context): self.__dict__.update(**context.config.userdata) + self._base_dir = Path(context.config.base_dir).parent.resolve() def libinput_play(self, recording): ''' Play the specified libinput recording file. ''' - recordFile = Path().resolve() / "recordings" / recording - self.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) + recordFile = self._base_dir / "recordings" / recording + self.machine.succeed("sudo libinput replay --once --replay-after 0 %s" %recordFile) def gjs_eval(self, code): ''' Execute the specified GJS code from within the GNOME Shell process. From 0c9a916a2d7f59ffbc8dece48cbfe953345a038c Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Thu, 19 Mar 2026 15:50:18 +0900 Subject: [PATCH 06/16] Wait for PaperWM before starting tests --- tests/features/environment.py | 8 ++++++++ tests/features/steps/common.py | 23 ++++++++++++++--------- tests/template.nix | 2 ++ 3 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 tests/features/environment.py diff --git a/tests/features/environment.py b/tests/features/environment.py new file mode 100644 index 00000000..1e4c5890 --- /dev/null +++ b/tests/features/environment.py @@ -0,0 +1,8 @@ +from steps.common import NixOSNamespace + +def before_all(context): + ''' Wait until PaperWM is actually running + ''' + print("Waiting for PaperWM...") + nixos = NixOSNamespace(context) + nixos.wait_for_paperwm() diff --git a/tests/features/steps/common.py b/tests/features/steps/common.py index 8375a94e..3ae4da48 100644 --- a/tests/features/steps/common.py +++ b/tests/features/steps/common.py @@ -10,21 +10,26 @@ def __init__(self, context): self.__dict__.update(**context.config.userdata) self._base_dir = Path(context.config.base_dir).parent.resolve() + def _gjs_cmdline(self, code): + SHELL_DBUS = "org.gnome.Shell" + SHELL_OBJECT = "/org/gnome/Shell" + EVAL_DBUS = "org.gnome.Shell.Eval" + code_full = f''' paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; {code} ''' + esc_code = code_full.replace('"', '\\"').replace('`', '\\`') + return f"sudo -u user gdbus call -a unix:path=/run/user/1000/bus -d {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{esc_code}\"" + def libinput_play(self, recording): ''' Play the specified libinput recording file. ''' recordFile = self._base_dir / "recordings" / recording - self.machine.succeed("sudo libinput replay --once --replay-after 0 %s" %recordFile) + self.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) def gjs_eval(self, code): ''' Execute the specified GJS code from within the GNOME Shell process. ''' - SHELL_DBUS = "org.gnome.Shell" - SHELL_OBJECT = "/org/gnome/Shell" - EVAL_DBUS = "org.gnome.Shell.Eval" - code_full = f''' - paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; - {code} + return self.machine.succeed(self._gjs_cmdline(code)) + + def wait_for_paperwm(self): + ''' Wait until GNOME Shell is able to yield PaperWM internal state. ''' - esc_code = code_full.replace('"', '\\"').replace('`', '\\`') - return self.machine.succeed(f"gdbus call --session {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{esc_code}\"") + return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone')) diff --git a/tests/template.nix b/tests/template.nix index a216e3da..7fcb1fd0 100644 --- a/tests/template.nix +++ b/tests/template.nix @@ -16,6 +16,8 @@ from behave.__main__ import run_behave conf = Configuration("${testsDir}/features/${featureName}", userdata = driver.test_symbols()) + conf.capture_stdout = False + conf.capture_stderr = False start_all() exit(run_behave(conf)) ''; From e9fe9f9d2ed07ae12653078b7059bf3e02a382c3 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Thu, 19 Mar 2026 15:52:42 +0900 Subject: [PATCH 07/16] Clean up NixOSContext setup --- tests/features/environment.py | 40 +++++++++++++++++++++++++++++++--- tests/features/steps/basic.py | 6 ++--- tests/features/steps/common.py | 35 ----------------------------- tests/features/steps/input.py | 4 +--- 4 files changed, 40 insertions(+), 45 deletions(-) delete mode 100644 tests/features/steps/common.py diff --git a/tests/features/environment.py b/tests/features/environment.py index 1e4c5890..3fb9085f 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -1,8 +1,42 @@ -from steps.common import NixOSNamespace +from types import SimpleNamespace +from pathlib import Path + +class NixOSNamespace(SimpleNamespace): + ''' Derived version of SimpleNamespace, helps unpack our NixOS test objects + and add utility functions for commonly used test steps. + ''' + + def __init__(self, context): + self.__dict__.update(**context.config.userdata) + self._base_dir = Path(context.config.base_dir).parent.resolve() + + def _gjs_cmdline(self, code): + SHELL_DBUS = "org.gnome.Shell" + SHELL_OBJECT = "/org/gnome/Shell" + EVAL_DBUS = "org.gnome.Shell.Eval" + code_full = f''' paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; {code} ''' + esc_code = code_full.replace('"', '\\"').replace('`', '\\`') + return f"sudo -u user gdbus call -a unix:path=/run/user/1000/bus -d {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{esc_code}\"" + + def libinput_play(self, recording): + ''' Play the specified libinput recording file. + ''' + recordFile = self._base_dir / "recordings" / recording + self.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) + + def gjs_eval(self, code): + ''' Execute the specified GJS code from within the GNOME Shell process. + ''' + return self.machine.succeed(self._gjs_cmdline(code)) + + def wait_for_paperwm(self): + ''' Wait until GNOME Shell is able to yield PaperWM internal state. + ''' + return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone')) def before_all(context): ''' Wait until PaperWM is actually running ''' print("Waiting for PaperWM...") - nixos = NixOSNamespace(context) - nixos.wait_for_paperwm() + context.nixos = NixOSNamespace(context) + context.nixos.wait_for_paperwm() diff --git a/tests/features/steps/basic.py b/tests/features/steps/basic.py index 144b9d59..807ee129 100644 --- a/tests/features/steps/basic.py +++ b/tests/features/steps/basic.py @@ -1,12 +1,10 @@ from behave import given, when, then -from common import NixOSNamespace @when("the machine starts") def machine_boot(context): - nixos = NixOSNamespace(context) + pass # no-op: our test template starts the machine already @then("the machine should reach graphics") def graphical_target(context): - nixos = NixOSNamespace(context) - nixos.machine.wait_for_unit("graphical.target") + context.nixos.machine.wait_for_unit("graphical.target") diff --git a/tests/features/steps/common.py b/tests/features/steps/common.py deleted file mode 100644 index 3ae4da48..00000000 --- a/tests/features/steps/common.py +++ /dev/null @@ -1,35 +0,0 @@ -from types import SimpleNamespace -from pathlib import Path - -class NixOSNamespace(SimpleNamespace): - ''' Derived version of SimpleNamespace, helps unpack our NixOS test objects - and add utility functions for commonly used test steps. - ''' - - def __init__(self, context): - self.__dict__.update(**context.config.userdata) - self._base_dir = Path(context.config.base_dir).parent.resolve() - - def _gjs_cmdline(self, code): - SHELL_DBUS = "org.gnome.Shell" - SHELL_OBJECT = "/org/gnome/Shell" - EVAL_DBUS = "org.gnome.Shell.Eval" - code_full = f''' paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; {code} ''' - esc_code = code_full.replace('"', '\\"').replace('`', '\\`') - return f"sudo -u user gdbus call -a unix:path=/run/user/1000/bus -d {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{esc_code}\"" - - def libinput_play(self, recording): - ''' Play the specified libinput recording file. - ''' - recordFile = self._base_dir / "recordings" / recording - self.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) - - def gjs_eval(self, code): - ''' Execute the specified GJS code from within the GNOME Shell process. - ''' - return self.machine.succeed(self._gjs_cmdline(code)) - - def wait_for_paperwm(self): - ''' Wait until GNOME Shell is able to yield PaperWM internal state. - ''' - return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone')) diff --git a/tests/features/steps/input.py b/tests/features/steps/input.py index 257d65e7..50c98a6b 100644 --- a/tests/features/steps/input.py +++ b/tests/features/steps/input.py @@ -1,7 +1,5 @@ from behave import given, when, then -from common import NixOSNamespace @when("the user performs {gesture}") def play_gesture(context, gesture): - nixos = NixOSNamespace(context) - nixos.libinput_play(gesture + ".yaml") + context.nixos.libinput_play(gesture + ".yaml") From 4adc11e852137556bc224627fd8b305637bbedc9 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Thu, 19 Mar 2026 16:11:17 +0900 Subject: [PATCH 08/16] Add fixture for waiting for PaperWM --- tests/features/basic.feature | 1 + tests/features/environment.py | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/features/basic.feature b/tests/features/basic.feature index 04b605c6..f7554c62 100644 --- a/tests/features/basic.feature +++ b/tests/features/basic.feature @@ -7,5 +7,6 @@ Feature: The test machine starts When the machine starts Then the machine should reach graphics + @fixture.shell Scenario: Three finger swipe (stub) When the user performs three-finger-swipe diff --git a/tests/features/environment.py b/tests/features/environment.py index 3fb9085f..ef00b13c 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -1,5 +1,6 @@ from types import SimpleNamespace from pathlib import Path +from behave import fixture, use_fixture class NixOSNamespace(SimpleNamespace): ''' Derived version of SimpleNamespace, helps unpack our NixOS test objects @@ -34,9 +35,26 @@ def wait_for_paperwm(self): ''' return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone')) +@fixture +def shell(context): + ''' Wait for PaperWM to start + + ### Wait, why do we need to specify which tests need PaperWM? + + If we want to be able to assume given settings when PaperWM starts, we need + to have already updated dconf with them by the time GNOME has finished + loading, meaning the steps altering dconf cannot wait for the Shell. + + The first Scenario should then make configuration assumptions, which the + rest of the feature will be able to inherit. + ''' + context.nixos.wait_for_paperwm() + +def before_tag(context, tag): + if tag == "fixture.shell": + use_fixture(shell, context) + def before_all(context): - ''' Wait until PaperWM is actually running + ''' Populate the context with NixOS test objects ''' - print("Waiting for PaperWM...") context.nixos = NixOSNamespace(context) - context.nixos.wait_for_paperwm() From 89dce9f5b1bb5f01af4dbfe7ea63497a7325b921 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Thu, 19 Mar 2026 21:56:28 +0900 Subject: [PATCH 09/16] Add tentative GitHub workflow and OpenCV --- .github/workflows/testing.yaml | 36 ++++++++++++++++++++++++++++++++++ tests/features/environment.py | 10 ++++++++++ tests/template.nix | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/testing.yaml diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml new file mode 100644 index 00000000..23d3c5e0 --- /dev/null +++ b/.github/workflows/testing.yaml @@ -0,0 +1,36 @@ +name: "Run end-to-end tests for PaperWM" + +on: + push: + paths: + - '*.nix' + - '*.js' + - 'tests/**' + +jobs: + run-tests: + name: Run unit tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Set up Nix + uses: cachix/install-nix-action@v20 + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + sudo tee -a /etc/nix/nix.conf <<< "extra-system-features = kvm nixos-test" + - name: Build test VM + run: | + nix build .#vm + - name: Launch tests + run: | + for file in tests/features/*.feature + do + echo "::group::Test ${file##*/}" + feat="${file##*/}" + nix run .#checks.x86_64-linux.${feat%%.feature}.driver + echo "::endgroup::" + done diff --git a/tests/features/environment.py b/tests/features/environment.py index ef00b13c..74f87a4a 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -2,6 +2,8 @@ from pathlib import Path from behave import fixture, use_fixture +import cv2 + class NixOSNamespace(SimpleNamespace): ''' Derived version of SimpleNamespace, helps unpack our NixOS test objects and add utility functions for commonly used test steps. @@ -10,6 +12,7 @@ class NixOSNamespace(SimpleNamespace): def __init__(self, context): self.__dict__.update(**context.config.userdata) self._base_dir = Path(context.config.base_dir).parent.resolve() + self._context = context def _gjs_cmdline(self, code): SHELL_DBUS = "org.gnome.Shell" @@ -35,6 +38,13 @@ def wait_for_paperwm(self): ''' return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone')) + def screenshot(self): + ''' Take a screenshot and load it as an OpenCV-compatible representation + ''' + filename = f"scenario-{self._context.scenario.line}.png" + self.machine.screenshot(filename) + return cv2.imread(filename) + @fixture def shell(context): ''' Wait for PaperWM to start diff --git a/tests/template.nix b/tests/template.nix index 7fcb1fd0..b6407acd 100644 --- a/tests/template.nix +++ b/tests/template.nix @@ -7,7 +7,7 @@ name = featureName; nodes = { machine = defaultConfig; }; - extraPythonPackages = p: with p; [ behave ]; + extraPythonPackages = p: with p; [ behave opencv-python ]; skipTypeCheck = true; From fea07f7b9517e5804fbbfceb904aa9927b1bc6ee Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Sun, 22 Mar 2026 12:33:19 +0900 Subject: [PATCH 10/16] Stub test for OpenCV capture and comparison --- tests/features/basic.feature | 1 + tests/features/environment.py | 11 ++++++++++- tests/features/steps/visual.py | 18 ++++++++++++++++++ vm.nix | 8 +++++++- 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/features/steps/visual.py diff --git a/tests/features/basic.feature b/tests/features/basic.feature index f7554c62..82c1ad01 100644 --- a/tests/features/basic.feature +++ b/tests/features/basic.feature @@ -10,3 +10,4 @@ Feature: The test machine starts @fixture.shell Scenario: Three finger swipe (stub) When the user performs three-finger-swipe + Then the screen should match basic diff --git a/tests/features/environment.py b/tests/features/environment.py index 74f87a4a..ccf91c43 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -13,6 +13,8 @@ def __init__(self, context): self.__dict__.update(**context.config.userdata) self._base_dir = Path(context.config.base_dir).parent.resolve() self._context = context + self._last_scr_line = -1 + self._last_scr_id = 0 def _gjs_cmdline(self, code): SHELL_DBUS = "org.gnome.Shell" @@ -41,7 +43,14 @@ def wait_for_paperwm(self): def screenshot(self): ''' Take a screenshot and load it as an OpenCV-compatible representation ''' - filename = f"scenario-{self._context.scenario.line}.png" + if self._last_scr_line == self._context.scenario.line: + self._last_scr_id += 1 + else: + self._last_scr_line = self._context.scenario.line + self._last_scr_id = 0 + + featname = Path(self._context.config.paths[0]).name[:-len(".feature")] + filename = f"scr-{featname}-{self._context.scenario.line}_{self._last_scr_id}.png" self.machine.screenshot(filename) return cv2.imread(filename) diff --git a/tests/features/steps/visual.py b/tests/features/steps/visual.py new file mode 100644 index 00000000..1cac315e --- /dev/null +++ b/tests/features/steps/visual.py @@ -0,0 +1,18 @@ +from behave import given, when, then +from pathlib import Path + +import cv2 +import numpy as np + +@then("the screen should match {image}") +def scrcompare_simple(context, image): + screen = context.nixos.screenshot() + template = cv2.imread(Path(context.config.base_dir) / "screenshots" / f"{image}.png") + + res = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) + threshold = 0.90 + loc = np.whre(res >= threshold) + + print(loc) + + assert(len(loc[0]) > 0, "No match found.") diff --git a/vm.nix b/vm.nix index 00f04198..19260e49 100644 --- a/vm.nix +++ b/vm.nix @@ -23,7 +23,13 @@ ### Enable unsafe mode by default systemd.user.services."org.gnome.Shell@wayland" = { overrideStrategy = "asDropin"; - serviceConfig.ExecStart = ["" "${pkgs.gnome-shell}/bin/gnome-shell --unsafe-mode"]; + serviceConfig = { + ExecStart = ["" "${pkgs.gnome-shell}/bin/gnome-shell --unsafe-mode"]; + Environment = [ + "GJS_COVERAGE_OUTPUT=/home/coverage" + #"GJS_COVERAGE_PREFIXES=${./.}" + ]; + }; }; ### Set dconf to enable PaperWM out of the box From 4a4da803b348d402d124987d8fc96cd981d2a8a6 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Tue, 24 Mar 2026 22:22:41 +0900 Subject: [PATCH 11/16] Improved logic to wait for GNOME Shell, fixed screenshot path --- tests/features/environment.py | 11 ++++++++--- tests/features/steps/visual.py | 10 ++++------ tests/screenshots/basic.png | Bin 0 -> 58707 bytes vm.nix | 5 +++++ 4 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 tests/screenshots/basic.png diff --git a/tests/features/environment.py b/tests/features/environment.py index ccf91c43..72fdc05f 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -20,7 +20,7 @@ def _gjs_cmdline(self, code): SHELL_DBUS = "org.gnome.Shell" SHELL_OBJECT = "/org/gnome/Shell" EVAL_DBUS = "org.gnome.Shell.Eval" - code_full = f''' paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; {code} ''' + code_full = f''' let paperwm = Main.extensionManager.lookup("paperwm@paperwm.github.com").stateObj; {code} ''' esc_code = code_full.replace('"', '\\"').replace('`', '\\`') return f"sudo -u user gdbus call -a unix:path=/run/user/1000/bus -d {SHELL_DBUS} --object-path {SHELL_OBJECT} --method {EVAL_DBUS} \"{esc_code}\"" @@ -32,13 +32,18 @@ def libinput_play(self, recording): def gjs_eval(self, code): ''' Execute the specified GJS code from within the GNOME Shell process. + Will raise Exception in the event of a GJS error. ''' - return self.machine.succeed(self._gjs_cmdline(code)) + result = eval(self.machine.succeed(self._gjs_cmdline(code))) + if result[0]: + return result[1] + else: + raise Exception(result[1]) def wait_for_paperwm(self): ''' Wait until GNOME Shell is able to yield PaperWM internal state. ''' - return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone')) + return self.machine.wait_until_succeeds(self._gjs_cmdline('paperwm.findModule("tiling").spaces._initDone') + "| grep \"(true, 'true')\"") def screenshot(self): ''' Take a screenshot and load it as an OpenCV-compatible representation diff --git a/tests/features/steps/visual.py b/tests/features/steps/visual.py index 1cac315e..0ed4eded 100644 --- a/tests/features/steps/visual.py +++ b/tests/features/steps/visual.py @@ -7,12 +7,10 @@ @then("the screen should match {image}") def scrcompare_simple(context, image): screen = context.nixos.screenshot() - template = cv2.imread(Path(context.config.base_dir) / "screenshots" / f"{image}.png") + template = cv2.imread(Path(context.config.base_dir).parent.resolve() / "screenshots" / f"{image}.png") res = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) - threshold = 0.90 - loc = np.whre(res >= threshold) + threshold = 0.80 + loc = np.where(res >= threshold) - print(loc) - - assert(len(loc[0]) > 0, "No match found.") + assert len(loc[0]) > 0, "No match found." diff --git a/tests/screenshots/basic.png b/tests/screenshots/basic.png new file mode 100644 index 0000000000000000000000000000000000000000..6d1567c471c979fded12ffdfd88cc3304b99ab08 GIT binary patch literal 58707 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
e#~El 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 literal 0 HcmV?d00001 diff --git a/vm.nix b/vm.nix index 19260e49..6149c86e 100644 --- a/vm.nix +++ b/vm.nix @@ -66,4 +66,9 @@ { enable = true; extraConfig = "%wheel ALL=(ALL) NOPASSWD: ALL"; }; + + ### Switch to VirtIO emulated GPU + virtualisation.qemu.options = [ + "-vga virtio" + ]; } From d1e4a8b5f5d0aa7cd840caaa27eae904b779143e Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Wed, 25 Mar 2026 16:04:35 +0900 Subject: [PATCH 12/16] Generating Allure HTML reports --- .github/workflows/testing.yaml | 31 +++++++++++++++++++++++++++++++ tests/default.nix | 12 +++++++++--- tests/features/environment.py | 4 ++++ tests/report.nix | 22 ++++++++++++++++++++++ tests/template.nix | 7 ++++--- 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 tests/report.nix diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 23d3c5e0..f391050a 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -34,3 +34,34 @@ jobs: nix run .#checks.x86_64-linux.${feat%%.feature}.driver echo "::endgroup::" done + - name: Save results + uses: actions/upload-artifact@v7 + if: always() + with: + name: allure-output + path: allure_output + + push-reports: + name: Upload HTML reports to Pages + needs: run-tests + if: always() + runs-on: ubuntu-latest + permissions: + contents: write + pages: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Fetch report + uses: actions/download-artifact@v8 + with: + name: allure-output + path: allure_output + - name: Deploy report to GitHub Pages + uses: PavanMudigonda/html-reporter-github-pages@v1.5.21 + with: + test_results: allure_output + allure_report_generate_flag: true + keep_reports: 10 + gh_pages: pages_reports + workflow_name: ${{ github.workflow }} diff --git a/tests/default.nix b/tests/default.nix index 7992596f..7a0aec04 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -1,5 +1,4 @@ { pkgs ? import {} -, system ? builtins.currentSystem , runTest ? pkgs.testers.nixosTest , defaultConfig ? { ... }: { imports = [ ../vm.nix ]; } @@ -17,10 +16,17 @@ let lib = pkgs.lib; + # Run a test and generate an HTML report + behaveReport = test: + (pkgs.callPackage ./report.nix { inherit test; }); + # Run a single Behave feature file - behaveTest = featureName: as: runTest - (import ./template.nix ({ inherit defaultConfig pkgs featureName; } // as)); + behaveTest = featureName: as: + let testDrv = runTest + (import ./template.nix ({ inherit defaultConfig pkgs featureName; } // as)); + in testDrv // { report = behaveReport testDrv; }; + # Gather and generate tests for all feature files allBehaveTests = let allBehaveFiles = lib.filterAttrs (k: v: lib.hasSuffix ".feature" k && v == "regular") diff --git a/tests/features/environment.py b/tests/features/environment.py index 72fdc05f..5707b0ce 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -2,6 +2,7 @@ from pathlib import Path from behave import fixture, use_fixture +import allure import cv2 class NixOSNamespace(SimpleNamespace): @@ -57,6 +58,9 @@ def screenshot(self): featname = Path(self._context.config.paths[0]).name[:-len(".feature")] filename = f"scr-{featname}-{self._context.scenario.line}_{self._last_scr_id}.png" self.machine.screenshot(filename) + + with open(filename, 'rb') as imfile: + allure.attach(imfile.read(), name=filename, attachment_type=allure.attachment_type.PNG) return cv2.imread(filename) @fixture diff --git a/tests/report.nix b/tests/report.nix new file mode 100644 index 00000000..89b3d866 --- /dev/null +++ b/tests/report.nix @@ -0,0 +1,22 @@ +{ pkgs, lib, stdenv, allure + # A NixOS Behave test (with a .driver output) to run +, test +, ...}: + +stdenv.mkDerivation { + name = "${test.name}-report"; + src = pkgs.emptyDirectory; + + nativeBuildInputs = [ + allure + ]; + + buildPhase = '' + ${lib.getExe test.driver} || true + ''; + + installPhase = '' + mkdir -p $out + allure generate allure_output -o $out + ''; +} diff --git a/tests/template.nix b/tests/template.nix index b6407acd..a6545053 100644 --- a/tests/template.nix +++ b/tests/template.nix @@ -7,7 +7,7 @@ name = featureName; nodes = { machine = defaultConfig; }; - extraPythonPackages = p: with p; [ behave opencv-python ]; + extraPythonPackages = p: with p; [ behave opencv-python allure-behave ]; skipTypeCheck = true; @@ -16,8 +16,9 @@ from behave.__main__ import run_behave conf = Configuration("${testsDir}/features/${featureName}", userdata = driver.test_symbols()) - conf.capture_stdout = False - conf.capture_stderr = False + conf.format = [ "allure_behave.formatter:AllureFormatter", "pretty" ] + conf.outputs = [] + conf.setup_outputs(['allure_output']) start_all() exit(run_behave(conf)) ''; From bee581c80e58965ee2878e250a931d149bc5922d Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Wed, 25 Mar 2026 16:19:27 +0900 Subject: [PATCH 13/16] Added delay to libinput replay --- .github/workflows/testing.yaml | 1 + tests/features/steps/input.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index f391050a..47ca0730 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -65,3 +65,4 @@ jobs: keep_reports: 10 gh_pages: pages_reports workflow_name: ${{ github.workflow }} + use_actions_summary: true diff --git a/tests/features/steps/input.py b/tests/features/steps/input.py index 50c98a6b..4d5bee56 100644 --- a/tests/features/steps/input.py +++ b/tests/features/steps/input.py @@ -1,5 +1,8 @@ from behave import given, when, then +from time import sleep @when("the user performs {gesture}") def play_gesture(context, gesture): context.nixos.libinput_play(gesture + ".yaml") + # Wait for frames to settle on slow systems + sleep(1) From 5a73fc9183d0a5562f000da3c32843a573fad24e Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Wed, 25 Mar 2026 16:38:07 +0900 Subject: [PATCH 14/16] Attempting actions-based report summary --- .github/workflows/testing.yaml | 10 ++++++++++ .gitignore | 4 ++++ tests/features/steps/basic.py | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 47ca0730..cd8fa16d 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -47,6 +47,7 @@ jobs: if: always() runs-on: ubuntu-latest permissions: + statuses: write contents: write pages: write steps: @@ -58,6 +59,7 @@ jobs: name: allure-output path: allure_output - name: Deploy report to GitHub Pages + id: report uses: PavanMudigonda/html-reporter-github-pages@v1.5.21 with: test_results: allure_output @@ -66,3 +68,11 @@ jobs: gh_pages: pages_reports workflow_name: ${{ github.workflow }} use_actions_summary: true + - name: Notify about generated report + uses: guibranco/github-status-action-v2@v1.1.14 + with: + authToken: ${{ secrets.GITHUB_TOKEN }} + context: PaperWM test reports + state: success + sha: ${{github.event.pull_request.head.sha || github.sha}} + target_url: ${{env.GITHUB_PAGES_WEBSITE_URL}}/${{github.run_number}}/index.html diff --git a/.gitignore b/.gitignore index d366ed98..0170565c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ package-lock.json # generated disk image for test VM nixos.qcow2 + +# generated test outputs +allure_output/ +scr-*.png diff --git a/tests/features/steps/basic.py b/tests/features/steps/basic.py index 807ee129..4a1a29bc 100644 --- a/tests/features/steps/basic.py +++ b/tests/features/steps/basic.py @@ -2,8 +2,8 @@ @when("the machine starts") def machine_boot(context): - pass # no-op: our test template starts the machine already + pass @then("the machine should reach graphics") def graphical_target(context): From 8309d78f9f3d4b012bef2ebbd1c8e16a52273911 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Sat, 4 Apr 2026 15:06:03 +0900 Subject: [PATCH 15/16] Introduce piloted Gtk app (WIP) --- .github/workflows/testing.yaml | 1 + flake.lock | 17 +++++++ flake.nix | 23 +++++++--- tests/features/basic.feature | 1 + tests/features/environment.py | 25 +++++++++++ tests/features/lib/application.py | 50 +++++++++++++++++++++ tests/features/steps/visual.py | 23 ++++++++++ tests/report.nix | 4 +- tests/screenshots/basic.png | Bin 58707 -> 75120 bytes vm.nix | 71 +++++++++++++++++++++++++----- 10 files changed, 195 insertions(+), 20 deletions(-) create mode 100644 tests/features/lib/application.py diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index cd8fa16d..783ed934 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -73,6 +73,7 @@ jobs: with: authToken: ${{ secrets.GITHUB_TOKEN }} context: PaperWM test reports + description: Click here to open test reports state: success sha: ${{github.event.pull_request.head.sha || github.sha}} target_url: ${{env.GITHUB_PAGES_WEBSITE_URL}}/${{github.run_number}}/index.html diff --git a/flake.lock b/flake.lock index 59dc9ee2..5e626cbe 100644 --- a/flake.lock +++ b/flake.lock @@ -17,6 +17,22 @@ "type": "indirect" } }, + "gtk-stream": { + "flake": false, + "locked": { + "lastModified": 1741788805, + "narHash": "sha256-HWi2qDjCsmCbFFUhYiHgZ6a7ptsVn6sUMHK4A9gBdTw=", + "ref": "refs/heads/master", + "rev": "18ed0d3fdbbf67a1323e8e5b7848bb564569fc6c", + "revCount": 134, + "type": "git", + "url": "https://git.sr.ht/~marc-coiffier/gtk-stream" + }, + "original": { + "type": "git", + "url": "https://git.sr.ht/~marc-coiffier/gtk-stream" + } + }, "nixpkgs": { "locked": { "lastModified": 1773371044, @@ -51,6 +67,7 @@ "root": { "inputs": { "flake-utils": "flake-utils", + "gtk-stream": "gtk-stream", "nixpkgs": "nixpkgs", "nixpkgs-gnome": "nixpkgs-gnome" } diff --git a/flake.nix b/flake.nix index 8916c2ff..8530dd5c 100644 --- a/flake.nix +++ b/flake.nix @@ -1,9 +1,14 @@ { description = "Tiled, scrollable window management for GNOME Shell"; - inputs."nixpkgs".url = github:NixOS/nixpkgs; - inputs."nixpkgs-gnome".url = github:NixOS/nixpkgs/wip-gnome; + inputs = + { "nixpkgs".url = "github:NixOS/nixpkgs"; + "nixpkgs-gnome".url = "github:NixOS/nixpkgs/wip-gnome"; - outputs = { self, nixpkgs, nixpkgs-gnome, flake-utils, ... }: + "gtk-stream".url = "git+https://git.sr.ht/~marc-coiffier/gtk-stream"; + "gtk-stream".flake = false; + }; + + outputs = { self, nixpkgs, nixpkgs-gnome, flake-utils, gtk-stream, ... }: let testSystem = "x86_64-linux"; pkgs-gnome = import nixpkgs-gnome { system = testSystem; }; @@ -55,10 +60,13 @@ checks = import ./tests { system = testSystem; pkgs = import nixpkgs { system = testSystem; }; - defaultConfig = { + defaultConfig = { pkgs, ... }: { imports = [ ./vm.nix ]; nixpkgs.overlays = [ - (s: super: { paperwm = self.packages.${testSystem}.default; }) + (s: super: { + paperwm = self.packages.${testSystem}.default; + gtk-stream = s.callPackage gtk-stream {}; + }) (if useGnomeStaging then gnomeOverlay else (s: super: {})) ]; @@ -72,7 +80,10 @@ ./vm.nix { nixpkgs.overlays = [ # Introduce PaperWM into our extensions - (s: super: { paperwm = self.packages.${testSystem}.default; }) + (s: super: { + paperwm = self.packages.${testSystem}.default; + gtk-stream = s.callPackage gtk-stream {}; + }) # Pull GNOME-specific packages from GNOME staging (if useGnomeStaging then gnomeOverlay else (s: super: {})) diff --git a/tests/features/basic.feature b/tests/features/basic.feature index 82c1ad01..856117e2 100644 --- a/tests/features/basic.feature +++ b/tests/features/basic.feature @@ -9,5 +9,6 @@ Feature: The test machine starts @fixture.shell Scenario: Three finger swipe (stub) + Given a Wayland window with ID "hello" When the user performs three-finger-swipe Then the screen should match basic diff --git a/tests/features/environment.py b/tests/features/environment.py index 5707b0ce..f2540b2b 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -2,6 +2,8 @@ from pathlib import Path from behave import fixture, use_fixture +from lib.application import GTKApplication, GTKWidgetBuilder + import allure import cv2 @@ -16,6 +18,7 @@ def __init__(self, context): self._context = context self._last_scr_line = -1 self._last_scr_id = 0 + self._active_apps = {} def _gjs_cmdline(self, code): SHELL_DBUS = "org.gnome.Shell" @@ -63,6 +66,28 @@ def screenshot(self): allure.attach(imfile.read(), name=filename, attachment_type=allure.attachment_type.PNG) return cv2.imread(filename) + def create_app(self, id, use_x11 = False, scratch = False): + ''' Create a new remote-controllable Gtk application + ''' + self._active_apps[id] = GTKApplication(self, id, use_x11, scratch) + return self._active_apps[id] + + def get_app(self, id): + ''' Retrieve an application created using create_app + ''' + return self._active_apps[id] + + def close_app(self, id): + ''' Close an application created using create_app + ''' + self._active_apps[id].exit() + del self._active_apps[id] + + def create_widget(self, widget, id, children = None, **kwargs): + ''' Create a new composable widget object for a Gtk application + ''' + return GTKWidgetBuilder(widget, id, children, **kwargs) + @fixture def shell(context): ''' Wait for PaperWM to start diff --git a/tests/features/lib/application.py b/tests/features/lib/application.py new file mode 100644 index 00000000..67efb5d9 --- /dev/null +++ b/tests/features/lib/application.py @@ -0,0 +1,50 @@ +class GTKWidgetBuilder: + """ A Gtk widget node in the gtk-stream format that can accept children. + """ + + def __init__(self, widget, id, children = None, **kwargs): + kw_merged = " ".join(f'{k}="{v}"' for k, v in kwargs.items()) + self._kind = widget + self._output = f'<{widget} id="{id}" {kw_merged}>\n' + self._finished = False + if children is not None: + for child in children: + self.add(child) + + + def add(self, child): + self._output += child.finish() + + def finish(self): + self._output += f"\n" + self._finished = True + return self._output + +class GTKApplication: + """ A remote-controlled Gtk application using gtk-stream. + """ + + def __init__(self, nixos, id, use_x11 = False, scratch = False): + self._id = id + self._nixos = nixos + self._kind = "x11" if use_x11 else "wayland" + self._fqid = f'com.github.paperwm.{"scratch_app" if scratch else "app"}_{id}' + nixos.machine.succeed(f""" + sudo -u user DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus systemctl --user start gtk-stream-{self._kind}@{self._id}.service + """) + self._send(f'') + + def _send(self, data): + self._nixos.machine.succeed(f"cat > /tmp/app_{self._id} <') + + def exit(self): + self._send(f'') + self._nixos.machine.succeed(f""" + sudo -u user DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus systemctl --user stop gtk-stream-{self._kind}@{self._id}.service + """) diff --git a/tests/features/steps/visual.py b/tests/features/steps/visual.py index 0ed4eded..63bdf71c 100644 --- a/tests/features/steps/visual.py +++ b/tests/features/steps/visual.py @@ -4,6 +4,29 @@ import cv2 import numpy as np +@given("a {kind} window with ID \"{id}\"") +def gtk_stream_spawn_wayland(context, kind, id): + use_x11 = False + scratch = False + if "Wayland" in kind: + use_x11 = False + elif "X11" in kind: + use_x11 = True + + if "scratch" in kind: + scratch = True + elif "tiled" in kind: + scratch = False + + app = context.nixos.create_app(id, use_x11, scratch) + win = context.nixos.create_widget("window", "win1", [ + context.nixos.create_widget("button", "btn1", [ + context.nixos.create_widget("label", "lbl1", text="Hello!") + ]) + ]) + app.add(win) + + @then("the screen should match {image}") def scrcompare_simple(context, image): screen = context.nixos.screenshot() diff --git a/tests/report.nix b/tests/report.nix index 89b3d866..7ccc709e 100644 --- a/tests/report.nix +++ b/tests/report.nix @@ -1,11 +1,11 @@ -{ pkgs, lib, stdenv, allure +{ pkgs, lib, stdenv, allure, emptyDirectory # A NixOS Behave test (with a .driver output) to run , test , ...}: stdenv.mkDerivation { name = "${test.name}-report"; - src = pkgs.emptyDirectory; + src = emptyDirectory; nativeBuildInputs = [ allure diff --git a/tests/screenshots/basic.png b/tests/screenshots/basic.png index 6d1567c471c979fded12ffdfd88cc3304b99ab08..4c73398cd525425dac874f9c045a8011cd90d62e 100644 GIT binary patch literal 75120 zcmb5WbySpJ7%n=1pr{Cl(j_P%0@4kl11Kr2w9-g-&L9d5QX(MIN_Te+h?I0UgQRrV zz%XZzzkB|;>z;MbIp1R8ESUMez4u$s^Sm#Hyi`>nxlVf>0)ddccn;NoKnTH00_JP@ z;GYBZs{#mw8S(-utL2%rIqP9^XLO2a_oV0Rp}aT#{TQ;RPnmxxc#|-*eERfVchj(T zz0s&NUAK5V=+3m9bp7`LW@hHblaG{7Nr*FoKd1C=TdexRmCFh^6MHS*?O#Y2p)A}_ zdL#rAH>G|0lHN4lW@H6V1(*M^YKaHlf3G1`{*ashy=1`0fBfGo*K60B|9drXj~PPn z@8y%=|K%HC!`k*n{@ebJN;0GQQG~_T(C@;sZ=j9@o^&dqUTR5nryJ?*&5R$ zy=b@00T%A!QzRT=kc4RtwsW|SHzCGxXWvUrIZ@i}xru*dRPbHO*uvLv$HCQ&$|=3X zQH!*zSm8G|`^{~sg{acin8tViR_{m~v=)aTB1PD2M`axxJD=OE33yy=HCBl{0M9-5 zYwMPlW*my7=wQ1^Gw^Q8(1GgC*M!-u;>h4mFE1~*r^xN0+YY=UvSfS8IX$^ z&0(e#i9KhFmYDb(84sA64w_>^2+CZFRK8u-RV+0Up3L%_@BT@r+V-*i5wdZ7a5RHF zl47CdUkTj5uDuaj{XyS>k>A2hlAIf}A9+CKVp}z5$&`9L;76hF`|9QQe%2GUg(P@| zSs_WDO>8z}{QCBG*;1>*YGaLUcf{f`&sE5G)&A`t8!%WPLNH+}k*(p?Yi-k(cJqMU zU#-zs*`Rha-nMPUK4Fq&K4zUWVx~Usq=f}}lVyvi>y=ks)1E`Qnqaa#(L$cPCtMyy zui-f@Ki?Be?bP`}EbDXJ6VD+L;cMvL)qZc!8bz6i=j+jA zD8I`@6uG)V>b3X*$Da}H>F@1T8BbBwEBx)Q;_7S^_O!GDFjwq(>M8Wj8Mh`8vU*;c zY5{k+%jf6%hA>0nH#Ko$w+bT%0AH9qdWO2QSc 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 Y;O~jsOSvf;4^Neqxvg0h)C}`~0OQzDCjbBd literal 58707 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
e#~El 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 diff --git a/vm.nix b/vm.nix index 6149c86e..ee6012a6 100644 --- a/vm.nix +++ b/vm.nix @@ -1,10 +1,18 @@ { pkgs, config, lib, ... }: { - ### Make PaperWM available in system environment +options = { + +}; + +config = { + ### Make PaperWM and test tools available in system environment environment.systemPackages = with pkgs; [ paperwm + gtk-stream (lib.getBin libinput) + + gnomeExtensions.no-overview ]; ### Set graphical session to auto-login GNOME @@ -20,16 +28,42 @@ debug = true; }; - ### Enable unsafe mode by default - systemd.user.services."org.gnome.Shell@wayland" = { - overrideStrategy = "asDropin"; - serviceConfig = { - ExecStart = ["" "${pkgs.gnome-shell}/bin/gnome-shell --unsafe-mode"]; - Environment = [ - "GJS_COVERAGE_OUTPUT=/home/coverage" - #"GJS_COVERAGE_PREFIXES=${./.}" - ]; + ### Allow FIFOs to poke through cgroups, required for testing + boot.kernel.sysctl = { + "fs.protected_fifos" = 0; + }; + + systemd.user.services = let + mkGtkStream = backend: { + path = with pkgs; [ gtk-stream coreutils ]; + serviceConfig = { + ExecStartPre = [ + "${pkgs.coreutils}/bin/mkfifo /tmp/app_%i" + ]; + ExecStart = ["/bin/sh -c 'gtk-stream < /tmp/app_%i > /tmp/app_%i'"]; + Environment = [ + "GDK_BACKEND=wayland" + ]; + ExecStop = ["${pkgs.coreutils}/bin/rm /tmp/app_%i"]; + }; + environment."GTK_BACKEND" = backend; }; + in { + ### Enable unsafe mode by default + "org.gnome.Shell@wayland" = { + overrideStrategy = "asDropin"; + serviceConfig = { + ExecStart = ["" "${pkgs.gnome-shell}/bin/gnome-shell --unsafe-mode"]; + Environment = [ + "GJS_COVERAGE_OUTPUT=/home/coverage" + #"GJS_COVERAGE_PREFIXES=${./.}" + ]; + }; + }; + + ### Let systemd manage the gtk-stream lifecycle + "gtk-stream-wayland@" = mkGtkStream "wayland"; + "gtk-stream-x11@" = mkGtkStream "x11"; }; ### Set dconf to enable PaperWM out of the box @@ -38,11 +72,23 @@ profiles."user".databases = [ { settings = { "org/gnome/shell" = - { enabled-extensions = [ "paperwm@paperwm.github.com" ]; + { enabled-extensions = + [ "paperwm@paperwm.github.com" + "no-overview@fthx" + ]; disable-user-extensions = false; }; + "org/gnome/shell/extensions/paperwm" = + { winprops = + [ (builtins.toJSON { + wm_class = "/^com.github.paperwm.scratch_app/i"; + scratch_layer = true; + }) + ]; + + #NOTE: You can add more dconf settings to test with here! + }; }; - #NOTE: You can add more dconf settings to test with here! } ]; }; @@ -71,4 +117,5 @@ virtualisation.qemu.options = [ "-vga virtio" ]; +}; } From f505fb104c89a4138c91acc6abfc183150ff4096 Mon Sep 17 00:00:00 2001 From: TheSola10 Date: Sun, 19 Apr 2026 19:13:42 +0900 Subject: [PATCH 16/16] Add typing and options --- tests/features/environment.py | 8 +++--- tests/features/lib/application.py | 25 ++++++++++++++++--- tests/features/steps/visual.py | 15 ++++++++--- vm.nix | 41 +++++++++++++++++++++++++------ 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/tests/features/environment.py b/tests/features/environment.py index f2540b2b..a9f97aff 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -34,7 +34,7 @@ def libinput_play(self, recording): recordFile = self._base_dir / "recordings" / recording self.machine.succeed("libinput replay --once --replay-after 0 %s" %recordFile) - def gjs_eval(self, code): + def gjs_eval(self, code) -> str: ''' Execute the specified GJS code from within the GNOME Shell process. Will raise Exception in the event of a GJS error. ''' @@ -66,13 +66,13 @@ def screenshot(self): allure.attach(imfile.read(), name=filename, attachment_type=allure.attachment_type.PNG) return cv2.imread(filename) - def create_app(self, id, use_x11 = False, scratch = False): + def create_app(self, id, use_x11 = False, scratch = False) -> GTKApplication: ''' Create a new remote-controllable Gtk application ''' self._active_apps[id] = GTKApplication(self, id, use_x11, scratch) return self._active_apps[id] - def get_app(self, id): + def get_app(self, id) -> GTKApplication: ''' Retrieve an application created using create_app ''' return self._active_apps[id] @@ -83,7 +83,7 @@ def close_app(self, id): self._active_apps[id].exit() del self._active_apps[id] - def create_widget(self, widget, id, children = None, **kwargs): + def create_widget(self, widget, id, children = None, **kwargs) -> GTKWidgetBuilder: ''' Create a new composable widget object for a Gtk application ''' return GTKWidgetBuilder(widget, id, children, **kwargs) diff --git a/tests/features/lib/application.py b/tests/features/lib/application.py index 67efb5d9..f1f5faf0 100644 --- a/tests/features/lib/application.py +++ b/tests/features/lib/application.py @@ -13,9 +13,13 @@ def __init__(self, widget, id, children = None, **kwargs): def add(self, child): + ''' Add a new widget as a child of this widget. + ''' self._output += child.finish() - def finish(self): + def finish(self) -> str: + ''' Finish this widget and return its XML value. + ''' self._output += f"\n" self._finished = True return self._output @@ -37,13 +41,28 @@ def __init__(self, nixos, id, use_x11 = False, scratch = False): def _send(self, data): self._nixos.machine.succeed(f"cat > /tmp/app_{self._id} < str: + ''' Wait for and read a single event. + ''' + return self._nixos.machine.succeed(f"head -n 1 /tmp/app_{self._id}", timeout=timeout) + + def add(self, child: GTKWidgetBuilder or str): + ''' Add a new widget to the current application. The top-level widget + is usually a window. + ''' + if type(child) is GTKWidgetBuilder: + self._send(child.finish()) + else: + self._send(child) def close_window(self, winid): + ''' Close a window of the given ID. + ''' self._send(f'') def exit(self): + ''' Cleanly exit this application. The instance will be unusable afterwards. + ''' self._send(f'') self._nixos.machine.succeed(f""" sudo -u user DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus systemctl --user stop gtk-stream-{self._kind}@{self._id}.service diff --git a/tests/features/steps/visual.py b/tests/features/steps/visual.py index 63bdf71c..ac067b7a 100644 --- a/tests/features/steps/visual.py +++ b/tests/features/steps/visual.py @@ -4,8 +4,7 @@ import cv2 import numpy as np -@given("a {kind} window with ID \"{id}\"") -def gtk_stream_spawn_wayland(context, kind, id): +def gtk_stream_spawn(context, kind, id, child): use_x11 = False scratch = False if "Wayland" in kind: @@ -19,13 +18,23 @@ def gtk_stream_spawn_wayland(context, kind, id): scratch = False app = context.nixos.create_app(id, use_x11, scratch) + app.add(child) + +@given("a {kind} window with ID \"{id}\"") +@given("an {kind} window with ID \"{id}\"") +def gtk_stream_spawn_default(context, kind, id): win = context.nixos.create_widget("window", "win1", [ context.nixos.create_widget("button", "btn1", [ context.nixos.create_widget("label", "lbl1", text="Hello!") ]) ]) - app.add(win) + gtk_stream_spawn(context, kind, id, win) +@given("a {kind} window from {template} with ID \"{id}\"") +@given("an {kind} window from {template} with ID \"{id}\"") +def gtk_stream_spawn_file(context, kind, template, id): + with open(Path(context.config.base_dir).parent.resolve() / "windows" / f"{template}.xml") as wintemp: + gtk_stream_spawn(context, kind, id, "\n".join(wintemp.readlines())) @then("the screen should match {image}") def scrcompare_simple(context, image): diff --git a/vm.nix b/vm.nix index ee6012a6..ca2db500 100644 --- a/vm.nix +++ b/vm.nix @@ -1,8 +1,35 @@ { pkgs, config, lib, ... }: +let + cfg = config.testing; +in { -options = { +options.testing = with lib; { + ### Shorthand options to configure the VM for different test scenarios + extraExtensions = mkOption { + type = types.listOf (types.package); + default = []; + description = "Additional GNOME extensions to install"; + }; + + extraWinprops = mkOption { + type = types.listOf (types.attrs); + default = []; + description = "Additional PaperWM winprops to load"; + }; + + extraConfig = mkOption { + type = types.attrs; + default = {}; + description = "Additional PaperWM configuration"; + }; + + useCoverage = mkOption { + type = types.bool; + default = false; + description = "Generate coverage data for this run"; + }; }; config = { @@ -13,7 +40,7 @@ config = { (lib.getBin libinput) gnomeExtensions.no-overview - ]; + ] ++ cfg.extraExtensions; ### Set graphical session to auto-login GNOME services.displayManager = { @@ -54,9 +81,9 @@ config = { overrideStrategy = "asDropin"; serviceConfig = { ExecStart = ["" "${pkgs.gnome-shell}/bin/gnome-shell --unsafe-mode"]; - Environment = [ + Environment = lib.mkIf cfg.useCoverage [ "GJS_COVERAGE_OUTPUT=/home/coverage" - #"GJS_COVERAGE_PREFIXES=${./.}" + "GJS_COVERAGE_PREFIXES=${./.}" ]; }; }; @@ -75,7 +102,7 @@ config = { { enabled-extensions = [ "paperwm@paperwm.github.com" "no-overview@fthx" - ]; + ] ++ map (ex: ex.extensionUuid) cfg.extraExtensions; disable-user-extensions = false; }; "org/gnome/shell/extensions/paperwm" = @@ -84,10 +111,10 @@ config = { wm_class = "/^com.github.paperwm.scratch_app/i"; scratch_layer = true; }) - ]; + ] ++ map builtins.toJSON cfg.extraWinprops; #NOTE: You can add more dconf settings to test with here! - }; + } // cfg.extraConfig; }; } ];