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
|
|
@ -161,21 +161,6 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
|||
int32_t sy, void *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 =
|
||||
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_height = surface->current.height;
|
||||
|
||||
surface_width = buffer_data->width_scale < 1
|
||||
? surface_width
|
||||
: buffer_data->width_scale * surface_width;
|
||||
surface_height = buffer_data->height_scale < 1
|
||||
? surface_height
|
||||
: buffer_data->height_scale * surface_height;
|
||||
surface_width = buffer_data->width_scale * surface_width;
|
||||
surface_height = buffer_data->height_scale * surface_height;
|
||||
|
||||
if (surface_width > buffer_data->width &&
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if (!c || c->iskilling)
|
||||
|
|
@ -267,6 +329,8 @@ void client_draw_shadow(Client *c) {
|
|||
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);
|
||||
enum corner_location current_corner_location =
|
||||
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 = {
|
||||
.x = shadow_box.x + c->animation.current.x,
|
||||
.y = shadow_box.y + c->animation.current.y,
|
||||
.width = shadow_box.width,
|
||||
.height = shadow_box.height,
|
||||
.x = shadow_box.x * zoom + c->animation.current.x,
|
||||
.y = shadow_box.y * zoom + c->animation.current.y,
|
||||
.width = shadow_box.width * zoom,
|
||||
.height = shadow_box.height * zoom,
|
||||
};
|
||||
|
||||
int32_t right_offset, bottom_offset, left_offset, top_offset;
|
||||
|
|
@ -323,13 +387,15 @@ void client_draw_shadow(Client *c) {
|
|||
} else {
|
||||
right_offset =
|
||||
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 =
|
||||
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);
|
||||
top_offset = GEZERO(c->mon->m.y - absolute_shadow_box.y);
|
||||
left_offset = GEZERO(c->mon->m.x - absolute_shadow_box.x) / zoom;
|
||||
top_offset = GEZERO(c->mon->m.y - absolute_shadow_box.y) / zoom;
|
||||
}
|
||||
|
||||
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);
|
||||
bottom_offset = MIN(bottom_offset, shadow_box.height);
|
||||
|
||||
wlr_scene_node_set_position(&c->shadow->node, shadow_box.x + left_offset,
|
||||
shadow_box.y + top_offset);
|
||||
wlr_scene_node_set_position(&c->shadow->node,
|
||||
(shadow_box.x + left_offset) * zoom,
|
||||
(shadow_box.y + top_offset) * zoom);
|
||||
|
||||
wlr_scene_shadow_set_size(
|
||||
c->shadow, GEZERO(shadow_box.width - left_offset - right_offset),
|
||||
GEZERO(shadow_box.height - top_offset - bottom_offset));
|
||||
c->shadow, GEZERO(shadow_box.width - left_offset - right_offset) * zoom,
|
||||
GEZERO(shadow_box.height - top_offset - bottom_offset) * zoom);
|
||||
|
||||
clipped_region.area.x = clipped_region.area.x - left_offset;
|
||||
clipped_region.area.y = clipped_region.area.y - top_offset;
|
||||
clipped_region.area.x = (clipped_region.area.x - left_offset) * zoom;
|
||||
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);
|
||||
}
|
||||
|
|
@ -354,6 +423,8 @@ void apply_border(Client *c) {
|
|||
if (!c || c->iskilling || !client_surface(c)->mapped)
|
||||
return;
|
||||
|
||||
float zoom = get_client_effective_zoom(c);
|
||||
|
||||
bool hit_no_border = check_hit_no_border(c);
|
||||
enum corner_location current_corner_location;
|
||||
if (c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||
|
|
@ -389,14 +460,16 @@ void apply_border(Client *c) {
|
|||
top_offset = 0;
|
||||
} else {
|
||||
right_offset =
|
||||
GEZERO(c->animation.current.x + c->animation.current.width -
|
||||
c->mon->m.x - c->mon->m.width);
|
||||
GEZERO(c->animation.current.x + c->animation.current.width * zoom -
|
||||
c->mon->m.x - c->mon->m.width) /
|
||||
zoom;
|
||||
bottom_offset =
|
||||
GEZERO(c->animation.current.y + c->animation.current.height -
|
||||
c->mon->m.y - c->mon->m.height);
|
||||
GEZERO(c->animation.current.y + c->animation.current.height * zoom -
|
||||
c->mon->m.y - c->mon->m.height) /
|
||||
zoom;
|
||||
|
||||
left_offset = GEZERO(c->mon->m.x - c->animation.current.x);
|
||||
top_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
||||
left_offset = GEZERO(c->mon->m.x - c->animation.current.x) / zoom;
|
||||
top_offset = GEZERO(c->mon->m.y - c->animation.current.y) / zoom;
|
||||
}
|
||||
|
||||
int32_t inner_surface_width = GEZERO(clip_box.width - 2 * bw);
|
||||
|
|
@ -438,9 +511,14 @@ void apply_border(Client *c) {
|
|||
.corners = current_corner_location,
|
||||
};
|
||||
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border, rect_width, rect_height);
|
||||
wlr_scene_node_set_position(&c->border->node, rect_x, rect_y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node,
|
||||
(int32_t)roundf(c->bw * zoom),
|
||||
(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,
|
||||
current_corner_location);
|
||||
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;
|
||||
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)
|
||||
return offset;
|
||||
|
||||
float zoom = get_client_effective_zoom(c);
|
||||
|
||||
int32_t bottom_out_offset =
|
||||
GEZERO(c->animation.current.y + c->animation.current.height -
|
||||
c->mon->m.y - c->mon->m.height);
|
||||
GEZERO(c->animation.current.y + c->animation.current.height * zoom -
|
||||
c->mon->m.y - c->mon->m.height) /
|
||||
zoom;
|
||||
int32_t right_out_offset =
|
||||
GEZERO(c->animation.current.x + c->animation.current.width -
|
||||
c->mon->m.x - c->mon->m.width);
|
||||
int32_t left_out_offset = GEZERO(c->mon->m.x - c->animation.current.x);
|
||||
int32_t top_out_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
||||
GEZERO(c->animation.current.x + c->animation.current.width * zoom -
|
||||
c->mon->m.x - c->mon->m.width) /
|
||||
zoom;
|
||||
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,否计算会没有负数导致判断错误
|
||||
int32_t bw = (int32_t)c->bw;
|
||||
|
|
@ -471,7 +556,8 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
|||
需要主要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) {
|
||||
if (left_out_offset > 0) {
|
||||
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;
|
||||
|
||||
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;
|
||||
wlr_scene_node_set_enabled(&c->scene->node, false);
|
||||
} else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) {
|
||||
|
|
@ -540,6 +627,17 @@ void client_apply_clip(Client *c, float factor) {
|
|||
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);
|
||||
buffer_set_effect(c, (BufferData){1.0f, 1.0f, clip_box.width,
|
||||
clip_box.height,
|
||||
|
|
@ -587,6 +685,16 @@ void client_apply_clip(Client *c, float factor) {
|
|||
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);
|
||||
|
||||
|
|
@ -926,7 +1034,8 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
|||
// float_geom = c->geom;
|
||||
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.width = MAX(1 + 2 * (int32_t)c->bw, c->geom.width);
|
||||
c->geom.height = MAX(1 + 2 * (int32_t)c->bw, c->geom.height);
|
||||
|
|
@ -1182,20 +1291,41 @@ bool client_draw_frame(Client *c) {
|
|||
if (!c || !client_surface(c)->mapped)
|
||||
return false;
|
||||
|
||||
if (!c->need_output_flush) {
|
||||
bool need_flush = c->need_output_flush;
|
||||
|
||||
if (need_flush) {
|
||||
if (config.animations && c->animation.running) {
|
||||
client_animation_next_tick(c);
|
||||
} else {
|
||||
wlr_scene_node_set_position(&c->scene->node, c->pending.x,
|
||||
c->pending.y);
|
||||
c->animation.current = c->animainit_geom = c->animation.initial =
|
||||
c->pending = c->current = c->geom;
|
||||
client_apply_clip(c, 1.0);
|
||||
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);
|
||||
}
|
||||
|
||||
if (config.animations && c->animation.running) {
|
||||
client_animation_next_tick(c);
|
||||
} else {
|
||||
wlr_scene_node_set_position(&c->scene->node, c->pending.x,
|
||||
c->pending.y);
|
||||
c->animation.current = c->animainit_geom = c->animation.initial =
|
||||
c->pending = c->current = c->geom;
|
||||
client_apply_clip(c, 1.0);
|
||||
c->need_output_flush = false;
|
||||
}
|
||||
client_apply_focus_opacity(c);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue