feat: extend Files app marquee selection and highlight to list view

This commit is contained in:
2026-06-04 07:47:42 +02:00
parent 0f16785c9f
commit 87433f3b7f
3 changed files with 85 additions and 43 deletions
@@ -153,6 +153,7 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
if (clicked_idx >= 0 && clicked_idx < fm->entry_count) {
uint64_t now = montauk::get_milliseconds();
filemanager_clear_multi_selection(fm);
// Double-click detection
if (fm->last_click_item == clicked_idx &&
@@ -166,15 +167,24 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
fm->last_click_time = now;
}
} else {
// Background click in list area: start marquee drag
fm->selected = -1;
filemanager_clear_multi_selection(fm);
fm->marquee_active = true;
fm->marquee_start_x = local_x;
fm->marquee_start_y = rel_y;
fm->marquee_cur_x = local_x;
fm->marquee_cur_y = rel_y;
}
}
}
}
// ---- Marquee drag in grid view ----
// ---- Marquee drag (grid or list view) ----
if (fm->marquee_active) {
int list_y = FM_TOOLBAR_H + FM_PATHBAR_H;
int list_y = fm->grid_view
? FM_TOOLBAR_H + FM_PATHBAR_H
: FM_TOOLBAR_H + FM_PATHBAR_H + FM_HEADER_H;
int rel_y = local_y - list_y + fm->scrollbar.scroll_offset;
int clamp_x = local_x;
if (clamp_x < 0) clamp_x = 0;
@@ -187,31 +197,43 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
fm->marquee_cur_y = rel_y;
}
// Recompute hit-set every frame so icons highlight live during the drag.
int cols = (cw - FM_SCROLLBAR_W) / FM_GRID_CELL_W;
if (cols < 1) cols = 1;
int rx0 = fm->marquee_start_x < fm->marquee_cur_x ? fm->marquee_start_x : fm->marquee_cur_x;
int ry0 = fm->marquee_start_y < fm->marquee_cur_y ? fm->marquee_start_y : fm->marquee_cur_y;
int rx1 = fm->marquee_start_x > fm->marquee_cur_x ? fm->marquee_start_x : fm->marquee_cur_x;
int ry1 = fm->marquee_start_y > fm->marquee_cur_y ? fm->marquee_start_y : fm->marquee_cur_y;
// Recompute hit-set every frame so entries highlight live during the drag.
filemanager_clear_multi_selection(fm);
int limit = fm->entry_count < 64 ? fm->entry_count : 64;
for (int i = 0; i < limit; i++) {
int col = i % cols;
int row = i / cols;
int cell_x = col * FM_GRID_CELL_W;
int cell_y = filemanager_grid_row_y(fm, row, cols);
int cell_h = filemanager_grid_row_height(fm, row, cols);
int cx1 = cell_x + FM_GRID_CELL_W;
int cy1 = cell_y + cell_h;
if (fm->grid_view) {
int cols = (cw - FM_SCROLLBAR_W) / FM_GRID_CELL_W;
if (cols < 1) cols = 1;
for (int i = 0; i < limit; i++) {
int col = i % cols;
int row = i / cols;
int cell_x = col * FM_GRID_CELL_W;
int cell_y = filemanager_grid_row_y(fm, row, cols);
int cell_h = filemanager_grid_row_height(fm, row, cols);
int cx1 = cell_x + FM_GRID_CELL_W;
int cy1 = cell_y + cell_h;
if (rx1 < cell_x || rx0 >= cx1) continue;
if (ry1 < cell_y || ry0 >= cy1) continue;
if (rx1 < cell_x || rx0 >= cx1) continue;
if (ry1 < cell_y || ry0 >= cy1) continue;
fm->multi_selected[i] = true;
fm->multi_count++;
fm->multi_selected[i] = true;
fm->multi_count++;
}
} else {
// List rows span the full width, so select any row whose vertical
// extent overlaps the marquee box.
for (int i = 0; i < limit; i++) {
int cell_y = i * FM_ITEM_H;
int cy1 = cell_y + FM_ITEM_H;
if (ry1 < cell_y || ry0 >= cy1) continue;
fm->multi_selected[i] = true;
fm->multi_count++;
}
}
fm->selected = -1;
@@ -262,7 +284,15 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
int idx = rel_y / FM_ITEM_H;
if (idx >= 0 && idx < fm->entry_count) {
target_idx = idx;
fm->selected = idx;
// Preserve multi-selection if right-clicking inside it,
// otherwise replace it with a single selection.
if (!(fm->multi_count > 0 && fm->multi_selected[idx])) {
filemanager_clear_multi_selection(fm);
fm->selected = idx;
}
} else {
filemanager_clear_multi_selection(fm);
fm->selected = -1;
}
}
}