Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 56 additions & 33 deletions sensors/sensors.vala
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ class SensorsIndicator : Gtk.Box {
// Sensor counts vary by two orders of magnitude across platforms, so
// the detail list is capped rather than unbounded.
private const int MAX_ROWS_PER_GROUP = 6;
// Gdk.Monitor geometry is expressed in logical pixels. Two 340px
// columns plus the popover margins fit comfortably from 1280px up;
// below that, keeping one column avoids a popover that dominates the
// Column count is derived from BOTH logical Gdk.Monitor geometry and
// the monitor's scale factor (see configure_detail_layout()), so a
// scaled HiDPI panel can use more columns than a same-logical-width
// native display; capped at 3 so the popover never dominates a huge
// display.
private const int TWO_COLUMN_MIN_WIDTH = 1280;
private const int MAX_DETAIL_COLUMNS = 3;
private const int DETAIL_COLUMN_WIDTH = 340;
private const int DETAIL_COLUMN_SPACING = 18;
private const int DETAIL_SCREEN_MARGIN = 96;
Expand All @@ -64,13 +65,11 @@ class SensorsIndicator : Gtk.Box {
private Box detail_box;
private Box detail_toggle_box;
private Box detail_columns_box;
private Box detail_left;
private Box detail_right;
private Box[] detail_columns;
private Box detail_target;
private ScrolledWindow detail_scroller;
private bool use_two_columns = false;
private int left_row_count = 0;
private int right_row_count = 0;
private int detail_column_count = 1;
private int[] detail_column_rows;
private static Gtk.CssProvider? compact_rows_provider = null;
private SensorMonitor monitor;
private bool show_frequency = true;
Expand Down Expand Up @@ -145,15 +144,17 @@ class SensorsIndicator : Gtk.Box {
detail_columns_box = new Box(Orientation.HORIZONTAL,
DETAIL_COLUMN_SPACING);
detail_columns_box.homogeneous = true;
detail_left = new Box(Orientation.VERTICAL, 8);
detail_right = new Box(Orientation.VERTICAL, 8);
detail_left.hexpand = true;
detail_right.hexpand = true;
detail_columns_box.append(detail_left);
detail_columns_box.append(detail_right);
detail_columns = new Box[MAX_DETAIL_COLUMNS];
detail_column_rows = new int[MAX_DETAIL_COLUMNS];
for (int i = 0; i < MAX_DETAIL_COLUMNS; i++) {
detail_columns[i] = new Box(Orientation.VERTICAL, 8);
detail_columns[i].hexpand = true;
detail_columns[i].visible = i == 0;
detail_columns_box.append(detail_columns[i]);
}
detail_box.append(detail_toggle_box);
detail_box.append(detail_columns_box);
detail_target = detail_left;
detail_target = detail_columns[0];

Popover popover = new Popover();
// Natural size is the ordinary presentation. Automatic vertical
Expand Down Expand Up @@ -331,14 +332,32 @@ class SensorsIndicator : Gtk.Box {
screen_height = geometry.height;
}

use_two_columns = screen_width >= TWO_COLUMN_MIN_WIDTH;
detail_right.visible = use_two_columns;
detail_columns_box.spacing = use_two_columns
// Base density on effective physical resolution rather than one
// logical-pixel breakpoint. A scaled HiDPI panel can therefore use
// more columns than a native low-resolution display with the same
// logical width, and a huge logical desktop on a non-scaled panel
// is capped by the logical calculation instead of over-widening.
int scale_factor = 1;
if (target_monitor != null) scale_factor = target_monitor.get_scale_factor();
int effective_width = screen_width * int.max(1, scale_factor);
int available_width = int.max(DETAIL_COLUMN_WIDTH, effective_width - DETAIL_SCREEN_MARGIN);
int density_slot = DETAIL_COLUMN_WIDTH * 2 + DETAIL_COLUMN_SPACING;
int physical_column_count = int.min(MAX_DETAIL_COLUMNS,
int.max(1, (available_width + DETAIL_COLUMN_SPACING) / density_slot));
int logical_width = int.max(DETAIL_COLUMN_WIDTH, screen_width - DETAIL_SCREEN_MARGIN);
int logical_column_count = int.max(1,
(logical_width + DETAIL_COLUMN_SPACING) / (DETAIL_COLUMN_WIDTH + DETAIL_COLUMN_SPACING));
detail_column_count = int.min(physical_column_count, logical_column_count);
detail_column_count = int.min(detail_column_count, MAX_DETAIL_COLUMNS);

for (int i = 0; i < MAX_DETAIL_COLUMNS; i++) {
detail_columns[i].visible = i < detail_column_count;
}
detail_columns_box.spacing = detail_column_count > 1
? DETAIL_COLUMN_SPACING : 0;

int content_width = use_two_columns
? DETAIL_COLUMN_WIDTH * 2 + DETAIL_COLUMN_SPACING
: DETAIL_COLUMN_WIDTH;
int content_width = DETAIL_COLUMN_WIDTH * detail_column_count
+ DETAIL_COLUMN_SPACING * (detail_column_count - 1);
detail_scroller.min_content_width = content_width;
detail_scroller.max_content_width = content_width;
detail_scroller.max_content_height = int.max(320,
Expand Down Expand Up @@ -582,6 +601,9 @@ class SensorsIndicator : Gtk.Box {

private Box begin_detail_section() {
var section = new Box(Orientation.VERTICAL, 4);
// Bordered frame so stacked resource-pool sections in the same
// column read as distinct cards, not one continuous list.
section.add_css_class("sensors-resource-section");
detail_target = section;
return section;
}
Expand All @@ -596,14 +618,15 @@ class SensorsIndicator : Gtk.Box {
rows++;
}

if (!use_two_columns || left_row_count <= right_row_count) {
detail_left.append(section);
left_row_count += rows;
} else {
detail_right.append(section);
right_row_count += rows;
int target_column = 0;
for (int i = 1; i < detail_column_count; i++) {
if (detail_column_rows[i] < detail_column_rows[target_column]) {
target_column = i;
}
}
detail_target = detail_left;
detail_columns[target_column].append(section);
detail_column_rows[target_column] += rows;
detail_target = detail_columns[0];
}

private void add_heading(string title) {
Expand Down Expand Up @@ -1115,10 +1138,10 @@ class SensorsIndicator : Gtk.Box {
/** Built only while the popover is open. */
private void rebuild_details() {
clear_box(detail_toggle_box);
clear_box(detail_left);
clear_box(detail_right);
left_row_count = 0;
right_row_count = 0;
for (int i = 0; i < MAX_DETAIL_COLUMNS; i++) {
clear_box(detail_columns[i]);
detail_column_rows[i] = 0;
}

// One control for the whole popover, at the top so its scope is
// obvious before any section renders: it decides whether every
Expand Down
Loading