mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-03 06:46:38 -04:00
feat: smart spawning/tiling for easier keyboard usage
This commit is contained in:
parent
64e29e7f1d
commit
b509004f4a
2 changed files with 153 additions and 3 deletions
|
|
@ -314,6 +314,8 @@ typedef struct {
|
|||
uint32_t gappoh;
|
||||
uint32_t gappov;
|
||||
uint32_t borderpx;
|
||||
int32_t canvas_tiling;
|
||||
int32_t canvas_tiling_gap;
|
||||
float scratchpad_width_ratio;
|
||||
float scratchpad_height_ratio;
|
||||
float rootcolor[4];
|
||||
|
|
@ -1713,6 +1715,10 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
config->scratchpad_height_ratio = atof(value);
|
||||
} else if (strcmp(key, "borderpx") == 0) {
|
||||
config->borderpx = atoi(value);
|
||||
} else if (strcmp(key, "canvas_tiling") == 0) {
|
||||
config->canvas_tiling = atoi(value);
|
||||
} else if (strcmp(key, "canvas_tiling_gap") == 0) {
|
||||
config->canvas_tiling_gap = atoi(value);
|
||||
} else if (strcmp(key, "rootcolor") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
|
|
@ -3352,6 +3358,8 @@ void set_value_default() {
|
|||
config.idleinhibit_ignore_visible = 0;
|
||||
|
||||
config.borderpx = 4;
|
||||
config.canvas_tiling = 0;
|
||||
config.canvas_tiling_gap = 10;
|
||||
config.overviewgappi = 5;
|
||||
config.overviewgappo = 30;
|
||||
config.cursor_hide_timeout = 0;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,144 @@
|
|||
static void canvas_pan_to_client(Monitor *m, Client *c);
|
||||
|
||||
// dir: 1=left, 2=right, 3=up, 4=down
|
||||
static Client *canvas_chain_end(Monitor *m, uint32_t tag, Client *ref, int dir,
|
||||
int gap) {
|
||||
Client *c;
|
||||
int tolerance = 60;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c == ref || c->isunglobal)
|
||||
continue;
|
||||
if (c->canvas_geom[tag].width == 0 || c->canvas_geom[tag].height == 0)
|
||||
continue;
|
||||
|
||||
int cx1 = c->canvas_geom[tag].x;
|
||||
int cy1 = c->canvas_geom[tag].y;
|
||||
int cx2 = cx1 + c->canvas_geom[tag].width;
|
||||
int cy2 = cy1 + c->canvas_geom[tag].height;
|
||||
int rx1 = ref->canvas_geom[tag].x;
|
||||
int ry1 = ref->canvas_geom[tag].y;
|
||||
int rx2 = rx1 + ref->canvas_geom[tag].width;
|
||||
int ry2 = ry1 + ref->canvas_geom[tag].height;
|
||||
|
||||
bool overlaps_h = cx1 < rx2 && cx2 > rx1;
|
||||
bool overlaps_v = cy1 < ry2 && cy2 > ry1;
|
||||
|
||||
bool adjacent = false;
|
||||
switch (dir) {
|
||||
case 1:
|
||||
adjacent = overlaps_v && abs(cx2 - (rx1 - gap)) < tolerance;
|
||||
break;
|
||||
case 2:
|
||||
adjacent = overlaps_v && abs(cx1 - (rx2 + gap)) < tolerance;
|
||||
break;
|
||||
case 3:
|
||||
adjacent = overlaps_h && abs(cy2 - (ry1 - gap)) < tolerance;
|
||||
break;
|
||||
case 4:
|
||||
adjacent = overlaps_h && abs(cy1 - (ry2 + gap)) < tolerance;
|
||||
break;
|
||||
}
|
||||
|
||||
if (adjacent)
|
||||
return canvas_chain_end(m, tag, c, dir, gap);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static void canvas_geom_init(Client *c, Monitor *m, uint32_t tag, float pan_x,
|
||||
float pan_y, int *cascade_idx) {
|
||||
int w = c->geom.width > 0 ? c->geom.width : 640;
|
||||
int h = c->geom.height > 0 ? c->geom.height : 480;
|
||||
int w = c->geom.width > 100 ? c->geom.width : 640;
|
||||
int h = c->geom.height > 100 ? c->geom.height : 480;
|
||||
float zoom = m->pertag->canvas_zoom[tag];
|
||||
|
||||
int tiling = config.canvas_tiling;
|
||||
|
||||
if (tiling > 0 && !client_is_float_type(c) && !client_get_parent(c)) {
|
||||
Client *focused = NULL, *tmp;
|
||||
wl_list_for_each(tmp, &fstack, flink) {
|
||||
if (tmp == c || tmp->iskilling || tmp->isunglobal)
|
||||
continue;
|
||||
if (VISIBLEON(tmp, m)) {
|
||||
focused = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float vp_w = m->w.width / zoom;
|
||||
float vp_h = m->w.height / zoom;
|
||||
bool focused_in_viewport =
|
||||
focused && focused->canvas_geom[tag].width > 0 &&
|
||||
focused->canvas_geom[tag].height > 0 &&
|
||||
focused->canvas_geom[tag].x + focused->canvas_geom[tag].width >
|
||||
pan_x &&
|
||||
focused->canvas_geom[tag].y + focused->canvas_geom[tag].height >
|
||||
pan_y &&
|
||||
focused->canvas_geom[tag].x < pan_x + vp_w &&
|
||||
focused->canvas_geom[tag].y < pan_y + vp_h;
|
||||
|
||||
if (focused_in_viewport) {
|
||||
|
||||
int dir = tiling;
|
||||
int gap = config.canvas_tiling_gap;
|
||||
|
||||
if (tiling == 5) {
|
||||
float fx = focused->canvas_geom[tag].x;
|
||||
float fy = focused->canvas_geom[tag].y;
|
||||
float fw = focused->canvas_geom[tag].width;
|
||||
float fh = focused->canvas_geom[tag].height;
|
||||
|
||||
float mouse_cx = pan_x + (cursor->x - m->w.x) / zoom;
|
||||
float mouse_cy = pan_y + (cursor->y - m->w.y) / zoom;
|
||||
|
||||
float dl = fabsf(mouse_cx - fx);
|
||||
float dr = fabsf(mouse_cx - (fx + fw));
|
||||
float du = fabsf(mouse_cy - fy);
|
||||
float dd = fabsf(mouse_cy - (fy + fh));
|
||||
|
||||
float min = dl;
|
||||
dir = 1;
|
||||
if (dr < min) {
|
||||
min = dr;
|
||||
dir = 2;
|
||||
}
|
||||
if (du < min) {
|
||||
min = du;
|
||||
dir = 3;
|
||||
}
|
||||
if (dd < min) {
|
||||
dir = 4;
|
||||
}
|
||||
}
|
||||
|
||||
Client *end = canvas_chain_end(m, tag, focused, dir, gap);
|
||||
|
||||
switch (dir) {
|
||||
case 1:
|
||||
c->canvas_geom[tag].x = end->canvas_geom[tag].x - w - gap;
|
||||
c->canvas_geom[tag].y = end->canvas_geom[tag].y;
|
||||
break;
|
||||
case 2:
|
||||
c->canvas_geom[tag].x =
|
||||
end->canvas_geom[tag].x + end->canvas_geom[tag].width + gap;
|
||||
c->canvas_geom[tag].y = end->canvas_geom[tag].y;
|
||||
break;
|
||||
case 3:
|
||||
c->canvas_geom[tag].x = end->canvas_geom[tag].x;
|
||||
c->canvas_geom[tag].y = end->canvas_geom[tag].y - h - gap;
|
||||
break;
|
||||
case 4:
|
||||
c->canvas_geom[tag].x = end->canvas_geom[tag].x;
|
||||
c->canvas_geom[tag].y = end->canvas_geom[tag].y +
|
||||
end->canvas_geom[tag].height + gap;
|
||||
break;
|
||||
}
|
||||
c->canvas_geom[tag].width = w;
|
||||
c->canvas_geom[tag].height = h;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float cx = pan_x + (m->w.width / 2.0f) / zoom;
|
||||
float cy = pan_y + (m->w.height / 2.0f) / zoom;
|
||||
|
||||
|
|
@ -76,6 +211,7 @@ static void canvas(Monitor *m) {
|
|||
float zoom = m->pertag->canvas_zoom[tag];
|
||||
|
||||
int cascade_idx = 0;
|
||||
Client *newly_tiled = NULL;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isunglobal)
|
||||
|
|
@ -84,8 +220,11 @@ static void canvas(Monitor *m) {
|
|||
if (c->isfullscreen || c->ismaximizescreen)
|
||||
continue;
|
||||
|
||||
if (c->canvas_geom[tag].width == 0 && c->canvas_geom[tag].height == 0)
|
||||
if (c->canvas_geom[tag].width == 0 && c->canvas_geom[tag].height == 0) {
|
||||
canvas_geom_init(c, m, tag, pan_x, pan_y, &cascade_idx);
|
||||
if (config.canvas_tiling > 0 && !newly_tiled)
|
||||
newly_tiled = c;
|
||||
}
|
||||
|
||||
int screen_x =
|
||||
m->w.x + (int32_t)roundf((c->canvas_geom[tag].x - pan_x) * zoom);
|
||||
|
|
@ -115,6 +254,9 @@ static void canvas(Monitor *m) {
|
|||
else
|
||||
apply_visual_zoom(c, effective_zoom);
|
||||
}
|
||||
|
||||
if (newly_tiled)
|
||||
canvas_pan_to_client(m, newly_tiled);
|
||||
}
|
||||
|
||||
static void canvas_pan_to_client(Monitor *m, Client *c) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue