mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-24 21:37:30 -04:00
feat: dont resize client when in overview
This commit is contained in:
parent
9e4fade55e
commit
a6a765caff
9 changed files with 446 additions and 137 deletions
298
src/layout/overview.h
Normal file
298
src/layout/overview.h
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
void overview_scale(Monitor *m) {
|
||||
int32_t target_gappo = config.overviewgappo;
|
||||
int32_t target_gappi = config.overviewgappi;
|
||||
|
||||
int orig_n = m->visible_clients;
|
||||
|
||||
if (orig_n == 0)
|
||||
return;
|
||||
|
||||
size_t sz_c_arr = orig_n * sizeof(Client *);
|
||||
size_t sz_aspects = orig_n * sizeof(float);
|
||||
size_t sz_suffix_sums = (orig_n + 1) * sizeof(float);
|
||||
size_t sz_best_items = orig_n * sizeof(int);
|
||||
size_t sz_temp_items = orig_n * sizeof(int);
|
||||
size_t sz_items = orig_n * sizeof(int);
|
||||
size_t sz_A_sum = orig_n * sizeof(float);
|
||||
|
||||
size_t total_size = sz_c_arr + sz_aspects + sz_suffix_sums + sz_best_items +
|
||||
sz_temp_items + sz_items + sz_A_sum;
|
||||
|
||||
void *buffer = malloc(total_size);
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
Client **c_arr = (Client **)buffer;
|
||||
float *aspects = (float *)((char *)buffer + sz_c_arr);
|
||||
float *suffix_sums = (float *)((char *)aspects + sz_aspects);
|
||||
int *best_items_per_row = (int *)((char *)suffix_sums + sz_suffix_sums);
|
||||
int *temp_items_per_row =
|
||||
(int *)((char *)best_items_per_row + sz_best_items);
|
||||
int *items_per_row = (int *)((char *)temp_items_per_row + sz_temp_items);
|
||||
float *A_sum = (float *)((char *)items_per_row + sz_items);
|
||||
|
||||
int actual_n = 0;
|
||||
Client *c = NULL;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
if (VISIBLEON(c, m) && !c->isunglobal && !client_is_x11_popup(c)) {
|
||||
|
||||
c_arr[actual_n] = c;
|
||||
float aspect = 1.0f;
|
||||
if (c->overview_backup_geom.height > 0 &&
|
||||
c->overview_backup_geom.width > 0) {
|
||||
aspect = (float)c->overview_backup_geom.width /
|
||||
c->overview_backup_geom.height;
|
||||
}
|
||||
if (aspect < 0.2f)
|
||||
aspect = 0.2f;
|
||||
if (aspect > 5.0f)
|
||||
aspect = 5.0f;
|
||||
|
||||
aspects[actual_n] = aspect;
|
||||
actual_n++;
|
||||
}
|
||||
}
|
||||
|
||||
int n = actual_n;
|
||||
if (n == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
suffix_sums[n] = 0.0f;
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
suffix_sums[i] = suffix_sums[i + 1] + aspects[i];
|
||||
}
|
||||
|
||||
float max_avail_w = m->w.width - 2 * target_gappo;
|
||||
float max_avail_h = m->w.height - 2 * target_gappo;
|
||||
if (max_avail_w < 10)
|
||||
max_avail_w = 10;
|
||||
if (max_avail_h < 10)
|
||||
max_avail_h = 10;
|
||||
|
||||
int best_rows = 1;
|
||||
float best_row_height = 0.0f;
|
||||
best_items_per_row[0] = n;
|
||||
|
||||
for (int R = 1; R <= n; R++) {
|
||||
int start_idx = 0;
|
||||
|
||||
for (int r = 0; r < R; r++) {
|
||||
int rows_left = R - r;
|
||||
|
||||
float S_rem = suffix_sums[start_idx];
|
||||
float target_sum = S_rem / rows_left;
|
||||
|
||||
float current_sum = 0;
|
||||
int count = 0;
|
||||
|
||||
while (start_idx + count < n - (rows_left - 1)) {
|
||||
float next_val = aspects[start_idx + count];
|
||||
if (rows_left == 1) {
|
||||
current_sum += next_val;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
float diff_without = fabs(current_sum - target_sum);
|
||||
float diff_with = fabs(current_sum + next_val - target_sum);
|
||||
if (diff_with > diff_without) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
current_sum += next_val;
|
||||
count++;
|
||||
}
|
||||
temp_items_per_row[r] = count;
|
||||
start_idx += count;
|
||||
}
|
||||
|
||||
float min_h_max_w = 999999.0f;
|
||||
start_idx = 0;
|
||||
for (int r = 0; r < R; r++) {
|
||||
float row_A_sum = suffix_sums[start_idx] -
|
||||
suffix_sums[start_idx + temp_items_per_row[r]];
|
||||
start_idx += temp_items_per_row[r];
|
||||
|
||||
float gap_x_total = (temp_items_per_row[r] - 1) * target_gappi;
|
||||
float w_avail = max_avail_w - gap_x_total;
|
||||
if (w_avail < 1)
|
||||
w_avail = 1;
|
||||
|
||||
float h_limit = w_avail / row_A_sum;
|
||||
if (h_limit < min_h_max_w) {
|
||||
min_h_max_w = h_limit;
|
||||
}
|
||||
}
|
||||
|
||||
float gap_y_total_temp = (R - 1) * target_gappi;
|
||||
float h_avail = max_avail_h - gap_y_total_temp;
|
||||
if (h_avail < 1)
|
||||
h_avail = 1;
|
||||
|
||||
float h_max_h = h_avail / R;
|
||||
float final_h = min_h_max_w < h_max_h ? min_h_max_w : h_max_h;
|
||||
|
||||
if (final_h > best_row_height) {
|
||||
best_row_height = final_h;
|
||||
best_rows = R;
|
||||
for (int r = 0; r < R; r++) {
|
||||
best_items_per_row[r] = temp_items_per_row[r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rows = best_rows;
|
||||
float row_height = best_row_height;
|
||||
|
||||
int current_render_idx = 0;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
items_per_row[r] = best_items_per_row[r];
|
||||
A_sum[r] = suffix_sums[current_render_idx] -
|
||||
suffix_sums[current_render_idx + items_per_row[r]];
|
||||
current_render_idx += items_per_row[r];
|
||||
}
|
||||
|
||||
float gap_y_total = (rows - 1) * target_gappi;
|
||||
float total_layout_height = rows * row_height + gap_y_total;
|
||||
float start_y = m->w.y + (m->w.height - total_layout_height) / 2.0f;
|
||||
|
||||
int current_idx = 0;
|
||||
float current_y = start_y;
|
||||
|
||||
for (int r = 0; r < rows; r++) {
|
||||
float row_width =
|
||||
row_height * A_sum[r] + (items_per_row[r] - 1) * target_gappi;
|
||||
float current_x = m->w.x + (m->w.width - row_width) / 2.0f;
|
||||
|
||||
for (int i = 0; i < items_per_row[r]; i++) {
|
||||
Client *client = c_arr[current_idx];
|
||||
float aspect = aspects[current_idx];
|
||||
float client_width = row_height * aspect;
|
||||
|
||||
struct wlr_box client_geom;
|
||||
client_geom.x = (int)(current_x + 0.5f);
|
||||
client_geom.y = (int)(current_y + 0.5f);
|
||||
|
||||
float next_x = current_x + client_width;
|
||||
client_geom.width = (int)(next_x + 0.5f) - client_geom.x;
|
||||
|
||||
float next_y = current_y + row_height;
|
||||
client_geom.height = (int)(next_y + 0.5f) - client_geom.y;
|
||||
|
||||
resize(client, client_geom, 0);
|
||||
|
||||
current_x = next_x + target_gappi;
|
||||
current_idx++;
|
||||
}
|
||||
current_y += row_height + target_gappi;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void overview_resize(Monitor *m) {
|
||||
int32_t i, n;
|
||||
int32_t cx, cy, cw, ch;
|
||||
int32_t dx;
|
||||
int32_t cols, rows, overcols;
|
||||
Client *c = NULL;
|
||||
|
||||
int32_t target_gappo = config.overviewgappo;
|
||||
int32_t target_gappi = config.overviewgappi;
|
||||
float single_width_ratio = 0.7;
|
||||
float single_height_ratio = 0.8;
|
||||
|
||||
n = m->visible_clients;
|
||||
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
if (n == 1) {
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
if (VISIBLEON(c, m) && !c->isunglobal && !client_is_x11_popup(c)) {
|
||||
cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
|
||||
ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
|
||||
c->geom.x = m->w.x + (m->w.width - cw) / 2;
|
||||
c->geom.y = m->w.y + (m->w.height - ch) / 2;
|
||||
c->geom.width = cw;
|
||||
c->geom.height = ch;
|
||||
resize(c, c->geom, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 2) {
|
||||
cw = (m->w.width - 2 * target_gappo - target_gappi) / 2;
|
||||
ch = (m->w.height - 2 * target_gappo) * 0.65;
|
||||
i = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
if (VISIBLEON(c, m) && !c->isunglobal && !client_is_x11_popup(c)) {
|
||||
if (i == 0) {
|
||||
c->geom.x = m->w.x + target_gappo;
|
||||
c->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||
} else if (i == 1) {
|
||||
c->geom.x = m->w.x + cw + target_gappo + target_gappi;
|
||||
c->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||
}
|
||||
c->geom.width = cw;
|
||||
c->geom.height = ch;
|
||||
resize(c, c->geom, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (cols = 0; cols <= n / 2; cols++) {
|
||||
if (cols * cols >= n)
|
||||
break;
|
||||
}
|
||||
rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols;
|
||||
|
||||
ch = (m->w.height - 2 * target_gappo - (rows - 1) * target_gappi) / rows;
|
||||
cw = (m->w.width - 2 * target_gappo - (cols - 1) * target_gappi) / cols;
|
||||
|
||||
overcols = n % cols;
|
||||
if (overcols) {
|
||||
dx = (m->w.width - overcols * cw - (overcols - 1) * target_gappi) / 2 -
|
||||
target_gappo;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
if (VISIBLEON(c, m) && !c->isunglobal && !client_is_x11_popup(c)) {
|
||||
cx = m->w.x + (i % cols) * (cw + target_gappi);
|
||||
cy = m->w.y + (i / cols) * (ch + target_gappi);
|
||||
if (overcols && i >= n - overcols)
|
||||
cx += dx;
|
||||
c->geom.x = cx + target_gappo;
|
||||
c->geom.y = cy + target_gappo;
|
||||
c->geom.width = cw;
|
||||
c->geom.height = ch;
|
||||
resize(c, c->geom, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void overview(Monitor *m) {
|
||||
if (config.ov_no_resize) {
|
||||
overview_scale(m);
|
||||
} else {
|
||||
overview_resize(m);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue