feat: Enhance widget discovery with telemetry data and improve output formatting

This commit is contained in:
scawful
2025-10-02 22:50:47 -04:00
parent 21074f6445
commit c202aa9fa4
11 changed files with 457 additions and 78 deletions

View File

@@ -227,11 +227,31 @@ absl::Status HandleGuiDiscoverCommand(const std::vector<std::string>& arg_vec) {
<< (widget.visible ? "true" : "false") << ",\n";
std::cout << " \"enabled\": "
<< (widget.enabled ? "true" : "false") << ",\n";
std::cout << " \"bounds\": { \"min\": [" << widget.bounds.min_x
<< ", " << widget.bounds.min_y << "], \"max\": ["
<< widget.bounds.max_x << ", " << widget.bounds.max_y
<< "] },\n";
std::cout << " \"widgetId\": " << widget.widget_id << "\n";
if (widget.has_bounds) {
std::cout << " \"bounds\": { \"min\": ["
<< widget.bounds.min_x << ", " << widget.bounds.min_y
<< "], \"max\": [" << widget.bounds.max_x << ", "
<< widget.bounds.max_y << "] },\n";
} else {
std::cout << " \"bounds\": null,\n";
}
std::cout << " \"widgetId\": " << widget.widget_id << ",\n";
std::cout << " \"lastSeenFrame\": "
<< widget.last_seen_frame << ",\n";
std::cout << " \"lastSeenAt\": ";
if (widget.last_seen_at.has_value()) {
std::cout
<< "\""
<< JsonEscape(absl::FormatTime("%Y-%m-%dT%H:%M:%SZ",
*widget.last_seen_at,
absl::UTCTimeZone()))
<< "\"";
} else {
std::cout << "null";
}
std::cout << ",\n";
std::cout << " \"stale\": "
<< (widget.stale ? "true" : "false") << "\n";
std::cout << " }";
if (i + 1 < window.widgets.size()) {
std::cout << ",";
@@ -284,9 +304,24 @@ absl::Status HandleGuiDiscoverCommand(const std::vector<std::string>& arg_vec) {
std::cout << " Suggested: " << widget.suggested_action << "\n";
std::cout << " State: " << (widget.visible ? "visible" : "hidden")
<< ", " << (widget.enabled ? "enabled" : "disabled") << "\n";
std::cout << absl::StrFormat(" Bounds: (%.1f, %.1f) → (%.1f, %.1f)\n",
widget.bounds.min_x, widget.bounds.min_y,
widget.bounds.max_x, widget.bounds.max_y);
if (widget.has_bounds) {
std::cout << absl::StrFormat(
" Bounds: (%.1f, %.1f) → (%.1f, %.1f)\n", widget.bounds.min_x,
widget.bounds.min_y, widget.bounds.max_x, widget.bounds.max_y);
} else {
std::cout << " Bounds: (not available)\n";
}
std::cout << " Last seen: frame " << widget.last_seen_frame;
if (widget.last_seen_at.has_value()) {
std::cout << " @ "
<< absl::FormatTime("%Y-%m-%d %H:%M:%S",
*widget.last_seen_at,
absl::LocalTimeZone());
}
if (widget.stale) {
std::cout << " [STALE]";
}
std::cout << "\n";
std::cout << " Widget ID: 0x" << std::hex << widget.widget_id
<< std::dec << "\n";
}

View File

@@ -519,11 +519,19 @@ absl::StatusOr<DiscoverWidgetsResult> GuiAutomationClient::DiscoverWidgets(
widget.suggested_action = widget_proto.suggested_action();
widget.visible = widget_proto.visible();
widget.enabled = widget_proto.enabled();
widget.bounds.min_x = widget_proto.bounds().min_x();
widget.bounds.min_y = widget_proto.bounds().min_y();
widget.bounds.max_x = widget_proto.bounds().max_x();
widget.bounds.max_y = widget_proto.bounds().max_y();
widget.has_bounds = widget_proto.has_bounds();
if (widget.has_bounds) {
widget.bounds.min_x = widget_proto.bounds().min_x();
widget.bounds.min_y = widget_proto.bounds().min_y();
widget.bounds.max_x = widget_proto.bounds().max_x();
widget.bounds.max_y = widget_proto.bounds().max_y();
} else {
widget.bounds = WidgetBoundingBox();
}
widget.widget_id = widget_proto.widget_id();
widget.last_seen_frame = widget_proto.last_seen_frame();
widget.last_seen_at = OptionalTimeFromMillis(widget_proto.last_seen_at_ms());
widget.stale = widget_proto.stale();
window_info.widgets.push_back(std::move(widget));
}

View File

@@ -152,6 +152,10 @@ struct WidgetDescriptor {
bool enabled = true;
WidgetBoundingBox bounds;
uint32_t widget_id = 0;
bool has_bounds = false;
int64_t last_seen_frame = -1;
std::optional<absl::Time> last_seen_at;
bool stale = false;
};
struct DiscoveredWindowInfo {