From cba722f8a207982ade9e941eca3e6070e8705749 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sat, 20 Jun 2026 13:01:49 +0800
Subject: [PATCH] Commit single-window app shortcuts on first key
---
C3.tools/round1-window-index-progressive-filter-fixture-qa.sh | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 159 insertions(+), 1 deletions(-)
diff --git a/C3.tools/round1-window-index-progressive-filter-fixture-qa.sh b/C3.tools/round1-window-index-progressive-filter-fixture-qa.sh
index 3e1a74c..af1a9f4 100755
--- a/C3.tools/round1-window-index-progressive-filter-fixture-qa.sh
+++ b/C3.tools/round1-window-index-progressive-filter-fixture-qa.sh
@@ -27,6 +27,7 @@
REPORT_HORIZONTAL_DARK="$BUILD_REPORT_ROOT/round01-window-index-progressive-filter-horizontal-dark-report.json"
REPORT_COMMIT="$BUILD_REPORT_ROOT/round01-window-index-progressive-filter-commit-report.json"
REPORT_INVALID="$BUILD_REPORT_ROOT/round01-window-index-progressive-filter-invalid-report.json"
+REPORT_SINGLE_WINDOW="$BUILD_REPORT_ROOT/round01-window-index-progressive-filter-single-window-report.json"
SUMMARY_DIR="$BUILD_TMP_ROOT/round01-window-index-progressive-filter-fixture-qa"
APP_PID=""
@@ -140,11 +141,16 @@
echo "app:$APP_SYMBOL,windowInvalid:${APP_SYMBOL}Z"
}
+single_window_expected_sequence() {
+ echo "app:$APP_SYMBOL,windowSingle:$APP_SYMBOL"
+}
+
run_fixture() {
local report="$1"
local theme="$2"
local mode="$3"
local key_sequence="$4"
+ local windows_per_app="${5:-$FIXTURE_WINDOWS_PER_APP}"
stop_current_aligner
set_theme "$theme"
@@ -154,7 +160,7 @@
--round0-skip-permissions \
--round01-open-quick-switch \
--round01-fixture-app-count="$FIXTURE_APP_COUNT" \
- --round01-fixture-windows-per-app="$FIXTURE_WINDOWS_PER_APP" \
+ --round01-fixture-windows-per-app="$windows_per_app" \
--round01-disable-screenshot-refresh \
--round01-waterfall-view-mode="$mode" \
--round01-debug-key-sequence="$key_sequence" \
@@ -306,6 +312,51 @@
if last_report is not None:
print(json.dumps(last_report, indent=2, ensure_ascii=False), file=sys.stderr)
print(f"invalid report did not reach invalid state within {timeout:.1f}s", file=sys.stderr)
+sys.exit(1)
+PY
+}
+
+wait_for_single_window_report() {
+ local report="$1"
+ local expected_mode="$2"
+ local expected_sequence="$3"
+
+ /usr/bin/python3 - "$report" "$REPORT_WAIT" "$expected_mode" "$expected_sequence" "$APP_SYMBOL" <<'PY'
+import json
+import sys
+import time
+
+path = sys.argv[1]
+timeout = float(sys.argv[2])
+expected_mode = sys.argv[3]
+expected_sequence = [part for part in sys.argv[4].split(",") if part]
+app_symbol = sys.argv[5]
+deadline = time.monotonic() + timeout
+last_report = None
+
+while time.monotonic() < deadline:
+ try:
+ with open(path, "r", encoding="utf-8") as file:
+ report = json.load(file)
+ last_report = report
+ root = report.get("rootView", {})
+ if (
+ report.get("snapshotLoaded") is True
+ and root.get("waterfallViewMode") == expected_mode
+ and root.get("keyboardCommandsApplied") == expected_sequence
+ and root.get("lastWindowIndexKeyCommand") == f"windowSingle:{app_symbol}"
+ and root.get("lastCommitSource") == "keyboard"
+ ):
+ sys.exit(0)
+ except FileNotFoundError:
+ pass
+ except json.JSONDecodeError:
+ pass
+ time.sleep(0.2)
+
+if last_report is not None:
+ print(json.dumps(last_report, indent=2, ensure_ascii=False), file=sys.stderr)
+print(f"single-window report did not reach direct commit within {timeout:.1f}s", file=sys.stderr)
sys.exit(1)
PY
}
@@ -689,6 +740,108 @@
SUMMARY_FILES+=("$summary_file")
}
+assert_single_window_report() {
+ local report="$1"
+ local case_name="single-window-first-key-commit-horizontal"
+ local summary_file="$SUMMARY_DIR/$case_name.json"
+
+ /usr/bin/python3 - \
+ "$report" \
+ "$case_name" \
+ "horizontalMasonry" \
+ "$(single_window_expected_sequence)" \
+ "$FIXTURE_APP_COUNT" \
+ "$TARGET_APP_INDEX" \
+ "$APP_SYMBOL" \
+ "$summary_file" <<'PY'
+import json
+import numbers
+import sys
+
+path = sys.argv[1]
+case_name = sys.argv[2]
+expected_mode = sys.argv[3]
+expected_sequence = [part for part in sys.argv[4].split(",") if part]
+fixture_app_count = int(sys.argv[5])
+target_app_index = int(sys.argv[6])
+app_symbol = sys.argv[7]
+summary_file = sys.argv[8]
+
+with open(path, "r", encoding="utf-8") as file:
+ report = json.load(file)
+
+def require(condition, message):
+ if not condition:
+ print(f"{case_name}: {message}", file=sys.stderr)
+ print(json.dumps(report, indent=2, ensure_ascii=False), file=sys.stderr)
+ sys.exit(1)
+
+def is_number(value):
+ return isinstance(value, numbers.Real) and not isinstance(value, bool)
+
+root = report.get("rootView", {})
+columns = root.get("waterfallColumns", [])
+cards = [card for column in columns for card in column.get("cards", [])]
+target_column = next((column for column in columns if column.get("appGroupIndex") == target_app_index), None)
+
+require(report.get("snapshotLoaded") is True, "snapshotLoaded must be true")
+require(report.get("appCount") == fixture_app_count, "fixture appCount must match")
+require(report.get("windowCount") == fixture_app_count, "single-window fixture must have one window per App")
+require(root.get("waterfallViewMode") == expected_mode, "single-window run must use horizontal Waterfall")
+require(root.get("keyboardCommandsApplied") == expected_sequence, "single-window key sequence must direct-commit")
+require(root.get("appShelfIndexKeyDownCount") == 1, "single-window direct commit must use one physical keyDown")
+require(root.get("lastAppShelfIndexKeySymbol") == app_symbol, "last physical symbol must be the App key")
+require(root.get("lastWindowIndexKeyCommand") == f"windowSingle:{app_symbol}", "single-window direct command must be reported")
+require(root.get("lastWindowIndexKeyCommitCode") == app_symbol, "single-window commit code must be the one-key shortcut")
+require(root.get("lastCommitSource") == "keyboard", "single-window direct commit must be keyboard sourced")
+require(root.get("windowIndexKeyPendingAppGroupIndex") is None, "single-window direct commit must not leave pending App group")
+require(root.get("windowIndexKeyPendingAppSymbol") is None, "single-window direct commit must not leave pending App symbol")
+require(root.get("windowShortcutFilterActive") is False, "single-window direct commit must not enter progressive filter")
+require(root.get("windowShortcutFilterPhase") == "none", "single-window direct commit must keep filter phase none")
+require(root.get("windowShortcutFilterMatchedCount") == 0, "single-window direct commit must not leave matched filter count")
+require(root.get("windowShortcutFilterDimmedCount") == 0, "single-window direct commit must not leave dimmed filter count")
+require(root.get("lastWindowShortcutPreCommitFilterSnapshot") is None, "single-window direct commit must not expose two-key pre-commit snapshot")
+
+require(target_column is not None, "target App column must exist")
+target_cards = target_column.get("cards", [])
+require(len(target_cards) == 1, "target App must have exactly one visible window")
+target_card = target_cards[0]
+target_window_id = int(target_card.get("windowID"))
+require(root.get("lastCommittedAppGroupIndex") == target_app_index, "direct commit must target expected App")
+require(root.get("lastCommittedWindowIndex") == 0, "direct commit must target the only window")
+require(root.get("lastCommittedWindowID") == target_window_id, "direct commit must target expected window ID")
+require(root.get("selectedAppGroupIndex") == target_app_index, "selection must land on target App")
+require(root.get("selectedWindowIndex") == 0, "selection must land on the only window")
+require(root.get("selectedWindowID") == target_window_id, "selectedWindowID must match target window")
+
+for card in cards:
+ opacity = card.get("windowShortcutFilterOpacity")
+ states = card.get("visualStates", [])
+ require(card.get("windowShortcutFilterState") == "none", "single-window direct commit must not leave card filter state")
+ require(is_number(opacity), "cards must expose numeric filter opacity")
+ require(float(opacity) >= 0.99, "single-window direct commit must not dim cards")
+ require("shortcutDimmed" not in states, "single-window direct commit must not leave shortcutDimmed state")
+ require("shortcutMatched" not in states, "single-window direct commit must not leave shortcutMatched state")
+ require("shortcutTarget" not in states, "single-window direct commit must not leave shortcutTarget state")
+
+summary = {
+ "case": case_name,
+ "status": "passed",
+ "mode": root.get("waterfallViewMode"),
+ "report": path,
+ "commands": root.get("keyboardCommandsApplied"),
+ "targetWindowID": target_window_id,
+ "lastCommitSource": root.get("lastCommitSource"),
+ "lastWindowIndexKeyCommitCode": root.get("lastWindowIndexKeyCommitCode"),
+ "cardCount": len(cards)
+}
+with open(summary_file, "w", encoding="utf-8") as file:
+ json.dump(summary, file, indent=2, ensure_ascii=False)
+PY
+
+ SUMMARY_FILES+=("$summary_file")
+}
+
assert_pending_summaries_consistent() {
local baseline="$1"
local candidate="$2"
@@ -775,6 +928,11 @@
trap cleanup EXIT
stop_current_aligner
+run_fixture "$REPORT_SINGLE_WINDOW" "light" "horizontal" "$(pending_key_sequence)" 1
+wait_for_single_window_report "$REPORT_SINGLE_WINDOW" "$(mode_report_value horizontal)" "$(single_window_expected_sequence)"
+assert_single_window_report "$REPORT_SINGLE_WINDOW"
+finish_case
+
run_fixture "$REPORT_HORIZONTAL_LIGHT" "light" "horizontal" "$(pending_key_sequence)"
wait_for_pending_report "$REPORT_HORIZONTAL_LIGHT" "$(mode_report_value horizontal)" "$(pending_expected_sequence)" "pending-horizontal-light"
assert_pending_report "$REPORT_HORIZONTAL_LIGHT" "pending-horizontal-light" "light" "$(mode_report_value horizontal)"
--
Gitblit v1.9.3