mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-03 06:46:38 -04:00
feat: add canvas layout
This commit is contained in:
parent
f94ddc671e
commit
9e2f0fc2b8
13 changed files with 1509 additions and 127 deletions
|
|
@ -174,10 +174,15 @@ bind=ALT,a,togglemaximizescreen,
|
||||||
bind=ALT,f,togglefullscreen,
|
bind=ALT,f,togglefullscreen,
|
||||||
bind=ALT+SHIFT,f,togglefakefullscreen,
|
bind=ALT+SHIFT,f,togglefakefullscreen,
|
||||||
bind=SUPER,i,minimized,
|
bind=SUPER,i,minimized,
|
||||||
bind=SUPER,o,toggleoverlay,
|
|
||||||
bind=SUPER+SHIFT,I,restore_minimized
|
bind=SUPER+SHIFT,I,restore_minimized
|
||||||
bind=ALT,z,toggle_scratchpad
|
bind=ALT,z,toggle_scratchpad
|
||||||
|
|
||||||
|
# canvas layout
|
||||||
|
bind=SUPER,o,toggleminimap,
|
||||||
|
bind=SUPER,p,canvas_overview_toggle,
|
||||||
|
bind=SUPER,z,canvas_zoom_resize,0.909090909
|
||||||
|
bind=SUPER,x,canvas_zoom_resize,1.1
|
||||||
|
|
||||||
# scroller layout
|
# scroller layout
|
||||||
bind=ALT,e,set_proportion,1.0
|
bind=ALT,e,set_proportion,1.0
|
||||||
bind=ALT,x,switch_proportion_preset,
|
bind=ALT,x,switch_proportion_preset,
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ mangowm is available in the **PikaOS package repository**.
|
||||||
You can install it using the `pikman` package manager:
|
You can install it using the `pikman` package manager:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pikman install mangowc
|
pikman install mangowm
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
project('mango', ['c', 'cpp'],
|
project('mango', ['c', 'cpp'],
|
||||||
version : '0.12.7',
|
version : '0.12.8',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
|
|
|
||||||
|
|
@ -161,21 +161,6 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
int32_t sy, void *data) {
|
int32_t sy, void *data) {
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
|
|
||||||
if (buffer_data->should_scale && buffer_data->height_scale < 1 &&
|
|
||||||
buffer_data->width_scale < 1) {
|
|
||||||
buffer_data->should_scale = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_data->should_scale && buffer_data->height_scale == 1 &&
|
|
||||||
buffer_data->width_scale < 1) {
|
|
||||||
buffer_data->should_scale = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_data->should_scale && buffer_data->height_scale < 1 &&
|
|
||||||
buffer_data->width_scale == 1) {
|
|
||||||
buffer_data->should_scale = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_scene_surface *scene_surface =
|
struct wlr_scene_surface *scene_surface =
|
||||||
wlr_scene_surface_try_from_buffer(buffer);
|
wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
|
||||||
|
|
@ -189,12 +174,8 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
int32_t surface_width = surface->current.width;
|
int32_t surface_width = surface->current.width;
|
||||||
int32_t surface_height = surface->current.height;
|
int32_t surface_height = surface->current.height;
|
||||||
|
|
||||||
surface_width = buffer_data->width_scale < 1
|
surface_width = buffer_data->width_scale * surface_width;
|
||||||
? surface_width
|
surface_height = buffer_data->height_scale * surface_height;
|
||||||
: buffer_data->width_scale * surface_width;
|
|
||||||
surface_height = buffer_data->height_scale < 1
|
|
||||||
? surface_height
|
|
||||||
: buffer_data->height_scale * surface_height;
|
|
||||||
|
|
||||||
if (surface_width > buffer_data->width &&
|
if (surface_width > buffer_data->width &&
|
||||||
wlr_subsurface_try_from_wlr_surface(surface) == NULL) {
|
wlr_subsurface_try_from_wlr_surface(surface) == NULL) {
|
||||||
|
|
@ -230,6 +211,87 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
buffer_data->corner_location);
|
buffer_data->corner_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scene_buffer_apply_canvas_zoom(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy, void *data) {
|
||||||
|
float zoom = *(float *)data;
|
||||||
|
struct wlr_scene_surface *scene_surface =
|
||||||
|
wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
if (!scene_surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wlr_scene_node_set_position(&buffer->node,
|
||||||
|
(int32_t)roundf(buffer->node.x * zoom),
|
||||||
|
(int32_t)roundf(buffer->node.y * zoom));
|
||||||
|
|
||||||
|
int32_t w = buffer->dst_width > 0 ? buffer->dst_width
|
||||||
|
: scene_surface->surface->current.width;
|
||||||
|
int32_t h = buffer->dst_height > 0 ? buffer->dst_height
|
||||||
|
: scene_surface->surface->current.height;
|
||||||
|
wlr_scene_buffer_set_dest_size(buffer, (int32_t)roundf(w * zoom),
|
||||||
|
(int32_t)roundf(h * zoom));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_canvas_zoom_correct(Client *c, float zoom) {
|
||||||
|
if (!c || !c->scene)
|
||||||
|
return;
|
||||||
|
wlr_scene_node_for_each_buffer(&c->scene_surface->node,
|
||||||
|
scene_buffer_apply_canvas_zoom, &zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_buffer_apply_zoom(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
|
int32_t sy, void *data) {
|
||||||
|
float zoom = *(float *)data;
|
||||||
|
struct wlr_scene_surface *scene_surface =
|
||||||
|
wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
if (!scene_surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32_t w = scene_surface->surface->current.width;
|
||||||
|
int32_t h = scene_surface->surface->current.height;
|
||||||
|
wlr_scene_buffer_set_dest_size(buffer, (int32_t)roundf(w * zoom),
|
||||||
|
(int32_t)roundf(h * zoom));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_buffer_clear_dest_size(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy, void *data) {
|
||||||
|
struct wlr_scene_surface *scene_surface =
|
||||||
|
wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
if (!scene_surface)
|
||||||
|
return;
|
||||||
|
wlr_scene_buffer_set_dest_size(buffer, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_visual_zoom(Client *c) {
|
||||||
|
if (!c || !c->scene)
|
||||||
|
return;
|
||||||
|
wlr_scene_node_for_each_buffer(&c->scene_surface->node,
|
||||||
|
scene_buffer_clear_dest_size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_visual_zoom(Client *c, float zoom) {
|
||||||
|
if (!c || !c->scene || zoom == 1.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wlr_scene_node_for_each_buffer(&c->scene_surface->node,
|
||||||
|
scene_buffer_apply_zoom, &zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float get_client_effective_zoom(Client *c) {
|
||||||
|
if (c->mon && is_canvas_layout(c->mon) && !c->isfullscreen &&
|
||||||
|
!c->ismaximizescreen) {
|
||||||
|
uint32_t tag = c->mon->pertag->curtag;
|
||||||
|
float zoom = c->mon->pertag->canvas_zoom[tag];
|
||||||
|
float effective_zoom = zoom;
|
||||||
|
if (c->mon->canvas_in_overview &&
|
||||||
|
c->canvas_geom_backup[tag].width > 0) {
|
||||||
|
effective_zoom *= (float)c->canvas_geom[tag].width /
|
||||||
|
c->canvas_geom_backup[tag].width;
|
||||||
|
}
|
||||||
|
return effective_zoom;
|
||||||
|
}
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
void buffer_set_effect(Client *c, BufferData data) {
|
void buffer_set_effect(Client *c, BufferData data) {
|
||||||
|
|
||||||
if (!c || c->iskilling)
|
if (!c || c->iskilling)
|
||||||
|
|
@ -267,6 +329,8 @@ void client_draw_shadow(Client *c) {
|
||||||
wlr_scene_node_set_enabled(&c->shadow->node, true);
|
wlr_scene_node_set_enabled(&c->shadow->node, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float zoom = get_client_effective_zoom(c);
|
||||||
|
|
||||||
bool hit_no_border = check_hit_no_border(c);
|
bool hit_no_border = check_hit_no_border(c);
|
||||||
enum corner_location current_corner_location =
|
enum corner_location current_corner_location =
|
||||||
c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||||
|
|
@ -307,10 +371,10 @@ void client_draw_shadow(Client *c) {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_box absolute_shadow_box = {
|
struct wlr_box absolute_shadow_box = {
|
||||||
.x = shadow_box.x + c->animation.current.x,
|
.x = shadow_box.x * zoom + c->animation.current.x,
|
||||||
.y = shadow_box.y + c->animation.current.y,
|
.y = shadow_box.y * zoom + c->animation.current.y,
|
||||||
.width = shadow_box.width,
|
.width = shadow_box.width * zoom,
|
||||||
.height = shadow_box.height,
|
.height = shadow_box.height * zoom,
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t right_offset, bottom_offset, left_offset, top_offset;
|
int32_t right_offset, bottom_offset, left_offset, top_offset;
|
||||||
|
|
@ -323,13 +387,15 @@ void client_draw_shadow(Client *c) {
|
||||||
} else {
|
} else {
|
||||||
right_offset =
|
right_offset =
|
||||||
GEZERO(absolute_shadow_box.x + absolute_shadow_box.width -
|
GEZERO(absolute_shadow_box.x + absolute_shadow_box.width -
|
||||||
c->mon->m.x - c->mon->m.width);
|
c->mon->m.x - c->mon->m.width) /
|
||||||
|
zoom;
|
||||||
bottom_offset =
|
bottom_offset =
|
||||||
GEZERO(absolute_shadow_box.y + absolute_shadow_box.height -
|
GEZERO(absolute_shadow_box.y + absolute_shadow_box.height -
|
||||||
c->mon->m.y - c->mon->m.height);
|
c->mon->m.y - c->mon->m.height) /
|
||||||
|
zoom;
|
||||||
|
|
||||||
left_offset = GEZERO(c->mon->m.x - absolute_shadow_box.x);
|
left_offset = GEZERO(c->mon->m.x - absolute_shadow_box.x) / zoom;
|
||||||
top_offset = GEZERO(c->mon->m.y - absolute_shadow_box.y);
|
top_offset = GEZERO(c->mon->m.y - absolute_shadow_box.y) / zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
left_offset = MIN(left_offset, shadow_box.width);
|
left_offset = MIN(left_offset, shadow_box.width);
|
||||||
|
|
@ -337,15 +403,18 @@ void client_draw_shadow(Client *c) {
|
||||||
top_offset = MIN(top_offset, shadow_box.height);
|
top_offset = MIN(top_offset, shadow_box.height);
|
||||||
bottom_offset = MIN(bottom_offset, shadow_box.height);
|
bottom_offset = MIN(bottom_offset, shadow_box.height);
|
||||||
|
|
||||||
wlr_scene_node_set_position(&c->shadow->node, shadow_box.x + left_offset,
|
wlr_scene_node_set_position(&c->shadow->node,
|
||||||
shadow_box.y + top_offset);
|
(shadow_box.x + left_offset) * zoom,
|
||||||
|
(shadow_box.y + top_offset) * zoom);
|
||||||
|
|
||||||
wlr_scene_shadow_set_size(
|
wlr_scene_shadow_set_size(
|
||||||
c->shadow, GEZERO(shadow_box.width - left_offset - right_offset),
|
c->shadow, GEZERO(shadow_box.width - left_offset - right_offset) * zoom,
|
||||||
GEZERO(shadow_box.height - top_offset - bottom_offset));
|
GEZERO(shadow_box.height - top_offset - bottom_offset) * zoom);
|
||||||
|
|
||||||
clipped_region.area.x = clipped_region.area.x - left_offset;
|
clipped_region.area.x = (clipped_region.area.x - left_offset) * zoom;
|
||||||
clipped_region.area.y = clipped_region.area.y - top_offset;
|
clipped_region.area.y = (clipped_region.area.y - top_offset) * zoom;
|
||||||
|
clipped_region.area.width *= zoom;
|
||||||
|
clipped_region.area.height *= zoom;
|
||||||
|
|
||||||
wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region);
|
wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region);
|
||||||
}
|
}
|
||||||
|
|
@ -354,6 +423,8 @@ void apply_border(Client *c) {
|
||||||
if (!c || c->iskilling || !client_surface(c)->mapped)
|
if (!c || c->iskilling || !client_surface(c)->mapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
float zoom = get_client_effective_zoom(c);
|
||||||
|
|
||||||
bool hit_no_border = check_hit_no_border(c);
|
bool hit_no_border = check_hit_no_border(c);
|
||||||
enum corner_location current_corner_location;
|
enum corner_location current_corner_location;
|
||||||
if (c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
if (c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||||
|
|
@ -389,14 +460,16 @@ void apply_border(Client *c) {
|
||||||
top_offset = 0;
|
top_offset = 0;
|
||||||
} else {
|
} else {
|
||||||
right_offset =
|
right_offset =
|
||||||
GEZERO(c->animation.current.x + c->animation.current.width -
|
GEZERO(c->animation.current.x + c->animation.current.width * zoom -
|
||||||
c->mon->m.x - c->mon->m.width);
|
c->mon->m.x - c->mon->m.width) /
|
||||||
|
zoom;
|
||||||
bottom_offset =
|
bottom_offset =
|
||||||
GEZERO(c->animation.current.y + c->animation.current.height -
|
GEZERO(c->animation.current.y + c->animation.current.height * zoom -
|
||||||
c->mon->m.y - c->mon->m.height);
|
c->mon->m.y - c->mon->m.height) /
|
||||||
|
zoom;
|
||||||
|
|
||||||
left_offset = GEZERO(c->mon->m.x - c->animation.current.x);
|
left_offset = GEZERO(c->mon->m.x - c->animation.current.x) / zoom;
|
||||||
top_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
top_offset = GEZERO(c->mon->m.y - c->animation.current.y) / zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t inner_surface_width = GEZERO(clip_box.width - 2 * bw);
|
int32_t inner_surface_width = GEZERO(clip_box.width - 2 * bw);
|
||||||
|
|
@ -438,9 +511,14 @@ void apply_border(Client *c) {
|
||||||
.corners = current_corner_location,
|
.corners = current_corner_location,
|
||||||
};
|
};
|
||||||
|
|
||||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
wlr_scene_node_set_position(&c->scene_surface->node,
|
||||||
wlr_scene_rect_set_size(c->border, rect_width, rect_height);
|
(int32_t)roundf(c->bw * zoom),
|
||||||
wlr_scene_node_set_position(&c->border->node, rect_x, rect_y);
|
(int32_t)roundf(c->bw * zoom));
|
||||||
|
wlr_scene_rect_set_size(c->border, (int32_t)roundf(rect_width * zoom),
|
||||||
|
(int32_t)roundf(rect_height * zoom));
|
||||||
|
wlr_scene_node_set_position(&c->border->node,
|
||||||
|
(int32_t)roundf(rect_x * zoom),
|
||||||
|
(int32_t)roundf(rect_y * zoom));
|
||||||
wlr_scene_rect_set_corner_radius(c->border, config.border_radius,
|
wlr_scene_rect_set_corner_radius(c->border, config.border_radius,
|
||||||
current_corner_location);
|
current_corner_location);
|
||||||
wlr_scene_rect_set_clipped_region(c->border, clipped_region);
|
wlr_scene_rect_set_clipped_region(c->border, clipped_region);
|
||||||
|
|
@ -450,18 +528,25 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
||||||
int32_t offsetx = 0, offsety = 0, offsetw = 0, offseth = 0;
|
int32_t offsetx = 0, offsety = 0, offsetw = 0, offseth = 0;
|
||||||
struct ivec2 offset = {0, 0, 0, 0};
|
struct ivec2 offset = {0, 0, 0, 0};
|
||||||
|
|
||||||
if (!ISSCROLLTILED(c) && !c->animation.tagining && !c->animation.tagouted &&
|
if (!ISSCROLLTILED(c) && !(c->mon && is_canvas_layout(c->mon)) &&
|
||||||
|
!c->animation.tagining && !c->animation.tagouted &&
|
||||||
!c->animation.tagouting)
|
!c->animation.tagouting)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
|
float zoom = get_client_effective_zoom(c);
|
||||||
|
|
||||||
int32_t bottom_out_offset =
|
int32_t bottom_out_offset =
|
||||||
GEZERO(c->animation.current.y + c->animation.current.height -
|
GEZERO(c->animation.current.y + c->animation.current.height * zoom -
|
||||||
c->mon->m.y - c->mon->m.height);
|
c->mon->m.y - c->mon->m.height) /
|
||||||
|
zoom;
|
||||||
int32_t right_out_offset =
|
int32_t right_out_offset =
|
||||||
GEZERO(c->animation.current.x + c->animation.current.width -
|
GEZERO(c->animation.current.x + c->animation.current.width * zoom -
|
||||||
c->mon->m.x - c->mon->m.width);
|
c->mon->m.x - c->mon->m.width) /
|
||||||
int32_t left_out_offset = GEZERO(c->mon->m.x - c->animation.current.x);
|
zoom;
|
||||||
int32_t top_out_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
int32_t left_out_offset =
|
||||||
|
GEZERO(c->mon->m.x - c->animation.current.x) / zoom;
|
||||||
|
int32_t top_out_offset =
|
||||||
|
GEZERO(c->mon->m.y - c->animation.current.y) / zoom;
|
||||||
|
|
||||||
// 必须转换为int,否计算会没有负数导致判断错误
|
// 必须转换为int,否计算会没有负数导致判断错误
|
||||||
int32_t bw = (int32_t)c->bw;
|
int32_t bw = (int32_t)c->bw;
|
||||||
|
|
@ -471,7 +556,8 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
||||||
需要主要border超出屏幕的时候不计算如偏差之内而是
|
需要主要border超出屏幕的时候不计算如偏差之内而是
|
||||||
要等窗口表面超出才开始计算偏差
|
要等窗口表面超出才开始计算偏差
|
||||||
*/
|
*/
|
||||||
if (ISSCROLLTILED(c) || c->animation.tagining || c->animation.tagouted ||
|
if (ISSCROLLTILED(c) || (c->mon && is_canvas_layout(c->mon)) ||
|
||||||
|
c->animation.tagining || c->animation.tagouted ||
|
||||||
c->animation.tagouting) {
|
c->animation.tagouting) {
|
||||||
if (left_out_offset > 0) {
|
if (left_out_offset > 0) {
|
||||||
offsetx = GEZERO(left_out_offset - bw);
|
offsetx = GEZERO(left_out_offset - bw);
|
||||||
|
|
@ -499,7 +585,8 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
||||||
offset.height = offseth;
|
offset.height = offseth;
|
||||||
|
|
||||||
if ((clip_box->width + bw <= 0 || clip_box->height + bw <= 0) &&
|
if ((clip_box->width + bw <= 0 || clip_box->height + bw <= 0) &&
|
||||||
(ISSCROLLTILED(c) || c->animation.tagouting || c->animation.tagining)) {
|
(ISSCROLLTILED(c) || (c->mon && is_canvas_layout(c->mon)) ||
|
||||||
|
c->animation.tagouting || c->animation.tagining)) {
|
||||||
c->is_clip_to_hide = true;
|
c->is_clip_to_hide = true;
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, false);
|
wlr_scene_node_set_enabled(&c->scene->node, false);
|
||||||
} else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) {
|
} else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) {
|
||||||
|
|
@ -540,6 +627,17 @@ void client_apply_clip(Client *c, float factor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(c->mon && is_canvas_layout(c->mon))) {
|
||||||
|
float noanim_zoom = get_client_effective_zoom(c);
|
||||||
|
if (noanim_zoom != 1.0f) {
|
||||||
|
clip_box.x = (int32_t)roundf(clip_box.x * noanim_zoom);
|
||||||
|
clip_box.y = (int32_t)roundf(clip_box.y * noanim_zoom);
|
||||||
|
clip_box.width = (int32_t)roundf(clip_box.width * noanim_zoom);
|
||||||
|
clip_box.height =
|
||||||
|
(int32_t)roundf(clip_box.height * noanim_zoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
||||||
buffer_set_effect(c, (BufferData){1.0f, 1.0f, clip_box.width,
|
buffer_set_effect(c, (BufferData){1.0f, 1.0f, clip_box.width,
|
||||||
clip_box.height,
|
clip_box.height,
|
||||||
|
|
@ -587,6 +685,16 @@ void client_apply_clip(Client *c, float factor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(c->mon && is_canvas_layout(c->mon))) {
|
||||||
|
float clip_zoom = get_client_effective_zoom(c);
|
||||||
|
if (clip_zoom != 1.0f) {
|
||||||
|
clip_box.x = (int32_t)roundf(clip_box.x * clip_zoom);
|
||||||
|
clip_box.y = (int32_t)roundf(clip_box.y * clip_zoom);
|
||||||
|
clip_box.width = (int32_t)roundf(clip_box.width * clip_zoom);
|
||||||
|
clip_box.height = (int32_t)roundf(clip_box.height * clip_zoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 应用窗口表面剪切
|
// 应用窗口表面剪切
|
||||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
||||||
|
|
||||||
|
|
@ -926,7 +1034,8 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
||||||
// float_geom = c->geom;
|
// float_geom = c->geom;
|
||||||
bbox = (interact || c->isfloating || c->isfullscreen) ? &sgeom : &c->mon->w;
|
bbox = (interact || c->isfloating || c->isfullscreen) ? &sgeom : &c->mon->w;
|
||||||
|
|
||||||
if (is_scroller_layout(c->mon) && (!c->isfloating || c == grabc)) {
|
if (is_canvas_layout(c->mon) ||
|
||||||
|
(is_scroller_layout(c->mon) && (!c->isfloating || c == grabc))) {
|
||||||
c->geom = geo;
|
c->geom = geo;
|
||||||
c->geom.width = MAX(1 + 2 * (int32_t)c->bw, c->geom.width);
|
c->geom.width = MAX(1 + 2 * (int32_t)c->bw, c->geom.width);
|
||||||
c->geom.height = MAX(1 + 2 * (int32_t)c->bw, c->geom.height);
|
c->geom.height = MAX(1 + 2 * (int32_t)c->bw, c->geom.height);
|
||||||
|
|
@ -1182,10 +1291,9 @@ bool client_draw_frame(Client *c) {
|
||||||
if (!c || !client_surface(c)->mapped)
|
if (!c || !client_surface(c)->mapped)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!c->need_output_flush) {
|
bool need_flush = c->need_output_flush;
|
||||||
return client_apply_focus_opacity(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (need_flush) {
|
||||||
if (config.animations && c->animation.running) {
|
if (config.animations && c->animation.running) {
|
||||||
client_animation_next_tick(c);
|
client_animation_next_tick(c);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1196,6 +1304,28 @@ bool client_draw_frame(Client *c) {
|
||||||
client_apply_clip(c, 1.0);
|
client_apply_clip(c, 1.0);
|
||||||
c->need_output_flush = false;
|
c->need_output_flush = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->mon && is_canvas_layout(c->mon) && !c->isfullscreen &&
|
||||||
|
!c->ismaximizescreen) {
|
||||||
|
uint32_t tag = c->mon->pertag->curtag;
|
||||||
|
float zoom = c->mon->pertag->canvas_zoom[tag];
|
||||||
|
float effective_zoom = zoom;
|
||||||
|
if (c->mon->canvas_in_overview &&
|
||||||
|
c->canvas_geom_backup[tag].width > 0) {
|
||||||
|
effective_zoom *= (float)c->canvas_geom[tag].width /
|
||||||
|
c->canvas_geom_backup[tag].width;
|
||||||
|
}
|
||||||
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, NULL);
|
||||||
|
client_apply_clip(c, 1.0);
|
||||||
|
if (effective_zoom != 1.0f && !c->is_clip_to_hide)
|
||||||
|
apply_canvas_zoom_correct(c, effective_zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!need_flush) {
|
||||||
|
return client_apply_focus_opacity(c);
|
||||||
|
}
|
||||||
|
|
||||||
client_apply_focus_opacity(c);
|
client_apply_focus_opacity(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,36 @@ typedef struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认按键绑定数组
|
// 默认按键绑定数组
|
||||||
KeyBinding default_key_bindings[] = {CHVT(1), CHVT(2), CHVT(3), CHVT(4),
|
KeyBinding default_key_bindings[] = {
|
||||||
CHVT(5), CHVT(6), CHVT(7), CHVT(8),
|
CHVT(1),
|
||||||
CHVT(9), CHVT(10), CHVT(11), CHVT(12)};
|
CHVT(2),
|
||||||
|
CHVT(3),
|
||||||
|
CHVT(4),
|
||||||
|
CHVT(5),
|
||||||
|
CHVT(6),
|
||||||
|
CHVT(7),
|
||||||
|
CHVT(8),
|
||||||
|
CHVT(9),
|
||||||
|
CHVT(10),
|
||||||
|
CHVT(11),
|
||||||
|
CHVT(12),
|
||||||
|
{WLR_MODIFIER_LOGO,
|
||||||
|
{.keysym = XKB_KEY_o, .type = KEY_TYPE_SYM},
|
||||||
|
toggleminimap,
|
||||||
|
{0}},
|
||||||
|
{WLR_MODIFIER_LOGO,
|
||||||
|
{.keysym = XKB_KEY_p, .type = KEY_TYPE_SYM},
|
||||||
|
canvas_overview_toggle,
|
||||||
|
{0}},
|
||||||
|
{WLR_MODIFIER_LOGO,
|
||||||
|
{.keysym = XKB_KEY_z, .type = KEY_TYPE_SYM},
|
||||||
|
canvas_zoom_resize,
|
||||||
|
{.f = 1.0f / 1.1f}},
|
||||||
|
{WLR_MODIFIER_LOGO,
|
||||||
|
{.keysym = XKB_KEY_x, .type = KEY_TYPE_SYM},
|
||||||
|
canvas_zoom_resize,
|
||||||
|
{.f = 1.1f}},
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t mod;
|
uint32_t mod;
|
||||||
|
|
@ -1052,6 +1079,8 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||||
func = togglefakefullscreen;
|
func = togglefakefullscreen;
|
||||||
} else if (strcmp(func_name, "toggleoverlay") == 0) {
|
} else if (strcmp(func_name, "toggleoverlay") == 0) {
|
||||||
func = toggleoverlay;
|
func = toggleoverlay;
|
||||||
|
} else if (strcmp(func_name, "toggleminimap") == 0) {
|
||||||
|
func = toggleminimap;
|
||||||
} else if (strcmp(func_name, "minimized") == 0) {
|
} else if (strcmp(func_name, "minimized") == 0) {
|
||||||
func = minimized;
|
func = minimized;
|
||||||
} else if (strcmp(func_name, "restore_minimized") == 0) {
|
} else if (strcmp(func_name, "restore_minimized") == 0) {
|
||||||
|
|
@ -1204,6 +1233,13 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||||
(*arg).i = parse_direction(arg_value);
|
(*arg).i = parse_direction(arg_value);
|
||||||
} else if (strcmp(func_name, "toggle_all_floating") == 0) {
|
} else if (strcmp(func_name, "toggle_all_floating") == 0) {
|
||||||
func = toggle_all_floating;
|
func = toggle_all_floating;
|
||||||
|
} else if (strcmp(func_name, "canvas_zoom_resize") == 0) {
|
||||||
|
func = canvas_zoom_resize;
|
||||||
|
(*arg).f = atof(arg_value);
|
||||||
|
} else if (strcmp(func_name, "canvas_overview_toggle") == 0) {
|
||||||
|
func = canvas_overview_toggle;
|
||||||
|
} else if (strcmp(func_name, "canvas_fill_viewport") == 0) {
|
||||||
|
func = canvas_fill_viewport;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ int32_t incohgaps(const Arg *arg);
|
||||||
int32_t incovgaps(const Arg *arg);
|
int32_t incovgaps(const Arg *arg);
|
||||||
int32_t defaultgaps(const Arg *arg);
|
int32_t defaultgaps(const Arg *arg);
|
||||||
int32_t togglefakefullscreen(const Arg *arg);
|
int32_t togglefakefullscreen(const Arg *arg);
|
||||||
|
int32_t toggleminimap(const Arg *arg);
|
||||||
int32_t toggleoverlay(const Arg *arg);
|
int32_t toggleoverlay(const Arg *arg);
|
||||||
int32_t movewin(const Arg *arg);
|
int32_t movewin(const Arg *arg);
|
||||||
int32_t resizewin(const Arg *arg);
|
int32_t resizewin(const Arg *arg);
|
||||||
|
|
@ -70,4 +71,7 @@ int32_t disable_monitor(const Arg *arg);
|
||||||
int32_t enable_monitor(const Arg *arg);
|
int32_t enable_monitor(const Arg *arg);
|
||||||
int32_t toggle_monitor(const Arg *arg);
|
int32_t toggle_monitor(const Arg *arg);
|
||||||
int32_t scroller_stack(const Arg *arg);
|
int32_t scroller_stack(const Arg *arg);
|
||||||
|
int32_t canvas_zoom_resize(const Arg *arg);
|
||||||
|
int32_t canvas_overview_toggle(const Arg *arg);
|
||||||
|
int32_t canvas_fill_viewport(const Arg *arg);
|
||||||
int32_t toggle_all_floating(const Arg *arg);
|
int32_t toggle_all_floating(const Arg *arg);
|
||||||
|
|
@ -142,6 +142,8 @@ int32_t focusdir(const Arg *arg) {
|
||||||
focusclient(c, 1);
|
focusclient(c, 1);
|
||||||
if (config.warpcursor)
|
if (config.warpcursor)
|
||||||
warp_cursor(c);
|
warp_cursor(c);
|
||||||
|
if (selmon && is_canvas_layout(selmon))
|
||||||
|
canvas_pan_to_client(selmon, c);
|
||||||
} else {
|
} else {
|
||||||
if (config.focus_cross_tag) {
|
if (config.focus_cross_tag) {
|
||||||
if (arg->i == LEFT || arg->i == UP)
|
if (arg->i == LEFT || arg->i == UP)
|
||||||
|
|
@ -374,7 +376,10 @@ int32_t moveresize(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Float the window and tell motionnotify to grab it */
|
/* Float the window and tell motionnotify to grab it */
|
||||||
if (grabc->isfloating == 0 && arg->ui == CurMove) {
|
if (grabc->isfloating == 0 && arg->ui == CurMove &&
|
||||||
|
!(grabc->mon &&
|
||||||
|
grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag]->id ==
|
||||||
|
CANVAS)) {
|
||||||
grabc->drag_to_tile = true;
|
grabc->drag_to_tile = true;
|
||||||
exit_scroller_stack(grabc);
|
exit_scroller_stack(grabc);
|
||||||
setfloating(grabc, 1);
|
setfloating(grabc, 1);
|
||||||
|
|
@ -385,34 +390,52 @@ int32_t moveresize(const Arg *arg) {
|
||||||
|
|
||||||
switch (cursor_mode = arg->ui) {
|
switch (cursor_mode = arg->ui) {
|
||||||
case CurMove:
|
case CurMove:
|
||||||
|
if (grabc->mon &&
|
||||||
|
grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag]->id ==
|
||||||
|
CANVAS) {
|
||||||
|
grabcx = (int32_t)round(cursor->x);
|
||||||
|
grabcy = (int32_t)round(cursor->y);
|
||||||
|
} else {
|
||||||
grabcx = cursor->x - grabc->geom.x;
|
grabcx = cursor->x - grabc->geom.x;
|
||||||
grabcy = cursor->y - grabc->geom.y;
|
grabcy = cursor->y - grabc->geom.y;
|
||||||
|
}
|
||||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab");
|
wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab");
|
||||||
break;
|
break;
|
||||||
case CurResize:
|
case CurResize:
|
||||||
/* Doesn't work for X11 output - the next absolute motion event
|
/* Doesn't work for X11 output - the next absolute motion event
|
||||||
* returns the cursor to where it started */
|
* returns the cursor to where it started */
|
||||||
if (grabc->isfloating) {
|
if (grabc->isfloating ||
|
||||||
|
(grabc->mon &&
|
||||||
|
grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag]->id ==
|
||||||
|
CANVAS)) {
|
||||||
rzcorner = config.drag_corner;
|
rzcorner = config.drag_corner;
|
||||||
grabcx = (int)round(cursor->x);
|
grabcx = (int)round(cursor->x);
|
||||||
grabcy = (int)round(cursor->y);
|
grabcy = (int)round(cursor->y);
|
||||||
|
|
||||||
|
int32_t vis_w = grabc->geom.width;
|
||||||
|
int32_t vis_h = grabc->geom.height;
|
||||||
|
if (grabc->mon &&
|
||||||
|
grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag]->id ==
|
||||||
|
CANVAS) {
|
||||||
|
uint32_t _tag = grabc->mon->pertag->curtag;
|
||||||
|
float _zoom = grabc->mon->pertag->canvas_zoom[_tag];
|
||||||
|
vis_w = (int32_t)roundf(vis_w * _zoom);
|
||||||
|
vis_h = (int32_t)roundf(vis_h * _zoom);
|
||||||
|
}
|
||||||
|
|
||||||
if (rzcorner == 4)
|
if (rzcorner == 4)
|
||||||
/* identify the closest corner index */
|
/* identify the closest corner index */
|
||||||
rzcorner = (grabcx - grabc->geom.x <
|
rzcorner =
|
||||||
grabc->geom.x + grabc->geom.width - grabcx
|
(grabcx - grabc->geom.x < grabc->geom.x + vis_w - grabcx
|
||||||
? 0
|
? 0
|
||||||
: 1) +
|
: 1) +
|
||||||
(grabcy - grabc->geom.y <
|
(grabcy - grabc->geom.y < grabc->geom.y + vis_h - grabcy
|
||||||
grabc->geom.y + grabc->geom.height - grabcy
|
|
||||||
? 0
|
? 0
|
||||||
: 2);
|
: 2);
|
||||||
|
|
||||||
if (config.drag_warp_cursor) {
|
if (config.drag_warp_cursor) {
|
||||||
grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width
|
grabcx = rzcorner & 1 ? grabc->geom.x + vis_w : grabc->geom.x;
|
||||||
: grabc->geom.x;
|
grabcy = rzcorner & 2 ? grabc->geom.y + vis_h : grabc->geom.y;
|
||||||
grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height
|
|
||||||
: grabc->geom.y;
|
|
||||||
wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
|
wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1013,7 +1036,6 @@ int32_t switch_layout(const Arg *arg) {
|
||||||
len = MAX(strlen(layouts[ji].name), strlen(target_layout_name));
|
len = MAX(strlen(layouts[ji].name), strlen(target_layout_name));
|
||||||
if (strncmp(layouts[ji].name, target_layout_name, len) == 0) {
|
if (strncmp(layouts[ji].name, target_layout_name, len) == 0) {
|
||||||
selmon->pertag->ltidxs[selmon->pertag->curtag] = &layouts[ji];
|
selmon->pertag->ltidxs[selmon->pertag->curtag] = &layouts[ji];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1667,6 +1689,10 @@ int32_t toggleoverview(const Arg *arg) {
|
||||||
if (!selmon)
|
if (!selmon)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
Client *fs_ov = focustop(selmon);
|
||||||
|
if (fs_ov && fs_ov->isfullscreen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (selmon->isoverview && config.ov_tab_mode && arg->i != 1 &&
|
if (selmon->isoverview && config.ov_tab_mode && arg->i != 1 &&
|
||||||
selmon->sel) {
|
selmon->sel) {
|
||||||
focusstack(&(Arg){.i = 1});
|
focusstack(&(Arg){.i = 1});
|
||||||
|
|
@ -1871,6 +1897,86 @@ int32_t scroller_stack(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t canvas_zoom_resize(const Arg *arg) {
|
||||||
|
if (!selmon || !is_canvas_layout(selmon))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *fs = focustop(selmon);
|
||||||
|
if (fs && fs->isfullscreen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
float factor = arg->f;
|
||||||
|
if (factor <= 0.0f)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint32_t tag = selmon->pertag->curtag;
|
||||||
|
float old_zoom = selmon->pertag->canvas_zoom[tag];
|
||||||
|
selmon->pertag->canvas_zoom[tag] *= factor;
|
||||||
|
selmon->pertag->canvas_zoom[tag] =
|
||||||
|
CLAMP_FLOAT(selmon->pertag->canvas_zoom[tag], 0.1f, 1.0f);
|
||||||
|
float new_zoom = selmon->pertag->canvas_zoom[tag];
|
||||||
|
|
||||||
|
// Adjust pan so zoom centers on the screen center
|
||||||
|
float center_canvas_x =
|
||||||
|
selmon->pertag->canvas_pan_x[tag] + (selmon->w.width / old_zoom) / 2.0f;
|
||||||
|
float center_canvas_y = selmon->pertag->canvas_pan_y[tag] +
|
||||||
|
(selmon->w.height / old_zoom) / 2.0f;
|
||||||
|
selmon->pertag->canvas_pan_x[tag] =
|
||||||
|
center_canvas_x - (selmon->w.width / new_zoom) / 2.0f;
|
||||||
|
selmon->pertag->canvas_pan_y[tag] =
|
||||||
|
center_canvas_y - (selmon->w.height / new_zoom) / 2.0f;
|
||||||
|
|
||||||
|
canvas_reposition(selmon);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t canvas_overview_toggle(const Arg *arg) {
|
||||||
|
if (!selmon || !is_canvas_layout(selmon))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (selmon->canvas_overview_visible && !selmon->canvas_overview_closing) {
|
||||||
|
selmon->canvas_overview_closing = true;
|
||||||
|
selmon->canvas_overview_anim_start = get_now_in_ms();
|
||||||
|
} else if (!selmon->canvas_overview_visible) {
|
||||||
|
if (selmon->minimap_visible) {
|
||||||
|
selmon->minimap_visible = false;
|
||||||
|
if (minimap_scene_tree) {
|
||||||
|
wlr_scene_node_destroy(&minimap_scene_tree->node);
|
||||||
|
minimap_scene_tree = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selmon->canvas_overview_visible = true;
|
||||||
|
selmon->canvas_overview_closing = false;
|
||||||
|
selmon->canvas_overview_progress = 0.0f;
|
||||||
|
selmon->canvas_overview_anim_start = get_now_in_ms();
|
||||||
|
}
|
||||||
|
request_fresh_all_monitors();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t canvas_fill_viewport(const Arg *arg) {
|
||||||
|
if (!selmon || !is_canvas_layout(selmon))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *c = selmon->sel;
|
||||||
|
if (!c || c->isfullscreen || c->ismaximizescreen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint32_t tag = selmon->pertag->curtag;
|
||||||
|
float zoom = selmon->pertag->canvas_zoom[tag];
|
||||||
|
float pan_x = selmon->pertag->canvas_pan_x[tag];
|
||||||
|
float pan_y = selmon->pertag->canvas_pan_y[tag];
|
||||||
|
|
||||||
|
c->canvas_geom[tag].x = (int32_t)roundf(pan_x);
|
||||||
|
c->canvas_geom[tag].y = (int32_t)roundf(pan_y);
|
||||||
|
c->canvas_geom[tag].width = (int32_t)roundf(selmon->w.width / zoom);
|
||||||
|
c->canvas_geom[tag].height = (int32_t)roundf(selmon->w.height / zoom);
|
||||||
|
c->iscustomsize = 1;
|
||||||
|
|
||||||
|
arrange(selmon, false, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t toggle_all_floating(const Arg *arg) {
|
int32_t toggle_all_floating(const Arg *arg) {
|
||||||
if (!selmon || !selmon->sel)
|
if (!selmon || !selmon->sel)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -96,10 +96,13 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
if (!node->enabled)
|
if (!node->enabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER)
|
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
||||||
surface = wlr_scene_surface_try_from_buffer(
|
struct wlr_scene_surface *scene_surface =
|
||||||
wlr_scene_buffer_from_node(node))
|
wlr_scene_surface_try_from_buffer(
|
||||||
->surface;
|
wlr_scene_buffer_from_node(node));
|
||||||
|
if (scene_surface)
|
||||||
|
surface = scene_surface->surface;
|
||||||
|
}
|
||||||
|
|
||||||
/* start from the topmost layer,
|
/* start from the topmost layer,
|
||||||
find a sureface that can be focused by pointer,
|
find a sureface that can be focused by pointer,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,10 @@ bool is_scroller_layout(Monitor *m) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_canvas_layout(Monitor *m) {
|
||||||
|
return m->pertag->ltidxs[m->pertag->curtag]->id == CANVAS;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_centertile_layout(Monitor *m) {
|
bool is_centertile_layout(Monitor *m) {
|
||||||
|
|
||||||
if (m->pertag->ltidxs[m->pertag->curtag]->id == CENTER_TILE)
|
if (m->pertag->ltidxs[m->pertag->curtag]->id == CENTER_TILE)
|
||||||
|
|
|
||||||
|
|
@ -813,6 +813,17 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
int32_t stack_index = 0;
|
int32_t stack_index = 0;
|
||||||
int32_t master_num = 0;
|
int32_t master_num = 0;
|
||||||
int32_t stack_num = 0;
|
int32_t stack_num = 0;
|
||||||
|
bool is_canvas = m->pertag->ltidxs[m->pertag->curtag]->id == CANVAS;
|
||||||
|
|
||||||
|
if (!is_canvas) {
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (VISIBLEON(c, m) && c->canvas_floating) {
|
||||||
|
c->isfloating = 0;
|
||||||
|
c->canvas_floating = false;
|
||||||
|
clear_visual_zoom(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m->visible_clients = 0;
|
m->visible_clients = 0;
|
||||||
m->visible_tiling_clients = 0;
|
m->visible_tiling_clients = 0;
|
||||||
|
|
@ -844,7 +855,7 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
if (!c->isunglobal)
|
if (!c->isunglobal)
|
||||||
m->visible_clients++;
|
m->visible_clients++;
|
||||||
|
|
||||||
if (ISTILED(c)) {
|
if (ISTILED(c) && !is_canvas) {
|
||||||
m->visible_tiling_clients++;
|
m->visible_tiling_clients++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -862,7 +873,7 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
|
|
||||||
if (c->mon == m) {
|
if (c->mon == m) {
|
||||||
if (VISIBLEON(c, m)) {
|
if (VISIBLEON(c, m)) {
|
||||||
if (ISTILED(c)) {
|
if (ISTILED(c) && !is_canvas) {
|
||||||
|
|
||||||
if (i < nmasters) {
|
if (i < nmasters) {
|
||||||
master_num++;
|
master_num++;
|
||||||
|
|
@ -916,6 +927,22 @@ arrange(Monitor *m, bool want_animation, bool from_view) {
|
||||||
if (!m->wlr_output->enabled)
|
if (!m->wlr_output->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!is_canvas_layout(m) && m->canvas_in_overview) {
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
Client *ov_c;
|
||||||
|
wl_list_for_each(ov_c, &clients, link) {
|
||||||
|
if (!VISIBLEON(ov_c, m) || ov_c->isunglobal)
|
||||||
|
continue;
|
||||||
|
if (ov_c->canvas_geom_backup[tag].width > 0)
|
||||||
|
ov_c->canvas_geom[tag] = ov_c->canvas_geom_backup[tag];
|
||||||
|
memset(&ov_c->canvas_geom_backup[tag], 0,
|
||||||
|
sizeof(ov_c->canvas_geom_backup[tag]));
|
||||||
|
}
|
||||||
|
m->pertag->canvas_pan_x[tag] = m->canvas_saved_pan_x;
|
||||||
|
m->pertag->canvas_pan_y[tag] = m->canvas_saved_pan_y;
|
||||||
|
m->canvas_in_overview = false;
|
||||||
|
}
|
||||||
|
|
||||||
pre_caculate_before_arrange(m, want_animation, from_view, false);
|
pre_caculate_before_arrange(m, want_animation, from_view, false);
|
||||||
|
|
||||||
if (m->isoverview) {
|
if (m->isoverview) {
|
||||||
|
|
|
||||||
146
src/layout/canvas.h
Normal file
146
src/layout/canvas.h
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
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;
|
||||||
|
float zoom = m->pertag->canvas_zoom[tag];
|
||||||
|
|
||||||
|
float cx = pan_x + (m->w.width / 2.0f) / zoom;
|
||||||
|
float cy = pan_y + (m->w.height / 2.0f) / zoom;
|
||||||
|
|
||||||
|
if (c->is_pending_open_animation) {
|
||||||
|
c->canvas_geom[tag].x = (int32_t)(cx - w / 2.0f);
|
||||||
|
c->canvas_geom[tag].y = (int32_t)(cy - h / 2.0f);
|
||||||
|
} else {
|
||||||
|
c->canvas_geom[tag].x = (int32_t)(cx + (*cascade_idx) * 30 - w / 2.0f);
|
||||||
|
c->canvas_geom[tag].y = (int32_t)(cy + (*cascade_idx) * 30 - h / 2.0f);
|
||||||
|
(*cascade_idx)++;
|
||||||
|
}
|
||||||
|
c->canvas_geom[tag].width = w;
|
||||||
|
c->canvas_geom[tag].height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void canvas_reposition(Monitor *m) {
|
||||||
|
Client *c;
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
|
||||||
|
float pan_x = m->pertag->canvas_pan_x[tag];
|
||||||
|
float pan_y = m->pertag->canvas_pan_y[tag];
|
||||||
|
float zoom = m->pertag->canvas_zoom[tag];
|
||||||
|
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (!VISIBLEON(c, m) || c->isunglobal)
|
||||||
|
continue;
|
||||||
|
if (c->isfullscreen || c->ismaximizescreen)
|
||||||
|
continue;
|
||||||
|
if (c->canvas_geom[tag].width <= 0 || c->canvas_geom[tag].height <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int new_x =
|
||||||
|
m->w.x + (int32_t)roundf((c->canvas_geom[tag].x - pan_x) * zoom);
|
||||||
|
int new_y =
|
||||||
|
m->w.y + (int32_t)roundf((c->canvas_geom[tag].y - pan_y) * zoom);
|
||||||
|
|
||||||
|
if (c->animation.running) {
|
||||||
|
c->animation.running = false;
|
||||||
|
c->need_output_flush = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->geom.x = new_x;
|
||||||
|
c->geom.y = new_y;
|
||||||
|
c->pending.x = new_x;
|
||||||
|
c->pending.y = new_y;
|
||||||
|
c->current.x = new_x;
|
||||||
|
c->current.y = new_y;
|
||||||
|
c->animation.current.x = new_x;
|
||||||
|
c->animation.current.y = new_y;
|
||||||
|
c->animation.initial.x = new_x;
|
||||||
|
c->animation.initial.y = new_y;
|
||||||
|
c->animainit_geom.x = new_x;
|
||||||
|
c->animainit_geom.y = new_y;
|
||||||
|
|
||||||
|
wlr_scene_node_set_position(&c->scene->node, new_x, new_y);
|
||||||
|
|
||||||
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, NULL);
|
||||||
|
client_apply_clip(c, 1.0);
|
||||||
|
if (zoom != 1.0f && !c->is_clip_to_hide)
|
||||||
|
apply_canvas_zoom_correct(c, zoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void canvas(Monitor *m) {
|
||||||
|
Client *c;
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
|
||||||
|
float pan_x = m->pertag->canvas_pan_x[tag];
|
||||||
|
float pan_y = m->pertag->canvas_pan_y[tag];
|
||||||
|
float zoom = m->pertag->canvas_zoom[tag];
|
||||||
|
|
||||||
|
int cascade_idx = 0;
|
||||||
|
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (!VISIBLEON(c, m) || c->isunglobal)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (c->isfullscreen || c->ismaximizescreen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int screen_x =
|
||||||
|
m->w.x + (int32_t)roundf((c->canvas_geom[tag].x - pan_x) * zoom);
|
||||||
|
int screen_y =
|
||||||
|
m->w.y + (int32_t)roundf((c->canvas_geom[tag].y - pan_y) * zoom);
|
||||||
|
|
||||||
|
float effective_zoom = zoom;
|
||||||
|
int32_t base_w = c->canvas_geom[tag].width;
|
||||||
|
int32_t base_h = c->canvas_geom[tag].height;
|
||||||
|
|
||||||
|
if (m->canvas_in_overview && c->canvas_geom_backup[tag].width > 0) {
|
||||||
|
base_w = c->canvas_geom_backup[tag].width;
|
||||||
|
base_h = c->canvas_geom_backup[tag].height;
|
||||||
|
effective_zoom *= (float)c->canvas_geom[tag].width / base_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_box client_geom = {
|
||||||
|
.x = screen_x,
|
||||||
|
.y = screen_y,
|
||||||
|
.width = base_w,
|
||||||
|
.height = base_h,
|
||||||
|
};
|
||||||
|
resize(c, client_geom, 0);
|
||||||
|
|
||||||
|
if (effective_zoom == 1.0f)
|
||||||
|
clear_visual_zoom(c);
|
||||||
|
else
|
||||||
|
apply_visual_zoom(c, effective_zoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void canvas_pan_to_client(Monitor *m, Client *c) {
|
||||||
|
if (!m || !c || !is_canvas_layout(m))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
if (c->canvas_geom[tag].width <= 0 || c->canvas_geom[tag].height <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float zoom = m->pertag->canvas_zoom[tag];
|
||||||
|
float pan_x = m->pertag->canvas_pan_x[tag];
|
||||||
|
float pan_y = m->pertag->canvas_pan_y[tag];
|
||||||
|
float vp_w = m->w.width / zoom;
|
||||||
|
float vp_h = m->w.height / zoom;
|
||||||
|
|
||||||
|
float cx = c->canvas_geom[tag].x;
|
||||||
|
float cy = c->canvas_geom[tag].y;
|
||||||
|
float cw = c->canvas_geom[tag].width;
|
||||||
|
float ch = c->canvas_geom[tag].height;
|
||||||
|
|
||||||
|
if (cx >= pan_x && cy >= pan_y && cx + cw <= pan_x + vp_w &&
|
||||||
|
cy + ch <= pan_y + vp_h)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m->pertag->canvas_pan_x[tag] = cx + cw / 2.0f - vp_w / 2.0f;
|
||||||
|
m->pertag->canvas_pan_y[tag] = cy + ch / 2.0f - vp_h / 2.0f;
|
||||||
|
canvas_reposition(m);
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ static void vertical_grid(Monitor *m);
|
||||||
static void vertical_scroller(Monitor *m);
|
static void vertical_scroller(Monitor *m);
|
||||||
static void vertical_deck(Monitor *mon);
|
static void vertical_deck(Monitor *mon);
|
||||||
static void tgmix(Monitor *m);
|
static void tgmix(Monitor *m);
|
||||||
|
static void canvas(Monitor *m);
|
||||||
|
|
||||||
/* layout(s) */
|
/* layout(s) */
|
||||||
Layout overviewlayout = {"", overview, "overview"};
|
Layout overviewlayout = {"", overview, "overview"};
|
||||||
|
|
@ -29,6 +30,7 @@ enum {
|
||||||
VERTICAL_DECK,
|
VERTICAL_DECK,
|
||||||
RIGHT_TILE,
|
RIGHT_TILE,
|
||||||
TGMIX,
|
TGMIX,
|
||||||
|
CANVAS,
|
||||||
};
|
};
|
||||||
|
|
||||||
Layout layouts[] = {
|
Layout layouts[] = {
|
||||||
|
|
@ -47,4 +49,5 @@ Layout layouts[] = {
|
||||||
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
||||||
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
||||||
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
|
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
|
||||||
|
{"CV", canvas, "canvas", CANVAS}, // canvas layout
|
||||||
};
|
};
|
||||||
954
src/mango.c
954
src/mango.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue