mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2025-11-05 13:29:54 -05:00
381 lines
10 KiB
C
381 lines
10 KiB
C
void layer_actual_size(LayerSurface *l, unsigned int *width,
|
||
unsigned int *height) {
|
||
struct wlr_box box;
|
||
|
||
if (l->animation.running) {
|
||
*width = l->animation.current.width;
|
||
*height = l->animation.current.height;
|
||
} else {
|
||
get_layer_target_geometry(l, &box);
|
||
*width = box.width;
|
||
*height = box.height;
|
||
}
|
||
}
|
||
|
||
void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box) {
|
||
|
||
if (!l || !l->mapped)
|
||
return;
|
||
|
||
const struct wlr_layer_surface_v1_state *state = &l->layer_surface->current;
|
||
|
||
// 限制区域
|
||
// waybar一般都是大于0,表示要占用多少区域,所以计算位置也要用全部区域作为基准
|
||
// 如果是-1可能表示独占所有可用空间
|
||
// 如果是0,应该是表示使用exclusive_zone外的可用区域
|
||
struct wlr_box bounds;
|
||
if (state->exclusive_zone > 0 || state->exclusive_zone == -1)
|
||
bounds = l->mon->m;
|
||
else
|
||
bounds = l->mon->w;
|
||
|
||
// 初始化几何位置
|
||
struct wlr_box box = {.width = state->desired_width,
|
||
.height = state->desired_height};
|
||
|
||
// 水平方向定位
|
||
const uint32_t both_horiz =
|
||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||
if (box.width == 0) {
|
||
box.x = bounds.x;
|
||
} else if ((state->anchor & both_horiz) == both_horiz) {
|
||
box.x = bounds.x + ((bounds.width - box.width) / 2);
|
||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
||
box.x = bounds.x;
|
||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
||
box.x = bounds.x + (bounds.width - box.width);
|
||
} else {
|
||
box.x = bounds.x + ((bounds.width - box.width) / 2);
|
||
}
|
||
|
||
// 垂直方向定位
|
||
const uint32_t both_vert =
|
||
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
||
if (box.height == 0) {
|
||
box.y = bounds.y;
|
||
} else if ((state->anchor & both_vert) == both_vert) {
|
||
box.y = bounds.y + ((bounds.height - box.height) / 2);
|
||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
||
box.y = bounds.y;
|
||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
||
box.y = bounds.y + (bounds.height - box.height);
|
||
} else {
|
||
box.y = bounds.y + ((bounds.height - box.height) / 2);
|
||
}
|
||
|
||
// 应用边距
|
||
if (box.width == 0) {
|
||
box.x += state->margin.left;
|
||
box.width = bounds.width - (state->margin.left + state->margin.right);
|
||
} else {
|
||
if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
||
box.x += state->margin.left;
|
||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
||
box.x -= state->margin.right;
|
||
}
|
||
}
|
||
|
||
if (box.height == 0) {
|
||
box.y += state->margin.top;
|
||
box.height = bounds.height - (state->margin.top + state->margin.bottom);
|
||
} else {
|
||
if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
||
box.y += state->margin.top;
|
||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
||
box.y -= state->margin.bottom;
|
||
}
|
||
}
|
||
|
||
target_box->x = box.x;
|
||
target_box->y = box.y;
|
||
target_box->width = box.width;
|
||
target_box->height = box.height;
|
||
}
|
||
|
||
void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
||
int slide_direction;
|
||
int horizontal, horizontal_value;
|
||
int vertical, vertical_value;
|
||
int center_x, center_y;
|
||
|
||
if (!l)
|
||
return;
|
||
|
||
center_x = l->geom.x + l->geom.width / 2;
|
||
center_y = l->geom.y + l->geom.height / 2;
|
||
horizontal = center_x > l->mon->m.x + l->mon->m.width / 2 ? RIGHT : LEFT;
|
||
horizontal_value = horizontal == LEFT
|
||
? center_x - l->mon->m.x
|
||
: l->mon->m.x + l->mon->m.width - center_x;
|
||
vertical = center_y > l->mon->m.y + l->mon->m.height / 2 ? DOWN : UP;
|
||
vertical_value = vertical == UP ? center_y - l->mon->w.y
|
||
: l->mon->m.y + l->mon->m.height - center_y;
|
||
slide_direction = horizontal_value < vertical_value ? horizontal : vertical;
|
||
|
||
switch (slide_direction) {
|
||
case UP:
|
||
geo->x = l->geom.x;
|
||
geo->y = l->mon->m.y - l->geom.height;
|
||
break;
|
||
case DOWN:
|
||
geo->x = l->geom.x;
|
||
geo->y = l->mon->m.y + l->mon->m.height;
|
||
break;
|
||
case LEFT:
|
||
geo->x = l->mon->m.x - l->geom.width;
|
||
geo->y = l->geom.y;
|
||
break;
|
||
case RIGHT:
|
||
geo->x = l->mon->m.x + l->mon->m.width;
|
||
geo->y = l->geom.y;
|
||
break;
|
||
default:
|
||
geo->x = l->geom.x;
|
||
geo->y = 0 - l->geom.height;
|
||
}
|
||
}
|
||
|
||
void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
||
if (!l)
|
||
return;
|
||
|
||
double animation_passed =
|
||
(double)l->animation.passed_frames / l->animation.total_frames;
|
||
int type = l->animation.action = l->animation.action;
|
||
double factor = find_animation_curve_at(animation_passed, type);
|
||
unsigned int width =
|
||
l->animation.initial.width +
|
||
(l->current.width - l->animation.initial.width) * factor;
|
||
unsigned int height =
|
||
l->animation.initial.height +
|
||
(l->current.height - l->animation.initial.height) * factor;
|
||
|
||
unsigned int x = l->animation.initial.x +
|
||
(l->current.x - l->animation.initial.x) * factor;
|
||
unsigned int y = l->animation.initial.y +
|
||
(l->current.y - l->animation.initial.y) * factor;
|
||
|
||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||
|
||
l->animation.current = (struct wlr_box){
|
||
.x = x,
|
||
.y = y,
|
||
.width = width,
|
||
.height = height,
|
||
};
|
||
|
||
double opacity = MAX(fadeout_begin_opacity - animation_passed, 0.0f);
|
||
|
||
if (animation_fade_out)
|
||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||
scene_buffer_apply_opacity, &opacity);
|
||
|
||
if (animation_passed == 1.0) {
|
||
wl_list_remove(&l->fadeout_link);
|
||
wlr_scene_node_destroy(&l->scene->node);
|
||
free(l);
|
||
l = NULL;
|
||
} else {
|
||
l->animation.passed_frames++;
|
||
}
|
||
}
|
||
|
||
void layer_animation_next_tick(LayerSurface *l) {
|
||
|
||
if (!l || !l->mapped)
|
||
return;
|
||
|
||
double animation_passed =
|
||
(double)l->animation.passed_frames / l->animation.total_frames;
|
||
|
||
int type = l->animation.action == NONE ? MOVE : l->animation.action;
|
||
double factor = find_animation_curve_at(animation_passed, type);
|
||
|
||
unsigned int width =
|
||
l->animation.initial.width +
|
||
(l->current.width - l->animation.initial.width) * factor;
|
||
unsigned int height =
|
||
l->animation.initial.height +
|
||
(l->current.height - l->animation.initial.height) * factor;
|
||
|
||
unsigned int x = l->animation.initial.x +
|
||
(l->current.x - l->animation.initial.x) * factor;
|
||
unsigned int y = l->animation.initial.y +
|
||
(l->current.y - l->animation.initial.y) * factor;
|
||
|
||
double opacity = MIN(fadein_begin_opacity + animation_passed, 1.0f);
|
||
|
||
if (animation_fade_in)
|
||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||
scene_buffer_apply_opacity, &opacity);
|
||
|
||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||
|
||
l->animation.current = (struct wlr_box){
|
||
.x = x,
|
||
.y = y,
|
||
.width = width,
|
||
.height = height,
|
||
};
|
||
|
||
if (animation_passed == 1.0) {
|
||
l->animation.running = false;
|
||
l->need_output_flush = false;
|
||
l->animation.action = MOVE;
|
||
} else {
|
||
l->animation.passed_frames++;
|
||
}
|
||
}
|
||
|
||
void init_fadeout_layers(LayerSurface *l) {
|
||
|
||
if (!layer_animations || l->noanim) {
|
||
return;
|
||
}
|
||
|
||
if (!l->mon)
|
||
return;
|
||
|
||
if (!l->scene) {
|
||
return;
|
||
}
|
||
|
||
if (l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM ||
|
||
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND)
|
||
return;
|
||
|
||
LayerSurface *fadeout_layer = ecalloc(1, sizeof(*fadeout_layer));
|
||
|
||
wlr_scene_node_set_enabled(&l->scene->node, true);
|
||
fadeout_layer->scene =
|
||
wlr_scene_tree_snapshot(&l->scene->node, layers[LyrFadeOut]);
|
||
wlr_scene_node_set_enabled(&l->scene->node, false);
|
||
|
||
if (!fadeout_layer->scene) {
|
||
free(fadeout_layer);
|
||
return;
|
||
}
|
||
|
||
fadeout_layer->animation.duration = animation_duration_close;
|
||
fadeout_layer->geom = fadeout_layer->current =
|
||
fadeout_layer->animainit_geom = fadeout_layer->animation.initial =
|
||
l->animation.current;
|
||
fadeout_layer->mon = l->mon;
|
||
fadeout_layer->animation.action = CLOSE;
|
||
|
||
// 这里snap节点的坐标设置是使用的相对坐标,所以不能加上原来坐标
|
||
// 这跟普通node有区别
|
||
|
||
fadeout_layer->animation.initial.x = 0;
|
||
fadeout_layer->animation.initial.y = 0;
|
||
|
||
if ((!l->animation_type_close &&
|
||
strcmp(layer_animation_type_close, "slide") == 0) ||
|
||
(l->animation_type_close &&
|
||
strcmp(l->animation_type_close, "slide") == 0)) {
|
||
set_layer_dir_animaiton(l, &fadeout_layer->current);
|
||
fadeout_layer->current.x = fadeout_layer->current.x - l->geom.x;
|
||
fadeout_layer->current.y = fadeout_layer->current.y - l->geom.y;
|
||
} else {
|
||
fadeout_layer->current.x = 0;
|
||
fadeout_layer->current.y = 0;
|
||
}
|
||
|
||
fadeout_layer->animation.passed_frames = 0;
|
||
fadeout_layer->animation.total_frames =
|
||
fadeout_layer->animation.duration / output_frame_duration_ms();
|
||
wlr_scene_node_set_enabled(&fadeout_layer->scene->node, true);
|
||
wl_list_insert(&fadeout_layers, &fadeout_layer->fadeout_link);
|
||
}
|
||
|
||
void layer_set_pending_state(LayerSurface *l) {
|
||
|
||
if (!l || !l->mapped)
|
||
return;
|
||
|
||
l->pending = l->geom;
|
||
if (l->animation.action == OPEN) {
|
||
if ((!l->animation_type_open &&
|
||
strcmp(layer_animation_type_open, "slide") == 0) ||
|
||
(l->animation_type_open &&
|
||
strcmp(l->animation_type_open, "slide") == 0)) {
|
||
|
||
set_layer_dir_animaiton(l, &l->animainit_geom);
|
||
} else {
|
||
l->animainit_geom.x = l->geom.x;
|
||
l->animainit_geom.y = l->geom.y;
|
||
}
|
||
} else {
|
||
l->animainit_geom = l->animation.current;
|
||
}
|
||
// 判断是否需要动画
|
||
if (!animations || !layer_animations || l->noanim ||
|
||
l->layer_surface->current.layer ==
|
||
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
||
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
||
l->animation.should_animate = false;
|
||
} else {
|
||
l->animation.should_animate = true;
|
||
}
|
||
|
||
l->animation.duration = animation_duration_open;
|
||
l->animation.action = OPEN;
|
||
// 开始动画
|
||
layer_commit(l);
|
||
l->dirty = true;
|
||
}
|
||
|
||
void layer_commit(LayerSurface *l) {
|
||
|
||
if (!l || !l->mapped)
|
||
return;
|
||
|
||
l->current = l->pending; // 设置动画的结束位置
|
||
|
||
if (l->animation.should_animate) {
|
||
if (!l->animation.running) {
|
||
l->animation.current = l->animainit_geom;
|
||
}
|
||
|
||
l->animation.initial = l->animainit_geom;
|
||
// 设置动画速度
|
||
l->animation.passed_frames = 0;
|
||
l->animation.total_frames =
|
||
l->animation.duration / output_frame_duration_ms();
|
||
|
||
// 标记动画开始
|
||
l->animation.running = true;
|
||
l->animation.should_animate = false;
|
||
}
|
||
// 请求刷新屏幕
|
||
wlr_output_schedule_frame(l->mon->wlr_output);
|
||
}
|
||
|
||
bool layer_draw_frame(LayerSurface *l) {
|
||
|
||
if (!l || !l->mapped)
|
||
return false;
|
||
|
||
if (!l->need_output_flush)
|
||
return false;
|
||
|
||
if (l->layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
|
||
l->layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
|
||
return false;
|
||
}
|
||
|
||
if (animations && layer_animations && l->animation.running && !l->noanim) {
|
||
layer_animation_next_tick(l);
|
||
} else {
|
||
l->need_output_flush = false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool layer_draw_fadeout_frame(LayerSurface *l) {
|
||
if (!l)
|
||
return false;
|
||
|
||
fadeout_layer_animation_next_tick(l);
|
||
return true;
|
||
}
|